1 // SPDX-License-Identifier: GPL-2.0 1 2 /* 3 * arch/alpha/lib/checksum.c 4 * 5 * This file contains network checksum routine 6 * in an architecture-specific manner due to s 7 * Comments in other versions indicate that th 8 * 9 * accelerated versions (and 21264 assembly ve 10 * Rick Gorton <rick.gorton@alpha-pro 11 */ 12 13 #include <linux/module.h> 14 #include <linux/string.h> 15 #include <net/checksum.h> 16 17 #include <asm/byteorder.h> 18 #include <asm/checksum.h> 19 20 static inline unsigned short from64to16(unsign 21 { 22 /* Using extract instructions is a bit 23 than the original shift/bitmask ver 24 25 union { 26 unsigned long ul; 27 unsigned int ui[2]; 28 unsigned short us[4]; 29 } in_v, tmp_v, out_v; 30 31 in_v.ul = x; 32 tmp_v.ul = (unsigned long) in_v.ui[0] 33 34 /* Since the bits of tmp_v.sh[3] are g 35 we don't have to bother to add that 36 out_v.ul = (unsigned long) tmp_v.us[0] 37 + (unsigned long) tmp_ 38 39 /* Similarly, out_v.us[2] is always ze 40 return out_v.us[0] + out_v.us[1]; 41 } 42 43 /* 44 * computes the checksum of the TCP/UDP pseudo 45 * returns a 16-bit checksum, already compleme 46 */ 47 __sum16 csum_tcpudp_magic(__be32 saddr, __be32 48 __u32 len, __u8 prot 49 { 50 return (__force __sum16)~from64to16( 51 (__force u64)saddr + (__force 52 (__force u64)sum + ((len + pro 53 } 54 EXPORT_SYMBOL(csum_tcpudp_magic); 55 56 __wsum csum_tcpudp_nofold(__be32 saddr, __be32 57 __u32 len, __u8 prot 58 { 59 unsigned long result; 60 61 result = (__force u64)saddr + (__force 62 (__force u64)sum + ((len + pr 63 64 /* Fold down to 32-bits so we don't lo 65 network stack. */ 66 /* 64 to 33 */ 67 result = (result & 0xffffffff) + (resu 68 /* 33 to 32 */ 69 result = (result & 0xffffffff) + (resu 70 return (__force __wsum)result; 71 } 72 EXPORT_SYMBOL(csum_tcpudp_nofold); 73 74 /* 75 * Do a 64-bit checksum on an arbitrary memory 76 * 77 * This isn't a great routine, but it's not _h 78 * inner loop could be unrolled a bit further, 79 * ways to do the carry, but this is reasonabl 80 */ 81 static inline unsigned long do_csum(const unsi 82 { 83 int odd, count; 84 unsigned long result = 0; 85 86 if (len <= 0) 87 goto out; 88 odd = 1 & (unsigned long) buff; 89 if (odd) { 90 result = *buff << 8; 91 len--; 92 buff++; 93 } 94 count = len >> 1; /* nr 95 if (count) { 96 if (2 & (unsigned long) buff) 97 result += *(unsigned s 98 count--; 99 len -= 2; 100 buff += 2; 101 } 102 count >>= 1; /* nr 103 if (count) { 104 if (4 & (unsigned long 105 result += *(un 106 count--; 107 len -= 4; 108 buff += 4; 109 } 110 count >>= 1; /* nr 111 if (count) { 112 unsigned long 113 do { 114 unsign 115 count- 116 buff + 117 result 118 result 119 carry 120 } while (count 121 result += carr 122 result = (resu 123 } 124 if (len & 4) { 125 result += *(un 126 buff += 4; 127 } 128 } 129 if (len & 2) { 130 result += *(unsigned s 131 buff += 2; 132 } 133 } 134 if (len & 1) 135 result += *buff; 136 result = from64to16(result); 137 if (odd) 138 result = ((result >> 8) & 0xff 139 out: 140 return result; 141 } 142 143 /* 144 * This is a version of ip_compute_csum() 145 * which always checksum on 4 octet bound 146 */ 147 __sum16 ip_fast_csum(const void *iph, unsigned 148 { 149 return (__force __sum16)~do_csum(iph,i 150 } 151 EXPORT_SYMBOL(ip_fast_csum); 152 153 /* 154 * computes the checksum of a memory block at 155 * and adds in "sum" (32-bit) 156 * 157 * returns a 32-bit number suitable for feedin 158 * or csum_tcpudp_magic 159 * 160 * this function must be called with even leng 161 * for the last fragment, which may be odd 162 * 163 * it's best to have buff aligned on a 32-bit 164 */ 165 __wsum csum_partial(const void *buff, int len, 166 { 167 unsigned long result = do_csum(buff, l 168 169 /* add in old sum, and carry.. */ 170 result += (__force u32)sum; 171 /* 32+c bits -> 32 bits */ 172 result = (result & 0xffffffff) + (resu 173 return (__force __wsum)result; 174 } 175 176 EXPORT_SYMBOL(csum_partial); 177 178 /* 179 * this routine is used for miscellaneous IP-l 180 * in icmp.c 181 */ 182 __sum16 ip_compute_csum(const void *buff, int 183 { 184 return (__force __sum16)~from64to16(do 185 } 186 EXPORT_SYMBOL(ip_compute_csum); 187
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.