3 #include <net/udplite.h>
4 #include <asm/checksum.h>
6 #ifndef _HAVE_ARCH_IPV6_CSUM
7 __sum16
csum_ipv6_magic(const struct in6_addr
*saddr
,
8 const struct in6_addr
*daddr
,
9 __u32 len
, __u8 proto
, __wsum csum
)
15 __u32 sum
= (__force u32
)csum
;
17 sum
+= (__force u32
)saddr
->s6_addr32
[0];
18 carry
= (sum
< (__force u32
)saddr
->s6_addr32
[0]);
21 sum
+= (__force u32
)saddr
->s6_addr32
[1];
22 carry
= (sum
< (__force u32
)saddr
->s6_addr32
[1]);
25 sum
+= (__force u32
)saddr
->s6_addr32
[2];
26 carry
= (sum
< (__force u32
)saddr
->s6_addr32
[2]);
29 sum
+= (__force u32
)saddr
->s6_addr32
[3];
30 carry
= (sum
< (__force u32
)saddr
->s6_addr32
[3]);
33 sum
+= (__force u32
)daddr
->s6_addr32
[0];
34 carry
= (sum
< (__force u32
)daddr
->s6_addr32
[0]);
37 sum
+= (__force u32
)daddr
->s6_addr32
[1];
38 carry
= (sum
< (__force u32
)daddr
->s6_addr32
[1]);
41 sum
+= (__force u32
)daddr
->s6_addr32
[2];
42 carry
= (sum
< (__force u32
)daddr
->s6_addr32
[2]);
45 sum
+= (__force u32
)daddr
->s6_addr32
[3];
46 carry
= (sum
< (__force u32
)daddr
->s6_addr32
[3]);
49 ulen
= (__force u32
)htonl((__u32
) len
);
54 uproto
= (__force u32
)htonl(proto
);
56 carry
= (sum
< uproto
);
59 return csum_fold((__force __wsum
)sum
);
61 EXPORT_SYMBOL(csum_ipv6_magic
);
64 int udp6_csum_init(struct sk_buff
*skb
, struct udphdr
*uh
, int proto
)
68 UDP_SKB_CB(skb
)->partial_cov
= 0;
69 UDP_SKB_CB(skb
)->cscov
= skb
->len
;
71 if (proto
== IPPROTO_UDPLITE
) {
72 err
= udplite_checksum_init(skb
, uh
);
76 if (UDP_SKB_CB(skb
)->partial_cov
) {
77 skb
->csum
= ip6_compute_pseudo(skb
, proto
);
82 /* To support RFC 6936 (allow zero checksum in UDP/IPV6 for tunnels)
83 * we accept a checksum of zero here. When we find the socket
84 * for the UDP packet we'll check if that socket allows zero checksum
85 * for IPv6 (set by socket option).
87 * Note, we are only interested in != 0 or == 0, thus the
90 err
= (__force
int)skb_checksum_init_zero_check(skb
, proto
, uh
->check
,
95 if (skb
->ip_summed
== CHECKSUM_COMPLETE
&& !skb
->csum_valid
) {
96 /* If SW calculated the value, we know it's bad */
97 if (skb
->csum_complete_sw
)
100 /* HW says the value is bad. Let's validate that.
101 * skb->csum is no longer the full packet checksum,
102 * so don't treat is as such.
104 skb_checksum_complete_unset(skb
);
109 EXPORT_SYMBOL(udp6_csum_init
);
111 /* Function to set UDP checksum for an IPv6 UDP packet. This is intended
112 * for the simple case like when setting the checksum for a UDP tunnel.
114 void udp6_set_csum(bool nocheck
, struct sk_buff
*skb
,
115 const struct in6_addr
*saddr
,
116 const struct in6_addr
*daddr
, int len
)
118 struct udphdr
*uh
= udp_hdr(skb
);
122 else if (skb_is_gso(skb
))
123 uh
->check
= ~udp_v6_check(len
, saddr
, daddr
, 0);
124 else if (skb
->ip_summed
== CHECKSUM_PARTIAL
) {
126 uh
->check
= udp_v6_check(len
, saddr
, daddr
, lco_csum(skb
));
128 uh
->check
= CSUM_MANGLED_0
;
130 skb
->ip_summed
= CHECKSUM_PARTIAL
;
131 skb
->csum_start
= skb_transport_header(skb
) - skb
->head
;
132 skb
->csum_offset
= offsetof(struct udphdr
, check
);
133 uh
->check
= ~udp_v6_check(len
, saddr
, daddr
, 0);
136 EXPORT_SYMBOL(udp6_set_csum
);