/* New version of ip_checksum, notice this version does not change it into * network order. It is useful to keep it in host order for further processing */ uint16_t __ip_checksum(void *dataptr, unsigned int len, uint32_t sum) { uint8_t *pb = (uint8_t *)dataptr; uint16_t *ps, t = 0; int odd = ((uintptr_t)pb & 1); /* Get aligned to uint16_t */ // this means pb started on some weird address.. // but in our world this should never happen.. since the payload should always be aligned.. // right.. if (odd && len > 0) { // change the second half of t to what pb is // and advance pb ((uint8_t *)&t)[1] = *pb++; len--; } /* Add the bulk of the data */ ps = (uint16_t *)(void *)pb; while (len > 1) { sum += *ps++; len -= 2; } /* Consume left-over byte, if any */ if (len > 0) { ((uint8_t *)&t)[0] = *(uint8_t *)ps; } /* Add end bytes */ sum += t; /* Fold 32-bit sum to 16 bits calling this twice is propably faster than if statements... */ sum = FOLD_U32T(sum); sum = FOLD_U32T(sum); /* Swap if alignment was odd */ if (odd) { sum = byte_swap16(sum); } return (uint16_t)sum; }
/** Add a checksum of newly added data to the segment */ static void ICACHE_FLASH_ATTR tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, u8_t *seg_chksum_swapped) { u32_t helper; /* add chksum to old chksum and fold to u16_t */ helper = chksum + *seg_chksum; chksum = FOLD_U32T(helper); if ((len & 1) != 0) { *seg_chksum_swapped = 1 - *seg_chksum_swapped; chksum = SWAP_BYTES_IN_WORD(chksum); } *seg_chksum = chksum; }
/* ip addresses need to be network order, protolen and proto are HO */ uint16_t inet_chksum_pseudo(struct pbuf *p, uint32_t src, uint32_t dest, uint8_t proto, uint16_t proto_len) { uint32_t acc; uint32_t addr; struct pbuf *q; uint8_t swapped; acc = 0; swapped = 0; /* iterate through all pbuf in chain */ for(q = p; q != NULL; q = STAILQ_NEXT(q, next)) { acc += __ip_checksum(q->payload, q->len, 0); acc = FOLD_U32T(acc); if (q->len % 2 != 0) { swapped = 1 - swapped; acc = byte_swap16(acc); } } if (swapped) { acc = byte_swap16(acc); } addr = (src); acc += (addr & 0xffffUL); acc += ((addr >> 16) & 0xffffUL); addr = (dest); acc += (addr & 0xffffUL); acc += ((addr >> 16) & 0xffffUL); acc += (uint32_t)htons((uint16_t)proto); acc += (uint32_t)htons(proto_len); /* Fold 32-bit sum to 16 bits calling this twice is propably faster than if statements... */ acc = FOLD_U32T(acc); acc = FOLD_U32T(acc); return (uint16_t)~(acc & 0xffffUL); }