2019-05-27 09:55:01 +03:00
/* SPDX-License-Identifier: GPL-2.0-or-later */
2005-04-17 02:20:36 +04:00
/*
* INET An implementation of the TCP / IP protocol suite for the LINUX
* operating system . INET is implemented using the BSD Socket
* interface as the means of communication with the user level .
*
* Checksumming functions for IPv6
*
* Authors : Jorge Cwik , < jorge @ laser . satlink . net >
* Arnt Gulbrandsen , < agulbra @ nvg . unit . no >
* Borrows very liberally from tcp . c and ip . c , see those
* files for more names .
*/
/*
* Fixes :
*
* Ralf Baechle : generic ipv6 checksum
* < ralf @ waldorf - gmbh . de >
*/
# ifndef _CHECKSUM_IPV6_H
# define _CHECKSUM_IPV6_H
# include <asm/types.h>
# include <asm/byteorder.h>
# include <net/ip.h>
# include <asm/checksum.h>
# include <linux/in6.h>
2012-11-15 12:49:17 +04:00
# include <linux/tcp.h>
# include <linux/ipv6.h>
2005-04-17 02:20:36 +04:00
# ifndef _HAVE_ARCH_IPV6_CSUM
2013-01-08 00:52:40 +04:00
__sum16 csum_ipv6_magic ( const struct in6_addr * saddr ,
const struct in6_addr * daddr ,
2016-03-12 01:05:41 +03:00
__u32 len , __u8 proto , __wsum csum ) ;
2005-04-17 02:20:36 +04:00
# endif
2012-11-15 12:49:17 +04:00
2014-05-03 03:29:51 +04:00
static inline __wsum ip6_compute_pseudo ( struct sk_buff * skb , int proto )
{
return ~ csum_unfold ( csum_ipv6_magic ( & ipv6_hdr ( skb ) - > saddr ,
& ipv6_hdr ( skb ) - > daddr ,
skb - > len , proto , 0 ) ) ;
}
2014-08-23 00:34:04 +04:00
static inline __wsum ip6_gro_compute_pseudo ( struct sk_buff * skb , int proto )
{
const struct ipv6hdr * iph = skb_gro_network_header ( skb ) ;
return ~ csum_unfold ( csum_ipv6_magic ( & iph - > saddr , & iph - > daddr ,
skb_gro_len ( skb ) , proto , 0 ) ) ;
}
2012-11-15 12:49:17 +04:00
static __inline__ __sum16 tcp_v6_check ( int len ,
const struct in6_addr * saddr ,
const struct in6_addr * daddr ,
__wsum base )
{
return csum_ipv6_magic ( saddr , daddr , len , IPPROTO_TCP , base ) ;
}
static inline void __tcp_v6_send_check ( struct sk_buff * skb ,
const struct in6_addr * saddr ,
const struct in6_addr * daddr )
{
struct tcphdr * th = tcp_hdr ( skb ) ;
if ( skb - > ip_summed = = CHECKSUM_PARTIAL ) {
th - > check = ~ tcp_v6_check ( skb - > len , saddr , daddr , 0 ) ;
skb - > csum_start = skb_transport_header ( skb ) - skb - > head ;
skb - > csum_offset = offsetof ( struct tcphdr , check ) ;
} else {
th - > check = tcp_v6_check ( skb - > len , saddr , daddr ,
csum_partial ( th , th - > doff < < 2 ,
skb - > csum ) ) ;
}
}
2013-10-09 14:05:48 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2012-11-15 12:49:17 +04:00
static inline void tcp_v6_send_check ( struct sock * sk , struct sk_buff * skb )
{
struct ipv6_pinfo * np = inet6_sk ( sk ) ;
ipv6: make lookups simpler and faster
TCP listener refactoring, part 4 :
To speed up inet lookups, we moved IPv4 addresses from inet to struct
sock_common
Now is time to do the same for IPv6, because it permits us to have fast
lookups for all kind of sockets, including upcoming SYN_RECV.
Getting IPv6 addresses in TCP lookups currently requires two extra cache
lines, plus a dereference (and memory stall).
inet6_sk(sk) does the dereference of inet_sk(__sk)->pinet6
This patch is way bigger than its IPv4 counter part, because for IPv4,
we could add aliases (inet_daddr, inet_rcv_saddr), while on IPv6,
it's not doable easily.
inet6_sk(sk)->daddr becomes sk->sk_v6_daddr
inet6_sk(sk)->rcv_saddr becomes sk->sk_v6_rcv_saddr
And timewait socket also have tw->tw_v6_daddr & tw->tw_v6_rcv_saddr
at the same offset.
We get rid of INET6_TW_MATCH() as INET6_MATCH() is now the generic
macro.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-10-04 02:42:29 +04:00
__tcp_v6_send_check ( skb , & np - > saddr , & sk - > sk_v6_daddr ) ;
2012-11-15 12:49:17 +04:00
}
2013-10-09 14:05:48 +04:00
# endif
2012-11-15 12:49:17 +04:00
2014-06-05 04:19:48 +04:00
static inline __sum16 udp_v6_check ( int len ,
const struct in6_addr * saddr ,
const struct in6_addr * daddr ,
__wsum base )
{
return csum_ipv6_magic ( saddr , daddr , len , IPPROTO_UDP , base ) ;
}
void udp6_set_csum ( bool nocheck , struct sk_buff * skb ,
const struct in6_addr * saddr ,
const struct in6_addr * daddr , int len ) ;
2013-01-08 00:52:40 +04:00
int udp6_csum_init ( struct sk_buff * skb , struct udphdr * uh , int proto ) ;
2005-04-17 02:20:36 +04:00
# endif