From 4787d6d7df196ff7463517423dfbdfd41bdceffe Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 8 Mar 2010 13:33:13 -0800 Subject: csum: Fix rare error cases in checksum computation. Occasionally the checksum test on "make check" would fail. This commit fixes the problem, which was that the partial checksum may need more than one reduction step to obtain a final checksum. Now running checksum tests in a continuous loop yields no failures. --- lib/csum.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/csum.c') diff --git a/lib/csum.c b/lib/csum.c index 6f044473e..922f68625 100644 --- a/lib/csum.c +++ b/lib/csum.c @@ -76,7 +76,10 @@ csum_continue(uint32_t partial, const void *data_, size_t n) uint16_t csum_finish(uint32_t partial) { - return ~((partial & 0xffff) + (partial >> 16)); + while (partial >> 16) { + partial = (partial & 0xffff) + (partial >> 16); + } + return ~partial; } /* Returns the new checksum for a packet in which the checksum field previously @@ -93,8 +96,7 @@ recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16) uint16_t m_complement = ~old_u16; uint16_t m_prime = new_u16; uint32_t sum = hc_complement + m_complement + m_prime; - uint16_t hc_prime_complement = sum + (sum >> 16); - return ~hc_prime_complement; + return csum_finish(sum); } /* Returns the new checksum for a packet in which the checksum field previously -- cgit v1.2.1