Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e3cead5 authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller
Browse files

net: Save software checksum complete



In skb_checksum complete, if we need to compute the checksum for the
packet (via skb_checksum) save the result as CHECKSUM_COMPLETE.
Subsequent checksum verification can use this.

Also, added csum_complete_sw flag to distinguish between software and
hardware generated checksum complete, we should always be able to trust
the software computation.

Signed-off-by: default avatarTom Herbert <therbert@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5d0c2b95
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -573,7 +573,8 @@ struct sk_buff {
	__u8			encapsulation:1;
	__u8			encap_hdr_csum:1;
	__u8			csum_valid:1;
	/* 4/6 bit hole (depending on ndisc_nodetype presence) */
	__u8			csum_complete_sw:1;
	/* 3/5 bit hole (depending on ndisc_nodetype presence) */
	kmemcheck_bitfield_end(flags2);

#if defined CONFIG_NET_DMA || defined CONFIG_NET_RX_BUSY_POLL
+9 −5
Original line number Diff line number Diff line
@@ -739,11 +739,15 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
	__sum16 sum;

	sum = csum_fold(skb_checksum(skb, 0, len, skb->csum));
	if (likely(!sum)) {
		if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
	if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && !sum &&
	    !skb->csum_complete_sw)
		netdev_rx_csum_fault(skb->dev);
		skb->ip_summed = CHECKSUM_UNNECESSARY;
	}

	/* Save checksum complete for later use */
	skb->csum = sum;
	skb->ip_summed = CHECKSUM_COMPLETE;
	skb->csum_complete_sw = 1;

	return sum;
}
EXPORT_SYMBOL(__skb_checksum_complete_head);
+4 −2
Original line number Diff line number Diff line
@@ -131,10 +131,12 @@ static __sum16 gro_skb_checksum(struct sk_buff *skb)
		csum_partial(skb->data, skb_gro_offset(skb), 0));
	sum = csum_fold(NAPI_GRO_CB(skb)->csum);
	if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) {
		if (unlikely(!sum))
		if (unlikely(!sum) && !skb->csum_complete_sw)
			netdev_rx_csum_fault(skb->dev);
	} else
	} else {
		skb->ip_summed = CHECKSUM_COMPLETE;
		skb->csum_complete_sw = 1;
	}

	return sum;
}
+2 −1
Original line number Diff line number Diff line
@@ -173,7 +173,8 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
		return -1;
	if (csum_fold(desc.csum))
		return -1;
	if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
	if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
	    !skb->csum_complete_sw)
		netdev_rx_csum_fault(skb->dev);
	return 0;
no_checksum: