diff options
author | Ben Pfaff <blp@nicira.com> | 2010-03-08 13:33:13 -0800 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2010-03-08 13:33:13 -0800 |
commit | 4787d6d7df196ff7463517423dfbdfd41bdceffe (patch) | |
tree | 606adb1b02b7acdd60c0616dbfb10654ae6513b9 /lib/csum.c | |
parent | ee402caec46c116a862b716cb4851ff5be371c9f (diff) | |
download | openvswitch-4787d6d7df196ff7463517423dfbdfd41bdceffe.tar.gz |
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.
Diffstat (limited to 'lib/csum.c')
-rw-r--r-- | lib/csum.c | 8 |
1 files changed, 5 insertions, 3 deletions
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 |