Print this page
11848 Remove STRUIO_IP support from ip_cksum.c
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/ip_cksum.c
+++ new/usr/src/uts/common/os/ip_cksum.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25 /* Copyright (c) 1990 Mentat Inc. */
26 +/*
27 + * Copyright 2019 Joyent, Inc.
28 + */
26 29
27 30 #include <sys/types.h>
28 31 #include <sys/inttypes.h>
29 32 #include <sys/systm.h>
30 33 #include <sys/stream.h>
31 34 #include <sys/strsun.h>
35 +#include <sys/strsubr.h>
32 36 #include <sys/debug.h>
33 37 #include <sys/ddi.h>
34 38 #include <sys/vtrace.h>
35 39 #include <inet/sctp_crc32.h>
36 40 #include <inet/ip.h>
37 41
38 42 #include <sys/multidata.h>
39 43 #include <sys/multidata_impl.h>
40 44
41 -extern unsigned int ip_ocsum(ushort_t *address, int halfword_count,
45 +extern unsigned int ip_ocsum(ushort_t *address, int halfword_count,
42 46 unsigned int sum);
43 47
44 48 /*
45 49 * Checksum routine for Internet Protocol family headers.
46 50 * This routine is very heavily used in the network
47 51 * code and should be modified for each CPU to be as fast as possible.
48 52 */
49 53
50 -#define mp_len(mp) ((mp)->b_wptr - (mp)->b_rptr)
51 -
52 54 /*
53 55 * Even/Odd checks. Usually it is performed on pointers but may be
54 56 * used on integers as well. uintptr_t is long enough to hold both
55 57 * integer and pointer.
56 58 */
57 -#define is_odd(p) (((uintptr_t)(p) & 0x1) != 0)
58 -#define is_even(p) (!is_odd(p))
59 +#define IS_ODD(p) (((uintptr_t)(p) & 0x1) != 0)
60 +#define IS_EVEN(p) (((uintptr_t)(p) & 0x1) == 0)
59 61
60 -
61 -#ifdef ZC_TEST
62 62 /*
63 - * Disable the TCP s/w cksum.
64 - * XXX - This is just a hack for testing purpose. Don't use it for
65 - * anything else!
66 63 */
67 -int noswcksum = 0;
64 +#define HAS_UIOSUM(mp) ((mp)->b_datap->db_struioflag & STRUIO_IP)
65 +
66 +#ifdef _LITTLE_ENDIAN
67 +#define FRAG(ptr) (*(ptr))
68 +#else
69 +#define FRAG(ptr) (*(ptr) << 8)
68 70 #endif
71 +
69 72 /*
73 + * Give the compiler a hint to help optimize the code layout
74 + */
75 +#define UNLIKELY(exp) __builtin_expect((exp), 0)
76 +
77 +#define FOLD(val) (((val) & 0xFFFF) + ((val) >> 16))
78 +
79 +/*
70 80 * Note: this does not ones-complement the result since it is used
71 - * when computing partial checksums.
72 - * For nonSTRUIO_IP mblks, assumes mp->b_rptr+offset is 16 bit aligned.
73 - * For STRUIO_IP mblks, assumes mp->b_datap->db_struiobase is 16 bit aligned.
74 - *
75 - * Note: for STRUIO_IP special mblks some data may have been previously
76 - * checksumed, this routine will handle additional data prefixed within
77 - * an mblk or b_cont (chained) mblk(s). This routine will also handle
78 - * suffixed b_cont mblk(s) and data suffixed within an mblk.
81 + * when computing partial checksums. It assumes mp->b_rptr + offset is
82 + * 16 bit aligned and a valid offset in mp.
79 83 */
80 84 unsigned int
81 -ip_cksum(mblk_t *mp, int offset, uint_t sum)
85 +ip_cksum(mblk_t *mp, int offset, uint_t initial_sum)
82 86 {
83 - ushort_t *w;
84 - ssize_t mlen;
85 - int pmlen;
86 - mblk_t *pmp;
87 - dblk_t *dp = mp->b_datap;
88 - ushort_t psum = 0;
87 + const uint_t sum_mask[2] = { 0, UINT_MAX };
88 + uint64_t sum = initial_sum;
89 + uint64_t total_len = 0;
90 + uchar_t *w;
91 + size_t mlen = MBLKL(mp);
92 + uint_t msum, mask;
89 93
90 -#ifdef ZC_TEST
91 - if (noswcksum)
92 - return (0xffff);
93 -#endif
94 - ASSERT(dp);
94 + ASSERT3S(offset, >=, 0);
95 95
96 - if (mp->b_cont == NULL) {
97 - /*
98 - * May be fast-path, only one mblk.
99 - */
100 - w = (ushort_t *)(mp->b_rptr + offset);
101 - if (dp->db_struioflag & STRUIO_IP) {
102 - /*
103 - * Checksum any data not already done by
104 - * the caller and add in any partial checksum.
105 - */
106 - if ((offset > dp->db_cksumstart) ||
107 - mp->b_wptr != (uchar_t *)(mp->b_rptr +
108 - dp->db_cksumend)) {
109 - /*
110 - * Mblk data pointers aren't inclusive
111 - * of uio data, so disregard checksum.
112 - *
113 - * not using all of data in dblk make sure
114 - * not use to use the precalculated checksum
115 - * in this case.
116 - */
117 - dp->db_struioflag &= ~STRUIO_IP;
118 - goto norm;
119 - }
120 - ASSERT(mp->b_wptr == (mp->b_rptr + dp->db_cksumend));
121 - psum = *(ushort_t *)dp->db_struioun.data;
122 - if ((mlen = dp->db_cksumstart - offset) < 0)
123 - mlen = 0;
124 - if (is_odd(mlen))
125 - goto slow;
126 - if (mlen && dp->db_cksumstart != dp->db_cksumstuff &&
127 - dp->db_cksumend != dp->db_cksumstuff) {
128 - /*
129 - * There is prefix data to do and some uio
130 - * data has already been checksumed and there
131 - * is more uio data to do, so do the prefix
132 - * data first, then do the remainder of the
133 - * uio data.
134 - */
135 - sum = ip_ocsum(w, mlen >> 1, sum);
136 - w = (ushort_t *)(mp->b_rptr +
137 - dp->db_cksumstuff);
138 - if (is_odd(w)) {
139 - pmp = mp;
140 - goto slow1;
141 - }
142 - mlen = dp->db_cksumend - dp->db_cksumstuff;
143 - } else if (dp->db_cksumend != dp->db_cksumstuff) {
144 - /*
145 - * There may be uio data to do, if there is
146 - * prefix data to do then add in all of the
147 - * uio data (if any) to do, else just do any
148 - * uio data.
149 - */
150 - if (mlen)
151 - mlen += dp->db_cksumend
152 - - dp->db_cksumstuff;
153 - else {
154 - w = (ushort_t *)(mp->b_rptr +
155 - dp->db_cksumstuff);
156 - if (is_odd(w))
157 - goto slow;
158 - mlen = dp->db_cksumend
159 - - dp->db_cksumstuff;
160 - }
161 - } else if (mlen == 0)
162 - return (psum);
96 + VERIFY(!HAS_UIOSUM(mp));
97 + while (UNLIKELY(offset > mlen)) {
98 + ASSERT3P(mp->b_cont, !=, NULL);
99 + mp = mp->b_cont;
100 + VERIFY(!HAS_UIOSUM(mp));
101 + offset -= mlen;
102 + mlen = MBLKL(mp);
103 + }
163 104
164 - if (is_odd(mlen))
165 - goto slow;
166 - sum += psum;
167 - } else {
168 - /*
169 - * Checksum all data not already done by the caller.
170 - */
171 - norm:
172 - mlen = mp->b_wptr - (uchar_t *)w;
173 - if (is_odd(mlen))
174 - goto slow;
105 + /*
106 + * Make sure we start with a folded sum. Since the initial sum
107 + * is 32 bits, folding twice will always produce a sum <= 0xFFFF
108 + */
109 + sum = FOLD(sum);
110 + sum = FOLD(sum);
111 + ASSERT3U(sum, <=, 0xFFFF);
112 +
113 + while (mp != NULL) {
114 + w = mp->b_rptr + offset;
115 + mlen = mp->b_wptr - w;
116 + offset = 0;
117 +
118 + ASSERT3P(w, <=, mp->b_wptr);
119 + VERIFY(!HAS_UIOSUM(mp));
120 +
121 + if (UNLIKELY(mlen == 0)) {
122 + mp = mp->b_cont;
123 + continue;
175 124 }
176 - ASSERT(is_even(w));
177 - ASSERT(is_even(mlen));
178 - return (ip_ocsum(w, mlen >> 1, sum));
179 - }
180 - if (dp->db_struioflag & STRUIO_IP)
181 - psum = *(ushort_t *)dp->db_struioun.data;
182 -slow:
183 - pmp = 0;
184 -slow1:
185 - mlen = 0;
186 - pmlen = 0;
187 - for (; ; ) {
125 +
188 126 /*
189 - * Each trip around loop adds in word(s) from one mbuf segment
190 - * (except for when pmp == mp, then its two partial trips).
127 + * ip_ocsum() currently requires a 16-bit aligned address.
128 + * For unaligned buffers, we first sum the odd byte (and
129 + * fold if necessary) before calling ip_ocsum(). ip_ocsum()
130 + * also takes its length in units of 16-bit words. If
131 + * we have an odd length, we must also manually add it after
132 + * computing the main sum (and again fold if necessary).
133 + *
134 + * Since ip_ocsum() _should_ be a private per-platform
135 + * optimized ip cksum implementation (with ip_cksum() being
136 + * the less-private wrapper around it), a nice future
137 + * optimization could be to modify ip_ocsum() for each
138 + * platform to take a 64-bit sum. This would allow us to
139 + * only have to fold exactly once before we return --
140 + * the amount of data we'd need to checksum to overflow 64
141 + * bits far exceeds the possible size of any mblk chain we
142 + * could ever have.
191 143 */
192 - w = (ushort_t *)(mp->b_rptr + offset);
193 - if (pmp) {
194 - /*
195 - * This is the second trip around for this mblk.
196 - */
197 - pmp = 0;
198 - mlen = 0;
199 - goto douio;
200 - } else if (dp->db_struioflag & STRUIO_IP) {
201 - /*
202 - * Checksum any data not already done by the
203 - * caller and add in any partial checksum.
204 - */
205 - if ((offset > dp->db_cksumstart) ||
206 - mp->b_wptr != (uchar_t *)(mp->b_rptr +
207 - dp->db_cksumend)) {
208 - /*
209 - * Mblk data pointers aren't inclusive
210 - * of uio data, so disregard checksum.
211 - *
212 - * not using all of data in dblk make sure
213 - * not use to use the precalculated checksum
214 - * in this case.
215 - */
216 - dp->db_struioflag &= ~STRUIO_IP;
217 - goto snorm;
218 - }
219 - ASSERT(mp->b_wptr == (mp->b_rptr + dp->db_cksumend));
220 - if ((mlen = dp->db_cksumstart - offset) < 0)
221 - mlen = 0;
222 - if (mlen && dp->db_cksumstart != dp->db_cksumstuff) {
223 - /*
224 - * There is prefix data too do and some
225 - * uio data has already been checksumed,
226 - * so do the prefix data only this trip.
227 - */
228 - pmp = mp;
229 - } else {
230 - /*
231 - * Add in any partial cksum (if any) and
232 - * do the remainder of the uio data.
233 - */
234 - int odd;
235 - douio:
236 - odd = is_odd(dp->db_cksumstuff -
237 - dp->db_cksumstart);
238 - if (pmlen == -1) {
239 - /*
240 - * Previous mlen was odd, so swap
241 - * the partial checksum bytes.
242 - */
243 - sum += ((psum << 8) & 0xffff)
244 - | (psum >> 8);
245 - if (odd)
246 - pmlen = 0;
247 - } else {
248 - sum += psum;
249 - if (odd)
250 - pmlen = -1;
251 - }
252 - if (dp->db_cksumend != dp->db_cksumstuff) {
253 - /*
254 - * If prefix data to do and then all
255 - * the uio data nees to be checksumed,
256 - * else just do any uio data.
257 - */
258 - if (mlen)
259 - mlen += dp->db_cksumend
260 - - dp->db_cksumstuff;
261 - else {
262 - w = (ushort_t *)(mp->b_rptr +
263 - dp->db_cksumstuff);
264 - mlen = dp->db_cksumend -
265 - dp->db_cksumstuff;
266 - }
267 - }
268 - }
269 - } else {
270 - /*
271 - * Checksum all of the mblk data.
272 - */
273 - snorm:
274 - mlen = mp->b_wptr - (uchar_t *)w;
275 - }
144 + if (UNLIKELY(IS_ODD(w))) {
145 + sum += FRAG(w);
146 + w++;
276 147
277 - mp = mp->b_cont;
278 - if (mlen > 0 && pmlen == -1) {
279 - /*
280 - * There is a byte left from the last
281 - * segment; add it into the checksum.
282 - * Don't have to worry about a carry-
283 - * out here because we make sure that
284 - * high part of (32 bit) sum is small
285 - * below.
286 - */
287 -#ifdef _LITTLE_ENDIAN
288 - sum += *(uchar_t *)w << 8;
289 -#else
290 - sum += *(uchar_t *)w;
291 -#endif
292 - w = (ushort_t *)((char *)w + 1);
293 - mlen--;
294 - pmlen = 0;
295 - }
296 - if (mlen > 0) {
297 - if (is_even(w)) {
298 - sum = ip_ocsum(w, mlen>>1, sum);
299 - w += mlen>>1;
300 - /*
301 - * If we had an odd number of bytes,
302 - * then the last byte goes in the high
303 - * part of the sum, and we take the
304 - * first byte to the low part of the sum
305 - * the next time around the loop.
306 - */
307 - if (is_odd(mlen)) {
308 -#ifdef _LITTLE_ENDIAN
309 - sum += *(uchar_t *)w;
310 -#else
311 - sum += *(uchar_t *)w << 8;
312 -#endif
313 - pmlen = -1;
314 - }
315 - } else {
316 - ushort_t swsum;
317 -#ifdef _LITTLE_ENDIAN
318 - sum += *(uchar_t *)w;
319 -#else
320 - sum += *(uchar_t *)w << 8;
321 -#endif
322 - mlen--;
323 - w = (ushort_t *)(1 + (uintptr_t)w);
148 + --mlen;
149 + total_len++;
324 150
325 - /* Do a separate checksum and copy operation */
326 - swsum = ip_ocsum(w, mlen>>1, 0);
327 - sum += ((swsum << 8) & 0xffff) | (swsum >> 8);
328 - w += mlen>>1;
329 - /*
330 - * If we had an even number of bytes,
331 - * then the last byte goes in the low
332 - * part of the sum. Otherwise we had an
333 - * odd number of bytes and we take the first
334 - * byte to the low part of the sum the
335 - * next time around the loop.
336 - */
337 - if (is_odd(mlen)) {
338 -#ifdef _LITTLE_ENDIAN
339 - sum += *(uchar_t *)w << 8;
340 -#else
341 - sum += *(uchar_t *)w;
342 -#endif
343 - }
344 - else
345 - pmlen = -1;
151 + if (UNLIKELY(mlen == 0)) {
152 + mp = mp->b_cont;
153 + continue;
346 154 }
347 155 }
156 +
348 157 /*
349 - * Locate the next block with some data.
350 - * If there is a word split across a boundary we
351 - * will wrap to the top with mlen == -1 and
352 - * then add it in shifted appropriately.
158 + * ip_ocsum() takes the length as the number of half words
159 + * (i.e. uint16_ts). It returns a result that is already
160 + * folded (<= 0xFFFF).
353 161 */
354 - offset = 0;
355 - if (! pmp) {
356 - for (; ; ) {
357 - if (mp == 0) {
358 - goto done;
359 - }
360 - if (mp_len(mp))
361 - break;
362 - mp = mp->b_cont;
363 - }
364 - dp = mp->b_datap;
365 - if (dp->db_struioflag & STRUIO_IP)
366 - psum = *(ushort_t *)dp->db_struioun.data;
367 - } else
368 - mp = pmp;
162 + msum = ip_ocsum((ushort_t *)w, mlen / 2, 0);
163 + ASSERT3U(msum, <=, 0xFFFF);
164 +
165 + /*
166 + * We mask the last byte based on the length of data.
167 + * If the length is odd, we AND with UINT_MAX otherwise
168 + * we AND with 0 (resulting in 0) and add the result to
169 + * the mblk_t sum. This effectively gives us:
170 + *
171 + * if (IS_ODD(mlen))
172 + * msum += FRAG(w + mlen - 1);
173 + * else
174 + * msum += 0;
175 + *
176 + * Without incurring a branch.
177 + */
178 + mask = sum_mask[IS_ODD(mlen)];
179 + msum += FRAG(w + mlen - 1) & mask;
180 +
181 + /*
182 + * If the data we are checksumming has been split
183 + * between two mblk_ts along a non-16 bit boundary, that is
184 + * we have something like:
185 + * mblk_t 1: aa bb cc
186 + * mblk_t 2: dd ee ff
187 + * the result must be the same as if we checksummed a
188 + * single mblk_t with 'aa bb cc dd ee ff'. As can be seen
189 + * from the example, this situation causes the grouping of
190 + * the data in the second mblk_t to be offset by a byte.
191 + * The fix is to byteswap the mblk_t sum before adding it
192 + * to the final sum. Again, we AND the mblk_t sum with a mask
193 + * so that either the non-swapped or byteswapped sum is zeroed
194 + * out and the other one is preserved (depending on the
195 + * total bytes checksummed so far) and added to the sum.
196 + *
197 + * Effectively,
198 + *
199 + * if (IS_ODD(total_len))
200 + * sum += BSWAP_32(msum);
201 + * else
202 + * sum += msum;
203 + */
204 + mask = sum_mask[IS_ODD(total_len)];
205 + sum += BSWAP_32(msum) & mask;
206 + sum += msum & ~mask;
207 +
208 + total_len += mlen;
209 + mp = mp->b_cont;
369 210 }
370 -done:
211 +
371 212 /*
372 - * Add together high and low parts of sum
373 - * and carry to get cksum.
374 - * Have to be careful to not drop the last
375 - * carry here.
213 + * To avoid unnecessary folding, we store the cumulative sum in
214 + * a uint64_t. This means we can always checksum up to 2^56 bytes
215 + * (2^(64-8)) without danger of overflowing. Since 2^56 is well past
216 + * the petabyte range, and is far beyond the amount of data that
217 + * could every be stored in a single mblk_t chain (for the forseeable
218 + * future), this serves more as a sanity check than anything else.
376 219 */
377 - sum = (sum & 0xFFFF) + (sum >> 16);
378 - sum = (sum & 0xFFFF) + (sum >> 16);
220 + VERIFY3U(total_len, <=, (uint64_t)1 << 56);
221 +
222 + /*
223 + * For a 64-bit sum, we have to fold at most 4 times to
224 + * produce a sum <= 0xFFFF.
225 + */
226 + sum = FOLD(sum);
227 + sum = FOLD(sum);
228 + sum = FOLD(sum);
229 + sum = FOLD(sum);
230 +
379 231 TRACE_3(TR_FAC_IP, TR_IP_CKSUM_END,
380 232 "ip_cksum_end:(%S) type %d (%X)", "ip_cksum", 1, sum);
381 - return (sum);
233 + return ((unsigned int)sum);
382 234 }
383 235
384 236 uint32_t
385 237 sctp_cksum(mblk_t *mp, int offset)
386 238 {
387 239 uint32_t crc32;
388 240 uchar_t *p = NULL;
389 241
390 242 crc32 = 0xFFFFFFFF;
391 243 p = mp->b_rptr + offset;
392 244 crc32 = sctp_crc32(crc32, p, mp->b_wptr - p);
393 245 for (mp = mp->b_cont; mp != NULL; mp = mp->b_cont) {
394 246 crc32 = sctp_crc32(crc32, mp->b_rptr, MBLKL(mp));
395 247 }
396 248
397 249 /* Complement the result */
398 250 crc32 = ~crc32;
399 251
400 252 return (crc32);
401 253 }
402 254
403 255 /*
404 256 * Routine to compute Internet checksum (16-bit 1's complement) of a given
405 257 * Multidata packet descriptor. As in the non-Multidata routine, this doesn't
406 258 * 1's complement the result, such that it may be used to compute partial
407 259 * checksums. Since it works on buffer spans rather than mblks, this routine
408 260 * does not handle existing partial checksum value as in the STRUIO_IP special
409 261 * mblk case (supporting this is rather trivial, but is perhaps of no use at
410 262 * the moment unless synchronous streams and delayed checksum calculation are
411 263 * revived.)
412 264 *
413 265 * Note also here that the given Multidata packet descriptor must refer to
414 266 * a header buffer, i.e. it must have a header fragment. In addition, the
415 267 * offset must lie within the boundary of the header fragment. For the
416 268 * outbound tcp (MDT) case, this will not be an issue because the stack
417 269 * ensures that such conditions are met, and that there is no need whatsoever
418 270 * to compute partial checksums on an arbitrary offset that is not part of
419 271 * the header fragment. We may need to revisit this routine to handle all
420 272 * cases of the inbound (MDR) case, especially when we need to perform partial
421 273 * checksum calculation due to padded bytes (non-zeroes) in the frame.
422 274 */
423 275 uint_t
424 276 ip_md_cksum(pdesc_t *pd, int offset, uint_t sum)
425 277 {
426 278 pdescinfo_t *pdi = &pd->pd_pdi;
427 279 uchar_t *reg_start, *reg_end;
428 280 ssize_t mlen, i;
429 281 ushort_t *w;
430 282 boolean_t byteleft = B_FALSE;
431 283
432 284 ASSERT((pdi->flags & PDESC_HAS_REF) != 0);
433 285 ASSERT(pdi->hdr_rptr != NULL && pdi->hdr_wptr != NULL);
434 286 ASSERT(offset <= PDESC_HDRL(pdi));
435 287
436 288 for (i = 0; i < pdi->pld_cnt + 1; i++) {
437 289 if (i == 0) {
438 290 reg_start = pdi->hdr_rptr;
439 291 reg_end = pdi->hdr_wptr;
440 292 } else {
441 293 reg_start = pdi->pld_ary[i - 1].pld_rptr;
442 294 reg_end = pdi->pld_ary[i - 1].pld_wptr;
443 295 offset = 0;
444 296 }
445 297
446 298 w = (ushort_t *)(reg_start + offset);
447 299 mlen = reg_end - (uchar_t *)w;
448 300
449 301 if (mlen > 0 && byteleft) {
450 302 /*
451 303 * There is a byte left from the last
452 304 * segment; add it into the checksum.
453 305 * Don't have to worry about a carry-
454 306 * out here because we make sure that
455 307 * high part of (32 bit) sum is small
456 308 * below.
457 309 */
458 310 #ifdef _LITTLE_ENDIAN
459 311 sum += *(uchar_t *)w << 8;
460 312 #else
↓ open down ↓ |
69 lines elided |
↑ open up ↑ |
461 313 sum += *(uchar_t *)w;
462 314 #endif
463 315 w = (ushort_t *)((char *)w + 1);
464 316 mlen--;
465 317 byteleft = B_FALSE;
466 318 }
467 319
468 320 if (mlen == 0)
469 321 continue;
470 322
471 - if (is_even(w)) {
323 + if (IS_EVEN(w)) {
472 324 sum = ip_ocsum(w, mlen >> 1, sum);
473 325 w += mlen >> 1;
474 326 /*
475 327 * If we had an odd number of bytes,
476 328 * then the last byte goes in the high
477 329 * part of the sum, and we take the
478 330 * first byte to the low part of the sum
479 331 * the next time around the loop.
480 332 */
481 - if (is_odd(mlen)) {
333 + if (IS_ODD(mlen)) {
482 334 #ifdef _LITTLE_ENDIAN
483 335 sum += *(uchar_t *)w;
484 336 #else
485 337 sum += *(uchar_t *)w << 8;
486 338 #endif
487 339 byteleft = B_TRUE;
488 340 }
489 341 } else {
490 342 ushort_t swsum;
491 343 #ifdef _LITTLE_ENDIAN
492 344 sum += *(uchar_t *)w;
493 345 #else
494 346 sum += *(uchar_t *)w << 8;
495 347 #endif
496 348 mlen--;
497 349 w = (ushort_t *)(1 + (uintptr_t)w);
498 350
499 351 /* Do a separate checksum and copy operation */
500 352 swsum = ip_ocsum(w, mlen >> 1, 0);
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
501 353 sum += ((swsum << 8) & 0xffff) | (swsum >> 8);
502 354 w += mlen >> 1;
503 355 /*
504 356 * If we had an even number of bytes,
505 357 * then the last byte goes in the low
506 358 * part of the sum. Otherwise we had an
507 359 * odd number of bytes and we take the first
508 360 * byte to the low part of the sum the
509 361 * next time around the loop.
510 362 */
511 - if (is_odd(mlen)) {
363 + if (IS_ODD(mlen)) {
512 364 #ifdef _LITTLE_ENDIAN
513 365 sum += *(uchar_t *)w << 8;
514 366 #else
515 367 sum += *(uchar_t *)w;
516 368 #endif
517 369 } else {
518 370 byteleft = B_TRUE;
519 371 }
520 372 }
521 373 }
522 374
523 375 /*
524 376 * Add together high and low parts of sum and carry to get cksum.
525 377 * Have to be careful to not drop the last carry here.
526 378 */
527 379 sum = (sum & 0xffff) + (sum >> 16);
528 380 sum = (sum & 0xffff) + (sum >> 16);
529 381
530 382 return (sum);
531 383 }
532 384
533 385 /* Return the IP checksum for the IP header at "iph". */
534 386 uint16_t
535 387 ip_csum_hdr(ipha_t *ipha)
536 388 {
537 389 uint16_t *uph;
538 390 uint32_t sum;
539 391 int opt_len;
540 392
541 393 opt_len = (ipha->ipha_version_and_hdr_length & 0xF) -
542 394 IP_SIMPLE_HDR_LENGTH_IN_WORDS;
543 395 uph = (uint16_t *)ipha;
544 396 sum = uph[0] + uph[1] + uph[2] + uph[3] + uph[4] +
545 397 uph[5] + uph[6] + uph[7] + uph[8] + uph[9];
546 398 if (opt_len > 0) {
547 399 do {
548 400 sum += uph[10];
549 401 sum += uph[11];
550 402 uph += 2;
551 403 } while (--opt_len);
552 404 }
553 405 sum = (sum & 0xFFFF) + (sum >> 16);
554 406 sum = ~(sum + (sum >> 16)) & 0xFFFF;
555 407 if (sum == 0xffff)
556 408 sum = 0;
557 409 return ((uint16_t)sum);
558 410 }
↓ open down ↓ |
37 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX