1use bytes::Bytes;
2use crc::{Crc, Table, CRC_32_ISCSI};
3
4pub(crate) const PADDING_MULTIPLE: usize = 4;
5
6pub(crate) fn get_padding_size(len: usize) -> usize {
7 (PADDING_MULTIPLE - (len % PADDING_MULTIPLE)) % PADDING_MULTIPLE
8}
9
10pub(crate) static FOUR_ZEROES: Bytes = Bytes::from_static(&[0, 0, 0, 0]);
13
14pub(crate) const ISCSI_CRC: Crc<u32, Table<16>> = Crc::<u32, Table<16>>::new(&CRC_32_ISCSI);
15
16pub(crate) fn generate_packet_checksum(raw: &Bytes) -> u32 {
18 let mut digest = ISCSI_CRC.digest();
19 digest.update(&raw[0..8]);
20 digest.update(&FOUR_ZEROES[..]);
21 digest.update(&raw[12..]);
22 digest.finalize()
23}
24
25#[inline]
27pub(crate) fn sna32lt(i1: u32, i2: u32) -> bool {
28 (i1 < i2 && i2 - i1 < 1 << 31) || (i1 > i2 && i1 - i2 > 1 << 31)
29}
30
31#[inline]
32pub(crate) fn sna32lte(i1: u32, i2: u32) -> bool {
33 i1 == i2 || sna32lt(i1, i2)
34}
35
36#[inline]
37pub(crate) fn sna32gt(i1: u32, i2: u32) -> bool {
38 (i1 < i2 && (i2 - i1) >= 1 << 31) || (i1 > i2 && (i1 - i2) <= 1 << 31)
39}
40
41#[inline]
42pub(crate) fn sna32gte(i1: u32, i2: u32) -> bool {
43 i1 == i2 || sna32gt(i1, i2)
44}
45
46#[inline]
47pub(crate) fn sna32eq(i1: u32, i2: u32) -> bool {
48 i1 == i2
49}
50
51#[inline]
52pub(crate) fn sna16lt(i1: u16, i2: u16) -> bool {
53 (i1 < i2 && (i2 - i1) < 1 << 15) || (i1 > i2 && (i1 - i2) > 1 << 15)
54}
55
56#[inline]
57pub(crate) fn sna16lte(i1: u16, i2: u16) -> bool {
58 i1 == i2 || sna16lt(i1, i2)
59}
60
61#[inline]
62pub(crate) fn sna16gt(i1: u16, i2: u16) -> bool {
63 (i1 < i2 && (i2 - i1) >= 1 << 15) || (i1 > i2 && (i1 - i2) <= 1 << 15)
64}
65
66#[inline]
67pub(crate) fn sna16gte(i1: u16, i2: u16) -> bool {
68 i1 == i2 || sna16gt(i1, i2)
69}
70
71#[inline]
72pub(crate) fn sna16eq(i1: u16, i2: u16) -> bool {
73 i1 == i2
74}
75
76#[cfg(test)]
77mod test {
78 use super::*;
79 use crate::error::Result;
80
81 const DIV: isize = 16;
82
83 #[test]
84 fn test_serial_number_arithmetic32bit() -> Result<()> {
85 const SERIAL_BITS: u32 = 32;
86 const INTERVAL: u32 = ((1u64 << (SERIAL_BITS as u64)) / (DIV as u64)) as u32;
87 const MAX_FORWARD_DISTANCE: u32 = 1 << ((SERIAL_BITS - 1) - 1);
88 const MAX_BACKWARD_DISTANCE: u32 = 1 << (SERIAL_BITS - 1);
89
90 for i in 0..DIV as u32 {
91 let s1 = i * INTERVAL;
92 let s2f = s1.checked_add(MAX_FORWARD_DISTANCE);
93 let s2b = s1.checked_add(MAX_BACKWARD_DISTANCE);
94
95 if let (Some(s2f), Some(s2b)) = (s2f, s2b) {
96 assert!(sna32lt(s1, s2f), "s1 < s2 should be true: s1={s1} s2={s2f}");
97 assert!(
98 !sna32lt(s1, s2b),
99 "s1 < s2 should be false: s1={s1} s2={s2b}"
100 );
101
102 assert!(
103 !sna32gt(s1, s2f),
104 "s1 > s2 should be false: s1={s1} s2={s2f}"
105 );
106 assert!(sna32gt(s1, s2b), "s1 > s2 should be true: s1={s1} s2={s2b}");
107
108 assert!(
109 sna32lte(s1, s2f),
110 "s1 <= s2 should be true: s1={s1} s2={s2f}"
111 );
112 assert!(
113 !sna32lte(s1, s2b),
114 "s1 <= s2 should be false: s1={s1} s2={s2b}"
115 );
116
117 assert!(
118 !sna32gte(s1, s2f),
119 "s1 >= s2 should be fales: s1={s1} s2={s2f}"
120 );
121 assert!(
122 sna32gte(s1, s2b),
123 "s1 >= s2 should be true: s1={s1} s2={s2b}"
124 );
125
126 assert!(
127 sna32eq(s2b, s2b),
128 "s2 == s2 should be true: s2={s2b} s2={s2b}"
129 );
130 assert!(
131 sna32lte(s2b, s2b),
132 "s2 == s2 should be true: s2={s2b} s2={s2b}"
133 );
134 assert!(
135 sna32gte(s2b, s2b),
136 "s2 == s2 should be true: s2={s2b} s2={s2b}"
137 );
138 }
139
140 if let Some(s1add1) = s1.checked_add(1) {
141 assert!(
142 !sna32eq(s1, s1add1),
143 "s1 == s1+1 should be false: s1={s1} s1+1={s1add1}"
144 );
145 }
146
147 if let Some(s1sub1) = s1.checked_sub(1) {
148 assert!(
149 !sna32eq(s1, s1sub1),
150 "s1 == s1-1 should be false: s1={s1} s1-1={s1sub1}"
151 );
152 }
153
154 assert!(sna32eq(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
155 assert!(sna32lte(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
156
157 assert!(sna32gte(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
158 }
159
160 Ok(())
161 }
162
163 #[test]
164 fn test_serial_number_arithmetic16bit() -> Result<()> {
165 const SERIAL_BITS: u16 = 16;
166 const INTERVAL: u16 = ((1u64 << (SERIAL_BITS as u64)) / (DIV as u64)) as u16;
167 const MAX_FORWARD_DISTANCE: u16 = 1 << ((SERIAL_BITS - 1) - 1);
168 const MAX_BACKWARD_DISTANCE: u16 = 1 << (SERIAL_BITS - 1);
169
170 for i in 0..DIV as u16 {
171 let s1 = i * INTERVAL;
172 let s2f = s1.checked_add(MAX_FORWARD_DISTANCE);
173 let s2b = s1.checked_add(MAX_BACKWARD_DISTANCE);
174
175 if let (Some(s2f), Some(s2b)) = (s2f, s2b) {
176 assert!(sna16lt(s1, s2f), "s1 < s2 should be true: s1={s1} s2={s2f}");
177 assert!(
178 !sna16lt(s1, s2b),
179 "s1 < s2 should be false: s1={s1} s2={s2b}"
180 );
181
182 assert!(
183 !sna16gt(s1, s2f),
184 "s1 > s2 should be fales: s1={s1} s2={s2f}"
185 );
186 assert!(sna16gt(s1, s2b), "s1 > s2 should be true: s1={s1} s2={s2b}");
187
188 assert!(
189 sna16lte(s1, s2f),
190 "s1 <= s2 should be true: s1={s1} s2={s2f}"
191 );
192 assert!(
193 !sna16lte(s1, s2b),
194 "s1 <= s2 should be false: s1={s1} s2={s2b}"
195 );
196
197 assert!(
198 !sna16gte(s1, s2f),
199 "s1 >= s2 should be fales: s1={s1} s2={s2f}"
200 );
201 assert!(
202 sna16gte(s1, s2b),
203 "s1 >= s2 should be true: s1={s1} s2={s2b}"
204 );
205
206 assert!(
207 sna16eq(s2b, s2b),
208 "s2 == s2 should be true: s2={s2b} s2={s2b}"
209 );
210 assert!(
211 sna16lte(s2b, s2b),
212 "s2 == s2 should be true: s2={s2b} s2={s2b}"
213 );
214 assert!(
215 sna16gte(s2b, s2b),
216 "s2 == s2 should be true: s2={s2b} s2={s2b}"
217 );
218 }
219
220 assert!(sna16eq(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
221
222 if let Some(s1add1) = s1.checked_add(1) {
223 assert!(
224 !sna16eq(s1, s1add1),
225 "s1 == s1+1 should be false: s1={s1} s1+1={s1add1}"
226 );
227 }
228 if let Some(s1sub1) = s1.checked_sub(1) {
229 assert!(
230 !sna16eq(s1, s1sub1),
231 "s1 == s1-1 should be false: s1={s1} s1-1={s1sub1}"
232 );
233 }
234
235 assert!(sna16lte(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
236 assert!(sna16gte(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
237 }
238
239 Ok(())
240 }
241}