1 use bytes::Bytes; 2 use crc::{Crc, CRC_32_ISCSI}; 3 4 const PADDING_MULTIPLE: usize = 4; 5 6 pub(crate) fn get_padding_size(len: usize) -> usize { 7 (PADDING_MULTIPLE - (len % PADDING_MULTIPLE)) % PADDING_MULTIPLE 8 } 9 10 /// Allocate and zero this data once. 11 /// We need to use it for the checksum and don't want to allocate/clear each time. 12 pub(crate) static FOUR_ZEROES: Bytes = Bytes::from_static(&[0, 0, 0, 0]); 13 14 /// Fastest way to do a crc32 without allocating. 15 pub(crate) fn generate_packet_checksum(raw: &Bytes) -> u32 { 16 let hasher = Crc::<u32>::new(&CRC_32_ISCSI); 17 let mut digest = hasher.digest(); 18 digest.update(&raw[0..8]); 19 digest.update(&FOUR_ZEROES[..]); 20 digest.update(&raw[12..]); 21 digest.finalize() 22 } 23 24 /// Serial Number Arithmetic (RFC 1982) 25 #[inline] 26 pub(crate) fn sna32lt(i1: u32, i2: u32) -> bool { 27 (i1 < i2 && i2 - i1 < 1 << 31) || (i1 > i2 && i1 - i2 > 1 << 31) 28 } 29 30 #[inline] 31 pub(crate) fn sna32lte(i1: u32, i2: u32) -> bool { 32 i1 == i2 || sna32lt(i1, i2) 33 } 34 35 #[inline] 36 pub(crate) fn sna32gt(i1: u32, i2: u32) -> bool { 37 (i1 < i2 && (i2 - i1) >= 1 << 31) || (i1 > i2 && (i1 - i2) <= 1 << 31) 38 } 39 40 #[inline] 41 pub(crate) fn sna32gte(i1: u32, i2: u32) -> bool { 42 i1 == i2 || sna32gt(i1, i2) 43 } 44 45 #[inline] 46 pub(crate) fn sna32eq(i1: u32, i2: u32) -> bool { 47 i1 == i2 48 } 49 50 #[inline] 51 pub(crate) fn sna16lt(i1: u16, i2: u16) -> bool { 52 (i1 < i2 && (i2 - i1) < 1 << 15) || (i1 > i2 && (i1 - i2) > 1 << 15) 53 } 54 55 #[inline] 56 pub(crate) fn sna16lte(i1: u16, i2: u16) -> bool { 57 i1 == i2 || sna16lt(i1, i2) 58 } 59 60 #[inline] 61 pub(crate) fn sna16gt(i1: u16, i2: u16) -> bool { 62 (i1 < i2 && (i2 - i1) >= 1 << 15) || (i1 > i2 && (i1 - i2) <= 1 << 15) 63 } 64 65 #[inline] 66 pub(crate) fn sna16gte(i1: u16, i2: u16) -> bool { 67 i1 == i2 || sna16gt(i1, i2) 68 } 69 70 #[inline] 71 pub(crate) fn sna16eq(i1: u16, i2: u16) -> bool { 72 i1 == i2 73 } 74 75 #[cfg(test)] 76 mod test { 77 use crate::error::Result; 78 79 use super::*; 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!( 97 sna32lt(s1, s2f), 98 "s1 < s2 should be true: s1={} s2={}", 99 s1, 100 s2f 101 ); 102 assert!( 103 !sna32lt(s1, s2b), 104 "s1 < s2 should be false: s1={} s2={}", 105 s1, 106 s2b 107 ); 108 109 assert!( 110 !sna32gt(s1, s2f), 111 "s1 > s2 should be false: s1={} s2={}", 112 s1, 113 s2f 114 ); 115 assert!( 116 sna32gt(s1, s2b), 117 "s1 > s2 should be true: s1={} s2={}", 118 s1, 119 s2b 120 ); 121 122 assert!( 123 sna32lte(s1, s2f), 124 "s1 <= s2 should be true: s1={} s2={}", 125 s1, 126 s2f 127 ); 128 assert!( 129 !sna32lte(s1, s2b), 130 "s1 <= s2 should be false: s1={} s2={}", 131 s1, 132 s2b 133 ); 134 135 assert!( 136 !sna32gte(s1, s2f), 137 "s1 >= s2 should be fales: s1={} s2={}", 138 s1, 139 s2f 140 ); 141 assert!( 142 sna32gte(s1, s2b), 143 "s1 >= s2 should be true: s1={} s2={}", 144 s1, 145 s2b 146 ); 147 148 assert!( 149 sna32eq(s2b, s2b), 150 "s2 == s2 should be true: s2={} s2={}", 151 s2b, 152 s2b 153 ); 154 assert!( 155 sna32lte(s2b, s2b), 156 "s2 == s2 should be true: s2={} s2={}", 157 s2b, 158 s2b 159 ); 160 assert!( 161 sna32gte(s2b, s2b), 162 "s2 == s2 should be true: s2={} s2={}", 163 s2b, 164 s2b 165 ); 166 } 167 168 if let Some(s1add1) = s1.checked_add(1) { 169 assert!( 170 !sna32eq(s1, s1add1), 171 "s1 == s1+1 should be false: s1={} s1+1={}", 172 s1, 173 s1add1 174 ); 175 } 176 177 if let Some(s1sub1) = s1.checked_sub(1) { 178 assert!( 179 !sna32eq(s1, s1sub1), 180 "s1 == s1-1 hould be false: s1={} s1-1={}", 181 s1, 182 s1sub1 183 ); 184 } 185 186 assert!( 187 sna32eq(s1, s1), 188 "s1 == s1 should be true: s1={} s2={}", 189 s1, 190 s1 191 ); 192 assert!( 193 sna32lte(s1, s1), 194 "s1 == s1 should be true: s1={} s2={}", 195 s1, 196 s1 197 ); 198 199 assert!( 200 sna32gte(s1, s1), 201 "s1 == s1 should be true: s1={} s2={}", 202 s1, 203 s1 204 ); 205 } 206 207 Ok(()) 208 } 209 210 #[test] 211 fn test_serial_number_arithmetic16bit() -> Result<()> { 212 const SERIAL_BITS: u16 = 16; 213 const INTERVAL: u16 = ((1u64 << (SERIAL_BITS as u64)) / (DIV as u64)) as u16; 214 const MAX_FORWARD_DISTANCE: u16 = 1 << ((SERIAL_BITS - 1) - 1); 215 const MAX_BACKWARD_DISTANCE: u16 = 1 << (SERIAL_BITS - 1); 216 217 for i in 0..DIV as u16 { 218 let s1 = i * INTERVAL; 219 let s2f = s1.checked_add(MAX_FORWARD_DISTANCE); 220 let s2b = s1.checked_add(MAX_BACKWARD_DISTANCE); 221 222 if let (Some(s2f), Some(s2b)) = (s2f, s2b) { 223 assert!( 224 sna16lt(s1, s2f), 225 "s1 < s2 should be true: s1={} s2={}", 226 s1, 227 s2f 228 ); 229 assert!( 230 !sna16lt(s1, s2b), 231 "s1 < s2 should be false: s1={} s2={}", 232 s1, 233 s2b 234 ); 235 236 assert!( 237 !sna16gt(s1, s2f), 238 "s1 > s2 should be fales: s1={} s2={}", 239 s1, 240 s2f 241 ); 242 assert!( 243 sna16gt(s1, s2b), 244 "s1 > s2 should be true: s1={} s2={}", 245 s1, 246 s2b 247 ); 248 249 assert!( 250 sna16lte(s1, s2f), 251 "s1 <= s2 should be true: s1={} s2={}", 252 s1, 253 s2f 254 ); 255 assert!( 256 !sna16lte(s1, s2b), 257 "s1 <= s2 should be false: s1={} s2={}", 258 s1, 259 s2b 260 ); 261 262 assert!( 263 !sna16gte(s1, s2f), 264 "s1 >= s2 should be fales: s1={} s2={}", 265 s1, 266 s2f 267 ); 268 assert!( 269 sna16gte(s1, s2b), 270 "s1 >= s2 should be true: s1={} s2={}", 271 s1, 272 s2b 273 ); 274 275 assert!( 276 sna16eq(s2b, s2b), 277 "s2 == s2 should be true: s2={} s2={}", 278 s2b, 279 s2b 280 ); 281 assert!( 282 sna16lte(s2b, s2b), 283 "s2 == s2 should be true: s2={} s2={}", 284 s2b, 285 s2b 286 ); 287 assert!( 288 sna16gte(s2b, s2b), 289 "s2 == s2 should be true: s2={} s2={}", 290 s2b, 291 s2b 292 ); 293 } 294 295 assert!( 296 sna16eq(s1, s1), 297 "s1 == s1 should be true: s1={} s2={}", 298 s1, 299 s1 300 ); 301 302 if let Some(s1add1) = s1.checked_add(1) { 303 assert!( 304 !sna16eq(s1, s1add1), 305 "s1 == s1+1 should be false: s1={} s1+1={}", 306 s1, 307 s1add1 308 ); 309 } 310 if let Some(s1sub1) = s1.checked_sub(1) { 311 assert!( 312 !sna16eq(s1, s1sub1), 313 "s1 == s1-1 hould be false: s1={} s1-1={}", 314 s1, 315 s1sub1 316 ); 317 } 318 319 assert!( 320 sna16lte(s1, s1), 321 "s1 == s1 should be true: s1={} s2={}", 322 s1, 323 s1 324 ); 325 assert!( 326 sna16gte(s1, s1), 327 "s1 == s1 should be true: s1={} s2={}", 328 s1, 329 s1 330 ); 331 } 332 333 Ok(()) 334 } 335 } 336