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 .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
/*
* 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>
# ifndef _HAVE_ARCH_IPV6_CSUM
2006-11-15 08:23:59 +03:00
static __inline__ __sum16 csum_ipv6_magic ( const struct in6_addr * saddr ,
const struct in6_addr * daddr ,
__u32 len , unsigned short proto ,
__wsum csum )
2005-04-17 02:20:36 +04:00
{
int carry ;
__u32 ulen ;
__u32 uproto ;
2006-11-15 08:23:59 +03:00
__u32 sum = ( __force u32 ) csum ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
sum + = ( __force u32 ) saddr - > s6_addr32 [ 0 ] ;
carry = ( sum < ( __force u32 ) saddr - > s6_addr32 [ 0 ] ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
sum + = ( __force u32 ) saddr - > s6_addr32 [ 1 ] ;
carry = ( sum < ( __force u32 ) saddr - > s6_addr32 [ 1 ] ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
sum + = ( __force u32 ) saddr - > s6_addr32 [ 2 ] ;
carry = ( sum < ( __force u32 ) saddr - > s6_addr32 [ 2 ] ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
sum + = ( __force u32 ) saddr - > s6_addr32 [ 3 ] ;
carry = ( sum < ( __force u32 ) saddr - > s6_addr32 [ 3 ] ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
sum + = ( __force u32 ) daddr - > s6_addr32 [ 0 ] ;
carry = ( sum < ( __force u32 ) daddr - > s6_addr32 [ 0 ] ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
sum + = ( __force u32 ) daddr - > s6_addr32 [ 1 ] ;
carry = ( sum < ( __force u32 ) daddr - > s6_addr32 [ 1 ] ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
sum + = ( __force u32 ) daddr - > s6_addr32 [ 2 ] ;
carry = ( sum < ( __force u32 ) daddr - > s6_addr32 [ 2 ] ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
sum + = ( __force u32 ) daddr - > s6_addr32 [ 3 ] ;
carry = ( sum < ( __force u32 ) daddr - > s6_addr32 [ 3 ] ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
ulen = ( __force u32 ) htonl ( ( __u32 ) len ) ;
sum + = ulen ;
carry = ( sum < ulen ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-11-15 08:23:59 +03:00
uproto = ( __force u32 ) htonl ( proto ) ;
sum + = uproto ;
carry = ( sum < uproto ) ;
sum + = carry ;
2005-04-17 02:20:36 +04:00
2006-12-22 00:15:18 +03:00
return csum_fold ( ( __force __wsum ) sum ) ;
2005-04-17 02:20:36 +04:00
}
# endif
# endif