aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-10-30 06:50:49 -0400
committerDavid S. Miller <davem@davemloft.net>2013-11-03 23:04:56 -0500
commit6e95fcaa42e5078ac265964deebed597f9eae07a (patch)
tree36e2b8bc15a615772015ef62c0bdda8047711321 /lib
parentd921e049a02c7bd6ddf8f5e72303ca336009556d (diff)
lib: crc32: add functionality to combine two crc32{, c}s in GF(2)
This patch adds a combinator to merge two or more crc32{,c}s into a new one. This is useful for checksum computations of fragmented skbs that use crc32/crc32c as checksums. The arithmetics for combining both in the GF(2) was taken and slightly modified from zlib. Only passing two crcs is insufficient as two crcs and the length of the second piece is needed for merging. The code is made generic, so that only polynomials need to be passed for crc32_le resp. crc32c_le. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Cc: linux-kernel@vger.kernel.org Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/crc32.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/crc32.c b/lib/crc32.c
index 429d61ce6aa0..595205cddc30 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -49,6 +49,30 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@dell.com>");
49MODULE_DESCRIPTION("Various CRC32 calculations"); 49MODULE_DESCRIPTION("Various CRC32 calculations");
50MODULE_LICENSE("GPL"); 50MODULE_LICENSE("GPL");
51 51
52#define GF2_DIM 32
53
54static u32 gf2_matrix_times(u32 *mat, u32 vec)
55{
56 u32 sum = 0;
57
58 while (vec) {
59 if (vec & 1)
60 sum ^= *mat;
61 vec >>= 1;
62 mat++;
63 }
64
65 return sum;
66}
67
68static void gf2_matrix_square(u32 *square, u32 *mat)
69{
70 int i;
71
72 for (i = 0; i < GF2_DIM; i++)
73 square[i] = gf2_matrix_times(mat, mat[i]);
74}
75
52#if CRC_LE_BITS > 8 || CRC_BE_BITS > 8 76#if CRC_LE_BITS > 8 || CRC_BE_BITS > 8
53 77
54/* implements slicing-by-4 or slicing-by-8 algorithm */ 78/* implements slicing-by-4 or slicing-by-8 algorithm */
@@ -130,6 +154,52 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256])
130} 154}
131#endif 155#endif
132 156
157/* For conditions of distribution and use, see copyright notice in zlib.h */
158static u32 crc32_generic_combine(u32 crc1, u32 crc2, size_t len2,
159 u32 polynomial)
160{
161 u32 even[GF2_DIM]; /* Even-power-of-two zeros operator */
162 u32 odd[GF2_DIM]; /* Odd-power-of-two zeros operator */
163 u32 row;
164 int i;
165
166 if (len2 <= 0)
167 return crc1;
168
169 /* Put operator for one zero bit in odd */
170 odd[0] = polynomial;
171 row = 1;
172 for (i = 1; i < GF2_DIM; i++) {
173 odd[i] = row;
174 row <<= 1;
175 }
176
177 gf2_matrix_square(even, odd); /* Put operator for two zero bits in even */
178 gf2_matrix_square(odd, even); /* Put operator for four zero bits in odd */
179
180 /* Apply len2 zeros to crc1 (first square will put the operator for one
181 * zero byte, eight zero bits, in even).
182 */
183 do {
184 /* Apply zeros operator for this bit of len2 */
185 gf2_matrix_square(even, odd);
186 if (len2 & 1)
187 crc1 = gf2_matrix_times(even, crc1);
188 len2 >>= 1;
189 /* If no more bits set, then done */
190 if (len2 == 0)
191 break;
192 /* Another iteration of the loop with odd and even swapped */
193 gf2_matrix_square(odd, even);
194 if (len2 & 1)
195 crc1 = gf2_matrix_times(odd, crc1);
196 len2 >>= 1;
197 } while (len2 != 0);
198
199 crc1 ^= crc2;
200 return crc1;
201}
202
133/** 203/**
134 * crc32_le_generic() - Calculate bitwise little-endian Ethernet AUTODIN II 204 * crc32_le_generic() - Calculate bitwise little-endian Ethernet AUTODIN II
135 * CRC32/CRC32C 205 * CRC32/CRC32C
@@ -200,8 +270,19 @@ u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len)
200 (const u32 (*)[256])crc32ctable_le, CRC32C_POLY_LE); 270 (const u32 (*)[256])crc32ctable_le, CRC32C_POLY_LE);
201} 271}
202#endif 272#endif
273u32 __pure crc32_le_combine(u32 crc1, u32 crc2, size_t len2)
274{
275 return crc32_generic_combine(crc1, crc2, len2, CRCPOLY_LE);
276}
277
278u32 __pure __crc32c_le_combine(u32 crc1, u32 crc2, size_t len2)
279{
280 return crc32_generic_combine(crc1, crc2, len2, CRC32C_POLY_LE);
281}
203EXPORT_SYMBOL(crc32_le); 282EXPORT_SYMBOL(crc32_le);
283EXPORT_SYMBOL(crc32_le_combine);
204EXPORT_SYMBOL(__crc32c_le); 284EXPORT_SYMBOL(__crc32c_le);
285EXPORT_SYMBOL(__crc32c_le_combine);
205 286
206/** 287/**
207 * crc32_be_generic() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32 288 * crc32_be_generic() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32