From patchwork Sat Apr 26 21:26:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 343104 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 27BAA14008C for ; Sun, 27 Apr 2014 07:26:28 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752568AbaDZV0X (ORCPT ); Sat, 26 Apr 2014 17:26:23 -0400 Received: from mail-oa0-f73.google.com ([209.85.219.73]:55689 "EHLO mail-oa0-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752474AbaDZV0V (ORCPT ); Sat, 26 Apr 2014 17:26:21 -0400 Received: by mail-oa0-f73.google.com with SMTP id m1so1161713oag.4 for ; Sat, 26 Apr 2014 14:26:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=date:from:to:subject:message-id:user-agent:mime-version :content-type; bh=kPWrHKws8IziyVt6p13la/dwJDYCG+ELI1sI57XJWXs=; b=aasDgaF0OyuAOvnG+ZGaJkVSDDTq8TbmiqpZpQewGKYvOJX0diJA23R4S8Lv7gCoW0 1/iY4tITzAwPDffL8mvIkBcU0l+8k7WGOPjJ7DaTgsZQamcFrOJP8WYYszuYdBQ3GeQf 8kBZfsDC1oRpwYPxXzAwHkMMT6rQUfv4ZNQYdEI1smd87h33BuX4KcjeJ1h2pwlyox8H m+1OFsJ7wE7RWQnbEvNqWGI5xOYK+97nlFT53UAzArchZRMhV77puYrMWa6wAAXeOmbG xcQd2cyBIfe58FM0LvSavhqFyx+5NtE49OQ8Ay8JXnQAaMRXcIc0DNMO7so/okGME31r isjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:subject:message-id:user-agent :mime-version:content-type; bh=kPWrHKws8IziyVt6p13la/dwJDYCG+ELI1sI57XJWXs=; b=bFDQ9GqzxHhxAX8dVl7FDN/RnQcKzIJj99u11kgfQIoaEy3t3zI9/jMapSgLl7Lhhm XCVrLeFRfkaGWsZrsKh8MaCq1Gmaj83R1vhTgFfSRlC63coI/9ASnqAQrQfCeGEzgSoc JhkMhMlXwcuWmmyJsXS1YWqJzYvfRBjJFc7g/ftCEvrcsUfEWK0RAWrhZ99nDGYovNCK dw5EM7N0+S5Ta06T9AENoVlrmbUij/Y48VdJDq3nXhuKnzdz9P8CdZMPB0vECevH2ewC qqitRWLAskdnUWXiw9EGKMwze/3A+vdtWEDDfb7bZWFkCirSrfUScXgzF4CJ817+fXeJ nj0Q== X-Gm-Message-State: ALoCoQn43o6Kwy0z1mLKaNhm5KhC0RrsqFpfXI9GLEm8SkBpftR0k7IiUocnSe+kzcUvz37bhbip018MmnIhNNRRmH87BOmH6LK+gSiBTDqmjY7PN548AS46OTVKeMMDx387yGfXfw3GmbSDZPlpDI9Nvt5cLTonYent9pS2CvKWw0R8xne6J7T/Q5PsDoIj7FsF+Hjh4fi8qOBKhIeJB0zMyBPR2tf+Yw== X-Received: by 10.50.70.66 with SMTP id k2mr6720321igu.7.1398547581357; Sat, 26 Apr 2014 14:26:21 -0700 (PDT) Received: from corp2gmr1-1.hot.corp.google.com (corp2gmr1-1.hot.corp.google.com [172.24.189.92]) by gmr-mx.google.com with ESMTPS id r79si1130486yhj.2.2014.04.26.14.26.21 for (version=TLSv1.1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 26 Apr 2014 14:26:21 -0700 (PDT) Received: from tomh.mtv.corp.google.com (tomh.mtv.corp.google.com [172.18.117.126]) by corp2gmr1-1.hot.corp.google.com (Postfix) with ESMTP id 1D03931C1F4; Sat, 26 Apr 2014 14:26:21 -0700 (PDT) Received: by tomh.mtv.corp.google.com (Postfix, from userid 60832) id CF131200746; Sat, 26 Apr 2014 14:26:20 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by tomh.mtv.corp.google.com (Postfix) with ESMTP id 941BD2003BA; Sat, 26 Apr 2014 14:26:20 -0700 (PDT) Date: Sat, 26 Apr 2014 14:26:20 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net, netdev@vger.kernel.org Subject: [PATCH 8/9 v2] net: Implmement RFC 6936 (zero RX csums for UDP/IPv6) Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org RFC 6936 relaxes the requirement of RFC 2460 that UDP/IPv6 packets which are received with a zero UDP checksum value must be dropped. RFC 6936 allows zero checksums to support tunnels over UDP. When sk_no_check is set we allow on a socket we allow a zero IPv6 UDP checksum. Signed-off-by: Tom Herbert --- net/ipv6/ip6_checksum.c | 19 ++++++++----------- net/ipv6/udp.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c index c69fe37..ca9262a 100644 --- a/net/ipv6/ip6_checksum.c +++ b/net/ipv6/ip6_checksum.c @@ -75,16 +75,13 @@ int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto) return err; } - if (uh->check == 0) { - /* RFC 2460 section 8.1 says that we SHOULD log - this error. Well, it is reasonable. - */ - LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0 for [%pI6c]:%u->[%pI6c]:%u\n", - &ipv6_hdr(skb)->saddr, ntohs(uh->source), - &ipv6_hdr(skb)->daddr, ntohs(uh->dest)); - return 1; - } - - return skb_checksum_init(skb, IPPROTO_UDP, ip6_compute_pseudo); + /* + * To support RFC 6936 (allow zero checksum in UDP/IPV6 for tunnels) + * we accept a checksum of zero here. When we find the socket + * for the UDP packet we'll check if that socket allows zero checksum + * for IPv6 (set by socket option). + */ + return skb_checksum_init_zero_check(skb, proto, uh->check, + ip6_compute_pseudo); } EXPORT_SYMBOL(udp6_csum_init); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1e586d9..787f9d0 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -760,6 +760,18 @@ static void flush_stack(struct sock **stack, unsigned int count, if (unlikely(skb1)) kfree_skb(skb1); } + +static void udp6_csum_zero_error(struct sk_buff *skb) +{ + /* + * RFC 2460 section 8.1 says that we SHOULD log + * this error. Well, it is reasonable. + */ + LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0 for [%pI6c]:%u->[%pI6c]:%u\n", + &ipv6_hdr(skb)->saddr, ntohs(udp_hdr(skb)->source), + &ipv6_hdr(skb)->daddr, ntohs(udp_hdr(skb)->dest)); +} + /* * Note: called only from the BH handler context, * so we don't need to lock the hashes. @@ -779,6 +791,16 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, dif = inet6_iif(skb); sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); while (sk) { + if (!uh->check && !sk->sk_no_check) { + /* + * If zero checksum and sk_no_check is not on for + * the socket then skip it. + */ + sk = udp_v6_mcast_next(net, sk_nulls_next(sk), + uh->dest, daddr, + uh->source, saddr, dif); + continue; + } stack[count++] = sk; sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr, uh->source, saddr, dif); @@ -867,6 +889,11 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (sk != NULL) { int ret; + if (!uh->check && !sk->sk_no_check) { + udp6_csum_zero_error(skb); + goto csum_error; + } + ret = udpv6_queue_rcv_skb(sk, skb); sock_put(sk); @@ -879,6 +906,11 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, return 0; } + if (!uh->check) { + udp6_csum_zero_error(skb); + goto csum_error; + } + if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) goto discard;