Skip to content

Commit 3b38ffc

Browse files
committed
pldm-file: client: Perform retries on CRC failure
Up to 20 consecutive retries will be performed before returning a protocol error. Signed-off-by: Matt Johnston <[email protected]>
1 parent 982d4c2 commit 3b38ffc

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

pldm-file/src/client.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use deku::{DekuContainerRead, DekuContainerWrite};
2-
use log::trace;
2+
use log::{trace, warn};
33
use pldm::control::{MultipartReceiveReq, MultipartReceiveResp};
44
use pldm::{
55
pldm_xfer_buf_async, proto_error, PldmError, PldmRequest, PldmResult,
@@ -153,6 +153,9 @@ pub async fn df_read_with<F>(
153153
where
154154
F: FnMut(&[u8]) -> PldmResult<()>,
155155
{
156+
// Maximum retries for the same offset. Avoids looping forever.
157+
const CRC_FAIL_RETRIES: usize = 20;
158+
156159
let req_offset = u32::try_from(offset).map_err(|_| {
157160
trace!("invalid offset");
158161
PldmError::InvalidArgument
@@ -177,6 +180,7 @@ where
177180
};
178181
let crc32 = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC);
179182
let mut digest = crc32.digest();
183+
let mut crc_fail_count = 0;
180184
loop {
181185
let mut tx_buf = [0; 18];
182186
let l = req.to_slice(&mut tx_buf).map_err(|_| PldmError::NoSpace)?;
@@ -205,13 +209,25 @@ where
205209

206210
let (resp_data, resp_cs) = rest.split_at(resp_data_len);
207211

208-
digest.update(resp_data);
212+
let mut up_digest = digest.clone();
213+
up_digest.update(resp_data);
209214
// unwrap: we have asserted the lengths above
210215
let cs = u32::from_le_bytes(resp_cs.try_into().unwrap());
211216

212-
if digest.clone().finalize() != cs {
213-
return Err(proto_error!("data checksum mismatch"));
217+
if up_digest.clone().finalize() != cs {
218+
warn!(
219+
"data checksum mismatch requesting offset {}",
220+
req_offset as usize + part_offset
221+
);
222+
crc_fail_count += 1;
223+
if crc_fail_count > CRC_FAIL_RETRIES {
224+
return Err(proto_error!("excess CRC failures"));
225+
}
226+
req.xfer_op = pldm::control::xfer_op::CURRENT_PART;
227+
continue;
214228
}
229+
digest = up_digest;
230+
crc_fail_count = 0;
215231

216232
// Ensure the host doesn't send more data than requested
217233
let total_len = part_offset

0 commit comments

Comments
 (0)