From: Ben Pfaff Date: Mon, 8 Mar 2010 21:33:13 +0000 (-0800) Subject: csum: Fix rare error cases in checksum computation. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4787d6d7df196ff7463517423dfbdfd41bdceffe;p=openvswitch 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. --- diff --git a/lib/csum.c b/lib/csum.c index 6f044473..922f6862 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