root/include/asm-sparc/checksum.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. from32to16
  2. do_csum
  3. ip_fast_csum
  4. csum_partial
  5. csum_partial_copy
  6. ip_compute_csum
  7. csum_fold
  8. csum_tcpudp_magic

   1 /* $Id: checksum.h,v 1.10 1995/11/25 02:31:23 davem Exp $ */
   2 #ifndef __SPARC_CHECKSUM_H
   3 #define __SPARC_CHECKSUM_H
   4 
   5 /*  checksum.h:  IP/UDP/TCP checksum routines on the Sparc.
   6  *
   7  *  Copyright(C) 1995 Linus Torvalds
   8  *  Copyright(C) 1995 Miguel de Icaza
   9  */
  10 
  11 
  12 /* 32 bits version of the checksum routines written for the Alpha by Linus */
  13 extern inline unsigned short from32to16(unsigned long x)
     /* [previous][next][first][last][top][bottom][index][help] */
  14 {
  15         /* add up 16-bit and 17-bit words for 17+c bits */
  16         x = (x & 0xffff) + (x >> 16);
  17         /* add up 16-bit and 2-bit for 16+c bit */
  18         x = (x & 0xffff) + (x >> 16);
  19         /* add up carry.. */
  20         x = (x & 0xffff) + (x >> 16);
  21         return x;
  22 }
  23 
  24 extern inline unsigned long
  25 do_csum(unsigned char * buff, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27         int odd, count;
  28         unsigned long result = 0;
  29 
  30         if (len <= 0)
  31                 goto out;
  32         odd = 1 & (unsigned long) buff;
  33         if (odd) {
  34                 result = *buff << 8;
  35                 len--;
  36                 buff++;
  37         }
  38         count = len >> 1;               /* nr of 16-bit words.. */
  39         if (count) {
  40                 if (2 & (unsigned long) buff) {
  41                         result += *(unsigned short *) buff;
  42                         count--;
  43                         len -= 2;
  44                         buff += 2;
  45                 }
  46                 count >>= 1;            /* nr of 32-bit words.. */
  47                 if (count) {
  48                         unsigned long carry = 0;
  49                         do {
  50                                 unsigned long w = *(unsigned long *) buff;
  51                                 count--;
  52                                 buff += 4;
  53                                 len -= 4;
  54                                 result += carry;
  55                                 result += w;
  56                                 carry = (w > result);
  57                         } while (count);
  58                         result += carry;
  59                         result = (result & 0xffff) + (result >> 16);
  60                 }
  61                 if (len & 2) {
  62                         result += *(unsigned short *) buff;
  63                         buff += 2;
  64                 }
  65         }
  66         if (len & 1)
  67                 result += (*buff) << 8;
  68         result = from32to16(result);
  69         if (odd)
  70                 result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
  71 out:
  72         return result;
  73 }
  74 
  75 extern inline unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
     /* [previous][next][first][last][top][bottom][index][help] */
  76 {
  77         return ~do_csum(iph,ihl*4);
  78 }
  79 
  80 /*
  81  * computes the checksum of a memory block at buff, length len,
  82  * and adds in "sum" (32-bit)
  83  *
  84  * returns a 32-bit number suitable for feeding into itself
  85  * or csum_tcpudp_magic
  86  *
  87  * this function must be called with even lengths, except
  88  * for the last fragment, which may be odd
  89  *
  90  * it's best to have buff aligned on a 32-bit boundary
  91  */
  92 extern inline unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94         unsigned long result = do_csum(buff, len);
  95 
  96         /* add in old sum, and carry.. */
  97         result += sum;
  98         /* 32+c bits -> 32 bits */
  99         result = (result & 0xffff) + (result >> 16);
 100         return result;
 101 }
 102 
 103 /*
 104  * the same as csum_partial, but copies from fs:src while it
 105  * checksums
 106  *
 107  * here even more important to align src and dst on a 32-bit (or even
 108  * better 64-bit) boundary
 109  */
 110 extern inline unsigned int csum_partial_copy(char *src, char *dst, int len, int sum)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112         /*
 113          * The whole idea is to do the copy and the checksum at
 114          * the same time, but we do it the easy way now.
 115          *
 116          * At least csum on the source, not destination, for cache
 117          * reasons..
 118          */
 119         sum = csum_partial(src, len, sum);
 120         memcpy(dst, src, len);
 121         return sum;
 122 }
 123 
 124 /*
 125  * this routine is used for miscellaneous IP-like checksums, mainly
 126  * in icmp.c
 127  */
 128 extern inline unsigned short ip_compute_csum(unsigned char * buff, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130         return ~from32to16(do_csum(buff,len));
 131 }
 132 
 133 #define csum_partial_copy_fromuser(s, d, l, w)  \
 134                        csum_partial_copy((char *) (s), (d), (l), (w))
 135 
 136 /*
 137  *      Fold a partial checksum without adding pseudo headers
 138  */
 139 
 140 static inline unsigned short csum_fold(unsigned int sum)
     /* [previous][next][first][last][top][bottom][index][help] */
 141 {
 142         sum = (sum & 0xffff) + (sum >> 16);
 143         sum = (sum & 0xffff) + (sum >> 16);
 144         return ~sum;
 145 }
 146 
 147 /*
 148  * computes the checksum of the TCP/UDP pseudo-header
 149  * returns a 16-bit checksum, already complemented
 150  */
 151 extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 152                                            unsigned long daddr,
 153                                            unsigned short len,
 154                                            unsigned short proto,
 155                                            unsigned int sum)
 156 {
 157         return ~from32to16 (((saddr >> 16) + (saddr & 0xffff) + (daddr >> 16)
 158                              + (daddr & 0xffff) + (sum >> 16) +
 159                              (sum & 0xffff) + proto + len));
 160 }
 161 
 162 #endif /* !(__SPARC_CHECKSUM_H) */

/* [previous][next][first][last][top][bottom][index][help] */