checksum.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef _S390_CHECKSUM_H
  2. #define _S390_CHECKSUM_H
  3. /*
  4.  *  include/asm-s390/checksum.h
  5.  *    S390 fast network checksum routines
  6.  *    see also arch/S390/lib/checksum.c
  7.  *
  8.  *  S390 version
  9.  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  10.  *    Author(s): Ulrich Hild        (first version)
  11.  *               Martin Schwidefsky (heavily optimized CKSM version)
  12.  *               D.J. Barrow        (third attempt) 
  13.  */
  14. #include <asm/uaccess.h>
  15. /*
  16.  * computes the checksum of a memory block at buff, length len,
  17.  * and adds in "sum" (32-bit)
  18.  *
  19.  * returns a 32-bit number suitable for feeding into itself
  20.  * or csum_tcpudp_magic
  21.  *
  22.  * this function must be called with even lengths, except
  23.  * for the last fragment, which may be odd
  24.  *
  25.  * it's best to have buff aligned on a 32-bit boundary
  26.  */
  27. unsigned int
  28. csum_partial(const unsigned char * buff, int len, unsigned int sum);
  29. /*
  30.  * csum_partial as an inline function
  31.  */
  32. extern inline unsigned int 
  33. csum_partial_inline(const unsigned char * buff, int len, unsigned int sum)
  34. {
  35. register_pair rp;
  36. rp.subreg.even = (unsigned long) buff;
  37. rp.subreg.odd = (unsigned long) len;
  38. __asm__ __volatile__ (
  39. "0:  cksm %0,%1n"    /* do checksum on longs */
  40. "    jo   0bn"
  41.                 : "+&d" (sum), "+&a" (rp) : : "cc" );
  42. return sum;
  43. }
  44. /*
  45.  * the same as csum_partial, but copies from src while it
  46.  * checksums
  47.  *
  48.  * here even more important to align src and dst on a 32-bit (or even
  49.  * better 64-bit) boundary
  50.  */
  51. extern inline unsigned int 
  52. csum_partial_copy(const char *src, char *dst, int len,unsigned int sum)
  53. {
  54. memcpy(dst,src,len);
  55.         return csum_partial_inline(dst, len, sum);
  56. }
  57. /*
  58.  * the same as csum_partial_copy, but copies from user space.
  59.  *
  60.  * here even more important to align src and dst on a 32-bit (or even
  61.  * better 64-bit) boundary
  62.  *
  63.  * Copy from userspace and compute checksum.  If we catch an exception
  64.  * then zero the rest of the buffer.
  65.  */
  66. extern inline unsigned int 
  67. csum_partial_copy_from_user (const char *src, char *dst,
  68.                                           int len, unsigned int sum,
  69.                                           int *err_ptr)
  70. {
  71. int missing;
  72. missing = copy_from_user(dst, src, len);
  73. if (missing) {
  74. memset(dst + len - missing, 0, missing);
  75. *err_ptr = -EFAULT;
  76. }
  77. return csum_partial(dst, len, sum);
  78. }
  79. extern inline unsigned int
  80. csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum)
  81. {
  82.         memcpy(dst,src,len);
  83.         return csum_partial_inline(dst, len, sum);
  84. }
  85. /*
  86.  *      Fold a partial checksum without adding pseudo headers
  87.  */
  88. #if 1
  89. unsigned short csum_fold(unsigned int sum);
  90. #else
  91. extern inline unsigned short
  92. csum_fold(unsigned int sum)
  93. {
  94. register_pair rp;
  95. __asm__ __volatile__ (
  96. "    slr  %N1,%N1n" /* %0 = H L */
  97. "    lr   %1,%0n"   /* %0 = H L, %1 = H L 0 0 */
  98. "    srdl %1,16n"   /* %0 = H L, %1 = 0 H L 0 */
  99. "    alr  %1,%N1n"  /* %0 = H L, %1 = L H L 0 */
  100. "    alr  %0,%1n"   /* %0 = H+L+C L+H */
  101. "    srl  %0,16n"   /* %0 = H+L+C */
  102. : "+&d" (sum), "=d" (rp) : : "cc" );
  103. return ((unsigned short) ~sum);
  104. }
  105. #endif
  106. /*
  107.  * This is a version of ip_compute_csum() optimized for IP headers,
  108.  * which always checksum on 4 octet boundaries.
  109.  *
  110.  */
  111. extern inline unsigned short
  112. ip_fast_csum(unsigned char *iph, unsigned int ihl)
  113. {
  114. register_pair rp;
  115. unsigned long sum;
  116. rp.subreg.even = (unsigned long) iph;
  117. rp.subreg.odd = (unsigned long) ihl*4;
  118.         __asm__ __volatile__ (
  119. "    sr   %0,%0n"   /* set sum to zero */
  120.                 "0:  cksm %0,%1n"   /* do checksum on longs */
  121.                 "    jo   0bn"
  122.                 : "=&d" (sum), "+&a" (rp) : : "cc" );
  123.         return csum_fold(sum);
  124. }
  125. /*
  126.  * computes the checksum of the TCP/UDP pseudo-header
  127.  * returns a 32-bit checksum
  128.  */
  129. extern inline unsigned int 
  130. csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
  131.                    unsigned short len, unsigned short proto,
  132.                    unsigned int sum)
  133. {
  134. __asm__ __volatile__ (
  135.                 "    alr   %0,%1n"  /* sum += saddr */
  136.                 "    brc   12,0fn"
  137. "    ahi   %0,1n"   /* add carry */
  138. "0:"
  139. : "+&d" (sum) : "d" (saddr) : "cc" );
  140. __asm__ __volatile__ (
  141.                 "    alr   %0,%1n"  /* sum += daddr */
  142.                 "    brc   12,1fn"
  143.                 "    ahi   %0,1n"   /* add carry */
  144. "1:"
  145. : "+&d" (sum) : "d" (daddr) : "cc" );
  146. __asm__ __volatile__ (
  147.                 "    alr   %0,%1n"  /* sum += (len<<16) + (proto<<8) */
  148. "    brc   12,2fn"
  149. "    ahi   %0,1n"   /* add carry */
  150. "2:"
  151. : "+&d" (sum)
  152. : "d" (((unsigned int) len<<16) + (unsigned int) proto)
  153. : "cc" );
  154. return sum;
  155. }
  156. /*
  157.  * computes the checksum of the TCP/UDP pseudo-header
  158.  * returns a 16-bit checksum, already complemented
  159.  */
  160. extern inline unsigned short int
  161. csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
  162.                   unsigned short len, unsigned short proto,
  163.                   unsigned int sum)
  164. {
  165. return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
  166. }
  167. /*
  168.  * this routine is used for miscellaneous IP-like checksums, mainly
  169.  * in icmp.c
  170.  */
  171. extern inline unsigned short
  172. ip_compute_csum(unsigned char * buff, int len)
  173. {
  174. return csum_fold(csum_partial(buff, len, 0));
  175. }
  176. #endif /* _S390_CHECKSUM_H */