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

Commit 1b5d3535 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'inet_csums_part2'



Tom Herbert says:

====================
net: Checksum offload changes - Part II

I am working on overhauling RX checksum offload. Goals of this effort
are:

- Specify what exactly it means when driver returns CHECKSUM_UNNECESSARY
- Preserve CHECKSUM_COMPLETE through encapsulation layers
- Don't do skb_checksum more than once per packet
- Unify GRO and non-GRO csum verification as much as possible
- Unify the checksum functions (checksum_init)
- Simply code

What is in this second patch set:

- Call common inet checksum validation functions in ICMP{4,6},
  GRE{4,6}, and IGMP.
- In UDP, verify checksum before handing off to encap_rcv.
- Remove custom UDP checksum validation code in L2TP.

Please review carefully and test if possible, mucking with basic
checksum functions is always a little precarious :-)
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1a91de28 58d6085c
Loading
Loading
Loading
Loading
+1 −23
Original line number Diff line number Diff line
@@ -93,28 +93,6 @@ void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
}
EXPORT_SYMBOL_GPL(gre_build_header);

static __sum16 check_checksum(struct sk_buff *skb)
{
	__sum16 csum = 0;

	switch (skb->ip_summed) {
	case CHECKSUM_COMPLETE:
		csum = csum_fold(skb->csum);

		if (!csum)
			break;
		/* Fall through. */

	case CHECKSUM_NONE:
		skb->csum = 0;
		csum = __skb_checksum_complete(skb);
		skb->ip_summed = CHECKSUM_COMPLETE;
		break;
	}

	return csum;
}

static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
			    bool *csum_err)
{
@@ -141,7 +119,7 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,

	options = (__be32 *)(greh + 1);
	if (greh->flags & GRE_CSUM) {
		if (check_checksum(skb)) {
		if (skb_checksum_simple_validate(skb)) {
			*csum_err = true;
			return -EINVAL;
		}
+2 −10
Original line number Diff line number Diff line
@@ -908,16 +908,8 @@ int icmp_rcv(struct sk_buff *skb)

	ICMP_INC_STATS_BH(net, ICMP_MIB_INMSGS);

	switch (skb->ip_summed) {
	case CHECKSUM_COMPLETE:
		if (!csum_fold(skb->csum))
			break;
		/* fall through */
	case CHECKSUM_NONE:
		skb->csum = 0;
		if (__skb_checksum_complete(skb))
	if (skb_checksum_simple_validate(skb))
		goto csum_error;
	}

	if (!pskb_pull(skb, sizeof(*icmph)))
		goto error;
+2 −10
Original line number Diff line number Diff line
@@ -988,16 +988,8 @@ int igmp_rcv(struct sk_buff *skb)
	if (!pskb_may_pull(skb, sizeof(struct igmphdr)))
		goto drop;

	switch (skb->ip_summed) {
	case CHECKSUM_COMPLETE:
		if (!csum_fold(skb->csum))
			break;
		/* fall through */
	case CHECKSUM_NONE:
		skb->csum = 0;
		if (__skb_checksum_complete(skb))
	if (skb_checksum_simple_validate(skb))
		goto drop;
	}

	ih = igmp_hdr(skb);
	switch (ih->type) {
+4 −0
Original line number Diff line number Diff line
@@ -1495,6 +1495,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
		if (skb->len > sizeof(struct udphdr) && encap_rcv != NULL) {
			int ret;

			/* Verify checksum before giving to encap */
			if (udp_lib_checksum_complete(skb))
				goto csum_error;

			ret = encap_rcv(sk, skb);
			if (ret <= 0) {
				UDP_INC_STATS_BH(sock_net(sk),
+5 −16
Original line number Diff line number Diff line
@@ -692,23 +692,12 @@ static int icmpv6_rcv(struct sk_buff *skb)
	saddr = &ipv6_hdr(skb)->saddr;
	daddr = &ipv6_hdr(skb)->daddr;

	/* Perform checksum. */
	switch (skb->ip_summed) {
	case CHECKSUM_COMPLETE:
		if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
				     skb->csum))
			break;
		/* fall through */
	case CHECKSUM_NONE:
		skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
					     IPPROTO_ICMPV6, 0));
		if (__skb_checksum_complete(skb)) {
	if (skb_checksum_validate(skb, IPPROTO_ICMPV6, ip6_compute_pseudo)) {
		LIMIT_NETDEBUG(KERN_DEBUG
			       "ICMPv6 checksum failed [%pI6c > %pI6c]\n",
			       saddr, daddr);
		goto csum_error;
	}
	}

	if (!pskb_pull(skb, sizeof(*hdr)))
		goto discard_it;
Loading