* [PATCH 8/8 v3] net: Implmement RFC 6936 (zero csums for UDP/IPv6)
@ 2014-04-29 16:19 Tom Herbert
2014-04-29 17:16 ` Alexander Aring
0 siblings, 1 reply; 2+ messages in thread
From: Tom Herbert @ 2014-04-29 16:19 UTC (permalink / raw)
To: davem, netdev
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. This is for both sending zero checksum and accepting
a zero checksum on receive.
Signed-off-by: Tom Herbert <therbert@google.com>
---
net/ipv6/ip6_checksum.c | 18 +++++++-----------
net/ipv6/udp.c | 33 +++++++++++++++++++++++++++++++--
2 files changed, 38 insertions(+), 13 deletions(-)
diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c
index c69fe37..da26224 100644
--- a/net/ipv6/ip6_checksum.c
+++ b/net/ipv6/ip6_checksum.c
@@ -75,16 +75,12 @@ 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..8037412 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -760,6 +760,17 @@ 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,7 +790,12 @@ 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) {
- stack[count++] = sk;
+ /* If zero checksum and sk_no_check is not on for
+ * the socket then skip it.
+ */
+ if (uh->check || sk->sk_no_check)
+ stack[count++] = sk;
+
sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr,
uh->source, saddr, dif);
if (unlikely(count == ARRAY_SIZE(stack))) {
@@ -867,6 +883,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 +900,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;
@@ -1006,7 +1032,10 @@ static int udp_v6_push_pending_frames(struct sock *sk)
if (is_udplite)
csum = udplite_csum_outgoing(sk, skb);
- else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
+ else if (sk->sk_no_check == UDP_CSUM_NOXMIT) { /* UDP csum disabled */
+ skb->ip_summed = CHECKSUM_NONE;
+ goto send;
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
udp6_hwcsum_outgoing(sk, skb, &fl6->saddr, &fl6->daddr,
up->len);
goto send;
--
1.9.1.423.g4596e3a
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH 8/8 v3] net: Implmement RFC 6936 (zero csums for UDP/IPv6)
2014-04-29 16:19 [PATCH 8/8 v3] net: Implmement RFC 6936 (zero csums for UDP/IPv6) Tom Herbert
@ 2014-04-29 17:16 ` Alexander Aring
0 siblings, 0 replies; 2+ messages in thread
From: Alexander Aring @ 2014-04-29 17:16 UTC (permalink / raw)
To: Tom Herbert; +Cc: davem, netdev
Hello Tom Herbert,
On Tue, Apr 29, 2014 at 09:19:18AM -0700, Tom Herbert wrote:
> 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. This is for both sending zero checksum and accepting
> a zero checksum on receive.
>
I only want to mention that this is a interesting feature which we "maybe"
also can use for the 6LoWPAN IPHC format [0]. This is another possible use
case for this. We doesn't support this at the moment, maybe in the near
future...
It's to save some payload in the UDP header because we could drop the
checksum there, integrity check is already handeld by the MAC layer.
Cheers
Alex
[0] http://tools.ietf.org/html/rfc6282#section-4.3.2
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-04-29 17:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-29 16:19 [PATCH 8/8 v3] net: Implmement RFC 6936 (zero csums for UDP/IPv6) Tom Herbert
2014-04-29 17:16 ` Alexander Aring
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).