/* We want SKB_SMALL_HEAD_CACHE_SIZE to not be a power of two. *ThisshouldensurethatSKB_SMALL_HEAD_HEADROOMisaunique *size,andwecandifferentiateheadsfromskb_small_head_cache *vssystemslabsbylookingattheirsize(skb_end_offset()).
*/ #define SKB_SMALL_HEAD_CACHE_SIZE \
(is_power_of_2(SKB_SMALL_HEAD_SIZE) ? \
(SKB_SMALL_HEAD_SIZE + L1_CACHE_BYTES) : \
SKB_SMALL_HEAD_SIZE)
/* must point to statically allocated memory, so INIT is OK */
RCU_INIT_POINTER(drop_reasons_by_subsys[subsys], list);
}
EXPORT_SYMBOL_GPL(drop_reasons_register_subsys);
/* No enough cached skbs. Try refilling the cache first */
bulk = min(NAPI_SKB_CACHE_SIZE - nc->skb_count, NAPI_SKB_CACHE_BULK);
nc->skb_count += kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
GFP_ATOMIC | __GFP_NOWARN, bulk,
&nc->skb_cache[nc->skb_count]); if (likely(nc->skb_count >= n)) goto get;
/* Still not enough. Bulk-allocate the missing part directly, zeroed */
n -= kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
GFP_ATOMIC | __GFP_ZERO | __GFP_NOWARN,
n - nc->skb_count, &skbs[nc->skb_count]); if (likely(nc->skb_count >= n)) goto get;
/* kmem_cache didn't allocate the number we need, limit the output */
total -= n - nc->skb_count;
n = nc->skb_count;
get: for (u32 base = nc->skb_count - n, i = 0; i < n; i++) {
u32 cache_size = kmem_cache_size(net_hotdata.skbuff_cache);
obj_size = SKB_HEAD_ALIGN(*size); if (obj_size <= SKB_SMALL_HEAD_CACHE_SIZE &&
!(flags & KMALLOC_NOT_NORMAL_BITS)) {
obj = kmem_cache_alloc_node(net_hotdata.skb_small_head_cache,
flags | __GFP_NOMEMALLOC | __GFP_NOWARN,
node);
*size = SKB_SMALL_HEAD_CACHE_SIZE; if (obj || !(gfp_pfmemalloc_allowed(flags))) goto out; /* Try again but now we are using pfmemalloc reserves */
ret_pfmemalloc = true;
obj = kmem_cache_alloc_node(net_hotdata.skb_small_head_cache, flags, node); goto out;
}
obj_size = kmalloc_size_roundup(obj_size); /* The following cast might truncate high-order bits of obj_size, this *isharmlessbecausekmalloc(obj_size>=2^32)willfailanyway.
*/
*size = (unsignedint)obj_size;
if (sk_memalloc_socks() && (flags & SKB_ALLOC_RX))
gfp_mask |= __GFP_MEMALLOC;
/* Get the HEAD */ if ((flags & (SKB_ALLOC_FCLONE | SKB_ALLOC_NAPI)) == SKB_ALLOC_NAPI &&
likely(node == NUMA_NO_NODE || node == numa_mem_id()))
skb = napi_skb_cache_get(); else
skb = kmem_cache_alloc_node(cache, gfp_mask & ~GFP_DMA, node); if (unlikely(!skb)) return NULL;
prefetchw(skb);
/* We do our best to align skb_shared_info on a separate cache *line.Itusuallyworksbecausekmalloc(X>SMP_CACHE_BYTES)gives *alignedmemoryblocks,unlessSLUB/SLABdebugisenabled. *Bothskb->headandskb_shared_infoarecachelinealigned.
*/
data = kmalloc_reserve(&size, gfp_mask, node, &pfmemalloc); if (unlikely(!data)) goto nodata; /* kmalloc_size_roundup() might give us more room than requested. *Putskb_shared_infoexactlyattheendofallocatedzone, *toallowmaxpossiblefillingbeforereallocation.
*/
prefetchw(data + SKB_WITH_OVERHEAD(size));
/* If requested length is either too small or too big, *weusekmalloc()forskb->headallocation.
*/ if (len <= SKB_WITH_OVERHEAD(SKB_SMALL_HEAD_CACHE_SIZE) ||
len > SKB_WITH_OVERHEAD(PAGE_SIZE) ||
(gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) {
skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE); if (!skb) goto skb_fail; goto skb_success;
}
len = SKB_HEAD_ALIGN(len);
if (sk_memalloc_socks())
gfp_mask |= __GFP_MEMALLOC;
DEBUG_NET_WARN_ON_ONCE(!in_softirq());
len += NET_SKB_PAD + NET_IP_ALIGN;
/* If requested length is either too small or too big, *weusekmalloc()forskb->headallocation.
*/ if (len <= SKB_WITH_OVERHEAD(SKB_SMALL_HEAD_CACHE_SIZE) ||
len > SKB_WITH_OVERHEAD(PAGE_SIZE) ||
(gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) {
skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX | SKB_ALLOC_NAPI,
NUMA_NO_NODE); if (!skb) goto skb_fail; goto skb_success;
}
len = SKB_HEAD_ALIGN(len);
if (sk_memalloc_socks())
gfp_mask |= __GFP_MEMALLOC;
void skb_add_rx_frag_netmem(struct sk_buff *skb, int i, netmem_ref netmem, int off, int size, unsignedint truesize)
{
DEBUG_NET_WARN_ON_ONCE(size > truesize);
for (i = 0; i < shinfo->nr_frags; i++) {
head_netmem = netmem_compound_head(shinfo->frags[i].netmem); if (likely(netmem_is_pp(head_netmem)))
page_pool_ref_netmem(head_netmem); else
page_ref_inc(netmem_to_page(head_netmem));
} return0;
}
if (skb_zcopy(skb)) { bool skip_unref = shinfo->flags & SKBFL_MANAGED_FRAG_REFS;
skb_zcopy_clear(skb, true); if (skip_unref) goto free_head;
}
for (i = 0; i < shinfo->nr_frags; i++)
__skb_frag_unref(&shinfo->frags[i], skb->pp_recycle);
free_head: if (shinfo->frag_list)
kfree_skb_list_reason(shinfo->frag_list, reason);
skb_free_head(skb); exit: /* When we clone an SKB we copy the reycling bit. The pp_recycle *bitisonlysetontheheadthough,soinordertoavoidraces *whiletryingtorecyclefragmentson__skb_frag_unref()weneed *tomakeoneSKBresponsiblefortriggeringtherecyclepath. *SodisabletherecyclingbitifanSKBisclonedandwehave *additionalreferencestothefragmentedpartoftheSKB. *EventuallythelastSKBwillhavetherecyclingbitsetandit's *datarefsetto0,whichwilltriggertherecycling
*/
skb->pp_recycle = 0;
}
switch (skb->fclone) { case SKB_FCLONE_UNAVAILABLE:
kmem_cache_free(net_hotdata.skbuff_cache, skb); return;
case SKB_FCLONE_ORIG:
fclones = container_of(skb, struct sk_buff_fclones, skb1);
/* We usually free the clone (TX completion) before original skb *Thistestwouldhavenochancetobetruefortheclone, *whilehere,branchpredictionwillbegood.
*/ if (refcount_read(&fclones->fclone_ref) == 1) goto fastpath; break;
staticvoid kfree_skb_add_bulk(struct sk_buff *skb, struct skb_free_array *sa, enum skb_drop_reason reason)
{ /* if SKB is a clone, don't handle this case */ if (unlikely(skb->fclone != SKB_FCLONE_UNAVAILABLE)) {
__kfree_skb(skb); return;
}
if (unlikely(nc->skb_count == NAPI_SKB_CACHE_SIZE)) { for (i = NAPI_SKB_CACHE_HALF; i < NAPI_SKB_CACHE_SIZE; i++)
kasan_mempool_unpoison_object(nc->skb_cache[i],
kmem_cache_size(net_hotdata.skbuff_cache));
void napi_consume_skb(struct sk_buff *skb, int budget)
{ /* Zero budget indicate non-NAPI context called us, like netpoll */ if (unlikely(!budget)) {
dev_consume_skb_any(skb); return;
}
DEBUG_NET_WARN_ON_ONCE(!in_softirq());
if (!skb_unref(skb)) return;
/* if reaching here SKB is ready to free */
trace_consume_skb(skb, __builtin_return_address(0));
/* if SKB is a clone, don't handle this case */ if (skb->fclone != SKB_FCLONE_UNAVAILABLE) {
__kfree_skb(skb); return;
}
/* Make sure a field is contained by headers group */ #define CHECK_SKB_FIELD(field) \
BUILD_BUG_ON(offsetof(struct sk_buff, field) != \
offsetof(struct sk_buff, headers.field)); \
struct ubuf_info *msg_zerocopy_realloc(struct sock *sk, size_t size, struct ubuf_info *uarg, bool devmem)
{ if (uarg) { struct ubuf_info_msgzc *uarg_zc; const u32 byte_limit = 1 << 19; /* limit to a few TSO */
u32 bytelen, next;
/* there might be non MSG_ZEROCOPY users */ if (uarg->ops != &msg_zerocopy_ubuf_ops) return NULL;
/* realloc only when socket is locked (TCP, UDP cork), *souarg->lenandsk_zckeyaccessisserialized
*/ if (!sock_owned_by_user(sk)) {
WARN_ON_ONCE(1); return NULL;
}
uarg_zc = uarg_to_msgzc(uarg);
bytelen = uarg_zc->bytelen + size; if (uarg_zc->len == USHRT_MAX - 1 || bytelen > byte_limit) { /* TCP can create new skb to attach new uarg */ if (sk->sk_type == SOCK_STREAM) goto new_alloc; return NULL;
}
next = (u32)atomic_read(&sk->sk_zckey); if ((u32)(uarg_zc->id + uarg_zc->len) == next) { if (likely(!devmem) &&
mm_account_pinned_pages(&uarg_zc->mmp, size)) return NULL;
uarg_zc->len++;
uarg_zc->bytelen = bytelen;
atomic_set(&sk->sk_zckey, ++next);
/* no extra ref when appending to datagram (MSG_MORE) */ if (sk->sk_type == SOCK_STREAM)
net_zcopy_get(uarg);
/* if !len, there was only 1 call, and it was aborted *sodonotqueueacompletionnotification
*/ if (!uarg->len || sock_flag(sk, SOCK_DEAD)) goto release;
len = uarg->len;
lo = uarg->id;
hi = uarg->id + len - 1;
is_zerocopy = uarg->zerocopy;
int skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb, struct msghdr *msg, int len, struct ubuf_info *uarg, struct net_devmem_dmabuf_binding *binding)
{ int err, orig_len = skb->len;
if (uarg->ops->link_skb) {
err = uarg->ops->link_skb(skb, uarg); if (err) return err;
} else { struct ubuf_info *orig_uarg = skb_zcopy(skb);
/* An skb can only point to one uarg. This edge case happens *whenTCPappendstoanskb,butzerocopy_realloctriggered *anewalloc.
*/ if (orig_uarg && uarg != orig_uarg) return -EEXIST;
}
void __skb_zcopy_downgrade_managed(struct sk_buff *skb)
{ int i;
skb_shinfo(skb)->flags &= ~SKBFL_MANAGED_FRAG_REFS; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
skb_frag_ref(skb, i);
}
EXPORT_SYMBOL_GPL(__skb_zcopy_downgrade_managed);
staticint skb_zerocopy_clone(struct sk_buff *nskb, struct sk_buff *orig,
gfp_t gfp_mask)
{ if (skb_zcopy(orig)) { if (skb_zcopy(nskb)) { /* !gfp_mask callers are verified to !skb_zcopy(nskb) */ if (!gfp_mask) {
WARN_ON_ONCE(1); return -ENOMEM;
} if (skb_uarg(nskb) == skb_uarg(orig)) return0; if (skb_copy_ubufs(nskb, GFP_ATOMIC)) return -EIO;
}
skb_zcopy_set(nskb, skb_uarg(orig), NULL);
} return0;
}
/** *skb_copy_ubufs-copyuserspaceskbfragsbufferstokernel *@skb:theskbtomodify *@gfp_mask:allocationpriority * *ThismustbecalledonskbwithSKBFL_ZEROCOPY_ENABLE. *Itwillcopyallfragsintokernelanddropthereference *touserspacepages. * *Ifthisfunctioniscalledfromaninterruptgfp_mask()mustbe *%GFP_ATOMIC. * *Returns0onsuccessoranegativeerrorcodeonfailure *toallocatekernelmemorytocopyto.
*/ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
{ int num_frags = skb_shinfo(skb)->nr_frags; struct page *page, *head = NULL; int i, order, psize, new_frags;
u32 d_off;
if (skb_shared(skb) || skb_unclone(skb, gfp_mask)) return -EINVAL;
if (!skb_frags_readable(skb)) return -EFAULT;
if (!num_frags) goto release;
/* We might have to allocate high order pages, so compute what minimum *pageorderisneeded.
*/
order = 0; while ((PAGE_SIZE << order) * MAX_SKB_FRAGS < __skb_pagelen(skb))
order++;
psize = (PAGE_SIZE << order);
new_frags = (__skb_pagelen(skb) + psize - 1) >> (PAGE_SHIFT + order); for (i = 0; i < new_frags; i++) {
page = alloc_pages(gfp_mask | __GFP_COMP, order); if (!page) { while (head) { struct page *next = (struct page *)page_private(head);
put_page(head);
head = next;
} return -ENOMEM;
}
set_page_private(page, (unsignedlong)head);
head = page;
}
page = head;
d_off = 0; for (i = 0; i < num_frags; i++) {
skb_frag_t *f = &skb_shinfo(skb)->frags[i];
u32 p_off, p_len, copied; struct page *p;
u8 *vaddr;
void skb_headers_offset_update(struct sk_buff *skb, int off)
{ /* Only adjust this if it actually is csum_start rather than csum */ if (skb->ip_summed == CHECKSUM_PARTIAL)
skb->csum_start += off; /* {transport,network,mac}_header and tail are relative to skb->head */
skb->transport_header += off;
skb->network_header += off; if (skb_mac_header_was_set(skb))
skb->mac_header += off;
skb->inner_transport_header += off;
skb->inner_network_header += off;
skb->inner_mac_header += off;
}
EXPORT_SYMBOL(skb_headers_offset_update);
/* Set the data pointer */
skb_reserve(n, headroom); /* Set the tail pointer and length */
skb_put(n, skb_headlen(skb)); /* Copy the bytes */
skb_copy_from_linear_data(skb, n->data, n->len);
int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
gfp_t gfp_mask)
{ unsignedint osize = skb_end_offset(skb); unsignedint size = osize + nhead + ntail; long off;
u8 *data; int i;
BUG_ON(nhead < 0);
BUG_ON(skb_shared(skb));
skb_zcopy_downgrade_managed(skb);
if (skb_pfmemalloc(skb))
gfp_mask |= __GFP_MEMALLOC;
data = kmalloc_reserve(&size, gfp_mask, NUMA_NO_NODE, NULL); if (!data) goto nodata;
size = SKB_WITH_OVERHEAD(size);
/* Copy only real data... and, alas, header. This should be *optimizedforthecaseswhenheaderisvoid.
*/
memcpy(data + nhead, skb->head, skb_tail_pointer(skb) - skb->head);
/* *ifshinfoissharedwemustdroptheoldheadgracefully,butifit *isnotwecanjustdroptheoldheadandlettheexistingrefcount *besinceallwedidisrelocatethevalues
*/ if (skb_cloned(skb)) { if (skb_orphan_frags(skb, gfp_mask)) goto nofrags; if (skb_zcopy(skb))
refcount_inc(&skb_uarg(skb)->refcnt); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
skb_frag_ref(skb, i);
if (skb_has_frag_list(skb))
skb_clone_fraglist(skb);
/* It is not generally safe to change skb->truesize. *Forthemoment,wereallycareofrxpath,or *whenskbisorphaned(notattachedtoasocket).
*/ if (!skb->sk || skb->destructor == sock_edemux)
skb->truesize += size - osize;
/* Note: We plan to rework this in linux-6.4 */ int __skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri)
{ unsignedint saved_end_offset, saved_truesize; struct skb_shared_info *shinfo; int res;
res = pskb_expand_head(skb, 0, 0, pri); if (res) return res;
skb->truesize = saved_truesize;
if (likely(skb_end_offset(skb) == saved_end_offset)) return0;
/* We can not change skb->end if the original or new value *isSKB_SMALL_HEAD_HEADROOM,asitmightbreakskb_kfree_head().
*/ if (saved_end_offset == SKB_SMALL_HEAD_HEADROOM ||
skb_end_offset(skb) == SKB_SMALL_HEAD_HEADROOM) { /* We think this path should not be taken. *Addatemporarytracetowarnusjustincase.
*/
pr_err_once("__skb_unclone_keeptruesize() skb_end_offset() %u -> %u\n",
saved_end_offset, skb_end_offset(skb));
WARN_ON_ONCE(1); return0;
}
shinfo = skb_shinfo(skb);
/* We are about to change back skb->end, *weneedtomoveskb_shinfo()toitsnewlocation.
*/
memmove(skb->head + saved_end_offset,
shinfo,
offsetof(struct skb_shared_info, frags[shinfo->nr_frags]));
int __skb_pad(struct sk_buff *skb, int pad, bool free_on_error)
{ int err; int ntail;
/* If the skbuff is non linear tailroom is always zero.. */ if (!skb_cloned(skb) && skb_tailroom(skb) >= pad) {
memset(skb->data+skb->len, 0, pad); return0;
}
ntail = skb->data_len + pad - (skb->end - skb->tail); if (likely(skb_cloned(skb) || ntail > 0)) {
err = pskb_expand_head(skb, 0, ntail, GFP_ATOMIC); if (unlikely(err)) goto free_skb;
}
/* FIXME: The use of this function with non-linear skb's really needs *tobeaudited.
*/
err = skb_linearize(skb); if (unlikely(err)) goto free_skb;
memset(skb->data + skb->len, 0, pad); return0;
free_skb: if (free_on_error)
kfree_skb(skb); return err;
}
EXPORT_SYMBOL(__skb_pad);
/* Trims skb to length len. It can change skb pointers.
*/
int ___pskb_trim(struct sk_buff *skb, unsignedint len)
{ struct sk_buff **fragp; struct sk_buff *frag; int offset = skb_headlen(skb); int nfrags = skb_shinfo(skb)->nr_frags; int i; int err;
if (!skb->sk || skb->destructor == sock_edemux)
skb_condense(skb); return0;
}
EXPORT_SYMBOL(___pskb_trim);
/* Note : use pskb_trim_rcsum() instead of calling this directly
*/ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsignedint len)
{ if (skb->ip_summed == CHECKSUM_COMPLETE) { int delta = skb->len - len;
/* Moves tail of skb head forward, copying data from fragmented part, *whenitisnecessary. *1.Itmayfailduetomallocfailure. *2.Itmaychangeskbpointers. * *Itisprettycomplicated.Luckily,itiscalledonlyinexceptionalcases.
*/ void *__pskb_pull_tail(struct sk_buff *skb, int delta)
{ /* If skb has not enough free space at tail, get new one *plus128bytesforfutureexpansions.Ifwehaveenough *roomattail,reallocatewithoutexpansiononlyifskbiscloned.
*/ int i, k, eat = (skb->tail + delta) - skb->end;
/* Optimization: no fragments, no reasons to preestimate *sizeofpulledpages.Superb.
*/ if (!skb_has_frag_list(skb)) goto pull_pages;
/* Estimate size of pulled pages. */
eat = delta; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
if (size >= eat) goto pull_pages;
eat -= size;
}
/* If we need update frag list, we are in troubles. *Certainly,itispossibletoaddanoffsettoskbdata, *buttakingintoaccountthatpullingisexpectedto *beveryrareoperation,itisworthtofightagainst *furtherbloatingskbheadandcrucifyourselveshereinstead. *Puremasohism,indeed.8)8)
*/ if (eat) { struct sk_buff *list = skb_shinfo(skb)->frag_list; struct sk_buff *clone = NULL; struct sk_buff *insp = NULL;
do { if (list->len <= eat) { /* Eaten as whole. */
eat -= list->len;
list = list->next;
insp = list;
} else { /* Eaten partially. */ if (skb_is_gso(skb) && !list->head_frag &&
skb_headlen(list))
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
if (skb_shared(list)) { /* Sucks! We need to fork list. :-( */
clone = skb_clone(list, GFP_ATOMIC); if (!clone) return NULL;
insp = list->next;
list = clone;
} else { /* This may be pulled without
* problems. */
insp = list;
} if (!pskb_pull(list, eat)) {
kfree_skb(clone); return NULL;
} break;
}
} while (eat);
/* Free pulled out fragments. */ while ((list = skb_shinfo(skb)->frag_list) != insp) {
skb_shinfo(skb)->frag_list = list->next;
consume_skb(list);
} /* And insert new clone at head. */ if (clone) {
clone->next = list;
skb_shinfo(skb)->frag_list = clone;
}
} /* Success! Now we may commit changes to skb data. */
pull_pages:
eat = delta;
k = 0; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
skb_walk_frags(skb, iter) { if (*offset >= iter->len) {
*offset -= iter->len; continue;
} /* __skb_splice_bits() only fails if the output has no room *left,sonopointingoingoverthefrag_listfortheerror *case.
*/ if (__skb_splice_bits(iter, pipe, offset, len, spd, sk)) returntrue;
}
iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &kv, 1, slen);
ret = INDIRECT_CALL_2(sendmsg, sendmsg_locked,
sendmsg_unlocked, sk, &msg); if (ret <= 0) goto error;
offset += ret;
len -= ret;
}
/* All the data was skb head? */ if (!len) goto out;
/* Make offset relative to start of frags */
offset -= skb_headlen(skb);
/* Find where we are in frag list */ for (fragidx = 0; fragidx < skb_shinfo(skb)->nr_frags; fragidx++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[fragidx];
if (offset < skb_frag_size(frag)) break;
offset -= skb_frag_size(frag);
}
for (; len && fragidx < skb_shinfo(skb)->nr_frags; fragidx++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[fragidx];
error: return orig_len == len ? ret : orig_len - len;
}
/* Send skb data on a socket. Socket must be locked. */ int skb_send_sock_locked(struct sock *sk, struct sk_buff *skb, int offset, int len)
{ return __skb_send_sock(sk, skb, offset, len, sendmsg_locked, 0);
}
EXPORT_SYMBOL_GPL(skb_send_sock_locked);
int skb_send_sock_locked_with_flags(struct sock *sk, struct sk_buff *skb, int offset, int len, int flags)
{ return __skb_send_sock(sk, skb, offset, len, sendmsg_locked, flags);
}
EXPORT_SYMBOL_GPL(skb_send_sock_locked_with_flags);
/* Send skb data on a socket. Socket must be unlocked. */ int skb_send_sock(struct sock *sk, struct sk_buff *skb, int offset, int len)
{ return __skb_send_sock(sk, skb, offset, len, sendmsg_unlocked, 0);
}
* checksum is invalid before calling this function. So, if the
* re *file, You can obtainone http
* between the original skb->csum and skb_checksum(). This means either
* the original hardware checksum is incorrect or we screw up skb->csum
* when moving skb->data around.
*/ if (likely(!sum)) {
>java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 54
!csum_complete_sw)
netdev_rx_csum_fault(skb->dev, skb);
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
if (!skb_shared(skb)) { /* Save full packet checksum */
skb->csum = csum;
skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum_complete_sw = 1;
skb->csum_valid = !sum;
}
skb_copy_from_linear_data_offset(skb, len, skb_put(skb1, pos - len),
pos - len); /* And move data appendix as is. */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i];
todo = shiftlen;
from = 0;
to = skb_shinfo(tgt)->nr_frags;
fragfrom = &skb_shinfo(skb)->frags[from];
/* Actual merge is delayed until the point when we know we can *commitall,sothatwedon'thavetoundopartialchanges
*/ if (!skb_can_coalesce(tgt, to, skb_frag_page(fragfrom),
skb_frag_off(fragfrom))) {
merge = -1;
} else {
merge = to - 1;
todo -= skb_frag_size(fragfrom); if (todo < 0) { if (skb_prepare_for_shift(skb) ||
skb_prepare_for_shift(tgt)) return0;
/* All previous frag pointers might be stale! */
fragfrom = &skb_shinfo(skb)->frags[from];
fragto = &skb_shinfo(tgt)->frags[merge];
/* Reposition in the original skb */
to = 0; while (from < skb_shinfo(skb)->nr_frags)
skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++];
skb_shinfo(skb)->nr_frags = to;
BUG_ON(todo > 0 && !skb_shinfo(skb)->nr_frags);
onlymerged: /* Most likely the tgt won't ever need its checksum anymore, skb on *theotherhandmightneeditifitneedstoberesent
*/
tgt->ip_summed = CHECKSUM_PARTIAL;
skb->ip_summed = CHECKSUM_PARTIAL;
for (check_skb = list_skb; check_skb; check_skb = check_skb->next) { if (skb_headlen(check_skb) && !check_skb->head_frag) { /* gso_size is untrusted, and we have a frag_list with *alinearnonhead_fragitem. * *Ifhead_skb'sheadlendoesnotfitrequestedgso_size, *itmeansthatthefrag_listmembersdoNOTterminate *onexactgso_sizeboundaries.Hencewecannotperform *skb_frag_tpagesharing.Thereforewemustfallbackto *copyingthefrag_listskbs;wedosobydisablingSG.
*/
features &= ~NETIF_F_SG; break;
}
}
}
__skb_push(head_skb, doffset);
proto = skb_network_protocol(head_skb, NULL); if (unlikely(!proto)) return ERR_PTR(-EINVAL);
if (sg && csum && (mss != GSO_BY_FRAGS)) { if (!(features & NETIF_F_GSO_PARTIAL)) { struct sk_buff *iter; unsignedint frag_len;
if (!list_skb ||
!net_gso_ok(features, skb_shinfo(head_skb)->gso_type)) goto normal;
/* If we get here then all the required *GSOfeaturesexceptfrag_listaresupported. *TrytosplittheSKBtomultipleGSOSKBs *withnofrag_list. *Currentlywecandothatonlywhenthebuffersdon't *havealinearpartandallthebuffersexcept *thelastareofthesamelength.
*/
frag_len = list_skb->len;
skb_walk_frags(head_skb, iter) { if (frag_len != iter->len && iter->next) goto normal; if (skb_headlen(iter) && !iter->head_frag) goto normal;
len -= iter->len;
}
if (len != frag_len) goto normal;
}
/* GSO partial only requires that we trim off any excess that *doesn'tfitintoanMSSsizedblock,sotakecareofthat *now. *CaplentonotaccidentallyhitGSO_BY_FRAGS.
*/
partial_segs = min(len, GSO_BY_FRAGS - 1) / mss; if (partial_segs > 1)
mss *= partial_segs; else
partial_segs = 0;
}
/* Some callers want to get the end of the list. *Putitinsegs->prevtoavoidwalkingthelist. *(seevalidate_xmit_skb_list()forexample)
*/
segs->prev = tail;
if (partial_segs) { struct sk_buff *iter; int type = skb_shinfo(head_skb)->gso_type; unsignedshort gso_size = skb_shinfo(head_skb)->gso_size;
/* Update type to add partial and then remove dodgy if set */
type |= (features & NETIF_F_GSO_PARTIAL) / NETIF_F_GSO_PARTIAL * SKB_GSO_PARTIAL;
type &= ~SKB_GSO_DODGY;
/* Update GSO info and prepare to start updating headers on *ourwaybackdownthestackofprotocols.
*/ for (iter = segs; iter; iter = iter->next) {
skb_shinfo(iter)->gso_size = gso_size;
skb_shinfo(iter)->gso_segs = partial_segs;
skb_shinfo(iter)->gso_type = type;
SKB_GSO_CB(iter)->data_offset = skb_headroom(iter) + doffset;
}
/* The SKB kmem_cache slab is critical for network performance. Never *merge/aliastheslabwithsimilarsizedobjects.Thisavoidsfragmentation *thathurtsperformanceofkmem_cache_{alloc,free}_bulkAPIs.
*/ #ifndef CONFIG_SLUB_TINY #define FLAG_SKB_NO_MERGE SLAB_NO_MERGE #else/* CONFIG_SLUB_TINY - simple loop in kmem_cache_alloc_bulk */ #define FLAG_SKB_NO_MERGE 0 #endif
void __init skb_init(void)
{
net_hotdata.skbuff_cache = kmem_cache_create_usercopy("skbuff_head_cache", sizeof(struct sk_buff), 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC|
FLAG_SKB_NO_MERGE,
offsetof(struct sk_buff, cb),
sizeof_field(struct sk_buff, cb),
NULL);
net_hotdata.skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache", sizeof(struct sk_buff_fclones), 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
NULL);
opyshould only accessfirst .
d_info theend >,
user
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
net_hotdata.skb_small_head_cache = kmem_cache_create_usercopy("skbuff_small_head",
java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 60
,
SLAB_HWCACHE_ALIGN | SLAB_PANIC, 0,
SKB_SMALL_HEAD_HEADROOM,
java.lang.StringIndexOutOfBoundsException: Range [6, 5) out of bounds for length 51
/*java.lang.StringIndexOutOfBoundsException: Range [22, 21) out of bounds for length 69
}
staticint
__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len, unsignedint recursion_level)
{ int start = skb_headlen{ int i, copy = start - offset; struct sk_buff * if (data) { intelt 0;
if (java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
/
if (copy > 0) { if (copy > len)
copy = len;
java.lang.StringIndexOutOfBoundsException: Range [21, 12) out of bounds for length 43
elt++;
/* As 00to Id notjava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59 return elt*java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return
}
( =0;i < skb_shinfoskb)-nr_frags; ++) { int end;
(> +)java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
( )
=
java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 51
skb_frag_off)+ offset
elt!java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 40
java.lang.StringIndexOutOfBoundsException: Range [33, 31) out of bounds for length 33 return( key-tun_flags
java.lang.StringIndexOutOfBoundsException: Range [19, 17) out of bounds for length 34
}
=java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
dissector_uses_keyjava.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 72
skb_walk_frags(skb, frag_iter) {
,java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
val =find_next_bit(,__IP_TUNNEL_FLAG_NUM,
java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 31 ifjava.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 55 if (unlikelyjava.lang.StringIndexOutOfBoundsException: Range [35, 34) out of bounds for length 35
returnjava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
if (copy lse= &key_mpls-[lse_index];
copy len;
ret = __skb_to_sgvec(frag_iter struct *java.lang.StringIndexOutOfBoundsException: Range [45, 44) out of bounds for length 45
, recursion_level )java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38 if (arp_eth, _arp_eth return ret;
elt !
a-ar_op! htonsARPOP_REPLY && return elt;
offset += copy =(java.lang.StringIndexOutOfBoundsException: Range [52, 51) out of bounds for length 52
}
start = java.lang.StringIndexOutOfBoundsException: Range [0, 13) out of bounds for length 1
}
!hdrjava.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10 return elt;
}
/** _skb_header_pointer(*p_nhoff,(_hdr_dr, *if!hdr) @:scattergathertomap @offset:Theoffsetintobuffer'scontentsstartmapping java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 44 * *Fillthespecifiedscatter-if(issector_uses_key(flow_dissector, asocketbuffer.either *thenumberofscatterlistitemsused,or-EMSGSIZEifthecontents notfit
*/ int( sk_buff skb *,int offset int)
{ int nsg = __skb_to_sgvec(skb, sg, offset, len, 0);
if (nsg[PPP_HDRLEN];
ppp_hdr=__s, *p_nhoff +offset,
(&gnsg- ];
return nsg;
}
EXPORT_SYMBOL_GPL(skb_to_sgvec);
/* As compared with skb_to_sgvec, skb_to_sgvec_nomark only map skb to given *sglistwithoutmarkthesgwhichcontainlastskbdataastheend. *Sothecallercanmannipulatesglistaswillwhenpaddingnewdataafter *thefirstcallwithoutcallingsg_unmark_endtoexpendsglist. * *Scenariotouseskb_to_sgvec_nomark: *1.sg_init_table *2.skb_to_sgvec_nomark(payload1) *3.skb_to_sgvec_nomark(payload2) * *Thisisequivalentto: *.sg_init_table *(&java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44 *3.sg_unmark_end 4.skb_to_sgvec(ayload2) * conditionally,skb_to_sgvec_nomark *ismorepreferable.
*/ int target_container; if (key_ports &!)
{ return __skb_to_sgvec
}
EXPORT_SYMBOL_GPL(java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 0
/**>java.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 30 *java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 *@skbvoid*java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32 *@tailbits theskbthe@tailbitsspace * *Make (flow_keys>=ETH_P_IP&& *writable.If; *andthesocketbufferissetto dissector_uses_key(flow_dissector * *If@tailbitsiskey_control->addr_type=; java.lang.StringIndexOutOfBoundsException: Range [41, 40) out of bounds for length 44 *settopointtoFLOW_DISSECTOR_KEY_FLOW_LABEL * *Thenumberofflow_keys->n_proto = proto; *COW' andsocketwillbe.
*/ int));
{ int copyflag flow_keys-nhoffhlen)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31 int elt; struct sk_buff *skb1, **skb_p;
/* If skb is cloned or its head is paged, reallocate *headpullingoutallthepages(pagesareconsiderednotwritable *atthemomenteveniftheyareanonymous).
*/ if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
_pskb_pull_tail(skb,_skb_pagelen(kb))java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48 return -ENOMEM;
/* Easy case. Most of packets will go this way. */ if (!skb_has_frag_list(skb)) { /* A little of trouble, not enough of space for trailer. *Thisshouldnothappen,whenstackistunedtogenerate *goodframes.OK,onmisswereallocateandreserveevenmore
* space, 128 bytes is fair. */
if (skb_tailroom(skb) < tailbits & mpls_lse ;
pskb_expand_head(
;
/* Voila! */
*trailer = skb;
ops->flow_dissectskb,&proto offset)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 /* It is ensured by skb_flow_dissector_init() that control key will
/* Misery. We are in troubles, going to mincer fragments... */
if skb-sk)
)->frag_list
copyflag = =un_array= rcu_dereferenceinit_net.run_array])java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
}; int ntail = /* we can't use 'proto' in the skb case
/* The fragment is partially pulled by someone, *this prog = READ_ONCErun_array->items[0].prog);
* after it. */
java.lang.StringIndexOutOfBoundsException: Range [16, 4) out of bounds for length 23
}
orry about trailer. */
if =_java.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 74
)-n|
skb_has_frag_list(skb1) |
) <java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
ntail = tailbits + 128;
}
ifcopyflag|
skb_cloned(skb1 }
ntail ||
skb_shinfo(skb1)->java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 13
skb_has_frag_list(skb1)) ifdjava.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 40 struct sk_buff *skb2;
/* Fuck, we are miserable poor guys... */ if (ntail == ip6_flowlabel(){
java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 38 else
skb2 = java.lang.StringIndexOutOfBoundsException: Range [0, 26) out of bounds for length 10
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
,
GFP_ATOMIC); if (unlikely(skb2 vlan = __skb_header_pointer(skb, nhoff, sizeof(_vlan), return data hlen,&vlan)java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
if (skb1->sk)
skb_set_owner_w(skb2, skb1->sk);
/* Looking around. Are we still alive?
* OK, link new skb, drop old one */
skb2->next = skb1->next;
*skb_p = skb2;
kfree_skb(java.lang.StringIndexOutOfBoundsException: Range [2, 1) out of bounds for length 57
skb1 = skb2;
}
elt+
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
skb_p ;
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
EXPORT_SYMBOL_GPL(skb_cow_data);
atomic_subhtons() java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
}
staticvoid skb_set_err_queue(struct sk_buff *skb FLOW_DISSECTOR_KEY_TIPC
{ /* pkt_type of skbs received on local sockets is never PACKET_OUTGOING.ETH_P_MPLS_UC So,itissafeto(mis)useittomarkskbsontheerrorqueue.
*/
skb- break
target_container,data,
}
/* ,&_)java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
*/
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{ if (atomic_read=FLOW_DISSECT_RET_PROTO_AGAIN
(unsignedint)EAD_ONCE(sk-sk_rcvbuf)) return -ENOMEM;
skb;
go
skb->destructor = java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 15
atomic_add(skb->truesize, &sk->java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 18
skb_set_err_queue(skb);
/* before exiting rcu section, make sure dst is refcounted */
skb_dst_force(skb);
skb_queue_tail(&sk->sk_error_queue, skb); if (!sock_flag(sk, SOCK_DEAD))
java.lang.StringIndexOutOfBoundsException: Range [18, 17) out of bounds for length 22 return0;
}
PORT_SYMBOL(sock_queue_err_skb)java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
staticbool is_icmp_err_skb(conststruct sk_buff *skb)
{ return fdret
SKB_EXT_ERR(java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
}
struct sk_buff *java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 8
{ struct* =&-sk_error_queue; struct java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 9 bool icmp_next = false; unsignedlong flagsIPPROTO_TCP:
if (skb_queue_empty_lockless(q)) return NULL_skb_flow_dissect_l2tpv3(skb, flow_dissector, target_container,
spin_lock_irqsave(&q
skb = __java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 9 if data,nhoff hlen)java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 40 if (icmp_next) case FLOW_DISSECT_RET_OUT_GOODjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
sk->sk_err = SKB_EXT_ERR(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
spin_unlock_irqrestore(&q->lock, out_bad:
if (is_icmp_err_skb(skb) && !icmp_next) staticinline size_tflow_keys_hash_lengthconstflow_keysflow)
/**java.lang.StringIndexOutOfBoundsException: Range [19, 17) out of bounds for length 40 *skb_clone_sk-createcloneofskb,and *@skb:theskbtoclone * createsacloneof bufferbufferjava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70 *sk_refcnt.Bufferscreatedviathisfunctionaremeanttobe *returnedusingsock_queue_err_skb,java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 36 * *(__)eys->ports.dst< *itisnecessarytowrapthecallwithsock_hold/java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 *preventthesocketfrombeingreleasedpriortobeingenqueuedon *thesk_error_queue.
*/ struct sk_buff *skb_clone_sk
{java.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 44 struct siphash_key_tkeyval struct sk_buff
if ! |!(sk>sk_refcnt)) return NULL;
clone = skb_clone(skb, GFP_ATOMIC); if
sock_putdst-.java.lang.StringIndexOutOfBoundsException: Range [33, 32) out of bounds for length 37 return NULL;
}
->sk = sk;
clone->destructor = sock_efree;
return*
}
EXPORT_SYMBOL(skb_clone_sk);
staticvoid __skb_complete_tx_timestamp(struct sk_buff *skb*if acanonical4 hash over transportports. struct sock *
t tstypejava.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16 bool opt_stats)
{ struct sock_exterr_skb *serr; int err;
BUILD_BUG_ON __skb_get_hashskb,&eys,perturb)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
serr = SKB_EXT_ERR /* skip L4 headers for fragments after the first */
memset(serr, 0, sizeofreturnpoff;
serr->ee.ee_errno = _off;
serr->ee.ee_origin = java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 12
serr->ee.ee_info = tstype case IPPROTO_UDP:
+structudphdr;
serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0; if (READ_ONCE(sk->sk_tsflags) java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
serr->ee.ee_data = skb_shinfo(skb)->java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 19 if (sk_is_tcp
serr->ee.ee_data -= atomic_read(&sk->sk_tskey);
}
err = sock_queue_err_skb(sk, skb);
if (err)
kfree_skb(skb);
}
java.lang.StringIndexOutOfBoundsException: Range [71, 6) out of bounds for length 62
{ bool ret;
flow_hash_from_keyskeys)java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
.key_id FLOW_DISSECTOR_KEY_CONTROL,
java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 37
. java.lang.StringIndexOutOfBoundsException: Range [27, 20) out of bounds for length 54
file_ns_capable(sk-java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 37
read_unlock_bhsk-sk_callback_lock)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39 return
}
void =offsetofstruct control
*hwtstampsjava.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 1 struct sock *k = skb>sk;
if goto err;
/* Take a reference to prevent skb_orphan() from freeing the socket, onlythejava.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 48
*/ if (
*(&
__skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND, false);
sock_put(sk); return
}
staticbool skb_tstamp_tx_report_so_timestamping(struct sk_buff *skb, struct skb_shared_hwtstamps *hwtstamps, int tstype)
{ switch (tstype) { case SCM_TSTAMP_SCHED: return skb_shinfo(skb)->tx_flags & SKBTX_SCHED_TSTAMP; case SCM_TSTAMP_SND: return skb_shinfo(skb)->tx_flags & (hwtstamps ? SKBTX_HW_TSTAMP_NOBPF :
SKBTX_SW_TSTAMP); case SCM_TSTAMP_ACK: return TCP_SKB_CB(skb)->txstamp_ack & TSTAMP_ACK_SK; case SCM_TSTAMP_COMPLETION: return skb_shinfo(skb)->tx_flags & SKBTX_COMPLETION_TSTAMP;
}
returnfalse;
}
staticvoid skb_tstamp_tx_report_bpf_timestamping(struct sk_buff *skb, struct skb_shared_hwtstamps *hwtstamps, struct sock *sk, int tstype)
{ int op;
switch (tstype) { case SCM_TSTAMP_SCHED:
op = BPF_SOCK_OPS_TSTAMP_SCHED_CB; break; case SCM_TSTAMP_SND: if (hwtstamps) {
op = BPF_SOCK_OPS_TSTAMP_SND_HW_CB;
*skb_hwtstamps(skb) = *hwtstamps;
} else {
op = BPF_SOCK_OPS_TSTAMP_SND_SW_CB;
} break; case SCM_TSTAMP_ACK:
op = BPF_SOCK_OPS_TSTAMP_ACK_CB; break; default: return;
}
/* Take a reference to prevent skb_orphan() from freeing the socket, *butonlyifthesocketrefcountisnotzero.
*/ if (likely(refcount_inc_not_zero(&sk->sk_refcnt))) {
err = sock_queue_err_skb(sk, skb);
sock_put(sk);
} if (err)
kfree_skb(skb);
}
EXPORT_SYMBOL_GPL(skb_complete_wifi_ack); #endif/* CONFIG_WIRELESS */
/* This value should be large enough to cover a tagged ethernet header plus *anIPv6header,alloptions,andamaximalTCPorUDPheader.
*/ #define MAX_IPV6_HDR_LEN 256
len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len); while (off <= len && !done) { switch (nexthdr) { case IPPROTO_DSTOPTS: case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: { struct ipv6_opt_hdr *hp;
err = skb_maybe_pull_tail(skb,
off + sizeof(struct ipv6_opt_hdr),
MAX_IPV6_HDR_LEN); if (err < 0) goto out;
hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
nexthdr = hp->nexthdr;
off += ipv6_optlen(hp); break;
} case IPPROTO_AH: { struct ip_auth_hdr *hp;
err = skb_maybe_pull_tail(skb,
off + sizeof(struct ip_auth_hdr),
MAX_IPV6_HDR_LEN); if (err < 0) goto out;
hp = OPT_HDR(struct ip_auth_hdr, skb, off);
nexthdr = hp->nexthdr;
off += ipv6_authlen(hp); break;
} case IPPROTO_FRAGMENT: { struct frag_hdr *hp;
err = skb_maybe_pull_tail(skb,
off + sizeof(struct frag_hdr),
MAX_IPV6_HDR_LEN); if (err < 0) goto out;
hp = OPT_HDR(struct frag_hdr, skb, off);
if (hp->frag_off & htons(IP6_OFFSET | IP6_MF))
fragment = true;
skb_chk = skb_checksum_maybe_trim(skb, transport_len); if (!skb_chk) goto err;
if (!pskb_may_pull(skb_chk, offset)) goto err;
skb_pull_rcsum(skb_chk, offset);
ret = skb_chkf(skb_chk);
skb_push_rcsum(skb_chk, offset);
if (ret) goto err;
return skb_chk;
err: if (skb_chk && skb_chk != skb)
kfree_skb(skb_chk);
return NULL;
}
EXPORT_SYMBOL(skb_checksum_trimmed);
void __skb_warn_lro_forwarding(conststruct sk_buff *skb)
{
net_warn_ratelimited("%s: received packets cannot be forwarded while LRO is enabled\n",
skb->dev->name);
}
EXPORT_SYMBOL(__skb_warn_lro_forwarding);
/** *skb_try_coalesce-trytomergeskbtopriorone *@to:priorbuffer *@from:buffertoadd *@fragstolen:pointertoboolean *@delta_truesize:howmuchmorewasallocatedthanwasrequested
*/ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, bool *fragstolen, int *delta_truesize)
{ struct skb_shared_info *to_shinfo, *from_shinfo; int i, delta, len = from->len;
*fragstolen = false;
if (skb_cloned(to)) returnfalse;
/* In general, avoid mixing page_pool and non-page_pool allocated *pageswithinthesameSKB.Intheorywecouldtakefull *referencesif@fromisclonedand!@to->pp_recyclebutits *tricky(duetopotentialracewiththeclonedisappearing)and *rare,sonotworthdealingwith.
*/ if (to->pp_recycle != from->pp_recycle) returnfalse;
if (skb_frags_readable(from) != skb_frags_readable(to)) returnfalse;
if (len <= skb_tailroom(to) && skb_frags_readable(from)) { if (len)
BUG_ON(skb_copy_bits(from, 0, skb_put(to, len), len));
*delta_truesize = 0; returntrue;
}
to_shinfo = skb_shinfo(to);
from_shinfo = skb_shinfo(from); if (to_shinfo->frag_list || from_shinfo->frag_list) returnfalse; if (skb_zcopy(to) || skb_zcopy(from)) returnfalse;
if (skb_headlen(from) != 0) { struct page *page; unsignedint offset;
if (to_shinfo->nr_frags +
from_shinfo->nr_frags >= MAX_SKB_FRAGS) returnfalse;
/* if the skb is not cloned this does nothing *sincewesetnr_fragsto0.
*/ if (skb_pp_frag_ref(from)) { for (i = 0; i < from_shinfo->nr_frags; i++)
__skb_frag_ref(&from_shinfo->frags[i]);
}
if (unlikely(skb_vlan_tag_present(skb))) { /* vlan_tci is already set-up so leave this for another time */ return skb;
}
skb = skb_share_check(skb, GFP_ATOMIC); if (unlikely(!skb)) goto err_free; /* We may access the two bytes after vlan_hdr in vlan_set_encap_proto(). */ if (unlikely(!pskb_may_pull(skb, VLAN_HLEN + sizeof(unsignedshort)))) goto err_free;
if (skb_network_offset(skb) < ETH_HLEN)
skb_set_network_header(skb, ETH_HLEN);
skb_reset_mac_len(skb);
return err;
}
EXPORT_SYMBOL(__skb_vlan_pop);
/* Pop a vlan tag either from hwaccel or from payload. *Expectsskb->dataatmacheader.
*/ int skb_vlan_pop(struct sk_buff *skb)
{
u16 vlan_tci;
__be16 vlan_proto; int err;
if (likely(skb_vlan_tag_present(skb))) {
__vlan_hwaccel_clear_tag(skb);
} else { if (unlikely(!eth_type_vlan(skb->protocol))) return0;
err = __skb_vlan_pop(skb, &vlan_tci); if (err) return err;
} /* move next vlan tag to hw accel tag */ if (likely(!eth_type_vlan(skb->protocol))) return0;
/* Push a vlan tag either into hwaccel or into payload (if hwaccel tag present). *Expectsskb->dataatmacheader.
*/ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
{ if (skb_vlan_tag_present(skb)) { int offset = skb->data - skb_mac_header(skb); int err;
if (WARN_ONCE(offset, "skb_vlan_push got skb with skb->data not at mac header (offset %d)\n",
offset)) { return -EINVAL;
}
err = __vlan_insert_tag(skb, skb->vlan_proto,
skb_vlan_tag_get(skb)); if (err) return err;
/* carve out the first off bytes from skb when off < headlen */ staticint pskb_carve_inside_header(struct sk_buff *skb, const u32 off, constint headlen, gfp_t gfp_mask)
{ int i; unsignedint size = skb_end_offset(skb); int new_hlen = headlen - off;
u8 *data;
if (skb_pfmemalloc(skb))
gfp_mask |= __GFP_MEMALLOC;
data = kmalloc_reserve(&size, gfp_mask, NUMA_NO_NODE, NULL); if (!data) return -ENOMEM;
size = SKB_WITH_OVERHEAD(size);
/* Copy real data, and all frags */
skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
skb->len -= off;
memcpy((struct skb_shared_info *)(data + size),
skb_shinfo(skb),
offsetof(struct skb_shared_info,
frags[skb_shinfo(skb)->nr_frags])); if (skb_cloned(skb)) { /* drop the old head gracefully */ if (skb_orphan_frags(skb, gfp_mask)) {
skb_kfree_head(data, size); return -ENOMEM;
} for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
skb_frag_ref(skb, i); if (skb_has_frag_list(skb))
skb_clone_fraglist(skb);
skb_release_data(skb, SKB_CONSUMED);
} else { /* we can reuse existing recount- all we did was *relocatevalues
*/
skb_free_head(skb);
}
/* carve out the first eat bytes from skb's frag_list. May recurse into *pskb_carve()
*/ staticint pskb_carve_frag_list(struct skb_shared_info *shinfo, int eat,
gfp_t gfp_mask)
{ struct sk_buff *list = shinfo->frag_list; struct sk_buff *clone = NULL; struct sk_buff *insp = NULL;
do { if (!list) {
pr_err("Not enough bytes to eat. Want %d\n", eat); return -EFAULT;
} if (list->len <= eat) { /* Eaten as whole. */
eat -= list->len;
list = list->next;
insp = list;
} else { /* Eaten partially. */ if (skb_shared(list)) {
clone = skb_clone(list, gfp_mask); if (!clone) return -ENOMEM;
insp = list->next;
list = clone;
} else { /* This may be pulled without problems. */
insp = list;
} if (pskb_carve(list, eat, gfp_mask) < 0) {
kfree_skb(clone); return -ENOMEM;
} break;
}
} while (eat);
/* Free pulled out fragments. */ while ((list = shinfo->frag_list) != insp) {
shinfo->frag_list = list->next;
consume_skb(list);
} /* And insert new clone at head. */ if (clone) {
clone->next = list;
shinfo->frag_list = clone;
} return0;
}
/* carve off first len bytes from skb. Split line (off) is in the *non-linearpartofskb
*/ staticint pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off, int pos, gfp_t gfp_mask)
{ int i, k = 0; unsignedint size = skb_end_offset(skb);
u8 *data; constint nfrags = skb_shinfo(skb)->nr_frags; struct skb_shared_info *shinfo;
if (skb_pfmemalloc(skb))
gfp_mask |= __GFP_MEMALLOC;
data = kmalloc_reserve(&size, gfp_mask, NUMA_NO_NODE, NULL); if (!data) return -ENOMEM;
size = SKB_WITH_OVERHEAD(size);
memcpy((struct skb_shared_info *)(data + size),
skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0])); if (skb_orphan_frags(skb, gfp_mask)) {
skb_kfree_head(data, size); return -ENOMEM;
}
shinfo = (struct skb_shared_info *)(data + size); for (i = 0; i < nfrags; i++) { int fsize = skb_frag_size(&skb_shinfo(skb)->frags[i]);
if (pos + fsize > off) {
shinfo->frags[k] = skb_shinfo(skb)->frags[i];
if (pos < off) { /* Split frag. *Wehavetwovariantsinthiscase: *1.Moveallthefragtothesecond *part,ifitispossible.F.e. *thisapproachismandatoryforTUX, *wheresplittingisexpensive. *2.Splitisaccurately.Wemakethis.
*/
skb_frag_off_add(&shinfo->frags[0], off - pos);
skb_frag_size_sub(&shinfo->frags[0], off - pos);
}
skb_frag_ref(skb, i);
k++;
}
pos += fsize;
}
shinfo->nr_frags = k; if (skb_has_frag_list(skb))
skb_clone_fraglist(skb);
/* split line is in frag list */ if (k == 0 && pskb_carve_frag_list(shinfo, off - pos, gfp_mask)) { /* skb_frag_unref() is not needed here as shinfo->nr_frags = 0. */ if (skb_has_frag_list(skb))
kfree_skb_list(skb_shinfo(skb)->frag_list);
skb_kfree_head(data, size); return -ENOMEM;
}
skb_release_data(skb, SKB_CONSUMED);
/* remove len bytes from the beginning of the skb */ staticint pskb_carve(struct sk_buff *skb, const u32 len, gfp_t gfp)
{ int headlen = skb_headlen(skb);
/* Extract to_copy bytes starting at off from skb, and return this in *anewskb
*/ struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy, gfp_t gfp)
{ struct sk_buff *clone = skb_clone(skb, gfp);
/* Nice, we can free page frag(s) right now */
__pskb_pull_tail(skb, skb->data_len);
} /* At this point, skb->truesize might be over estimated, *becauseskbhadafragment,andfragmentsdonottell *theirtruesize. *Whenwepulleditscontentintoskb->head,fragment *wasfreed,but__pskb_pull_tail()couldnotpossibly *adjustskb->truesize,notknowingthefragtruesize.
*/
skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));
}
EXPORT_SYMBOL(skb_condense);
void __skb_ext_put(struct skb_ext *ext)
{ /* If this is last clone, nothing can increment *itaftercheckpasses.Avoidsoneatomicop.
*/ if (refcount_read(&ext->refcnt) == 1) goto free_now;
if (!refcount_dec_and_test(&ext->refcnt)) return;
free_now: #ifdef CONFIG_XFRM if (__skb_ext_exist(ext, SKB_EXT_SEC_PATH))
skb_ext_put_sp(skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH)); #endif #ifdef CONFIG_MCTP_FLOWS if (__skb_ext_exist(ext, SKB_EXT_MCTP))
skb_ext_put_mctp(skb_ext_get_ptr(ext, SKB_EXT_MCTP)); #endif
staticvoid kfree_skb_napi_cache(struct sk_buff *skb)
{ /* if SKB is a clone, don't handle this case */ if (skb->fclone != SKB_FCLONE_UNAVAILABLE) {
__kfree_skb(skb); return;
}
spin_lock_bh(&sd->defer_lock); /* Send an IPI every time queue reaches half capacity. */
kick = sd->defer_count == (defer_max >> 1); /* Paired with the READ_ONCE() few lines above */
WRITE_ONCE(sd->defer_count, sd->defer_count + 1);
skb->next = sd->defer_list; /* Paired with READ_ONCE() in skb_defer_free_flush() */
WRITE_ONCE(sd->defer_list, skb);
spin_unlock_bh(&sd->defer_lock);
/* Make sure to trigger NET_RX_SOFTIRQ on the remote CPU *ifweareunluckyenough(thisseemsveryunlikely).
*/ if (unlikely(kick))
kick_defer_list_purge(sd, cpu);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.