From patchwork Thu Dec 4 00:44:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 417598 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 993A81400E2 for ; Thu, 4 Dec 2014 11:45:15 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752273AbaLDApH (ORCPT ); Wed, 3 Dec 2014 19:45:07 -0500 Received: from mail-ie0-f171.google.com ([209.85.223.171]:46408 "EHLO mail-ie0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751106AbaLDApF (ORCPT ); Wed, 3 Dec 2014 19:45:05 -0500 Received: by mail-ie0-f171.google.com with SMTP id rl12so14747090iec.2 for ; Wed, 03 Dec 2014 16:45:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=pAJC7m6J+K6gTZcvdZwgAA+0L5ejFTgVYTxd+4RYKgs=; b=FJVFvBeJJ/oWMyPeWlK+6Zz6eqjyAu38UsFahxNT3oI3ThYu4RqmiNdUJns/VgcCJM /JVMSzWk4HX92kaxhR4HLMs0C1JDSQPl75MwbnfDUHidsmnkgPC6icFdiRYlo/E57MfX 0Z/VvWueITDhYKiz3h1vNuOsz78tAh5yif/EZn0R/a7hm82WIY0ZvwaaPGxtBBeA4/0T fXX2KFeVlb0vvIu0ptSrYiEeil261j7TM5aXh+kSfOKmRyrWQYN8hUXIdAyFKBOwOYCN 1OT4E80zTor3pyQQqZfq3BiUv+blo3C05RhZH+/V06ayJpoZKjtIKPCkWid8gm4zU9gs IFcg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=pAJC7m6J+K6gTZcvdZwgAA+0L5ejFTgVYTxd+4RYKgs=; b=EkIOK6ph68m4HiY9mHt1oZF5ZHqH/WM4XU4vdhJbvSkCLz7H38yKRjkt3hGT+nDe+Q wZnw/WSKLESF6Ipip89FpE+lW92DZTAIjRx30PpwCFeWckQ0gj3LkBCaej74ulNOJi6E 5wO5oUXc6Lz9l7FqSmuJ4P51RPBcOc2h8kS0drzA3sA2ScoCnHKRr6HhWHbuzu3zB25c q7GiqpJ847/jwtYkypvZaiyQTZUfoHsh5BOUPX9IcgqV2fJdl1H5+mWilDy5k1V8ak9a cO1Nezgzd2rqLN/6yUui4+gLisFXyOdMEAK3raF7gUfkUsgbGGzOHM4cOKHvlqfpaKSo 8D0A== X-Gm-Message-State: ALoCoQn3P7T82gzrDVfIA7HLbgCn3Fh1Jjr35jCHn9rnaboaD9DrOAablTCasbgl55gQjmE8siAr X-Received: by 10.42.71.194 with SMTP id l2mr9120529icj.71.1417653904643; Wed, 03 Dec 2014 16:45:04 -0800 (PST) Received: from tomh.mtv.corp.google.com ([172.18.117.126]) by mx.google.com with ESMTPSA id qc7sm8354103igb.5.2014.12.03.16.45.03 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 03 Dec 2014 16:45:04 -0800 (PST) From: Tom Herbert To: davem@davemloft.net, netdev@vger.kernel.org Subject: [PATCH net-next 3/3] ip: Add support for IP_CHECKSUM cmsg Date: Wed, 3 Dec 2014 16:44:28 -0800 Message-Id: <1417653868-14922-4-git-send-email-therbert@google.com> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c In-Reply-To: <1417653868-14922-1-git-send-email-therbert@google.com> References: <1417653868-14922-1-git-send-email-therbert@google.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org New cmsg type is IP_CHECKSUM under SOL_IP. Enabled by standard setsockopt. The value returned is the unfolded 32 bit checksum of the packet being received starting from the first byte returned in recvmsg through the end of the packet (truncation is disregarded). Modified UDP to postpull checksum beyond UDP header before returning checksum for UDP data to userspace. Signed-off-by: Tom Herbert --- include/net/inet_sock.h | 1 + include/uapi/linux/in.h | 1 + net/ipv4/ip_sockglue.c | 34 +++++++++++++++++++++++++++++++++- net/ipv4/udp.c | 10 +++++++++- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 4091fab..2823fc0 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -203,6 +203,7 @@ struct inet_sock { #define IP_CMSG_RETOPTS (1 << 4) #define IP_CMSG_PASSSEC (1 << 5) #define IP_CMSG_ORIGDSTADDR (1 << 6) +#define IP_CMSG_CHECKSUM (1 << 7) static inline struct inet_sock *inet_sk(const struct sock *sk) { diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h index c33a65e..589ced0 100644 --- a/include/uapi/linux/in.h +++ b/include/uapi/linux/in.h @@ -109,6 +109,7 @@ struct in_addr { #define IP_MINTTL 21 #define IP_NODEFRAG 22 +#define IP_CHECKSUM 23 /* IP_MTU_DISCOVER values */ #define IP_PMTUDISC_DONT 0 /* Never send DF frames */ diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index d4406aa..054280f 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -96,6 +96,14 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb) put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data); } +static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb) +{ + if (skb->ip_summed != CHECKSUM_COMPLETE) + return; + + put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &skb->csum); +} + static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) { char *secdata; @@ -190,9 +198,16 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) return; } - if (flags & IP_CMSG_ORIGDSTADDR) + if (flags & IP_CMSG_ORIGDSTADDR) { ip_cmsg_recv_dstaddr(msg, skb); + flags &= ~IP_CMSG_ORIGDSTADDR; + if (!flags) + return; + } + + if (flags & IP_CMSG_CHECKSUM) + ip_cmsg_recv_checksum(msg, skb); } EXPORT_SYMBOL(ip_cmsg_recv); @@ -512,6 +527,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, case IP_MULTICAST_ALL: case IP_MULTICAST_LOOP: case IP_RECVORIGDSTADDR: + case IP_CHECKSUM: if (optlen >= sizeof(int)) { if (get_user(val, (int __user *) optval)) return -EFAULT; @@ -609,6 +625,19 @@ static int do_ip_setsockopt(struct sock *sk, int level, else inet->cmsg_flags &= ~IP_CMSG_ORIGDSTADDR; break; + case IP_CHECKSUM: + if (val) { + if (!(inet->cmsg_flags & IP_CMSG_CHECKSUM)) { + inet_inc_convert_csum(sk); + inet->cmsg_flags |= IP_CMSG_CHECKSUM; + } + } else { + if (inet->cmsg_flags & IP_CMSG_CHECKSUM) { + inet_dec_convert_csum(sk); + inet->cmsg_flags &= ~IP_CMSG_CHECKSUM; + } + } + break; case IP_TOS: /* This sets both TOS and Precedence */ if (sk->sk_type == SOCK_STREAM) { val &= ~INET_ECN_MASK; @@ -1212,6 +1241,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, case IP_RECVORIGDSTADDR: val = (inet->cmsg_flags & IP_CMSG_ORIGDSTADDR) != 0; break; + case IP_CHECKSUM: + val = (inet->cmsg_flags & IP_CMSG_CHECKSUM) != 0; + break; case IP_TOS: val = inet->tos; break; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 221b53f..bba2e06 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1315,8 +1315,16 @@ try_again: memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); *addr_len = sizeof(*sin); } - if (inet->cmsg_flags) + if (inet->cmsg_flags) { + /* Pull checksum past UDP header in case we are providing + * checksum in cmsg. + */ + if (inet->cmsg_flags & IP_CMSG_CHECKSUM) + skb_postpull_rcsum(skb, skb->data, + sizeof(struct udphdr)); + ip_cmsg_recv(msg, skb); + } err = copied; if (flags & MSG_TRUNC)