1 /* SPDX-License-Identifier: GPL-2.0-or-later * << 2 /* 1 /* 3 * INET An implementation of the TCP/I 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 4 * operating system. INET is imp 3 * operating system. INET is implemented using the BSD Socket 5 * interface as the means of comm 4 * interface as the means of communication with the user level. 6 * 5 * 7 * Checksumming functions for IPv 6 * Checksumming functions for IPv6 8 * 7 * 9 * Authors: Jorge Cwik, <jorge@laser.satli 8 * Authors: Jorge Cwik, <jorge@laser.satlink.net> 10 * Arnt Gulbrandsen, <agulbra@nvg 9 * Arnt Gulbrandsen, <agulbra@nvg.unit.no> 11 * Borrows very liberally from tc 10 * Borrows very liberally from tcp.c and ip.c, see those 12 * files for more names. 11 * files for more names. >> 12 * >> 13 * This program is free software; you can redistribute it and/or >> 14 * modify it under the terms of the GNU General Public License >> 15 * as published by the Free Software Foundation; either version >> 16 * 2 of the License, or (at your option) any later version. 13 */ 17 */ 14 18 15 /* 19 /* 16 * Fixes: 20 * Fixes: 17 * 21 * 18 * Ralf Baechle : 22 * Ralf Baechle : generic ipv6 checksum 19 * <ralf@waldorf-gmbh.de> 23 * <ralf@waldorf-gmbh.de> 20 */ 24 */ 21 25 22 #ifndef _CHECKSUM_IPV6_H 26 #ifndef _CHECKSUM_IPV6_H 23 #define _CHECKSUM_IPV6_H 27 #define _CHECKSUM_IPV6_H 24 28 25 #include <asm/types.h> 29 #include <asm/types.h> 26 #include <asm/byteorder.h> 30 #include <asm/byteorder.h> 27 #include <net/ip.h> 31 #include <net/ip.h> 28 #include <asm/checksum.h> 32 #include <asm/checksum.h> 29 #include <linux/in6.h> 33 #include <linux/in6.h> 30 #include <linux/tcp.h> 34 #include <linux/tcp.h> 31 #include <linux/ipv6.h> 35 #include <linux/ipv6.h> 32 36 33 #ifndef _HAVE_ARCH_IPV6_CSUM 37 #ifndef _HAVE_ARCH_IPV6_CSUM 34 __sum16 csum_ipv6_magic(const struct in6_addr 38 __sum16 csum_ipv6_magic(const struct in6_addr *saddr, 35 const struct in6_addr 39 const struct in6_addr *daddr, 36 __u32 len, __u8 proto, 40 __u32 len, __u8 proto, __wsum csum); 37 #endif 41 #endif 38 42 39 static inline __wsum ip6_compute_pseudo(struct 43 static inline __wsum ip6_compute_pseudo(struct sk_buff *skb, int proto) 40 { 44 { 41 return ~csum_unfold(csum_ipv6_magic(&i 45 return ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, 42 &i 46 &ipv6_hdr(skb)->daddr, 43 sk 47 skb->len, proto, 0)); 44 } 48 } 45 49 >> 50 static inline __wsum ip6_gro_compute_pseudo(struct sk_buff *skb, int proto) >> 51 { >> 52 const struct ipv6hdr *iph = skb_gro_network_header(skb); >> 53 >> 54 return ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr, >> 55 skb_gro_len(skb), proto, 0)); >> 56 } >> 57 46 static __inline__ __sum16 tcp_v6_check(int len 58 static __inline__ __sum16 tcp_v6_check(int len, 47 const struc 59 const struct in6_addr *saddr, 48 const struc 60 const struct in6_addr *daddr, 49 __wsum base 61 __wsum base) 50 { 62 { 51 return csum_ipv6_magic(saddr, daddr, l 63 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); 52 } 64 } 53 65 54 static inline void __tcp_v6_send_check(struct 66 static inline void __tcp_v6_send_check(struct sk_buff *skb, 55 const s 67 const struct in6_addr *saddr, 56 const s 68 const struct in6_addr *daddr) 57 { 69 { 58 struct tcphdr *th = tcp_hdr(skb); 70 struct tcphdr *th = tcp_hdr(skb); 59 71 60 th->check = ~tcp_v6_check(skb->len, sa !! 72 if (skb->ip_summed == CHECKSUM_PARTIAL) { 61 skb->csum_start = skb_transport_header !! 73 th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0); 62 skb->csum_offset = offsetof(struct tcp !! 74 skb->csum_start = skb_transport_header(skb) - skb->head; >> 75 skb->csum_offset = offsetof(struct tcphdr, check); >> 76 } else { >> 77 th->check = tcp_v6_check(skb->len, saddr, daddr, >> 78 csum_partial(th, th->doff << 2, >> 79 skb->csum)); >> 80 } 63 } 81 } 64 82 65 static inline void tcp_v6_gso_csum_prep(struct !! 83 #if IS_ENABLED(CONFIG_IPV6) >> 84 static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) 66 { 85 { 67 struct ipv6hdr *ipv6h = ipv6_hdr(skb); !! 86 struct ipv6_pinfo *np = inet6_sk(sk); 68 struct tcphdr *th = tcp_hdr(skb); << 69 87 70 ipv6h->payload_len = 0; !! 88 __tcp_v6_send_check(skb, &np->saddr, &sk->sk_v6_daddr); 71 th->check = ~tcp_v6_check(0, &ipv6h->s << 72 } 89 } >> 90 #endif 73 91 74 static inline __sum16 udp_v6_check(int len, 92 static inline __sum16 udp_v6_check(int len, 75 const struc 93 const struct in6_addr *saddr, 76 const struc 94 const struct in6_addr *daddr, 77 __wsum base 95 __wsum base) 78 { 96 { 79 return csum_ipv6_magic(saddr, daddr, l 97 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, base); 80 } 98 } 81 99 82 void udp6_set_csum(bool nocheck, struct sk_buf 100 void udp6_set_csum(bool nocheck, struct sk_buff *skb, 83 const struct in6_addr *sadd 101 const struct in6_addr *saddr, 84 const struct in6_addr *dadd 102 const struct in6_addr *daddr, int len); 85 103 86 int udp6_csum_init(struct sk_buff *skb, struct 104 int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto); 87 #endif 105 #endif 88 106
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.