/*1* Network checksum routines2*3* Copyright (C) 1999, 2003 Hewlett-Packard Co4* Stephane Eranian <[email protected]>5*6* Most of the code coming from arch/alpha/lib/checksum.c7*8* This file contains network checksum routines that are better done9* in an architecture-specific manner due to speed..10*/1112#include <linux/module.h>13#include <linux/string.h>1415#include <asm/byteorder.h>1617static inline unsigned short18from64to16 (unsigned long x)19{20/* add up 32-bit words for 33 bits */21x = (x & 0xffffffff) + (x >> 32);22/* add up 16-bit and 17-bit words for 17+c bits */23x = (x & 0xffff) + (x >> 16);24/* add up 16-bit and 2-bit for 16+c bit */25x = (x & 0xffff) + (x >> 16);26/* add up carry.. */27x = (x & 0xffff) + (x >> 16);28return x;29}3031/*32* computes the checksum of the TCP/UDP pseudo-header33* returns a 16-bit checksum, already complemented.34*/35__sum1636csum_tcpudp_magic (__be32 saddr, __be32 daddr, unsigned short len,37unsigned short proto, __wsum sum)38{39return (__force __sum16)~from64to16(40(__force u64)saddr + (__force u64)daddr +41(__force u64)sum + ((len + proto) << 8));42}4344EXPORT_SYMBOL(csum_tcpudp_magic);4546__wsum47csum_tcpudp_nofold (__be32 saddr, __be32 daddr, unsigned short len,48unsigned short proto, __wsum sum)49{50unsigned long result;5152result = (__force u64)saddr + (__force u64)daddr +53(__force u64)sum + ((len + proto) << 8);5455/* Fold down to 32-bits so we don't lose in the typedef-less network stack. */56/* 64 to 33 */57result = (result & 0xffffffff) + (result >> 32);58/* 33 to 32 */59result = (result & 0xffffffff) + (result >> 32);60return (__force __wsum)result;61}62EXPORT_SYMBOL(csum_tcpudp_nofold);6364extern unsigned long do_csum (const unsigned char *, long);6566/*67* computes the checksum of a memory block at buff, length len,68* and adds in "sum" (32-bit)69*70* returns a 32-bit number suitable for feeding into itself71* or csum_tcpudp_magic72*73* this function must be called with even lengths, except74* for the last fragment, which may be odd75*76* it's best to have buff aligned on a 32-bit boundary77*/78__wsum csum_partial(const void *buff, int len, __wsum sum)79{80u64 result = do_csum(buff, len);8182/* add in old sum, and carry.. */83result += (__force u32)sum;84/* 32+c bits -> 32 bits */85result = (result & 0xffffffff) + (result >> 32);86return (__force __wsum)result;87}8889EXPORT_SYMBOL(csum_partial);9091/*92* this routine is used for miscellaneous IP-like checksums, mainly93* in icmp.c94*/95__sum16 ip_compute_csum (const void *buff, int len)96{97return (__force __sum16)~do_csum(buff,len);98}99100EXPORT_SYMBOL(ip_compute_csum);101102103