162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci#include <net/gro.h>
362306a36Sopenharmony_ci#include <net/dst_metadata.h>
462306a36Sopenharmony_ci#include <net/busy_poll.h>
562306a36Sopenharmony_ci#include <trace/events/net.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#define MAX_GRO_SKBS 8
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/* This should be increased if a protocol with a bigger head is added. */
1062306a36Sopenharmony_ci#define GRO_MAX_HEAD (MAX_HEADER + 128)
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic DEFINE_SPINLOCK(offload_lock);
1362306a36Sopenharmony_cistruct list_head offload_base __read_mostly = LIST_HEAD_INIT(offload_base);
1462306a36Sopenharmony_ci/* Maximum number of GRO_NORMAL skbs to batch up for list-RX */
1562306a36Sopenharmony_ciint gro_normal_batch __read_mostly = 8;
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/**
1862306a36Sopenharmony_ci *	dev_add_offload - register offload handlers
1962306a36Sopenharmony_ci *	@po: protocol offload declaration
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci *	Add protocol offload handlers to the networking stack. The passed
2262306a36Sopenharmony_ci *	&proto_offload is linked into kernel lists and may not be freed until
2362306a36Sopenharmony_ci *	it has been removed from the kernel lists.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci *	This call does not sleep therefore it can not
2662306a36Sopenharmony_ci *	guarantee all CPU's that are in middle of receiving packets
2762306a36Sopenharmony_ci *	will see the new offload handlers (until the next received packet).
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_civoid dev_add_offload(struct packet_offload *po)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	struct packet_offload *elem;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	spin_lock(&offload_lock);
3462306a36Sopenharmony_ci	list_for_each_entry(elem, &offload_base, list) {
3562306a36Sopenharmony_ci		if (po->priority < elem->priority)
3662306a36Sopenharmony_ci			break;
3762306a36Sopenharmony_ci	}
3862306a36Sopenharmony_ci	list_add_rcu(&po->list, elem->list.prev);
3962306a36Sopenharmony_ci	spin_unlock(&offload_lock);
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ciEXPORT_SYMBOL(dev_add_offload);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/**
4462306a36Sopenharmony_ci *	__dev_remove_offload	 - remove offload handler
4562306a36Sopenharmony_ci *	@po: packet offload declaration
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci *	Remove a protocol offload handler that was previously added to the
4862306a36Sopenharmony_ci *	kernel offload handlers by dev_add_offload(). The passed &offload_type
4962306a36Sopenharmony_ci *	is removed from the kernel lists and can be freed or reused once this
5062306a36Sopenharmony_ci *	function returns.
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci *      The packet type might still be in use by receivers
5362306a36Sopenharmony_ci *	and must not be freed until after all the CPU's have gone
5462306a36Sopenharmony_ci *	through a quiescent state.
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_cistatic void __dev_remove_offload(struct packet_offload *po)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	struct list_head *head = &offload_base;
5962306a36Sopenharmony_ci	struct packet_offload *po1;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	spin_lock(&offload_lock);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	list_for_each_entry(po1, head, list) {
6462306a36Sopenharmony_ci		if (po == po1) {
6562306a36Sopenharmony_ci			list_del_rcu(&po->list);
6662306a36Sopenharmony_ci			goto out;
6762306a36Sopenharmony_ci		}
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	pr_warn("dev_remove_offload: %p not found\n", po);
7162306a36Sopenharmony_ciout:
7262306a36Sopenharmony_ci	spin_unlock(&offload_lock);
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/**
7662306a36Sopenharmony_ci *	dev_remove_offload	 - remove packet offload handler
7762306a36Sopenharmony_ci *	@po: packet offload declaration
7862306a36Sopenharmony_ci *
7962306a36Sopenharmony_ci *	Remove a packet offload handler that was previously added to the kernel
8062306a36Sopenharmony_ci *	offload handlers by dev_add_offload(). The passed &offload_type is
8162306a36Sopenharmony_ci *	removed from the kernel lists and can be freed or reused once this
8262306a36Sopenharmony_ci *	function returns.
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci *	This call sleeps to guarantee that no CPU is looking at the packet
8562306a36Sopenharmony_ci *	type after return.
8662306a36Sopenharmony_ci */
8762306a36Sopenharmony_civoid dev_remove_offload(struct packet_offload *po)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	__dev_remove_offload(po);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	synchronize_net();
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ciEXPORT_SYMBOL(dev_remove_offload);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ciint skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb);
9962306a36Sopenharmony_ci	unsigned int offset = skb_gro_offset(skb);
10062306a36Sopenharmony_ci	unsigned int headlen = skb_headlen(skb);
10162306a36Sopenharmony_ci	unsigned int len = skb_gro_len(skb);
10262306a36Sopenharmony_ci	unsigned int delta_truesize;
10362306a36Sopenharmony_ci	unsigned int gro_max_size;
10462306a36Sopenharmony_ci	unsigned int new_truesize;
10562306a36Sopenharmony_ci	struct sk_buff *lp;
10662306a36Sopenharmony_ci	int segs;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	/* Do not splice page pool based packets w/ non-page pool
10962306a36Sopenharmony_ci	 * packets. This can result in reference count issues as page
11062306a36Sopenharmony_ci	 * pool pages will not decrement the reference count and will
11162306a36Sopenharmony_ci	 * instead be immediately returned to the pool or have frag
11262306a36Sopenharmony_ci	 * count decremented.
11362306a36Sopenharmony_ci	 */
11462306a36Sopenharmony_ci	if (p->pp_recycle != skb->pp_recycle)
11562306a36Sopenharmony_ci		return -ETOOMANYREFS;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	/* pairs with WRITE_ONCE() in netif_set_gro(_ipv4)_max_size() */
11862306a36Sopenharmony_ci	gro_max_size = p->protocol == htons(ETH_P_IPV6) ?
11962306a36Sopenharmony_ci			READ_ONCE(p->dev->gro_max_size) :
12062306a36Sopenharmony_ci			READ_ONCE(p->dev->gro_ipv4_max_size);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (unlikely(p->len + len >= gro_max_size || NAPI_GRO_CB(skb)->flush))
12362306a36Sopenharmony_ci		return -E2BIG;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	if (unlikely(p->len + len >= GRO_LEGACY_MAX_SIZE)) {
12662306a36Sopenharmony_ci		if (NAPI_GRO_CB(skb)->proto != IPPROTO_TCP ||
12762306a36Sopenharmony_ci		    (p->protocol == htons(ETH_P_IPV6) &&
12862306a36Sopenharmony_ci		     skb_headroom(p) < sizeof(struct hop_jumbo_hdr)) ||
12962306a36Sopenharmony_ci		    p->encapsulation)
13062306a36Sopenharmony_ci			return -E2BIG;
13162306a36Sopenharmony_ci	}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	segs = NAPI_GRO_CB(skb)->count;
13462306a36Sopenharmony_ci	lp = NAPI_GRO_CB(p)->last;
13562306a36Sopenharmony_ci	pinfo = skb_shinfo(lp);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	if (headlen <= offset) {
13862306a36Sopenharmony_ci		skb_frag_t *frag;
13962306a36Sopenharmony_ci		skb_frag_t *frag2;
14062306a36Sopenharmony_ci		int i = skbinfo->nr_frags;
14162306a36Sopenharmony_ci		int nr_frags = pinfo->nr_frags + i;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci		if (nr_frags > MAX_SKB_FRAGS)
14462306a36Sopenharmony_ci			goto merge;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci		offset -= headlen;
14762306a36Sopenharmony_ci		pinfo->nr_frags = nr_frags;
14862306a36Sopenharmony_ci		skbinfo->nr_frags = 0;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci		frag = pinfo->frags + nr_frags;
15162306a36Sopenharmony_ci		frag2 = skbinfo->frags + i;
15262306a36Sopenharmony_ci		do {
15362306a36Sopenharmony_ci			*--frag = *--frag2;
15462306a36Sopenharmony_ci		} while (--i);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		skb_frag_off_add(frag, offset);
15762306a36Sopenharmony_ci		skb_frag_size_sub(frag, offset);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci		/* all fragments truesize : remove (head size + sk_buff) */
16062306a36Sopenharmony_ci		new_truesize = SKB_TRUESIZE(skb_end_offset(skb));
16162306a36Sopenharmony_ci		delta_truesize = skb->truesize - new_truesize;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci		skb->truesize = new_truesize;
16462306a36Sopenharmony_ci		skb->len -= skb->data_len;
16562306a36Sopenharmony_ci		skb->data_len = 0;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE;
16862306a36Sopenharmony_ci		goto done;
16962306a36Sopenharmony_ci	} else if (skb->head_frag) {
17062306a36Sopenharmony_ci		int nr_frags = pinfo->nr_frags;
17162306a36Sopenharmony_ci		skb_frag_t *frag = pinfo->frags + nr_frags;
17262306a36Sopenharmony_ci		struct page *page = virt_to_head_page(skb->head);
17362306a36Sopenharmony_ci		unsigned int first_size = headlen - offset;
17462306a36Sopenharmony_ci		unsigned int first_offset;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci		if (nr_frags + 1 + skbinfo->nr_frags > MAX_SKB_FRAGS)
17762306a36Sopenharmony_ci			goto merge;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci		first_offset = skb->data -
18062306a36Sopenharmony_ci			       (unsigned char *)page_address(page) +
18162306a36Sopenharmony_ci			       offset;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci		pinfo->nr_frags = nr_frags + 1 + skbinfo->nr_frags;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci		skb_frag_fill_page_desc(frag, page, first_offset, first_size);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci		memcpy(frag + 1, skbinfo->frags, sizeof(*frag) * skbinfo->nr_frags);
18862306a36Sopenharmony_ci		/* We dont need to clear skbinfo->nr_frags here */
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci		new_truesize = SKB_DATA_ALIGN(sizeof(struct sk_buff));
19162306a36Sopenharmony_ci		delta_truesize = skb->truesize - new_truesize;
19262306a36Sopenharmony_ci		skb->truesize = new_truesize;
19362306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD;
19462306a36Sopenharmony_ci		goto done;
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cimerge:
19862306a36Sopenharmony_ci	/* sk owenrship - if any - completely transferred to the aggregated packet */
19962306a36Sopenharmony_ci	skb->destructor = NULL;
20062306a36Sopenharmony_ci	delta_truesize = skb->truesize;
20162306a36Sopenharmony_ci	if (offset > headlen) {
20262306a36Sopenharmony_ci		unsigned int eat = offset - headlen;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci		skb_frag_off_add(&skbinfo->frags[0], eat);
20562306a36Sopenharmony_ci		skb_frag_size_sub(&skbinfo->frags[0], eat);
20662306a36Sopenharmony_ci		skb->data_len -= eat;
20762306a36Sopenharmony_ci		skb->len -= eat;
20862306a36Sopenharmony_ci		offset = headlen;
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	__skb_pull(skb, offset);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	if (NAPI_GRO_CB(p)->last == p)
21462306a36Sopenharmony_ci		skb_shinfo(p)->frag_list = skb;
21562306a36Sopenharmony_ci	else
21662306a36Sopenharmony_ci		NAPI_GRO_CB(p)->last->next = skb;
21762306a36Sopenharmony_ci	NAPI_GRO_CB(p)->last = skb;
21862306a36Sopenharmony_ci	__skb_header_release(skb);
21962306a36Sopenharmony_ci	lp = p;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cidone:
22262306a36Sopenharmony_ci	NAPI_GRO_CB(p)->count += segs;
22362306a36Sopenharmony_ci	p->data_len += len;
22462306a36Sopenharmony_ci	p->truesize += delta_truesize;
22562306a36Sopenharmony_ci	p->len += len;
22662306a36Sopenharmony_ci	if (lp != p) {
22762306a36Sopenharmony_ci		lp->data_len += len;
22862306a36Sopenharmony_ci		lp->truesize += delta_truesize;
22962306a36Sopenharmony_ci		lp->len += len;
23062306a36Sopenharmony_ci	}
23162306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->same_flow = 1;
23262306a36Sopenharmony_ci	return 0;
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic void napi_gro_complete(struct napi_struct *napi, struct sk_buff *skb)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	struct packet_offload *ptype;
23962306a36Sopenharmony_ci	__be16 type = skb->protocol;
24062306a36Sopenharmony_ci	struct list_head *head = &offload_base;
24162306a36Sopenharmony_ci	int err = -ENOENT;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct napi_gro_cb) > sizeof(skb->cb));
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	if (NAPI_GRO_CB(skb)->count == 1) {
24662306a36Sopenharmony_ci		skb_shinfo(skb)->gso_size = 0;
24762306a36Sopenharmony_ci		goto out;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	rcu_read_lock();
25162306a36Sopenharmony_ci	list_for_each_entry_rcu(ptype, head, list) {
25262306a36Sopenharmony_ci		if (ptype->type != type || !ptype->callbacks.gro_complete)
25362306a36Sopenharmony_ci			continue;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci		err = INDIRECT_CALL_INET(ptype->callbacks.gro_complete,
25662306a36Sopenharmony_ci					 ipv6_gro_complete, inet_gro_complete,
25762306a36Sopenharmony_ci					 skb, 0);
25862306a36Sopenharmony_ci		break;
25962306a36Sopenharmony_ci	}
26062306a36Sopenharmony_ci	rcu_read_unlock();
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (err) {
26362306a36Sopenharmony_ci		WARN_ON(&ptype->list == head);
26462306a36Sopenharmony_ci		kfree_skb(skb);
26562306a36Sopenharmony_ci		return;
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ciout:
26962306a36Sopenharmony_ci	gro_normal_one(napi, skb, NAPI_GRO_CB(skb)->count);
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistatic void __napi_gro_flush_chain(struct napi_struct *napi, u32 index,
27362306a36Sopenharmony_ci				   bool flush_old)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	struct list_head *head = &napi->gro_hash[index].list;
27662306a36Sopenharmony_ci	struct sk_buff *skb, *p;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	list_for_each_entry_safe_reverse(skb, p, head, list) {
27962306a36Sopenharmony_ci		if (flush_old && NAPI_GRO_CB(skb)->age == jiffies)
28062306a36Sopenharmony_ci			return;
28162306a36Sopenharmony_ci		skb_list_del_init(skb);
28262306a36Sopenharmony_ci		napi_gro_complete(napi, skb);
28362306a36Sopenharmony_ci		napi->gro_hash[index].count--;
28462306a36Sopenharmony_ci	}
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	if (!napi->gro_hash[index].count)
28762306a36Sopenharmony_ci		__clear_bit(index, &napi->gro_bitmask);
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci/* napi->gro_hash[].list contains packets ordered by age.
29162306a36Sopenharmony_ci * youngest packets at the head of it.
29262306a36Sopenharmony_ci * Complete skbs in reverse order to reduce latencies.
29362306a36Sopenharmony_ci */
29462306a36Sopenharmony_civoid napi_gro_flush(struct napi_struct *napi, bool flush_old)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	unsigned long bitmask = napi->gro_bitmask;
29762306a36Sopenharmony_ci	unsigned int i, base = ~0U;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	while ((i = ffs(bitmask)) != 0) {
30062306a36Sopenharmony_ci		bitmask >>= i;
30162306a36Sopenharmony_ci		base += i;
30262306a36Sopenharmony_ci		__napi_gro_flush_chain(napi, base, flush_old);
30362306a36Sopenharmony_ci	}
30462306a36Sopenharmony_ci}
30562306a36Sopenharmony_ciEXPORT_SYMBOL(napi_gro_flush);
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_cistatic unsigned long gro_list_prepare_tc_ext(const struct sk_buff *skb,
30862306a36Sopenharmony_ci					     const struct sk_buff *p,
30962306a36Sopenharmony_ci					     unsigned long diffs)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
31262306a36Sopenharmony_ci	struct tc_skb_ext *skb_ext;
31362306a36Sopenharmony_ci	struct tc_skb_ext *p_ext;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	skb_ext = skb_ext_find(skb, TC_SKB_EXT);
31662306a36Sopenharmony_ci	p_ext = skb_ext_find(p, TC_SKB_EXT);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	diffs |= (!!p_ext) ^ (!!skb_ext);
31962306a36Sopenharmony_ci	if (!diffs && unlikely(skb_ext))
32062306a36Sopenharmony_ci		diffs |= p_ext->chain ^ skb_ext->chain;
32162306a36Sopenharmony_ci#endif
32262306a36Sopenharmony_ci	return diffs;
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic void gro_list_prepare(const struct list_head *head,
32662306a36Sopenharmony_ci			     const struct sk_buff *skb)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	unsigned int maclen = skb->dev->hard_header_len;
32962306a36Sopenharmony_ci	u32 hash = skb_get_hash_raw(skb);
33062306a36Sopenharmony_ci	struct sk_buff *p;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	list_for_each_entry(p, head, list) {
33362306a36Sopenharmony_ci		unsigned long diffs;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci		NAPI_GRO_CB(p)->flush = 0;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci		if (hash != skb_get_hash_raw(p)) {
33862306a36Sopenharmony_ci			NAPI_GRO_CB(p)->same_flow = 0;
33962306a36Sopenharmony_ci			continue;
34062306a36Sopenharmony_ci		}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci		diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
34362306a36Sopenharmony_ci		diffs |= p->vlan_all ^ skb->vlan_all;
34462306a36Sopenharmony_ci		diffs |= skb_metadata_differs(p, skb);
34562306a36Sopenharmony_ci		if (maclen == ETH_HLEN)
34662306a36Sopenharmony_ci			diffs |= compare_ether_header(skb_mac_header(p),
34762306a36Sopenharmony_ci						      skb_mac_header(skb));
34862306a36Sopenharmony_ci		else if (!diffs)
34962306a36Sopenharmony_ci			diffs = memcmp(skb_mac_header(p),
35062306a36Sopenharmony_ci				       skb_mac_header(skb),
35162306a36Sopenharmony_ci				       maclen);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci		/* in most common scenarions 'slow_gro' is 0
35462306a36Sopenharmony_ci		 * otherwise we are already on some slower paths
35562306a36Sopenharmony_ci		 * either skip all the infrequent tests altogether or
35662306a36Sopenharmony_ci		 * avoid trying too hard to skip each of them individually
35762306a36Sopenharmony_ci		 */
35862306a36Sopenharmony_ci		if (!diffs && unlikely(skb->slow_gro | p->slow_gro)) {
35962306a36Sopenharmony_ci			diffs |= p->sk != skb->sk;
36062306a36Sopenharmony_ci			diffs |= skb_metadata_dst_cmp(p, skb);
36162306a36Sopenharmony_ci			diffs |= skb_get_nfct(p) ^ skb_get_nfct(skb);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci			diffs |= gro_list_prepare_tc_ext(skb, p, diffs);
36462306a36Sopenharmony_ci		}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci		NAPI_GRO_CB(p)->same_flow = !diffs;
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci}
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_cistatic inline void skb_gro_reset_offset(struct sk_buff *skb, u32 nhoff)
37162306a36Sopenharmony_ci{
37262306a36Sopenharmony_ci	const struct skb_shared_info *pinfo = skb_shinfo(skb);
37362306a36Sopenharmony_ci	const skb_frag_t *frag0 = &pinfo->frags[0];
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->data_offset = 0;
37662306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->frag0 = NULL;
37762306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->frag0_len = 0;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	if (!skb_headlen(skb) && pinfo->nr_frags &&
38062306a36Sopenharmony_ci	    !PageHighMem(skb_frag_page(frag0)) &&
38162306a36Sopenharmony_ci	    (!NET_IP_ALIGN || !((skb_frag_off(frag0) + nhoff) & 3))) {
38262306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
38362306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int,
38462306a36Sopenharmony_ci						    skb_frag_size(frag0),
38562306a36Sopenharmony_ci						    skb->end - skb->tail);
38662306a36Sopenharmony_ci	}
38762306a36Sopenharmony_ci}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic void gro_pull_from_frag0(struct sk_buff *skb, int grow)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	struct skb_shared_info *pinfo = skb_shinfo(skb);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	BUG_ON(skb->end - skb->tail < grow);
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	memcpy(skb_tail_pointer(skb), NAPI_GRO_CB(skb)->frag0, grow);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	skb->data_len -= grow;
39862306a36Sopenharmony_ci	skb->tail += grow;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	skb_frag_off_add(&pinfo->frags[0], grow);
40162306a36Sopenharmony_ci	skb_frag_size_sub(&pinfo->frags[0], grow);
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	if (unlikely(!skb_frag_size(&pinfo->frags[0]))) {
40462306a36Sopenharmony_ci		skb_frag_unref(skb, 0);
40562306a36Sopenharmony_ci		memmove(pinfo->frags, pinfo->frags + 1,
40662306a36Sopenharmony_ci			--pinfo->nr_frags * sizeof(pinfo->frags[0]));
40762306a36Sopenharmony_ci	}
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic void gro_try_pull_from_frag0(struct sk_buff *skb)
41162306a36Sopenharmony_ci{
41262306a36Sopenharmony_ci	int grow = skb_gro_offset(skb) - skb_headlen(skb);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	if (grow > 0)
41562306a36Sopenharmony_ci		gro_pull_from_frag0(skb, grow);
41662306a36Sopenharmony_ci}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_cistatic void gro_flush_oldest(struct napi_struct *napi, struct list_head *head)
41962306a36Sopenharmony_ci{
42062306a36Sopenharmony_ci	struct sk_buff *oldest;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	oldest = list_last_entry(head, struct sk_buff, list);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	/* We are called with head length >= MAX_GRO_SKBS, so this is
42562306a36Sopenharmony_ci	 * impossible.
42662306a36Sopenharmony_ci	 */
42762306a36Sopenharmony_ci	if (WARN_ON_ONCE(!oldest))
42862306a36Sopenharmony_ci		return;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	/* Do not adjust napi->gro_hash[].count, caller is adding a new
43162306a36Sopenharmony_ci	 * SKB to the chain.
43262306a36Sopenharmony_ci	 */
43362306a36Sopenharmony_ci	skb_list_del_init(oldest);
43462306a36Sopenharmony_ci	napi_gro_complete(napi, oldest);
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cistatic enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
43862306a36Sopenharmony_ci{
43962306a36Sopenharmony_ci	u32 bucket = skb_get_hash_raw(skb) & (GRO_HASH_BUCKETS - 1);
44062306a36Sopenharmony_ci	struct gro_list *gro_list = &napi->gro_hash[bucket];
44162306a36Sopenharmony_ci	struct list_head *head = &offload_base;
44262306a36Sopenharmony_ci	struct packet_offload *ptype;
44362306a36Sopenharmony_ci	__be16 type = skb->protocol;
44462306a36Sopenharmony_ci	struct sk_buff *pp = NULL;
44562306a36Sopenharmony_ci	enum gro_result ret;
44662306a36Sopenharmony_ci	int same_flow;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	if (netif_elide_gro(skb->dev))
44962306a36Sopenharmony_ci		goto normal;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	gro_list_prepare(&gro_list->list, skb);
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	rcu_read_lock();
45462306a36Sopenharmony_ci	list_for_each_entry_rcu(ptype, head, list) {
45562306a36Sopenharmony_ci		if (ptype->type == type && ptype->callbacks.gro_receive)
45662306a36Sopenharmony_ci			goto found_ptype;
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci	rcu_read_unlock();
45962306a36Sopenharmony_ci	goto normal;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cifound_ptype:
46262306a36Sopenharmony_ci	skb_set_network_header(skb, skb_gro_offset(skb));
46362306a36Sopenharmony_ci	skb_reset_mac_len(skb);
46462306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof_field(struct napi_gro_cb, zeroed) != sizeof(u32));
46562306a36Sopenharmony_ci	BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct napi_gro_cb, zeroed),
46662306a36Sopenharmony_ci					sizeof(u32))); /* Avoid slow unaligned acc */
46762306a36Sopenharmony_ci	*(u32 *)&NAPI_GRO_CB(skb)->zeroed = 0;
46862306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->flush = skb_has_frag_list(skb);
46962306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->is_atomic = 1;
47062306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->count = 1;
47162306a36Sopenharmony_ci	if (unlikely(skb_is_gso(skb))) {
47262306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->count = skb_shinfo(skb)->gso_segs;
47362306a36Sopenharmony_ci		/* Only support TCP and non DODGY users. */
47462306a36Sopenharmony_ci		if (!skb_is_gso_tcp(skb) ||
47562306a36Sopenharmony_ci		    (skb_shinfo(skb)->gso_type & SKB_GSO_DODGY))
47662306a36Sopenharmony_ci			NAPI_GRO_CB(skb)->flush = 1;
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	/* Setup for GRO checksum validation */
48062306a36Sopenharmony_ci	switch (skb->ip_summed) {
48162306a36Sopenharmony_ci	case CHECKSUM_COMPLETE:
48262306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->csum = skb->csum;
48362306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->csum_valid = 1;
48462306a36Sopenharmony_ci		break;
48562306a36Sopenharmony_ci	case CHECKSUM_UNNECESSARY:
48662306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->csum_cnt = skb->csum_level + 1;
48762306a36Sopenharmony_ci		break;
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	pp = INDIRECT_CALL_INET(ptype->callbacks.gro_receive,
49162306a36Sopenharmony_ci				ipv6_gro_receive, inet_gro_receive,
49262306a36Sopenharmony_ci				&gro_list->list, skb);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	rcu_read_unlock();
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	if (PTR_ERR(pp) == -EINPROGRESS) {
49762306a36Sopenharmony_ci		ret = GRO_CONSUMED;
49862306a36Sopenharmony_ci		goto ok;
49962306a36Sopenharmony_ci	}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	same_flow = NAPI_GRO_CB(skb)->same_flow;
50262306a36Sopenharmony_ci	ret = NAPI_GRO_CB(skb)->free ? GRO_MERGED_FREE : GRO_MERGED;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	if (pp) {
50562306a36Sopenharmony_ci		skb_list_del_init(pp);
50662306a36Sopenharmony_ci		napi_gro_complete(napi, pp);
50762306a36Sopenharmony_ci		gro_list->count--;
50862306a36Sopenharmony_ci	}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	if (same_flow)
51162306a36Sopenharmony_ci		goto ok;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	if (NAPI_GRO_CB(skb)->flush)
51462306a36Sopenharmony_ci		goto normal;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	if (unlikely(gro_list->count >= MAX_GRO_SKBS))
51762306a36Sopenharmony_ci		gro_flush_oldest(napi, &gro_list->list);
51862306a36Sopenharmony_ci	else
51962306a36Sopenharmony_ci		gro_list->count++;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	/* Must be called before setting NAPI_GRO_CB(skb)->{age|last} */
52262306a36Sopenharmony_ci	gro_try_pull_from_frag0(skb);
52362306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->age = jiffies;
52462306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->last = skb;
52562306a36Sopenharmony_ci	if (!skb_is_gso(skb))
52662306a36Sopenharmony_ci		skb_shinfo(skb)->gso_size = skb_gro_len(skb);
52762306a36Sopenharmony_ci	list_add(&skb->list, &gro_list->list);
52862306a36Sopenharmony_ci	ret = GRO_HELD;
52962306a36Sopenharmony_ciok:
53062306a36Sopenharmony_ci	if (gro_list->count) {
53162306a36Sopenharmony_ci		if (!test_bit(bucket, &napi->gro_bitmask))
53262306a36Sopenharmony_ci			__set_bit(bucket, &napi->gro_bitmask);
53362306a36Sopenharmony_ci	} else if (test_bit(bucket, &napi->gro_bitmask)) {
53462306a36Sopenharmony_ci		__clear_bit(bucket, &napi->gro_bitmask);
53562306a36Sopenharmony_ci	}
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	return ret;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_cinormal:
54062306a36Sopenharmony_ci	ret = GRO_NORMAL;
54162306a36Sopenharmony_ci	gro_try_pull_from_frag0(skb);
54262306a36Sopenharmony_ci	goto ok;
54362306a36Sopenharmony_ci}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_cistruct packet_offload *gro_find_receive_by_type(__be16 type)
54662306a36Sopenharmony_ci{
54762306a36Sopenharmony_ci	struct list_head *offload_head = &offload_base;
54862306a36Sopenharmony_ci	struct packet_offload *ptype;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	list_for_each_entry_rcu(ptype, offload_head, list) {
55162306a36Sopenharmony_ci		if (ptype->type != type || !ptype->callbacks.gro_receive)
55262306a36Sopenharmony_ci			continue;
55362306a36Sopenharmony_ci		return ptype;
55462306a36Sopenharmony_ci	}
55562306a36Sopenharmony_ci	return NULL;
55662306a36Sopenharmony_ci}
55762306a36Sopenharmony_ciEXPORT_SYMBOL(gro_find_receive_by_type);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_cistruct packet_offload *gro_find_complete_by_type(__be16 type)
56062306a36Sopenharmony_ci{
56162306a36Sopenharmony_ci	struct list_head *offload_head = &offload_base;
56262306a36Sopenharmony_ci	struct packet_offload *ptype;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	list_for_each_entry_rcu(ptype, offload_head, list) {
56562306a36Sopenharmony_ci		if (ptype->type != type || !ptype->callbacks.gro_complete)
56662306a36Sopenharmony_ci			continue;
56762306a36Sopenharmony_ci		return ptype;
56862306a36Sopenharmony_ci	}
56962306a36Sopenharmony_ci	return NULL;
57062306a36Sopenharmony_ci}
57162306a36Sopenharmony_ciEXPORT_SYMBOL(gro_find_complete_by_type);
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_cistatic gro_result_t napi_skb_finish(struct napi_struct *napi,
57462306a36Sopenharmony_ci				    struct sk_buff *skb,
57562306a36Sopenharmony_ci				    gro_result_t ret)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	switch (ret) {
57862306a36Sopenharmony_ci	case GRO_NORMAL:
57962306a36Sopenharmony_ci		gro_normal_one(napi, skb, 1);
58062306a36Sopenharmony_ci		break;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	case GRO_MERGED_FREE:
58362306a36Sopenharmony_ci		if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
58462306a36Sopenharmony_ci			napi_skb_free_stolen_head(skb);
58562306a36Sopenharmony_ci		else if (skb->fclone != SKB_FCLONE_UNAVAILABLE)
58662306a36Sopenharmony_ci			__kfree_skb(skb);
58762306a36Sopenharmony_ci		else
58862306a36Sopenharmony_ci			__napi_kfree_skb(skb, SKB_CONSUMED);
58962306a36Sopenharmony_ci		break;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	case GRO_HELD:
59262306a36Sopenharmony_ci	case GRO_MERGED:
59362306a36Sopenharmony_ci	case GRO_CONSUMED:
59462306a36Sopenharmony_ci		break;
59562306a36Sopenharmony_ci	}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	return ret;
59862306a36Sopenharmony_ci}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_cigro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
60162306a36Sopenharmony_ci{
60262306a36Sopenharmony_ci	gro_result_t ret;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	skb_mark_napi_id(skb, napi);
60562306a36Sopenharmony_ci	trace_napi_gro_receive_entry(skb);
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	skb_gro_reset_offset(skb, 0);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	ret = napi_skb_finish(napi, skb, dev_gro_receive(napi, skb));
61062306a36Sopenharmony_ci	trace_napi_gro_receive_exit(ret);
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	return ret;
61362306a36Sopenharmony_ci}
61462306a36Sopenharmony_ciEXPORT_SYMBOL(napi_gro_receive);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_cistatic void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
61762306a36Sopenharmony_ci{
61862306a36Sopenharmony_ci	if (unlikely(skb->pfmemalloc)) {
61962306a36Sopenharmony_ci		consume_skb(skb);
62062306a36Sopenharmony_ci		return;
62162306a36Sopenharmony_ci	}
62262306a36Sopenharmony_ci	__skb_pull(skb, skb_headlen(skb));
62362306a36Sopenharmony_ci	/* restore the reserve we had after netdev_alloc_skb_ip_align() */
62462306a36Sopenharmony_ci	skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb));
62562306a36Sopenharmony_ci	__vlan_hwaccel_clear_tag(skb);
62662306a36Sopenharmony_ci	skb->dev = napi->dev;
62762306a36Sopenharmony_ci	skb->skb_iif = 0;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	/* eth_type_trans() assumes pkt_type is PACKET_HOST */
63062306a36Sopenharmony_ci	skb->pkt_type = PACKET_HOST;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	skb->encapsulation = 0;
63362306a36Sopenharmony_ci	skb_shinfo(skb)->gso_type = 0;
63462306a36Sopenharmony_ci	skb_shinfo(skb)->gso_size = 0;
63562306a36Sopenharmony_ci	if (unlikely(skb->slow_gro)) {
63662306a36Sopenharmony_ci		skb_orphan(skb);
63762306a36Sopenharmony_ci		skb_ext_reset(skb);
63862306a36Sopenharmony_ci		nf_reset_ct(skb);
63962306a36Sopenharmony_ci		skb->slow_gro = 0;
64062306a36Sopenharmony_ci	}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	napi->skb = skb;
64362306a36Sopenharmony_ci}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_cistruct sk_buff *napi_get_frags(struct napi_struct *napi)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	struct sk_buff *skb = napi->skb;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	if (!skb) {
65062306a36Sopenharmony_ci		skb = napi_alloc_skb(napi, GRO_MAX_HEAD);
65162306a36Sopenharmony_ci		if (skb) {
65262306a36Sopenharmony_ci			napi->skb = skb;
65362306a36Sopenharmony_ci			skb_mark_napi_id(skb, napi);
65462306a36Sopenharmony_ci		}
65562306a36Sopenharmony_ci	}
65662306a36Sopenharmony_ci	return skb;
65762306a36Sopenharmony_ci}
65862306a36Sopenharmony_ciEXPORT_SYMBOL(napi_get_frags);
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_cistatic gro_result_t napi_frags_finish(struct napi_struct *napi,
66162306a36Sopenharmony_ci				      struct sk_buff *skb,
66262306a36Sopenharmony_ci				      gro_result_t ret)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	switch (ret) {
66562306a36Sopenharmony_ci	case GRO_NORMAL:
66662306a36Sopenharmony_ci	case GRO_HELD:
66762306a36Sopenharmony_ci		__skb_push(skb, ETH_HLEN);
66862306a36Sopenharmony_ci		skb->protocol = eth_type_trans(skb, skb->dev);
66962306a36Sopenharmony_ci		if (ret == GRO_NORMAL)
67062306a36Sopenharmony_ci			gro_normal_one(napi, skb, 1);
67162306a36Sopenharmony_ci		break;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	case GRO_MERGED_FREE:
67462306a36Sopenharmony_ci		if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
67562306a36Sopenharmony_ci			napi_skb_free_stolen_head(skb);
67662306a36Sopenharmony_ci		else
67762306a36Sopenharmony_ci			napi_reuse_skb(napi, skb);
67862306a36Sopenharmony_ci		break;
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	case GRO_MERGED:
68162306a36Sopenharmony_ci	case GRO_CONSUMED:
68262306a36Sopenharmony_ci		break;
68362306a36Sopenharmony_ci	}
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	return ret;
68662306a36Sopenharmony_ci}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci/* Upper GRO stack assumes network header starts at gro_offset=0
68962306a36Sopenharmony_ci * Drivers could call both napi_gro_frags() and napi_gro_receive()
69062306a36Sopenharmony_ci * We copy ethernet header into skb->data to have a common layout.
69162306a36Sopenharmony_ci */
69262306a36Sopenharmony_cistatic struct sk_buff *napi_frags_skb(struct napi_struct *napi)
69362306a36Sopenharmony_ci{
69462306a36Sopenharmony_ci	struct sk_buff *skb = napi->skb;
69562306a36Sopenharmony_ci	const struct ethhdr *eth;
69662306a36Sopenharmony_ci	unsigned int hlen = sizeof(*eth);
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	napi->skb = NULL;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	skb_reset_mac_header(skb);
70162306a36Sopenharmony_ci	skb_gro_reset_offset(skb, hlen);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	if (unlikely(skb_gro_header_hard(skb, hlen))) {
70462306a36Sopenharmony_ci		eth = skb_gro_header_slow(skb, hlen, 0);
70562306a36Sopenharmony_ci		if (unlikely(!eth)) {
70662306a36Sopenharmony_ci			net_warn_ratelimited("%s: dropping impossible skb from %s\n",
70762306a36Sopenharmony_ci					     __func__, napi->dev->name);
70862306a36Sopenharmony_ci			napi_reuse_skb(napi, skb);
70962306a36Sopenharmony_ci			return NULL;
71062306a36Sopenharmony_ci		}
71162306a36Sopenharmony_ci	} else {
71262306a36Sopenharmony_ci		eth = (const struct ethhdr *)skb->data;
71362306a36Sopenharmony_ci		gro_pull_from_frag0(skb, hlen);
71462306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->frag0 += hlen;
71562306a36Sopenharmony_ci		NAPI_GRO_CB(skb)->frag0_len -= hlen;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci	__skb_pull(skb, hlen);
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	/*
72062306a36Sopenharmony_ci	 * This works because the only protocols we care about don't require
72162306a36Sopenharmony_ci	 * special handling.
72262306a36Sopenharmony_ci	 * We'll fix it up properly in napi_frags_finish()
72362306a36Sopenharmony_ci	 */
72462306a36Sopenharmony_ci	skb->protocol = eth->h_proto;
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	return skb;
72762306a36Sopenharmony_ci}
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_cigro_result_t napi_gro_frags(struct napi_struct *napi)
73062306a36Sopenharmony_ci{
73162306a36Sopenharmony_ci	gro_result_t ret;
73262306a36Sopenharmony_ci	struct sk_buff *skb = napi_frags_skb(napi);
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	trace_napi_gro_frags_entry(skb);
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	ret = napi_frags_finish(napi, skb, dev_gro_receive(napi, skb));
73762306a36Sopenharmony_ci	trace_napi_gro_frags_exit(ret);
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	return ret;
74062306a36Sopenharmony_ci}
74162306a36Sopenharmony_ciEXPORT_SYMBOL(napi_gro_frags);
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci/* Compute the checksum from gro_offset and return the folded value
74462306a36Sopenharmony_ci * after adding in any pseudo checksum.
74562306a36Sopenharmony_ci */
74662306a36Sopenharmony_ci__sum16 __skb_gro_checksum_complete(struct sk_buff *skb)
74762306a36Sopenharmony_ci{
74862306a36Sopenharmony_ci	__wsum wsum;
74962306a36Sopenharmony_ci	__sum16 sum;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb), 0);
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	/* NAPI_GRO_CB(skb)->csum holds pseudo checksum */
75462306a36Sopenharmony_ci	sum = csum_fold(csum_add(NAPI_GRO_CB(skb)->csum, wsum));
75562306a36Sopenharmony_ci	/* See comments in __skb_checksum_complete(). */
75662306a36Sopenharmony_ci	if (likely(!sum)) {
75762306a36Sopenharmony_ci		if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
75862306a36Sopenharmony_ci		    !skb->csum_complete_sw)
75962306a36Sopenharmony_ci			netdev_rx_csum_fault(skb->dev, skb);
76062306a36Sopenharmony_ci	}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->csum = wsum;
76362306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->csum_valid = 1;
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	return sum;
76662306a36Sopenharmony_ci}
76762306a36Sopenharmony_ciEXPORT_SYMBOL(__skb_gro_checksum_complete);
768