]>
git.ipfire.org Git - thirdparty/bird.git/blob - lib/fletcher16.h
2 * BIRD Library -- Fletcher-16 checksum
4 * (c) 2015 Ondrej Zajicek <santiago@crfreenet.org>
5 * (c) 2015 CZ.NIC z.s.p.o.
7 * Can be freely distributed and used under the terms of the GNU GPL.
11 * DOC: Fletcher-16 checksum
13 * Fletcher-16 checksum is a position-dependent checksum algorithm used for
14 * error-detection e.g. in OSPF LSAs.
16 * To generate Fletcher-16 checksum, zero the checksum field in data, initialize
17 * the context by fletcher16_init(), process the data by fletcher16_update(),
18 * compute the checksum value by fletcher16_final() and store it to the checksum
19 * field in data by put_u16() (or other means involving htons() conversion).
21 * To verify Fletcher-16 checksum, initialize the context by fletcher16_init(),
22 * process the data by fletcher16_update(), compute a passing checksum by
23 * fletcher16_compute() and check if it is zero.
26 #ifndef _BIRD_FLETCHER16_H_
27 #define _BIRD_FLETCHER16_H_
29 #include "nest/bird.h"
32 struct fletcher16_context
39 * fletcher16_init - initialize Fletcher-16 context
43 fletcher16_init(struct fletcher16_context
*ctx
)
45 ctx
->c0
= ctx
->c1
= 0;
49 * fletcher16_update - process data to Fletcher-16 context
54 * fletcher16_update() reads data from the buffer @buf and updates passing sums
55 * in the context @ctx. It may be used multiple times for multiple blocks of
59 fletcher16_update(struct fletcher16_context
*ctx
, const u8
* buf
, int len
)
62 * The Fletcher-16 sum is essentially a sequence of
63 * ctx->c1 += ctx->c0 += *buf++, modulo 255.
65 * In the inner loop, we eliminate modulo operation and we do some loop
66 * unrolling. MODX is the maximal number of steps that can be done without
67 * modulo before overflow, see RFC 1008 for details. We use a bit smaller
68 * value to cover for initial steps due to loop unrolling.
78 for (i
= 0; i
< blen
; i
++)
79 ctx
->c1
+= ctx
->c0
+= *buf
++;
82 blen
= MIN(len
, MODX
);
85 for (i
= 0; i
< blen
; i
+= 4)
87 ctx
->c1
+= ctx
->c0
+= *buf
++;
88 ctx
->c1
+= ctx
->c0
+= *buf
++;
89 ctx
->c1
+= ctx
->c0
+= *buf
++;
90 ctx
->c1
+= ctx
->c0
+= *buf
++;
101 * fletcher16_update_n32 - process data to Fletcher-16 context, with endianity adjustment
106 * fletcher16_update_n32() works like fletcher16_update(), except it applies
107 * 32-bit host/network endianity swap to the data before they are processed.
108 * I.e., it assumes that the data is a sequence of u32 that must be converted by
109 * ntohl() or htonl() before processing. The @buf need not to be aligned, but
110 * its length (@len) must be multiple of 4. Note that on big endian systems the
111 * host endianity is the same as the network endianity, therefore there is no
115 fletcher16_update_n32(struct fletcher16_context
*ctx
, const u8
* buf
, int len
)
117 /* See fletcher16_update() for details */
122 blen
= MIN(len
, MODX
);
125 for (i
= 0; i
< blen
; i
+= 4)
127 #ifdef CPU_BIG_ENDIAN
128 ctx
->c1
+= ctx
->c0
+= *buf
++;
129 ctx
->c1
+= ctx
->c0
+= *buf
++;
130 ctx
->c1
+= ctx
->c0
+= *buf
++;
131 ctx
->c1
+= ctx
->c0
+= *buf
++;
133 ctx
->c1
+= ctx
->c0
+= buf
[3];
134 ctx
->c1
+= ctx
->c0
+= buf
[2];
135 ctx
->c1
+= ctx
->c0
+= buf
[1];
136 ctx
->c1
+= ctx
->c0
+= buf
[0];
148 * fletcher16_final - compute final Fletcher-16 checksum value
150 * @len: total data length
151 * @pos: offset in data where the checksum will be stored
153 * fletcher16_final() computes the final checksum value and returns it.
154 * The caller is responsible for storing it in the appropriate position.
155 * The checksum value depends on @len and @pos, but only their difference
156 * (i.e. the offset from the end) is significant.
158 * The checksum value is represented as u16, although it is defined as two
159 * consecutive bytes. We treat them as one u16 in big endian / network order.
160 * I.e., the returned value is in the form that would be returned by get_u16()
161 * from the checksum field in the data buffer, therefore the caller should use
162 * put_u16() or an explicit host-to-network conversion when storing it to the
163 * checksum field in the data buffer.
165 * Note that the returned checksum value is always nonzero.
168 fletcher16_final(struct fletcher16_context
*ctx
, int len
, int pos
)
170 int x
= ((len
- pos
- 1) * ctx
->c0
- ctx
->c1
) % 255;
174 int y
= 510 - ctx
->c0
- x
;
183 * fletcher16_compute - compute Fletcher-16 sum for verification
186 * fletcher16_compute() returns a passing Fletcher-16 sum for processed data.
187 * If the data contains the proper Fletcher-16 checksum value, the returned
191 fletcher16_compute(struct fletcher16_context
*ctx
)
193 return (ctx
->c0
<< 8) | ctx
->c1
;