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