18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Routines having to do with the 'struct sk_buff' memory handlers. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Authors: Alan Cox <alan@lxorguk.ukuu.org.uk> 68c2ecf20Sopenharmony_ci * Florian La Roche <rzsfl@rz.uni-sb.de> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Fixes: 98c2ecf20Sopenharmony_ci * Alan Cox : Fixed the worst of the load 108c2ecf20Sopenharmony_ci * balancer bugs. 118c2ecf20Sopenharmony_ci * Dave Platt : Interrupt stacking fix. 128c2ecf20Sopenharmony_ci * Richard Kooijman : Timestamp fixes. 138c2ecf20Sopenharmony_ci * Alan Cox : Changed buffer format. 148c2ecf20Sopenharmony_ci * Alan Cox : destructor hook for AF_UNIX etc. 158c2ecf20Sopenharmony_ci * Linus Torvalds : Better skb_clone. 168c2ecf20Sopenharmony_ci * Alan Cox : Added skb_copy. 178c2ecf20Sopenharmony_ci * Alan Cox : Added all the changed routines Linus 188c2ecf20Sopenharmony_ci * only put in the headers 198c2ecf20Sopenharmony_ci * Ray VanTassle : Fixed --skb->lock in free 208c2ecf20Sopenharmony_ci * Alan Cox : skb_copy copy arp field 218c2ecf20Sopenharmony_ci * Andi Kleen : slabified it. 228c2ecf20Sopenharmony_ci * Robert Olsson : Removed skb_head_pool 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * NOTE: 258c2ecf20Sopenharmony_ci * The __skb_ routines should be called with interrupts 268c2ecf20Sopenharmony_ci * disabled, or you better be *real* sure that the operation is atomic 278c2ecf20Sopenharmony_ci * with respect to whatever list is being frobbed (e.g. via lock_sock() 288c2ecf20Sopenharmony_ci * or via disabling bottom half handlers, etc). 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * The functions in this file will not compile correctly with gcc 2.4.x 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <linux/module.h> 388c2ecf20Sopenharmony_ci#include <linux/types.h> 398c2ecf20Sopenharmony_ci#include <linux/kernel.h> 408c2ecf20Sopenharmony_ci#include <linux/mm.h> 418c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 428c2ecf20Sopenharmony_ci#include <linux/in.h> 438c2ecf20Sopenharmony_ci#include <linux/inet.h> 448c2ecf20Sopenharmony_ci#include <linux/slab.h> 458c2ecf20Sopenharmony_ci#include <linux/tcp.h> 468c2ecf20Sopenharmony_ci#include <linux/udp.h> 478c2ecf20Sopenharmony_ci#include <linux/sctp.h> 488c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 498c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_CLS_ACT 508c2ecf20Sopenharmony_ci#include <net/pkt_sched.h> 518c2ecf20Sopenharmony_ci#endif 528c2ecf20Sopenharmony_ci#include <linux/string.h> 538c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 548c2ecf20Sopenharmony_ci#include <linux/splice.h> 558c2ecf20Sopenharmony_ci#include <linux/cache.h> 568c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h> 578c2ecf20Sopenharmony_ci#include <linux/init.h> 588c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 598c2ecf20Sopenharmony_ci#include <linux/errqueue.h> 608c2ecf20Sopenharmony_ci#include <linux/prefetch.h> 618c2ecf20Sopenharmony_ci#include <linux/if_vlan.h> 628c2ecf20Sopenharmony_ci#include <linux/mpls.h> 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#include <net/protocol.h> 658c2ecf20Sopenharmony_ci#include <net/dst.h> 668c2ecf20Sopenharmony_ci#include <net/sock.h> 678c2ecf20Sopenharmony_ci#include <net/checksum.h> 688c2ecf20Sopenharmony_ci#include <net/ip6_checksum.h> 698c2ecf20Sopenharmony_ci#include <net/xfrm.h> 708c2ecf20Sopenharmony_ci#include <net/mpls.h> 718c2ecf20Sopenharmony_ci#include <net/mptcp.h> 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 748c2ecf20Sopenharmony_ci#include <trace/events/skb.h> 758c2ecf20Sopenharmony_ci#include <linux/highmem.h> 768c2ecf20Sopenharmony_ci#include <linux/capability.h> 778c2ecf20Sopenharmony_ci#include <linux/user_namespace.h> 788c2ecf20Sopenharmony_ci#include <linux/indirect_call_wrapper.h> 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#include "datagram.h" 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistruct kmem_cache *skbuff_head_cache __ro_after_init; 838c2ecf20Sopenharmony_cistatic struct kmem_cache *skbuff_fclone_cache __ro_after_init; 848c2ecf20Sopenharmony_ci#ifdef CONFIG_SKB_EXTENSIONS 858c2ecf20Sopenharmony_cistatic struct kmem_cache *skbuff_ext_cache __ro_after_init; 868c2ecf20Sopenharmony_ci#endif 878c2ecf20Sopenharmony_ciint sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS; 888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sysctl_max_skb_frags); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/** 918c2ecf20Sopenharmony_ci * skb_panic - private function for out-of-line support 928c2ecf20Sopenharmony_ci * @skb: buffer 938c2ecf20Sopenharmony_ci * @sz: size 948c2ecf20Sopenharmony_ci * @addr: address 958c2ecf20Sopenharmony_ci * @msg: skb_over_panic or skb_under_panic 968c2ecf20Sopenharmony_ci * 978c2ecf20Sopenharmony_ci * Out-of-line support for skb_put() and skb_push(). 988c2ecf20Sopenharmony_ci * Called via the wrapper skb_over_panic() or skb_under_panic(). 998c2ecf20Sopenharmony_ci * Keep out of line to prevent kernel bloat. 1008c2ecf20Sopenharmony_ci * __builtin_return_address is not used because it is not always reliable. 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_cistatic void skb_panic(struct sk_buff *skb, unsigned int sz, void *addr, 1038c2ecf20Sopenharmony_ci const char msg[]) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci pr_emerg("%s: text:%px len:%d put:%d head:%px data:%px tail:%#lx end:%#lx dev:%s\n", 1068c2ecf20Sopenharmony_ci msg, addr, skb->len, sz, skb->head, skb->data, 1078c2ecf20Sopenharmony_ci (unsigned long)skb->tail, (unsigned long)skb->end, 1088c2ecf20Sopenharmony_ci skb->dev ? skb->dev->name : "<NULL>"); 1098c2ecf20Sopenharmony_ci BUG(); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic void skb_over_panic(struct sk_buff *skb, unsigned int sz, void *addr) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci skb_panic(skb, sz, addr, __func__); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic void skb_under_panic(struct sk_buff *skb, unsigned int sz, void *addr) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci skb_panic(skb, sz, addr, __func__); 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/* 1238c2ecf20Sopenharmony_ci * kmalloc_reserve is a wrapper around kmalloc_node_track_caller that tells 1248c2ecf20Sopenharmony_ci * the caller if emergency pfmemalloc reserves are being used. If it is and 1258c2ecf20Sopenharmony_ci * the socket is later found to be SOCK_MEMALLOC then PFMEMALLOC reserves 1268c2ecf20Sopenharmony_ci * may be used. Otherwise, the packet data may be discarded until enough 1278c2ecf20Sopenharmony_ci * memory is free 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci#define kmalloc_reserve(size, gfp, node, pfmemalloc) \ 1308c2ecf20Sopenharmony_ci __kmalloc_reserve(size, gfp, node, _RET_IP_, pfmemalloc) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic void *__kmalloc_reserve(size_t size, gfp_t flags, int node, 1338c2ecf20Sopenharmony_ci unsigned long ip, bool *pfmemalloc) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci void *obj; 1368c2ecf20Sopenharmony_ci bool ret_pfmemalloc = false; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* 1398c2ecf20Sopenharmony_ci * Try a regular allocation, when that fails and we're not entitled 1408c2ecf20Sopenharmony_ci * to the reserves, fail. 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_ci obj = kmalloc_node_track_caller(size, 1438c2ecf20Sopenharmony_ci flags | __GFP_NOMEMALLOC | __GFP_NOWARN, 1448c2ecf20Sopenharmony_ci node); 1458c2ecf20Sopenharmony_ci if (obj || !(gfp_pfmemalloc_allowed(flags))) 1468c2ecf20Sopenharmony_ci goto out; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* Try again but now we are using pfmemalloc reserves */ 1498c2ecf20Sopenharmony_ci ret_pfmemalloc = true; 1508c2ecf20Sopenharmony_ci obj = kmalloc_node_track_caller(size, flags, node); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ciout: 1538c2ecf20Sopenharmony_ci if (pfmemalloc) 1548c2ecf20Sopenharmony_ci *pfmemalloc = ret_pfmemalloc; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return obj; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci/* Allocate a new skbuff. We do this ourselves so we can fill in a few 1608c2ecf20Sopenharmony_ci * 'private' fields and also do memory statistics to find all the 1618c2ecf20Sopenharmony_ci * [BEEP] leaks. 1628c2ecf20Sopenharmony_ci * 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/** 1668c2ecf20Sopenharmony_ci * __alloc_skb - allocate a network buffer 1678c2ecf20Sopenharmony_ci * @size: size to allocate 1688c2ecf20Sopenharmony_ci * @gfp_mask: allocation mask 1698c2ecf20Sopenharmony_ci * @flags: If SKB_ALLOC_FCLONE is set, allocate from fclone cache 1708c2ecf20Sopenharmony_ci * instead of head cache and allocate a cloned (child) skb. 1718c2ecf20Sopenharmony_ci * If SKB_ALLOC_RX is set, __GFP_MEMALLOC will be used for 1728c2ecf20Sopenharmony_ci * allocations in case the data is required for writeback 1738c2ecf20Sopenharmony_ci * @node: numa node to allocate memory on 1748c2ecf20Sopenharmony_ci * 1758c2ecf20Sopenharmony_ci * Allocate a new &sk_buff. The returned buffer has no headroom and a 1768c2ecf20Sopenharmony_ci * tail room of at least size bytes. The object has a reference count 1778c2ecf20Sopenharmony_ci * of one. The return is the buffer. On a failure the return is %NULL. 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * Buffers may only be allocated from interrupts using a @gfp_mask of 1808c2ecf20Sopenharmony_ci * %GFP_ATOMIC. 1818c2ecf20Sopenharmony_ci */ 1828c2ecf20Sopenharmony_cistruct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, 1838c2ecf20Sopenharmony_ci int flags, int node) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct kmem_cache *cache; 1868c2ecf20Sopenharmony_ci struct skb_shared_info *shinfo; 1878c2ecf20Sopenharmony_ci struct sk_buff *skb; 1888c2ecf20Sopenharmony_ci u8 *data; 1898c2ecf20Sopenharmony_ci bool pfmemalloc; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci cache = (flags & SKB_ALLOC_FCLONE) 1928c2ecf20Sopenharmony_ci ? skbuff_fclone_cache : skbuff_head_cache; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (sk_memalloc_socks() && (flags & SKB_ALLOC_RX)) 1958c2ecf20Sopenharmony_ci gfp_mask |= __GFP_MEMALLOC; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* Get the HEAD */ 1988c2ecf20Sopenharmony_ci skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node); 1998c2ecf20Sopenharmony_ci if (!skb) 2008c2ecf20Sopenharmony_ci goto out; 2018c2ecf20Sopenharmony_ci prefetchw(skb); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci /* We do our best to align skb_shared_info on a separate cache 2048c2ecf20Sopenharmony_ci * line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives 2058c2ecf20Sopenharmony_ci * aligned memory blocks, unless SLUB/SLAB debug is enabled. 2068c2ecf20Sopenharmony_ci * Both skb->head and skb_shared_info are cache line aligned. 2078c2ecf20Sopenharmony_ci */ 2088c2ecf20Sopenharmony_ci size = SKB_DATA_ALIGN(size); 2098c2ecf20Sopenharmony_ci size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 2108c2ecf20Sopenharmony_ci data = kmalloc_reserve(size, gfp_mask, node, &pfmemalloc); 2118c2ecf20Sopenharmony_ci if (!data) 2128c2ecf20Sopenharmony_ci goto nodata; 2138c2ecf20Sopenharmony_ci /* kmalloc(size) might give us more room than requested. 2148c2ecf20Sopenharmony_ci * Put skb_shared_info exactly at the end of allocated zone, 2158c2ecf20Sopenharmony_ci * to allow max possible filling before reallocation. 2168c2ecf20Sopenharmony_ci */ 2178c2ecf20Sopenharmony_ci size = SKB_WITH_OVERHEAD(ksize(data)); 2188c2ecf20Sopenharmony_ci prefetchw(data + size); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* 2218c2ecf20Sopenharmony_ci * Only clear those fields we need to clear, not those that we will 2228c2ecf20Sopenharmony_ci * actually initialise below. Hence, don't put any more fields after 2238c2ecf20Sopenharmony_ci * the tail pointer in struct sk_buff! 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci memset(skb, 0, offsetof(struct sk_buff, tail)); 2268c2ecf20Sopenharmony_ci /* Account for allocated memory : skb + skb->head */ 2278c2ecf20Sopenharmony_ci skb->truesize = SKB_TRUESIZE(size); 2288c2ecf20Sopenharmony_ci skb->pfmemalloc = pfmemalloc; 2298c2ecf20Sopenharmony_ci refcount_set(&skb->users, 1); 2308c2ecf20Sopenharmony_ci skb->head = data; 2318c2ecf20Sopenharmony_ci skb->data = data; 2328c2ecf20Sopenharmony_ci skb_reset_tail_pointer(skb); 2338c2ecf20Sopenharmony_ci skb->end = skb->tail + size; 2348c2ecf20Sopenharmony_ci skb->mac_header = (typeof(skb->mac_header))~0U; 2358c2ecf20Sopenharmony_ci skb->transport_header = (typeof(skb->transport_header))~0U; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* make sure we initialize shinfo sequentially */ 2388c2ecf20Sopenharmony_ci shinfo = skb_shinfo(skb); 2398c2ecf20Sopenharmony_ci memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); 2408c2ecf20Sopenharmony_ci atomic_set(&shinfo->dataref, 1); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (flags & SKB_ALLOC_FCLONE) { 2438c2ecf20Sopenharmony_ci struct sk_buff_fclones *fclones; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci fclones = container_of(skb, struct sk_buff_fclones, skb1); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci skb->fclone = SKB_FCLONE_ORIG; 2488c2ecf20Sopenharmony_ci refcount_set(&fclones->fclone_ref, 1); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci fclones->skb2.fclone = SKB_FCLONE_CLONE; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci skb_set_kcov_handle(skb, kcov_common_handle()); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ciout: 2568c2ecf20Sopenharmony_ci return skb; 2578c2ecf20Sopenharmony_cinodata: 2588c2ecf20Sopenharmony_ci kmem_cache_free(cache, skb); 2598c2ecf20Sopenharmony_ci skb = NULL; 2608c2ecf20Sopenharmony_ci goto out; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__alloc_skb); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci/* Caller must provide SKB that is memset cleared */ 2658c2ecf20Sopenharmony_cistatic struct sk_buff *__build_skb_around(struct sk_buff *skb, 2668c2ecf20Sopenharmony_ci void *data, unsigned int frag_size) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct skb_shared_info *shinfo; 2698c2ecf20Sopenharmony_ci unsigned int size = frag_size ? : ksize(data); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci size -= SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* Assumes caller memset cleared SKB */ 2748c2ecf20Sopenharmony_ci skb->truesize = SKB_TRUESIZE(size); 2758c2ecf20Sopenharmony_ci refcount_set(&skb->users, 1); 2768c2ecf20Sopenharmony_ci skb->head = data; 2778c2ecf20Sopenharmony_ci skb->data = data; 2788c2ecf20Sopenharmony_ci skb_reset_tail_pointer(skb); 2798c2ecf20Sopenharmony_ci skb->end = skb->tail + size; 2808c2ecf20Sopenharmony_ci skb->mac_header = (typeof(skb->mac_header))~0U; 2818c2ecf20Sopenharmony_ci skb->transport_header = (typeof(skb->transport_header))~0U; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* make sure we initialize shinfo sequentially */ 2848c2ecf20Sopenharmony_ci shinfo = skb_shinfo(skb); 2858c2ecf20Sopenharmony_ci memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); 2868c2ecf20Sopenharmony_ci atomic_set(&shinfo->dataref, 1); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci skb_set_kcov_handle(skb, kcov_common_handle()); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci return skb; 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/** 2948c2ecf20Sopenharmony_ci * __build_skb - build a network buffer 2958c2ecf20Sopenharmony_ci * @data: data buffer provided by caller 2968c2ecf20Sopenharmony_ci * @frag_size: size of data, or 0 if head was kmalloced 2978c2ecf20Sopenharmony_ci * 2988c2ecf20Sopenharmony_ci * Allocate a new &sk_buff. Caller provides space holding head and 2998c2ecf20Sopenharmony_ci * skb_shared_info. @data must have been allocated by kmalloc() only if 3008c2ecf20Sopenharmony_ci * @frag_size is 0, otherwise data should come from the page allocator 3018c2ecf20Sopenharmony_ci * or vmalloc() 3028c2ecf20Sopenharmony_ci * The return is the new skb buffer. 3038c2ecf20Sopenharmony_ci * On a failure the return is %NULL, and @data is not freed. 3048c2ecf20Sopenharmony_ci * Notes : 3058c2ecf20Sopenharmony_ci * Before IO, driver allocates only data buffer where NIC put incoming frame 3068c2ecf20Sopenharmony_ci * Driver should add room at head (NET_SKB_PAD) and 3078c2ecf20Sopenharmony_ci * MUST add room at tail (SKB_DATA_ALIGN(skb_shared_info)) 3088c2ecf20Sopenharmony_ci * After IO, driver calls build_skb(), to allocate sk_buff and populate it 3098c2ecf20Sopenharmony_ci * before giving packet to stack. 3108c2ecf20Sopenharmony_ci * RX rings only contains data buffers, not full skbs. 3118c2ecf20Sopenharmony_ci */ 3128c2ecf20Sopenharmony_cistruct sk_buff *__build_skb(void *data, unsigned int frag_size) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci struct sk_buff *skb; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci skb = kmem_cache_alloc(skbuff_head_cache, GFP_ATOMIC); 3178c2ecf20Sopenharmony_ci if (unlikely(!skb)) 3188c2ecf20Sopenharmony_ci return NULL; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci memset(skb, 0, offsetof(struct sk_buff, tail)); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci return __build_skb_around(skb, data, frag_size); 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci/* build_skb() is wrapper over __build_skb(), that specifically 3268c2ecf20Sopenharmony_ci * takes care of skb->head and skb->pfmemalloc 3278c2ecf20Sopenharmony_ci * This means that if @frag_size is not zero, then @data must be backed 3288c2ecf20Sopenharmony_ci * by a page fragment, not kmalloc() or vmalloc() 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_cistruct sk_buff *build_skb(void *data, unsigned int frag_size) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct sk_buff *skb = __build_skb(data, frag_size); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci if (skb && frag_size) { 3358c2ecf20Sopenharmony_ci skb->head_frag = 1; 3368c2ecf20Sopenharmony_ci if (page_is_pfmemalloc(virt_to_head_page(data))) 3378c2ecf20Sopenharmony_ci skb->pfmemalloc = 1; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci return skb; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(build_skb); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci/** 3448c2ecf20Sopenharmony_ci * build_skb_around - build a network buffer around provided skb 3458c2ecf20Sopenharmony_ci * @skb: sk_buff provide by caller, must be memset cleared 3468c2ecf20Sopenharmony_ci * @data: data buffer provided by caller 3478c2ecf20Sopenharmony_ci * @frag_size: size of data, or 0 if head was kmalloced 3488c2ecf20Sopenharmony_ci */ 3498c2ecf20Sopenharmony_cistruct sk_buff *build_skb_around(struct sk_buff *skb, 3508c2ecf20Sopenharmony_ci void *data, unsigned int frag_size) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci if (unlikely(!skb)) 3538c2ecf20Sopenharmony_ci return NULL; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci skb = __build_skb_around(skb, data, frag_size); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if (skb && frag_size) { 3588c2ecf20Sopenharmony_ci skb->head_frag = 1; 3598c2ecf20Sopenharmony_ci if (page_is_pfmemalloc(virt_to_head_page(data))) 3608c2ecf20Sopenharmony_ci skb->pfmemalloc = 1; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci return skb; 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(build_skb_around); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci#define NAPI_SKB_CACHE_SIZE 64 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistruct napi_alloc_cache { 3698c2ecf20Sopenharmony_ci struct page_frag_cache page; 3708c2ecf20Sopenharmony_ci unsigned int skb_count; 3718c2ecf20Sopenharmony_ci void *skb_cache[NAPI_SKB_CACHE_SIZE]; 3728c2ecf20Sopenharmony_ci}; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(struct page_frag_cache, netdev_alloc_cache); 3758c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(struct napi_alloc_cache, napi_alloc_cache); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic void *__napi_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci return page_frag_alloc(&nc->page, fragsz, gfp_mask); 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_civoid *napi_alloc_frag(unsigned int fragsz) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci fragsz = SKB_DATA_ALIGN(fragsz); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci return __napi_alloc_frag(fragsz, GFP_ATOMIC); 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(napi_alloc_frag); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci/** 3938c2ecf20Sopenharmony_ci * netdev_alloc_frag - allocate a page fragment 3948c2ecf20Sopenharmony_ci * @fragsz: fragment size 3958c2ecf20Sopenharmony_ci * 3968c2ecf20Sopenharmony_ci * Allocates a frag from a page for receive buffer. 3978c2ecf20Sopenharmony_ci * Uses GFP_ATOMIC allocations. 3988c2ecf20Sopenharmony_ci */ 3998c2ecf20Sopenharmony_civoid *netdev_alloc_frag(unsigned int fragsz) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci struct page_frag_cache *nc; 4028c2ecf20Sopenharmony_ci void *data; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci fragsz = SKB_DATA_ALIGN(fragsz); 4058c2ecf20Sopenharmony_ci if (in_irq() || irqs_disabled()) { 4068c2ecf20Sopenharmony_ci nc = this_cpu_ptr(&netdev_alloc_cache); 4078c2ecf20Sopenharmony_ci data = page_frag_alloc(nc, fragsz, GFP_ATOMIC); 4088c2ecf20Sopenharmony_ci } else { 4098c2ecf20Sopenharmony_ci local_bh_disable(); 4108c2ecf20Sopenharmony_ci data = __napi_alloc_frag(fragsz, GFP_ATOMIC); 4118c2ecf20Sopenharmony_ci local_bh_enable(); 4128c2ecf20Sopenharmony_ci } 4138c2ecf20Sopenharmony_ci return data; 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ciEXPORT_SYMBOL(netdev_alloc_frag); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci/** 4188c2ecf20Sopenharmony_ci * __netdev_alloc_skb - allocate an skbuff for rx on a specific device 4198c2ecf20Sopenharmony_ci * @dev: network device to receive on 4208c2ecf20Sopenharmony_ci * @len: length to allocate 4218c2ecf20Sopenharmony_ci * @gfp_mask: get_free_pages mask, passed to alloc_skb 4228c2ecf20Sopenharmony_ci * 4238c2ecf20Sopenharmony_ci * Allocate a new &sk_buff and assign it a usage count of one. The 4248c2ecf20Sopenharmony_ci * buffer has NET_SKB_PAD headroom built in. Users should allocate 4258c2ecf20Sopenharmony_ci * the headroom they think they need without accounting for the 4268c2ecf20Sopenharmony_ci * built in space. The built in space is used for optimisations. 4278c2ecf20Sopenharmony_ci * 4288c2ecf20Sopenharmony_ci * %NULL is returned if there is no free memory. 4298c2ecf20Sopenharmony_ci */ 4308c2ecf20Sopenharmony_cistruct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len, 4318c2ecf20Sopenharmony_ci gfp_t gfp_mask) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci struct page_frag_cache *nc; 4348c2ecf20Sopenharmony_ci struct sk_buff *skb; 4358c2ecf20Sopenharmony_ci bool pfmemalloc; 4368c2ecf20Sopenharmony_ci void *data; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci len += NET_SKB_PAD; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci /* If requested length is either too small or too big, 4418c2ecf20Sopenharmony_ci * we use kmalloc() for skb->head allocation. 4428c2ecf20Sopenharmony_ci */ 4438c2ecf20Sopenharmony_ci if (len <= SKB_WITH_OVERHEAD(1024) || 4448c2ecf20Sopenharmony_ci len > SKB_WITH_OVERHEAD(PAGE_SIZE) || 4458c2ecf20Sopenharmony_ci (gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) { 4468c2ecf20Sopenharmony_ci skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE); 4478c2ecf20Sopenharmony_ci if (!skb) 4488c2ecf20Sopenharmony_ci goto skb_fail; 4498c2ecf20Sopenharmony_ci goto skb_success; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 4538c2ecf20Sopenharmony_ci len = SKB_DATA_ALIGN(len); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (sk_memalloc_socks()) 4568c2ecf20Sopenharmony_ci gfp_mask |= __GFP_MEMALLOC; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci if (in_irq() || irqs_disabled()) { 4598c2ecf20Sopenharmony_ci nc = this_cpu_ptr(&netdev_alloc_cache); 4608c2ecf20Sopenharmony_ci data = page_frag_alloc(nc, len, gfp_mask); 4618c2ecf20Sopenharmony_ci pfmemalloc = nc->pfmemalloc; 4628c2ecf20Sopenharmony_ci } else { 4638c2ecf20Sopenharmony_ci local_bh_disable(); 4648c2ecf20Sopenharmony_ci nc = this_cpu_ptr(&napi_alloc_cache.page); 4658c2ecf20Sopenharmony_ci data = page_frag_alloc(nc, len, gfp_mask); 4668c2ecf20Sopenharmony_ci pfmemalloc = nc->pfmemalloc; 4678c2ecf20Sopenharmony_ci local_bh_enable(); 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (unlikely(!data)) 4718c2ecf20Sopenharmony_ci return NULL; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci skb = __build_skb(data, len); 4748c2ecf20Sopenharmony_ci if (unlikely(!skb)) { 4758c2ecf20Sopenharmony_ci skb_free_frag(data); 4768c2ecf20Sopenharmony_ci return NULL; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (pfmemalloc) 4808c2ecf20Sopenharmony_ci skb->pfmemalloc = 1; 4818c2ecf20Sopenharmony_ci skb->head_frag = 1; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ciskb_success: 4848c2ecf20Sopenharmony_ci skb_reserve(skb, NET_SKB_PAD); 4858c2ecf20Sopenharmony_ci skb->dev = dev; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ciskb_fail: 4888c2ecf20Sopenharmony_ci return skb; 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__netdev_alloc_skb); 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci/** 4938c2ecf20Sopenharmony_ci * __napi_alloc_skb - allocate skbuff for rx in a specific NAPI instance 4948c2ecf20Sopenharmony_ci * @napi: napi instance this buffer was allocated for 4958c2ecf20Sopenharmony_ci * @len: length to allocate 4968c2ecf20Sopenharmony_ci * @gfp_mask: get_free_pages mask, passed to alloc_skb and alloc_pages 4978c2ecf20Sopenharmony_ci * 4988c2ecf20Sopenharmony_ci * Allocate a new sk_buff for use in NAPI receive. This buffer will 4998c2ecf20Sopenharmony_ci * attempt to allocate the head from a special reserved region used 5008c2ecf20Sopenharmony_ci * only for NAPI Rx allocation. By doing this we can save several 5018c2ecf20Sopenharmony_ci * CPU cycles by avoiding having to disable and re-enable IRQs. 5028c2ecf20Sopenharmony_ci * 5038c2ecf20Sopenharmony_ci * %NULL is returned if there is no free memory. 5048c2ecf20Sopenharmony_ci */ 5058c2ecf20Sopenharmony_cistruct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len, 5068c2ecf20Sopenharmony_ci gfp_t gfp_mask) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci struct napi_alloc_cache *nc; 5098c2ecf20Sopenharmony_ci struct sk_buff *skb; 5108c2ecf20Sopenharmony_ci void *data; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci len += NET_SKB_PAD + NET_IP_ALIGN; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci /* If requested length is either too small or too big, 5158c2ecf20Sopenharmony_ci * we use kmalloc() for skb->head allocation. 5168c2ecf20Sopenharmony_ci */ 5178c2ecf20Sopenharmony_ci if (len <= SKB_WITH_OVERHEAD(1024) || 5188c2ecf20Sopenharmony_ci len > SKB_WITH_OVERHEAD(PAGE_SIZE) || 5198c2ecf20Sopenharmony_ci (gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) { 5208c2ecf20Sopenharmony_ci skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE); 5218c2ecf20Sopenharmony_ci if (!skb) 5228c2ecf20Sopenharmony_ci goto skb_fail; 5238c2ecf20Sopenharmony_ci goto skb_success; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci nc = this_cpu_ptr(&napi_alloc_cache); 5278c2ecf20Sopenharmony_ci len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 5288c2ecf20Sopenharmony_ci len = SKB_DATA_ALIGN(len); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci if (sk_memalloc_socks()) 5318c2ecf20Sopenharmony_ci gfp_mask |= __GFP_MEMALLOC; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci data = page_frag_alloc(&nc->page, len, gfp_mask); 5348c2ecf20Sopenharmony_ci if (unlikely(!data)) 5358c2ecf20Sopenharmony_ci return NULL; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci skb = __build_skb(data, len); 5388c2ecf20Sopenharmony_ci if (unlikely(!skb)) { 5398c2ecf20Sopenharmony_ci skb_free_frag(data); 5408c2ecf20Sopenharmony_ci return NULL; 5418c2ecf20Sopenharmony_ci } 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci if (nc->page.pfmemalloc) 5448c2ecf20Sopenharmony_ci skb->pfmemalloc = 1; 5458c2ecf20Sopenharmony_ci skb->head_frag = 1; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ciskb_success: 5488c2ecf20Sopenharmony_ci skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); 5498c2ecf20Sopenharmony_ci skb->dev = napi->dev; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ciskb_fail: 5528c2ecf20Sopenharmony_ci return skb; 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__napi_alloc_skb); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_civoid skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, 5578c2ecf20Sopenharmony_ci int size, unsigned int truesize) 5588c2ecf20Sopenharmony_ci{ 5598c2ecf20Sopenharmony_ci skb_fill_page_desc(skb, i, page, off, size); 5608c2ecf20Sopenharmony_ci skb->len += size; 5618c2ecf20Sopenharmony_ci skb->data_len += size; 5628c2ecf20Sopenharmony_ci skb->truesize += truesize; 5638c2ecf20Sopenharmony_ci} 5648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_add_rx_frag); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_civoid skb_coalesce_rx_frag(struct sk_buff *skb, int i, int size, 5678c2ecf20Sopenharmony_ci unsigned int truesize) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci skb_frag_size_add(frag, size); 5728c2ecf20Sopenharmony_ci skb->len += size; 5738c2ecf20Sopenharmony_ci skb->data_len += size; 5748c2ecf20Sopenharmony_ci skb->truesize += truesize; 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_coalesce_rx_frag); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistatic void skb_drop_list(struct sk_buff **listp) 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci kfree_skb_list(*listp); 5818c2ecf20Sopenharmony_ci *listp = NULL; 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic inline void skb_drop_fraglist(struct sk_buff *skb) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci skb_drop_list(&skb_shinfo(skb)->frag_list); 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic void skb_clone_fraglist(struct sk_buff *skb) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci struct sk_buff *list; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci skb_walk_frags(skb, list) 5948c2ecf20Sopenharmony_ci skb_get(list); 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic void skb_free_head(struct sk_buff *skb) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci unsigned char *head = skb->head; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (skb->head_frag) 6028c2ecf20Sopenharmony_ci skb_free_frag(head); 6038c2ecf20Sopenharmony_ci else 6048c2ecf20Sopenharmony_ci kfree(head); 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic void skb_release_data(struct sk_buff *skb) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci struct skb_shared_info *shinfo = skb_shinfo(skb); 6108c2ecf20Sopenharmony_ci int i; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci if (skb->cloned && 6138c2ecf20Sopenharmony_ci atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1, 6148c2ecf20Sopenharmony_ci &shinfo->dataref)) 6158c2ecf20Sopenharmony_ci return; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci for (i = 0; i < shinfo->nr_frags; i++) 6188c2ecf20Sopenharmony_ci __skb_frag_unref(&shinfo->frags[i]); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci if (shinfo->frag_list) 6218c2ecf20Sopenharmony_ci kfree_skb_list(shinfo->frag_list); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci skb_zcopy_clear(skb, true); 6248c2ecf20Sopenharmony_ci skb_free_head(skb); 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci/* 6288c2ecf20Sopenharmony_ci * Free an skbuff by memory without cleaning the state. 6298c2ecf20Sopenharmony_ci */ 6308c2ecf20Sopenharmony_cistatic void kfree_skbmem(struct sk_buff *skb) 6318c2ecf20Sopenharmony_ci{ 6328c2ecf20Sopenharmony_ci struct sk_buff_fclones *fclones; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci switch (skb->fclone) { 6358c2ecf20Sopenharmony_ci case SKB_FCLONE_UNAVAILABLE: 6368c2ecf20Sopenharmony_ci kmem_cache_free(skbuff_head_cache, skb); 6378c2ecf20Sopenharmony_ci return; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci case SKB_FCLONE_ORIG: 6408c2ecf20Sopenharmony_ci fclones = container_of(skb, struct sk_buff_fclones, skb1); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* We usually free the clone (TX completion) before original skb 6438c2ecf20Sopenharmony_ci * This test would have no chance to be true for the clone, 6448c2ecf20Sopenharmony_ci * while here, branch prediction will be good. 6458c2ecf20Sopenharmony_ci */ 6468c2ecf20Sopenharmony_ci if (refcount_read(&fclones->fclone_ref) == 1) 6478c2ecf20Sopenharmony_ci goto fastpath; 6488c2ecf20Sopenharmony_ci break; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci default: /* SKB_FCLONE_CLONE */ 6518c2ecf20Sopenharmony_ci fclones = container_of(skb, struct sk_buff_fclones, skb2); 6528c2ecf20Sopenharmony_ci break; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci if (!refcount_dec_and_test(&fclones->fclone_ref)) 6558c2ecf20Sopenharmony_ci return; 6568c2ecf20Sopenharmony_cifastpath: 6578c2ecf20Sopenharmony_ci kmem_cache_free(skbuff_fclone_cache, fclones); 6588c2ecf20Sopenharmony_ci} 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_civoid skb_release_head_state(struct sk_buff *skb) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci skb_dst_drop(skb); 6638c2ecf20Sopenharmony_ci if (skb->destructor) { 6648c2ecf20Sopenharmony_ci WARN_ON(in_irq()); 6658c2ecf20Sopenharmony_ci skb->destructor(skb); 6668c2ecf20Sopenharmony_ci } 6678c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NF_CONNTRACK) 6688c2ecf20Sopenharmony_ci nf_conntrack_put(skb_nfct(skb)); 6698c2ecf20Sopenharmony_ci#endif 6708c2ecf20Sopenharmony_ci skb_ext_put(skb); 6718c2ecf20Sopenharmony_ci} 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci/* Free everything but the sk_buff shell. */ 6748c2ecf20Sopenharmony_cistatic void skb_release_all(struct sk_buff *skb) 6758c2ecf20Sopenharmony_ci{ 6768c2ecf20Sopenharmony_ci skb_release_head_state(skb); 6778c2ecf20Sopenharmony_ci if (likely(skb->head)) 6788c2ecf20Sopenharmony_ci skb_release_data(skb); 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci/** 6828c2ecf20Sopenharmony_ci * __kfree_skb - private function 6838c2ecf20Sopenharmony_ci * @skb: buffer 6848c2ecf20Sopenharmony_ci * 6858c2ecf20Sopenharmony_ci * Free an sk_buff. Release anything attached to the buffer. 6868c2ecf20Sopenharmony_ci * Clean the state. This is an internal helper function. Users should 6878c2ecf20Sopenharmony_ci * always call kfree_skb 6888c2ecf20Sopenharmony_ci */ 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_civoid __kfree_skb(struct sk_buff *skb) 6918c2ecf20Sopenharmony_ci{ 6928c2ecf20Sopenharmony_ci skb_release_all(skb); 6938c2ecf20Sopenharmony_ci kfree_skbmem(skb); 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__kfree_skb); 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci/** 6988c2ecf20Sopenharmony_ci * kfree_skb - free an sk_buff 6998c2ecf20Sopenharmony_ci * @skb: buffer to free 7008c2ecf20Sopenharmony_ci * 7018c2ecf20Sopenharmony_ci * Drop a reference to the buffer and free it if the usage count has 7028c2ecf20Sopenharmony_ci * hit zero. 7038c2ecf20Sopenharmony_ci */ 7048c2ecf20Sopenharmony_civoid kfree_skb(struct sk_buff *skb) 7058c2ecf20Sopenharmony_ci{ 7068c2ecf20Sopenharmony_ci if (!skb_unref(skb)) 7078c2ecf20Sopenharmony_ci return; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci trace_kfree_skb(skb, __builtin_return_address(0)); 7108c2ecf20Sopenharmony_ci __kfree_skb(skb); 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kfree_skb); 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_civoid kfree_skb_list(struct sk_buff *segs) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci while (segs) { 7178c2ecf20Sopenharmony_ci struct sk_buff *next = segs->next; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci kfree_skb(segs); 7208c2ecf20Sopenharmony_ci segs = next; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kfree_skb_list); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci/* Dump skb information and contents. 7268c2ecf20Sopenharmony_ci * 7278c2ecf20Sopenharmony_ci * Must only be called from net_ratelimit()-ed paths. 7288c2ecf20Sopenharmony_ci * 7298c2ecf20Sopenharmony_ci * Dumps whole packets if full_pkt, only headers otherwise. 7308c2ecf20Sopenharmony_ci */ 7318c2ecf20Sopenharmony_civoid skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt) 7328c2ecf20Sopenharmony_ci{ 7338c2ecf20Sopenharmony_ci struct skb_shared_info *sh = skb_shinfo(skb); 7348c2ecf20Sopenharmony_ci struct net_device *dev = skb->dev; 7358c2ecf20Sopenharmony_ci struct sock *sk = skb->sk; 7368c2ecf20Sopenharmony_ci struct sk_buff *list_skb; 7378c2ecf20Sopenharmony_ci bool has_mac, has_trans; 7388c2ecf20Sopenharmony_ci int headroom, tailroom; 7398c2ecf20Sopenharmony_ci int i, len, seg_len; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci if (full_pkt) 7428c2ecf20Sopenharmony_ci len = skb->len; 7438c2ecf20Sopenharmony_ci else 7448c2ecf20Sopenharmony_ci len = min_t(int, skb->len, MAX_HEADER + 128); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci headroom = skb_headroom(skb); 7478c2ecf20Sopenharmony_ci tailroom = skb_tailroom(skb); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci has_mac = skb_mac_header_was_set(skb); 7508c2ecf20Sopenharmony_ci has_trans = skb_transport_header_was_set(skb); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci printk("%sskb len=%u headroom=%u headlen=%u tailroom=%u\n" 7538c2ecf20Sopenharmony_ci "mac=(%d,%d) net=(%d,%d) trans=%d\n" 7548c2ecf20Sopenharmony_ci "shinfo(txflags=%u nr_frags=%u gso(size=%hu type=%u segs=%hu))\n" 7558c2ecf20Sopenharmony_ci "csum(0x%x ip_summed=%u complete_sw=%u valid=%u level=%u)\n" 7568c2ecf20Sopenharmony_ci "hash(0x%x sw=%u l4=%u) proto=0x%04x pkttype=%u iif=%d\n", 7578c2ecf20Sopenharmony_ci level, skb->len, headroom, skb_headlen(skb), tailroom, 7588c2ecf20Sopenharmony_ci has_mac ? skb->mac_header : -1, 7598c2ecf20Sopenharmony_ci has_mac ? skb_mac_header_len(skb) : -1, 7608c2ecf20Sopenharmony_ci skb->network_header, 7618c2ecf20Sopenharmony_ci has_trans ? skb_network_header_len(skb) : -1, 7628c2ecf20Sopenharmony_ci has_trans ? skb->transport_header : -1, 7638c2ecf20Sopenharmony_ci sh->tx_flags, sh->nr_frags, 7648c2ecf20Sopenharmony_ci sh->gso_size, sh->gso_type, sh->gso_segs, 7658c2ecf20Sopenharmony_ci skb->csum, skb->ip_summed, skb->csum_complete_sw, 7668c2ecf20Sopenharmony_ci skb->csum_valid, skb->csum_level, 7678c2ecf20Sopenharmony_ci skb->hash, skb->sw_hash, skb->l4_hash, 7688c2ecf20Sopenharmony_ci ntohs(skb->protocol), skb->pkt_type, skb->skb_iif); 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci if (dev) 7718c2ecf20Sopenharmony_ci printk("%sdev name=%s feat=%pNF\n", 7728c2ecf20Sopenharmony_ci level, dev->name, &dev->features); 7738c2ecf20Sopenharmony_ci if (sk) 7748c2ecf20Sopenharmony_ci printk("%ssk family=%hu type=%u proto=%u\n", 7758c2ecf20Sopenharmony_ci level, sk->sk_family, sk->sk_type, sk->sk_protocol); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci if (full_pkt && headroom) 7788c2ecf20Sopenharmony_ci print_hex_dump(level, "skb headroom: ", DUMP_PREFIX_OFFSET, 7798c2ecf20Sopenharmony_ci 16, 1, skb->head, headroom, false); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci seg_len = min_t(int, skb_headlen(skb), len); 7828c2ecf20Sopenharmony_ci if (seg_len) 7838c2ecf20Sopenharmony_ci print_hex_dump(level, "skb linear: ", DUMP_PREFIX_OFFSET, 7848c2ecf20Sopenharmony_ci 16, 1, skb->data, seg_len, false); 7858c2ecf20Sopenharmony_ci len -= seg_len; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci if (full_pkt && tailroom) 7888c2ecf20Sopenharmony_ci print_hex_dump(level, "skb tailroom: ", DUMP_PREFIX_OFFSET, 7898c2ecf20Sopenharmony_ci 16, 1, skb_tail_pointer(skb), tailroom, false); 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci for (i = 0; len && i < skb_shinfo(skb)->nr_frags; i++) { 7928c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 7938c2ecf20Sopenharmony_ci u32 p_off, p_len, copied; 7948c2ecf20Sopenharmony_ci struct page *p; 7958c2ecf20Sopenharmony_ci u8 *vaddr; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci skb_frag_foreach_page(frag, skb_frag_off(frag), 7988c2ecf20Sopenharmony_ci skb_frag_size(frag), p, p_off, p_len, 7998c2ecf20Sopenharmony_ci copied) { 8008c2ecf20Sopenharmony_ci seg_len = min_t(int, p_len, len); 8018c2ecf20Sopenharmony_ci vaddr = kmap_atomic(p); 8028c2ecf20Sopenharmony_ci print_hex_dump(level, "skb frag: ", 8038c2ecf20Sopenharmony_ci DUMP_PREFIX_OFFSET, 8048c2ecf20Sopenharmony_ci 16, 1, vaddr + p_off, seg_len, false); 8058c2ecf20Sopenharmony_ci kunmap_atomic(vaddr); 8068c2ecf20Sopenharmony_ci len -= seg_len; 8078c2ecf20Sopenharmony_ci if (!len) 8088c2ecf20Sopenharmony_ci break; 8098c2ecf20Sopenharmony_ci } 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci if (full_pkt && skb_has_frag_list(skb)) { 8138c2ecf20Sopenharmony_ci printk("skb fraglist:\n"); 8148c2ecf20Sopenharmony_ci skb_walk_frags(skb, list_skb) 8158c2ecf20Sopenharmony_ci skb_dump(level, list_skb, true); 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci} 8188c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_dump); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci/** 8218c2ecf20Sopenharmony_ci * skb_tx_error - report an sk_buff xmit error 8228c2ecf20Sopenharmony_ci * @skb: buffer that triggered an error 8238c2ecf20Sopenharmony_ci * 8248c2ecf20Sopenharmony_ci * Report xmit error if a device callback is tracking this skb. 8258c2ecf20Sopenharmony_ci * skb must be freed afterwards. 8268c2ecf20Sopenharmony_ci */ 8278c2ecf20Sopenharmony_civoid skb_tx_error(struct sk_buff *skb) 8288c2ecf20Sopenharmony_ci{ 8298c2ecf20Sopenharmony_ci skb_zcopy_clear(skb, true); 8308c2ecf20Sopenharmony_ci} 8318c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_tx_error); 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci#ifdef CONFIG_TRACEPOINTS 8348c2ecf20Sopenharmony_ci/** 8358c2ecf20Sopenharmony_ci * consume_skb - free an skbuff 8368c2ecf20Sopenharmony_ci * @skb: buffer to free 8378c2ecf20Sopenharmony_ci * 8388c2ecf20Sopenharmony_ci * Drop a ref to the buffer and free it if the usage count has hit zero 8398c2ecf20Sopenharmony_ci * Functions identically to kfree_skb, but kfree_skb assumes that the frame 8408c2ecf20Sopenharmony_ci * is being dropped after a failure and notes that 8418c2ecf20Sopenharmony_ci */ 8428c2ecf20Sopenharmony_civoid consume_skb(struct sk_buff *skb) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci if (!skb_unref(skb)) 8458c2ecf20Sopenharmony_ci return; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci trace_consume_skb(skb); 8488c2ecf20Sopenharmony_ci __kfree_skb(skb); 8498c2ecf20Sopenharmony_ci} 8508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(consume_skb); 8518c2ecf20Sopenharmony_ci#endif 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci/** 8548c2ecf20Sopenharmony_ci * consume_stateless_skb - free an skbuff, assuming it is stateless 8558c2ecf20Sopenharmony_ci * @skb: buffer to free 8568c2ecf20Sopenharmony_ci * 8578c2ecf20Sopenharmony_ci * Alike consume_skb(), but this variant assumes that this is the last 8588c2ecf20Sopenharmony_ci * skb reference and all the head states have been already dropped 8598c2ecf20Sopenharmony_ci */ 8608c2ecf20Sopenharmony_civoid __consume_stateless_skb(struct sk_buff *skb) 8618c2ecf20Sopenharmony_ci{ 8628c2ecf20Sopenharmony_ci trace_consume_skb(skb); 8638c2ecf20Sopenharmony_ci skb_release_data(skb); 8648c2ecf20Sopenharmony_ci kfree_skbmem(skb); 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_civoid __kfree_skb_flush(void) 8688c2ecf20Sopenharmony_ci{ 8698c2ecf20Sopenharmony_ci struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci /* flush skb_cache if containing objects */ 8728c2ecf20Sopenharmony_ci if (nc->skb_count) { 8738c2ecf20Sopenharmony_ci kmem_cache_free_bulk(skbuff_head_cache, nc->skb_count, 8748c2ecf20Sopenharmony_ci nc->skb_cache); 8758c2ecf20Sopenharmony_ci nc->skb_count = 0; 8768c2ecf20Sopenharmony_ci } 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic inline void _kfree_skb_defer(struct sk_buff *skb) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci /* drop skb->head and call any destructors for packet */ 8848c2ecf20Sopenharmony_ci skb_release_all(skb); 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci /* record skb to CPU local list */ 8878c2ecf20Sopenharmony_ci nc->skb_cache[nc->skb_count++] = skb; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci#ifdef CONFIG_SLUB 8908c2ecf20Sopenharmony_ci /* SLUB writes into objects when freeing */ 8918c2ecf20Sopenharmony_ci prefetchw(skb); 8928c2ecf20Sopenharmony_ci#endif 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci /* flush skb_cache if it is filled */ 8958c2ecf20Sopenharmony_ci if (unlikely(nc->skb_count == NAPI_SKB_CACHE_SIZE)) { 8968c2ecf20Sopenharmony_ci kmem_cache_free_bulk(skbuff_head_cache, NAPI_SKB_CACHE_SIZE, 8978c2ecf20Sopenharmony_ci nc->skb_cache); 8988c2ecf20Sopenharmony_ci nc->skb_count = 0; 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci} 9018c2ecf20Sopenharmony_civoid __kfree_skb_defer(struct sk_buff *skb) 9028c2ecf20Sopenharmony_ci{ 9038c2ecf20Sopenharmony_ci _kfree_skb_defer(skb); 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_civoid napi_consume_skb(struct sk_buff *skb, int budget) 9078c2ecf20Sopenharmony_ci{ 9088c2ecf20Sopenharmony_ci /* Zero budget indicate non-NAPI context called us, like netpoll */ 9098c2ecf20Sopenharmony_ci if (unlikely(!budget)) { 9108c2ecf20Sopenharmony_ci dev_consume_skb_any(skb); 9118c2ecf20Sopenharmony_ci return; 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci if (!skb_unref(skb)) 9158c2ecf20Sopenharmony_ci return; 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci /* if reaching here SKB is ready to free */ 9188c2ecf20Sopenharmony_ci trace_consume_skb(skb); 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci /* if SKB is a clone, don't handle this case */ 9218c2ecf20Sopenharmony_ci if (skb->fclone != SKB_FCLONE_UNAVAILABLE) { 9228c2ecf20Sopenharmony_ci __kfree_skb(skb); 9238c2ecf20Sopenharmony_ci return; 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci _kfree_skb_defer(skb); 9278c2ecf20Sopenharmony_ci} 9288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(napi_consume_skb); 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci/* Make sure a field is enclosed inside headers_start/headers_end section */ 9318c2ecf20Sopenharmony_ci#define CHECK_SKB_FIELD(field) \ 9328c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(struct sk_buff, field) < \ 9338c2ecf20Sopenharmony_ci offsetof(struct sk_buff, headers_start)); \ 9348c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(struct sk_buff, field) > \ 9358c2ecf20Sopenharmony_ci offsetof(struct sk_buff, headers_end)); \ 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_cistatic void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci new->tstamp = old->tstamp; 9408c2ecf20Sopenharmony_ci /* We do not copy old->sk */ 9418c2ecf20Sopenharmony_ci new->dev = old->dev; 9428c2ecf20Sopenharmony_ci memcpy(new->cb, old->cb, sizeof(old->cb)); 9438c2ecf20Sopenharmony_ci skb_dst_copy(new, old); 9448c2ecf20Sopenharmony_ci __skb_ext_copy(new, old); 9458c2ecf20Sopenharmony_ci __nf_copy(new, old, false); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci /* Note : this field could be in headers_start/headers_end section 9488c2ecf20Sopenharmony_ci * It is not yet because we do not want to have a 16 bit hole 9498c2ecf20Sopenharmony_ci */ 9508c2ecf20Sopenharmony_ci new->queue_mapping = old->queue_mapping; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci memcpy(&new->headers_start, &old->headers_start, 9538c2ecf20Sopenharmony_ci offsetof(struct sk_buff, headers_end) - 9548c2ecf20Sopenharmony_ci offsetof(struct sk_buff, headers_start)); 9558c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(protocol); 9568c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(csum); 9578c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(hash); 9588c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(priority); 9598c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(skb_iif); 9608c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(vlan_proto); 9618c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(vlan_tci); 9628c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(transport_header); 9638c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(network_header); 9648c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(mac_header); 9658c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(inner_protocol); 9668c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(inner_transport_header); 9678c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(inner_network_header); 9688c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(inner_mac_header); 9698c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(mark); 9708c2ecf20Sopenharmony_ci#ifdef CONFIG_NETWORK_SECMARK 9718c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(secmark); 9728c2ecf20Sopenharmony_ci#endif 9738c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_RX_BUSY_POLL 9748c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(napi_id); 9758c2ecf20Sopenharmony_ci#endif 9768c2ecf20Sopenharmony_ci#ifdef CONFIG_XPS 9778c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(sender_cpu); 9788c2ecf20Sopenharmony_ci#endif 9798c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_SCHED 9808c2ecf20Sopenharmony_ci CHECK_SKB_FIELD(tc_index); 9818c2ecf20Sopenharmony_ci#endif 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci} 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci/* 9868c2ecf20Sopenharmony_ci * You should not add any new code to this function. Add it to 9878c2ecf20Sopenharmony_ci * __copy_skb_header above instead. 9888c2ecf20Sopenharmony_ci */ 9898c2ecf20Sopenharmony_cistatic struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) 9908c2ecf20Sopenharmony_ci{ 9918c2ecf20Sopenharmony_ci#define C(x) n->x = skb->x 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci n->next = n->prev = NULL; 9948c2ecf20Sopenharmony_ci n->sk = NULL; 9958c2ecf20Sopenharmony_ci __copy_skb_header(n, skb); 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci C(len); 9988c2ecf20Sopenharmony_ci C(data_len); 9998c2ecf20Sopenharmony_ci C(mac_len); 10008c2ecf20Sopenharmony_ci n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; 10018c2ecf20Sopenharmony_ci n->cloned = 1; 10028c2ecf20Sopenharmony_ci n->nohdr = 0; 10038c2ecf20Sopenharmony_ci n->peeked = 0; 10048c2ecf20Sopenharmony_ci C(pfmemalloc); 10058c2ecf20Sopenharmony_ci n->destructor = NULL; 10068c2ecf20Sopenharmony_ci C(tail); 10078c2ecf20Sopenharmony_ci C(end); 10088c2ecf20Sopenharmony_ci C(head); 10098c2ecf20Sopenharmony_ci C(head_frag); 10108c2ecf20Sopenharmony_ci C(data); 10118c2ecf20Sopenharmony_ci C(truesize); 10128c2ecf20Sopenharmony_ci refcount_set(&n->users, 1); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci atomic_inc(&(skb_shinfo(skb)->dataref)); 10158c2ecf20Sopenharmony_ci skb->cloned = 1; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci return n; 10188c2ecf20Sopenharmony_ci#undef C 10198c2ecf20Sopenharmony_ci} 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci/** 10228c2ecf20Sopenharmony_ci * alloc_skb_for_msg() - allocate sk_buff to wrap frag list forming a msg 10238c2ecf20Sopenharmony_ci * @first: first sk_buff of the msg 10248c2ecf20Sopenharmony_ci */ 10258c2ecf20Sopenharmony_cistruct sk_buff *alloc_skb_for_msg(struct sk_buff *first) 10268c2ecf20Sopenharmony_ci{ 10278c2ecf20Sopenharmony_ci struct sk_buff *n; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci n = alloc_skb(0, GFP_ATOMIC); 10308c2ecf20Sopenharmony_ci if (!n) 10318c2ecf20Sopenharmony_ci return NULL; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci n->len = first->len; 10348c2ecf20Sopenharmony_ci n->data_len = first->len; 10358c2ecf20Sopenharmony_ci n->truesize = first->truesize; 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci skb_shinfo(n)->frag_list = first; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci __copy_skb_header(n, first); 10408c2ecf20Sopenharmony_ci n->destructor = NULL; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci return n; 10438c2ecf20Sopenharmony_ci} 10448c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(alloc_skb_for_msg); 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci/** 10478c2ecf20Sopenharmony_ci * skb_morph - morph one skb into another 10488c2ecf20Sopenharmony_ci * @dst: the skb to receive the contents 10498c2ecf20Sopenharmony_ci * @src: the skb to supply the contents 10508c2ecf20Sopenharmony_ci * 10518c2ecf20Sopenharmony_ci * This is identical to skb_clone except that the target skb is 10528c2ecf20Sopenharmony_ci * supplied by the user. 10538c2ecf20Sopenharmony_ci * 10548c2ecf20Sopenharmony_ci * The target skb is returned upon exit. 10558c2ecf20Sopenharmony_ci */ 10568c2ecf20Sopenharmony_cistruct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) 10578c2ecf20Sopenharmony_ci{ 10588c2ecf20Sopenharmony_ci skb_release_all(dst); 10598c2ecf20Sopenharmony_ci return __skb_clone(dst, src); 10608c2ecf20Sopenharmony_ci} 10618c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_morph); 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ciint mm_account_pinned_pages(struct mmpin *mmp, size_t size) 10648c2ecf20Sopenharmony_ci{ 10658c2ecf20Sopenharmony_ci unsigned long max_pg, num_pg, new_pg, old_pg; 10668c2ecf20Sopenharmony_ci struct user_struct *user; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci if (capable(CAP_IPC_LOCK) || !size) 10698c2ecf20Sopenharmony_ci return 0; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci num_pg = (size >> PAGE_SHIFT) + 2; /* worst case */ 10728c2ecf20Sopenharmony_ci max_pg = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 10738c2ecf20Sopenharmony_ci user = mmp->user ? : current_user(); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci do { 10768c2ecf20Sopenharmony_ci old_pg = atomic_long_read(&user->locked_vm); 10778c2ecf20Sopenharmony_ci new_pg = old_pg + num_pg; 10788c2ecf20Sopenharmony_ci if (new_pg > max_pg) 10798c2ecf20Sopenharmony_ci return -ENOBUFS; 10808c2ecf20Sopenharmony_ci } while (atomic_long_cmpxchg(&user->locked_vm, old_pg, new_pg) != 10818c2ecf20Sopenharmony_ci old_pg); 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (!mmp->user) { 10848c2ecf20Sopenharmony_ci mmp->user = get_uid(user); 10858c2ecf20Sopenharmony_ci mmp->num_pg = num_pg; 10868c2ecf20Sopenharmony_ci } else { 10878c2ecf20Sopenharmony_ci mmp->num_pg += num_pg; 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci return 0; 10918c2ecf20Sopenharmony_ci} 10928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mm_account_pinned_pages); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_civoid mm_unaccount_pinned_pages(struct mmpin *mmp) 10958c2ecf20Sopenharmony_ci{ 10968c2ecf20Sopenharmony_ci if (mmp->user) { 10978c2ecf20Sopenharmony_ci atomic_long_sub(mmp->num_pg, &mmp->user->locked_vm); 10988c2ecf20Sopenharmony_ci free_uid(mmp->user); 10998c2ecf20Sopenharmony_ci } 11008c2ecf20Sopenharmony_ci} 11018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mm_unaccount_pinned_pages); 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_cistruct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size) 11048c2ecf20Sopenharmony_ci{ 11058c2ecf20Sopenharmony_ci struct ubuf_info *uarg; 11068c2ecf20Sopenharmony_ci struct sk_buff *skb; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci WARN_ON_ONCE(!in_task()); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci skb = sock_omalloc(sk, 0, GFP_KERNEL); 11118c2ecf20Sopenharmony_ci if (!skb) 11128c2ecf20Sopenharmony_ci return NULL; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(*uarg) > sizeof(skb->cb)); 11158c2ecf20Sopenharmony_ci uarg = (void *)skb->cb; 11168c2ecf20Sopenharmony_ci uarg->mmp.user = NULL; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci if (mm_account_pinned_pages(&uarg->mmp, size)) { 11198c2ecf20Sopenharmony_ci kfree_skb(skb); 11208c2ecf20Sopenharmony_ci return NULL; 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci uarg->callback = sock_zerocopy_callback; 11248c2ecf20Sopenharmony_ci uarg->id = ((u32)atomic_inc_return(&sk->sk_zckey)) - 1; 11258c2ecf20Sopenharmony_ci uarg->len = 1; 11268c2ecf20Sopenharmony_ci uarg->bytelen = size; 11278c2ecf20Sopenharmony_ci uarg->zerocopy = 1; 11288c2ecf20Sopenharmony_ci refcount_set(&uarg->refcnt, 1); 11298c2ecf20Sopenharmony_ci sock_hold(sk); 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci return uarg; 11328c2ecf20Sopenharmony_ci} 11338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sock_zerocopy_alloc); 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_cistatic inline struct sk_buff *skb_from_uarg(struct ubuf_info *uarg) 11368c2ecf20Sopenharmony_ci{ 11378c2ecf20Sopenharmony_ci return container_of((void *)uarg, struct sk_buff, cb); 11388c2ecf20Sopenharmony_ci} 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_cistruct ubuf_info *sock_zerocopy_realloc(struct sock *sk, size_t size, 11418c2ecf20Sopenharmony_ci struct ubuf_info *uarg) 11428c2ecf20Sopenharmony_ci{ 11438c2ecf20Sopenharmony_ci if (uarg) { 11448c2ecf20Sopenharmony_ci const u32 byte_limit = 1 << 19; /* limit to a few TSO */ 11458c2ecf20Sopenharmony_ci u32 bytelen, next; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci /* realloc only when socket is locked (TCP, UDP cork), 11488c2ecf20Sopenharmony_ci * so uarg->len and sk_zckey access is serialized 11498c2ecf20Sopenharmony_ci */ 11508c2ecf20Sopenharmony_ci if (!sock_owned_by_user(sk)) { 11518c2ecf20Sopenharmony_ci WARN_ON_ONCE(1); 11528c2ecf20Sopenharmony_ci return NULL; 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci bytelen = uarg->bytelen + size; 11568c2ecf20Sopenharmony_ci if (uarg->len == USHRT_MAX - 1 || bytelen > byte_limit) { 11578c2ecf20Sopenharmony_ci /* TCP can create new skb to attach new uarg */ 11588c2ecf20Sopenharmony_ci if (sk->sk_type == SOCK_STREAM) 11598c2ecf20Sopenharmony_ci goto new_alloc; 11608c2ecf20Sopenharmony_ci return NULL; 11618c2ecf20Sopenharmony_ci } 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci next = (u32)atomic_read(&sk->sk_zckey); 11648c2ecf20Sopenharmony_ci if ((u32)(uarg->id + uarg->len) == next) { 11658c2ecf20Sopenharmony_ci if (mm_account_pinned_pages(&uarg->mmp, size)) 11668c2ecf20Sopenharmony_ci return NULL; 11678c2ecf20Sopenharmony_ci uarg->len++; 11688c2ecf20Sopenharmony_ci uarg->bytelen = bytelen; 11698c2ecf20Sopenharmony_ci atomic_set(&sk->sk_zckey, ++next); 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci /* no extra ref when appending to datagram (MSG_MORE) */ 11728c2ecf20Sopenharmony_ci if (sk->sk_type == SOCK_STREAM) 11738c2ecf20Sopenharmony_ci sock_zerocopy_get(uarg); 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci return uarg; 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci } 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_cinew_alloc: 11808c2ecf20Sopenharmony_ci return sock_zerocopy_alloc(sk, size); 11818c2ecf20Sopenharmony_ci} 11828c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sock_zerocopy_realloc); 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_cistatic bool skb_zerocopy_notify_extend(struct sk_buff *skb, u32 lo, u16 len) 11858c2ecf20Sopenharmony_ci{ 11868c2ecf20Sopenharmony_ci struct sock_exterr_skb *serr = SKB_EXT_ERR(skb); 11878c2ecf20Sopenharmony_ci u32 old_lo, old_hi; 11888c2ecf20Sopenharmony_ci u64 sum_len; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci old_lo = serr->ee.ee_info; 11918c2ecf20Sopenharmony_ci old_hi = serr->ee.ee_data; 11928c2ecf20Sopenharmony_ci sum_len = old_hi - old_lo + 1ULL + len; 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci if (sum_len >= (1ULL << 32)) 11958c2ecf20Sopenharmony_ci return false; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci if (lo != old_hi + 1) 11988c2ecf20Sopenharmony_ci return false; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci serr->ee.ee_data += len; 12018c2ecf20Sopenharmony_ci return true; 12028c2ecf20Sopenharmony_ci} 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_civoid sock_zerocopy_callback(struct ubuf_info *uarg, bool success) 12058c2ecf20Sopenharmony_ci{ 12068c2ecf20Sopenharmony_ci struct sk_buff *tail, *skb = skb_from_uarg(uarg); 12078c2ecf20Sopenharmony_ci struct sock_exterr_skb *serr; 12088c2ecf20Sopenharmony_ci struct sock *sk = skb->sk; 12098c2ecf20Sopenharmony_ci struct sk_buff_head *q; 12108c2ecf20Sopenharmony_ci unsigned long flags; 12118c2ecf20Sopenharmony_ci u32 lo, hi; 12128c2ecf20Sopenharmony_ci u16 len; 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci mm_unaccount_pinned_pages(&uarg->mmp); 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci /* if !len, there was only 1 call, and it was aborted 12178c2ecf20Sopenharmony_ci * so do not queue a completion notification 12188c2ecf20Sopenharmony_ci */ 12198c2ecf20Sopenharmony_ci if (!uarg->len || sock_flag(sk, SOCK_DEAD)) 12208c2ecf20Sopenharmony_ci goto release; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci len = uarg->len; 12238c2ecf20Sopenharmony_ci lo = uarg->id; 12248c2ecf20Sopenharmony_ci hi = uarg->id + len - 1; 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci serr = SKB_EXT_ERR(skb); 12278c2ecf20Sopenharmony_ci memset(serr, 0, sizeof(*serr)); 12288c2ecf20Sopenharmony_ci serr->ee.ee_errno = 0; 12298c2ecf20Sopenharmony_ci serr->ee.ee_origin = SO_EE_ORIGIN_ZEROCOPY; 12308c2ecf20Sopenharmony_ci serr->ee.ee_data = hi; 12318c2ecf20Sopenharmony_ci serr->ee.ee_info = lo; 12328c2ecf20Sopenharmony_ci if (!success) 12338c2ecf20Sopenharmony_ci serr->ee.ee_code |= SO_EE_CODE_ZEROCOPY_COPIED; 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci q = &sk->sk_error_queue; 12368c2ecf20Sopenharmony_ci spin_lock_irqsave(&q->lock, flags); 12378c2ecf20Sopenharmony_ci tail = skb_peek_tail(q); 12388c2ecf20Sopenharmony_ci if (!tail || SKB_EXT_ERR(tail)->ee.ee_origin != SO_EE_ORIGIN_ZEROCOPY || 12398c2ecf20Sopenharmony_ci !skb_zerocopy_notify_extend(tail, lo, len)) { 12408c2ecf20Sopenharmony_ci __skb_queue_tail(q, skb); 12418c2ecf20Sopenharmony_ci skb = NULL; 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&q->lock, flags); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci sk->sk_error_report(sk); 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_cirelease: 12488c2ecf20Sopenharmony_ci consume_skb(skb); 12498c2ecf20Sopenharmony_ci sock_put(sk); 12508c2ecf20Sopenharmony_ci} 12518c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sock_zerocopy_callback); 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_civoid sock_zerocopy_put(struct ubuf_info *uarg) 12548c2ecf20Sopenharmony_ci{ 12558c2ecf20Sopenharmony_ci if (uarg && refcount_dec_and_test(&uarg->refcnt)) { 12568c2ecf20Sopenharmony_ci if (uarg->callback) 12578c2ecf20Sopenharmony_ci uarg->callback(uarg, uarg->zerocopy); 12588c2ecf20Sopenharmony_ci else 12598c2ecf20Sopenharmony_ci consume_skb(skb_from_uarg(uarg)); 12608c2ecf20Sopenharmony_ci } 12618c2ecf20Sopenharmony_ci} 12628c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sock_zerocopy_put); 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_civoid sock_zerocopy_put_abort(struct ubuf_info *uarg, bool have_uref) 12658c2ecf20Sopenharmony_ci{ 12668c2ecf20Sopenharmony_ci if (uarg) { 12678c2ecf20Sopenharmony_ci struct sock *sk = skb_from_uarg(uarg)->sk; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci atomic_dec(&sk->sk_zckey); 12708c2ecf20Sopenharmony_ci uarg->len--; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci if (have_uref) 12738c2ecf20Sopenharmony_ci sock_zerocopy_put(uarg); 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci} 12768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sock_zerocopy_put_abort); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ciint skb_zerocopy_iter_dgram(struct sk_buff *skb, struct msghdr *msg, int len) 12798c2ecf20Sopenharmony_ci{ 12808c2ecf20Sopenharmony_ci return __zerocopy_sg_from_iter(skb->sk, skb, &msg->msg_iter, len); 12818c2ecf20Sopenharmony_ci} 12828c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_zerocopy_iter_dgram); 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ciint skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb, 12858c2ecf20Sopenharmony_ci struct msghdr *msg, int len, 12868c2ecf20Sopenharmony_ci struct ubuf_info *uarg) 12878c2ecf20Sopenharmony_ci{ 12888c2ecf20Sopenharmony_ci struct ubuf_info *orig_uarg = skb_zcopy(skb); 12898c2ecf20Sopenharmony_ci struct iov_iter orig_iter = msg->msg_iter; 12908c2ecf20Sopenharmony_ci int err, orig_len = skb->len; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci /* An skb can only point to one uarg. This edge case happens when 12938c2ecf20Sopenharmony_ci * TCP appends to an skb, but zerocopy_realloc triggered a new alloc. 12948c2ecf20Sopenharmony_ci */ 12958c2ecf20Sopenharmony_ci if (orig_uarg && uarg != orig_uarg) 12968c2ecf20Sopenharmony_ci return -EEXIST; 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci err = __zerocopy_sg_from_iter(sk, skb, &msg->msg_iter, len); 12998c2ecf20Sopenharmony_ci if (err == -EFAULT || (err == -EMSGSIZE && skb->len == orig_len)) { 13008c2ecf20Sopenharmony_ci struct sock *save_sk = skb->sk; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci /* Streams do not free skb on error. Reset to prev state. */ 13038c2ecf20Sopenharmony_ci msg->msg_iter = orig_iter; 13048c2ecf20Sopenharmony_ci skb->sk = sk; 13058c2ecf20Sopenharmony_ci ___pskb_trim(skb, orig_len); 13068c2ecf20Sopenharmony_ci skb->sk = save_sk; 13078c2ecf20Sopenharmony_ci return err; 13088c2ecf20Sopenharmony_ci } 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci skb_zcopy_set(skb, uarg, NULL); 13118c2ecf20Sopenharmony_ci return skb->len - orig_len; 13128c2ecf20Sopenharmony_ci} 13138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_zerocopy_iter_stream); 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_cistatic int skb_zerocopy_clone(struct sk_buff *nskb, struct sk_buff *orig, 13168c2ecf20Sopenharmony_ci gfp_t gfp_mask) 13178c2ecf20Sopenharmony_ci{ 13188c2ecf20Sopenharmony_ci if (skb_zcopy(orig)) { 13198c2ecf20Sopenharmony_ci if (skb_zcopy(nskb)) { 13208c2ecf20Sopenharmony_ci /* !gfp_mask callers are verified to !skb_zcopy(nskb) */ 13218c2ecf20Sopenharmony_ci if (!gfp_mask) { 13228c2ecf20Sopenharmony_ci WARN_ON_ONCE(1); 13238c2ecf20Sopenharmony_ci return -ENOMEM; 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci if (skb_uarg(nskb) == skb_uarg(orig)) 13268c2ecf20Sopenharmony_ci return 0; 13278c2ecf20Sopenharmony_ci if (skb_copy_ubufs(nskb, GFP_ATOMIC)) 13288c2ecf20Sopenharmony_ci return -EIO; 13298c2ecf20Sopenharmony_ci } 13308c2ecf20Sopenharmony_ci skb_zcopy_set(nskb, skb_uarg(orig), NULL); 13318c2ecf20Sopenharmony_ci } 13328c2ecf20Sopenharmony_ci return 0; 13338c2ecf20Sopenharmony_ci} 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci/** 13368c2ecf20Sopenharmony_ci * skb_copy_ubufs - copy userspace skb frags buffers to kernel 13378c2ecf20Sopenharmony_ci * @skb: the skb to modify 13388c2ecf20Sopenharmony_ci * @gfp_mask: allocation priority 13398c2ecf20Sopenharmony_ci * 13408c2ecf20Sopenharmony_ci * This must be called on SKBTX_DEV_ZEROCOPY skb. 13418c2ecf20Sopenharmony_ci * It will copy all frags into kernel and drop the reference 13428c2ecf20Sopenharmony_ci * to userspace pages. 13438c2ecf20Sopenharmony_ci * 13448c2ecf20Sopenharmony_ci * If this function is called from an interrupt gfp_mask() must be 13458c2ecf20Sopenharmony_ci * %GFP_ATOMIC. 13468c2ecf20Sopenharmony_ci * 13478c2ecf20Sopenharmony_ci * Returns 0 on success or a negative error code on failure 13488c2ecf20Sopenharmony_ci * to allocate kernel memory to copy to. 13498c2ecf20Sopenharmony_ci */ 13508c2ecf20Sopenharmony_ciint skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) 13518c2ecf20Sopenharmony_ci{ 13528c2ecf20Sopenharmony_ci int num_frags = skb_shinfo(skb)->nr_frags; 13538c2ecf20Sopenharmony_ci struct page *page, *head = NULL; 13548c2ecf20Sopenharmony_ci int i, new_frags; 13558c2ecf20Sopenharmony_ci u32 d_off; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci if (skb_shared(skb) || skb_unclone(skb, gfp_mask)) 13588c2ecf20Sopenharmony_ci return -EINVAL; 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci if (!num_frags) 13618c2ecf20Sopenharmony_ci goto release; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci new_frags = (__skb_pagelen(skb) + PAGE_SIZE - 1) >> PAGE_SHIFT; 13648c2ecf20Sopenharmony_ci for (i = 0; i < new_frags; i++) { 13658c2ecf20Sopenharmony_ci page = alloc_page(gfp_mask); 13668c2ecf20Sopenharmony_ci if (!page) { 13678c2ecf20Sopenharmony_ci while (head) { 13688c2ecf20Sopenharmony_ci struct page *next = (struct page *)page_private(head); 13698c2ecf20Sopenharmony_ci put_page(head); 13708c2ecf20Sopenharmony_ci head = next; 13718c2ecf20Sopenharmony_ci } 13728c2ecf20Sopenharmony_ci return -ENOMEM; 13738c2ecf20Sopenharmony_ci } 13748c2ecf20Sopenharmony_ci set_page_private(page, (unsigned long)head); 13758c2ecf20Sopenharmony_ci head = page; 13768c2ecf20Sopenharmony_ci } 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci page = head; 13798c2ecf20Sopenharmony_ci d_off = 0; 13808c2ecf20Sopenharmony_ci for (i = 0; i < num_frags; i++) { 13818c2ecf20Sopenharmony_ci skb_frag_t *f = &skb_shinfo(skb)->frags[i]; 13828c2ecf20Sopenharmony_ci u32 p_off, p_len, copied; 13838c2ecf20Sopenharmony_ci struct page *p; 13848c2ecf20Sopenharmony_ci u8 *vaddr; 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci skb_frag_foreach_page(f, skb_frag_off(f), skb_frag_size(f), 13878c2ecf20Sopenharmony_ci p, p_off, p_len, copied) { 13888c2ecf20Sopenharmony_ci u32 copy, done = 0; 13898c2ecf20Sopenharmony_ci vaddr = kmap_atomic(p); 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci while (done < p_len) { 13928c2ecf20Sopenharmony_ci if (d_off == PAGE_SIZE) { 13938c2ecf20Sopenharmony_ci d_off = 0; 13948c2ecf20Sopenharmony_ci page = (struct page *)page_private(page); 13958c2ecf20Sopenharmony_ci } 13968c2ecf20Sopenharmony_ci copy = min_t(u32, PAGE_SIZE - d_off, p_len - done); 13978c2ecf20Sopenharmony_ci memcpy(page_address(page) + d_off, 13988c2ecf20Sopenharmony_ci vaddr + p_off + done, copy); 13998c2ecf20Sopenharmony_ci done += copy; 14008c2ecf20Sopenharmony_ci d_off += copy; 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci kunmap_atomic(vaddr); 14038c2ecf20Sopenharmony_ci } 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci /* skb frags release userspace buffers */ 14078c2ecf20Sopenharmony_ci for (i = 0; i < num_frags; i++) 14088c2ecf20Sopenharmony_ci skb_frag_unref(skb, i); 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci /* skb frags point to kernel buffers */ 14118c2ecf20Sopenharmony_ci for (i = 0; i < new_frags - 1; i++) { 14128c2ecf20Sopenharmony_ci __skb_fill_page_desc(skb, i, head, 0, PAGE_SIZE); 14138c2ecf20Sopenharmony_ci head = (struct page *)page_private(head); 14148c2ecf20Sopenharmony_ci } 14158c2ecf20Sopenharmony_ci __skb_fill_page_desc(skb, new_frags - 1, head, 0, d_off); 14168c2ecf20Sopenharmony_ci skb_shinfo(skb)->nr_frags = new_frags; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_cirelease: 14198c2ecf20Sopenharmony_ci skb_zcopy_clear(skb, false); 14208c2ecf20Sopenharmony_ci return 0; 14218c2ecf20Sopenharmony_ci} 14228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_copy_ubufs); 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci/** 14258c2ecf20Sopenharmony_ci * skb_clone - duplicate an sk_buff 14268c2ecf20Sopenharmony_ci * @skb: buffer to clone 14278c2ecf20Sopenharmony_ci * @gfp_mask: allocation priority 14288c2ecf20Sopenharmony_ci * 14298c2ecf20Sopenharmony_ci * Duplicate an &sk_buff. The new one is not owned by a socket. Both 14308c2ecf20Sopenharmony_ci * copies share the same packet data but not structure. The new 14318c2ecf20Sopenharmony_ci * buffer has a reference count of 1. If the allocation fails the 14328c2ecf20Sopenharmony_ci * function returns %NULL otherwise the new buffer is returned. 14338c2ecf20Sopenharmony_ci * 14348c2ecf20Sopenharmony_ci * If this function is called from an interrupt gfp_mask() must be 14358c2ecf20Sopenharmony_ci * %GFP_ATOMIC. 14368c2ecf20Sopenharmony_ci */ 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_cistruct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) 14398c2ecf20Sopenharmony_ci{ 14408c2ecf20Sopenharmony_ci struct sk_buff_fclones *fclones = container_of(skb, 14418c2ecf20Sopenharmony_ci struct sk_buff_fclones, 14428c2ecf20Sopenharmony_ci skb1); 14438c2ecf20Sopenharmony_ci struct sk_buff *n; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci if (skb_orphan_frags(skb, gfp_mask)) 14468c2ecf20Sopenharmony_ci return NULL; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci if (skb->fclone == SKB_FCLONE_ORIG && 14498c2ecf20Sopenharmony_ci refcount_read(&fclones->fclone_ref) == 1) { 14508c2ecf20Sopenharmony_ci n = &fclones->skb2; 14518c2ecf20Sopenharmony_ci refcount_set(&fclones->fclone_ref, 2); 14528c2ecf20Sopenharmony_ci } else { 14538c2ecf20Sopenharmony_ci if (skb_pfmemalloc(skb)) 14548c2ecf20Sopenharmony_ci gfp_mask |= __GFP_MEMALLOC; 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci n = kmem_cache_alloc(skbuff_head_cache, gfp_mask); 14578c2ecf20Sopenharmony_ci if (!n) 14588c2ecf20Sopenharmony_ci return NULL; 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci n->fclone = SKB_FCLONE_UNAVAILABLE; 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci return __skb_clone(n, skb); 14648c2ecf20Sopenharmony_ci} 14658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_clone); 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_civoid skb_headers_offset_update(struct sk_buff *skb, int off) 14688c2ecf20Sopenharmony_ci{ 14698c2ecf20Sopenharmony_ci /* Only adjust this if it actually is csum_start rather than csum */ 14708c2ecf20Sopenharmony_ci if (skb->ip_summed == CHECKSUM_PARTIAL) 14718c2ecf20Sopenharmony_ci skb->csum_start += off; 14728c2ecf20Sopenharmony_ci /* {transport,network,mac}_header and tail are relative to skb->head */ 14738c2ecf20Sopenharmony_ci skb->transport_header += off; 14748c2ecf20Sopenharmony_ci skb->network_header += off; 14758c2ecf20Sopenharmony_ci if (skb_mac_header_was_set(skb)) 14768c2ecf20Sopenharmony_ci skb->mac_header += off; 14778c2ecf20Sopenharmony_ci skb->inner_transport_header += off; 14788c2ecf20Sopenharmony_ci skb->inner_network_header += off; 14798c2ecf20Sopenharmony_ci skb->inner_mac_header += off; 14808c2ecf20Sopenharmony_ci} 14818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_headers_offset_update); 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_civoid skb_copy_header(struct sk_buff *new, const struct sk_buff *old) 14848c2ecf20Sopenharmony_ci{ 14858c2ecf20Sopenharmony_ci __copy_skb_header(new, old); 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; 14888c2ecf20Sopenharmony_ci skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; 14898c2ecf20Sopenharmony_ci skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; 14908c2ecf20Sopenharmony_ci} 14918c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_copy_header); 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_cistatic inline int skb_alloc_rx_flag(const struct sk_buff *skb) 14948c2ecf20Sopenharmony_ci{ 14958c2ecf20Sopenharmony_ci if (skb_pfmemalloc(skb)) 14968c2ecf20Sopenharmony_ci return SKB_ALLOC_RX; 14978c2ecf20Sopenharmony_ci return 0; 14988c2ecf20Sopenharmony_ci} 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci/** 15018c2ecf20Sopenharmony_ci * skb_copy - create private copy of an sk_buff 15028c2ecf20Sopenharmony_ci * @skb: buffer to copy 15038c2ecf20Sopenharmony_ci * @gfp_mask: allocation priority 15048c2ecf20Sopenharmony_ci * 15058c2ecf20Sopenharmony_ci * Make a copy of both an &sk_buff and its data. This is used when the 15068c2ecf20Sopenharmony_ci * caller wishes to modify the data and needs a private copy of the 15078c2ecf20Sopenharmony_ci * data to alter. Returns %NULL on failure or the pointer to the buffer 15088c2ecf20Sopenharmony_ci * on success. The returned buffer has a reference count of 1. 15098c2ecf20Sopenharmony_ci * 15108c2ecf20Sopenharmony_ci * As by-product this function converts non-linear &sk_buff to linear 15118c2ecf20Sopenharmony_ci * one, so that &sk_buff becomes completely private and caller is allowed 15128c2ecf20Sopenharmony_ci * to modify all the data of returned buffer. This means that this 15138c2ecf20Sopenharmony_ci * function is not recommended for use in circumstances when only 15148c2ecf20Sopenharmony_ci * header is going to be modified. Use pskb_copy() instead. 15158c2ecf20Sopenharmony_ci */ 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_cistruct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) 15188c2ecf20Sopenharmony_ci{ 15198c2ecf20Sopenharmony_ci struct sk_buff *n; 15208c2ecf20Sopenharmony_ci unsigned int size; 15218c2ecf20Sopenharmony_ci int headerlen; 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST)) 15248c2ecf20Sopenharmony_ci return NULL; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci headerlen = skb_headroom(skb); 15278c2ecf20Sopenharmony_ci size = skb_end_offset(skb) + skb->data_len; 15288c2ecf20Sopenharmony_ci n = __alloc_skb(size, gfp_mask, 15298c2ecf20Sopenharmony_ci skb_alloc_rx_flag(skb), NUMA_NO_NODE); 15308c2ecf20Sopenharmony_ci if (!n) 15318c2ecf20Sopenharmony_ci return NULL; 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci /* Set the data pointer */ 15348c2ecf20Sopenharmony_ci skb_reserve(n, headerlen); 15358c2ecf20Sopenharmony_ci /* Set the tail pointer and length */ 15368c2ecf20Sopenharmony_ci skb_put(n, skb->len); 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len)); 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci skb_copy_header(n, skb); 15418c2ecf20Sopenharmony_ci return n; 15428c2ecf20Sopenharmony_ci} 15438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_copy); 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci/** 15468c2ecf20Sopenharmony_ci * __pskb_copy_fclone - create copy of an sk_buff with private head. 15478c2ecf20Sopenharmony_ci * @skb: buffer to copy 15488c2ecf20Sopenharmony_ci * @headroom: headroom of new skb 15498c2ecf20Sopenharmony_ci * @gfp_mask: allocation priority 15508c2ecf20Sopenharmony_ci * @fclone: if true allocate the copy of the skb from the fclone 15518c2ecf20Sopenharmony_ci * cache instead of the head cache; it is recommended to set this 15528c2ecf20Sopenharmony_ci * to true for the cases where the copy will likely be cloned 15538c2ecf20Sopenharmony_ci * 15548c2ecf20Sopenharmony_ci * Make a copy of both an &sk_buff and part of its data, located 15558c2ecf20Sopenharmony_ci * in header. Fragmented data remain shared. This is used when 15568c2ecf20Sopenharmony_ci * the caller wishes to modify only header of &sk_buff and needs 15578c2ecf20Sopenharmony_ci * private copy of the header to alter. Returns %NULL on failure 15588c2ecf20Sopenharmony_ci * or the pointer to the buffer on success. 15598c2ecf20Sopenharmony_ci * The returned buffer has a reference count of 1. 15608c2ecf20Sopenharmony_ci */ 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_cistruct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom, 15638c2ecf20Sopenharmony_ci gfp_t gfp_mask, bool fclone) 15648c2ecf20Sopenharmony_ci{ 15658c2ecf20Sopenharmony_ci unsigned int size = skb_headlen(skb) + headroom; 15668c2ecf20Sopenharmony_ci int flags = skb_alloc_rx_flag(skb) | (fclone ? SKB_ALLOC_FCLONE : 0); 15678c2ecf20Sopenharmony_ci struct sk_buff *n = __alloc_skb(size, gfp_mask, flags, NUMA_NO_NODE); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci if (!n) 15708c2ecf20Sopenharmony_ci goto out; 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci /* Set the data pointer */ 15738c2ecf20Sopenharmony_ci skb_reserve(n, headroom); 15748c2ecf20Sopenharmony_ci /* Set the tail pointer and length */ 15758c2ecf20Sopenharmony_ci skb_put(n, skb_headlen(skb)); 15768c2ecf20Sopenharmony_ci /* Copy the bytes */ 15778c2ecf20Sopenharmony_ci skb_copy_from_linear_data(skb, n->data, n->len); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci n->truesize += skb->data_len; 15808c2ecf20Sopenharmony_ci n->data_len = skb->data_len; 15818c2ecf20Sopenharmony_ci n->len = skb->len; 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci if (skb_shinfo(skb)->nr_frags) { 15848c2ecf20Sopenharmony_ci int i; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci if (skb_orphan_frags(skb, gfp_mask) || 15878c2ecf20Sopenharmony_ci skb_zerocopy_clone(n, skb, gfp_mask)) { 15888c2ecf20Sopenharmony_ci kfree_skb(n); 15898c2ecf20Sopenharmony_ci n = NULL; 15908c2ecf20Sopenharmony_ci goto out; 15918c2ecf20Sopenharmony_ci } 15928c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 15938c2ecf20Sopenharmony_ci skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i]; 15948c2ecf20Sopenharmony_ci skb_frag_ref(skb, i); 15958c2ecf20Sopenharmony_ci } 15968c2ecf20Sopenharmony_ci skb_shinfo(n)->nr_frags = i; 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci if (skb_has_frag_list(skb)) { 16008c2ecf20Sopenharmony_ci skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list; 16018c2ecf20Sopenharmony_ci skb_clone_fraglist(n); 16028c2ecf20Sopenharmony_ci } 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci skb_copy_header(n, skb); 16058c2ecf20Sopenharmony_ciout: 16068c2ecf20Sopenharmony_ci return n; 16078c2ecf20Sopenharmony_ci} 16088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__pskb_copy_fclone); 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci/** 16118c2ecf20Sopenharmony_ci * pskb_expand_head - reallocate header of &sk_buff 16128c2ecf20Sopenharmony_ci * @skb: buffer to reallocate 16138c2ecf20Sopenharmony_ci * @nhead: room to add at head 16148c2ecf20Sopenharmony_ci * @ntail: room to add at tail 16158c2ecf20Sopenharmony_ci * @gfp_mask: allocation priority 16168c2ecf20Sopenharmony_ci * 16178c2ecf20Sopenharmony_ci * Expands (or creates identical copy, if @nhead and @ntail are zero) 16188c2ecf20Sopenharmony_ci * header of @skb. &sk_buff itself is not changed. &sk_buff MUST have 16198c2ecf20Sopenharmony_ci * reference count of 1. Returns zero in the case of success or error, 16208c2ecf20Sopenharmony_ci * if expansion failed. In the last case, &sk_buff is not changed. 16218c2ecf20Sopenharmony_ci * 16228c2ecf20Sopenharmony_ci * All the pointers pointing into skb header may change and must be 16238c2ecf20Sopenharmony_ci * reloaded after call to this function. 16248c2ecf20Sopenharmony_ci */ 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ciint pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, 16278c2ecf20Sopenharmony_ci gfp_t gfp_mask) 16288c2ecf20Sopenharmony_ci{ 16298c2ecf20Sopenharmony_ci int i, osize = skb_end_offset(skb); 16308c2ecf20Sopenharmony_ci int size = osize + nhead + ntail; 16318c2ecf20Sopenharmony_ci long off; 16328c2ecf20Sopenharmony_ci u8 *data; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci BUG_ON(nhead < 0); 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci BUG_ON(skb_shared(skb)); 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci size = SKB_DATA_ALIGN(size); 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci if (skb_pfmemalloc(skb)) 16418c2ecf20Sopenharmony_ci gfp_mask |= __GFP_MEMALLOC; 16428c2ecf20Sopenharmony_ci data = kmalloc_reserve(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), 16438c2ecf20Sopenharmony_ci gfp_mask, NUMA_NO_NODE, NULL); 16448c2ecf20Sopenharmony_ci if (!data) 16458c2ecf20Sopenharmony_ci goto nodata; 16468c2ecf20Sopenharmony_ci size = SKB_WITH_OVERHEAD(ksize(data)); 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci /* Copy only real data... and, alas, header. This should be 16498c2ecf20Sopenharmony_ci * optimized for the cases when header is void. 16508c2ecf20Sopenharmony_ci */ 16518c2ecf20Sopenharmony_ci memcpy(data + nhead, skb->head, skb_tail_pointer(skb) - skb->head); 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci memcpy((struct skb_shared_info *)(data + size), 16548c2ecf20Sopenharmony_ci skb_shinfo(skb), 16558c2ecf20Sopenharmony_ci offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags])); 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci /* 16588c2ecf20Sopenharmony_ci * if shinfo is shared we must drop the old head gracefully, but if it 16598c2ecf20Sopenharmony_ci * is not we can just drop the old head and let the existing refcount 16608c2ecf20Sopenharmony_ci * be since all we did is relocate the values 16618c2ecf20Sopenharmony_ci */ 16628c2ecf20Sopenharmony_ci if (skb_cloned(skb)) { 16638c2ecf20Sopenharmony_ci if (skb_orphan_frags(skb, gfp_mask)) 16648c2ecf20Sopenharmony_ci goto nofrags; 16658c2ecf20Sopenharmony_ci if (skb_zcopy(skb)) 16668c2ecf20Sopenharmony_ci refcount_inc(&skb_uarg(skb)->refcnt); 16678c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) 16688c2ecf20Sopenharmony_ci skb_frag_ref(skb, i); 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci if (skb_has_frag_list(skb)) 16718c2ecf20Sopenharmony_ci skb_clone_fraglist(skb); 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci skb_release_data(skb); 16748c2ecf20Sopenharmony_ci } else { 16758c2ecf20Sopenharmony_ci skb_free_head(skb); 16768c2ecf20Sopenharmony_ci } 16778c2ecf20Sopenharmony_ci off = (data + nhead) - skb->head; 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci skb->head = data; 16808c2ecf20Sopenharmony_ci skb->head_frag = 0; 16818c2ecf20Sopenharmony_ci skb->data += off; 16828c2ecf20Sopenharmony_ci#ifdef NET_SKBUFF_DATA_USES_OFFSET 16838c2ecf20Sopenharmony_ci skb->end = size; 16848c2ecf20Sopenharmony_ci off = nhead; 16858c2ecf20Sopenharmony_ci#else 16868c2ecf20Sopenharmony_ci skb->end = skb->head + size; 16878c2ecf20Sopenharmony_ci#endif 16888c2ecf20Sopenharmony_ci skb->tail += off; 16898c2ecf20Sopenharmony_ci skb_headers_offset_update(skb, nhead); 16908c2ecf20Sopenharmony_ci skb->cloned = 0; 16918c2ecf20Sopenharmony_ci skb->hdr_len = 0; 16928c2ecf20Sopenharmony_ci skb->nohdr = 0; 16938c2ecf20Sopenharmony_ci atomic_set(&skb_shinfo(skb)->dataref, 1); 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci skb_metadata_clear(skb); 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci /* It is not generally safe to change skb->truesize. 16988c2ecf20Sopenharmony_ci * For the moment, we really care of rx path, or 16998c2ecf20Sopenharmony_ci * when skb is orphaned (not attached to a socket). 17008c2ecf20Sopenharmony_ci */ 17018c2ecf20Sopenharmony_ci if (!skb->sk || skb->destructor == sock_edemux) 17028c2ecf20Sopenharmony_ci skb->truesize += size - osize; 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci return 0; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_cinofrags: 17078c2ecf20Sopenharmony_ci kfree(data); 17088c2ecf20Sopenharmony_cinodata: 17098c2ecf20Sopenharmony_ci return -ENOMEM; 17108c2ecf20Sopenharmony_ci} 17118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pskb_expand_head); 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci/* Make private copy of skb with writable head and some headroom */ 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_cistruct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) 17168c2ecf20Sopenharmony_ci{ 17178c2ecf20Sopenharmony_ci struct sk_buff *skb2; 17188c2ecf20Sopenharmony_ci int delta = headroom - skb_headroom(skb); 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci if (delta <= 0) 17218c2ecf20Sopenharmony_ci skb2 = pskb_copy(skb, GFP_ATOMIC); 17228c2ecf20Sopenharmony_ci else { 17238c2ecf20Sopenharmony_ci skb2 = skb_clone(skb, GFP_ATOMIC); 17248c2ecf20Sopenharmony_ci if (skb2 && pskb_expand_head(skb2, SKB_DATA_ALIGN(delta), 0, 17258c2ecf20Sopenharmony_ci GFP_ATOMIC)) { 17268c2ecf20Sopenharmony_ci kfree_skb(skb2); 17278c2ecf20Sopenharmony_ci skb2 = NULL; 17288c2ecf20Sopenharmony_ci } 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci return skb2; 17318c2ecf20Sopenharmony_ci} 17328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_realloc_headroom); 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci/** 17358c2ecf20Sopenharmony_ci * skb_copy_expand - copy and expand sk_buff 17368c2ecf20Sopenharmony_ci * @skb: buffer to copy 17378c2ecf20Sopenharmony_ci * @newheadroom: new free bytes at head 17388c2ecf20Sopenharmony_ci * @newtailroom: new free bytes at tail 17398c2ecf20Sopenharmony_ci * @gfp_mask: allocation priority 17408c2ecf20Sopenharmony_ci * 17418c2ecf20Sopenharmony_ci * Make a copy of both an &sk_buff and its data and while doing so 17428c2ecf20Sopenharmony_ci * allocate additional space. 17438c2ecf20Sopenharmony_ci * 17448c2ecf20Sopenharmony_ci * This is used when the caller wishes to modify the data and needs a 17458c2ecf20Sopenharmony_ci * private copy of the data to alter as well as more space for new fields. 17468c2ecf20Sopenharmony_ci * Returns %NULL on failure or the pointer to the buffer 17478c2ecf20Sopenharmony_ci * on success. The returned buffer has a reference count of 1. 17488c2ecf20Sopenharmony_ci * 17498c2ecf20Sopenharmony_ci * You must pass %GFP_ATOMIC as the allocation priority if this function 17508c2ecf20Sopenharmony_ci * is called from an interrupt. 17518c2ecf20Sopenharmony_ci */ 17528c2ecf20Sopenharmony_cistruct sk_buff *skb_copy_expand(const struct sk_buff *skb, 17538c2ecf20Sopenharmony_ci int newheadroom, int newtailroom, 17548c2ecf20Sopenharmony_ci gfp_t gfp_mask) 17558c2ecf20Sopenharmony_ci{ 17568c2ecf20Sopenharmony_ci /* 17578c2ecf20Sopenharmony_ci * Allocate the copy buffer 17588c2ecf20Sopenharmony_ci */ 17598c2ecf20Sopenharmony_ci int head_copy_len, head_copy_off; 17608c2ecf20Sopenharmony_ci struct sk_buff *n; 17618c2ecf20Sopenharmony_ci int oldheadroom; 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST)) 17648c2ecf20Sopenharmony_ci return NULL; 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci oldheadroom = skb_headroom(skb); 17678c2ecf20Sopenharmony_ci n = __alloc_skb(newheadroom + skb->len + newtailroom, 17688c2ecf20Sopenharmony_ci gfp_mask, skb_alloc_rx_flag(skb), 17698c2ecf20Sopenharmony_ci NUMA_NO_NODE); 17708c2ecf20Sopenharmony_ci if (!n) 17718c2ecf20Sopenharmony_ci return NULL; 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci skb_reserve(n, newheadroom); 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci /* Set the tail pointer and length */ 17768c2ecf20Sopenharmony_ci skb_put(n, skb->len); 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci head_copy_len = oldheadroom; 17798c2ecf20Sopenharmony_ci head_copy_off = 0; 17808c2ecf20Sopenharmony_ci if (newheadroom <= head_copy_len) 17818c2ecf20Sopenharmony_ci head_copy_len = newheadroom; 17828c2ecf20Sopenharmony_ci else 17838c2ecf20Sopenharmony_ci head_copy_off = newheadroom - head_copy_len; 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci /* Copy the linear header and data. */ 17868c2ecf20Sopenharmony_ci BUG_ON(skb_copy_bits(skb, -head_copy_len, n->head + head_copy_off, 17878c2ecf20Sopenharmony_ci skb->len + head_copy_len)); 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci skb_copy_header(n, skb); 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci skb_headers_offset_update(n, newheadroom - oldheadroom); 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci return n; 17948c2ecf20Sopenharmony_ci} 17958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_copy_expand); 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci/** 17988c2ecf20Sopenharmony_ci * __skb_pad - zero pad the tail of an skb 17998c2ecf20Sopenharmony_ci * @skb: buffer to pad 18008c2ecf20Sopenharmony_ci * @pad: space to pad 18018c2ecf20Sopenharmony_ci * @free_on_error: free buffer on error 18028c2ecf20Sopenharmony_ci * 18038c2ecf20Sopenharmony_ci * Ensure that a buffer is followed by a padding area that is zero 18048c2ecf20Sopenharmony_ci * filled. Used by network drivers which may DMA or transfer data 18058c2ecf20Sopenharmony_ci * beyond the buffer end onto the wire. 18068c2ecf20Sopenharmony_ci * 18078c2ecf20Sopenharmony_ci * May return error in out of memory cases. The skb is freed on error 18088c2ecf20Sopenharmony_ci * if @free_on_error is true. 18098c2ecf20Sopenharmony_ci */ 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ciint __skb_pad(struct sk_buff *skb, int pad, bool free_on_error) 18128c2ecf20Sopenharmony_ci{ 18138c2ecf20Sopenharmony_ci int err; 18148c2ecf20Sopenharmony_ci int ntail; 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_ci /* If the skbuff is non linear tailroom is always zero.. */ 18178c2ecf20Sopenharmony_ci if (!skb_cloned(skb) && skb_tailroom(skb) >= pad) { 18188c2ecf20Sopenharmony_ci memset(skb->data+skb->len, 0, pad); 18198c2ecf20Sopenharmony_ci return 0; 18208c2ecf20Sopenharmony_ci } 18218c2ecf20Sopenharmony_ci 18228c2ecf20Sopenharmony_ci ntail = skb->data_len + pad - (skb->end - skb->tail); 18238c2ecf20Sopenharmony_ci if (likely(skb_cloned(skb) || ntail > 0)) { 18248c2ecf20Sopenharmony_ci err = pskb_expand_head(skb, 0, ntail, GFP_ATOMIC); 18258c2ecf20Sopenharmony_ci if (unlikely(err)) 18268c2ecf20Sopenharmony_ci goto free_skb; 18278c2ecf20Sopenharmony_ci } 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci /* FIXME: The use of this function with non-linear skb's really needs 18308c2ecf20Sopenharmony_ci * to be audited. 18318c2ecf20Sopenharmony_ci */ 18328c2ecf20Sopenharmony_ci err = skb_linearize(skb); 18338c2ecf20Sopenharmony_ci if (unlikely(err)) 18348c2ecf20Sopenharmony_ci goto free_skb; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci memset(skb->data + skb->len, 0, pad); 18378c2ecf20Sopenharmony_ci return 0; 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_cifree_skb: 18408c2ecf20Sopenharmony_ci if (free_on_error) 18418c2ecf20Sopenharmony_ci kfree_skb(skb); 18428c2ecf20Sopenharmony_ci return err; 18438c2ecf20Sopenharmony_ci} 18448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__skb_pad); 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci/** 18478c2ecf20Sopenharmony_ci * pskb_put - add data to the tail of a potentially fragmented buffer 18488c2ecf20Sopenharmony_ci * @skb: start of the buffer to use 18498c2ecf20Sopenharmony_ci * @tail: tail fragment of the buffer to use 18508c2ecf20Sopenharmony_ci * @len: amount of data to add 18518c2ecf20Sopenharmony_ci * 18528c2ecf20Sopenharmony_ci * This function extends the used data area of the potentially 18538c2ecf20Sopenharmony_ci * fragmented buffer. @tail must be the last fragment of @skb -- or 18548c2ecf20Sopenharmony_ci * @skb itself. If this would exceed the total buffer size the kernel 18558c2ecf20Sopenharmony_ci * will panic. A pointer to the first byte of the extra data is 18568c2ecf20Sopenharmony_ci * returned. 18578c2ecf20Sopenharmony_ci */ 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_civoid *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len) 18608c2ecf20Sopenharmony_ci{ 18618c2ecf20Sopenharmony_ci if (tail != skb) { 18628c2ecf20Sopenharmony_ci skb->data_len += len; 18638c2ecf20Sopenharmony_ci skb->len += len; 18648c2ecf20Sopenharmony_ci } 18658c2ecf20Sopenharmony_ci return skb_put(tail, len); 18668c2ecf20Sopenharmony_ci} 18678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pskb_put); 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci/** 18708c2ecf20Sopenharmony_ci * skb_put - add data to a buffer 18718c2ecf20Sopenharmony_ci * @skb: buffer to use 18728c2ecf20Sopenharmony_ci * @len: amount of data to add 18738c2ecf20Sopenharmony_ci * 18748c2ecf20Sopenharmony_ci * This function extends the used data area of the buffer. If this would 18758c2ecf20Sopenharmony_ci * exceed the total buffer size the kernel will panic. A pointer to the 18768c2ecf20Sopenharmony_ci * first byte of the extra data is returned. 18778c2ecf20Sopenharmony_ci */ 18788c2ecf20Sopenharmony_civoid *skb_put(struct sk_buff *skb, unsigned int len) 18798c2ecf20Sopenharmony_ci{ 18808c2ecf20Sopenharmony_ci void *tmp = skb_tail_pointer(skb); 18818c2ecf20Sopenharmony_ci SKB_LINEAR_ASSERT(skb); 18828c2ecf20Sopenharmony_ci skb->tail += len; 18838c2ecf20Sopenharmony_ci skb->len += len; 18848c2ecf20Sopenharmony_ci if (unlikely(skb->tail > skb->end)) 18858c2ecf20Sopenharmony_ci skb_over_panic(skb, len, __builtin_return_address(0)); 18868c2ecf20Sopenharmony_ci return tmp; 18878c2ecf20Sopenharmony_ci} 18888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_put); 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci/** 18918c2ecf20Sopenharmony_ci * skb_push - add data to the start of a buffer 18928c2ecf20Sopenharmony_ci * @skb: buffer to use 18938c2ecf20Sopenharmony_ci * @len: amount of data to add 18948c2ecf20Sopenharmony_ci * 18958c2ecf20Sopenharmony_ci * This function extends the used data area of the buffer at the buffer 18968c2ecf20Sopenharmony_ci * start. If this would exceed the total buffer headroom the kernel will 18978c2ecf20Sopenharmony_ci * panic. A pointer to the first byte of the extra data is returned. 18988c2ecf20Sopenharmony_ci */ 18998c2ecf20Sopenharmony_civoid *skb_push(struct sk_buff *skb, unsigned int len) 19008c2ecf20Sopenharmony_ci{ 19018c2ecf20Sopenharmony_ci skb->data -= len; 19028c2ecf20Sopenharmony_ci skb->len += len; 19038c2ecf20Sopenharmony_ci if (unlikely(skb->data < skb->head)) 19048c2ecf20Sopenharmony_ci skb_under_panic(skb, len, __builtin_return_address(0)); 19058c2ecf20Sopenharmony_ci return skb->data; 19068c2ecf20Sopenharmony_ci} 19078c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_push); 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci/** 19108c2ecf20Sopenharmony_ci * skb_pull - remove data from the start of a buffer 19118c2ecf20Sopenharmony_ci * @skb: buffer to use 19128c2ecf20Sopenharmony_ci * @len: amount of data to remove 19138c2ecf20Sopenharmony_ci * 19148c2ecf20Sopenharmony_ci * This function removes data from the start of a buffer, returning 19158c2ecf20Sopenharmony_ci * the memory to the headroom. A pointer to the next data in the buffer 19168c2ecf20Sopenharmony_ci * is returned. Once the data has been pulled future pushes will overwrite 19178c2ecf20Sopenharmony_ci * the old data. 19188c2ecf20Sopenharmony_ci */ 19198c2ecf20Sopenharmony_civoid *skb_pull(struct sk_buff *skb, unsigned int len) 19208c2ecf20Sopenharmony_ci{ 19218c2ecf20Sopenharmony_ci return skb_pull_inline(skb, len); 19228c2ecf20Sopenharmony_ci} 19238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_pull); 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci/** 19268c2ecf20Sopenharmony_ci * skb_trim - remove end from a buffer 19278c2ecf20Sopenharmony_ci * @skb: buffer to alter 19288c2ecf20Sopenharmony_ci * @len: new length 19298c2ecf20Sopenharmony_ci * 19308c2ecf20Sopenharmony_ci * Cut the length of a buffer down by removing data from the tail. If 19318c2ecf20Sopenharmony_ci * the buffer is already under the length specified it is not modified. 19328c2ecf20Sopenharmony_ci * The skb must be linear. 19338c2ecf20Sopenharmony_ci */ 19348c2ecf20Sopenharmony_civoid skb_trim(struct sk_buff *skb, unsigned int len) 19358c2ecf20Sopenharmony_ci{ 19368c2ecf20Sopenharmony_ci if (skb->len > len) 19378c2ecf20Sopenharmony_ci __skb_trim(skb, len); 19388c2ecf20Sopenharmony_ci} 19398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_trim); 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci/* Trims skb to length len. It can change skb pointers. 19428c2ecf20Sopenharmony_ci */ 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ciint ___pskb_trim(struct sk_buff *skb, unsigned int len) 19458c2ecf20Sopenharmony_ci{ 19468c2ecf20Sopenharmony_ci struct sk_buff **fragp; 19478c2ecf20Sopenharmony_ci struct sk_buff *frag; 19488c2ecf20Sopenharmony_ci int offset = skb_headlen(skb); 19498c2ecf20Sopenharmony_ci int nfrags = skb_shinfo(skb)->nr_frags; 19508c2ecf20Sopenharmony_ci int i; 19518c2ecf20Sopenharmony_ci int err; 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_ci if (skb_cloned(skb) && 19548c2ecf20Sopenharmony_ci unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) 19558c2ecf20Sopenharmony_ci return err; 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci i = 0; 19588c2ecf20Sopenharmony_ci if (offset >= len) 19598c2ecf20Sopenharmony_ci goto drop_pages; 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci for (; i < nfrags; i++) { 19628c2ecf20Sopenharmony_ci int end = offset + skb_frag_size(&skb_shinfo(skb)->frags[i]); 19638c2ecf20Sopenharmony_ci 19648c2ecf20Sopenharmony_ci if (end < len) { 19658c2ecf20Sopenharmony_ci offset = end; 19668c2ecf20Sopenharmony_ci continue; 19678c2ecf20Sopenharmony_ci } 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci skb_frag_size_set(&skb_shinfo(skb)->frags[i++], len - offset); 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_cidrop_pages: 19728c2ecf20Sopenharmony_ci skb_shinfo(skb)->nr_frags = i; 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci for (; i < nfrags; i++) 19758c2ecf20Sopenharmony_ci skb_frag_unref(skb, i); 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci if (skb_has_frag_list(skb)) 19788c2ecf20Sopenharmony_ci skb_drop_fraglist(skb); 19798c2ecf20Sopenharmony_ci goto done; 19808c2ecf20Sopenharmony_ci } 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); 19838c2ecf20Sopenharmony_ci fragp = &frag->next) { 19848c2ecf20Sopenharmony_ci int end = offset + frag->len; 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci if (skb_shared(frag)) { 19878c2ecf20Sopenharmony_ci struct sk_buff *nfrag; 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_ci nfrag = skb_clone(frag, GFP_ATOMIC); 19908c2ecf20Sopenharmony_ci if (unlikely(!nfrag)) 19918c2ecf20Sopenharmony_ci return -ENOMEM; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci nfrag->next = frag->next; 19948c2ecf20Sopenharmony_ci consume_skb(frag); 19958c2ecf20Sopenharmony_ci frag = nfrag; 19968c2ecf20Sopenharmony_ci *fragp = frag; 19978c2ecf20Sopenharmony_ci } 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci if (end < len) { 20008c2ecf20Sopenharmony_ci offset = end; 20018c2ecf20Sopenharmony_ci continue; 20028c2ecf20Sopenharmony_ci } 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci if (end > len && 20058c2ecf20Sopenharmony_ci unlikely((err = pskb_trim(frag, len - offset)))) 20068c2ecf20Sopenharmony_ci return err; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci if (frag->next) 20098c2ecf20Sopenharmony_ci skb_drop_list(&frag->next); 20108c2ecf20Sopenharmony_ci break; 20118c2ecf20Sopenharmony_ci } 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_cidone: 20148c2ecf20Sopenharmony_ci if (len > skb_headlen(skb)) { 20158c2ecf20Sopenharmony_ci skb->data_len -= skb->len - len; 20168c2ecf20Sopenharmony_ci skb->len = len; 20178c2ecf20Sopenharmony_ci } else { 20188c2ecf20Sopenharmony_ci skb->len = len; 20198c2ecf20Sopenharmony_ci skb->data_len = 0; 20208c2ecf20Sopenharmony_ci skb_set_tail_pointer(skb, len); 20218c2ecf20Sopenharmony_ci } 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci if (!skb->sk || skb->destructor == sock_edemux) 20248c2ecf20Sopenharmony_ci skb_condense(skb); 20258c2ecf20Sopenharmony_ci return 0; 20268c2ecf20Sopenharmony_ci} 20278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(___pskb_trim); 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_ci/* Note : use pskb_trim_rcsum() instead of calling this directly 20308c2ecf20Sopenharmony_ci */ 20318c2ecf20Sopenharmony_ciint pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len) 20328c2ecf20Sopenharmony_ci{ 20338c2ecf20Sopenharmony_ci if (skb->ip_summed == CHECKSUM_COMPLETE) { 20348c2ecf20Sopenharmony_ci int delta = skb->len - len; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci skb->csum = csum_block_sub(skb->csum, 20378c2ecf20Sopenharmony_ci skb_checksum(skb, len, delta, 0), 20388c2ecf20Sopenharmony_ci len); 20398c2ecf20Sopenharmony_ci } else if (skb->ip_summed == CHECKSUM_PARTIAL) { 20408c2ecf20Sopenharmony_ci int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len; 20418c2ecf20Sopenharmony_ci int offset = skb_checksum_start_offset(skb) + skb->csum_offset; 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci if (offset + sizeof(__sum16) > hdlen) 20448c2ecf20Sopenharmony_ci return -EINVAL; 20458c2ecf20Sopenharmony_ci } 20468c2ecf20Sopenharmony_ci return __pskb_trim(skb, len); 20478c2ecf20Sopenharmony_ci} 20488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pskb_trim_rcsum_slow); 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci/** 20518c2ecf20Sopenharmony_ci * __pskb_pull_tail - advance tail of skb header 20528c2ecf20Sopenharmony_ci * @skb: buffer to reallocate 20538c2ecf20Sopenharmony_ci * @delta: number of bytes to advance tail 20548c2ecf20Sopenharmony_ci * 20558c2ecf20Sopenharmony_ci * The function makes a sense only on a fragmented &sk_buff, 20568c2ecf20Sopenharmony_ci * it expands header moving its tail forward and copying necessary 20578c2ecf20Sopenharmony_ci * data from fragmented part. 20588c2ecf20Sopenharmony_ci * 20598c2ecf20Sopenharmony_ci * &sk_buff MUST have reference count of 1. 20608c2ecf20Sopenharmony_ci * 20618c2ecf20Sopenharmony_ci * Returns %NULL (and &sk_buff does not change) if pull failed 20628c2ecf20Sopenharmony_ci * or value of new tail of skb in the case of success. 20638c2ecf20Sopenharmony_ci * 20648c2ecf20Sopenharmony_ci * All the pointers pointing into skb header may change and must be 20658c2ecf20Sopenharmony_ci * reloaded after call to this function. 20668c2ecf20Sopenharmony_ci */ 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci/* Moves tail of skb head forward, copying data from fragmented part, 20698c2ecf20Sopenharmony_ci * when it is necessary. 20708c2ecf20Sopenharmony_ci * 1. It may fail due to malloc failure. 20718c2ecf20Sopenharmony_ci * 2. It may change skb pointers. 20728c2ecf20Sopenharmony_ci * 20738c2ecf20Sopenharmony_ci * It is pretty complicated. Luckily, it is called only in exceptional cases. 20748c2ecf20Sopenharmony_ci */ 20758c2ecf20Sopenharmony_civoid *__pskb_pull_tail(struct sk_buff *skb, int delta) 20768c2ecf20Sopenharmony_ci{ 20778c2ecf20Sopenharmony_ci /* If skb has not enough free space at tail, get new one 20788c2ecf20Sopenharmony_ci * plus 128 bytes for future expansions. If we have enough 20798c2ecf20Sopenharmony_ci * room at tail, reallocate without expansion only if skb is cloned. 20808c2ecf20Sopenharmony_ci */ 20818c2ecf20Sopenharmony_ci int i, k, eat = (skb->tail + delta) - skb->end; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci if (eat > 0 || skb_cloned(skb)) { 20848c2ecf20Sopenharmony_ci if (pskb_expand_head(skb, 0, eat > 0 ? eat + 128 : 0, 20858c2ecf20Sopenharmony_ci GFP_ATOMIC)) 20868c2ecf20Sopenharmony_ci return NULL; 20878c2ecf20Sopenharmony_ci } 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci BUG_ON(skb_copy_bits(skb, skb_headlen(skb), 20908c2ecf20Sopenharmony_ci skb_tail_pointer(skb), delta)); 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci /* Optimization: no fragments, no reasons to preestimate 20938c2ecf20Sopenharmony_ci * size of pulled pages. Superb. 20948c2ecf20Sopenharmony_ci */ 20958c2ecf20Sopenharmony_ci if (!skb_has_frag_list(skb)) 20968c2ecf20Sopenharmony_ci goto pull_pages; 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci /* Estimate size of pulled pages. */ 20998c2ecf20Sopenharmony_ci eat = delta; 21008c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 21018c2ecf20Sopenharmony_ci int size = skb_frag_size(&skb_shinfo(skb)->frags[i]); 21028c2ecf20Sopenharmony_ci 21038c2ecf20Sopenharmony_ci if (size >= eat) 21048c2ecf20Sopenharmony_ci goto pull_pages; 21058c2ecf20Sopenharmony_ci eat -= size; 21068c2ecf20Sopenharmony_ci } 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci /* If we need update frag list, we are in troubles. 21098c2ecf20Sopenharmony_ci * Certainly, it is possible to add an offset to skb data, 21108c2ecf20Sopenharmony_ci * but taking into account that pulling is expected to 21118c2ecf20Sopenharmony_ci * be very rare operation, it is worth to fight against 21128c2ecf20Sopenharmony_ci * further bloating skb head and crucify ourselves here instead. 21138c2ecf20Sopenharmony_ci * Pure masohism, indeed. 8)8) 21148c2ecf20Sopenharmony_ci */ 21158c2ecf20Sopenharmony_ci if (eat) { 21168c2ecf20Sopenharmony_ci struct sk_buff *list = skb_shinfo(skb)->frag_list; 21178c2ecf20Sopenharmony_ci struct sk_buff *clone = NULL; 21188c2ecf20Sopenharmony_ci struct sk_buff *insp = NULL; 21198c2ecf20Sopenharmony_ci 21208c2ecf20Sopenharmony_ci do { 21218c2ecf20Sopenharmony_ci if (list->len <= eat) { 21228c2ecf20Sopenharmony_ci /* Eaten as whole. */ 21238c2ecf20Sopenharmony_ci eat -= list->len; 21248c2ecf20Sopenharmony_ci list = list->next; 21258c2ecf20Sopenharmony_ci insp = list; 21268c2ecf20Sopenharmony_ci } else { 21278c2ecf20Sopenharmony_ci /* Eaten partially. */ 21288c2ecf20Sopenharmony_ci if (skb_is_gso(skb) && !list->head_frag && 21298c2ecf20Sopenharmony_ci skb_headlen(list)) 21308c2ecf20Sopenharmony_ci skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci if (skb_shared(list)) { 21338c2ecf20Sopenharmony_ci /* Sucks! We need to fork list. :-( */ 21348c2ecf20Sopenharmony_ci clone = skb_clone(list, GFP_ATOMIC); 21358c2ecf20Sopenharmony_ci if (!clone) 21368c2ecf20Sopenharmony_ci return NULL; 21378c2ecf20Sopenharmony_ci insp = list->next; 21388c2ecf20Sopenharmony_ci list = clone; 21398c2ecf20Sopenharmony_ci } else { 21408c2ecf20Sopenharmony_ci /* This may be pulled without 21418c2ecf20Sopenharmony_ci * problems. */ 21428c2ecf20Sopenharmony_ci insp = list; 21438c2ecf20Sopenharmony_ci } 21448c2ecf20Sopenharmony_ci if (!pskb_pull(list, eat)) { 21458c2ecf20Sopenharmony_ci kfree_skb(clone); 21468c2ecf20Sopenharmony_ci return NULL; 21478c2ecf20Sopenharmony_ci } 21488c2ecf20Sopenharmony_ci break; 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci } while (eat); 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_ci /* Free pulled out fragments. */ 21538c2ecf20Sopenharmony_ci while ((list = skb_shinfo(skb)->frag_list) != insp) { 21548c2ecf20Sopenharmony_ci skb_shinfo(skb)->frag_list = list->next; 21558c2ecf20Sopenharmony_ci consume_skb(list); 21568c2ecf20Sopenharmony_ci } 21578c2ecf20Sopenharmony_ci /* And insert new clone at head. */ 21588c2ecf20Sopenharmony_ci if (clone) { 21598c2ecf20Sopenharmony_ci clone->next = list; 21608c2ecf20Sopenharmony_ci skb_shinfo(skb)->frag_list = clone; 21618c2ecf20Sopenharmony_ci } 21628c2ecf20Sopenharmony_ci } 21638c2ecf20Sopenharmony_ci /* Success! Now we may commit changes to skb data. */ 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_cipull_pages: 21668c2ecf20Sopenharmony_ci eat = delta; 21678c2ecf20Sopenharmony_ci k = 0; 21688c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 21698c2ecf20Sopenharmony_ci int size = skb_frag_size(&skb_shinfo(skb)->frags[i]); 21708c2ecf20Sopenharmony_ci 21718c2ecf20Sopenharmony_ci if (size <= eat) { 21728c2ecf20Sopenharmony_ci skb_frag_unref(skb, i); 21738c2ecf20Sopenharmony_ci eat -= size; 21748c2ecf20Sopenharmony_ci } else { 21758c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[k]; 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci *frag = skb_shinfo(skb)->frags[i]; 21788c2ecf20Sopenharmony_ci if (eat) { 21798c2ecf20Sopenharmony_ci skb_frag_off_add(frag, eat); 21808c2ecf20Sopenharmony_ci skb_frag_size_sub(frag, eat); 21818c2ecf20Sopenharmony_ci if (!i) 21828c2ecf20Sopenharmony_ci goto end; 21838c2ecf20Sopenharmony_ci eat = 0; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci k++; 21868c2ecf20Sopenharmony_ci } 21878c2ecf20Sopenharmony_ci } 21888c2ecf20Sopenharmony_ci skb_shinfo(skb)->nr_frags = k; 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ciend: 21918c2ecf20Sopenharmony_ci skb->tail += delta; 21928c2ecf20Sopenharmony_ci skb->data_len -= delta; 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ci if (!skb->data_len) 21958c2ecf20Sopenharmony_ci skb_zcopy_clear(skb, false); 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci return skb_tail_pointer(skb); 21988c2ecf20Sopenharmony_ci} 21998c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__pskb_pull_tail); 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci/** 22028c2ecf20Sopenharmony_ci * skb_copy_bits - copy bits from skb to kernel buffer 22038c2ecf20Sopenharmony_ci * @skb: source skb 22048c2ecf20Sopenharmony_ci * @offset: offset in source 22058c2ecf20Sopenharmony_ci * @to: destination buffer 22068c2ecf20Sopenharmony_ci * @len: number of bytes to copy 22078c2ecf20Sopenharmony_ci * 22088c2ecf20Sopenharmony_ci * Copy the specified number of bytes from the source skb to the 22098c2ecf20Sopenharmony_ci * destination buffer. 22108c2ecf20Sopenharmony_ci * 22118c2ecf20Sopenharmony_ci * CAUTION ! : 22128c2ecf20Sopenharmony_ci * If its prototype is ever changed, 22138c2ecf20Sopenharmony_ci * check arch/{*}/net/{*}.S files, 22148c2ecf20Sopenharmony_ci * since it is called from BPF assembly code. 22158c2ecf20Sopenharmony_ci */ 22168c2ecf20Sopenharmony_ciint skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) 22178c2ecf20Sopenharmony_ci{ 22188c2ecf20Sopenharmony_ci int start = skb_headlen(skb); 22198c2ecf20Sopenharmony_ci struct sk_buff *frag_iter; 22208c2ecf20Sopenharmony_ci int i, copy; 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci if (offset > (int)skb->len - len) 22238c2ecf20Sopenharmony_ci goto fault; 22248c2ecf20Sopenharmony_ci 22258c2ecf20Sopenharmony_ci /* Copy header. */ 22268c2ecf20Sopenharmony_ci if ((copy = start - offset) > 0) { 22278c2ecf20Sopenharmony_ci if (copy > len) 22288c2ecf20Sopenharmony_ci copy = len; 22298c2ecf20Sopenharmony_ci skb_copy_from_linear_data_offset(skb, offset, to, copy); 22308c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 22318c2ecf20Sopenharmony_ci return 0; 22328c2ecf20Sopenharmony_ci offset += copy; 22338c2ecf20Sopenharmony_ci to += copy; 22348c2ecf20Sopenharmony_ci } 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 22378c2ecf20Sopenharmony_ci int end; 22388c2ecf20Sopenharmony_ci skb_frag_t *f = &skb_shinfo(skb)->frags[i]; 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci end = start + skb_frag_size(f); 22438c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 22448c2ecf20Sopenharmony_ci u32 p_off, p_len, copied; 22458c2ecf20Sopenharmony_ci struct page *p; 22468c2ecf20Sopenharmony_ci u8 *vaddr; 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci if (copy > len) 22498c2ecf20Sopenharmony_ci copy = len; 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_ci skb_frag_foreach_page(f, 22528c2ecf20Sopenharmony_ci skb_frag_off(f) + offset - start, 22538c2ecf20Sopenharmony_ci copy, p, p_off, p_len, copied) { 22548c2ecf20Sopenharmony_ci vaddr = kmap_atomic(p); 22558c2ecf20Sopenharmony_ci memcpy(to + copied, vaddr + p_off, p_len); 22568c2ecf20Sopenharmony_ci kunmap_atomic(vaddr); 22578c2ecf20Sopenharmony_ci } 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 22608c2ecf20Sopenharmony_ci return 0; 22618c2ecf20Sopenharmony_ci offset += copy; 22628c2ecf20Sopenharmony_ci to += copy; 22638c2ecf20Sopenharmony_ci } 22648c2ecf20Sopenharmony_ci start = end; 22658c2ecf20Sopenharmony_ci } 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci skb_walk_frags(skb, frag_iter) { 22688c2ecf20Sopenharmony_ci int end; 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 22718c2ecf20Sopenharmony_ci 22728c2ecf20Sopenharmony_ci end = start + frag_iter->len; 22738c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 22748c2ecf20Sopenharmony_ci if (copy > len) 22758c2ecf20Sopenharmony_ci copy = len; 22768c2ecf20Sopenharmony_ci if (skb_copy_bits(frag_iter, offset - start, to, copy)) 22778c2ecf20Sopenharmony_ci goto fault; 22788c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 22798c2ecf20Sopenharmony_ci return 0; 22808c2ecf20Sopenharmony_ci offset += copy; 22818c2ecf20Sopenharmony_ci to += copy; 22828c2ecf20Sopenharmony_ci } 22838c2ecf20Sopenharmony_ci start = end; 22848c2ecf20Sopenharmony_ci } 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_ci if (!len) 22878c2ecf20Sopenharmony_ci return 0; 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_cifault: 22908c2ecf20Sopenharmony_ci return -EFAULT; 22918c2ecf20Sopenharmony_ci} 22928c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_copy_bits); 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci/* 22958c2ecf20Sopenharmony_ci * Callback from splice_to_pipe(), if we need to release some pages 22968c2ecf20Sopenharmony_ci * at the end of the spd in case we error'ed out in filling the pipe. 22978c2ecf20Sopenharmony_ci */ 22988c2ecf20Sopenharmony_cistatic void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) 22998c2ecf20Sopenharmony_ci{ 23008c2ecf20Sopenharmony_ci put_page(spd->pages[i]); 23018c2ecf20Sopenharmony_ci} 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_cistatic struct page *linear_to_page(struct page *page, unsigned int *len, 23048c2ecf20Sopenharmony_ci unsigned int *offset, 23058c2ecf20Sopenharmony_ci struct sock *sk) 23068c2ecf20Sopenharmony_ci{ 23078c2ecf20Sopenharmony_ci struct page_frag *pfrag = sk_page_frag(sk); 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_ci if (!sk_page_frag_refill(sk, pfrag)) 23108c2ecf20Sopenharmony_ci return NULL; 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_ci *len = min_t(unsigned int, *len, pfrag->size - pfrag->offset); 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci memcpy(page_address(pfrag->page) + pfrag->offset, 23158c2ecf20Sopenharmony_ci page_address(page) + *offset, *len); 23168c2ecf20Sopenharmony_ci *offset = pfrag->offset; 23178c2ecf20Sopenharmony_ci pfrag->offset += *len; 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci return pfrag->page; 23208c2ecf20Sopenharmony_ci} 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_cistatic bool spd_can_coalesce(const struct splice_pipe_desc *spd, 23238c2ecf20Sopenharmony_ci struct page *page, 23248c2ecf20Sopenharmony_ci unsigned int offset) 23258c2ecf20Sopenharmony_ci{ 23268c2ecf20Sopenharmony_ci return spd->nr_pages && 23278c2ecf20Sopenharmony_ci spd->pages[spd->nr_pages - 1] == page && 23288c2ecf20Sopenharmony_ci (spd->partial[spd->nr_pages - 1].offset + 23298c2ecf20Sopenharmony_ci spd->partial[spd->nr_pages - 1].len == offset); 23308c2ecf20Sopenharmony_ci} 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci/* 23338c2ecf20Sopenharmony_ci * Fill page/offset/length into spd, if it can hold more pages. 23348c2ecf20Sopenharmony_ci */ 23358c2ecf20Sopenharmony_cistatic bool spd_fill_page(struct splice_pipe_desc *spd, 23368c2ecf20Sopenharmony_ci struct pipe_inode_info *pipe, struct page *page, 23378c2ecf20Sopenharmony_ci unsigned int *len, unsigned int offset, 23388c2ecf20Sopenharmony_ci bool linear, 23398c2ecf20Sopenharmony_ci struct sock *sk) 23408c2ecf20Sopenharmony_ci{ 23418c2ecf20Sopenharmony_ci if (unlikely(spd->nr_pages == MAX_SKB_FRAGS)) 23428c2ecf20Sopenharmony_ci return true; 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_ci if (linear) { 23458c2ecf20Sopenharmony_ci page = linear_to_page(page, len, &offset, sk); 23468c2ecf20Sopenharmony_ci if (!page) 23478c2ecf20Sopenharmony_ci return true; 23488c2ecf20Sopenharmony_ci } 23498c2ecf20Sopenharmony_ci if (spd_can_coalesce(spd, page, offset)) { 23508c2ecf20Sopenharmony_ci spd->partial[spd->nr_pages - 1].len += *len; 23518c2ecf20Sopenharmony_ci return false; 23528c2ecf20Sopenharmony_ci } 23538c2ecf20Sopenharmony_ci get_page(page); 23548c2ecf20Sopenharmony_ci spd->pages[spd->nr_pages] = page; 23558c2ecf20Sopenharmony_ci spd->partial[spd->nr_pages].len = *len; 23568c2ecf20Sopenharmony_ci spd->partial[spd->nr_pages].offset = offset; 23578c2ecf20Sopenharmony_ci spd->nr_pages++; 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_ci return false; 23608c2ecf20Sopenharmony_ci} 23618c2ecf20Sopenharmony_ci 23628c2ecf20Sopenharmony_cistatic bool __splice_segment(struct page *page, unsigned int poff, 23638c2ecf20Sopenharmony_ci unsigned int plen, unsigned int *off, 23648c2ecf20Sopenharmony_ci unsigned int *len, 23658c2ecf20Sopenharmony_ci struct splice_pipe_desc *spd, bool linear, 23668c2ecf20Sopenharmony_ci struct sock *sk, 23678c2ecf20Sopenharmony_ci struct pipe_inode_info *pipe) 23688c2ecf20Sopenharmony_ci{ 23698c2ecf20Sopenharmony_ci if (!*len) 23708c2ecf20Sopenharmony_ci return true; 23718c2ecf20Sopenharmony_ci 23728c2ecf20Sopenharmony_ci /* skip this segment if already processed */ 23738c2ecf20Sopenharmony_ci if (*off >= plen) { 23748c2ecf20Sopenharmony_ci *off -= plen; 23758c2ecf20Sopenharmony_ci return false; 23768c2ecf20Sopenharmony_ci } 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci /* ignore any bits we already processed */ 23798c2ecf20Sopenharmony_ci poff += *off; 23808c2ecf20Sopenharmony_ci plen -= *off; 23818c2ecf20Sopenharmony_ci *off = 0; 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci do { 23848c2ecf20Sopenharmony_ci unsigned int flen = min(*len, plen); 23858c2ecf20Sopenharmony_ci 23868c2ecf20Sopenharmony_ci if (spd_fill_page(spd, pipe, page, &flen, poff, 23878c2ecf20Sopenharmony_ci linear, sk)) 23888c2ecf20Sopenharmony_ci return true; 23898c2ecf20Sopenharmony_ci poff += flen; 23908c2ecf20Sopenharmony_ci plen -= flen; 23918c2ecf20Sopenharmony_ci *len -= flen; 23928c2ecf20Sopenharmony_ci } while (*len && plen); 23938c2ecf20Sopenharmony_ci 23948c2ecf20Sopenharmony_ci return false; 23958c2ecf20Sopenharmony_ci} 23968c2ecf20Sopenharmony_ci 23978c2ecf20Sopenharmony_ci/* 23988c2ecf20Sopenharmony_ci * Map linear and fragment data from the skb to spd. It reports true if the 23998c2ecf20Sopenharmony_ci * pipe is full or if we already spliced the requested length. 24008c2ecf20Sopenharmony_ci */ 24018c2ecf20Sopenharmony_cistatic bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, 24028c2ecf20Sopenharmony_ci unsigned int *offset, unsigned int *len, 24038c2ecf20Sopenharmony_ci struct splice_pipe_desc *spd, struct sock *sk) 24048c2ecf20Sopenharmony_ci{ 24058c2ecf20Sopenharmony_ci int seg; 24068c2ecf20Sopenharmony_ci struct sk_buff *iter; 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci /* map the linear part : 24098c2ecf20Sopenharmony_ci * If skb->head_frag is set, this 'linear' part is backed by a 24108c2ecf20Sopenharmony_ci * fragment, and if the head is not shared with any clones then 24118c2ecf20Sopenharmony_ci * we can avoid a copy since we own the head portion of this page. 24128c2ecf20Sopenharmony_ci */ 24138c2ecf20Sopenharmony_ci if (__splice_segment(virt_to_page(skb->data), 24148c2ecf20Sopenharmony_ci (unsigned long) skb->data & (PAGE_SIZE - 1), 24158c2ecf20Sopenharmony_ci skb_headlen(skb), 24168c2ecf20Sopenharmony_ci offset, len, spd, 24178c2ecf20Sopenharmony_ci skb_head_is_locked(skb), 24188c2ecf20Sopenharmony_ci sk, pipe)) 24198c2ecf20Sopenharmony_ci return true; 24208c2ecf20Sopenharmony_ci 24218c2ecf20Sopenharmony_ci /* 24228c2ecf20Sopenharmony_ci * then map the fragments 24238c2ecf20Sopenharmony_ci */ 24248c2ecf20Sopenharmony_ci for (seg = 0; seg < skb_shinfo(skb)->nr_frags; seg++) { 24258c2ecf20Sopenharmony_ci const skb_frag_t *f = &skb_shinfo(skb)->frags[seg]; 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci if (__splice_segment(skb_frag_page(f), 24288c2ecf20Sopenharmony_ci skb_frag_off(f), skb_frag_size(f), 24298c2ecf20Sopenharmony_ci offset, len, spd, false, sk, pipe)) 24308c2ecf20Sopenharmony_ci return true; 24318c2ecf20Sopenharmony_ci } 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci skb_walk_frags(skb, iter) { 24348c2ecf20Sopenharmony_ci if (*offset >= iter->len) { 24358c2ecf20Sopenharmony_ci *offset -= iter->len; 24368c2ecf20Sopenharmony_ci continue; 24378c2ecf20Sopenharmony_ci } 24388c2ecf20Sopenharmony_ci /* __skb_splice_bits() only fails if the output has no room 24398c2ecf20Sopenharmony_ci * left, so no point in going over the frag_list for the error 24408c2ecf20Sopenharmony_ci * case. 24418c2ecf20Sopenharmony_ci */ 24428c2ecf20Sopenharmony_ci if (__skb_splice_bits(iter, pipe, offset, len, spd, sk)) 24438c2ecf20Sopenharmony_ci return true; 24448c2ecf20Sopenharmony_ci } 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci return false; 24478c2ecf20Sopenharmony_ci} 24488c2ecf20Sopenharmony_ci 24498c2ecf20Sopenharmony_ci/* 24508c2ecf20Sopenharmony_ci * Map data from the skb to a pipe. Should handle both the linear part, 24518c2ecf20Sopenharmony_ci * the fragments, and the frag list. 24528c2ecf20Sopenharmony_ci */ 24538c2ecf20Sopenharmony_ciint skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset, 24548c2ecf20Sopenharmony_ci struct pipe_inode_info *pipe, unsigned int tlen, 24558c2ecf20Sopenharmony_ci unsigned int flags) 24568c2ecf20Sopenharmony_ci{ 24578c2ecf20Sopenharmony_ci struct partial_page partial[MAX_SKB_FRAGS]; 24588c2ecf20Sopenharmony_ci struct page *pages[MAX_SKB_FRAGS]; 24598c2ecf20Sopenharmony_ci struct splice_pipe_desc spd = { 24608c2ecf20Sopenharmony_ci .pages = pages, 24618c2ecf20Sopenharmony_ci .partial = partial, 24628c2ecf20Sopenharmony_ci .nr_pages_max = MAX_SKB_FRAGS, 24638c2ecf20Sopenharmony_ci .ops = &nosteal_pipe_buf_ops, 24648c2ecf20Sopenharmony_ci .spd_release = sock_spd_release, 24658c2ecf20Sopenharmony_ci }; 24668c2ecf20Sopenharmony_ci int ret = 0; 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ci __skb_splice_bits(skb, pipe, &offset, &tlen, &spd, sk); 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci if (spd.nr_pages) 24718c2ecf20Sopenharmony_ci ret = splice_to_pipe(pipe, &spd); 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_ci return ret; 24748c2ecf20Sopenharmony_ci} 24758c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_splice_bits); 24768c2ecf20Sopenharmony_ci 24778c2ecf20Sopenharmony_ci/* Send skb data on a socket. Socket must be locked. */ 24788c2ecf20Sopenharmony_ciint skb_send_sock_locked(struct sock *sk, struct sk_buff *skb, int offset, 24798c2ecf20Sopenharmony_ci int len) 24808c2ecf20Sopenharmony_ci{ 24818c2ecf20Sopenharmony_ci unsigned int orig_len = len; 24828c2ecf20Sopenharmony_ci struct sk_buff *head = skb; 24838c2ecf20Sopenharmony_ci unsigned short fragidx; 24848c2ecf20Sopenharmony_ci int slen, ret; 24858c2ecf20Sopenharmony_ci 24868c2ecf20Sopenharmony_cido_frag_list: 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci /* Deal with head data */ 24898c2ecf20Sopenharmony_ci while (offset < skb_headlen(skb) && len) { 24908c2ecf20Sopenharmony_ci struct kvec kv; 24918c2ecf20Sopenharmony_ci struct msghdr msg; 24928c2ecf20Sopenharmony_ci 24938c2ecf20Sopenharmony_ci slen = min_t(int, len, skb_headlen(skb) - offset); 24948c2ecf20Sopenharmony_ci kv.iov_base = skb->data + offset; 24958c2ecf20Sopenharmony_ci kv.iov_len = slen; 24968c2ecf20Sopenharmony_ci memset(&msg, 0, sizeof(msg)); 24978c2ecf20Sopenharmony_ci msg.msg_flags = MSG_DONTWAIT; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci ret = kernel_sendmsg_locked(sk, &msg, &kv, 1, slen); 25008c2ecf20Sopenharmony_ci if (ret <= 0) 25018c2ecf20Sopenharmony_ci goto error; 25028c2ecf20Sopenharmony_ci 25038c2ecf20Sopenharmony_ci offset += ret; 25048c2ecf20Sopenharmony_ci len -= ret; 25058c2ecf20Sopenharmony_ci } 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci /* All the data was skb head? */ 25088c2ecf20Sopenharmony_ci if (!len) 25098c2ecf20Sopenharmony_ci goto out; 25108c2ecf20Sopenharmony_ci 25118c2ecf20Sopenharmony_ci /* Make offset relative to start of frags */ 25128c2ecf20Sopenharmony_ci offset -= skb_headlen(skb); 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci /* Find where we are in frag list */ 25158c2ecf20Sopenharmony_ci for (fragidx = 0; fragidx < skb_shinfo(skb)->nr_frags; fragidx++) { 25168c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[fragidx]; 25178c2ecf20Sopenharmony_ci 25188c2ecf20Sopenharmony_ci if (offset < skb_frag_size(frag)) 25198c2ecf20Sopenharmony_ci break; 25208c2ecf20Sopenharmony_ci 25218c2ecf20Sopenharmony_ci offset -= skb_frag_size(frag); 25228c2ecf20Sopenharmony_ci } 25238c2ecf20Sopenharmony_ci 25248c2ecf20Sopenharmony_ci for (; len && fragidx < skb_shinfo(skb)->nr_frags; fragidx++) { 25258c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[fragidx]; 25268c2ecf20Sopenharmony_ci 25278c2ecf20Sopenharmony_ci slen = min_t(size_t, len, skb_frag_size(frag) - offset); 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci while (slen) { 25308c2ecf20Sopenharmony_ci ret = kernel_sendpage_locked(sk, skb_frag_page(frag), 25318c2ecf20Sopenharmony_ci skb_frag_off(frag) + offset, 25328c2ecf20Sopenharmony_ci slen, MSG_DONTWAIT); 25338c2ecf20Sopenharmony_ci if (ret <= 0) 25348c2ecf20Sopenharmony_ci goto error; 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci len -= ret; 25378c2ecf20Sopenharmony_ci offset += ret; 25388c2ecf20Sopenharmony_ci slen -= ret; 25398c2ecf20Sopenharmony_ci } 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci offset = 0; 25428c2ecf20Sopenharmony_ci } 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci if (len) { 25458c2ecf20Sopenharmony_ci /* Process any frag lists */ 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci if (skb == head) { 25488c2ecf20Sopenharmony_ci if (skb_has_frag_list(skb)) { 25498c2ecf20Sopenharmony_ci skb = skb_shinfo(skb)->frag_list; 25508c2ecf20Sopenharmony_ci goto do_frag_list; 25518c2ecf20Sopenharmony_ci } 25528c2ecf20Sopenharmony_ci } else if (skb->next) { 25538c2ecf20Sopenharmony_ci skb = skb->next; 25548c2ecf20Sopenharmony_ci goto do_frag_list; 25558c2ecf20Sopenharmony_ci } 25568c2ecf20Sopenharmony_ci } 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ciout: 25598c2ecf20Sopenharmony_ci return orig_len - len; 25608c2ecf20Sopenharmony_ci 25618c2ecf20Sopenharmony_cierror: 25628c2ecf20Sopenharmony_ci return orig_len == len ? ret : orig_len - len; 25638c2ecf20Sopenharmony_ci} 25648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_send_sock_locked); 25658c2ecf20Sopenharmony_ci 25668c2ecf20Sopenharmony_ci/** 25678c2ecf20Sopenharmony_ci * skb_store_bits - store bits from kernel buffer to skb 25688c2ecf20Sopenharmony_ci * @skb: destination buffer 25698c2ecf20Sopenharmony_ci * @offset: offset in destination 25708c2ecf20Sopenharmony_ci * @from: source buffer 25718c2ecf20Sopenharmony_ci * @len: number of bytes to copy 25728c2ecf20Sopenharmony_ci * 25738c2ecf20Sopenharmony_ci * Copy the specified number of bytes from the source buffer to the 25748c2ecf20Sopenharmony_ci * destination skb. This function handles all the messy bits of 25758c2ecf20Sopenharmony_ci * traversing fragment lists and such. 25768c2ecf20Sopenharmony_ci */ 25778c2ecf20Sopenharmony_ci 25788c2ecf20Sopenharmony_ciint skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) 25798c2ecf20Sopenharmony_ci{ 25808c2ecf20Sopenharmony_ci int start = skb_headlen(skb); 25818c2ecf20Sopenharmony_ci struct sk_buff *frag_iter; 25828c2ecf20Sopenharmony_ci int i, copy; 25838c2ecf20Sopenharmony_ci 25848c2ecf20Sopenharmony_ci if (offset > (int)skb->len - len) 25858c2ecf20Sopenharmony_ci goto fault; 25868c2ecf20Sopenharmony_ci 25878c2ecf20Sopenharmony_ci if ((copy = start - offset) > 0) { 25888c2ecf20Sopenharmony_ci if (copy > len) 25898c2ecf20Sopenharmony_ci copy = len; 25908c2ecf20Sopenharmony_ci skb_copy_to_linear_data_offset(skb, offset, from, copy); 25918c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 25928c2ecf20Sopenharmony_ci return 0; 25938c2ecf20Sopenharmony_ci offset += copy; 25948c2ecf20Sopenharmony_ci from += copy; 25958c2ecf20Sopenharmony_ci } 25968c2ecf20Sopenharmony_ci 25978c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 25988c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 25998c2ecf20Sopenharmony_ci int end; 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 26028c2ecf20Sopenharmony_ci 26038c2ecf20Sopenharmony_ci end = start + skb_frag_size(frag); 26048c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 26058c2ecf20Sopenharmony_ci u32 p_off, p_len, copied; 26068c2ecf20Sopenharmony_ci struct page *p; 26078c2ecf20Sopenharmony_ci u8 *vaddr; 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci if (copy > len) 26108c2ecf20Sopenharmony_ci copy = len; 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci skb_frag_foreach_page(frag, 26138c2ecf20Sopenharmony_ci skb_frag_off(frag) + offset - start, 26148c2ecf20Sopenharmony_ci copy, p, p_off, p_len, copied) { 26158c2ecf20Sopenharmony_ci vaddr = kmap_atomic(p); 26168c2ecf20Sopenharmony_ci memcpy(vaddr + p_off, from + copied, p_len); 26178c2ecf20Sopenharmony_ci kunmap_atomic(vaddr); 26188c2ecf20Sopenharmony_ci } 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 26218c2ecf20Sopenharmony_ci return 0; 26228c2ecf20Sopenharmony_ci offset += copy; 26238c2ecf20Sopenharmony_ci from += copy; 26248c2ecf20Sopenharmony_ci } 26258c2ecf20Sopenharmony_ci start = end; 26268c2ecf20Sopenharmony_ci } 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci skb_walk_frags(skb, frag_iter) { 26298c2ecf20Sopenharmony_ci int end; 26308c2ecf20Sopenharmony_ci 26318c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci end = start + frag_iter->len; 26348c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 26358c2ecf20Sopenharmony_ci if (copy > len) 26368c2ecf20Sopenharmony_ci copy = len; 26378c2ecf20Sopenharmony_ci if (skb_store_bits(frag_iter, offset - start, 26388c2ecf20Sopenharmony_ci from, copy)) 26398c2ecf20Sopenharmony_ci goto fault; 26408c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 26418c2ecf20Sopenharmony_ci return 0; 26428c2ecf20Sopenharmony_ci offset += copy; 26438c2ecf20Sopenharmony_ci from += copy; 26448c2ecf20Sopenharmony_ci } 26458c2ecf20Sopenharmony_ci start = end; 26468c2ecf20Sopenharmony_ci } 26478c2ecf20Sopenharmony_ci if (!len) 26488c2ecf20Sopenharmony_ci return 0; 26498c2ecf20Sopenharmony_ci 26508c2ecf20Sopenharmony_cifault: 26518c2ecf20Sopenharmony_ci return -EFAULT; 26528c2ecf20Sopenharmony_ci} 26538c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_store_bits); 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_ci/* Checksum skb data. */ 26568c2ecf20Sopenharmony_ci__wsum __skb_checksum(const struct sk_buff *skb, int offset, int len, 26578c2ecf20Sopenharmony_ci __wsum csum, const struct skb_checksum_ops *ops) 26588c2ecf20Sopenharmony_ci{ 26598c2ecf20Sopenharmony_ci int start = skb_headlen(skb); 26608c2ecf20Sopenharmony_ci int i, copy = start - offset; 26618c2ecf20Sopenharmony_ci struct sk_buff *frag_iter; 26628c2ecf20Sopenharmony_ci int pos = 0; 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_ci /* Checksum header. */ 26658c2ecf20Sopenharmony_ci if (copy > 0) { 26668c2ecf20Sopenharmony_ci if (copy > len) 26678c2ecf20Sopenharmony_ci copy = len; 26688c2ecf20Sopenharmony_ci csum = INDIRECT_CALL_1(ops->update, csum_partial_ext, 26698c2ecf20Sopenharmony_ci skb->data + offset, copy, csum); 26708c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 26718c2ecf20Sopenharmony_ci return csum; 26728c2ecf20Sopenharmony_ci offset += copy; 26738c2ecf20Sopenharmony_ci pos = copy; 26748c2ecf20Sopenharmony_ci } 26758c2ecf20Sopenharmony_ci 26768c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 26778c2ecf20Sopenharmony_ci int end; 26788c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 26818c2ecf20Sopenharmony_ci 26828c2ecf20Sopenharmony_ci end = start + skb_frag_size(frag); 26838c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 26848c2ecf20Sopenharmony_ci u32 p_off, p_len, copied; 26858c2ecf20Sopenharmony_ci struct page *p; 26868c2ecf20Sopenharmony_ci __wsum csum2; 26878c2ecf20Sopenharmony_ci u8 *vaddr; 26888c2ecf20Sopenharmony_ci 26898c2ecf20Sopenharmony_ci if (copy > len) 26908c2ecf20Sopenharmony_ci copy = len; 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci skb_frag_foreach_page(frag, 26938c2ecf20Sopenharmony_ci skb_frag_off(frag) + offset - start, 26948c2ecf20Sopenharmony_ci copy, p, p_off, p_len, copied) { 26958c2ecf20Sopenharmony_ci vaddr = kmap_atomic(p); 26968c2ecf20Sopenharmony_ci csum2 = INDIRECT_CALL_1(ops->update, 26978c2ecf20Sopenharmony_ci csum_partial_ext, 26988c2ecf20Sopenharmony_ci vaddr + p_off, p_len, 0); 26998c2ecf20Sopenharmony_ci kunmap_atomic(vaddr); 27008c2ecf20Sopenharmony_ci csum = INDIRECT_CALL_1(ops->combine, 27018c2ecf20Sopenharmony_ci csum_block_add_ext, csum, 27028c2ecf20Sopenharmony_ci csum2, pos, p_len); 27038c2ecf20Sopenharmony_ci pos += p_len; 27048c2ecf20Sopenharmony_ci } 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_ci if (!(len -= copy)) 27078c2ecf20Sopenharmony_ci return csum; 27088c2ecf20Sopenharmony_ci offset += copy; 27098c2ecf20Sopenharmony_ci } 27108c2ecf20Sopenharmony_ci start = end; 27118c2ecf20Sopenharmony_ci } 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_ci skb_walk_frags(skb, frag_iter) { 27148c2ecf20Sopenharmony_ci int end; 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci end = start + frag_iter->len; 27198c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 27208c2ecf20Sopenharmony_ci __wsum csum2; 27218c2ecf20Sopenharmony_ci if (copy > len) 27228c2ecf20Sopenharmony_ci copy = len; 27238c2ecf20Sopenharmony_ci csum2 = __skb_checksum(frag_iter, offset - start, 27248c2ecf20Sopenharmony_ci copy, 0, ops); 27258c2ecf20Sopenharmony_ci csum = INDIRECT_CALL_1(ops->combine, csum_block_add_ext, 27268c2ecf20Sopenharmony_ci csum, csum2, pos, copy); 27278c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 27288c2ecf20Sopenharmony_ci return csum; 27298c2ecf20Sopenharmony_ci offset += copy; 27308c2ecf20Sopenharmony_ci pos += copy; 27318c2ecf20Sopenharmony_ci } 27328c2ecf20Sopenharmony_ci start = end; 27338c2ecf20Sopenharmony_ci } 27348c2ecf20Sopenharmony_ci BUG_ON(len); 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci return csum; 27378c2ecf20Sopenharmony_ci} 27388c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__skb_checksum); 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci__wsum skb_checksum(const struct sk_buff *skb, int offset, 27418c2ecf20Sopenharmony_ci int len, __wsum csum) 27428c2ecf20Sopenharmony_ci{ 27438c2ecf20Sopenharmony_ci const struct skb_checksum_ops ops = { 27448c2ecf20Sopenharmony_ci .update = csum_partial_ext, 27458c2ecf20Sopenharmony_ci .combine = csum_block_add_ext, 27468c2ecf20Sopenharmony_ci }; 27478c2ecf20Sopenharmony_ci 27488c2ecf20Sopenharmony_ci return __skb_checksum(skb, offset, len, csum, &ops); 27498c2ecf20Sopenharmony_ci} 27508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_checksum); 27518c2ecf20Sopenharmony_ci 27528c2ecf20Sopenharmony_ci/* Both of above in one bottle. */ 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_ci__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, 27558c2ecf20Sopenharmony_ci u8 *to, int len) 27568c2ecf20Sopenharmony_ci{ 27578c2ecf20Sopenharmony_ci int start = skb_headlen(skb); 27588c2ecf20Sopenharmony_ci int i, copy = start - offset; 27598c2ecf20Sopenharmony_ci struct sk_buff *frag_iter; 27608c2ecf20Sopenharmony_ci int pos = 0; 27618c2ecf20Sopenharmony_ci __wsum csum = 0; 27628c2ecf20Sopenharmony_ci 27638c2ecf20Sopenharmony_ci /* Copy header. */ 27648c2ecf20Sopenharmony_ci if (copy > 0) { 27658c2ecf20Sopenharmony_ci if (copy > len) 27668c2ecf20Sopenharmony_ci copy = len; 27678c2ecf20Sopenharmony_ci csum = csum_partial_copy_nocheck(skb->data + offset, to, 27688c2ecf20Sopenharmony_ci copy); 27698c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 27708c2ecf20Sopenharmony_ci return csum; 27718c2ecf20Sopenharmony_ci offset += copy; 27728c2ecf20Sopenharmony_ci to += copy; 27738c2ecf20Sopenharmony_ci pos = copy; 27748c2ecf20Sopenharmony_ci } 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 27778c2ecf20Sopenharmony_ci int end; 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]); 27828c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 27838c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 27848c2ecf20Sopenharmony_ci u32 p_off, p_len, copied; 27858c2ecf20Sopenharmony_ci struct page *p; 27868c2ecf20Sopenharmony_ci __wsum csum2; 27878c2ecf20Sopenharmony_ci u8 *vaddr; 27888c2ecf20Sopenharmony_ci 27898c2ecf20Sopenharmony_ci if (copy > len) 27908c2ecf20Sopenharmony_ci copy = len; 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci skb_frag_foreach_page(frag, 27938c2ecf20Sopenharmony_ci skb_frag_off(frag) + offset - start, 27948c2ecf20Sopenharmony_ci copy, p, p_off, p_len, copied) { 27958c2ecf20Sopenharmony_ci vaddr = kmap_atomic(p); 27968c2ecf20Sopenharmony_ci csum2 = csum_partial_copy_nocheck(vaddr + p_off, 27978c2ecf20Sopenharmony_ci to + copied, 27988c2ecf20Sopenharmony_ci p_len); 27998c2ecf20Sopenharmony_ci kunmap_atomic(vaddr); 28008c2ecf20Sopenharmony_ci csum = csum_block_add(csum, csum2, pos); 28018c2ecf20Sopenharmony_ci pos += p_len; 28028c2ecf20Sopenharmony_ci } 28038c2ecf20Sopenharmony_ci 28048c2ecf20Sopenharmony_ci if (!(len -= copy)) 28058c2ecf20Sopenharmony_ci return csum; 28068c2ecf20Sopenharmony_ci offset += copy; 28078c2ecf20Sopenharmony_ci to += copy; 28088c2ecf20Sopenharmony_ci } 28098c2ecf20Sopenharmony_ci start = end; 28108c2ecf20Sopenharmony_ci } 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci skb_walk_frags(skb, frag_iter) { 28138c2ecf20Sopenharmony_ci __wsum csum2; 28148c2ecf20Sopenharmony_ci int end; 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_ci end = start + frag_iter->len; 28198c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 28208c2ecf20Sopenharmony_ci if (copy > len) 28218c2ecf20Sopenharmony_ci copy = len; 28228c2ecf20Sopenharmony_ci csum2 = skb_copy_and_csum_bits(frag_iter, 28238c2ecf20Sopenharmony_ci offset - start, 28248c2ecf20Sopenharmony_ci to, copy); 28258c2ecf20Sopenharmony_ci csum = csum_block_add(csum, csum2, pos); 28268c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 28278c2ecf20Sopenharmony_ci return csum; 28288c2ecf20Sopenharmony_ci offset += copy; 28298c2ecf20Sopenharmony_ci to += copy; 28308c2ecf20Sopenharmony_ci pos += copy; 28318c2ecf20Sopenharmony_ci } 28328c2ecf20Sopenharmony_ci start = end; 28338c2ecf20Sopenharmony_ci } 28348c2ecf20Sopenharmony_ci BUG_ON(len); 28358c2ecf20Sopenharmony_ci return csum; 28368c2ecf20Sopenharmony_ci} 28378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_copy_and_csum_bits); 28388c2ecf20Sopenharmony_ci 28398c2ecf20Sopenharmony_ci__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len) 28408c2ecf20Sopenharmony_ci{ 28418c2ecf20Sopenharmony_ci __sum16 sum; 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci sum = csum_fold(skb_checksum(skb, 0, len, skb->csum)); 28448c2ecf20Sopenharmony_ci /* See comments in __skb_checksum_complete(). */ 28458c2ecf20Sopenharmony_ci if (likely(!sum)) { 28468c2ecf20Sopenharmony_ci if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && 28478c2ecf20Sopenharmony_ci !skb->csum_complete_sw) 28488c2ecf20Sopenharmony_ci netdev_rx_csum_fault(skb->dev, skb); 28498c2ecf20Sopenharmony_ci } 28508c2ecf20Sopenharmony_ci if (!skb_shared(skb)) 28518c2ecf20Sopenharmony_ci skb->csum_valid = !sum; 28528c2ecf20Sopenharmony_ci return sum; 28538c2ecf20Sopenharmony_ci} 28548c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__skb_checksum_complete_head); 28558c2ecf20Sopenharmony_ci 28568c2ecf20Sopenharmony_ci/* This function assumes skb->csum already holds pseudo header's checksum, 28578c2ecf20Sopenharmony_ci * which has been changed from the hardware checksum, for example, by 28588c2ecf20Sopenharmony_ci * __skb_checksum_validate_complete(). And, the original skb->csum must 28598c2ecf20Sopenharmony_ci * have been validated unsuccessfully for CHECKSUM_COMPLETE case. 28608c2ecf20Sopenharmony_ci * 28618c2ecf20Sopenharmony_ci * It returns non-zero if the recomputed checksum is still invalid, otherwise 28628c2ecf20Sopenharmony_ci * zero. The new checksum is stored back into skb->csum unless the skb is 28638c2ecf20Sopenharmony_ci * shared. 28648c2ecf20Sopenharmony_ci */ 28658c2ecf20Sopenharmony_ci__sum16 __skb_checksum_complete(struct sk_buff *skb) 28668c2ecf20Sopenharmony_ci{ 28678c2ecf20Sopenharmony_ci __wsum csum; 28688c2ecf20Sopenharmony_ci __sum16 sum; 28698c2ecf20Sopenharmony_ci 28708c2ecf20Sopenharmony_ci csum = skb_checksum(skb, 0, skb->len, 0); 28718c2ecf20Sopenharmony_ci 28728c2ecf20Sopenharmony_ci sum = csum_fold(csum_add(skb->csum, csum)); 28738c2ecf20Sopenharmony_ci /* This check is inverted, because we already knew the hardware 28748c2ecf20Sopenharmony_ci * checksum is invalid before calling this function. So, if the 28758c2ecf20Sopenharmony_ci * re-computed checksum is valid instead, then we have a mismatch 28768c2ecf20Sopenharmony_ci * between the original skb->csum and skb_checksum(). This means either 28778c2ecf20Sopenharmony_ci * the original hardware checksum is incorrect or we screw up skb->csum 28788c2ecf20Sopenharmony_ci * when moving skb->data around. 28798c2ecf20Sopenharmony_ci */ 28808c2ecf20Sopenharmony_ci if (likely(!sum)) { 28818c2ecf20Sopenharmony_ci if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && 28828c2ecf20Sopenharmony_ci !skb->csum_complete_sw) 28838c2ecf20Sopenharmony_ci netdev_rx_csum_fault(skb->dev, skb); 28848c2ecf20Sopenharmony_ci } 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_ci if (!skb_shared(skb)) { 28878c2ecf20Sopenharmony_ci /* Save full packet checksum */ 28888c2ecf20Sopenharmony_ci skb->csum = csum; 28898c2ecf20Sopenharmony_ci skb->ip_summed = CHECKSUM_COMPLETE; 28908c2ecf20Sopenharmony_ci skb->csum_complete_sw = 1; 28918c2ecf20Sopenharmony_ci skb->csum_valid = !sum; 28928c2ecf20Sopenharmony_ci } 28938c2ecf20Sopenharmony_ci 28948c2ecf20Sopenharmony_ci return sum; 28958c2ecf20Sopenharmony_ci} 28968c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__skb_checksum_complete); 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_cistatic __wsum warn_crc32c_csum_update(const void *buff, int len, __wsum sum) 28998c2ecf20Sopenharmony_ci{ 29008c2ecf20Sopenharmony_ci net_warn_ratelimited( 29018c2ecf20Sopenharmony_ci "%s: attempt to compute crc32c without libcrc32c.ko\n", 29028c2ecf20Sopenharmony_ci __func__); 29038c2ecf20Sopenharmony_ci return 0; 29048c2ecf20Sopenharmony_ci} 29058c2ecf20Sopenharmony_ci 29068c2ecf20Sopenharmony_cistatic __wsum warn_crc32c_csum_combine(__wsum csum, __wsum csum2, 29078c2ecf20Sopenharmony_ci int offset, int len) 29088c2ecf20Sopenharmony_ci{ 29098c2ecf20Sopenharmony_ci net_warn_ratelimited( 29108c2ecf20Sopenharmony_ci "%s: attempt to compute crc32c without libcrc32c.ko\n", 29118c2ecf20Sopenharmony_ci __func__); 29128c2ecf20Sopenharmony_ci return 0; 29138c2ecf20Sopenharmony_ci} 29148c2ecf20Sopenharmony_ci 29158c2ecf20Sopenharmony_cistatic const struct skb_checksum_ops default_crc32c_ops = { 29168c2ecf20Sopenharmony_ci .update = warn_crc32c_csum_update, 29178c2ecf20Sopenharmony_ci .combine = warn_crc32c_csum_combine, 29188c2ecf20Sopenharmony_ci}; 29198c2ecf20Sopenharmony_ci 29208c2ecf20Sopenharmony_ciconst struct skb_checksum_ops *crc32c_csum_stub __read_mostly = 29218c2ecf20Sopenharmony_ci &default_crc32c_ops; 29228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(crc32c_csum_stub); 29238c2ecf20Sopenharmony_ci 29248c2ecf20Sopenharmony_ci /** 29258c2ecf20Sopenharmony_ci * skb_zerocopy_headlen - Calculate headroom needed for skb_zerocopy() 29268c2ecf20Sopenharmony_ci * @from: source buffer 29278c2ecf20Sopenharmony_ci * 29288c2ecf20Sopenharmony_ci * Calculates the amount of linear headroom needed in the 'to' skb passed 29298c2ecf20Sopenharmony_ci * into skb_zerocopy(). 29308c2ecf20Sopenharmony_ci */ 29318c2ecf20Sopenharmony_ciunsigned int 29328c2ecf20Sopenharmony_ciskb_zerocopy_headlen(const struct sk_buff *from) 29338c2ecf20Sopenharmony_ci{ 29348c2ecf20Sopenharmony_ci unsigned int hlen = 0; 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci if (!from->head_frag || 29378c2ecf20Sopenharmony_ci skb_headlen(from) < L1_CACHE_BYTES || 29388c2ecf20Sopenharmony_ci skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS) { 29398c2ecf20Sopenharmony_ci hlen = skb_headlen(from); 29408c2ecf20Sopenharmony_ci if (!hlen) 29418c2ecf20Sopenharmony_ci hlen = from->len; 29428c2ecf20Sopenharmony_ci } 29438c2ecf20Sopenharmony_ci 29448c2ecf20Sopenharmony_ci if (skb_has_frag_list(from)) 29458c2ecf20Sopenharmony_ci hlen = from->len; 29468c2ecf20Sopenharmony_ci 29478c2ecf20Sopenharmony_ci return hlen; 29488c2ecf20Sopenharmony_ci} 29498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_zerocopy_headlen); 29508c2ecf20Sopenharmony_ci 29518c2ecf20Sopenharmony_ci/** 29528c2ecf20Sopenharmony_ci * skb_zerocopy - Zero copy skb to skb 29538c2ecf20Sopenharmony_ci * @to: destination buffer 29548c2ecf20Sopenharmony_ci * @from: source buffer 29558c2ecf20Sopenharmony_ci * @len: number of bytes to copy from source buffer 29568c2ecf20Sopenharmony_ci * @hlen: size of linear headroom in destination buffer 29578c2ecf20Sopenharmony_ci * 29588c2ecf20Sopenharmony_ci * Copies up to `len` bytes from `from` to `to` by creating references 29598c2ecf20Sopenharmony_ci * to the frags in the source buffer. 29608c2ecf20Sopenharmony_ci * 29618c2ecf20Sopenharmony_ci * The `hlen` as calculated by skb_zerocopy_headlen() specifies the 29628c2ecf20Sopenharmony_ci * headroom in the `to` buffer. 29638c2ecf20Sopenharmony_ci * 29648c2ecf20Sopenharmony_ci * Return value: 29658c2ecf20Sopenharmony_ci * 0: everything is OK 29668c2ecf20Sopenharmony_ci * -ENOMEM: couldn't orphan frags of @from due to lack of memory 29678c2ecf20Sopenharmony_ci * -EFAULT: skb_copy_bits() found some problem with skb geometry 29688c2ecf20Sopenharmony_ci */ 29698c2ecf20Sopenharmony_ciint 29708c2ecf20Sopenharmony_ciskb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen) 29718c2ecf20Sopenharmony_ci{ 29728c2ecf20Sopenharmony_ci int i, j = 0; 29738c2ecf20Sopenharmony_ci int plen = 0; /* length of skb->head fragment */ 29748c2ecf20Sopenharmony_ci int ret; 29758c2ecf20Sopenharmony_ci struct page *page; 29768c2ecf20Sopenharmony_ci unsigned int offset; 29778c2ecf20Sopenharmony_ci 29788c2ecf20Sopenharmony_ci BUG_ON(!from->head_frag && !hlen); 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_ci /* dont bother with small payloads */ 29818c2ecf20Sopenharmony_ci if (len <= skb_tailroom(to)) 29828c2ecf20Sopenharmony_ci return skb_copy_bits(from, 0, skb_put(to, len), len); 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ci if (hlen) { 29858c2ecf20Sopenharmony_ci ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen); 29868c2ecf20Sopenharmony_ci if (unlikely(ret)) 29878c2ecf20Sopenharmony_ci return ret; 29888c2ecf20Sopenharmony_ci len -= hlen; 29898c2ecf20Sopenharmony_ci } else { 29908c2ecf20Sopenharmony_ci plen = min_t(int, skb_headlen(from), len); 29918c2ecf20Sopenharmony_ci if (plen) { 29928c2ecf20Sopenharmony_ci page = virt_to_head_page(from->head); 29938c2ecf20Sopenharmony_ci offset = from->data - (unsigned char *)page_address(page); 29948c2ecf20Sopenharmony_ci __skb_fill_page_desc(to, 0, page, offset, plen); 29958c2ecf20Sopenharmony_ci get_page(page); 29968c2ecf20Sopenharmony_ci j = 1; 29978c2ecf20Sopenharmony_ci len -= plen; 29988c2ecf20Sopenharmony_ci } 29998c2ecf20Sopenharmony_ci } 30008c2ecf20Sopenharmony_ci 30018c2ecf20Sopenharmony_ci to->truesize += len + plen; 30028c2ecf20Sopenharmony_ci to->len += len + plen; 30038c2ecf20Sopenharmony_ci to->data_len += len + plen; 30048c2ecf20Sopenharmony_ci 30058c2ecf20Sopenharmony_ci if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) { 30068c2ecf20Sopenharmony_ci skb_tx_error(from); 30078c2ecf20Sopenharmony_ci return -ENOMEM; 30088c2ecf20Sopenharmony_ci } 30098c2ecf20Sopenharmony_ci skb_zerocopy_clone(to, from, GFP_ATOMIC); 30108c2ecf20Sopenharmony_ci 30118c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { 30128c2ecf20Sopenharmony_ci int size; 30138c2ecf20Sopenharmony_ci 30148c2ecf20Sopenharmony_ci if (!len) 30158c2ecf20Sopenharmony_ci break; 30168c2ecf20Sopenharmony_ci skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i]; 30178c2ecf20Sopenharmony_ci size = min_t(int, skb_frag_size(&skb_shinfo(to)->frags[j]), 30188c2ecf20Sopenharmony_ci len); 30198c2ecf20Sopenharmony_ci skb_frag_size_set(&skb_shinfo(to)->frags[j], size); 30208c2ecf20Sopenharmony_ci len -= size; 30218c2ecf20Sopenharmony_ci skb_frag_ref(to, j); 30228c2ecf20Sopenharmony_ci j++; 30238c2ecf20Sopenharmony_ci } 30248c2ecf20Sopenharmony_ci skb_shinfo(to)->nr_frags = j; 30258c2ecf20Sopenharmony_ci 30268c2ecf20Sopenharmony_ci return 0; 30278c2ecf20Sopenharmony_ci} 30288c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_zerocopy); 30298c2ecf20Sopenharmony_ci 30308c2ecf20Sopenharmony_civoid skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) 30318c2ecf20Sopenharmony_ci{ 30328c2ecf20Sopenharmony_ci __wsum csum; 30338c2ecf20Sopenharmony_ci long csstart; 30348c2ecf20Sopenharmony_ci 30358c2ecf20Sopenharmony_ci if (skb->ip_summed == CHECKSUM_PARTIAL) 30368c2ecf20Sopenharmony_ci csstart = skb_checksum_start_offset(skb); 30378c2ecf20Sopenharmony_ci else 30388c2ecf20Sopenharmony_ci csstart = skb_headlen(skb); 30398c2ecf20Sopenharmony_ci 30408c2ecf20Sopenharmony_ci BUG_ON(csstart > skb_headlen(skb)); 30418c2ecf20Sopenharmony_ci 30428c2ecf20Sopenharmony_ci skb_copy_from_linear_data(skb, to, csstart); 30438c2ecf20Sopenharmony_ci 30448c2ecf20Sopenharmony_ci csum = 0; 30458c2ecf20Sopenharmony_ci if (csstart != skb->len) 30468c2ecf20Sopenharmony_ci csum = skb_copy_and_csum_bits(skb, csstart, to + csstart, 30478c2ecf20Sopenharmony_ci skb->len - csstart); 30488c2ecf20Sopenharmony_ci 30498c2ecf20Sopenharmony_ci if (skb->ip_summed == CHECKSUM_PARTIAL) { 30508c2ecf20Sopenharmony_ci long csstuff = csstart + skb->csum_offset; 30518c2ecf20Sopenharmony_ci 30528c2ecf20Sopenharmony_ci *((__sum16 *)(to + csstuff)) = csum_fold(csum); 30538c2ecf20Sopenharmony_ci } 30548c2ecf20Sopenharmony_ci} 30558c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_copy_and_csum_dev); 30568c2ecf20Sopenharmony_ci 30578c2ecf20Sopenharmony_ci/** 30588c2ecf20Sopenharmony_ci * skb_dequeue - remove from the head of the queue 30598c2ecf20Sopenharmony_ci * @list: list to dequeue from 30608c2ecf20Sopenharmony_ci * 30618c2ecf20Sopenharmony_ci * Remove the head of the list. The list lock is taken so the function 30628c2ecf20Sopenharmony_ci * may be used safely with other locking list functions. The head item is 30638c2ecf20Sopenharmony_ci * returned or %NULL if the list is empty. 30648c2ecf20Sopenharmony_ci */ 30658c2ecf20Sopenharmony_ci 30668c2ecf20Sopenharmony_cistruct sk_buff *skb_dequeue(struct sk_buff_head *list) 30678c2ecf20Sopenharmony_ci{ 30688c2ecf20Sopenharmony_ci unsigned long flags; 30698c2ecf20Sopenharmony_ci struct sk_buff *result; 30708c2ecf20Sopenharmony_ci 30718c2ecf20Sopenharmony_ci spin_lock_irqsave(&list->lock, flags); 30728c2ecf20Sopenharmony_ci result = __skb_dequeue(list); 30738c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&list->lock, flags); 30748c2ecf20Sopenharmony_ci return result; 30758c2ecf20Sopenharmony_ci} 30768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_dequeue); 30778c2ecf20Sopenharmony_ci 30788c2ecf20Sopenharmony_ci/** 30798c2ecf20Sopenharmony_ci * skb_dequeue_tail - remove from the tail of the queue 30808c2ecf20Sopenharmony_ci * @list: list to dequeue from 30818c2ecf20Sopenharmony_ci * 30828c2ecf20Sopenharmony_ci * Remove the tail of the list. The list lock is taken so the function 30838c2ecf20Sopenharmony_ci * may be used safely with other locking list functions. The tail item is 30848c2ecf20Sopenharmony_ci * returned or %NULL if the list is empty. 30858c2ecf20Sopenharmony_ci */ 30868c2ecf20Sopenharmony_cistruct sk_buff *skb_dequeue_tail(struct sk_buff_head *list) 30878c2ecf20Sopenharmony_ci{ 30888c2ecf20Sopenharmony_ci unsigned long flags; 30898c2ecf20Sopenharmony_ci struct sk_buff *result; 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci spin_lock_irqsave(&list->lock, flags); 30928c2ecf20Sopenharmony_ci result = __skb_dequeue_tail(list); 30938c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&list->lock, flags); 30948c2ecf20Sopenharmony_ci return result; 30958c2ecf20Sopenharmony_ci} 30968c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_dequeue_tail); 30978c2ecf20Sopenharmony_ci 30988c2ecf20Sopenharmony_ci/** 30998c2ecf20Sopenharmony_ci * skb_queue_purge - empty a list 31008c2ecf20Sopenharmony_ci * @list: list to empty 31018c2ecf20Sopenharmony_ci * 31028c2ecf20Sopenharmony_ci * Delete all buffers on an &sk_buff list. Each buffer is removed from 31038c2ecf20Sopenharmony_ci * the list and one reference dropped. This function takes the list 31048c2ecf20Sopenharmony_ci * lock and is atomic with respect to other list locking functions. 31058c2ecf20Sopenharmony_ci */ 31068c2ecf20Sopenharmony_civoid skb_queue_purge(struct sk_buff_head *list) 31078c2ecf20Sopenharmony_ci{ 31088c2ecf20Sopenharmony_ci struct sk_buff *skb; 31098c2ecf20Sopenharmony_ci while ((skb = skb_dequeue(list)) != NULL) 31108c2ecf20Sopenharmony_ci kfree_skb(skb); 31118c2ecf20Sopenharmony_ci} 31128c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_queue_purge); 31138c2ecf20Sopenharmony_ci 31148c2ecf20Sopenharmony_ci/** 31158c2ecf20Sopenharmony_ci * skb_rbtree_purge - empty a skb rbtree 31168c2ecf20Sopenharmony_ci * @root: root of the rbtree to empty 31178c2ecf20Sopenharmony_ci * Return value: the sum of truesizes of all purged skbs. 31188c2ecf20Sopenharmony_ci * 31198c2ecf20Sopenharmony_ci * Delete all buffers on an &sk_buff rbtree. Each buffer is removed from 31208c2ecf20Sopenharmony_ci * the list and one reference dropped. This function does not take 31218c2ecf20Sopenharmony_ci * any lock. Synchronization should be handled by the caller (e.g., TCP 31228c2ecf20Sopenharmony_ci * out-of-order queue is protected by the socket lock). 31238c2ecf20Sopenharmony_ci */ 31248c2ecf20Sopenharmony_ciunsigned int skb_rbtree_purge(struct rb_root *root) 31258c2ecf20Sopenharmony_ci{ 31268c2ecf20Sopenharmony_ci struct rb_node *p = rb_first(root); 31278c2ecf20Sopenharmony_ci unsigned int sum = 0; 31288c2ecf20Sopenharmony_ci 31298c2ecf20Sopenharmony_ci while (p) { 31308c2ecf20Sopenharmony_ci struct sk_buff *skb = rb_entry(p, struct sk_buff, rbnode); 31318c2ecf20Sopenharmony_ci 31328c2ecf20Sopenharmony_ci p = rb_next(p); 31338c2ecf20Sopenharmony_ci rb_erase(&skb->rbnode, root); 31348c2ecf20Sopenharmony_ci sum += skb->truesize; 31358c2ecf20Sopenharmony_ci kfree_skb(skb); 31368c2ecf20Sopenharmony_ci } 31378c2ecf20Sopenharmony_ci return sum; 31388c2ecf20Sopenharmony_ci} 31398c2ecf20Sopenharmony_ci 31408c2ecf20Sopenharmony_ci/** 31418c2ecf20Sopenharmony_ci * skb_queue_head - queue a buffer at the list head 31428c2ecf20Sopenharmony_ci * @list: list to use 31438c2ecf20Sopenharmony_ci * @newsk: buffer to queue 31448c2ecf20Sopenharmony_ci * 31458c2ecf20Sopenharmony_ci * Queue a buffer at the start of the list. This function takes the 31468c2ecf20Sopenharmony_ci * list lock and can be used safely with other locking &sk_buff functions 31478c2ecf20Sopenharmony_ci * safely. 31488c2ecf20Sopenharmony_ci * 31498c2ecf20Sopenharmony_ci * A buffer cannot be placed on two lists at the same time. 31508c2ecf20Sopenharmony_ci */ 31518c2ecf20Sopenharmony_civoid skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) 31528c2ecf20Sopenharmony_ci{ 31538c2ecf20Sopenharmony_ci unsigned long flags; 31548c2ecf20Sopenharmony_ci 31558c2ecf20Sopenharmony_ci spin_lock_irqsave(&list->lock, flags); 31568c2ecf20Sopenharmony_ci __skb_queue_head(list, newsk); 31578c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&list->lock, flags); 31588c2ecf20Sopenharmony_ci} 31598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_queue_head); 31608c2ecf20Sopenharmony_ci 31618c2ecf20Sopenharmony_ci/** 31628c2ecf20Sopenharmony_ci * skb_queue_tail - queue a buffer at the list tail 31638c2ecf20Sopenharmony_ci * @list: list to use 31648c2ecf20Sopenharmony_ci * @newsk: buffer to queue 31658c2ecf20Sopenharmony_ci * 31668c2ecf20Sopenharmony_ci * Queue a buffer at the tail of the list. This function takes the 31678c2ecf20Sopenharmony_ci * list lock and can be used safely with other locking &sk_buff functions 31688c2ecf20Sopenharmony_ci * safely. 31698c2ecf20Sopenharmony_ci * 31708c2ecf20Sopenharmony_ci * A buffer cannot be placed on two lists at the same time. 31718c2ecf20Sopenharmony_ci */ 31728c2ecf20Sopenharmony_civoid skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) 31738c2ecf20Sopenharmony_ci{ 31748c2ecf20Sopenharmony_ci unsigned long flags; 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_ci spin_lock_irqsave(&list->lock, flags); 31778c2ecf20Sopenharmony_ci __skb_queue_tail(list, newsk); 31788c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&list->lock, flags); 31798c2ecf20Sopenharmony_ci} 31808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_queue_tail); 31818c2ecf20Sopenharmony_ci 31828c2ecf20Sopenharmony_ci/** 31838c2ecf20Sopenharmony_ci * skb_unlink - remove a buffer from a list 31848c2ecf20Sopenharmony_ci * @skb: buffer to remove 31858c2ecf20Sopenharmony_ci * @list: list to use 31868c2ecf20Sopenharmony_ci * 31878c2ecf20Sopenharmony_ci * Remove a packet from a list. The list locks are taken and this 31888c2ecf20Sopenharmony_ci * function is atomic with respect to other list locked calls 31898c2ecf20Sopenharmony_ci * 31908c2ecf20Sopenharmony_ci * You must know what list the SKB is on. 31918c2ecf20Sopenharmony_ci */ 31928c2ecf20Sopenharmony_civoid skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) 31938c2ecf20Sopenharmony_ci{ 31948c2ecf20Sopenharmony_ci unsigned long flags; 31958c2ecf20Sopenharmony_ci 31968c2ecf20Sopenharmony_ci spin_lock_irqsave(&list->lock, flags); 31978c2ecf20Sopenharmony_ci __skb_unlink(skb, list); 31988c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&list->lock, flags); 31998c2ecf20Sopenharmony_ci} 32008c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_unlink); 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci/** 32038c2ecf20Sopenharmony_ci * skb_append - append a buffer 32048c2ecf20Sopenharmony_ci * @old: buffer to insert after 32058c2ecf20Sopenharmony_ci * @newsk: buffer to insert 32068c2ecf20Sopenharmony_ci * @list: list to use 32078c2ecf20Sopenharmony_ci * 32088c2ecf20Sopenharmony_ci * Place a packet after a given packet in a list. The list locks are taken 32098c2ecf20Sopenharmony_ci * and this function is atomic with respect to other list locked calls. 32108c2ecf20Sopenharmony_ci * A buffer cannot be placed on two lists at the same time. 32118c2ecf20Sopenharmony_ci */ 32128c2ecf20Sopenharmony_civoid skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list) 32138c2ecf20Sopenharmony_ci{ 32148c2ecf20Sopenharmony_ci unsigned long flags; 32158c2ecf20Sopenharmony_ci 32168c2ecf20Sopenharmony_ci spin_lock_irqsave(&list->lock, flags); 32178c2ecf20Sopenharmony_ci __skb_queue_after(list, old, newsk); 32188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&list->lock, flags); 32198c2ecf20Sopenharmony_ci} 32208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_append); 32218c2ecf20Sopenharmony_ci 32228c2ecf20Sopenharmony_cistatic inline void skb_split_inside_header(struct sk_buff *skb, 32238c2ecf20Sopenharmony_ci struct sk_buff* skb1, 32248c2ecf20Sopenharmony_ci const u32 len, const int pos) 32258c2ecf20Sopenharmony_ci{ 32268c2ecf20Sopenharmony_ci int i; 32278c2ecf20Sopenharmony_ci 32288c2ecf20Sopenharmony_ci skb_copy_from_linear_data_offset(skb, len, skb_put(skb1, pos - len), 32298c2ecf20Sopenharmony_ci pos - len); 32308c2ecf20Sopenharmony_ci /* And move data appendix as is. */ 32318c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) 32328c2ecf20Sopenharmony_ci skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i]; 32338c2ecf20Sopenharmony_ci 32348c2ecf20Sopenharmony_ci skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags; 32358c2ecf20Sopenharmony_ci skb_shinfo(skb)->nr_frags = 0; 32368c2ecf20Sopenharmony_ci skb1->data_len = skb->data_len; 32378c2ecf20Sopenharmony_ci skb1->len += skb1->data_len; 32388c2ecf20Sopenharmony_ci skb->data_len = 0; 32398c2ecf20Sopenharmony_ci skb->len = len; 32408c2ecf20Sopenharmony_ci skb_set_tail_pointer(skb, len); 32418c2ecf20Sopenharmony_ci} 32428c2ecf20Sopenharmony_ci 32438c2ecf20Sopenharmony_cistatic inline void skb_split_no_header(struct sk_buff *skb, 32448c2ecf20Sopenharmony_ci struct sk_buff* skb1, 32458c2ecf20Sopenharmony_ci const u32 len, int pos) 32468c2ecf20Sopenharmony_ci{ 32478c2ecf20Sopenharmony_ci int i, k = 0; 32488c2ecf20Sopenharmony_ci const int nfrags = skb_shinfo(skb)->nr_frags; 32498c2ecf20Sopenharmony_ci 32508c2ecf20Sopenharmony_ci skb_shinfo(skb)->nr_frags = 0; 32518c2ecf20Sopenharmony_ci skb1->len = skb1->data_len = skb->len - len; 32528c2ecf20Sopenharmony_ci skb->len = len; 32538c2ecf20Sopenharmony_ci skb->data_len = len - pos; 32548c2ecf20Sopenharmony_ci 32558c2ecf20Sopenharmony_ci for (i = 0; i < nfrags; i++) { 32568c2ecf20Sopenharmony_ci int size = skb_frag_size(&skb_shinfo(skb)->frags[i]); 32578c2ecf20Sopenharmony_ci 32588c2ecf20Sopenharmony_ci if (pos + size > len) { 32598c2ecf20Sopenharmony_ci skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i]; 32608c2ecf20Sopenharmony_ci 32618c2ecf20Sopenharmony_ci if (pos < len) { 32628c2ecf20Sopenharmony_ci /* Split frag. 32638c2ecf20Sopenharmony_ci * We have two variants in this case: 32648c2ecf20Sopenharmony_ci * 1. Move all the frag to the second 32658c2ecf20Sopenharmony_ci * part, if it is possible. F.e. 32668c2ecf20Sopenharmony_ci * this approach is mandatory for TUX, 32678c2ecf20Sopenharmony_ci * where splitting is expensive. 32688c2ecf20Sopenharmony_ci * 2. Split is accurately. We make this. 32698c2ecf20Sopenharmony_ci */ 32708c2ecf20Sopenharmony_ci skb_frag_ref(skb, i); 32718c2ecf20Sopenharmony_ci skb_frag_off_add(&skb_shinfo(skb1)->frags[0], len - pos); 32728c2ecf20Sopenharmony_ci skb_frag_size_sub(&skb_shinfo(skb1)->frags[0], len - pos); 32738c2ecf20Sopenharmony_ci skb_frag_size_set(&skb_shinfo(skb)->frags[i], len - pos); 32748c2ecf20Sopenharmony_ci skb_shinfo(skb)->nr_frags++; 32758c2ecf20Sopenharmony_ci } 32768c2ecf20Sopenharmony_ci k++; 32778c2ecf20Sopenharmony_ci } else 32788c2ecf20Sopenharmony_ci skb_shinfo(skb)->nr_frags++; 32798c2ecf20Sopenharmony_ci pos += size; 32808c2ecf20Sopenharmony_ci } 32818c2ecf20Sopenharmony_ci skb_shinfo(skb1)->nr_frags = k; 32828c2ecf20Sopenharmony_ci} 32838c2ecf20Sopenharmony_ci 32848c2ecf20Sopenharmony_ci/** 32858c2ecf20Sopenharmony_ci * skb_split - Split fragmented skb to two parts at length len. 32868c2ecf20Sopenharmony_ci * @skb: the buffer to split 32878c2ecf20Sopenharmony_ci * @skb1: the buffer to receive the second part 32888c2ecf20Sopenharmony_ci * @len: new length for skb 32898c2ecf20Sopenharmony_ci */ 32908c2ecf20Sopenharmony_civoid skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len) 32918c2ecf20Sopenharmony_ci{ 32928c2ecf20Sopenharmony_ci int pos = skb_headlen(skb); 32938c2ecf20Sopenharmony_ci 32948c2ecf20Sopenharmony_ci skb_shinfo(skb1)->tx_flags |= skb_shinfo(skb)->tx_flags & 32958c2ecf20Sopenharmony_ci SKBTX_SHARED_FRAG; 32968c2ecf20Sopenharmony_ci skb_zerocopy_clone(skb1, skb, 0); 32978c2ecf20Sopenharmony_ci if (len < pos) /* Split line is inside header. */ 32988c2ecf20Sopenharmony_ci skb_split_inside_header(skb, skb1, len, pos); 32998c2ecf20Sopenharmony_ci else /* Second chunk has no header, nothing to copy. */ 33008c2ecf20Sopenharmony_ci skb_split_no_header(skb, skb1, len, pos); 33018c2ecf20Sopenharmony_ci} 33028c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_split); 33038c2ecf20Sopenharmony_ci 33048c2ecf20Sopenharmony_ci/* Shifting from/to a cloned skb is a no-go. 33058c2ecf20Sopenharmony_ci * 33068c2ecf20Sopenharmony_ci * Caller cannot keep skb_shinfo related pointers past calling here! 33078c2ecf20Sopenharmony_ci */ 33088c2ecf20Sopenharmony_cistatic int skb_prepare_for_shift(struct sk_buff *skb) 33098c2ecf20Sopenharmony_ci{ 33108c2ecf20Sopenharmony_ci int ret = 0; 33118c2ecf20Sopenharmony_ci 33128c2ecf20Sopenharmony_ci if (skb_cloned(skb)) { 33138c2ecf20Sopenharmony_ci /* Save and restore truesize: pskb_expand_head() may reallocate 33148c2ecf20Sopenharmony_ci * memory where ksize(kmalloc(S)) != ksize(kmalloc(S)), but we 33158c2ecf20Sopenharmony_ci * cannot change truesize at this point. 33168c2ecf20Sopenharmony_ci */ 33178c2ecf20Sopenharmony_ci unsigned int save_truesize = skb->truesize; 33188c2ecf20Sopenharmony_ci 33198c2ecf20Sopenharmony_ci ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); 33208c2ecf20Sopenharmony_ci skb->truesize = save_truesize; 33218c2ecf20Sopenharmony_ci } 33228c2ecf20Sopenharmony_ci return ret; 33238c2ecf20Sopenharmony_ci} 33248c2ecf20Sopenharmony_ci 33258c2ecf20Sopenharmony_ci/** 33268c2ecf20Sopenharmony_ci * skb_shift - Shifts paged data partially from skb to another 33278c2ecf20Sopenharmony_ci * @tgt: buffer into which tail data gets added 33288c2ecf20Sopenharmony_ci * @skb: buffer from which the paged data comes from 33298c2ecf20Sopenharmony_ci * @shiftlen: shift up to this many bytes 33308c2ecf20Sopenharmony_ci * 33318c2ecf20Sopenharmony_ci * Attempts to shift up to shiftlen worth of bytes, which may be less than 33328c2ecf20Sopenharmony_ci * the length of the skb, from skb to tgt. Returns number bytes shifted. 33338c2ecf20Sopenharmony_ci * It's up to caller to free skb if everything was shifted. 33348c2ecf20Sopenharmony_ci * 33358c2ecf20Sopenharmony_ci * If @tgt runs out of frags, the whole operation is aborted. 33368c2ecf20Sopenharmony_ci * 33378c2ecf20Sopenharmony_ci * Skb cannot include anything else but paged data while tgt is allowed 33388c2ecf20Sopenharmony_ci * to have non-paged data as well. 33398c2ecf20Sopenharmony_ci * 33408c2ecf20Sopenharmony_ci * TODO: full sized shift could be optimized but that would need 33418c2ecf20Sopenharmony_ci * specialized skb free'er to handle frags without up-to-date nr_frags. 33428c2ecf20Sopenharmony_ci */ 33438c2ecf20Sopenharmony_ciint skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) 33448c2ecf20Sopenharmony_ci{ 33458c2ecf20Sopenharmony_ci int from, to, merge, todo; 33468c2ecf20Sopenharmony_ci skb_frag_t *fragfrom, *fragto; 33478c2ecf20Sopenharmony_ci 33488c2ecf20Sopenharmony_ci BUG_ON(shiftlen > skb->len); 33498c2ecf20Sopenharmony_ci 33508c2ecf20Sopenharmony_ci if (skb_headlen(skb)) 33518c2ecf20Sopenharmony_ci return 0; 33528c2ecf20Sopenharmony_ci if (skb_zcopy(tgt) || skb_zcopy(skb)) 33538c2ecf20Sopenharmony_ci return 0; 33548c2ecf20Sopenharmony_ci 33558c2ecf20Sopenharmony_ci todo = shiftlen; 33568c2ecf20Sopenharmony_ci from = 0; 33578c2ecf20Sopenharmony_ci to = skb_shinfo(tgt)->nr_frags; 33588c2ecf20Sopenharmony_ci fragfrom = &skb_shinfo(skb)->frags[from]; 33598c2ecf20Sopenharmony_ci 33608c2ecf20Sopenharmony_ci /* Actual merge is delayed until the point when we know we can 33618c2ecf20Sopenharmony_ci * commit all, so that we don't have to undo partial changes 33628c2ecf20Sopenharmony_ci */ 33638c2ecf20Sopenharmony_ci if (!to || 33648c2ecf20Sopenharmony_ci !skb_can_coalesce(tgt, to, skb_frag_page(fragfrom), 33658c2ecf20Sopenharmony_ci skb_frag_off(fragfrom))) { 33668c2ecf20Sopenharmony_ci merge = -1; 33678c2ecf20Sopenharmony_ci } else { 33688c2ecf20Sopenharmony_ci merge = to - 1; 33698c2ecf20Sopenharmony_ci 33708c2ecf20Sopenharmony_ci todo -= skb_frag_size(fragfrom); 33718c2ecf20Sopenharmony_ci if (todo < 0) { 33728c2ecf20Sopenharmony_ci if (skb_prepare_for_shift(skb) || 33738c2ecf20Sopenharmony_ci skb_prepare_for_shift(tgt)) 33748c2ecf20Sopenharmony_ci return 0; 33758c2ecf20Sopenharmony_ci 33768c2ecf20Sopenharmony_ci /* All previous frag pointers might be stale! */ 33778c2ecf20Sopenharmony_ci fragfrom = &skb_shinfo(skb)->frags[from]; 33788c2ecf20Sopenharmony_ci fragto = &skb_shinfo(tgt)->frags[merge]; 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_ci skb_frag_size_add(fragto, shiftlen); 33818c2ecf20Sopenharmony_ci skb_frag_size_sub(fragfrom, shiftlen); 33828c2ecf20Sopenharmony_ci skb_frag_off_add(fragfrom, shiftlen); 33838c2ecf20Sopenharmony_ci 33848c2ecf20Sopenharmony_ci goto onlymerged; 33858c2ecf20Sopenharmony_ci } 33868c2ecf20Sopenharmony_ci 33878c2ecf20Sopenharmony_ci from++; 33888c2ecf20Sopenharmony_ci } 33898c2ecf20Sopenharmony_ci 33908c2ecf20Sopenharmony_ci /* Skip full, not-fitting skb to avoid expensive operations */ 33918c2ecf20Sopenharmony_ci if ((shiftlen == skb->len) && 33928c2ecf20Sopenharmony_ci (skb_shinfo(skb)->nr_frags - from) > (MAX_SKB_FRAGS - to)) 33938c2ecf20Sopenharmony_ci return 0; 33948c2ecf20Sopenharmony_ci 33958c2ecf20Sopenharmony_ci if (skb_prepare_for_shift(skb) || skb_prepare_for_shift(tgt)) 33968c2ecf20Sopenharmony_ci return 0; 33978c2ecf20Sopenharmony_ci 33988c2ecf20Sopenharmony_ci while ((todo > 0) && (from < skb_shinfo(skb)->nr_frags)) { 33998c2ecf20Sopenharmony_ci if (to == MAX_SKB_FRAGS) 34008c2ecf20Sopenharmony_ci return 0; 34018c2ecf20Sopenharmony_ci 34028c2ecf20Sopenharmony_ci fragfrom = &skb_shinfo(skb)->frags[from]; 34038c2ecf20Sopenharmony_ci fragto = &skb_shinfo(tgt)->frags[to]; 34048c2ecf20Sopenharmony_ci 34058c2ecf20Sopenharmony_ci if (todo >= skb_frag_size(fragfrom)) { 34068c2ecf20Sopenharmony_ci *fragto = *fragfrom; 34078c2ecf20Sopenharmony_ci todo -= skb_frag_size(fragfrom); 34088c2ecf20Sopenharmony_ci from++; 34098c2ecf20Sopenharmony_ci to++; 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_ci } else { 34128c2ecf20Sopenharmony_ci __skb_frag_ref(fragfrom); 34138c2ecf20Sopenharmony_ci skb_frag_page_copy(fragto, fragfrom); 34148c2ecf20Sopenharmony_ci skb_frag_off_copy(fragto, fragfrom); 34158c2ecf20Sopenharmony_ci skb_frag_size_set(fragto, todo); 34168c2ecf20Sopenharmony_ci 34178c2ecf20Sopenharmony_ci skb_frag_off_add(fragfrom, todo); 34188c2ecf20Sopenharmony_ci skb_frag_size_sub(fragfrom, todo); 34198c2ecf20Sopenharmony_ci todo = 0; 34208c2ecf20Sopenharmony_ci 34218c2ecf20Sopenharmony_ci to++; 34228c2ecf20Sopenharmony_ci break; 34238c2ecf20Sopenharmony_ci } 34248c2ecf20Sopenharmony_ci } 34258c2ecf20Sopenharmony_ci 34268c2ecf20Sopenharmony_ci /* Ready to "commit" this state change to tgt */ 34278c2ecf20Sopenharmony_ci skb_shinfo(tgt)->nr_frags = to; 34288c2ecf20Sopenharmony_ci 34298c2ecf20Sopenharmony_ci if (merge >= 0) { 34308c2ecf20Sopenharmony_ci fragfrom = &skb_shinfo(skb)->frags[0]; 34318c2ecf20Sopenharmony_ci fragto = &skb_shinfo(tgt)->frags[merge]; 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci skb_frag_size_add(fragto, skb_frag_size(fragfrom)); 34348c2ecf20Sopenharmony_ci __skb_frag_unref(fragfrom); 34358c2ecf20Sopenharmony_ci } 34368c2ecf20Sopenharmony_ci 34378c2ecf20Sopenharmony_ci /* Reposition in the original skb */ 34388c2ecf20Sopenharmony_ci to = 0; 34398c2ecf20Sopenharmony_ci while (from < skb_shinfo(skb)->nr_frags) 34408c2ecf20Sopenharmony_ci skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++]; 34418c2ecf20Sopenharmony_ci skb_shinfo(skb)->nr_frags = to; 34428c2ecf20Sopenharmony_ci 34438c2ecf20Sopenharmony_ci BUG_ON(todo > 0 && !skb_shinfo(skb)->nr_frags); 34448c2ecf20Sopenharmony_ci 34458c2ecf20Sopenharmony_cionlymerged: 34468c2ecf20Sopenharmony_ci /* Most likely the tgt won't ever need its checksum anymore, skb on 34478c2ecf20Sopenharmony_ci * the other hand might need it if it needs to be resent 34488c2ecf20Sopenharmony_ci */ 34498c2ecf20Sopenharmony_ci tgt->ip_summed = CHECKSUM_PARTIAL; 34508c2ecf20Sopenharmony_ci skb->ip_summed = CHECKSUM_PARTIAL; 34518c2ecf20Sopenharmony_ci 34528c2ecf20Sopenharmony_ci /* Yak, is it really working this way? Some helper please? */ 34538c2ecf20Sopenharmony_ci skb->len -= shiftlen; 34548c2ecf20Sopenharmony_ci skb->data_len -= shiftlen; 34558c2ecf20Sopenharmony_ci skb->truesize -= shiftlen; 34568c2ecf20Sopenharmony_ci tgt->len += shiftlen; 34578c2ecf20Sopenharmony_ci tgt->data_len += shiftlen; 34588c2ecf20Sopenharmony_ci tgt->truesize += shiftlen; 34598c2ecf20Sopenharmony_ci 34608c2ecf20Sopenharmony_ci return shiftlen; 34618c2ecf20Sopenharmony_ci} 34628c2ecf20Sopenharmony_ci 34638c2ecf20Sopenharmony_ci/** 34648c2ecf20Sopenharmony_ci * skb_prepare_seq_read - Prepare a sequential read of skb data 34658c2ecf20Sopenharmony_ci * @skb: the buffer to read 34668c2ecf20Sopenharmony_ci * @from: lower offset of data to be read 34678c2ecf20Sopenharmony_ci * @to: upper offset of data to be read 34688c2ecf20Sopenharmony_ci * @st: state variable 34698c2ecf20Sopenharmony_ci * 34708c2ecf20Sopenharmony_ci * Initializes the specified state variable. Must be called before 34718c2ecf20Sopenharmony_ci * invoking skb_seq_read() for the first time. 34728c2ecf20Sopenharmony_ci */ 34738c2ecf20Sopenharmony_civoid skb_prepare_seq_read(struct sk_buff *skb, unsigned int from, 34748c2ecf20Sopenharmony_ci unsigned int to, struct skb_seq_state *st) 34758c2ecf20Sopenharmony_ci{ 34768c2ecf20Sopenharmony_ci st->lower_offset = from; 34778c2ecf20Sopenharmony_ci st->upper_offset = to; 34788c2ecf20Sopenharmony_ci st->root_skb = st->cur_skb = skb; 34798c2ecf20Sopenharmony_ci st->frag_idx = st->stepped_offset = 0; 34808c2ecf20Sopenharmony_ci st->frag_data = NULL; 34818c2ecf20Sopenharmony_ci} 34828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_prepare_seq_read); 34838c2ecf20Sopenharmony_ci 34848c2ecf20Sopenharmony_ci/** 34858c2ecf20Sopenharmony_ci * skb_seq_read - Sequentially read skb data 34868c2ecf20Sopenharmony_ci * @consumed: number of bytes consumed by the caller so far 34878c2ecf20Sopenharmony_ci * @data: destination pointer for data to be returned 34888c2ecf20Sopenharmony_ci * @st: state variable 34898c2ecf20Sopenharmony_ci * 34908c2ecf20Sopenharmony_ci * Reads a block of skb data at @consumed relative to the 34918c2ecf20Sopenharmony_ci * lower offset specified to skb_prepare_seq_read(). Assigns 34928c2ecf20Sopenharmony_ci * the head of the data block to @data and returns the length 34938c2ecf20Sopenharmony_ci * of the block or 0 if the end of the skb data or the upper 34948c2ecf20Sopenharmony_ci * offset has been reached. 34958c2ecf20Sopenharmony_ci * 34968c2ecf20Sopenharmony_ci * The caller is not required to consume all of the data 34978c2ecf20Sopenharmony_ci * returned, i.e. @consumed is typically set to the number 34988c2ecf20Sopenharmony_ci * of bytes already consumed and the next call to 34998c2ecf20Sopenharmony_ci * skb_seq_read() will return the remaining part of the block. 35008c2ecf20Sopenharmony_ci * 35018c2ecf20Sopenharmony_ci * Note 1: The size of each block of data returned can be arbitrary, 35028c2ecf20Sopenharmony_ci * this limitation is the cost for zerocopy sequential 35038c2ecf20Sopenharmony_ci * reads of potentially non linear data. 35048c2ecf20Sopenharmony_ci * 35058c2ecf20Sopenharmony_ci * Note 2: Fragment lists within fragments are not implemented 35068c2ecf20Sopenharmony_ci * at the moment, state->root_skb could be replaced with 35078c2ecf20Sopenharmony_ci * a stack for this purpose. 35088c2ecf20Sopenharmony_ci */ 35098c2ecf20Sopenharmony_ciunsigned int skb_seq_read(unsigned int consumed, const u8 **data, 35108c2ecf20Sopenharmony_ci struct skb_seq_state *st) 35118c2ecf20Sopenharmony_ci{ 35128c2ecf20Sopenharmony_ci unsigned int block_limit, abs_offset = consumed + st->lower_offset; 35138c2ecf20Sopenharmony_ci skb_frag_t *frag; 35148c2ecf20Sopenharmony_ci 35158c2ecf20Sopenharmony_ci if (unlikely(abs_offset >= st->upper_offset)) { 35168c2ecf20Sopenharmony_ci if (st->frag_data) { 35178c2ecf20Sopenharmony_ci kunmap_atomic(st->frag_data); 35188c2ecf20Sopenharmony_ci st->frag_data = NULL; 35198c2ecf20Sopenharmony_ci } 35208c2ecf20Sopenharmony_ci return 0; 35218c2ecf20Sopenharmony_ci } 35228c2ecf20Sopenharmony_ci 35238c2ecf20Sopenharmony_cinext_skb: 35248c2ecf20Sopenharmony_ci block_limit = skb_headlen(st->cur_skb) + st->stepped_offset; 35258c2ecf20Sopenharmony_ci 35268c2ecf20Sopenharmony_ci if (abs_offset < block_limit && !st->frag_data) { 35278c2ecf20Sopenharmony_ci *data = st->cur_skb->data + (abs_offset - st->stepped_offset); 35288c2ecf20Sopenharmony_ci return block_limit - abs_offset; 35298c2ecf20Sopenharmony_ci } 35308c2ecf20Sopenharmony_ci 35318c2ecf20Sopenharmony_ci if (st->frag_idx == 0 && !st->frag_data) 35328c2ecf20Sopenharmony_ci st->stepped_offset += skb_headlen(st->cur_skb); 35338c2ecf20Sopenharmony_ci 35348c2ecf20Sopenharmony_ci while (st->frag_idx < skb_shinfo(st->cur_skb)->nr_frags) { 35358c2ecf20Sopenharmony_ci frag = &skb_shinfo(st->cur_skb)->frags[st->frag_idx]; 35368c2ecf20Sopenharmony_ci block_limit = skb_frag_size(frag) + st->stepped_offset; 35378c2ecf20Sopenharmony_ci 35388c2ecf20Sopenharmony_ci if (abs_offset < block_limit) { 35398c2ecf20Sopenharmony_ci if (!st->frag_data) 35408c2ecf20Sopenharmony_ci st->frag_data = kmap_atomic(skb_frag_page(frag)); 35418c2ecf20Sopenharmony_ci 35428c2ecf20Sopenharmony_ci *data = (u8 *) st->frag_data + skb_frag_off(frag) + 35438c2ecf20Sopenharmony_ci (abs_offset - st->stepped_offset); 35448c2ecf20Sopenharmony_ci 35458c2ecf20Sopenharmony_ci return block_limit - abs_offset; 35468c2ecf20Sopenharmony_ci } 35478c2ecf20Sopenharmony_ci 35488c2ecf20Sopenharmony_ci if (st->frag_data) { 35498c2ecf20Sopenharmony_ci kunmap_atomic(st->frag_data); 35508c2ecf20Sopenharmony_ci st->frag_data = NULL; 35518c2ecf20Sopenharmony_ci } 35528c2ecf20Sopenharmony_ci 35538c2ecf20Sopenharmony_ci st->frag_idx++; 35548c2ecf20Sopenharmony_ci st->stepped_offset += skb_frag_size(frag); 35558c2ecf20Sopenharmony_ci } 35568c2ecf20Sopenharmony_ci 35578c2ecf20Sopenharmony_ci if (st->frag_data) { 35588c2ecf20Sopenharmony_ci kunmap_atomic(st->frag_data); 35598c2ecf20Sopenharmony_ci st->frag_data = NULL; 35608c2ecf20Sopenharmony_ci } 35618c2ecf20Sopenharmony_ci 35628c2ecf20Sopenharmony_ci if (st->root_skb == st->cur_skb && skb_has_frag_list(st->root_skb)) { 35638c2ecf20Sopenharmony_ci st->cur_skb = skb_shinfo(st->root_skb)->frag_list; 35648c2ecf20Sopenharmony_ci st->frag_idx = 0; 35658c2ecf20Sopenharmony_ci goto next_skb; 35668c2ecf20Sopenharmony_ci } else if (st->cur_skb->next) { 35678c2ecf20Sopenharmony_ci st->cur_skb = st->cur_skb->next; 35688c2ecf20Sopenharmony_ci st->frag_idx = 0; 35698c2ecf20Sopenharmony_ci goto next_skb; 35708c2ecf20Sopenharmony_ci } 35718c2ecf20Sopenharmony_ci 35728c2ecf20Sopenharmony_ci return 0; 35738c2ecf20Sopenharmony_ci} 35748c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_seq_read); 35758c2ecf20Sopenharmony_ci 35768c2ecf20Sopenharmony_ci/** 35778c2ecf20Sopenharmony_ci * skb_abort_seq_read - Abort a sequential read of skb data 35788c2ecf20Sopenharmony_ci * @st: state variable 35798c2ecf20Sopenharmony_ci * 35808c2ecf20Sopenharmony_ci * Must be called if skb_seq_read() was not called until it 35818c2ecf20Sopenharmony_ci * returned 0. 35828c2ecf20Sopenharmony_ci */ 35838c2ecf20Sopenharmony_civoid skb_abort_seq_read(struct skb_seq_state *st) 35848c2ecf20Sopenharmony_ci{ 35858c2ecf20Sopenharmony_ci if (st->frag_data) 35868c2ecf20Sopenharmony_ci kunmap_atomic(st->frag_data); 35878c2ecf20Sopenharmony_ci} 35888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_abort_seq_read); 35898c2ecf20Sopenharmony_ci 35908c2ecf20Sopenharmony_ci#define TS_SKB_CB(state) ((struct skb_seq_state *) &((state)->cb)) 35918c2ecf20Sopenharmony_ci 35928c2ecf20Sopenharmony_cistatic unsigned int skb_ts_get_next_block(unsigned int offset, const u8 **text, 35938c2ecf20Sopenharmony_ci struct ts_config *conf, 35948c2ecf20Sopenharmony_ci struct ts_state *state) 35958c2ecf20Sopenharmony_ci{ 35968c2ecf20Sopenharmony_ci return skb_seq_read(offset, text, TS_SKB_CB(state)); 35978c2ecf20Sopenharmony_ci} 35988c2ecf20Sopenharmony_ci 35998c2ecf20Sopenharmony_cistatic void skb_ts_finish(struct ts_config *conf, struct ts_state *state) 36008c2ecf20Sopenharmony_ci{ 36018c2ecf20Sopenharmony_ci skb_abort_seq_read(TS_SKB_CB(state)); 36028c2ecf20Sopenharmony_ci} 36038c2ecf20Sopenharmony_ci 36048c2ecf20Sopenharmony_ci/** 36058c2ecf20Sopenharmony_ci * skb_find_text - Find a text pattern in skb data 36068c2ecf20Sopenharmony_ci * @skb: the buffer to look in 36078c2ecf20Sopenharmony_ci * @from: search offset 36088c2ecf20Sopenharmony_ci * @to: search limit 36098c2ecf20Sopenharmony_ci * @config: textsearch configuration 36108c2ecf20Sopenharmony_ci * 36118c2ecf20Sopenharmony_ci * Finds a pattern in the skb data according to the specified 36128c2ecf20Sopenharmony_ci * textsearch configuration. Use textsearch_next() to retrieve 36138c2ecf20Sopenharmony_ci * subsequent occurrences of the pattern. Returns the offset 36148c2ecf20Sopenharmony_ci * to the first occurrence or UINT_MAX if no match was found. 36158c2ecf20Sopenharmony_ci */ 36168c2ecf20Sopenharmony_ciunsigned int skb_find_text(struct sk_buff *skb, unsigned int from, 36178c2ecf20Sopenharmony_ci unsigned int to, struct ts_config *config) 36188c2ecf20Sopenharmony_ci{ 36198c2ecf20Sopenharmony_ci struct ts_state state; 36208c2ecf20Sopenharmony_ci unsigned int ret; 36218c2ecf20Sopenharmony_ci 36228c2ecf20Sopenharmony_ci config->get_next_block = skb_ts_get_next_block; 36238c2ecf20Sopenharmony_ci config->finish = skb_ts_finish; 36248c2ecf20Sopenharmony_ci 36258c2ecf20Sopenharmony_ci skb_prepare_seq_read(skb, from, to, TS_SKB_CB(&state)); 36268c2ecf20Sopenharmony_ci 36278c2ecf20Sopenharmony_ci ret = textsearch_find(config, &state); 36288c2ecf20Sopenharmony_ci return (ret <= to - from ? ret : UINT_MAX); 36298c2ecf20Sopenharmony_ci} 36308c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_find_text); 36318c2ecf20Sopenharmony_ci 36328c2ecf20Sopenharmony_ciint skb_append_pagefrags(struct sk_buff *skb, struct page *page, 36338c2ecf20Sopenharmony_ci int offset, size_t size) 36348c2ecf20Sopenharmony_ci{ 36358c2ecf20Sopenharmony_ci int i = skb_shinfo(skb)->nr_frags; 36368c2ecf20Sopenharmony_ci 36378c2ecf20Sopenharmony_ci if (skb_can_coalesce(skb, i, page, offset)) { 36388c2ecf20Sopenharmony_ci skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], size); 36398c2ecf20Sopenharmony_ci } else if (i < MAX_SKB_FRAGS) { 36408c2ecf20Sopenharmony_ci get_page(page); 36418c2ecf20Sopenharmony_ci skb_fill_page_desc(skb, i, page, offset, size); 36428c2ecf20Sopenharmony_ci } else { 36438c2ecf20Sopenharmony_ci return -EMSGSIZE; 36448c2ecf20Sopenharmony_ci } 36458c2ecf20Sopenharmony_ci 36468c2ecf20Sopenharmony_ci return 0; 36478c2ecf20Sopenharmony_ci} 36488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_append_pagefrags); 36498c2ecf20Sopenharmony_ci 36508c2ecf20Sopenharmony_ci/** 36518c2ecf20Sopenharmony_ci * skb_pull_rcsum - pull skb and update receive checksum 36528c2ecf20Sopenharmony_ci * @skb: buffer to update 36538c2ecf20Sopenharmony_ci * @len: length of data pulled 36548c2ecf20Sopenharmony_ci * 36558c2ecf20Sopenharmony_ci * This function performs an skb_pull on the packet and updates 36568c2ecf20Sopenharmony_ci * the CHECKSUM_COMPLETE checksum. It should be used on 36578c2ecf20Sopenharmony_ci * receive path processing instead of skb_pull unless you know 36588c2ecf20Sopenharmony_ci * that the checksum difference is zero (e.g., a valid IP header) 36598c2ecf20Sopenharmony_ci * or you are setting ip_summed to CHECKSUM_NONE. 36608c2ecf20Sopenharmony_ci */ 36618c2ecf20Sopenharmony_civoid *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) 36628c2ecf20Sopenharmony_ci{ 36638c2ecf20Sopenharmony_ci unsigned char *data = skb->data; 36648c2ecf20Sopenharmony_ci 36658c2ecf20Sopenharmony_ci BUG_ON(len > skb->len); 36668c2ecf20Sopenharmony_ci __skb_pull(skb, len); 36678c2ecf20Sopenharmony_ci skb_postpull_rcsum(skb, data, len); 36688c2ecf20Sopenharmony_ci return skb->data; 36698c2ecf20Sopenharmony_ci} 36708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_pull_rcsum); 36718c2ecf20Sopenharmony_ci 36728c2ecf20Sopenharmony_cistatic inline skb_frag_t skb_head_frag_to_page_desc(struct sk_buff *frag_skb) 36738c2ecf20Sopenharmony_ci{ 36748c2ecf20Sopenharmony_ci skb_frag_t head_frag; 36758c2ecf20Sopenharmony_ci struct page *page; 36768c2ecf20Sopenharmony_ci 36778c2ecf20Sopenharmony_ci page = virt_to_head_page(frag_skb->head); 36788c2ecf20Sopenharmony_ci __skb_frag_set_page(&head_frag, page); 36798c2ecf20Sopenharmony_ci skb_frag_off_set(&head_frag, frag_skb->data - 36808c2ecf20Sopenharmony_ci (unsigned char *)page_address(page)); 36818c2ecf20Sopenharmony_ci skb_frag_size_set(&head_frag, skb_headlen(frag_skb)); 36828c2ecf20Sopenharmony_ci return head_frag; 36838c2ecf20Sopenharmony_ci} 36848c2ecf20Sopenharmony_ci 36858c2ecf20Sopenharmony_cistruct sk_buff *skb_segment_list(struct sk_buff *skb, 36868c2ecf20Sopenharmony_ci netdev_features_t features, 36878c2ecf20Sopenharmony_ci unsigned int offset) 36888c2ecf20Sopenharmony_ci{ 36898c2ecf20Sopenharmony_ci struct sk_buff *list_skb = skb_shinfo(skb)->frag_list; 36908c2ecf20Sopenharmony_ci unsigned int tnl_hlen = skb_tnl_header_len(skb); 36918c2ecf20Sopenharmony_ci unsigned int delta_truesize = 0; 36928c2ecf20Sopenharmony_ci unsigned int delta_len = 0; 36938c2ecf20Sopenharmony_ci struct sk_buff *tail = NULL; 36948c2ecf20Sopenharmony_ci struct sk_buff *nskb, *tmp; 36958c2ecf20Sopenharmony_ci int err; 36968c2ecf20Sopenharmony_ci 36978c2ecf20Sopenharmony_ci skb_push(skb, -skb_network_offset(skb) + offset); 36988c2ecf20Sopenharmony_ci 36998c2ecf20Sopenharmony_ci /* Ensure the head is writeable before touching the shared info */ 37008c2ecf20Sopenharmony_ci err = skb_unclone(skb, GFP_ATOMIC); 37018c2ecf20Sopenharmony_ci if (err) 37028c2ecf20Sopenharmony_ci goto err_linearize; 37038c2ecf20Sopenharmony_ci 37048c2ecf20Sopenharmony_ci skb_shinfo(skb)->frag_list = NULL; 37058c2ecf20Sopenharmony_ci 37068c2ecf20Sopenharmony_ci while (list_skb) { 37078c2ecf20Sopenharmony_ci nskb = list_skb; 37088c2ecf20Sopenharmony_ci list_skb = list_skb->next; 37098c2ecf20Sopenharmony_ci 37108c2ecf20Sopenharmony_ci err = 0; 37118c2ecf20Sopenharmony_ci delta_truesize += nskb->truesize; 37128c2ecf20Sopenharmony_ci if (skb_shared(nskb)) { 37138c2ecf20Sopenharmony_ci tmp = skb_clone(nskb, GFP_ATOMIC); 37148c2ecf20Sopenharmony_ci if (tmp) { 37158c2ecf20Sopenharmony_ci consume_skb(nskb); 37168c2ecf20Sopenharmony_ci nskb = tmp; 37178c2ecf20Sopenharmony_ci err = skb_unclone(nskb, GFP_ATOMIC); 37188c2ecf20Sopenharmony_ci } else { 37198c2ecf20Sopenharmony_ci err = -ENOMEM; 37208c2ecf20Sopenharmony_ci } 37218c2ecf20Sopenharmony_ci } 37228c2ecf20Sopenharmony_ci 37238c2ecf20Sopenharmony_ci if (!tail) 37248c2ecf20Sopenharmony_ci skb->next = nskb; 37258c2ecf20Sopenharmony_ci else 37268c2ecf20Sopenharmony_ci tail->next = nskb; 37278c2ecf20Sopenharmony_ci 37288c2ecf20Sopenharmony_ci if (unlikely(err)) { 37298c2ecf20Sopenharmony_ci nskb->next = list_skb; 37308c2ecf20Sopenharmony_ci goto err_linearize; 37318c2ecf20Sopenharmony_ci } 37328c2ecf20Sopenharmony_ci 37338c2ecf20Sopenharmony_ci tail = nskb; 37348c2ecf20Sopenharmony_ci 37358c2ecf20Sopenharmony_ci delta_len += nskb->len; 37368c2ecf20Sopenharmony_ci 37378c2ecf20Sopenharmony_ci skb_push(nskb, -skb_network_offset(nskb) + offset); 37388c2ecf20Sopenharmony_ci 37398c2ecf20Sopenharmony_ci skb_release_head_state(nskb); 37408c2ecf20Sopenharmony_ci __copy_skb_header(nskb, skb); 37418c2ecf20Sopenharmony_ci 37428c2ecf20Sopenharmony_ci skb_headers_offset_update(nskb, skb_headroom(nskb) - skb_headroom(skb)); 37438c2ecf20Sopenharmony_ci skb_copy_from_linear_data_offset(skb, -tnl_hlen, 37448c2ecf20Sopenharmony_ci nskb->data - tnl_hlen, 37458c2ecf20Sopenharmony_ci offset + tnl_hlen); 37468c2ecf20Sopenharmony_ci 37478c2ecf20Sopenharmony_ci if (skb_needs_linearize(nskb, features) && 37488c2ecf20Sopenharmony_ci __skb_linearize(nskb)) 37498c2ecf20Sopenharmony_ci goto err_linearize; 37508c2ecf20Sopenharmony_ci } 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_ci skb->truesize = skb->truesize - delta_truesize; 37538c2ecf20Sopenharmony_ci skb->data_len = skb->data_len - delta_len; 37548c2ecf20Sopenharmony_ci skb->len = skb->len - delta_len; 37558c2ecf20Sopenharmony_ci 37568c2ecf20Sopenharmony_ci skb_gso_reset(skb); 37578c2ecf20Sopenharmony_ci 37588c2ecf20Sopenharmony_ci skb->prev = tail; 37598c2ecf20Sopenharmony_ci 37608c2ecf20Sopenharmony_ci if (skb_needs_linearize(skb, features) && 37618c2ecf20Sopenharmony_ci __skb_linearize(skb)) 37628c2ecf20Sopenharmony_ci goto err_linearize; 37638c2ecf20Sopenharmony_ci 37648c2ecf20Sopenharmony_ci skb_get(skb); 37658c2ecf20Sopenharmony_ci 37668c2ecf20Sopenharmony_ci return skb; 37678c2ecf20Sopenharmony_ci 37688c2ecf20Sopenharmony_cierr_linearize: 37698c2ecf20Sopenharmony_ci kfree_skb_list(skb->next); 37708c2ecf20Sopenharmony_ci skb->next = NULL; 37718c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 37728c2ecf20Sopenharmony_ci} 37738c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_segment_list); 37748c2ecf20Sopenharmony_ci 37758c2ecf20Sopenharmony_ciint skb_gro_receive_list(struct sk_buff *p, struct sk_buff *skb) 37768c2ecf20Sopenharmony_ci{ 37778c2ecf20Sopenharmony_ci if (unlikely(p->len + skb->len >= 65536)) 37788c2ecf20Sopenharmony_ci return -E2BIG; 37798c2ecf20Sopenharmony_ci 37808c2ecf20Sopenharmony_ci if (NAPI_GRO_CB(p)->last == p) 37818c2ecf20Sopenharmony_ci skb_shinfo(p)->frag_list = skb; 37828c2ecf20Sopenharmony_ci else 37838c2ecf20Sopenharmony_ci NAPI_GRO_CB(p)->last->next = skb; 37848c2ecf20Sopenharmony_ci 37858c2ecf20Sopenharmony_ci skb_pull(skb, skb_gro_offset(skb)); 37868c2ecf20Sopenharmony_ci 37878c2ecf20Sopenharmony_ci NAPI_GRO_CB(p)->last = skb; 37888c2ecf20Sopenharmony_ci NAPI_GRO_CB(p)->count++; 37898c2ecf20Sopenharmony_ci p->data_len += skb->len; 37908c2ecf20Sopenharmony_ci p->truesize += skb->truesize; 37918c2ecf20Sopenharmony_ci p->len += skb->len; 37928c2ecf20Sopenharmony_ci 37938c2ecf20Sopenharmony_ci NAPI_GRO_CB(skb)->same_flow = 1; 37948c2ecf20Sopenharmony_ci 37958c2ecf20Sopenharmony_ci return 0; 37968c2ecf20Sopenharmony_ci} 37978c2ecf20Sopenharmony_ci 37988c2ecf20Sopenharmony_ci/** 37998c2ecf20Sopenharmony_ci * skb_segment - Perform protocol segmentation on skb. 38008c2ecf20Sopenharmony_ci * @head_skb: buffer to segment 38018c2ecf20Sopenharmony_ci * @features: features for the output path (see dev->features) 38028c2ecf20Sopenharmony_ci * 38038c2ecf20Sopenharmony_ci * This function performs segmentation on the given skb. It returns 38048c2ecf20Sopenharmony_ci * a pointer to the first in a list of new skbs for the segments. 38058c2ecf20Sopenharmony_ci * In case of error it returns ERR_PTR(err). 38068c2ecf20Sopenharmony_ci */ 38078c2ecf20Sopenharmony_cistruct sk_buff *skb_segment(struct sk_buff *head_skb, 38088c2ecf20Sopenharmony_ci netdev_features_t features) 38098c2ecf20Sopenharmony_ci{ 38108c2ecf20Sopenharmony_ci struct sk_buff *segs = NULL; 38118c2ecf20Sopenharmony_ci struct sk_buff *tail = NULL; 38128c2ecf20Sopenharmony_ci struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list; 38138c2ecf20Sopenharmony_ci unsigned int mss = skb_shinfo(head_skb)->gso_size; 38148c2ecf20Sopenharmony_ci unsigned int doffset = head_skb->data - skb_mac_header(head_skb); 38158c2ecf20Sopenharmony_ci unsigned int offset = doffset; 38168c2ecf20Sopenharmony_ci unsigned int tnl_hlen = skb_tnl_header_len(head_skb); 38178c2ecf20Sopenharmony_ci unsigned int partial_segs = 0; 38188c2ecf20Sopenharmony_ci unsigned int headroom; 38198c2ecf20Sopenharmony_ci unsigned int len = head_skb->len; 38208c2ecf20Sopenharmony_ci struct sk_buff *frag_skb; 38218c2ecf20Sopenharmony_ci skb_frag_t *frag; 38228c2ecf20Sopenharmony_ci __be16 proto; 38238c2ecf20Sopenharmony_ci bool csum, sg; 38248c2ecf20Sopenharmony_ci int err = -ENOMEM; 38258c2ecf20Sopenharmony_ci int i = 0; 38268c2ecf20Sopenharmony_ci int nfrags, pos; 38278c2ecf20Sopenharmony_ci 38288c2ecf20Sopenharmony_ci if ((skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY) && 38298c2ecf20Sopenharmony_ci mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb)) { 38308c2ecf20Sopenharmony_ci struct sk_buff *check_skb; 38318c2ecf20Sopenharmony_ci 38328c2ecf20Sopenharmony_ci for (check_skb = list_skb; check_skb; check_skb = check_skb->next) { 38338c2ecf20Sopenharmony_ci if (skb_headlen(check_skb) && !check_skb->head_frag) { 38348c2ecf20Sopenharmony_ci /* gso_size is untrusted, and we have a frag_list with 38358c2ecf20Sopenharmony_ci * a linear non head_frag item. 38368c2ecf20Sopenharmony_ci * 38378c2ecf20Sopenharmony_ci * If head_skb's headlen does not fit requested gso_size, 38388c2ecf20Sopenharmony_ci * it means that the frag_list members do NOT terminate 38398c2ecf20Sopenharmony_ci * on exact gso_size boundaries. Hence we cannot perform 38408c2ecf20Sopenharmony_ci * skb_frag_t page sharing. Therefore we must fallback to 38418c2ecf20Sopenharmony_ci * copying the frag_list skbs; we do so by disabling SG. 38428c2ecf20Sopenharmony_ci */ 38438c2ecf20Sopenharmony_ci features &= ~NETIF_F_SG; 38448c2ecf20Sopenharmony_ci break; 38458c2ecf20Sopenharmony_ci } 38468c2ecf20Sopenharmony_ci } 38478c2ecf20Sopenharmony_ci } 38488c2ecf20Sopenharmony_ci 38498c2ecf20Sopenharmony_ci __skb_push(head_skb, doffset); 38508c2ecf20Sopenharmony_ci proto = skb_network_protocol(head_skb, NULL); 38518c2ecf20Sopenharmony_ci if (unlikely(!proto)) 38528c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 38538c2ecf20Sopenharmony_ci 38548c2ecf20Sopenharmony_ci sg = !!(features & NETIF_F_SG); 38558c2ecf20Sopenharmony_ci csum = !!can_checksum_protocol(features, proto); 38568c2ecf20Sopenharmony_ci 38578c2ecf20Sopenharmony_ci if (sg && csum && (mss != GSO_BY_FRAGS)) { 38588c2ecf20Sopenharmony_ci if (!(features & NETIF_F_GSO_PARTIAL)) { 38598c2ecf20Sopenharmony_ci struct sk_buff *iter; 38608c2ecf20Sopenharmony_ci unsigned int frag_len; 38618c2ecf20Sopenharmony_ci 38628c2ecf20Sopenharmony_ci if (!list_skb || 38638c2ecf20Sopenharmony_ci !net_gso_ok(features, skb_shinfo(head_skb)->gso_type)) 38648c2ecf20Sopenharmony_ci goto normal; 38658c2ecf20Sopenharmony_ci 38668c2ecf20Sopenharmony_ci /* If we get here then all the required 38678c2ecf20Sopenharmony_ci * GSO features except frag_list are supported. 38688c2ecf20Sopenharmony_ci * Try to split the SKB to multiple GSO SKBs 38698c2ecf20Sopenharmony_ci * with no frag_list. 38708c2ecf20Sopenharmony_ci * Currently we can do that only when the buffers don't 38718c2ecf20Sopenharmony_ci * have a linear part and all the buffers except 38728c2ecf20Sopenharmony_ci * the last are of the same length. 38738c2ecf20Sopenharmony_ci */ 38748c2ecf20Sopenharmony_ci frag_len = list_skb->len; 38758c2ecf20Sopenharmony_ci skb_walk_frags(head_skb, iter) { 38768c2ecf20Sopenharmony_ci if (frag_len != iter->len && iter->next) 38778c2ecf20Sopenharmony_ci goto normal; 38788c2ecf20Sopenharmony_ci if (skb_headlen(iter) && !iter->head_frag) 38798c2ecf20Sopenharmony_ci goto normal; 38808c2ecf20Sopenharmony_ci 38818c2ecf20Sopenharmony_ci len -= iter->len; 38828c2ecf20Sopenharmony_ci } 38838c2ecf20Sopenharmony_ci 38848c2ecf20Sopenharmony_ci if (len != frag_len) 38858c2ecf20Sopenharmony_ci goto normal; 38868c2ecf20Sopenharmony_ci } 38878c2ecf20Sopenharmony_ci 38888c2ecf20Sopenharmony_ci /* GSO partial only requires that we trim off any excess that 38898c2ecf20Sopenharmony_ci * doesn't fit into an MSS sized block, so take care of that 38908c2ecf20Sopenharmony_ci * now. 38918c2ecf20Sopenharmony_ci * Cap len to not accidentally hit GSO_BY_FRAGS. 38928c2ecf20Sopenharmony_ci */ 38938c2ecf20Sopenharmony_ci partial_segs = min(len, GSO_BY_FRAGS - 1U) / mss; 38948c2ecf20Sopenharmony_ci if (partial_segs > 1) 38958c2ecf20Sopenharmony_ci mss *= partial_segs; 38968c2ecf20Sopenharmony_ci else 38978c2ecf20Sopenharmony_ci partial_segs = 0; 38988c2ecf20Sopenharmony_ci } 38998c2ecf20Sopenharmony_ci 39008c2ecf20Sopenharmony_cinormal: 39018c2ecf20Sopenharmony_ci headroom = skb_headroom(head_skb); 39028c2ecf20Sopenharmony_ci pos = skb_headlen(head_skb); 39038c2ecf20Sopenharmony_ci 39048c2ecf20Sopenharmony_ci if (skb_orphan_frags(head_skb, GFP_ATOMIC)) 39058c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 39068c2ecf20Sopenharmony_ci 39078c2ecf20Sopenharmony_ci nfrags = skb_shinfo(head_skb)->nr_frags; 39088c2ecf20Sopenharmony_ci frag = skb_shinfo(head_skb)->frags; 39098c2ecf20Sopenharmony_ci frag_skb = head_skb; 39108c2ecf20Sopenharmony_ci 39118c2ecf20Sopenharmony_ci do { 39128c2ecf20Sopenharmony_ci struct sk_buff *nskb; 39138c2ecf20Sopenharmony_ci skb_frag_t *nskb_frag; 39148c2ecf20Sopenharmony_ci int hsize; 39158c2ecf20Sopenharmony_ci int size; 39168c2ecf20Sopenharmony_ci 39178c2ecf20Sopenharmony_ci if (unlikely(mss == GSO_BY_FRAGS)) { 39188c2ecf20Sopenharmony_ci len = list_skb->len; 39198c2ecf20Sopenharmony_ci } else { 39208c2ecf20Sopenharmony_ci len = head_skb->len - offset; 39218c2ecf20Sopenharmony_ci if (len > mss) 39228c2ecf20Sopenharmony_ci len = mss; 39238c2ecf20Sopenharmony_ci } 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_ci hsize = skb_headlen(head_skb) - offset; 39268c2ecf20Sopenharmony_ci if (hsize < 0) 39278c2ecf20Sopenharmony_ci hsize = 0; 39288c2ecf20Sopenharmony_ci if (hsize > len || !sg) 39298c2ecf20Sopenharmony_ci hsize = len; 39308c2ecf20Sopenharmony_ci 39318c2ecf20Sopenharmony_ci if (!hsize && i >= nfrags && skb_headlen(list_skb) && 39328c2ecf20Sopenharmony_ci (skb_headlen(list_skb) == len || sg)) { 39338c2ecf20Sopenharmony_ci BUG_ON(skb_headlen(list_skb) > len); 39348c2ecf20Sopenharmony_ci 39358c2ecf20Sopenharmony_ci nskb = skb_clone(list_skb, GFP_ATOMIC); 39368c2ecf20Sopenharmony_ci if (unlikely(!nskb)) 39378c2ecf20Sopenharmony_ci goto err; 39388c2ecf20Sopenharmony_ci 39398c2ecf20Sopenharmony_ci i = 0; 39408c2ecf20Sopenharmony_ci nfrags = skb_shinfo(list_skb)->nr_frags; 39418c2ecf20Sopenharmony_ci frag = skb_shinfo(list_skb)->frags; 39428c2ecf20Sopenharmony_ci frag_skb = list_skb; 39438c2ecf20Sopenharmony_ci pos += skb_headlen(list_skb); 39448c2ecf20Sopenharmony_ci 39458c2ecf20Sopenharmony_ci while (pos < offset + len) { 39468c2ecf20Sopenharmony_ci BUG_ON(i >= nfrags); 39478c2ecf20Sopenharmony_ci 39488c2ecf20Sopenharmony_ci size = skb_frag_size(frag); 39498c2ecf20Sopenharmony_ci if (pos + size > offset + len) 39508c2ecf20Sopenharmony_ci break; 39518c2ecf20Sopenharmony_ci 39528c2ecf20Sopenharmony_ci i++; 39538c2ecf20Sopenharmony_ci pos += size; 39548c2ecf20Sopenharmony_ci frag++; 39558c2ecf20Sopenharmony_ci } 39568c2ecf20Sopenharmony_ci 39578c2ecf20Sopenharmony_ci list_skb = list_skb->next; 39588c2ecf20Sopenharmony_ci 39598c2ecf20Sopenharmony_ci if (unlikely(pskb_trim(nskb, len))) { 39608c2ecf20Sopenharmony_ci kfree_skb(nskb); 39618c2ecf20Sopenharmony_ci goto err; 39628c2ecf20Sopenharmony_ci } 39638c2ecf20Sopenharmony_ci 39648c2ecf20Sopenharmony_ci hsize = skb_end_offset(nskb); 39658c2ecf20Sopenharmony_ci if (skb_cow_head(nskb, doffset + headroom)) { 39668c2ecf20Sopenharmony_ci kfree_skb(nskb); 39678c2ecf20Sopenharmony_ci goto err; 39688c2ecf20Sopenharmony_ci } 39698c2ecf20Sopenharmony_ci 39708c2ecf20Sopenharmony_ci nskb->truesize += skb_end_offset(nskb) - hsize; 39718c2ecf20Sopenharmony_ci skb_release_head_state(nskb); 39728c2ecf20Sopenharmony_ci __skb_push(nskb, doffset); 39738c2ecf20Sopenharmony_ci } else { 39748c2ecf20Sopenharmony_ci nskb = __alloc_skb(hsize + doffset + headroom, 39758c2ecf20Sopenharmony_ci GFP_ATOMIC, skb_alloc_rx_flag(head_skb), 39768c2ecf20Sopenharmony_ci NUMA_NO_NODE); 39778c2ecf20Sopenharmony_ci 39788c2ecf20Sopenharmony_ci if (unlikely(!nskb)) 39798c2ecf20Sopenharmony_ci goto err; 39808c2ecf20Sopenharmony_ci 39818c2ecf20Sopenharmony_ci skb_reserve(nskb, headroom); 39828c2ecf20Sopenharmony_ci __skb_put(nskb, doffset); 39838c2ecf20Sopenharmony_ci } 39848c2ecf20Sopenharmony_ci 39858c2ecf20Sopenharmony_ci if (segs) 39868c2ecf20Sopenharmony_ci tail->next = nskb; 39878c2ecf20Sopenharmony_ci else 39888c2ecf20Sopenharmony_ci segs = nskb; 39898c2ecf20Sopenharmony_ci tail = nskb; 39908c2ecf20Sopenharmony_ci 39918c2ecf20Sopenharmony_ci __copy_skb_header(nskb, head_skb); 39928c2ecf20Sopenharmony_ci 39938c2ecf20Sopenharmony_ci skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); 39948c2ecf20Sopenharmony_ci skb_reset_mac_len(nskb); 39958c2ecf20Sopenharmony_ci 39968c2ecf20Sopenharmony_ci skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, 39978c2ecf20Sopenharmony_ci nskb->data - tnl_hlen, 39988c2ecf20Sopenharmony_ci doffset + tnl_hlen); 39998c2ecf20Sopenharmony_ci 40008c2ecf20Sopenharmony_ci if (nskb->len == len + doffset) 40018c2ecf20Sopenharmony_ci goto perform_csum_check; 40028c2ecf20Sopenharmony_ci 40038c2ecf20Sopenharmony_ci if (!sg) { 40048c2ecf20Sopenharmony_ci if (!csum) { 40058c2ecf20Sopenharmony_ci if (!nskb->remcsum_offload) 40068c2ecf20Sopenharmony_ci nskb->ip_summed = CHECKSUM_NONE; 40078c2ecf20Sopenharmony_ci SKB_GSO_CB(nskb)->csum = 40088c2ecf20Sopenharmony_ci skb_copy_and_csum_bits(head_skb, offset, 40098c2ecf20Sopenharmony_ci skb_put(nskb, 40108c2ecf20Sopenharmony_ci len), 40118c2ecf20Sopenharmony_ci len); 40128c2ecf20Sopenharmony_ci SKB_GSO_CB(nskb)->csum_start = 40138c2ecf20Sopenharmony_ci skb_headroom(nskb) + doffset; 40148c2ecf20Sopenharmony_ci } else { 40158c2ecf20Sopenharmony_ci if (skb_copy_bits(head_skb, offset, skb_put(nskb, len), len)) 40168c2ecf20Sopenharmony_ci goto err; 40178c2ecf20Sopenharmony_ci } 40188c2ecf20Sopenharmony_ci continue; 40198c2ecf20Sopenharmony_ci } 40208c2ecf20Sopenharmony_ci 40218c2ecf20Sopenharmony_ci nskb_frag = skb_shinfo(nskb)->frags; 40228c2ecf20Sopenharmony_ci 40238c2ecf20Sopenharmony_ci skb_copy_from_linear_data_offset(head_skb, offset, 40248c2ecf20Sopenharmony_ci skb_put(nskb, hsize), hsize); 40258c2ecf20Sopenharmony_ci 40268c2ecf20Sopenharmony_ci skb_shinfo(nskb)->tx_flags |= skb_shinfo(head_skb)->tx_flags & 40278c2ecf20Sopenharmony_ci SKBTX_SHARED_FRAG; 40288c2ecf20Sopenharmony_ci 40298c2ecf20Sopenharmony_ci if (skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC)) 40308c2ecf20Sopenharmony_ci goto err; 40318c2ecf20Sopenharmony_ci 40328c2ecf20Sopenharmony_ci while (pos < offset + len) { 40338c2ecf20Sopenharmony_ci if (i >= nfrags) { 40348c2ecf20Sopenharmony_ci if (skb_orphan_frags(list_skb, GFP_ATOMIC) || 40358c2ecf20Sopenharmony_ci skb_zerocopy_clone(nskb, list_skb, 40368c2ecf20Sopenharmony_ci GFP_ATOMIC)) 40378c2ecf20Sopenharmony_ci goto err; 40388c2ecf20Sopenharmony_ci 40398c2ecf20Sopenharmony_ci i = 0; 40408c2ecf20Sopenharmony_ci nfrags = skb_shinfo(list_skb)->nr_frags; 40418c2ecf20Sopenharmony_ci frag = skb_shinfo(list_skb)->frags; 40428c2ecf20Sopenharmony_ci frag_skb = list_skb; 40438c2ecf20Sopenharmony_ci if (!skb_headlen(list_skb)) { 40448c2ecf20Sopenharmony_ci BUG_ON(!nfrags); 40458c2ecf20Sopenharmony_ci } else { 40468c2ecf20Sopenharmony_ci BUG_ON(!list_skb->head_frag); 40478c2ecf20Sopenharmony_ci 40488c2ecf20Sopenharmony_ci /* to make room for head_frag. */ 40498c2ecf20Sopenharmony_ci i--; 40508c2ecf20Sopenharmony_ci frag--; 40518c2ecf20Sopenharmony_ci } 40528c2ecf20Sopenharmony_ci 40538c2ecf20Sopenharmony_ci list_skb = list_skb->next; 40548c2ecf20Sopenharmony_ci } 40558c2ecf20Sopenharmony_ci 40568c2ecf20Sopenharmony_ci if (unlikely(skb_shinfo(nskb)->nr_frags >= 40578c2ecf20Sopenharmony_ci MAX_SKB_FRAGS)) { 40588c2ecf20Sopenharmony_ci net_warn_ratelimited( 40598c2ecf20Sopenharmony_ci "skb_segment: too many frags: %u %u\n", 40608c2ecf20Sopenharmony_ci pos, mss); 40618c2ecf20Sopenharmony_ci err = -EINVAL; 40628c2ecf20Sopenharmony_ci goto err; 40638c2ecf20Sopenharmony_ci } 40648c2ecf20Sopenharmony_ci 40658c2ecf20Sopenharmony_ci *nskb_frag = (i < 0) ? skb_head_frag_to_page_desc(frag_skb) : *frag; 40668c2ecf20Sopenharmony_ci __skb_frag_ref(nskb_frag); 40678c2ecf20Sopenharmony_ci size = skb_frag_size(nskb_frag); 40688c2ecf20Sopenharmony_ci 40698c2ecf20Sopenharmony_ci if (pos < offset) { 40708c2ecf20Sopenharmony_ci skb_frag_off_add(nskb_frag, offset - pos); 40718c2ecf20Sopenharmony_ci skb_frag_size_sub(nskb_frag, offset - pos); 40728c2ecf20Sopenharmony_ci } 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci skb_shinfo(nskb)->nr_frags++; 40758c2ecf20Sopenharmony_ci 40768c2ecf20Sopenharmony_ci if (pos + size <= offset + len) { 40778c2ecf20Sopenharmony_ci i++; 40788c2ecf20Sopenharmony_ci frag++; 40798c2ecf20Sopenharmony_ci pos += size; 40808c2ecf20Sopenharmony_ci } else { 40818c2ecf20Sopenharmony_ci skb_frag_size_sub(nskb_frag, pos + size - (offset + len)); 40828c2ecf20Sopenharmony_ci goto skip_fraglist; 40838c2ecf20Sopenharmony_ci } 40848c2ecf20Sopenharmony_ci 40858c2ecf20Sopenharmony_ci nskb_frag++; 40868c2ecf20Sopenharmony_ci } 40878c2ecf20Sopenharmony_ci 40888c2ecf20Sopenharmony_ciskip_fraglist: 40898c2ecf20Sopenharmony_ci nskb->data_len = len - hsize; 40908c2ecf20Sopenharmony_ci nskb->len += nskb->data_len; 40918c2ecf20Sopenharmony_ci nskb->truesize += nskb->data_len; 40928c2ecf20Sopenharmony_ci 40938c2ecf20Sopenharmony_ciperform_csum_check: 40948c2ecf20Sopenharmony_ci if (!csum) { 40958c2ecf20Sopenharmony_ci if (skb_has_shared_frag(nskb) && 40968c2ecf20Sopenharmony_ci __skb_linearize(nskb)) 40978c2ecf20Sopenharmony_ci goto err; 40988c2ecf20Sopenharmony_ci 40998c2ecf20Sopenharmony_ci if (!nskb->remcsum_offload) 41008c2ecf20Sopenharmony_ci nskb->ip_summed = CHECKSUM_NONE; 41018c2ecf20Sopenharmony_ci SKB_GSO_CB(nskb)->csum = 41028c2ecf20Sopenharmony_ci skb_checksum(nskb, doffset, 41038c2ecf20Sopenharmony_ci nskb->len - doffset, 0); 41048c2ecf20Sopenharmony_ci SKB_GSO_CB(nskb)->csum_start = 41058c2ecf20Sopenharmony_ci skb_headroom(nskb) + doffset; 41068c2ecf20Sopenharmony_ci } 41078c2ecf20Sopenharmony_ci } while ((offset += len) < head_skb->len); 41088c2ecf20Sopenharmony_ci 41098c2ecf20Sopenharmony_ci /* Some callers want to get the end of the list. 41108c2ecf20Sopenharmony_ci * Put it in segs->prev to avoid walking the list. 41118c2ecf20Sopenharmony_ci * (see validate_xmit_skb_list() for example) 41128c2ecf20Sopenharmony_ci */ 41138c2ecf20Sopenharmony_ci segs->prev = tail; 41148c2ecf20Sopenharmony_ci 41158c2ecf20Sopenharmony_ci if (partial_segs) { 41168c2ecf20Sopenharmony_ci struct sk_buff *iter; 41178c2ecf20Sopenharmony_ci int type = skb_shinfo(head_skb)->gso_type; 41188c2ecf20Sopenharmony_ci unsigned short gso_size = skb_shinfo(head_skb)->gso_size; 41198c2ecf20Sopenharmony_ci 41208c2ecf20Sopenharmony_ci /* Update type to add partial and then remove dodgy if set */ 41218c2ecf20Sopenharmony_ci type |= (features & NETIF_F_GSO_PARTIAL) / NETIF_F_GSO_PARTIAL * SKB_GSO_PARTIAL; 41228c2ecf20Sopenharmony_ci type &= ~SKB_GSO_DODGY; 41238c2ecf20Sopenharmony_ci 41248c2ecf20Sopenharmony_ci /* Update GSO info and prepare to start updating headers on 41258c2ecf20Sopenharmony_ci * our way back down the stack of protocols. 41268c2ecf20Sopenharmony_ci */ 41278c2ecf20Sopenharmony_ci for (iter = segs; iter; iter = iter->next) { 41288c2ecf20Sopenharmony_ci skb_shinfo(iter)->gso_size = gso_size; 41298c2ecf20Sopenharmony_ci skb_shinfo(iter)->gso_segs = partial_segs; 41308c2ecf20Sopenharmony_ci skb_shinfo(iter)->gso_type = type; 41318c2ecf20Sopenharmony_ci SKB_GSO_CB(iter)->data_offset = skb_headroom(iter) + doffset; 41328c2ecf20Sopenharmony_ci } 41338c2ecf20Sopenharmony_ci 41348c2ecf20Sopenharmony_ci if (tail->len - doffset <= gso_size) 41358c2ecf20Sopenharmony_ci skb_shinfo(tail)->gso_size = 0; 41368c2ecf20Sopenharmony_ci else if (tail != segs) 41378c2ecf20Sopenharmony_ci skb_shinfo(tail)->gso_segs = DIV_ROUND_UP(tail->len - doffset, gso_size); 41388c2ecf20Sopenharmony_ci } 41398c2ecf20Sopenharmony_ci 41408c2ecf20Sopenharmony_ci /* Following permits correct backpressure, for protocols 41418c2ecf20Sopenharmony_ci * using skb_set_owner_w(). 41428c2ecf20Sopenharmony_ci * Idea is to tranfert ownership from head_skb to last segment. 41438c2ecf20Sopenharmony_ci */ 41448c2ecf20Sopenharmony_ci if (head_skb->destructor == sock_wfree) { 41458c2ecf20Sopenharmony_ci swap(tail->truesize, head_skb->truesize); 41468c2ecf20Sopenharmony_ci swap(tail->destructor, head_skb->destructor); 41478c2ecf20Sopenharmony_ci swap(tail->sk, head_skb->sk); 41488c2ecf20Sopenharmony_ci } 41498c2ecf20Sopenharmony_ci return segs; 41508c2ecf20Sopenharmony_ci 41518c2ecf20Sopenharmony_cierr: 41528c2ecf20Sopenharmony_ci kfree_skb_list(segs); 41538c2ecf20Sopenharmony_ci return ERR_PTR(err); 41548c2ecf20Sopenharmony_ci} 41558c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_segment); 41568c2ecf20Sopenharmony_ci 41578c2ecf20Sopenharmony_ciint skb_gro_receive(struct sk_buff *p, struct sk_buff *skb) 41588c2ecf20Sopenharmony_ci{ 41598c2ecf20Sopenharmony_ci struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb); 41608c2ecf20Sopenharmony_ci unsigned int offset = skb_gro_offset(skb); 41618c2ecf20Sopenharmony_ci unsigned int headlen = skb_headlen(skb); 41628c2ecf20Sopenharmony_ci unsigned int len = skb_gro_len(skb); 41638c2ecf20Sopenharmony_ci unsigned int delta_truesize; 41648c2ecf20Sopenharmony_ci struct sk_buff *lp; 41658c2ecf20Sopenharmony_ci 41668c2ecf20Sopenharmony_ci if (unlikely(p->len + len >= 65536 || NAPI_GRO_CB(skb)->flush)) 41678c2ecf20Sopenharmony_ci return -E2BIG; 41688c2ecf20Sopenharmony_ci 41698c2ecf20Sopenharmony_ci lp = NAPI_GRO_CB(p)->last; 41708c2ecf20Sopenharmony_ci pinfo = skb_shinfo(lp); 41718c2ecf20Sopenharmony_ci 41728c2ecf20Sopenharmony_ci if (headlen <= offset) { 41738c2ecf20Sopenharmony_ci skb_frag_t *frag; 41748c2ecf20Sopenharmony_ci skb_frag_t *frag2; 41758c2ecf20Sopenharmony_ci int i = skbinfo->nr_frags; 41768c2ecf20Sopenharmony_ci int nr_frags = pinfo->nr_frags + i; 41778c2ecf20Sopenharmony_ci 41788c2ecf20Sopenharmony_ci if (nr_frags > MAX_SKB_FRAGS) 41798c2ecf20Sopenharmony_ci goto merge; 41808c2ecf20Sopenharmony_ci 41818c2ecf20Sopenharmony_ci offset -= headlen; 41828c2ecf20Sopenharmony_ci pinfo->nr_frags = nr_frags; 41838c2ecf20Sopenharmony_ci skbinfo->nr_frags = 0; 41848c2ecf20Sopenharmony_ci 41858c2ecf20Sopenharmony_ci frag = pinfo->frags + nr_frags; 41868c2ecf20Sopenharmony_ci frag2 = skbinfo->frags + i; 41878c2ecf20Sopenharmony_ci do { 41888c2ecf20Sopenharmony_ci *--frag = *--frag2; 41898c2ecf20Sopenharmony_ci } while (--i); 41908c2ecf20Sopenharmony_ci 41918c2ecf20Sopenharmony_ci skb_frag_off_add(frag, offset); 41928c2ecf20Sopenharmony_ci skb_frag_size_sub(frag, offset); 41938c2ecf20Sopenharmony_ci 41948c2ecf20Sopenharmony_ci /* all fragments truesize : remove (head size + sk_buff) */ 41958c2ecf20Sopenharmony_ci delta_truesize = skb->truesize - 41968c2ecf20Sopenharmony_ci SKB_TRUESIZE(skb_end_offset(skb)); 41978c2ecf20Sopenharmony_ci 41988c2ecf20Sopenharmony_ci skb->truesize -= skb->data_len; 41998c2ecf20Sopenharmony_ci skb->len -= skb->data_len; 42008c2ecf20Sopenharmony_ci skb->data_len = 0; 42018c2ecf20Sopenharmony_ci 42028c2ecf20Sopenharmony_ci NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE; 42038c2ecf20Sopenharmony_ci goto done; 42048c2ecf20Sopenharmony_ci } else if (skb->head_frag) { 42058c2ecf20Sopenharmony_ci int nr_frags = pinfo->nr_frags; 42068c2ecf20Sopenharmony_ci skb_frag_t *frag = pinfo->frags + nr_frags; 42078c2ecf20Sopenharmony_ci struct page *page = virt_to_head_page(skb->head); 42088c2ecf20Sopenharmony_ci unsigned int first_size = headlen - offset; 42098c2ecf20Sopenharmony_ci unsigned int first_offset; 42108c2ecf20Sopenharmony_ci 42118c2ecf20Sopenharmony_ci if (nr_frags + 1 + skbinfo->nr_frags > MAX_SKB_FRAGS) 42128c2ecf20Sopenharmony_ci goto merge; 42138c2ecf20Sopenharmony_ci 42148c2ecf20Sopenharmony_ci first_offset = skb->data - 42158c2ecf20Sopenharmony_ci (unsigned char *)page_address(page) + 42168c2ecf20Sopenharmony_ci offset; 42178c2ecf20Sopenharmony_ci 42188c2ecf20Sopenharmony_ci pinfo->nr_frags = nr_frags + 1 + skbinfo->nr_frags; 42198c2ecf20Sopenharmony_ci 42208c2ecf20Sopenharmony_ci __skb_frag_set_page(frag, page); 42218c2ecf20Sopenharmony_ci skb_frag_off_set(frag, first_offset); 42228c2ecf20Sopenharmony_ci skb_frag_size_set(frag, first_size); 42238c2ecf20Sopenharmony_ci 42248c2ecf20Sopenharmony_ci memcpy(frag + 1, skbinfo->frags, sizeof(*frag) * skbinfo->nr_frags); 42258c2ecf20Sopenharmony_ci /* We dont need to clear skbinfo->nr_frags here */ 42268c2ecf20Sopenharmony_ci 42278c2ecf20Sopenharmony_ci delta_truesize = skb->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff)); 42288c2ecf20Sopenharmony_ci NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD; 42298c2ecf20Sopenharmony_ci goto done; 42308c2ecf20Sopenharmony_ci } 42318c2ecf20Sopenharmony_ci 42328c2ecf20Sopenharmony_cimerge: 42338c2ecf20Sopenharmony_ci delta_truesize = skb->truesize; 42348c2ecf20Sopenharmony_ci if (offset > headlen) { 42358c2ecf20Sopenharmony_ci unsigned int eat = offset - headlen; 42368c2ecf20Sopenharmony_ci 42378c2ecf20Sopenharmony_ci skb_frag_off_add(&skbinfo->frags[0], eat); 42388c2ecf20Sopenharmony_ci skb_frag_size_sub(&skbinfo->frags[0], eat); 42398c2ecf20Sopenharmony_ci skb->data_len -= eat; 42408c2ecf20Sopenharmony_ci skb->len -= eat; 42418c2ecf20Sopenharmony_ci offset = headlen; 42428c2ecf20Sopenharmony_ci } 42438c2ecf20Sopenharmony_ci 42448c2ecf20Sopenharmony_ci __skb_pull(skb, offset); 42458c2ecf20Sopenharmony_ci 42468c2ecf20Sopenharmony_ci if (NAPI_GRO_CB(p)->last == p) 42478c2ecf20Sopenharmony_ci skb_shinfo(p)->frag_list = skb; 42488c2ecf20Sopenharmony_ci else 42498c2ecf20Sopenharmony_ci NAPI_GRO_CB(p)->last->next = skb; 42508c2ecf20Sopenharmony_ci NAPI_GRO_CB(p)->last = skb; 42518c2ecf20Sopenharmony_ci __skb_header_release(skb); 42528c2ecf20Sopenharmony_ci lp = p; 42538c2ecf20Sopenharmony_ci 42548c2ecf20Sopenharmony_cidone: 42558c2ecf20Sopenharmony_ci NAPI_GRO_CB(p)->count++; 42568c2ecf20Sopenharmony_ci p->data_len += len; 42578c2ecf20Sopenharmony_ci p->truesize += delta_truesize; 42588c2ecf20Sopenharmony_ci p->len += len; 42598c2ecf20Sopenharmony_ci if (lp != p) { 42608c2ecf20Sopenharmony_ci lp->data_len += len; 42618c2ecf20Sopenharmony_ci lp->truesize += delta_truesize; 42628c2ecf20Sopenharmony_ci lp->len += len; 42638c2ecf20Sopenharmony_ci } 42648c2ecf20Sopenharmony_ci NAPI_GRO_CB(skb)->same_flow = 1; 42658c2ecf20Sopenharmony_ci return 0; 42668c2ecf20Sopenharmony_ci} 42678c2ecf20Sopenharmony_ci 42688c2ecf20Sopenharmony_ci#ifdef CONFIG_SKB_EXTENSIONS 42698c2ecf20Sopenharmony_ci#define SKB_EXT_ALIGN_VALUE 8 42708c2ecf20Sopenharmony_ci#define SKB_EXT_CHUNKSIZEOF(x) (ALIGN((sizeof(x)), SKB_EXT_ALIGN_VALUE) / SKB_EXT_ALIGN_VALUE) 42718c2ecf20Sopenharmony_ci 42728c2ecf20Sopenharmony_cistatic const u8 skb_ext_type_len[] = { 42738c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 42748c2ecf20Sopenharmony_ci [SKB_EXT_BRIDGE_NF] = SKB_EXT_CHUNKSIZEOF(struct nf_bridge_info), 42758c2ecf20Sopenharmony_ci#endif 42768c2ecf20Sopenharmony_ci#ifdef CONFIG_XFRM 42778c2ecf20Sopenharmony_ci [SKB_EXT_SEC_PATH] = SKB_EXT_CHUNKSIZEOF(struct sec_path), 42788c2ecf20Sopenharmony_ci#endif 42798c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) 42808c2ecf20Sopenharmony_ci [TC_SKB_EXT] = SKB_EXT_CHUNKSIZEOF(struct tc_skb_ext), 42818c2ecf20Sopenharmony_ci#endif 42828c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP) 42838c2ecf20Sopenharmony_ci [SKB_EXT_MPTCP] = SKB_EXT_CHUNKSIZEOF(struct mptcp_ext), 42848c2ecf20Sopenharmony_ci#endif 42858c2ecf20Sopenharmony_ci}; 42868c2ecf20Sopenharmony_ci 42878c2ecf20Sopenharmony_cistatic __always_inline unsigned int skb_ext_total_length(void) 42888c2ecf20Sopenharmony_ci{ 42898c2ecf20Sopenharmony_ci return SKB_EXT_CHUNKSIZEOF(struct skb_ext) + 42908c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 42918c2ecf20Sopenharmony_ci skb_ext_type_len[SKB_EXT_BRIDGE_NF] + 42928c2ecf20Sopenharmony_ci#endif 42938c2ecf20Sopenharmony_ci#ifdef CONFIG_XFRM 42948c2ecf20Sopenharmony_ci skb_ext_type_len[SKB_EXT_SEC_PATH] + 42958c2ecf20Sopenharmony_ci#endif 42968c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) 42978c2ecf20Sopenharmony_ci skb_ext_type_len[TC_SKB_EXT] + 42988c2ecf20Sopenharmony_ci#endif 42998c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP) 43008c2ecf20Sopenharmony_ci skb_ext_type_len[SKB_EXT_MPTCP] + 43018c2ecf20Sopenharmony_ci#endif 43028c2ecf20Sopenharmony_ci 0; 43038c2ecf20Sopenharmony_ci} 43048c2ecf20Sopenharmony_ci 43058c2ecf20Sopenharmony_cistatic void skb_extensions_init(void) 43068c2ecf20Sopenharmony_ci{ 43078c2ecf20Sopenharmony_ci BUILD_BUG_ON(SKB_EXT_NUM >= 8); 43088c2ecf20Sopenharmony_ci BUILD_BUG_ON(skb_ext_total_length() > 255); 43098c2ecf20Sopenharmony_ci 43108c2ecf20Sopenharmony_ci skbuff_ext_cache = kmem_cache_create("skbuff_ext_cache", 43118c2ecf20Sopenharmony_ci SKB_EXT_ALIGN_VALUE * skb_ext_total_length(), 43128c2ecf20Sopenharmony_ci 0, 43138c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN|SLAB_PANIC, 43148c2ecf20Sopenharmony_ci NULL); 43158c2ecf20Sopenharmony_ci} 43168c2ecf20Sopenharmony_ci#else 43178c2ecf20Sopenharmony_cistatic void skb_extensions_init(void) {} 43188c2ecf20Sopenharmony_ci#endif 43198c2ecf20Sopenharmony_ci 43208c2ecf20Sopenharmony_civoid __init skb_init(void) 43218c2ecf20Sopenharmony_ci{ 43228c2ecf20Sopenharmony_ci skbuff_head_cache = kmem_cache_create_usercopy("skbuff_head_cache", 43238c2ecf20Sopenharmony_ci sizeof(struct sk_buff), 43248c2ecf20Sopenharmony_ci 0, 43258c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN|SLAB_PANIC, 43268c2ecf20Sopenharmony_ci offsetof(struct sk_buff, cb), 43278c2ecf20Sopenharmony_ci sizeof_field(struct sk_buff, cb), 43288c2ecf20Sopenharmony_ci NULL); 43298c2ecf20Sopenharmony_ci skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache", 43308c2ecf20Sopenharmony_ci sizeof(struct sk_buff_fclones), 43318c2ecf20Sopenharmony_ci 0, 43328c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN|SLAB_PANIC, 43338c2ecf20Sopenharmony_ci NULL); 43348c2ecf20Sopenharmony_ci skb_extensions_init(); 43358c2ecf20Sopenharmony_ci} 43368c2ecf20Sopenharmony_ci 43378c2ecf20Sopenharmony_cistatic int 43388c2ecf20Sopenharmony_ci__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len, 43398c2ecf20Sopenharmony_ci unsigned int recursion_level) 43408c2ecf20Sopenharmony_ci{ 43418c2ecf20Sopenharmony_ci int start = skb_headlen(skb); 43428c2ecf20Sopenharmony_ci int i, copy = start - offset; 43438c2ecf20Sopenharmony_ci struct sk_buff *frag_iter; 43448c2ecf20Sopenharmony_ci int elt = 0; 43458c2ecf20Sopenharmony_ci 43468c2ecf20Sopenharmony_ci if (unlikely(recursion_level >= 24)) 43478c2ecf20Sopenharmony_ci return -EMSGSIZE; 43488c2ecf20Sopenharmony_ci 43498c2ecf20Sopenharmony_ci if (copy > 0) { 43508c2ecf20Sopenharmony_ci if (copy > len) 43518c2ecf20Sopenharmony_ci copy = len; 43528c2ecf20Sopenharmony_ci sg_set_buf(sg, skb->data + offset, copy); 43538c2ecf20Sopenharmony_ci elt++; 43548c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 43558c2ecf20Sopenharmony_ci return elt; 43568c2ecf20Sopenharmony_ci offset += copy; 43578c2ecf20Sopenharmony_ci } 43588c2ecf20Sopenharmony_ci 43598c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 43608c2ecf20Sopenharmony_ci int end; 43618c2ecf20Sopenharmony_ci 43628c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 43638c2ecf20Sopenharmony_ci 43648c2ecf20Sopenharmony_ci end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]); 43658c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 43668c2ecf20Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 43678c2ecf20Sopenharmony_ci if (unlikely(elt && sg_is_last(&sg[elt - 1]))) 43688c2ecf20Sopenharmony_ci return -EMSGSIZE; 43698c2ecf20Sopenharmony_ci 43708c2ecf20Sopenharmony_ci if (copy > len) 43718c2ecf20Sopenharmony_ci copy = len; 43728c2ecf20Sopenharmony_ci sg_set_page(&sg[elt], skb_frag_page(frag), copy, 43738c2ecf20Sopenharmony_ci skb_frag_off(frag) + offset - start); 43748c2ecf20Sopenharmony_ci elt++; 43758c2ecf20Sopenharmony_ci if (!(len -= copy)) 43768c2ecf20Sopenharmony_ci return elt; 43778c2ecf20Sopenharmony_ci offset += copy; 43788c2ecf20Sopenharmony_ci } 43798c2ecf20Sopenharmony_ci start = end; 43808c2ecf20Sopenharmony_ci } 43818c2ecf20Sopenharmony_ci 43828c2ecf20Sopenharmony_ci skb_walk_frags(skb, frag_iter) { 43838c2ecf20Sopenharmony_ci int end, ret; 43848c2ecf20Sopenharmony_ci 43858c2ecf20Sopenharmony_ci WARN_ON(start > offset + len); 43868c2ecf20Sopenharmony_ci 43878c2ecf20Sopenharmony_ci end = start + frag_iter->len; 43888c2ecf20Sopenharmony_ci if ((copy = end - offset) > 0) { 43898c2ecf20Sopenharmony_ci if (unlikely(elt && sg_is_last(&sg[elt - 1]))) 43908c2ecf20Sopenharmony_ci return -EMSGSIZE; 43918c2ecf20Sopenharmony_ci 43928c2ecf20Sopenharmony_ci if (copy > len) 43938c2ecf20Sopenharmony_ci copy = len; 43948c2ecf20Sopenharmony_ci ret = __skb_to_sgvec(frag_iter, sg+elt, offset - start, 43958c2ecf20Sopenharmony_ci copy, recursion_level + 1); 43968c2ecf20Sopenharmony_ci if (unlikely(ret < 0)) 43978c2ecf20Sopenharmony_ci return ret; 43988c2ecf20Sopenharmony_ci elt += ret; 43998c2ecf20Sopenharmony_ci if ((len -= copy) == 0) 44008c2ecf20Sopenharmony_ci return elt; 44018c2ecf20Sopenharmony_ci offset += copy; 44028c2ecf20Sopenharmony_ci } 44038c2ecf20Sopenharmony_ci start = end; 44048c2ecf20Sopenharmony_ci } 44058c2ecf20Sopenharmony_ci BUG_ON(len); 44068c2ecf20Sopenharmony_ci return elt; 44078c2ecf20Sopenharmony_ci} 44088c2ecf20Sopenharmony_ci 44098c2ecf20Sopenharmony_ci/** 44108c2ecf20Sopenharmony_ci * skb_to_sgvec - Fill a scatter-gather list from a socket buffer 44118c2ecf20Sopenharmony_ci * @skb: Socket buffer containing the buffers to be mapped 44128c2ecf20Sopenharmony_ci * @sg: The scatter-gather list to map into 44138c2ecf20Sopenharmony_ci * @offset: The offset into the buffer's contents to start mapping 44148c2ecf20Sopenharmony_ci * @len: Length of buffer space to be mapped 44158c2ecf20Sopenharmony_ci * 44168c2ecf20Sopenharmony_ci * Fill the specified scatter-gather list with mappings/pointers into a 44178c2ecf20Sopenharmony_ci * region of the buffer space attached to a socket buffer. Returns either 44188c2ecf20Sopenharmony_ci * the number of scatterlist items used, or -EMSGSIZE if the contents 44198c2ecf20Sopenharmony_ci * could not fit. 44208c2ecf20Sopenharmony_ci */ 44218c2ecf20Sopenharmony_ciint skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) 44228c2ecf20Sopenharmony_ci{ 44238c2ecf20Sopenharmony_ci int nsg = __skb_to_sgvec(skb, sg, offset, len, 0); 44248c2ecf20Sopenharmony_ci 44258c2ecf20Sopenharmony_ci if (nsg <= 0) 44268c2ecf20Sopenharmony_ci return nsg; 44278c2ecf20Sopenharmony_ci 44288c2ecf20Sopenharmony_ci sg_mark_end(&sg[nsg - 1]); 44298c2ecf20Sopenharmony_ci 44308c2ecf20Sopenharmony_ci return nsg; 44318c2ecf20Sopenharmony_ci} 44328c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_to_sgvec); 44338c2ecf20Sopenharmony_ci 44348c2ecf20Sopenharmony_ci/* As compared with skb_to_sgvec, skb_to_sgvec_nomark only map skb to given 44358c2ecf20Sopenharmony_ci * sglist without mark the sg which contain last skb data as the end. 44368c2ecf20Sopenharmony_ci * So the caller can mannipulate sg list as will when padding new data after 44378c2ecf20Sopenharmony_ci * the first call without calling sg_unmark_end to expend sg list. 44388c2ecf20Sopenharmony_ci * 44398c2ecf20Sopenharmony_ci * Scenario to use skb_to_sgvec_nomark: 44408c2ecf20Sopenharmony_ci * 1. sg_init_table 44418c2ecf20Sopenharmony_ci * 2. skb_to_sgvec_nomark(payload1) 44428c2ecf20Sopenharmony_ci * 3. skb_to_sgvec_nomark(payload2) 44438c2ecf20Sopenharmony_ci * 44448c2ecf20Sopenharmony_ci * This is equivalent to: 44458c2ecf20Sopenharmony_ci * 1. sg_init_table 44468c2ecf20Sopenharmony_ci * 2. skb_to_sgvec(payload1) 44478c2ecf20Sopenharmony_ci * 3. sg_unmark_end 44488c2ecf20Sopenharmony_ci * 4. skb_to_sgvec(payload2) 44498c2ecf20Sopenharmony_ci * 44508c2ecf20Sopenharmony_ci * When mapping mutilple payload conditionally, skb_to_sgvec_nomark 44518c2ecf20Sopenharmony_ci * is more preferable. 44528c2ecf20Sopenharmony_ci */ 44538c2ecf20Sopenharmony_ciint skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg, 44548c2ecf20Sopenharmony_ci int offset, int len) 44558c2ecf20Sopenharmony_ci{ 44568c2ecf20Sopenharmony_ci return __skb_to_sgvec(skb, sg, offset, len, 0); 44578c2ecf20Sopenharmony_ci} 44588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_to_sgvec_nomark); 44598c2ecf20Sopenharmony_ci 44608c2ecf20Sopenharmony_ci 44618c2ecf20Sopenharmony_ci 44628c2ecf20Sopenharmony_ci/** 44638c2ecf20Sopenharmony_ci * skb_cow_data - Check that a socket buffer's data buffers are writable 44648c2ecf20Sopenharmony_ci * @skb: The socket buffer to check. 44658c2ecf20Sopenharmony_ci * @tailbits: Amount of trailing space to be added 44668c2ecf20Sopenharmony_ci * @trailer: Returned pointer to the skb where the @tailbits space begins 44678c2ecf20Sopenharmony_ci * 44688c2ecf20Sopenharmony_ci * Make sure that the data buffers attached to a socket buffer are 44698c2ecf20Sopenharmony_ci * writable. If they are not, private copies are made of the data buffers 44708c2ecf20Sopenharmony_ci * and the socket buffer is set to use these instead. 44718c2ecf20Sopenharmony_ci * 44728c2ecf20Sopenharmony_ci * If @tailbits is given, make sure that there is space to write @tailbits 44738c2ecf20Sopenharmony_ci * bytes of data beyond current end of socket buffer. @trailer will be 44748c2ecf20Sopenharmony_ci * set to point to the skb in which this space begins. 44758c2ecf20Sopenharmony_ci * 44768c2ecf20Sopenharmony_ci * The number of scatterlist elements required to completely map the 44778c2ecf20Sopenharmony_ci * COW'd and extended socket buffer will be returned. 44788c2ecf20Sopenharmony_ci */ 44798c2ecf20Sopenharmony_ciint skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) 44808c2ecf20Sopenharmony_ci{ 44818c2ecf20Sopenharmony_ci int copyflag; 44828c2ecf20Sopenharmony_ci int elt; 44838c2ecf20Sopenharmony_ci struct sk_buff *skb1, **skb_p; 44848c2ecf20Sopenharmony_ci 44858c2ecf20Sopenharmony_ci /* If skb is cloned or its head is paged, reallocate 44868c2ecf20Sopenharmony_ci * head pulling out all the pages (pages are considered not writable 44878c2ecf20Sopenharmony_ci * at the moment even if they are anonymous). 44888c2ecf20Sopenharmony_ci */ 44898c2ecf20Sopenharmony_ci if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) && 44908c2ecf20Sopenharmony_ci !__pskb_pull_tail(skb, __skb_pagelen(skb))) 44918c2ecf20Sopenharmony_ci return -ENOMEM; 44928c2ecf20Sopenharmony_ci 44938c2ecf20Sopenharmony_ci /* Easy case. Most of packets will go this way. */ 44948c2ecf20Sopenharmony_ci if (!skb_has_frag_list(skb)) { 44958c2ecf20Sopenharmony_ci /* A little of trouble, not enough of space for trailer. 44968c2ecf20Sopenharmony_ci * This should not happen, when stack is tuned to generate 44978c2ecf20Sopenharmony_ci * good frames. OK, on miss we reallocate and reserve even more 44988c2ecf20Sopenharmony_ci * space, 128 bytes is fair. */ 44998c2ecf20Sopenharmony_ci 45008c2ecf20Sopenharmony_ci if (skb_tailroom(skb) < tailbits && 45018c2ecf20Sopenharmony_ci pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC)) 45028c2ecf20Sopenharmony_ci return -ENOMEM; 45038c2ecf20Sopenharmony_ci 45048c2ecf20Sopenharmony_ci /* Voila! */ 45058c2ecf20Sopenharmony_ci *trailer = skb; 45068c2ecf20Sopenharmony_ci return 1; 45078c2ecf20Sopenharmony_ci } 45088c2ecf20Sopenharmony_ci 45098c2ecf20Sopenharmony_ci /* Misery. We are in troubles, going to mincer fragments... */ 45108c2ecf20Sopenharmony_ci 45118c2ecf20Sopenharmony_ci elt = 1; 45128c2ecf20Sopenharmony_ci skb_p = &skb_shinfo(skb)->frag_list; 45138c2ecf20Sopenharmony_ci copyflag = 0; 45148c2ecf20Sopenharmony_ci 45158c2ecf20Sopenharmony_ci while ((skb1 = *skb_p) != NULL) { 45168c2ecf20Sopenharmony_ci int ntail = 0; 45178c2ecf20Sopenharmony_ci 45188c2ecf20Sopenharmony_ci /* The fragment is partially pulled by someone, 45198c2ecf20Sopenharmony_ci * this can happen on input. Copy it and everything 45208c2ecf20Sopenharmony_ci * after it. */ 45218c2ecf20Sopenharmony_ci 45228c2ecf20Sopenharmony_ci if (skb_shared(skb1)) 45238c2ecf20Sopenharmony_ci copyflag = 1; 45248c2ecf20Sopenharmony_ci 45258c2ecf20Sopenharmony_ci /* If the skb is the last, worry about trailer. */ 45268c2ecf20Sopenharmony_ci 45278c2ecf20Sopenharmony_ci if (skb1->next == NULL && tailbits) { 45288c2ecf20Sopenharmony_ci if (skb_shinfo(skb1)->nr_frags || 45298c2ecf20Sopenharmony_ci skb_has_frag_list(skb1) || 45308c2ecf20Sopenharmony_ci skb_tailroom(skb1) < tailbits) 45318c2ecf20Sopenharmony_ci ntail = tailbits + 128; 45328c2ecf20Sopenharmony_ci } 45338c2ecf20Sopenharmony_ci 45348c2ecf20Sopenharmony_ci if (copyflag || 45358c2ecf20Sopenharmony_ci skb_cloned(skb1) || 45368c2ecf20Sopenharmony_ci ntail || 45378c2ecf20Sopenharmony_ci skb_shinfo(skb1)->nr_frags || 45388c2ecf20Sopenharmony_ci skb_has_frag_list(skb1)) { 45398c2ecf20Sopenharmony_ci struct sk_buff *skb2; 45408c2ecf20Sopenharmony_ci 45418c2ecf20Sopenharmony_ci /* Fuck, we are miserable poor guys... */ 45428c2ecf20Sopenharmony_ci if (ntail == 0) 45438c2ecf20Sopenharmony_ci skb2 = skb_copy(skb1, GFP_ATOMIC); 45448c2ecf20Sopenharmony_ci else 45458c2ecf20Sopenharmony_ci skb2 = skb_copy_expand(skb1, 45468c2ecf20Sopenharmony_ci skb_headroom(skb1), 45478c2ecf20Sopenharmony_ci ntail, 45488c2ecf20Sopenharmony_ci GFP_ATOMIC); 45498c2ecf20Sopenharmony_ci if (unlikely(skb2 == NULL)) 45508c2ecf20Sopenharmony_ci return -ENOMEM; 45518c2ecf20Sopenharmony_ci 45528c2ecf20Sopenharmony_ci if (skb1->sk) 45538c2ecf20Sopenharmony_ci skb_set_owner_w(skb2, skb1->sk); 45548c2ecf20Sopenharmony_ci 45558c2ecf20Sopenharmony_ci /* Looking around. Are we still alive? 45568c2ecf20Sopenharmony_ci * OK, link new skb, drop old one */ 45578c2ecf20Sopenharmony_ci 45588c2ecf20Sopenharmony_ci skb2->next = skb1->next; 45598c2ecf20Sopenharmony_ci *skb_p = skb2; 45608c2ecf20Sopenharmony_ci kfree_skb(skb1); 45618c2ecf20Sopenharmony_ci skb1 = skb2; 45628c2ecf20Sopenharmony_ci } 45638c2ecf20Sopenharmony_ci elt++; 45648c2ecf20Sopenharmony_ci *trailer = skb1; 45658c2ecf20Sopenharmony_ci skb_p = &skb1->next; 45668c2ecf20Sopenharmony_ci } 45678c2ecf20Sopenharmony_ci 45688c2ecf20Sopenharmony_ci return elt; 45698c2ecf20Sopenharmony_ci} 45708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_cow_data); 45718c2ecf20Sopenharmony_ci 45728c2ecf20Sopenharmony_cistatic void sock_rmem_free(struct sk_buff *skb) 45738c2ecf20Sopenharmony_ci{ 45748c2ecf20Sopenharmony_ci struct sock *sk = skb->sk; 45758c2ecf20Sopenharmony_ci 45768c2ecf20Sopenharmony_ci atomic_sub(skb->truesize, &sk->sk_rmem_alloc); 45778c2ecf20Sopenharmony_ci} 45788c2ecf20Sopenharmony_ci 45798c2ecf20Sopenharmony_cistatic void skb_set_err_queue(struct sk_buff *skb) 45808c2ecf20Sopenharmony_ci{ 45818c2ecf20Sopenharmony_ci /* pkt_type of skbs received on local sockets is never PACKET_OUTGOING. 45828c2ecf20Sopenharmony_ci * So, it is safe to (mis)use it to mark skbs on the error queue. 45838c2ecf20Sopenharmony_ci */ 45848c2ecf20Sopenharmony_ci skb->pkt_type = PACKET_OUTGOING; 45858c2ecf20Sopenharmony_ci BUILD_BUG_ON(PACKET_OUTGOING == 0); 45868c2ecf20Sopenharmony_ci} 45878c2ecf20Sopenharmony_ci 45888c2ecf20Sopenharmony_ci/* 45898c2ecf20Sopenharmony_ci * Note: We dont mem charge error packets (no sk_forward_alloc changes) 45908c2ecf20Sopenharmony_ci */ 45918c2ecf20Sopenharmony_ciint sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) 45928c2ecf20Sopenharmony_ci{ 45938c2ecf20Sopenharmony_ci if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= 45948c2ecf20Sopenharmony_ci (unsigned int)READ_ONCE(sk->sk_rcvbuf)) 45958c2ecf20Sopenharmony_ci return -ENOMEM; 45968c2ecf20Sopenharmony_ci 45978c2ecf20Sopenharmony_ci skb_orphan(skb); 45988c2ecf20Sopenharmony_ci skb->sk = sk; 45998c2ecf20Sopenharmony_ci skb->destructor = sock_rmem_free; 46008c2ecf20Sopenharmony_ci atomic_add(skb->truesize, &sk->sk_rmem_alloc); 46018c2ecf20Sopenharmony_ci skb_set_err_queue(skb); 46028c2ecf20Sopenharmony_ci 46038c2ecf20Sopenharmony_ci /* before exiting rcu section, make sure dst is refcounted */ 46048c2ecf20Sopenharmony_ci skb_dst_force(skb); 46058c2ecf20Sopenharmony_ci 46068c2ecf20Sopenharmony_ci skb_queue_tail(&sk->sk_error_queue, skb); 46078c2ecf20Sopenharmony_ci if (!sock_flag(sk, SOCK_DEAD)) 46088c2ecf20Sopenharmony_ci sk->sk_error_report(sk); 46098c2ecf20Sopenharmony_ci return 0; 46108c2ecf20Sopenharmony_ci} 46118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_queue_err_skb); 46128c2ecf20Sopenharmony_ci 46138c2ecf20Sopenharmony_cistatic bool is_icmp_err_skb(const struct sk_buff *skb) 46148c2ecf20Sopenharmony_ci{ 46158c2ecf20Sopenharmony_ci return skb && (SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP || 46168c2ecf20Sopenharmony_ci SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP6); 46178c2ecf20Sopenharmony_ci} 46188c2ecf20Sopenharmony_ci 46198c2ecf20Sopenharmony_cistruct sk_buff *sock_dequeue_err_skb(struct sock *sk) 46208c2ecf20Sopenharmony_ci{ 46218c2ecf20Sopenharmony_ci struct sk_buff_head *q = &sk->sk_error_queue; 46228c2ecf20Sopenharmony_ci struct sk_buff *skb, *skb_next = NULL; 46238c2ecf20Sopenharmony_ci bool icmp_next = false; 46248c2ecf20Sopenharmony_ci unsigned long flags; 46258c2ecf20Sopenharmony_ci 46268c2ecf20Sopenharmony_ci spin_lock_irqsave(&q->lock, flags); 46278c2ecf20Sopenharmony_ci skb = __skb_dequeue(q); 46288c2ecf20Sopenharmony_ci if (skb && (skb_next = skb_peek(q))) { 46298c2ecf20Sopenharmony_ci icmp_next = is_icmp_err_skb(skb_next); 46308c2ecf20Sopenharmony_ci if (icmp_next) 46318c2ecf20Sopenharmony_ci sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_errno; 46328c2ecf20Sopenharmony_ci } 46338c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&q->lock, flags); 46348c2ecf20Sopenharmony_ci 46358c2ecf20Sopenharmony_ci if (is_icmp_err_skb(skb) && !icmp_next) 46368c2ecf20Sopenharmony_ci sk->sk_err = 0; 46378c2ecf20Sopenharmony_ci 46388c2ecf20Sopenharmony_ci if (skb_next) 46398c2ecf20Sopenharmony_ci sk->sk_error_report(sk); 46408c2ecf20Sopenharmony_ci 46418c2ecf20Sopenharmony_ci return skb; 46428c2ecf20Sopenharmony_ci} 46438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_dequeue_err_skb); 46448c2ecf20Sopenharmony_ci 46458c2ecf20Sopenharmony_ci/** 46468c2ecf20Sopenharmony_ci * skb_clone_sk - create clone of skb, and take reference to socket 46478c2ecf20Sopenharmony_ci * @skb: the skb to clone 46488c2ecf20Sopenharmony_ci * 46498c2ecf20Sopenharmony_ci * This function creates a clone of a buffer that holds a reference on 46508c2ecf20Sopenharmony_ci * sk_refcnt. Buffers created via this function are meant to be 46518c2ecf20Sopenharmony_ci * returned using sock_queue_err_skb, or free via kfree_skb. 46528c2ecf20Sopenharmony_ci * 46538c2ecf20Sopenharmony_ci * When passing buffers allocated with this function to sock_queue_err_skb 46548c2ecf20Sopenharmony_ci * it is necessary to wrap the call with sock_hold/sock_put in order to 46558c2ecf20Sopenharmony_ci * prevent the socket from being released prior to being enqueued on 46568c2ecf20Sopenharmony_ci * the sk_error_queue. 46578c2ecf20Sopenharmony_ci */ 46588c2ecf20Sopenharmony_cistruct sk_buff *skb_clone_sk(struct sk_buff *skb) 46598c2ecf20Sopenharmony_ci{ 46608c2ecf20Sopenharmony_ci struct sock *sk = skb->sk; 46618c2ecf20Sopenharmony_ci struct sk_buff *clone; 46628c2ecf20Sopenharmony_ci 46638c2ecf20Sopenharmony_ci if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt)) 46648c2ecf20Sopenharmony_ci return NULL; 46658c2ecf20Sopenharmony_ci 46668c2ecf20Sopenharmony_ci clone = skb_clone(skb, GFP_ATOMIC); 46678c2ecf20Sopenharmony_ci if (!clone) { 46688c2ecf20Sopenharmony_ci sock_put(sk); 46698c2ecf20Sopenharmony_ci return NULL; 46708c2ecf20Sopenharmony_ci } 46718c2ecf20Sopenharmony_ci 46728c2ecf20Sopenharmony_ci clone->sk = sk; 46738c2ecf20Sopenharmony_ci clone->destructor = sock_efree; 46748c2ecf20Sopenharmony_ci 46758c2ecf20Sopenharmony_ci return clone; 46768c2ecf20Sopenharmony_ci} 46778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_clone_sk); 46788c2ecf20Sopenharmony_ci 46798c2ecf20Sopenharmony_cistatic void __skb_complete_tx_timestamp(struct sk_buff *skb, 46808c2ecf20Sopenharmony_ci struct sock *sk, 46818c2ecf20Sopenharmony_ci int tstype, 46828c2ecf20Sopenharmony_ci bool opt_stats) 46838c2ecf20Sopenharmony_ci{ 46848c2ecf20Sopenharmony_ci struct sock_exterr_skb *serr; 46858c2ecf20Sopenharmony_ci int err; 46868c2ecf20Sopenharmony_ci 46878c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct sock_exterr_skb) > sizeof(skb->cb)); 46888c2ecf20Sopenharmony_ci 46898c2ecf20Sopenharmony_ci serr = SKB_EXT_ERR(skb); 46908c2ecf20Sopenharmony_ci memset(serr, 0, sizeof(*serr)); 46918c2ecf20Sopenharmony_ci serr->ee.ee_errno = ENOMSG; 46928c2ecf20Sopenharmony_ci serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; 46938c2ecf20Sopenharmony_ci serr->ee.ee_info = tstype; 46948c2ecf20Sopenharmony_ci serr->opt_stats = opt_stats; 46958c2ecf20Sopenharmony_ci serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0; 46968c2ecf20Sopenharmony_ci if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { 46978c2ecf20Sopenharmony_ci serr->ee.ee_data = skb_shinfo(skb)->tskey; 46988c2ecf20Sopenharmony_ci if (sk->sk_protocol == IPPROTO_TCP && 46998c2ecf20Sopenharmony_ci sk->sk_type == SOCK_STREAM) 47008c2ecf20Sopenharmony_ci serr->ee.ee_data -= sk->sk_tskey; 47018c2ecf20Sopenharmony_ci } 47028c2ecf20Sopenharmony_ci 47038c2ecf20Sopenharmony_ci err = sock_queue_err_skb(sk, skb); 47048c2ecf20Sopenharmony_ci 47058c2ecf20Sopenharmony_ci if (err) 47068c2ecf20Sopenharmony_ci kfree_skb(skb); 47078c2ecf20Sopenharmony_ci} 47088c2ecf20Sopenharmony_ci 47098c2ecf20Sopenharmony_cistatic bool skb_may_tx_timestamp(struct sock *sk, bool tsonly) 47108c2ecf20Sopenharmony_ci{ 47118c2ecf20Sopenharmony_ci bool ret; 47128c2ecf20Sopenharmony_ci 47138c2ecf20Sopenharmony_ci if (likely(READ_ONCE(sysctl_tstamp_allow_data) || tsonly)) 47148c2ecf20Sopenharmony_ci return true; 47158c2ecf20Sopenharmony_ci 47168c2ecf20Sopenharmony_ci read_lock_bh(&sk->sk_callback_lock); 47178c2ecf20Sopenharmony_ci ret = sk->sk_socket && sk->sk_socket->file && 47188c2ecf20Sopenharmony_ci file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW); 47198c2ecf20Sopenharmony_ci read_unlock_bh(&sk->sk_callback_lock); 47208c2ecf20Sopenharmony_ci return ret; 47218c2ecf20Sopenharmony_ci} 47228c2ecf20Sopenharmony_ci 47238c2ecf20Sopenharmony_civoid skb_complete_tx_timestamp(struct sk_buff *skb, 47248c2ecf20Sopenharmony_ci struct skb_shared_hwtstamps *hwtstamps) 47258c2ecf20Sopenharmony_ci{ 47268c2ecf20Sopenharmony_ci struct sock *sk = skb->sk; 47278c2ecf20Sopenharmony_ci 47288c2ecf20Sopenharmony_ci if (!skb_may_tx_timestamp(sk, false)) 47298c2ecf20Sopenharmony_ci goto err; 47308c2ecf20Sopenharmony_ci 47318c2ecf20Sopenharmony_ci /* Take a reference to prevent skb_orphan() from freeing the socket, 47328c2ecf20Sopenharmony_ci * but only if the socket refcount is not zero. 47338c2ecf20Sopenharmony_ci */ 47348c2ecf20Sopenharmony_ci if (likely(refcount_inc_not_zero(&sk->sk_refcnt))) { 47358c2ecf20Sopenharmony_ci *skb_hwtstamps(skb) = *hwtstamps; 47368c2ecf20Sopenharmony_ci __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND, false); 47378c2ecf20Sopenharmony_ci sock_put(sk); 47388c2ecf20Sopenharmony_ci return; 47398c2ecf20Sopenharmony_ci } 47408c2ecf20Sopenharmony_ci 47418c2ecf20Sopenharmony_cierr: 47428c2ecf20Sopenharmony_ci kfree_skb(skb); 47438c2ecf20Sopenharmony_ci} 47448c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_complete_tx_timestamp); 47458c2ecf20Sopenharmony_ci 47468c2ecf20Sopenharmony_civoid __skb_tstamp_tx(struct sk_buff *orig_skb, 47478c2ecf20Sopenharmony_ci struct skb_shared_hwtstamps *hwtstamps, 47488c2ecf20Sopenharmony_ci struct sock *sk, int tstype) 47498c2ecf20Sopenharmony_ci{ 47508c2ecf20Sopenharmony_ci struct sk_buff *skb; 47518c2ecf20Sopenharmony_ci bool tsonly, opt_stats = false; 47528c2ecf20Sopenharmony_ci 47538c2ecf20Sopenharmony_ci if (!sk) 47548c2ecf20Sopenharmony_ci return; 47558c2ecf20Sopenharmony_ci 47568c2ecf20Sopenharmony_ci if (!hwtstamps && !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TX_SWHW) && 47578c2ecf20Sopenharmony_ci skb_shinfo(orig_skb)->tx_flags & SKBTX_IN_PROGRESS) 47588c2ecf20Sopenharmony_ci return; 47598c2ecf20Sopenharmony_ci 47608c2ecf20Sopenharmony_ci tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY; 47618c2ecf20Sopenharmony_ci if (!skb_may_tx_timestamp(sk, tsonly)) 47628c2ecf20Sopenharmony_ci return; 47638c2ecf20Sopenharmony_ci 47648c2ecf20Sopenharmony_ci if (tsonly) { 47658c2ecf20Sopenharmony_ci#ifdef CONFIG_INET 47668c2ecf20Sopenharmony_ci if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) && 47678c2ecf20Sopenharmony_ci sk->sk_protocol == IPPROTO_TCP && 47688c2ecf20Sopenharmony_ci sk->sk_type == SOCK_STREAM) { 47698c2ecf20Sopenharmony_ci skb = tcp_get_timestamping_opt_stats(sk, orig_skb); 47708c2ecf20Sopenharmony_ci opt_stats = true; 47718c2ecf20Sopenharmony_ci } else 47728c2ecf20Sopenharmony_ci#endif 47738c2ecf20Sopenharmony_ci skb = alloc_skb(0, GFP_ATOMIC); 47748c2ecf20Sopenharmony_ci } else { 47758c2ecf20Sopenharmony_ci skb = skb_clone(orig_skb, GFP_ATOMIC); 47768c2ecf20Sopenharmony_ci 47778c2ecf20Sopenharmony_ci if (skb_orphan_frags_rx(skb, GFP_ATOMIC)) { 47788c2ecf20Sopenharmony_ci kfree_skb(skb); 47798c2ecf20Sopenharmony_ci return; 47808c2ecf20Sopenharmony_ci } 47818c2ecf20Sopenharmony_ci } 47828c2ecf20Sopenharmony_ci if (!skb) 47838c2ecf20Sopenharmony_ci return; 47848c2ecf20Sopenharmony_ci 47858c2ecf20Sopenharmony_ci if (tsonly) { 47868c2ecf20Sopenharmony_ci skb_shinfo(skb)->tx_flags |= skb_shinfo(orig_skb)->tx_flags & 47878c2ecf20Sopenharmony_ci SKBTX_ANY_TSTAMP; 47888c2ecf20Sopenharmony_ci skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey; 47898c2ecf20Sopenharmony_ci } 47908c2ecf20Sopenharmony_ci 47918c2ecf20Sopenharmony_ci if (hwtstamps) 47928c2ecf20Sopenharmony_ci *skb_hwtstamps(skb) = *hwtstamps; 47938c2ecf20Sopenharmony_ci else 47948c2ecf20Sopenharmony_ci skb->tstamp = ktime_get_real(); 47958c2ecf20Sopenharmony_ci 47968c2ecf20Sopenharmony_ci __skb_complete_tx_timestamp(skb, sk, tstype, opt_stats); 47978c2ecf20Sopenharmony_ci} 47988c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__skb_tstamp_tx); 47998c2ecf20Sopenharmony_ci 48008c2ecf20Sopenharmony_civoid skb_tstamp_tx(struct sk_buff *orig_skb, 48018c2ecf20Sopenharmony_ci struct skb_shared_hwtstamps *hwtstamps) 48028c2ecf20Sopenharmony_ci{ 48038c2ecf20Sopenharmony_ci return __skb_tstamp_tx(orig_skb, hwtstamps, orig_skb->sk, 48048c2ecf20Sopenharmony_ci SCM_TSTAMP_SND); 48058c2ecf20Sopenharmony_ci} 48068c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_tstamp_tx); 48078c2ecf20Sopenharmony_ci 48088c2ecf20Sopenharmony_civoid skb_complete_wifi_ack(struct sk_buff *skb, bool acked) 48098c2ecf20Sopenharmony_ci{ 48108c2ecf20Sopenharmony_ci struct sock *sk = skb->sk; 48118c2ecf20Sopenharmony_ci struct sock_exterr_skb *serr; 48128c2ecf20Sopenharmony_ci int err = 1; 48138c2ecf20Sopenharmony_ci 48148c2ecf20Sopenharmony_ci skb->wifi_acked_valid = 1; 48158c2ecf20Sopenharmony_ci skb->wifi_acked = acked; 48168c2ecf20Sopenharmony_ci 48178c2ecf20Sopenharmony_ci serr = SKB_EXT_ERR(skb); 48188c2ecf20Sopenharmony_ci memset(serr, 0, sizeof(*serr)); 48198c2ecf20Sopenharmony_ci serr->ee.ee_errno = ENOMSG; 48208c2ecf20Sopenharmony_ci serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS; 48218c2ecf20Sopenharmony_ci 48228c2ecf20Sopenharmony_ci /* Take a reference to prevent skb_orphan() from freeing the socket, 48238c2ecf20Sopenharmony_ci * but only if the socket refcount is not zero. 48248c2ecf20Sopenharmony_ci */ 48258c2ecf20Sopenharmony_ci if (likely(refcount_inc_not_zero(&sk->sk_refcnt))) { 48268c2ecf20Sopenharmony_ci err = sock_queue_err_skb(sk, skb); 48278c2ecf20Sopenharmony_ci sock_put(sk); 48288c2ecf20Sopenharmony_ci } 48298c2ecf20Sopenharmony_ci if (err) 48308c2ecf20Sopenharmony_ci kfree_skb(skb); 48318c2ecf20Sopenharmony_ci} 48328c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_complete_wifi_ack); 48338c2ecf20Sopenharmony_ci 48348c2ecf20Sopenharmony_ci/** 48358c2ecf20Sopenharmony_ci * skb_partial_csum_set - set up and verify partial csum values for packet 48368c2ecf20Sopenharmony_ci * @skb: the skb to set 48378c2ecf20Sopenharmony_ci * @start: the number of bytes after skb->data to start checksumming. 48388c2ecf20Sopenharmony_ci * @off: the offset from start to place the checksum. 48398c2ecf20Sopenharmony_ci * 48408c2ecf20Sopenharmony_ci * For untrusted partially-checksummed packets, we need to make sure the values 48418c2ecf20Sopenharmony_ci * for skb->csum_start and skb->csum_offset are valid so we don't oops. 48428c2ecf20Sopenharmony_ci * 48438c2ecf20Sopenharmony_ci * This function checks and sets those values and skb->ip_summed: if this 48448c2ecf20Sopenharmony_ci * returns false you should drop the packet. 48458c2ecf20Sopenharmony_ci */ 48468c2ecf20Sopenharmony_cibool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off) 48478c2ecf20Sopenharmony_ci{ 48488c2ecf20Sopenharmony_ci u32 csum_end = (u32)start + (u32)off + sizeof(__sum16); 48498c2ecf20Sopenharmony_ci u32 csum_start = skb_headroom(skb) + (u32)start; 48508c2ecf20Sopenharmony_ci 48518c2ecf20Sopenharmony_ci if (unlikely(csum_start > U16_MAX || csum_end > skb_headlen(skb))) { 48528c2ecf20Sopenharmony_ci net_warn_ratelimited("bad partial csum: csum=%u/%u headroom=%u headlen=%u\n", 48538c2ecf20Sopenharmony_ci start, off, skb_headroom(skb), skb_headlen(skb)); 48548c2ecf20Sopenharmony_ci return false; 48558c2ecf20Sopenharmony_ci } 48568c2ecf20Sopenharmony_ci skb->ip_summed = CHECKSUM_PARTIAL; 48578c2ecf20Sopenharmony_ci skb->csum_start = csum_start; 48588c2ecf20Sopenharmony_ci skb->csum_offset = off; 48598c2ecf20Sopenharmony_ci skb_set_transport_header(skb, start); 48608c2ecf20Sopenharmony_ci return true; 48618c2ecf20Sopenharmony_ci} 48628c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_partial_csum_set); 48638c2ecf20Sopenharmony_ci 48648c2ecf20Sopenharmony_cistatic int skb_maybe_pull_tail(struct sk_buff *skb, unsigned int len, 48658c2ecf20Sopenharmony_ci unsigned int max) 48668c2ecf20Sopenharmony_ci{ 48678c2ecf20Sopenharmony_ci if (skb_headlen(skb) >= len) 48688c2ecf20Sopenharmony_ci return 0; 48698c2ecf20Sopenharmony_ci 48708c2ecf20Sopenharmony_ci /* If we need to pullup then pullup to the max, so we 48718c2ecf20Sopenharmony_ci * won't need to do it again. 48728c2ecf20Sopenharmony_ci */ 48738c2ecf20Sopenharmony_ci if (max > skb->len) 48748c2ecf20Sopenharmony_ci max = skb->len; 48758c2ecf20Sopenharmony_ci 48768c2ecf20Sopenharmony_ci if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL) 48778c2ecf20Sopenharmony_ci return -ENOMEM; 48788c2ecf20Sopenharmony_ci 48798c2ecf20Sopenharmony_ci if (skb_headlen(skb) < len) 48808c2ecf20Sopenharmony_ci return -EPROTO; 48818c2ecf20Sopenharmony_ci 48828c2ecf20Sopenharmony_ci return 0; 48838c2ecf20Sopenharmony_ci} 48848c2ecf20Sopenharmony_ci 48858c2ecf20Sopenharmony_ci#define MAX_TCP_HDR_LEN (15 * 4) 48868c2ecf20Sopenharmony_ci 48878c2ecf20Sopenharmony_cistatic __sum16 *skb_checksum_setup_ip(struct sk_buff *skb, 48888c2ecf20Sopenharmony_ci typeof(IPPROTO_IP) proto, 48898c2ecf20Sopenharmony_ci unsigned int off) 48908c2ecf20Sopenharmony_ci{ 48918c2ecf20Sopenharmony_ci int err; 48928c2ecf20Sopenharmony_ci 48938c2ecf20Sopenharmony_ci switch (proto) { 48948c2ecf20Sopenharmony_ci case IPPROTO_TCP: 48958c2ecf20Sopenharmony_ci err = skb_maybe_pull_tail(skb, off + sizeof(struct tcphdr), 48968c2ecf20Sopenharmony_ci off + MAX_TCP_HDR_LEN); 48978c2ecf20Sopenharmony_ci if (!err && !skb_partial_csum_set(skb, off, 48988c2ecf20Sopenharmony_ci offsetof(struct tcphdr, 48998c2ecf20Sopenharmony_ci check))) 49008c2ecf20Sopenharmony_ci err = -EPROTO; 49018c2ecf20Sopenharmony_ci return err ? ERR_PTR(err) : &tcp_hdr(skb)->check; 49028c2ecf20Sopenharmony_ci 49038c2ecf20Sopenharmony_ci case IPPROTO_UDP: 49048c2ecf20Sopenharmony_ci err = skb_maybe_pull_tail(skb, off + sizeof(struct udphdr), 49058c2ecf20Sopenharmony_ci off + sizeof(struct udphdr)); 49068c2ecf20Sopenharmony_ci if (!err && !skb_partial_csum_set(skb, off, 49078c2ecf20Sopenharmony_ci offsetof(struct udphdr, 49088c2ecf20Sopenharmony_ci check))) 49098c2ecf20Sopenharmony_ci err = -EPROTO; 49108c2ecf20Sopenharmony_ci return err ? ERR_PTR(err) : &udp_hdr(skb)->check; 49118c2ecf20Sopenharmony_ci } 49128c2ecf20Sopenharmony_ci 49138c2ecf20Sopenharmony_ci return ERR_PTR(-EPROTO); 49148c2ecf20Sopenharmony_ci} 49158c2ecf20Sopenharmony_ci 49168c2ecf20Sopenharmony_ci/* This value should be large enough to cover a tagged ethernet header plus 49178c2ecf20Sopenharmony_ci * maximally sized IP and TCP or UDP headers. 49188c2ecf20Sopenharmony_ci */ 49198c2ecf20Sopenharmony_ci#define MAX_IP_HDR_LEN 128 49208c2ecf20Sopenharmony_ci 49218c2ecf20Sopenharmony_cistatic int skb_checksum_setup_ipv4(struct sk_buff *skb, bool recalculate) 49228c2ecf20Sopenharmony_ci{ 49238c2ecf20Sopenharmony_ci unsigned int off; 49248c2ecf20Sopenharmony_ci bool fragment; 49258c2ecf20Sopenharmony_ci __sum16 *csum; 49268c2ecf20Sopenharmony_ci int err; 49278c2ecf20Sopenharmony_ci 49288c2ecf20Sopenharmony_ci fragment = false; 49298c2ecf20Sopenharmony_ci 49308c2ecf20Sopenharmony_ci err = skb_maybe_pull_tail(skb, 49318c2ecf20Sopenharmony_ci sizeof(struct iphdr), 49328c2ecf20Sopenharmony_ci MAX_IP_HDR_LEN); 49338c2ecf20Sopenharmony_ci if (err < 0) 49348c2ecf20Sopenharmony_ci goto out; 49358c2ecf20Sopenharmony_ci 49368c2ecf20Sopenharmony_ci if (ip_is_fragment(ip_hdr(skb))) 49378c2ecf20Sopenharmony_ci fragment = true; 49388c2ecf20Sopenharmony_ci 49398c2ecf20Sopenharmony_ci off = ip_hdrlen(skb); 49408c2ecf20Sopenharmony_ci 49418c2ecf20Sopenharmony_ci err = -EPROTO; 49428c2ecf20Sopenharmony_ci 49438c2ecf20Sopenharmony_ci if (fragment) 49448c2ecf20Sopenharmony_ci goto out; 49458c2ecf20Sopenharmony_ci 49468c2ecf20Sopenharmony_ci csum = skb_checksum_setup_ip(skb, ip_hdr(skb)->protocol, off); 49478c2ecf20Sopenharmony_ci if (IS_ERR(csum)) 49488c2ecf20Sopenharmony_ci return PTR_ERR(csum); 49498c2ecf20Sopenharmony_ci 49508c2ecf20Sopenharmony_ci if (recalculate) 49518c2ecf20Sopenharmony_ci *csum = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, 49528c2ecf20Sopenharmony_ci ip_hdr(skb)->daddr, 49538c2ecf20Sopenharmony_ci skb->len - off, 49548c2ecf20Sopenharmony_ci ip_hdr(skb)->protocol, 0); 49558c2ecf20Sopenharmony_ci err = 0; 49568c2ecf20Sopenharmony_ci 49578c2ecf20Sopenharmony_ciout: 49588c2ecf20Sopenharmony_ci return err; 49598c2ecf20Sopenharmony_ci} 49608c2ecf20Sopenharmony_ci 49618c2ecf20Sopenharmony_ci/* This value should be large enough to cover a tagged ethernet header plus 49628c2ecf20Sopenharmony_ci * an IPv6 header, all options, and a maximal TCP or UDP header. 49638c2ecf20Sopenharmony_ci */ 49648c2ecf20Sopenharmony_ci#define MAX_IPV6_HDR_LEN 256 49658c2ecf20Sopenharmony_ci 49668c2ecf20Sopenharmony_ci#define OPT_HDR(type, skb, off) \ 49678c2ecf20Sopenharmony_ci (type *)(skb_network_header(skb) + (off)) 49688c2ecf20Sopenharmony_ci 49698c2ecf20Sopenharmony_cistatic int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate) 49708c2ecf20Sopenharmony_ci{ 49718c2ecf20Sopenharmony_ci int err; 49728c2ecf20Sopenharmony_ci u8 nexthdr; 49738c2ecf20Sopenharmony_ci unsigned int off; 49748c2ecf20Sopenharmony_ci unsigned int len; 49758c2ecf20Sopenharmony_ci bool fragment; 49768c2ecf20Sopenharmony_ci bool done; 49778c2ecf20Sopenharmony_ci __sum16 *csum; 49788c2ecf20Sopenharmony_ci 49798c2ecf20Sopenharmony_ci fragment = false; 49808c2ecf20Sopenharmony_ci done = false; 49818c2ecf20Sopenharmony_ci 49828c2ecf20Sopenharmony_ci off = sizeof(struct ipv6hdr); 49838c2ecf20Sopenharmony_ci 49848c2ecf20Sopenharmony_ci err = skb_maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN); 49858c2ecf20Sopenharmony_ci if (err < 0) 49868c2ecf20Sopenharmony_ci goto out; 49878c2ecf20Sopenharmony_ci 49888c2ecf20Sopenharmony_ci nexthdr = ipv6_hdr(skb)->nexthdr; 49898c2ecf20Sopenharmony_ci 49908c2ecf20Sopenharmony_ci len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len); 49918c2ecf20Sopenharmony_ci while (off <= len && !done) { 49928c2ecf20Sopenharmony_ci switch (nexthdr) { 49938c2ecf20Sopenharmony_ci case IPPROTO_DSTOPTS: 49948c2ecf20Sopenharmony_ci case IPPROTO_HOPOPTS: 49958c2ecf20Sopenharmony_ci case IPPROTO_ROUTING: { 49968c2ecf20Sopenharmony_ci struct ipv6_opt_hdr *hp; 49978c2ecf20Sopenharmony_ci 49988c2ecf20Sopenharmony_ci err = skb_maybe_pull_tail(skb, 49998c2ecf20Sopenharmony_ci off + 50008c2ecf20Sopenharmony_ci sizeof(struct ipv6_opt_hdr), 50018c2ecf20Sopenharmony_ci MAX_IPV6_HDR_LEN); 50028c2ecf20Sopenharmony_ci if (err < 0) 50038c2ecf20Sopenharmony_ci goto out; 50048c2ecf20Sopenharmony_ci 50058c2ecf20Sopenharmony_ci hp = OPT_HDR(struct ipv6_opt_hdr, skb, off); 50068c2ecf20Sopenharmony_ci nexthdr = hp->nexthdr; 50078c2ecf20Sopenharmony_ci off += ipv6_optlen(hp); 50088c2ecf20Sopenharmony_ci break; 50098c2ecf20Sopenharmony_ci } 50108c2ecf20Sopenharmony_ci case IPPROTO_AH: { 50118c2ecf20Sopenharmony_ci struct ip_auth_hdr *hp; 50128c2ecf20Sopenharmony_ci 50138c2ecf20Sopenharmony_ci err = skb_maybe_pull_tail(skb, 50148c2ecf20Sopenharmony_ci off + 50158c2ecf20Sopenharmony_ci sizeof(struct ip_auth_hdr), 50168c2ecf20Sopenharmony_ci MAX_IPV6_HDR_LEN); 50178c2ecf20Sopenharmony_ci if (err < 0) 50188c2ecf20Sopenharmony_ci goto out; 50198c2ecf20Sopenharmony_ci 50208c2ecf20Sopenharmony_ci hp = OPT_HDR(struct ip_auth_hdr, skb, off); 50218c2ecf20Sopenharmony_ci nexthdr = hp->nexthdr; 50228c2ecf20Sopenharmony_ci off += ipv6_authlen(hp); 50238c2ecf20Sopenharmony_ci break; 50248c2ecf20Sopenharmony_ci } 50258c2ecf20Sopenharmony_ci case IPPROTO_FRAGMENT: { 50268c2ecf20Sopenharmony_ci struct frag_hdr *hp; 50278c2ecf20Sopenharmony_ci 50288c2ecf20Sopenharmony_ci err = skb_maybe_pull_tail(skb, 50298c2ecf20Sopenharmony_ci off + 50308c2ecf20Sopenharmony_ci sizeof(struct frag_hdr), 50318c2ecf20Sopenharmony_ci MAX_IPV6_HDR_LEN); 50328c2ecf20Sopenharmony_ci if (err < 0) 50338c2ecf20Sopenharmony_ci goto out; 50348c2ecf20Sopenharmony_ci 50358c2ecf20Sopenharmony_ci hp = OPT_HDR(struct frag_hdr, skb, off); 50368c2ecf20Sopenharmony_ci 50378c2ecf20Sopenharmony_ci if (hp->frag_off & htons(IP6_OFFSET | IP6_MF)) 50388c2ecf20Sopenharmony_ci fragment = true; 50398c2ecf20Sopenharmony_ci 50408c2ecf20Sopenharmony_ci nexthdr = hp->nexthdr; 50418c2ecf20Sopenharmony_ci off += sizeof(struct frag_hdr); 50428c2ecf20Sopenharmony_ci break; 50438c2ecf20Sopenharmony_ci } 50448c2ecf20Sopenharmony_ci default: 50458c2ecf20Sopenharmony_ci done = true; 50468c2ecf20Sopenharmony_ci break; 50478c2ecf20Sopenharmony_ci } 50488c2ecf20Sopenharmony_ci } 50498c2ecf20Sopenharmony_ci 50508c2ecf20Sopenharmony_ci err = -EPROTO; 50518c2ecf20Sopenharmony_ci 50528c2ecf20Sopenharmony_ci if (!done || fragment) 50538c2ecf20Sopenharmony_ci goto out; 50548c2ecf20Sopenharmony_ci 50558c2ecf20Sopenharmony_ci csum = skb_checksum_setup_ip(skb, nexthdr, off); 50568c2ecf20Sopenharmony_ci if (IS_ERR(csum)) 50578c2ecf20Sopenharmony_ci return PTR_ERR(csum); 50588c2ecf20Sopenharmony_ci 50598c2ecf20Sopenharmony_ci if (recalculate) 50608c2ecf20Sopenharmony_ci *csum = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, 50618c2ecf20Sopenharmony_ci &ipv6_hdr(skb)->daddr, 50628c2ecf20Sopenharmony_ci skb->len - off, nexthdr, 0); 50638c2ecf20Sopenharmony_ci err = 0; 50648c2ecf20Sopenharmony_ci 50658c2ecf20Sopenharmony_ciout: 50668c2ecf20Sopenharmony_ci return err; 50678c2ecf20Sopenharmony_ci} 50688c2ecf20Sopenharmony_ci 50698c2ecf20Sopenharmony_ci/** 50708c2ecf20Sopenharmony_ci * skb_checksum_setup - set up partial checksum offset 50718c2ecf20Sopenharmony_ci * @skb: the skb to set up 50728c2ecf20Sopenharmony_ci * @recalculate: if true the pseudo-header checksum will be recalculated 50738c2ecf20Sopenharmony_ci */ 50748c2ecf20Sopenharmony_ciint skb_checksum_setup(struct sk_buff *skb, bool recalculate) 50758c2ecf20Sopenharmony_ci{ 50768c2ecf20Sopenharmony_ci int err; 50778c2ecf20Sopenharmony_ci 50788c2ecf20Sopenharmony_ci switch (skb->protocol) { 50798c2ecf20Sopenharmony_ci case htons(ETH_P_IP): 50808c2ecf20Sopenharmony_ci err = skb_checksum_setup_ipv4(skb, recalculate); 50818c2ecf20Sopenharmony_ci break; 50828c2ecf20Sopenharmony_ci 50838c2ecf20Sopenharmony_ci case htons(ETH_P_IPV6): 50848c2ecf20Sopenharmony_ci err = skb_checksum_setup_ipv6(skb, recalculate); 50858c2ecf20Sopenharmony_ci break; 50868c2ecf20Sopenharmony_ci 50878c2ecf20Sopenharmony_ci default: 50888c2ecf20Sopenharmony_ci err = -EPROTO; 50898c2ecf20Sopenharmony_ci break; 50908c2ecf20Sopenharmony_ci } 50918c2ecf20Sopenharmony_ci 50928c2ecf20Sopenharmony_ci return err; 50938c2ecf20Sopenharmony_ci} 50948c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_checksum_setup); 50958c2ecf20Sopenharmony_ci 50968c2ecf20Sopenharmony_ci/** 50978c2ecf20Sopenharmony_ci * skb_checksum_maybe_trim - maybe trims the given skb 50988c2ecf20Sopenharmony_ci * @skb: the skb to check 50998c2ecf20Sopenharmony_ci * @transport_len: the data length beyond the network header 51008c2ecf20Sopenharmony_ci * 51018c2ecf20Sopenharmony_ci * Checks whether the given skb has data beyond the given transport length. 51028c2ecf20Sopenharmony_ci * If so, returns a cloned skb trimmed to this transport length. 51038c2ecf20Sopenharmony_ci * Otherwise returns the provided skb. Returns NULL in error cases 51048c2ecf20Sopenharmony_ci * (e.g. transport_len exceeds skb length or out-of-memory). 51058c2ecf20Sopenharmony_ci * 51068c2ecf20Sopenharmony_ci * Caller needs to set the skb transport header and free any returned skb if it 51078c2ecf20Sopenharmony_ci * differs from the provided skb. 51088c2ecf20Sopenharmony_ci */ 51098c2ecf20Sopenharmony_cistatic struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb, 51108c2ecf20Sopenharmony_ci unsigned int transport_len) 51118c2ecf20Sopenharmony_ci{ 51128c2ecf20Sopenharmony_ci struct sk_buff *skb_chk; 51138c2ecf20Sopenharmony_ci unsigned int len = skb_transport_offset(skb) + transport_len; 51148c2ecf20Sopenharmony_ci int ret; 51158c2ecf20Sopenharmony_ci 51168c2ecf20Sopenharmony_ci if (skb->len < len) 51178c2ecf20Sopenharmony_ci return NULL; 51188c2ecf20Sopenharmony_ci else if (skb->len == len) 51198c2ecf20Sopenharmony_ci return skb; 51208c2ecf20Sopenharmony_ci 51218c2ecf20Sopenharmony_ci skb_chk = skb_clone(skb, GFP_ATOMIC); 51228c2ecf20Sopenharmony_ci if (!skb_chk) 51238c2ecf20Sopenharmony_ci return NULL; 51248c2ecf20Sopenharmony_ci 51258c2ecf20Sopenharmony_ci ret = pskb_trim_rcsum(skb_chk, len); 51268c2ecf20Sopenharmony_ci if (ret) { 51278c2ecf20Sopenharmony_ci kfree_skb(skb_chk); 51288c2ecf20Sopenharmony_ci return NULL; 51298c2ecf20Sopenharmony_ci } 51308c2ecf20Sopenharmony_ci 51318c2ecf20Sopenharmony_ci return skb_chk; 51328c2ecf20Sopenharmony_ci} 51338c2ecf20Sopenharmony_ci 51348c2ecf20Sopenharmony_ci/** 51358c2ecf20Sopenharmony_ci * skb_checksum_trimmed - validate checksum of an skb 51368c2ecf20Sopenharmony_ci * @skb: the skb to check 51378c2ecf20Sopenharmony_ci * @transport_len: the data length beyond the network header 51388c2ecf20Sopenharmony_ci * @skb_chkf: checksum function to use 51398c2ecf20Sopenharmony_ci * 51408c2ecf20Sopenharmony_ci * Applies the given checksum function skb_chkf to the provided skb. 51418c2ecf20Sopenharmony_ci * Returns a checked and maybe trimmed skb. Returns NULL on error. 51428c2ecf20Sopenharmony_ci * 51438c2ecf20Sopenharmony_ci * If the skb has data beyond the given transport length, then a 51448c2ecf20Sopenharmony_ci * trimmed & cloned skb is checked and returned. 51458c2ecf20Sopenharmony_ci * 51468c2ecf20Sopenharmony_ci * Caller needs to set the skb transport header and free any returned skb if it 51478c2ecf20Sopenharmony_ci * differs from the provided skb. 51488c2ecf20Sopenharmony_ci */ 51498c2ecf20Sopenharmony_cistruct sk_buff *skb_checksum_trimmed(struct sk_buff *skb, 51508c2ecf20Sopenharmony_ci unsigned int transport_len, 51518c2ecf20Sopenharmony_ci __sum16(*skb_chkf)(struct sk_buff *skb)) 51528c2ecf20Sopenharmony_ci{ 51538c2ecf20Sopenharmony_ci struct sk_buff *skb_chk; 51548c2ecf20Sopenharmony_ci unsigned int offset = skb_transport_offset(skb); 51558c2ecf20Sopenharmony_ci __sum16 ret; 51568c2ecf20Sopenharmony_ci 51578c2ecf20Sopenharmony_ci skb_chk = skb_checksum_maybe_trim(skb, transport_len); 51588c2ecf20Sopenharmony_ci if (!skb_chk) 51598c2ecf20Sopenharmony_ci goto err; 51608c2ecf20Sopenharmony_ci 51618c2ecf20Sopenharmony_ci if (!pskb_may_pull(skb_chk, offset)) 51628c2ecf20Sopenharmony_ci goto err; 51638c2ecf20Sopenharmony_ci 51648c2ecf20Sopenharmony_ci skb_pull_rcsum(skb_chk, offset); 51658c2ecf20Sopenharmony_ci ret = skb_chkf(skb_chk); 51668c2ecf20Sopenharmony_ci skb_push_rcsum(skb_chk, offset); 51678c2ecf20Sopenharmony_ci 51688c2ecf20Sopenharmony_ci if (ret) 51698c2ecf20Sopenharmony_ci goto err; 51708c2ecf20Sopenharmony_ci 51718c2ecf20Sopenharmony_ci return skb_chk; 51728c2ecf20Sopenharmony_ci 51738c2ecf20Sopenharmony_cierr: 51748c2ecf20Sopenharmony_ci if (skb_chk && skb_chk != skb) 51758c2ecf20Sopenharmony_ci kfree_skb(skb_chk); 51768c2ecf20Sopenharmony_ci 51778c2ecf20Sopenharmony_ci return NULL; 51788c2ecf20Sopenharmony_ci 51798c2ecf20Sopenharmony_ci} 51808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_checksum_trimmed); 51818c2ecf20Sopenharmony_ci 51828c2ecf20Sopenharmony_civoid __skb_warn_lro_forwarding(const struct sk_buff *skb) 51838c2ecf20Sopenharmony_ci{ 51848c2ecf20Sopenharmony_ci net_warn_ratelimited("%s: received packets cannot be forwarded while LRO is enabled\n", 51858c2ecf20Sopenharmony_ci skb->dev->name); 51868c2ecf20Sopenharmony_ci} 51878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__skb_warn_lro_forwarding); 51888c2ecf20Sopenharmony_ci 51898c2ecf20Sopenharmony_civoid kfree_skb_partial(struct sk_buff *skb, bool head_stolen) 51908c2ecf20Sopenharmony_ci{ 51918c2ecf20Sopenharmony_ci if (head_stolen) { 51928c2ecf20Sopenharmony_ci skb_release_head_state(skb); 51938c2ecf20Sopenharmony_ci kmem_cache_free(skbuff_head_cache, skb); 51948c2ecf20Sopenharmony_ci } else { 51958c2ecf20Sopenharmony_ci __kfree_skb(skb); 51968c2ecf20Sopenharmony_ci } 51978c2ecf20Sopenharmony_ci} 51988c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kfree_skb_partial); 51998c2ecf20Sopenharmony_ci 52008c2ecf20Sopenharmony_ci/** 52018c2ecf20Sopenharmony_ci * skb_try_coalesce - try to merge skb to prior one 52028c2ecf20Sopenharmony_ci * @to: prior buffer 52038c2ecf20Sopenharmony_ci * @from: buffer to add 52048c2ecf20Sopenharmony_ci * @fragstolen: pointer to boolean 52058c2ecf20Sopenharmony_ci * @delta_truesize: how much more was allocated than was requested 52068c2ecf20Sopenharmony_ci */ 52078c2ecf20Sopenharmony_cibool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, 52088c2ecf20Sopenharmony_ci bool *fragstolen, int *delta_truesize) 52098c2ecf20Sopenharmony_ci{ 52108c2ecf20Sopenharmony_ci struct skb_shared_info *to_shinfo, *from_shinfo; 52118c2ecf20Sopenharmony_ci int i, delta, len = from->len; 52128c2ecf20Sopenharmony_ci 52138c2ecf20Sopenharmony_ci *fragstolen = false; 52148c2ecf20Sopenharmony_ci 52158c2ecf20Sopenharmony_ci if (skb_cloned(to)) 52168c2ecf20Sopenharmony_ci return false; 52178c2ecf20Sopenharmony_ci 52188c2ecf20Sopenharmony_ci if (len <= skb_tailroom(to)) { 52198c2ecf20Sopenharmony_ci if (len) 52208c2ecf20Sopenharmony_ci BUG_ON(skb_copy_bits(from, 0, skb_put(to, len), len)); 52218c2ecf20Sopenharmony_ci *delta_truesize = 0; 52228c2ecf20Sopenharmony_ci return true; 52238c2ecf20Sopenharmony_ci } 52248c2ecf20Sopenharmony_ci 52258c2ecf20Sopenharmony_ci to_shinfo = skb_shinfo(to); 52268c2ecf20Sopenharmony_ci from_shinfo = skb_shinfo(from); 52278c2ecf20Sopenharmony_ci if (to_shinfo->frag_list || from_shinfo->frag_list) 52288c2ecf20Sopenharmony_ci return false; 52298c2ecf20Sopenharmony_ci if (skb_zcopy(to) || skb_zcopy(from)) 52308c2ecf20Sopenharmony_ci return false; 52318c2ecf20Sopenharmony_ci 52328c2ecf20Sopenharmony_ci if (skb_headlen(from) != 0) { 52338c2ecf20Sopenharmony_ci struct page *page; 52348c2ecf20Sopenharmony_ci unsigned int offset; 52358c2ecf20Sopenharmony_ci 52368c2ecf20Sopenharmony_ci if (to_shinfo->nr_frags + 52378c2ecf20Sopenharmony_ci from_shinfo->nr_frags >= MAX_SKB_FRAGS) 52388c2ecf20Sopenharmony_ci return false; 52398c2ecf20Sopenharmony_ci 52408c2ecf20Sopenharmony_ci if (skb_head_is_locked(from)) 52418c2ecf20Sopenharmony_ci return false; 52428c2ecf20Sopenharmony_ci 52438c2ecf20Sopenharmony_ci delta = from->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff)); 52448c2ecf20Sopenharmony_ci 52458c2ecf20Sopenharmony_ci page = virt_to_head_page(from->head); 52468c2ecf20Sopenharmony_ci offset = from->data - (unsigned char *)page_address(page); 52478c2ecf20Sopenharmony_ci 52488c2ecf20Sopenharmony_ci skb_fill_page_desc(to, to_shinfo->nr_frags, 52498c2ecf20Sopenharmony_ci page, offset, skb_headlen(from)); 52508c2ecf20Sopenharmony_ci *fragstolen = true; 52518c2ecf20Sopenharmony_ci } else { 52528c2ecf20Sopenharmony_ci if (to_shinfo->nr_frags + 52538c2ecf20Sopenharmony_ci from_shinfo->nr_frags > MAX_SKB_FRAGS) 52548c2ecf20Sopenharmony_ci return false; 52558c2ecf20Sopenharmony_ci 52568c2ecf20Sopenharmony_ci delta = from->truesize - SKB_TRUESIZE(skb_end_offset(from)); 52578c2ecf20Sopenharmony_ci } 52588c2ecf20Sopenharmony_ci 52598c2ecf20Sopenharmony_ci WARN_ON_ONCE(delta < len); 52608c2ecf20Sopenharmony_ci 52618c2ecf20Sopenharmony_ci memcpy(to_shinfo->frags + to_shinfo->nr_frags, 52628c2ecf20Sopenharmony_ci from_shinfo->frags, 52638c2ecf20Sopenharmony_ci from_shinfo->nr_frags * sizeof(skb_frag_t)); 52648c2ecf20Sopenharmony_ci to_shinfo->nr_frags += from_shinfo->nr_frags; 52658c2ecf20Sopenharmony_ci 52668c2ecf20Sopenharmony_ci if (!skb_cloned(from)) 52678c2ecf20Sopenharmony_ci from_shinfo->nr_frags = 0; 52688c2ecf20Sopenharmony_ci 52698c2ecf20Sopenharmony_ci /* if the skb is not cloned this does nothing 52708c2ecf20Sopenharmony_ci * since we set nr_frags to 0. 52718c2ecf20Sopenharmony_ci */ 52728c2ecf20Sopenharmony_ci for (i = 0; i < from_shinfo->nr_frags; i++) 52738c2ecf20Sopenharmony_ci __skb_frag_ref(&from_shinfo->frags[i]); 52748c2ecf20Sopenharmony_ci 52758c2ecf20Sopenharmony_ci to->truesize += delta; 52768c2ecf20Sopenharmony_ci to->len += len; 52778c2ecf20Sopenharmony_ci to->data_len += len; 52788c2ecf20Sopenharmony_ci 52798c2ecf20Sopenharmony_ci *delta_truesize = delta; 52808c2ecf20Sopenharmony_ci return true; 52818c2ecf20Sopenharmony_ci} 52828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_try_coalesce); 52838c2ecf20Sopenharmony_ci 52848c2ecf20Sopenharmony_ci/** 52858c2ecf20Sopenharmony_ci * skb_scrub_packet - scrub an skb 52868c2ecf20Sopenharmony_ci * 52878c2ecf20Sopenharmony_ci * @skb: buffer to clean 52888c2ecf20Sopenharmony_ci * @xnet: packet is crossing netns 52898c2ecf20Sopenharmony_ci * 52908c2ecf20Sopenharmony_ci * skb_scrub_packet can be used after encapsulating or decapsulting a packet 52918c2ecf20Sopenharmony_ci * into/from a tunnel. Some information have to be cleared during these 52928c2ecf20Sopenharmony_ci * operations. 52938c2ecf20Sopenharmony_ci * skb_scrub_packet can also be used to clean a skb before injecting it in 52948c2ecf20Sopenharmony_ci * another namespace (@xnet == true). We have to clear all information in the 52958c2ecf20Sopenharmony_ci * skb that could impact namespace isolation. 52968c2ecf20Sopenharmony_ci */ 52978c2ecf20Sopenharmony_civoid skb_scrub_packet(struct sk_buff *skb, bool xnet) 52988c2ecf20Sopenharmony_ci{ 52998c2ecf20Sopenharmony_ci skb->pkt_type = PACKET_HOST; 53008c2ecf20Sopenharmony_ci skb->skb_iif = 0; 53018c2ecf20Sopenharmony_ci skb->ignore_df = 0; 53028c2ecf20Sopenharmony_ci skb_dst_drop(skb); 53038c2ecf20Sopenharmony_ci skb_ext_reset(skb); 53048c2ecf20Sopenharmony_ci nf_reset_ct(skb); 53058c2ecf20Sopenharmony_ci nf_reset_trace(skb); 53068c2ecf20Sopenharmony_ci 53078c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_SWITCHDEV 53088c2ecf20Sopenharmony_ci skb->offload_fwd_mark = 0; 53098c2ecf20Sopenharmony_ci skb->offload_l3_fwd_mark = 0; 53108c2ecf20Sopenharmony_ci#endif 53118c2ecf20Sopenharmony_ci 53128c2ecf20Sopenharmony_ci if (!xnet) 53138c2ecf20Sopenharmony_ci return; 53148c2ecf20Sopenharmony_ci 53158c2ecf20Sopenharmony_ci ipvs_reset(skb); 53168c2ecf20Sopenharmony_ci skb->mark = 0; 53178c2ecf20Sopenharmony_ci skb->tstamp = 0; 53188c2ecf20Sopenharmony_ci} 53198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_scrub_packet); 53208c2ecf20Sopenharmony_ci 53218c2ecf20Sopenharmony_ci/** 53228c2ecf20Sopenharmony_ci * skb_gso_transport_seglen - Return length of individual segments of a gso packet 53238c2ecf20Sopenharmony_ci * 53248c2ecf20Sopenharmony_ci * @skb: GSO skb 53258c2ecf20Sopenharmony_ci * 53268c2ecf20Sopenharmony_ci * skb_gso_transport_seglen is used to determine the real size of the 53278c2ecf20Sopenharmony_ci * individual segments, including Layer4 headers (TCP/UDP). 53288c2ecf20Sopenharmony_ci * 53298c2ecf20Sopenharmony_ci * The MAC/L2 or network (IP, IPv6) headers are not accounted for. 53308c2ecf20Sopenharmony_ci */ 53318c2ecf20Sopenharmony_cistatic unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) 53328c2ecf20Sopenharmony_ci{ 53338c2ecf20Sopenharmony_ci const struct skb_shared_info *shinfo = skb_shinfo(skb); 53348c2ecf20Sopenharmony_ci unsigned int thlen = 0; 53358c2ecf20Sopenharmony_ci 53368c2ecf20Sopenharmony_ci if (skb->encapsulation) { 53378c2ecf20Sopenharmony_ci thlen = skb_inner_transport_header(skb) - 53388c2ecf20Sopenharmony_ci skb_transport_header(skb); 53398c2ecf20Sopenharmony_ci 53408c2ecf20Sopenharmony_ci if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) 53418c2ecf20Sopenharmony_ci thlen += inner_tcp_hdrlen(skb); 53428c2ecf20Sopenharmony_ci } else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) { 53438c2ecf20Sopenharmony_ci thlen = tcp_hdrlen(skb); 53448c2ecf20Sopenharmony_ci } else if (unlikely(skb_is_gso_sctp(skb))) { 53458c2ecf20Sopenharmony_ci thlen = sizeof(struct sctphdr); 53468c2ecf20Sopenharmony_ci } else if (shinfo->gso_type & SKB_GSO_UDP_L4) { 53478c2ecf20Sopenharmony_ci thlen = sizeof(struct udphdr); 53488c2ecf20Sopenharmony_ci } 53498c2ecf20Sopenharmony_ci /* UFO sets gso_size to the size of the fragmentation 53508c2ecf20Sopenharmony_ci * payload, i.e. the size of the L4 (UDP) header is already 53518c2ecf20Sopenharmony_ci * accounted for. 53528c2ecf20Sopenharmony_ci */ 53538c2ecf20Sopenharmony_ci return thlen + shinfo->gso_size; 53548c2ecf20Sopenharmony_ci} 53558c2ecf20Sopenharmony_ci 53568c2ecf20Sopenharmony_ci/** 53578c2ecf20Sopenharmony_ci * skb_gso_network_seglen - Return length of individual segments of a gso packet 53588c2ecf20Sopenharmony_ci * 53598c2ecf20Sopenharmony_ci * @skb: GSO skb 53608c2ecf20Sopenharmony_ci * 53618c2ecf20Sopenharmony_ci * skb_gso_network_seglen is used to determine the real size of the 53628c2ecf20Sopenharmony_ci * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP). 53638c2ecf20Sopenharmony_ci * 53648c2ecf20Sopenharmony_ci * The MAC/L2 header is not accounted for. 53658c2ecf20Sopenharmony_ci */ 53668c2ecf20Sopenharmony_cistatic unsigned int skb_gso_network_seglen(const struct sk_buff *skb) 53678c2ecf20Sopenharmony_ci{ 53688c2ecf20Sopenharmony_ci unsigned int hdr_len = skb_transport_header(skb) - 53698c2ecf20Sopenharmony_ci skb_network_header(skb); 53708c2ecf20Sopenharmony_ci 53718c2ecf20Sopenharmony_ci return hdr_len + skb_gso_transport_seglen(skb); 53728c2ecf20Sopenharmony_ci} 53738c2ecf20Sopenharmony_ci 53748c2ecf20Sopenharmony_ci/** 53758c2ecf20Sopenharmony_ci * skb_gso_mac_seglen - Return length of individual segments of a gso packet 53768c2ecf20Sopenharmony_ci * 53778c2ecf20Sopenharmony_ci * @skb: GSO skb 53788c2ecf20Sopenharmony_ci * 53798c2ecf20Sopenharmony_ci * skb_gso_mac_seglen is used to determine the real size of the 53808c2ecf20Sopenharmony_ci * individual segments, including MAC/L2, Layer3 (IP, IPv6) and L4 53818c2ecf20Sopenharmony_ci * headers (TCP/UDP). 53828c2ecf20Sopenharmony_ci */ 53838c2ecf20Sopenharmony_cistatic unsigned int skb_gso_mac_seglen(const struct sk_buff *skb) 53848c2ecf20Sopenharmony_ci{ 53858c2ecf20Sopenharmony_ci unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb); 53868c2ecf20Sopenharmony_ci 53878c2ecf20Sopenharmony_ci return hdr_len + skb_gso_transport_seglen(skb); 53888c2ecf20Sopenharmony_ci} 53898c2ecf20Sopenharmony_ci 53908c2ecf20Sopenharmony_ci/** 53918c2ecf20Sopenharmony_ci * skb_gso_size_check - check the skb size, considering GSO_BY_FRAGS 53928c2ecf20Sopenharmony_ci * 53938c2ecf20Sopenharmony_ci * There are a couple of instances where we have a GSO skb, and we 53948c2ecf20Sopenharmony_ci * want to determine what size it would be after it is segmented. 53958c2ecf20Sopenharmony_ci * 53968c2ecf20Sopenharmony_ci * We might want to check: 53978c2ecf20Sopenharmony_ci * - L3+L4+payload size (e.g. IP forwarding) 53988c2ecf20Sopenharmony_ci * - L2+L3+L4+payload size (e.g. sanity check before passing to driver) 53998c2ecf20Sopenharmony_ci * 54008c2ecf20Sopenharmony_ci * This is a helper to do that correctly considering GSO_BY_FRAGS. 54018c2ecf20Sopenharmony_ci * 54028c2ecf20Sopenharmony_ci * @skb: GSO skb 54038c2ecf20Sopenharmony_ci * 54048c2ecf20Sopenharmony_ci * @seg_len: The segmented length (from skb_gso_*_seglen). In the 54058c2ecf20Sopenharmony_ci * GSO_BY_FRAGS case this will be [header sizes + GSO_BY_FRAGS]. 54068c2ecf20Sopenharmony_ci * 54078c2ecf20Sopenharmony_ci * @max_len: The maximum permissible length. 54088c2ecf20Sopenharmony_ci * 54098c2ecf20Sopenharmony_ci * Returns true if the segmented length <= max length. 54108c2ecf20Sopenharmony_ci */ 54118c2ecf20Sopenharmony_cistatic inline bool skb_gso_size_check(const struct sk_buff *skb, 54128c2ecf20Sopenharmony_ci unsigned int seg_len, 54138c2ecf20Sopenharmony_ci unsigned int max_len) { 54148c2ecf20Sopenharmony_ci const struct skb_shared_info *shinfo = skb_shinfo(skb); 54158c2ecf20Sopenharmony_ci const struct sk_buff *iter; 54168c2ecf20Sopenharmony_ci 54178c2ecf20Sopenharmony_ci if (shinfo->gso_size != GSO_BY_FRAGS) 54188c2ecf20Sopenharmony_ci return seg_len <= max_len; 54198c2ecf20Sopenharmony_ci 54208c2ecf20Sopenharmony_ci /* Undo this so we can re-use header sizes */ 54218c2ecf20Sopenharmony_ci seg_len -= GSO_BY_FRAGS; 54228c2ecf20Sopenharmony_ci 54238c2ecf20Sopenharmony_ci skb_walk_frags(skb, iter) { 54248c2ecf20Sopenharmony_ci if (seg_len + skb_headlen(iter) > max_len) 54258c2ecf20Sopenharmony_ci return false; 54268c2ecf20Sopenharmony_ci } 54278c2ecf20Sopenharmony_ci 54288c2ecf20Sopenharmony_ci return true; 54298c2ecf20Sopenharmony_ci} 54308c2ecf20Sopenharmony_ci 54318c2ecf20Sopenharmony_ci/** 54328c2ecf20Sopenharmony_ci * skb_gso_validate_network_len - Will a split GSO skb fit into a given MTU? 54338c2ecf20Sopenharmony_ci * 54348c2ecf20Sopenharmony_ci * @skb: GSO skb 54358c2ecf20Sopenharmony_ci * @mtu: MTU to validate against 54368c2ecf20Sopenharmony_ci * 54378c2ecf20Sopenharmony_ci * skb_gso_validate_network_len validates if a given skb will fit a 54388c2ecf20Sopenharmony_ci * wanted MTU once split. It considers L3 headers, L4 headers, and the 54398c2ecf20Sopenharmony_ci * payload. 54408c2ecf20Sopenharmony_ci */ 54418c2ecf20Sopenharmony_cibool skb_gso_validate_network_len(const struct sk_buff *skb, unsigned int mtu) 54428c2ecf20Sopenharmony_ci{ 54438c2ecf20Sopenharmony_ci return skb_gso_size_check(skb, skb_gso_network_seglen(skb), mtu); 54448c2ecf20Sopenharmony_ci} 54458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_gso_validate_network_len); 54468c2ecf20Sopenharmony_ci 54478c2ecf20Sopenharmony_ci/** 54488c2ecf20Sopenharmony_ci * skb_gso_validate_mac_len - Will a split GSO skb fit in a given length? 54498c2ecf20Sopenharmony_ci * 54508c2ecf20Sopenharmony_ci * @skb: GSO skb 54518c2ecf20Sopenharmony_ci * @len: length to validate against 54528c2ecf20Sopenharmony_ci * 54538c2ecf20Sopenharmony_ci * skb_gso_validate_mac_len validates if a given skb will fit a wanted 54548c2ecf20Sopenharmony_ci * length once split, including L2, L3 and L4 headers and the payload. 54558c2ecf20Sopenharmony_ci */ 54568c2ecf20Sopenharmony_cibool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len) 54578c2ecf20Sopenharmony_ci{ 54588c2ecf20Sopenharmony_ci return skb_gso_size_check(skb, skb_gso_mac_seglen(skb), len); 54598c2ecf20Sopenharmony_ci} 54608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_gso_validate_mac_len); 54618c2ecf20Sopenharmony_ci 54628c2ecf20Sopenharmony_cistatic struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) 54638c2ecf20Sopenharmony_ci{ 54648c2ecf20Sopenharmony_ci int mac_len, meta_len; 54658c2ecf20Sopenharmony_ci void *meta; 54668c2ecf20Sopenharmony_ci 54678c2ecf20Sopenharmony_ci if (skb_cow(skb, skb_headroom(skb)) < 0) { 54688c2ecf20Sopenharmony_ci kfree_skb(skb); 54698c2ecf20Sopenharmony_ci return NULL; 54708c2ecf20Sopenharmony_ci } 54718c2ecf20Sopenharmony_ci 54728c2ecf20Sopenharmony_ci mac_len = skb->data - skb_mac_header(skb); 54738c2ecf20Sopenharmony_ci if (likely(mac_len > VLAN_HLEN + ETH_TLEN)) { 54748c2ecf20Sopenharmony_ci memmove(skb_mac_header(skb) + VLAN_HLEN, skb_mac_header(skb), 54758c2ecf20Sopenharmony_ci mac_len - VLAN_HLEN - ETH_TLEN); 54768c2ecf20Sopenharmony_ci } 54778c2ecf20Sopenharmony_ci 54788c2ecf20Sopenharmony_ci meta_len = skb_metadata_len(skb); 54798c2ecf20Sopenharmony_ci if (meta_len) { 54808c2ecf20Sopenharmony_ci meta = skb_metadata_end(skb) - meta_len; 54818c2ecf20Sopenharmony_ci memmove(meta + VLAN_HLEN, meta, meta_len); 54828c2ecf20Sopenharmony_ci } 54838c2ecf20Sopenharmony_ci 54848c2ecf20Sopenharmony_ci skb->mac_header += VLAN_HLEN; 54858c2ecf20Sopenharmony_ci return skb; 54868c2ecf20Sopenharmony_ci} 54878c2ecf20Sopenharmony_ci 54888c2ecf20Sopenharmony_cistruct sk_buff *skb_vlan_untag(struct sk_buff *skb) 54898c2ecf20Sopenharmony_ci{ 54908c2ecf20Sopenharmony_ci struct vlan_hdr *vhdr; 54918c2ecf20Sopenharmony_ci u16 vlan_tci; 54928c2ecf20Sopenharmony_ci 54938c2ecf20Sopenharmony_ci if (unlikely(skb_vlan_tag_present(skb))) { 54948c2ecf20Sopenharmony_ci /* vlan_tci is already set-up so leave this for another time */ 54958c2ecf20Sopenharmony_ci return skb; 54968c2ecf20Sopenharmony_ci } 54978c2ecf20Sopenharmony_ci 54988c2ecf20Sopenharmony_ci skb = skb_share_check(skb, GFP_ATOMIC); 54998c2ecf20Sopenharmony_ci if (unlikely(!skb)) 55008c2ecf20Sopenharmony_ci goto err_free; 55018c2ecf20Sopenharmony_ci /* We may access the two bytes after vlan_hdr in vlan_set_encap_proto(). */ 55028c2ecf20Sopenharmony_ci if (unlikely(!pskb_may_pull(skb, VLAN_HLEN + sizeof(unsigned short)))) 55038c2ecf20Sopenharmony_ci goto err_free; 55048c2ecf20Sopenharmony_ci 55058c2ecf20Sopenharmony_ci vhdr = (struct vlan_hdr *)skb->data; 55068c2ecf20Sopenharmony_ci vlan_tci = ntohs(vhdr->h_vlan_TCI); 55078c2ecf20Sopenharmony_ci __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci); 55088c2ecf20Sopenharmony_ci 55098c2ecf20Sopenharmony_ci skb_pull_rcsum(skb, VLAN_HLEN); 55108c2ecf20Sopenharmony_ci vlan_set_encap_proto(skb, vhdr); 55118c2ecf20Sopenharmony_ci 55128c2ecf20Sopenharmony_ci skb = skb_reorder_vlan_header(skb); 55138c2ecf20Sopenharmony_ci if (unlikely(!skb)) 55148c2ecf20Sopenharmony_ci goto err_free; 55158c2ecf20Sopenharmony_ci 55168c2ecf20Sopenharmony_ci skb_reset_network_header(skb); 55178c2ecf20Sopenharmony_ci skb_reset_transport_header(skb); 55188c2ecf20Sopenharmony_ci skb_reset_mac_len(skb); 55198c2ecf20Sopenharmony_ci 55208c2ecf20Sopenharmony_ci return skb; 55218c2ecf20Sopenharmony_ci 55228c2ecf20Sopenharmony_cierr_free: 55238c2ecf20Sopenharmony_ci kfree_skb(skb); 55248c2ecf20Sopenharmony_ci return NULL; 55258c2ecf20Sopenharmony_ci} 55268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_vlan_untag); 55278c2ecf20Sopenharmony_ci 55288c2ecf20Sopenharmony_ciint skb_ensure_writable(struct sk_buff *skb, int write_len) 55298c2ecf20Sopenharmony_ci{ 55308c2ecf20Sopenharmony_ci if (!pskb_may_pull(skb, write_len)) 55318c2ecf20Sopenharmony_ci return -ENOMEM; 55328c2ecf20Sopenharmony_ci 55338c2ecf20Sopenharmony_ci if (!skb_cloned(skb) || skb_clone_writable(skb, write_len)) 55348c2ecf20Sopenharmony_ci return 0; 55358c2ecf20Sopenharmony_ci 55368c2ecf20Sopenharmony_ci return pskb_expand_head(skb, 0, 0, GFP_ATOMIC); 55378c2ecf20Sopenharmony_ci} 55388c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_ensure_writable); 55398c2ecf20Sopenharmony_ci 55408c2ecf20Sopenharmony_ci/* remove VLAN header from packet and update csum accordingly. 55418c2ecf20Sopenharmony_ci * expects a non skb_vlan_tag_present skb with a vlan tag payload 55428c2ecf20Sopenharmony_ci */ 55438c2ecf20Sopenharmony_ciint __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci) 55448c2ecf20Sopenharmony_ci{ 55458c2ecf20Sopenharmony_ci struct vlan_hdr *vhdr; 55468c2ecf20Sopenharmony_ci int offset = skb->data - skb_mac_header(skb); 55478c2ecf20Sopenharmony_ci int err; 55488c2ecf20Sopenharmony_ci 55498c2ecf20Sopenharmony_ci if (WARN_ONCE(offset, 55508c2ecf20Sopenharmony_ci "__skb_vlan_pop got skb with skb->data not at mac header (offset %d)\n", 55518c2ecf20Sopenharmony_ci offset)) { 55528c2ecf20Sopenharmony_ci return -EINVAL; 55538c2ecf20Sopenharmony_ci } 55548c2ecf20Sopenharmony_ci 55558c2ecf20Sopenharmony_ci err = skb_ensure_writable(skb, VLAN_ETH_HLEN); 55568c2ecf20Sopenharmony_ci if (unlikely(err)) 55578c2ecf20Sopenharmony_ci return err; 55588c2ecf20Sopenharmony_ci 55598c2ecf20Sopenharmony_ci skb_postpull_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN); 55608c2ecf20Sopenharmony_ci 55618c2ecf20Sopenharmony_ci vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN); 55628c2ecf20Sopenharmony_ci *vlan_tci = ntohs(vhdr->h_vlan_TCI); 55638c2ecf20Sopenharmony_ci 55648c2ecf20Sopenharmony_ci memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN); 55658c2ecf20Sopenharmony_ci __skb_pull(skb, VLAN_HLEN); 55668c2ecf20Sopenharmony_ci 55678c2ecf20Sopenharmony_ci vlan_set_encap_proto(skb, vhdr); 55688c2ecf20Sopenharmony_ci skb->mac_header += VLAN_HLEN; 55698c2ecf20Sopenharmony_ci 55708c2ecf20Sopenharmony_ci if (skb_network_offset(skb) < ETH_HLEN) 55718c2ecf20Sopenharmony_ci skb_set_network_header(skb, ETH_HLEN); 55728c2ecf20Sopenharmony_ci 55738c2ecf20Sopenharmony_ci skb_reset_mac_len(skb); 55748c2ecf20Sopenharmony_ci 55758c2ecf20Sopenharmony_ci return err; 55768c2ecf20Sopenharmony_ci} 55778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__skb_vlan_pop); 55788c2ecf20Sopenharmony_ci 55798c2ecf20Sopenharmony_ci/* Pop a vlan tag either from hwaccel or from payload. 55808c2ecf20Sopenharmony_ci * Expects skb->data at mac header. 55818c2ecf20Sopenharmony_ci */ 55828c2ecf20Sopenharmony_ciint skb_vlan_pop(struct sk_buff *skb) 55838c2ecf20Sopenharmony_ci{ 55848c2ecf20Sopenharmony_ci u16 vlan_tci; 55858c2ecf20Sopenharmony_ci __be16 vlan_proto; 55868c2ecf20Sopenharmony_ci int err; 55878c2ecf20Sopenharmony_ci 55888c2ecf20Sopenharmony_ci if (likely(skb_vlan_tag_present(skb))) { 55898c2ecf20Sopenharmony_ci __vlan_hwaccel_clear_tag(skb); 55908c2ecf20Sopenharmony_ci } else { 55918c2ecf20Sopenharmony_ci if (unlikely(!eth_type_vlan(skb->protocol))) 55928c2ecf20Sopenharmony_ci return 0; 55938c2ecf20Sopenharmony_ci 55948c2ecf20Sopenharmony_ci err = __skb_vlan_pop(skb, &vlan_tci); 55958c2ecf20Sopenharmony_ci if (err) 55968c2ecf20Sopenharmony_ci return err; 55978c2ecf20Sopenharmony_ci } 55988c2ecf20Sopenharmony_ci /* move next vlan tag to hw accel tag */ 55998c2ecf20Sopenharmony_ci if (likely(!eth_type_vlan(skb->protocol))) 56008c2ecf20Sopenharmony_ci return 0; 56018c2ecf20Sopenharmony_ci 56028c2ecf20Sopenharmony_ci vlan_proto = skb->protocol; 56038c2ecf20Sopenharmony_ci err = __skb_vlan_pop(skb, &vlan_tci); 56048c2ecf20Sopenharmony_ci if (unlikely(err)) 56058c2ecf20Sopenharmony_ci return err; 56068c2ecf20Sopenharmony_ci 56078c2ecf20Sopenharmony_ci __vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci); 56088c2ecf20Sopenharmony_ci return 0; 56098c2ecf20Sopenharmony_ci} 56108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_vlan_pop); 56118c2ecf20Sopenharmony_ci 56128c2ecf20Sopenharmony_ci/* Push a vlan tag either into hwaccel or into payload (if hwaccel tag present). 56138c2ecf20Sopenharmony_ci * Expects skb->data at mac header. 56148c2ecf20Sopenharmony_ci */ 56158c2ecf20Sopenharmony_ciint skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) 56168c2ecf20Sopenharmony_ci{ 56178c2ecf20Sopenharmony_ci if (skb_vlan_tag_present(skb)) { 56188c2ecf20Sopenharmony_ci int offset = skb->data - skb_mac_header(skb); 56198c2ecf20Sopenharmony_ci int err; 56208c2ecf20Sopenharmony_ci 56218c2ecf20Sopenharmony_ci if (WARN_ONCE(offset, 56228c2ecf20Sopenharmony_ci "skb_vlan_push got skb with skb->data not at mac header (offset %d)\n", 56238c2ecf20Sopenharmony_ci offset)) { 56248c2ecf20Sopenharmony_ci return -EINVAL; 56258c2ecf20Sopenharmony_ci } 56268c2ecf20Sopenharmony_ci 56278c2ecf20Sopenharmony_ci err = __vlan_insert_tag(skb, skb->vlan_proto, 56288c2ecf20Sopenharmony_ci skb_vlan_tag_get(skb)); 56298c2ecf20Sopenharmony_ci if (err) 56308c2ecf20Sopenharmony_ci return err; 56318c2ecf20Sopenharmony_ci 56328c2ecf20Sopenharmony_ci skb->protocol = skb->vlan_proto; 56338c2ecf20Sopenharmony_ci skb->mac_len += VLAN_HLEN; 56348c2ecf20Sopenharmony_ci 56358c2ecf20Sopenharmony_ci skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN); 56368c2ecf20Sopenharmony_ci } 56378c2ecf20Sopenharmony_ci __vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci); 56388c2ecf20Sopenharmony_ci return 0; 56398c2ecf20Sopenharmony_ci} 56408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_vlan_push); 56418c2ecf20Sopenharmony_ci 56428c2ecf20Sopenharmony_ci/** 56438c2ecf20Sopenharmony_ci * skb_eth_pop() - Drop the Ethernet header at the head of a packet 56448c2ecf20Sopenharmony_ci * 56458c2ecf20Sopenharmony_ci * @skb: Socket buffer to modify 56468c2ecf20Sopenharmony_ci * 56478c2ecf20Sopenharmony_ci * Drop the Ethernet header of @skb. 56488c2ecf20Sopenharmony_ci * 56498c2ecf20Sopenharmony_ci * Expects that skb->data points to the mac header and that no VLAN tags are 56508c2ecf20Sopenharmony_ci * present. 56518c2ecf20Sopenharmony_ci * 56528c2ecf20Sopenharmony_ci * Returns 0 on success, -errno otherwise. 56538c2ecf20Sopenharmony_ci */ 56548c2ecf20Sopenharmony_ciint skb_eth_pop(struct sk_buff *skb) 56558c2ecf20Sopenharmony_ci{ 56568c2ecf20Sopenharmony_ci if (!pskb_may_pull(skb, ETH_HLEN) || skb_vlan_tagged(skb) || 56578c2ecf20Sopenharmony_ci skb_network_offset(skb) < ETH_HLEN) 56588c2ecf20Sopenharmony_ci return -EPROTO; 56598c2ecf20Sopenharmony_ci 56608c2ecf20Sopenharmony_ci skb_pull_rcsum(skb, ETH_HLEN); 56618c2ecf20Sopenharmony_ci skb_reset_mac_header(skb); 56628c2ecf20Sopenharmony_ci skb_reset_mac_len(skb); 56638c2ecf20Sopenharmony_ci 56648c2ecf20Sopenharmony_ci return 0; 56658c2ecf20Sopenharmony_ci} 56668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_eth_pop); 56678c2ecf20Sopenharmony_ci 56688c2ecf20Sopenharmony_ci/** 56698c2ecf20Sopenharmony_ci * skb_eth_push() - Add a new Ethernet header at the head of a packet 56708c2ecf20Sopenharmony_ci * 56718c2ecf20Sopenharmony_ci * @skb: Socket buffer to modify 56728c2ecf20Sopenharmony_ci * @dst: Destination MAC address of the new header 56738c2ecf20Sopenharmony_ci * @src: Source MAC address of the new header 56748c2ecf20Sopenharmony_ci * 56758c2ecf20Sopenharmony_ci * Prepend @skb with a new Ethernet header. 56768c2ecf20Sopenharmony_ci * 56778c2ecf20Sopenharmony_ci * Expects that skb->data points to the mac header, which must be empty. 56788c2ecf20Sopenharmony_ci * 56798c2ecf20Sopenharmony_ci * Returns 0 on success, -errno otherwise. 56808c2ecf20Sopenharmony_ci */ 56818c2ecf20Sopenharmony_ciint skb_eth_push(struct sk_buff *skb, const unsigned char *dst, 56828c2ecf20Sopenharmony_ci const unsigned char *src) 56838c2ecf20Sopenharmony_ci{ 56848c2ecf20Sopenharmony_ci struct ethhdr *eth; 56858c2ecf20Sopenharmony_ci int err; 56868c2ecf20Sopenharmony_ci 56878c2ecf20Sopenharmony_ci if (skb_network_offset(skb) || skb_vlan_tag_present(skb)) 56888c2ecf20Sopenharmony_ci return -EPROTO; 56898c2ecf20Sopenharmony_ci 56908c2ecf20Sopenharmony_ci err = skb_cow_head(skb, sizeof(*eth)); 56918c2ecf20Sopenharmony_ci if (err < 0) 56928c2ecf20Sopenharmony_ci return err; 56938c2ecf20Sopenharmony_ci 56948c2ecf20Sopenharmony_ci skb_push(skb, sizeof(*eth)); 56958c2ecf20Sopenharmony_ci skb_reset_mac_header(skb); 56968c2ecf20Sopenharmony_ci skb_reset_mac_len(skb); 56978c2ecf20Sopenharmony_ci 56988c2ecf20Sopenharmony_ci eth = eth_hdr(skb); 56998c2ecf20Sopenharmony_ci ether_addr_copy(eth->h_dest, dst); 57008c2ecf20Sopenharmony_ci ether_addr_copy(eth->h_source, src); 57018c2ecf20Sopenharmony_ci eth->h_proto = skb->protocol; 57028c2ecf20Sopenharmony_ci 57038c2ecf20Sopenharmony_ci skb_postpush_rcsum(skb, eth, sizeof(*eth)); 57048c2ecf20Sopenharmony_ci 57058c2ecf20Sopenharmony_ci return 0; 57068c2ecf20Sopenharmony_ci} 57078c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_eth_push); 57088c2ecf20Sopenharmony_ci 57098c2ecf20Sopenharmony_ci/* Update the ethertype of hdr and the skb csum value if required. */ 57108c2ecf20Sopenharmony_cistatic void skb_mod_eth_type(struct sk_buff *skb, struct ethhdr *hdr, 57118c2ecf20Sopenharmony_ci __be16 ethertype) 57128c2ecf20Sopenharmony_ci{ 57138c2ecf20Sopenharmony_ci if (skb->ip_summed == CHECKSUM_COMPLETE) { 57148c2ecf20Sopenharmony_ci __be16 diff[] = { ~hdr->h_proto, ethertype }; 57158c2ecf20Sopenharmony_ci 57168c2ecf20Sopenharmony_ci skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum); 57178c2ecf20Sopenharmony_ci } 57188c2ecf20Sopenharmony_ci 57198c2ecf20Sopenharmony_ci hdr->h_proto = ethertype; 57208c2ecf20Sopenharmony_ci} 57218c2ecf20Sopenharmony_ci 57228c2ecf20Sopenharmony_ci/** 57238c2ecf20Sopenharmony_ci * skb_mpls_push() - push a new MPLS header after mac_len bytes from start of 57248c2ecf20Sopenharmony_ci * the packet 57258c2ecf20Sopenharmony_ci * 57268c2ecf20Sopenharmony_ci * @skb: buffer 57278c2ecf20Sopenharmony_ci * @mpls_lse: MPLS label stack entry to push 57288c2ecf20Sopenharmony_ci * @mpls_proto: ethertype of the new MPLS header (expects 0x8847 or 0x8848) 57298c2ecf20Sopenharmony_ci * @mac_len: length of the MAC header 57308c2ecf20Sopenharmony_ci * @ethernet: flag to indicate if the resulting packet after skb_mpls_push is 57318c2ecf20Sopenharmony_ci * ethernet 57328c2ecf20Sopenharmony_ci * 57338c2ecf20Sopenharmony_ci * Expects skb->data at mac header. 57348c2ecf20Sopenharmony_ci * 57358c2ecf20Sopenharmony_ci * Returns 0 on success, -errno otherwise. 57368c2ecf20Sopenharmony_ci */ 57378c2ecf20Sopenharmony_ciint skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, 57388c2ecf20Sopenharmony_ci int mac_len, bool ethernet) 57398c2ecf20Sopenharmony_ci{ 57408c2ecf20Sopenharmony_ci struct mpls_shim_hdr *lse; 57418c2ecf20Sopenharmony_ci int err; 57428c2ecf20Sopenharmony_ci 57438c2ecf20Sopenharmony_ci if (unlikely(!eth_p_mpls(mpls_proto))) 57448c2ecf20Sopenharmony_ci return -EINVAL; 57458c2ecf20Sopenharmony_ci 57468c2ecf20Sopenharmony_ci /* Networking stack does not allow simultaneous Tunnel and MPLS GSO. */ 57478c2ecf20Sopenharmony_ci if (skb->encapsulation) 57488c2ecf20Sopenharmony_ci return -EINVAL; 57498c2ecf20Sopenharmony_ci 57508c2ecf20Sopenharmony_ci err = skb_cow_head(skb, MPLS_HLEN); 57518c2ecf20Sopenharmony_ci if (unlikely(err)) 57528c2ecf20Sopenharmony_ci return err; 57538c2ecf20Sopenharmony_ci 57548c2ecf20Sopenharmony_ci if (!skb->inner_protocol) { 57558c2ecf20Sopenharmony_ci skb_set_inner_network_header(skb, skb_network_offset(skb)); 57568c2ecf20Sopenharmony_ci skb_set_inner_protocol(skb, skb->protocol); 57578c2ecf20Sopenharmony_ci } 57588c2ecf20Sopenharmony_ci 57598c2ecf20Sopenharmony_ci skb_push(skb, MPLS_HLEN); 57608c2ecf20Sopenharmony_ci memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb), 57618c2ecf20Sopenharmony_ci mac_len); 57628c2ecf20Sopenharmony_ci skb_reset_mac_header(skb); 57638c2ecf20Sopenharmony_ci skb_set_network_header(skb, mac_len); 57648c2ecf20Sopenharmony_ci skb_reset_mac_len(skb); 57658c2ecf20Sopenharmony_ci 57668c2ecf20Sopenharmony_ci lse = mpls_hdr(skb); 57678c2ecf20Sopenharmony_ci lse->label_stack_entry = mpls_lse; 57688c2ecf20Sopenharmony_ci skb_postpush_rcsum(skb, lse, MPLS_HLEN); 57698c2ecf20Sopenharmony_ci 57708c2ecf20Sopenharmony_ci if (ethernet && mac_len >= ETH_HLEN) 57718c2ecf20Sopenharmony_ci skb_mod_eth_type(skb, eth_hdr(skb), mpls_proto); 57728c2ecf20Sopenharmony_ci skb->protocol = mpls_proto; 57738c2ecf20Sopenharmony_ci 57748c2ecf20Sopenharmony_ci return 0; 57758c2ecf20Sopenharmony_ci} 57768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_mpls_push); 57778c2ecf20Sopenharmony_ci 57788c2ecf20Sopenharmony_ci/** 57798c2ecf20Sopenharmony_ci * skb_mpls_pop() - pop the outermost MPLS header 57808c2ecf20Sopenharmony_ci * 57818c2ecf20Sopenharmony_ci * @skb: buffer 57828c2ecf20Sopenharmony_ci * @next_proto: ethertype of header after popped MPLS header 57838c2ecf20Sopenharmony_ci * @mac_len: length of the MAC header 57848c2ecf20Sopenharmony_ci * @ethernet: flag to indicate if the packet is ethernet 57858c2ecf20Sopenharmony_ci * 57868c2ecf20Sopenharmony_ci * Expects skb->data at mac header. 57878c2ecf20Sopenharmony_ci * 57888c2ecf20Sopenharmony_ci * Returns 0 on success, -errno otherwise. 57898c2ecf20Sopenharmony_ci */ 57908c2ecf20Sopenharmony_ciint skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len, 57918c2ecf20Sopenharmony_ci bool ethernet) 57928c2ecf20Sopenharmony_ci{ 57938c2ecf20Sopenharmony_ci int err; 57948c2ecf20Sopenharmony_ci 57958c2ecf20Sopenharmony_ci if (unlikely(!eth_p_mpls(skb->protocol))) 57968c2ecf20Sopenharmony_ci return 0; 57978c2ecf20Sopenharmony_ci 57988c2ecf20Sopenharmony_ci err = skb_ensure_writable(skb, mac_len + MPLS_HLEN); 57998c2ecf20Sopenharmony_ci if (unlikely(err)) 58008c2ecf20Sopenharmony_ci return err; 58018c2ecf20Sopenharmony_ci 58028c2ecf20Sopenharmony_ci skb_postpull_rcsum(skb, mpls_hdr(skb), MPLS_HLEN); 58038c2ecf20Sopenharmony_ci memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb), 58048c2ecf20Sopenharmony_ci mac_len); 58058c2ecf20Sopenharmony_ci 58068c2ecf20Sopenharmony_ci __skb_pull(skb, MPLS_HLEN); 58078c2ecf20Sopenharmony_ci skb_reset_mac_header(skb); 58088c2ecf20Sopenharmony_ci skb_set_network_header(skb, mac_len); 58098c2ecf20Sopenharmony_ci 58108c2ecf20Sopenharmony_ci if (ethernet && mac_len >= ETH_HLEN) { 58118c2ecf20Sopenharmony_ci struct ethhdr *hdr; 58128c2ecf20Sopenharmony_ci 58138c2ecf20Sopenharmony_ci /* use mpls_hdr() to get ethertype to account for VLANs. */ 58148c2ecf20Sopenharmony_ci hdr = (struct ethhdr *)((void *)mpls_hdr(skb) - ETH_HLEN); 58158c2ecf20Sopenharmony_ci skb_mod_eth_type(skb, hdr, next_proto); 58168c2ecf20Sopenharmony_ci } 58178c2ecf20Sopenharmony_ci skb->protocol = next_proto; 58188c2ecf20Sopenharmony_ci 58198c2ecf20Sopenharmony_ci return 0; 58208c2ecf20Sopenharmony_ci} 58218c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_mpls_pop); 58228c2ecf20Sopenharmony_ci 58238c2ecf20Sopenharmony_ci/** 58248c2ecf20Sopenharmony_ci * skb_mpls_update_lse() - modify outermost MPLS header and update csum 58258c2ecf20Sopenharmony_ci * 58268c2ecf20Sopenharmony_ci * @skb: buffer 58278c2ecf20Sopenharmony_ci * @mpls_lse: new MPLS label stack entry to update to 58288c2ecf20Sopenharmony_ci * 58298c2ecf20Sopenharmony_ci * Expects skb->data at mac header. 58308c2ecf20Sopenharmony_ci * 58318c2ecf20Sopenharmony_ci * Returns 0 on success, -errno otherwise. 58328c2ecf20Sopenharmony_ci */ 58338c2ecf20Sopenharmony_ciint skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse) 58348c2ecf20Sopenharmony_ci{ 58358c2ecf20Sopenharmony_ci int err; 58368c2ecf20Sopenharmony_ci 58378c2ecf20Sopenharmony_ci if (unlikely(!eth_p_mpls(skb->protocol))) 58388c2ecf20Sopenharmony_ci return -EINVAL; 58398c2ecf20Sopenharmony_ci 58408c2ecf20Sopenharmony_ci err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN); 58418c2ecf20Sopenharmony_ci if (unlikely(err)) 58428c2ecf20Sopenharmony_ci return err; 58438c2ecf20Sopenharmony_ci 58448c2ecf20Sopenharmony_ci if (skb->ip_summed == CHECKSUM_COMPLETE) { 58458c2ecf20Sopenharmony_ci __be32 diff[] = { ~mpls_hdr(skb)->label_stack_entry, mpls_lse }; 58468c2ecf20Sopenharmony_ci 58478c2ecf20Sopenharmony_ci skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum); 58488c2ecf20Sopenharmony_ci } 58498c2ecf20Sopenharmony_ci 58508c2ecf20Sopenharmony_ci mpls_hdr(skb)->label_stack_entry = mpls_lse; 58518c2ecf20Sopenharmony_ci 58528c2ecf20Sopenharmony_ci return 0; 58538c2ecf20Sopenharmony_ci} 58548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_mpls_update_lse); 58558c2ecf20Sopenharmony_ci 58568c2ecf20Sopenharmony_ci/** 58578c2ecf20Sopenharmony_ci * skb_mpls_dec_ttl() - decrement the TTL of the outermost MPLS header 58588c2ecf20Sopenharmony_ci * 58598c2ecf20Sopenharmony_ci * @skb: buffer 58608c2ecf20Sopenharmony_ci * 58618c2ecf20Sopenharmony_ci * Expects skb->data at mac header. 58628c2ecf20Sopenharmony_ci * 58638c2ecf20Sopenharmony_ci * Returns 0 on success, -errno otherwise. 58648c2ecf20Sopenharmony_ci */ 58658c2ecf20Sopenharmony_ciint skb_mpls_dec_ttl(struct sk_buff *skb) 58668c2ecf20Sopenharmony_ci{ 58678c2ecf20Sopenharmony_ci u32 lse; 58688c2ecf20Sopenharmony_ci u8 ttl; 58698c2ecf20Sopenharmony_ci 58708c2ecf20Sopenharmony_ci if (unlikely(!eth_p_mpls(skb->protocol))) 58718c2ecf20Sopenharmony_ci return -EINVAL; 58728c2ecf20Sopenharmony_ci 58738c2ecf20Sopenharmony_ci if (!pskb_may_pull(skb, skb_network_offset(skb) + MPLS_HLEN)) 58748c2ecf20Sopenharmony_ci return -ENOMEM; 58758c2ecf20Sopenharmony_ci 58768c2ecf20Sopenharmony_ci lse = be32_to_cpu(mpls_hdr(skb)->label_stack_entry); 58778c2ecf20Sopenharmony_ci ttl = (lse & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT; 58788c2ecf20Sopenharmony_ci if (!--ttl) 58798c2ecf20Sopenharmony_ci return -EINVAL; 58808c2ecf20Sopenharmony_ci 58818c2ecf20Sopenharmony_ci lse &= ~MPLS_LS_TTL_MASK; 58828c2ecf20Sopenharmony_ci lse |= ttl << MPLS_LS_TTL_SHIFT; 58838c2ecf20Sopenharmony_ci 58848c2ecf20Sopenharmony_ci return skb_mpls_update_lse(skb, cpu_to_be32(lse)); 58858c2ecf20Sopenharmony_ci} 58868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skb_mpls_dec_ttl); 58878c2ecf20Sopenharmony_ci 58888c2ecf20Sopenharmony_ci/** 58898c2ecf20Sopenharmony_ci * alloc_skb_with_frags - allocate skb with page frags 58908c2ecf20Sopenharmony_ci * 58918c2ecf20Sopenharmony_ci * @header_len: size of linear part 58928c2ecf20Sopenharmony_ci * @data_len: needed length in frags 58938c2ecf20Sopenharmony_ci * @max_page_order: max page order desired. 58948c2ecf20Sopenharmony_ci * @errcode: pointer to error code if any 58958c2ecf20Sopenharmony_ci * @gfp_mask: allocation mask 58968c2ecf20Sopenharmony_ci * 58978c2ecf20Sopenharmony_ci * This can be used to allocate a paged skb, given a maximal order for frags. 58988c2ecf20Sopenharmony_ci */ 58998c2ecf20Sopenharmony_cistruct sk_buff *alloc_skb_with_frags(unsigned long header_len, 59008c2ecf20Sopenharmony_ci unsigned long data_len, 59018c2ecf20Sopenharmony_ci int max_page_order, 59028c2ecf20Sopenharmony_ci int *errcode, 59038c2ecf20Sopenharmony_ci gfp_t gfp_mask) 59048c2ecf20Sopenharmony_ci{ 59058c2ecf20Sopenharmony_ci int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 59068c2ecf20Sopenharmony_ci unsigned long chunk; 59078c2ecf20Sopenharmony_ci struct sk_buff *skb; 59088c2ecf20Sopenharmony_ci struct page *page; 59098c2ecf20Sopenharmony_ci int i; 59108c2ecf20Sopenharmony_ci 59118c2ecf20Sopenharmony_ci *errcode = -EMSGSIZE; 59128c2ecf20Sopenharmony_ci /* Note this test could be relaxed, if we succeed to allocate 59138c2ecf20Sopenharmony_ci * high order pages... 59148c2ecf20Sopenharmony_ci */ 59158c2ecf20Sopenharmony_ci if (npages > MAX_SKB_FRAGS) 59168c2ecf20Sopenharmony_ci return NULL; 59178c2ecf20Sopenharmony_ci 59188c2ecf20Sopenharmony_ci *errcode = -ENOBUFS; 59198c2ecf20Sopenharmony_ci skb = alloc_skb(header_len, gfp_mask); 59208c2ecf20Sopenharmony_ci if (!skb) 59218c2ecf20Sopenharmony_ci return NULL; 59228c2ecf20Sopenharmony_ci 59238c2ecf20Sopenharmony_ci skb->truesize += npages << PAGE_SHIFT; 59248c2ecf20Sopenharmony_ci 59258c2ecf20Sopenharmony_ci for (i = 0; npages > 0; i++) { 59268c2ecf20Sopenharmony_ci int order = max_page_order; 59278c2ecf20Sopenharmony_ci 59288c2ecf20Sopenharmony_ci while (order) { 59298c2ecf20Sopenharmony_ci if (npages >= 1 << order) { 59308c2ecf20Sopenharmony_ci page = alloc_pages((gfp_mask & ~__GFP_DIRECT_RECLAIM) | 59318c2ecf20Sopenharmony_ci __GFP_COMP | 59328c2ecf20Sopenharmony_ci __GFP_NOWARN, 59338c2ecf20Sopenharmony_ci order); 59348c2ecf20Sopenharmony_ci if (page) 59358c2ecf20Sopenharmony_ci goto fill_page; 59368c2ecf20Sopenharmony_ci /* Do not retry other high order allocations */ 59378c2ecf20Sopenharmony_ci order = 1; 59388c2ecf20Sopenharmony_ci max_page_order = 0; 59398c2ecf20Sopenharmony_ci } 59408c2ecf20Sopenharmony_ci order--; 59418c2ecf20Sopenharmony_ci } 59428c2ecf20Sopenharmony_ci page = alloc_page(gfp_mask); 59438c2ecf20Sopenharmony_ci if (!page) 59448c2ecf20Sopenharmony_ci goto failure; 59458c2ecf20Sopenharmony_cifill_page: 59468c2ecf20Sopenharmony_ci chunk = min_t(unsigned long, data_len, 59478c2ecf20Sopenharmony_ci PAGE_SIZE << order); 59488c2ecf20Sopenharmony_ci skb_fill_page_desc(skb, i, page, 0, chunk); 59498c2ecf20Sopenharmony_ci data_len -= chunk; 59508c2ecf20Sopenharmony_ci npages -= 1 << order; 59518c2ecf20Sopenharmony_ci } 59528c2ecf20Sopenharmony_ci return skb; 59538c2ecf20Sopenharmony_ci 59548c2ecf20Sopenharmony_cifailure: 59558c2ecf20Sopenharmony_ci kfree_skb(skb); 59568c2ecf20Sopenharmony_ci return NULL; 59578c2ecf20Sopenharmony_ci} 59588c2ecf20Sopenharmony_ciEXPORT_SYMBOL(alloc_skb_with_frags); 59598c2ecf20Sopenharmony_ci 59608c2ecf20Sopenharmony_ci/* carve out the first off bytes from skb when off < headlen */ 59618c2ecf20Sopenharmony_cistatic int pskb_carve_inside_header(struct sk_buff *skb, const u32 off, 59628c2ecf20Sopenharmony_ci const int headlen, gfp_t gfp_mask) 59638c2ecf20Sopenharmony_ci{ 59648c2ecf20Sopenharmony_ci int i; 59658c2ecf20Sopenharmony_ci int size = skb_end_offset(skb); 59668c2ecf20Sopenharmony_ci int new_hlen = headlen - off; 59678c2ecf20Sopenharmony_ci u8 *data; 59688c2ecf20Sopenharmony_ci 59698c2ecf20Sopenharmony_ci size = SKB_DATA_ALIGN(size); 59708c2ecf20Sopenharmony_ci 59718c2ecf20Sopenharmony_ci if (skb_pfmemalloc(skb)) 59728c2ecf20Sopenharmony_ci gfp_mask |= __GFP_MEMALLOC; 59738c2ecf20Sopenharmony_ci data = kmalloc_reserve(size + 59748c2ecf20Sopenharmony_ci SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), 59758c2ecf20Sopenharmony_ci gfp_mask, NUMA_NO_NODE, NULL); 59768c2ecf20Sopenharmony_ci if (!data) 59778c2ecf20Sopenharmony_ci return -ENOMEM; 59788c2ecf20Sopenharmony_ci 59798c2ecf20Sopenharmony_ci size = SKB_WITH_OVERHEAD(ksize(data)); 59808c2ecf20Sopenharmony_ci 59818c2ecf20Sopenharmony_ci /* Copy real data, and all frags */ 59828c2ecf20Sopenharmony_ci skb_copy_from_linear_data_offset(skb, off, data, new_hlen); 59838c2ecf20Sopenharmony_ci skb->len -= off; 59848c2ecf20Sopenharmony_ci 59858c2ecf20Sopenharmony_ci memcpy((struct skb_shared_info *)(data + size), 59868c2ecf20Sopenharmony_ci skb_shinfo(skb), 59878c2ecf20Sopenharmony_ci offsetof(struct skb_shared_info, 59888c2ecf20Sopenharmony_ci frags[skb_shinfo(skb)->nr_frags])); 59898c2ecf20Sopenharmony_ci if (skb_cloned(skb)) { 59908c2ecf20Sopenharmony_ci /* drop the old head gracefully */ 59918c2ecf20Sopenharmony_ci if (skb_orphan_frags(skb, gfp_mask)) { 59928c2ecf20Sopenharmony_ci kfree(data); 59938c2ecf20Sopenharmony_ci return -ENOMEM; 59948c2ecf20Sopenharmony_ci } 59958c2ecf20Sopenharmony_ci for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) 59968c2ecf20Sopenharmony_ci skb_frag_ref(skb, i); 59978c2ecf20Sopenharmony_ci if (skb_has_frag_list(skb)) 59988c2ecf20Sopenharmony_ci skb_clone_fraglist(skb); 59998c2ecf20Sopenharmony_ci skb_release_data(skb); 60008c2ecf20Sopenharmony_ci } else { 60018c2ecf20Sopenharmony_ci /* we can reuse existing recount- all we did was 60028c2ecf20Sopenharmony_ci * relocate values 60038c2ecf20Sopenharmony_ci */ 60048c2ecf20Sopenharmony_ci skb_free_head(skb); 60058c2ecf20Sopenharmony_ci } 60068c2ecf20Sopenharmony_ci 60078c2ecf20Sopenharmony_ci skb->head = data; 60088c2ecf20Sopenharmony_ci skb->data = data; 60098c2ecf20Sopenharmony_ci skb->head_frag = 0; 60108c2ecf20Sopenharmony_ci#ifdef NET_SKBUFF_DATA_USES_OFFSET 60118c2ecf20Sopenharmony_ci skb->end = size; 60128c2ecf20Sopenharmony_ci#else 60138c2ecf20Sopenharmony_ci skb->end = skb->head + size; 60148c2ecf20Sopenharmony_ci#endif 60158c2ecf20Sopenharmony_ci skb_set_tail_pointer(skb, skb_headlen(skb)); 60168c2ecf20Sopenharmony_ci skb_headers_offset_update(skb, 0); 60178c2ecf20Sopenharmony_ci skb->cloned = 0; 60188c2ecf20Sopenharmony_ci skb->hdr_len = 0; 60198c2ecf20Sopenharmony_ci skb->nohdr = 0; 60208c2ecf20Sopenharmony_ci atomic_set(&skb_shinfo(skb)->dataref, 1); 60218c2ecf20Sopenharmony_ci 60228c2ecf20Sopenharmony_ci return 0; 60238c2ecf20Sopenharmony_ci} 60248c2ecf20Sopenharmony_ci 60258c2ecf20Sopenharmony_cistatic int pskb_carve(struct sk_buff *skb, const u32 off, gfp_t gfp); 60268c2ecf20Sopenharmony_ci 60278c2ecf20Sopenharmony_ci/* carve out the first eat bytes from skb's frag_list. May recurse into 60288c2ecf20Sopenharmony_ci * pskb_carve() 60298c2ecf20Sopenharmony_ci */ 60308c2ecf20Sopenharmony_cistatic int pskb_carve_frag_list(struct sk_buff *skb, 60318c2ecf20Sopenharmony_ci struct skb_shared_info *shinfo, int eat, 60328c2ecf20Sopenharmony_ci gfp_t gfp_mask) 60338c2ecf20Sopenharmony_ci{ 60348c2ecf20Sopenharmony_ci struct sk_buff *list = shinfo->frag_list; 60358c2ecf20Sopenharmony_ci struct sk_buff *clone = NULL; 60368c2ecf20Sopenharmony_ci struct sk_buff *insp = NULL; 60378c2ecf20Sopenharmony_ci 60388c2ecf20Sopenharmony_ci do { 60398c2ecf20Sopenharmony_ci if (!list) { 60408c2ecf20Sopenharmony_ci pr_err("Not enough bytes to eat. Want %d\n", eat); 60418c2ecf20Sopenharmony_ci return -EFAULT; 60428c2ecf20Sopenharmony_ci } 60438c2ecf20Sopenharmony_ci if (list->len <= eat) { 60448c2ecf20Sopenharmony_ci /* Eaten as whole. */ 60458c2ecf20Sopenharmony_ci eat -= list->len; 60468c2ecf20Sopenharmony_ci list = list->next; 60478c2ecf20Sopenharmony_ci insp = list; 60488c2ecf20Sopenharmony_ci } else { 60498c2ecf20Sopenharmony_ci /* Eaten partially. */ 60508c2ecf20Sopenharmony_ci if (skb_shared(list)) { 60518c2ecf20Sopenharmony_ci clone = skb_clone(list, gfp_mask); 60528c2ecf20Sopenharmony_ci if (!clone) 60538c2ecf20Sopenharmony_ci return -ENOMEM; 60548c2ecf20Sopenharmony_ci insp = list->next; 60558c2ecf20Sopenharmony_ci list = clone; 60568c2ecf20Sopenharmony_ci } else { 60578c2ecf20Sopenharmony_ci /* This may be pulled without problems. */ 60588c2ecf20Sopenharmony_ci insp = list; 60598c2ecf20Sopenharmony_ci } 60608c2ecf20Sopenharmony_ci if (pskb_carve(list, eat, gfp_mask) < 0) { 60618c2ecf20Sopenharmony_ci kfree_skb(clone); 60628c2ecf20Sopenharmony_ci return -ENOMEM; 60638c2ecf20Sopenharmony_ci } 60648c2ecf20Sopenharmony_ci break; 60658c2ecf20Sopenharmony_ci } 60668c2ecf20Sopenharmony_ci } while (eat); 60678c2ecf20Sopenharmony_ci 60688c2ecf20Sopenharmony_ci /* Free pulled out fragments. */ 60698c2ecf20Sopenharmony_ci while ((list = shinfo->frag_list) != insp) { 60708c2ecf20Sopenharmony_ci shinfo->frag_list = list->next; 60718c2ecf20Sopenharmony_ci consume_skb(list); 60728c2ecf20Sopenharmony_ci } 60738c2ecf20Sopenharmony_ci /* And insert new clone at head. */ 60748c2ecf20Sopenharmony_ci if (clone) { 60758c2ecf20Sopenharmony_ci clone->next = list; 60768c2ecf20Sopenharmony_ci shinfo->frag_list = clone; 60778c2ecf20Sopenharmony_ci } 60788c2ecf20Sopenharmony_ci return 0; 60798c2ecf20Sopenharmony_ci} 60808c2ecf20Sopenharmony_ci 60818c2ecf20Sopenharmony_ci/* carve off first len bytes from skb. Split line (off) is in the 60828c2ecf20Sopenharmony_ci * non-linear part of skb 60838c2ecf20Sopenharmony_ci */ 60848c2ecf20Sopenharmony_cistatic int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off, 60858c2ecf20Sopenharmony_ci int pos, gfp_t gfp_mask) 60868c2ecf20Sopenharmony_ci{ 60878c2ecf20Sopenharmony_ci int i, k = 0; 60888c2ecf20Sopenharmony_ci int size = skb_end_offset(skb); 60898c2ecf20Sopenharmony_ci u8 *data; 60908c2ecf20Sopenharmony_ci const int nfrags = skb_shinfo(skb)->nr_frags; 60918c2ecf20Sopenharmony_ci struct skb_shared_info *shinfo; 60928c2ecf20Sopenharmony_ci 60938c2ecf20Sopenharmony_ci size = SKB_DATA_ALIGN(size); 60948c2ecf20Sopenharmony_ci 60958c2ecf20Sopenharmony_ci if (skb_pfmemalloc(skb)) 60968c2ecf20Sopenharmony_ci gfp_mask |= __GFP_MEMALLOC; 60978c2ecf20Sopenharmony_ci data = kmalloc_reserve(size + 60988c2ecf20Sopenharmony_ci SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), 60998c2ecf20Sopenharmony_ci gfp_mask, NUMA_NO_NODE, NULL); 61008c2ecf20Sopenharmony_ci if (!data) 61018c2ecf20Sopenharmony_ci return -ENOMEM; 61028c2ecf20Sopenharmony_ci 61038c2ecf20Sopenharmony_ci size = SKB_WITH_OVERHEAD(ksize(data)); 61048c2ecf20Sopenharmony_ci 61058c2ecf20Sopenharmony_ci memcpy((struct skb_shared_info *)(data + size), 61068c2ecf20Sopenharmony_ci skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0])); 61078c2ecf20Sopenharmony_ci if (skb_orphan_frags(skb, gfp_mask)) { 61088c2ecf20Sopenharmony_ci kfree(data); 61098c2ecf20Sopenharmony_ci return -ENOMEM; 61108c2ecf20Sopenharmony_ci } 61118c2ecf20Sopenharmony_ci shinfo = (struct skb_shared_info *)(data + size); 61128c2ecf20Sopenharmony_ci for (i = 0; i < nfrags; i++) { 61138c2ecf20Sopenharmony_ci int fsize = skb_frag_size(&skb_shinfo(skb)->frags[i]); 61148c2ecf20Sopenharmony_ci 61158c2ecf20Sopenharmony_ci if (pos + fsize > off) { 61168c2ecf20Sopenharmony_ci shinfo->frags[k] = skb_shinfo(skb)->frags[i]; 61178c2ecf20Sopenharmony_ci 61188c2ecf20Sopenharmony_ci if (pos < off) { 61198c2ecf20Sopenharmony_ci /* Split frag. 61208c2ecf20Sopenharmony_ci * We have two variants in this case: 61218c2ecf20Sopenharmony_ci * 1. Move all the frag to the second 61228c2ecf20Sopenharmony_ci * part, if it is possible. F.e. 61238c2ecf20Sopenharmony_ci * this approach is mandatory for TUX, 61248c2ecf20Sopenharmony_ci * where splitting is expensive. 61258c2ecf20Sopenharmony_ci * 2. Split is accurately. We make this. 61268c2ecf20Sopenharmony_ci */ 61278c2ecf20Sopenharmony_ci skb_frag_off_add(&shinfo->frags[0], off - pos); 61288c2ecf20Sopenharmony_ci skb_frag_size_sub(&shinfo->frags[0], off - pos); 61298c2ecf20Sopenharmony_ci } 61308c2ecf20Sopenharmony_ci skb_frag_ref(skb, i); 61318c2ecf20Sopenharmony_ci k++; 61328c2ecf20Sopenharmony_ci } 61338c2ecf20Sopenharmony_ci pos += fsize; 61348c2ecf20Sopenharmony_ci } 61358c2ecf20Sopenharmony_ci shinfo->nr_frags = k; 61368c2ecf20Sopenharmony_ci if (skb_has_frag_list(skb)) 61378c2ecf20Sopenharmony_ci skb_clone_fraglist(skb); 61388c2ecf20Sopenharmony_ci 61398c2ecf20Sopenharmony_ci /* split line is in frag list */ 61408c2ecf20Sopenharmony_ci if (k == 0 && pskb_carve_frag_list(skb, shinfo, off - pos, gfp_mask)) { 61418c2ecf20Sopenharmony_ci /* skb_frag_unref() is not needed here as shinfo->nr_frags = 0. */ 61428c2ecf20Sopenharmony_ci if (skb_has_frag_list(skb)) 61438c2ecf20Sopenharmony_ci kfree_skb_list(skb_shinfo(skb)->frag_list); 61448c2ecf20Sopenharmony_ci kfree(data); 61458c2ecf20Sopenharmony_ci return -ENOMEM; 61468c2ecf20Sopenharmony_ci } 61478c2ecf20Sopenharmony_ci skb_release_data(skb); 61488c2ecf20Sopenharmony_ci 61498c2ecf20Sopenharmony_ci skb->head = data; 61508c2ecf20Sopenharmony_ci skb->head_frag = 0; 61518c2ecf20Sopenharmony_ci skb->data = data; 61528c2ecf20Sopenharmony_ci#ifdef NET_SKBUFF_DATA_USES_OFFSET 61538c2ecf20Sopenharmony_ci skb->end = size; 61548c2ecf20Sopenharmony_ci#else 61558c2ecf20Sopenharmony_ci skb->end = skb->head + size; 61568c2ecf20Sopenharmony_ci#endif 61578c2ecf20Sopenharmony_ci skb_reset_tail_pointer(skb); 61588c2ecf20Sopenharmony_ci skb_headers_offset_update(skb, 0); 61598c2ecf20Sopenharmony_ci skb->cloned = 0; 61608c2ecf20Sopenharmony_ci skb->hdr_len = 0; 61618c2ecf20Sopenharmony_ci skb->nohdr = 0; 61628c2ecf20Sopenharmony_ci skb->len -= off; 61638c2ecf20Sopenharmony_ci skb->data_len = skb->len; 61648c2ecf20Sopenharmony_ci atomic_set(&skb_shinfo(skb)->dataref, 1); 61658c2ecf20Sopenharmony_ci return 0; 61668c2ecf20Sopenharmony_ci} 61678c2ecf20Sopenharmony_ci 61688c2ecf20Sopenharmony_ci/* remove len bytes from the beginning of the skb */ 61698c2ecf20Sopenharmony_cistatic int pskb_carve(struct sk_buff *skb, const u32 len, gfp_t gfp) 61708c2ecf20Sopenharmony_ci{ 61718c2ecf20Sopenharmony_ci int headlen = skb_headlen(skb); 61728c2ecf20Sopenharmony_ci 61738c2ecf20Sopenharmony_ci if (len < headlen) 61748c2ecf20Sopenharmony_ci return pskb_carve_inside_header(skb, len, headlen, gfp); 61758c2ecf20Sopenharmony_ci else 61768c2ecf20Sopenharmony_ci return pskb_carve_inside_nonlinear(skb, len, headlen, gfp); 61778c2ecf20Sopenharmony_ci} 61788c2ecf20Sopenharmony_ci 61798c2ecf20Sopenharmony_ci/* Extract to_copy bytes starting at off from skb, and return this in 61808c2ecf20Sopenharmony_ci * a new skb 61818c2ecf20Sopenharmony_ci */ 61828c2ecf20Sopenharmony_cistruct sk_buff *pskb_extract(struct sk_buff *skb, int off, 61838c2ecf20Sopenharmony_ci int to_copy, gfp_t gfp) 61848c2ecf20Sopenharmony_ci{ 61858c2ecf20Sopenharmony_ci struct sk_buff *clone = skb_clone(skb, gfp); 61868c2ecf20Sopenharmony_ci 61878c2ecf20Sopenharmony_ci if (!clone) 61888c2ecf20Sopenharmony_ci return NULL; 61898c2ecf20Sopenharmony_ci 61908c2ecf20Sopenharmony_ci if (pskb_carve(clone, off, gfp) < 0 || 61918c2ecf20Sopenharmony_ci pskb_trim(clone, to_copy)) { 61928c2ecf20Sopenharmony_ci kfree_skb(clone); 61938c2ecf20Sopenharmony_ci return NULL; 61948c2ecf20Sopenharmony_ci } 61958c2ecf20Sopenharmony_ci return clone; 61968c2ecf20Sopenharmony_ci} 61978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pskb_extract); 61988c2ecf20Sopenharmony_ci 61998c2ecf20Sopenharmony_ci/** 62008c2ecf20Sopenharmony_ci * skb_condense - try to get rid of fragments/frag_list if possible 62018c2ecf20Sopenharmony_ci * @skb: buffer 62028c2ecf20Sopenharmony_ci * 62038c2ecf20Sopenharmony_ci * Can be used to save memory before skb is added to a busy queue. 62048c2ecf20Sopenharmony_ci * If packet has bytes in frags and enough tail room in skb->head, 62058c2ecf20Sopenharmony_ci * pull all of them, so that we can free the frags right now and adjust 62068c2ecf20Sopenharmony_ci * truesize. 62078c2ecf20Sopenharmony_ci * Notes: 62088c2ecf20Sopenharmony_ci * We do not reallocate skb->head thus can not fail. 62098c2ecf20Sopenharmony_ci * Caller must re-evaluate skb->truesize if needed. 62108c2ecf20Sopenharmony_ci */ 62118c2ecf20Sopenharmony_civoid skb_condense(struct sk_buff *skb) 62128c2ecf20Sopenharmony_ci{ 62138c2ecf20Sopenharmony_ci if (skb->data_len) { 62148c2ecf20Sopenharmony_ci if (skb->data_len > skb->end - skb->tail || 62158c2ecf20Sopenharmony_ci skb_cloned(skb)) 62168c2ecf20Sopenharmony_ci return; 62178c2ecf20Sopenharmony_ci 62188c2ecf20Sopenharmony_ci /* Nice, we can free page frag(s) right now */ 62198c2ecf20Sopenharmony_ci __pskb_pull_tail(skb, skb->data_len); 62208c2ecf20Sopenharmony_ci } 62218c2ecf20Sopenharmony_ci /* At this point, skb->truesize might be over estimated, 62228c2ecf20Sopenharmony_ci * because skb had a fragment, and fragments do not tell 62238c2ecf20Sopenharmony_ci * their truesize. 62248c2ecf20Sopenharmony_ci * When we pulled its content into skb->head, fragment 62258c2ecf20Sopenharmony_ci * was freed, but __pskb_pull_tail() could not possibly 62268c2ecf20Sopenharmony_ci * adjust skb->truesize, not knowing the frag truesize. 62278c2ecf20Sopenharmony_ci */ 62288c2ecf20Sopenharmony_ci skb->truesize = SKB_TRUESIZE(skb_end_offset(skb)); 62298c2ecf20Sopenharmony_ci} 62308c2ecf20Sopenharmony_ci 62318c2ecf20Sopenharmony_ci#ifdef CONFIG_SKB_EXTENSIONS 62328c2ecf20Sopenharmony_cistatic void *skb_ext_get_ptr(struct skb_ext *ext, enum skb_ext_id id) 62338c2ecf20Sopenharmony_ci{ 62348c2ecf20Sopenharmony_ci return (void *)ext + (ext->offset[id] * SKB_EXT_ALIGN_VALUE); 62358c2ecf20Sopenharmony_ci} 62368c2ecf20Sopenharmony_ci 62378c2ecf20Sopenharmony_ci/** 62388c2ecf20Sopenharmony_ci * __skb_ext_alloc - allocate a new skb extensions storage 62398c2ecf20Sopenharmony_ci * 62408c2ecf20Sopenharmony_ci * @flags: See kmalloc(). 62418c2ecf20Sopenharmony_ci * 62428c2ecf20Sopenharmony_ci * Returns the newly allocated pointer. The pointer can later attached to a 62438c2ecf20Sopenharmony_ci * skb via __skb_ext_set(). 62448c2ecf20Sopenharmony_ci * Note: caller must handle the skb_ext as an opaque data. 62458c2ecf20Sopenharmony_ci */ 62468c2ecf20Sopenharmony_cistruct skb_ext *__skb_ext_alloc(gfp_t flags) 62478c2ecf20Sopenharmony_ci{ 62488c2ecf20Sopenharmony_ci struct skb_ext *new = kmem_cache_alloc(skbuff_ext_cache, flags); 62498c2ecf20Sopenharmony_ci 62508c2ecf20Sopenharmony_ci if (new) { 62518c2ecf20Sopenharmony_ci memset(new->offset, 0, sizeof(new->offset)); 62528c2ecf20Sopenharmony_ci refcount_set(&new->refcnt, 1); 62538c2ecf20Sopenharmony_ci } 62548c2ecf20Sopenharmony_ci 62558c2ecf20Sopenharmony_ci return new; 62568c2ecf20Sopenharmony_ci} 62578c2ecf20Sopenharmony_ci 62588c2ecf20Sopenharmony_cistatic struct skb_ext *skb_ext_maybe_cow(struct skb_ext *old, 62598c2ecf20Sopenharmony_ci unsigned int old_active) 62608c2ecf20Sopenharmony_ci{ 62618c2ecf20Sopenharmony_ci struct skb_ext *new; 62628c2ecf20Sopenharmony_ci 62638c2ecf20Sopenharmony_ci if (refcount_read(&old->refcnt) == 1) 62648c2ecf20Sopenharmony_ci return old; 62658c2ecf20Sopenharmony_ci 62668c2ecf20Sopenharmony_ci new = kmem_cache_alloc(skbuff_ext_cache, GFP_ATOMIC); 62678c2ecf20Sopenharmony_ci if (!new) 62688c2ecf20Sopenharmony_ci return NULL; 62698c2ecf20Sopenharmony_ci 62708c2ecf20Sopenharmony_ci memcpy(new, old, old->chunks * SKB_EXT_ALIGN_VALUE); 62718c2ecf20Sopenharmony_ci refcount_set(&new->refcnt, 1); 62728c2ecf20Sopenharmony_ci 62738c2ecf20Sopenharmony_ci#ifdef CONFIG_XFRM 62748c2ecf20Sopenharmony_ci if (old_active & (1 << SKB_EXT_SEC_PATH)) { 62758c2ecf20Sopenharmony_ci struct sec_path *sp = skb_ext_get_ptr(old, SKB_EXT_SEC_PATH); 62768c2ecf20Sopenharmony_ci unsigned int i; 62778c2ecf20Sopenharmony_ci 62788c2ecf20Sopenharmony_ci for (i = 0; i < sp->len; i++) 62798c2ecf20Sopenharmony_ci xfrm_state_hold(sp->xvec[i]); 62808c2ecf20Sopenharmony_ci } 62818c2ecf20Sopenharmony_ci#endif 62828c2ecf20Sopenharmony_ci __skb_ext_put(old); 62838c2ecf20Sopenharmony_ci return new; 62848c2ecf20Sopenharmony_ci} 62858c2ecf20Sopenharmony_ci 62868c2ecf20Sopenharmony_ci/** 62878c2ecf20Sopenharmony_ci * __skb_ext_set - attach the specified extension storage to this skb 62888c2ecf20Sopenharmony_ci * @skb: buffer 62898c2ecf20Sopenharmony_ci * @id: extension id 62908c2ecf20Sopenharmony_ci * @ext: extension storage previously allocated via __skb_ext_alloc() 62918c2ecf20Sopenharmony_ci * 62928c2ecf20Sopenharmony_ci * Existing extensions, if any, are cleared. 62938c2ecf20Sopenharmony_ci * 62948c2ecf20Sopenharmony_ci * Returns the pointer to the extension. 62958c2ecf20Sopenharmony_ci */ 62968c2ecf20Sopenharmony_civoid *__skb_ext_set(struct sk_buff *skb, enum skb_ext_id id, 62978c2ecf20Sopenharmony_ci struct skb_ext *ext) 62988c2ecf20Sopenharmony_ci{ 62998c2ecf20Sopenharmony_ci unsigned int newlen, newoff = SKB_EXT_CHUNKSIZEOF(*ext); 63008c2ecf20Sopenharmony_ci 63018c2ecf20Sopenharmony_ci skb_ext_put(skb); 63028c2ecf20Sopenharmony_ci newlen = newoff + skb_ext_type_len[id]; 63038c2ecf20Sopenharmony_ci ext->chunks = newlen; 63048c2ecf20Sopenharmony_ci ext->offset[id] = newoff; 63058c2ecf20Sopenharmony_ci skb->extensions = ext; 63068c2ecf20Sopenharmony_ci skb->active_extensions = 1 << id; 63078c2ecf20Sopenharmony_ci return skb_ext_get_ptr(ext, id); 63088c2ecf20Sopenharmony_ci} 63098c2ecf20Sopenharmony_ci 63108c2ecf20Sopenharmony_ci/** 63118c2ecf20Sopenharmony_ci * skb_ext_add - allocate space for given extension, COW if needed 63128c2ecf20Sopenharmony_ci * @skb: buffer 63138c2ecf20Sopenharmony_ci * @id: extension to allocate space for 63148c2ecf20Sopenharmony_ci * 63158c2ecf20Sopenharmony_ci * Allocates enough space for the given extension. 63168c2ecf20Sopenharmony_ci * If the extension is already present, a pointer to that extension 63178c2ecf20Sopenharmony_ci * is returned. 63188c2ecf20Sopenharmony_ci * 63198c2ecf20Sopenharmony_ci * If the skb was cloned, COW applies and the returned memory can be 63208c2ecf20Sopenharmony_ci * modified without changing the extension space of clones buffers. 63218c2ecf20Sopenharmony_ci * 63228c2ecf20Sopenharmony_ci * Returns pointer to the extension or NULL on allocation failure. 63238c2ecf20Sopenharmony_ci */ 63248c2ecf20Sopenharmony_civoid *skb_ext_add(struct sk_buff *skb, enum skb_ext_id id) 63258c2ecf20Sopenharmony_ci{ 63268c2ecf20Sopenharmony_ci struct skb_ext *new, *old = NULL; 63278c2ecf20Sopenharmony_ci unsigned int newlen, newoff; 63288c2ecf20Sopenharmony_ci 63298c2ecf20Sopenharmony_ci if (skb->active_extensions) { 63308c2ecf20Sopenharmony_ci old = skb->extensions; 63318c2ecf20Sopenharmony_ci 63328c2ecf20Sopenharmony_ci new = skb_ext_maybe_cow(old, skb->active_extensions); 63338c2ecf20Sopenharmony_ci if (!new) 63348c2ecf20Sopenharmony_ci return NULL; 63358c2ecf20Sopenharmony_ci 63368c2ecf20Sopenharmony_ci if (__skb_ext_exist(new, id)) 63378c2ecf20Sopenharmony_ci goto set_active; 63388c2ecf20Sopenharmony_ci 63398c2ecf20Sopenharmony_ci newoff = new->chunks; 63408c2ecf20Sopenharmony_ci } else { 63418c2ecf20Sopenharmony_ci newoff = SKB_EXT_CHUNKSIZEOF(*new); 63428c2ecf20Sopenharmony_ci 63438c2ecf20Sopenharmony_ci new = __skb_ext_alloc(GFP_ATOMIC); 63448c2ecf20Sopenharmony_ci if (!new) 63458c2ecf20Sopenharmony_ci return NULL; 63468c2ecf20Sopenharmony_ci } 63478c2ecf20Sopenharmony_ci 63488c2ecf20Sopenharmony_ci newlen = newoff + skb_ext_type_len[id]; 63498c2ecf20Sopenharmony_ci new->chunks = newlen; 63508c2ecf20Sopenharmony_ci new->offset[id] = newoff; 63518c2ecf20Sopenharmony_ciset_active: 63528c2ecf20Sopenharmony_ci skb->extensions = new; 63538c2ecf20Sopenharmony_ci skb->active_extensions |= 1 << id; 63548c2ecf20Sopenharmony_ci return skb_ext_get_ptr(new, id); 63558c2ecf20Sopenharmony_ci} 63568c2ecf20Sopenharmony_ciEXPORT_SYMBOL(skb_ext_add); 63578c2ecf20Sopenharmony_ci 63588c2ecf20Sopenharmony_ci#ifdef CONFIG_XFRM 63598c2ecf20Sopenharmony_cistatic void skb_ext_put_sp(struct sec_path *sp) 63608c2ecf20Sopenharmony_ci{ 63618c2ecf20Sopenharmony_ci unsigned int i; 63628c2ecf20Sopenharmony_ci 63638c2ecf20Sopenharmony_ci for (i = 0; i < sp->len; i++) 63648c2ecf20Sopenharmony_ci xfrm_state_put(sp->xvec[i]); 63658c2ecf20Sopenharmony_ci} 63668c2ecf20Sopenharmony_ci#endif 63678c2ecf20Sopenharmony_ci 63688c2ecf20Sopenharmony_civoid __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id) 63698c2ecf20Sopenharmony_ci{ 63708c2ecf20Sopenharmony_ci struct skb_ext *ext = skb->extensions; 63718c2ecf20Sopenharmony_ci 63728c2ecf20Sopenharmony_ci skb->active_extensions &= ~(1 << id); 63738c2ecf20Sopenharmony_ci if (skb->active_extensions == 0) { 63748c2ecf20Sopenharmony_ci skb->extensions = NULL; 63758c2ecf20Sopenharmony_ci __skb_ext_put(ext); 63768c2ecf20Sopenharmony_ci#ifdef CONFIG_XFRM 63778c2ecf20Sopenharmony_ci } else if (id == SKB_EXT_SEC_PATH && 63788c2ecf20Sopenharmony_ci refcount_read(&ext->refcnt) == 1) { 63798c2ecf20Sopenharmony_ci struct sec_path *sp = skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH); 63808c2ecf20Sopenharmony_ci 63818c2ecf20Sopenharmony_ci skb_ext_put_sp(sp); 63828c2ecf20Sopenharmony_ci sp->len = 0; 63838c2ecf20Sopenharmony_ci#endif 63848c2ecf20Sopenharmony_ci } 63858c2ecf20Sopenharmony_ci} 63868c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__skb_ext_del); 63878c2ecf20Sopenharmony_ci 63888c2ecf20Sopenharmony_civoid __skb_ext_put(struct skb_ext *ext) 63898c2ecf20Sopenharmony_ci{ 63908c2ecf20Sopenharmony_ci /* If this is last clone, nothing can increment 63918c2ecf20Sopenharmony_ci * it after check passes. Avoids one atomic op. 63928c2ecf20Sopenharmony_ci */ 63938c2ecf20Sopenharmony_ci if (refcount_read(&ext->refcnt) == 1) 63948c2ecf20Sopenharmony_ci goto free_now; 63958c2ecf20Sopenharmony_ci 63968c2ecf20Sopenharmony_ci if (!refcount_dec_and_test(&ext->refcnt)) 63978c2ecf20Sopenharmony_ci return; 63988c2ecf20Sopenharmony_cifree_now: 63998c2ecf20Sopenharmony_ci#ifdef CONFIG_XFRM 64008c2ecf20Sopenharmony_ci if (__skb_ext_exist(ext, SKB_EXT_SEC_PATH)) 64018c2ecf20Sopenharmony_ci skb_ext_put_sp(skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH)); 64028c2ecf20Sopenharmony_ci#endif 64038c2ecf20Sopenharmony_ci 64048c2ecf20Sopenharmony_ci kmem_cache_free(skbuff_ext_cache, ext); 64058c2ecf20Sopenharmony_ci} 64068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__skb_ext_put); 64078c2ecf20Sopenharmony_ci#endif /* CONFIG_SKB_EXTENSIONS */ 6408