From c4249025606c3370c1b0a025df0077c78692db64 Mon Sep 17 00:00:00 2001 From: Carlos Guerra Date: Sun, 31 May 2026 15:54:22 +0200 Subject: [PATCH] linting and polishing for PR --- lib/src/diag/diaglog/measurement.rs | 28 +++++++++------ lib/src/gsmtap/parser.rs | 54 +++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/lib/src/diag/diaglog/measurement.rs b/lib/src/diag/diaglog/measurement.rs index 9b0c494..9a70502 100644 --- a/lib/src/diag/diaglog/measurement.rs +++ b/lib/src/diag/diaglog/measurement.rs @@ -77,23 +77,31 @@ mod test { // Constructed as: opcode(1) + pending(1) + outer_len(2) + inner_len(2) + // log_type(2=0xb17f LE) + timestamp(8) + body(40) = 56 bytes total let mut msg_bytes: Vec = vec![ - 0x10, 0x00, // opcode=Log, pending=0 - 56, 0, 56, 0, // outer_length=56, inner_length=56 - 0x7f, 0xb1, // log_type = 0xb17f (LE) + 0x10, 0x00, // opcode=Log, pending=0 + 56, 0, 56, 0, // outer_length=56, inner_length=56 + 0x7f, 0xb1, // log_type = 0xb17f (LE) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // timestamp ]; msg_bytes.extend_from_slice(&[ 0x05, // version=5 - 0x01, 0x00, 0x00, 0x39, 0x07, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, - 0xab, 0xb5, 0x5a, 0x00, 0xab, 0xb5, 0x5a, 0x00, - 0x1a, 0x69, 0xa4, 0x11, 0x1a, 0x45, 0x0d, 0x00, 0x86, 0xa7, 0xae, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x1c, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x39, 0x07, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0xab, 0xb5, 0x5a, + 0x00, 0xab, 0xb5, 0x5a, 0x00, 0x1a, 0x69, 0xa4, 0x11, 0x1a, 0x45, 0x0d, 0x00, 0x86, + 0xa7, 0xae, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1c, 0x00, 0x00, ]); - let msg = Message::from_bytes((&msg_bytes, 0)).expect("Message parse failed").1; - if let Message::Log { body: LogBody::LteMl1ServingCellMeas { packet, .. }, .. } = msg { + let msg = Message::from_bytes((&msg_bytes, 0)) + .expect("Message parse failed") + .1; + if let Message::Log { + body: LogBody::LteMl1ServingCellMeas { packet, .. }, + .. + } = msg + { assert_eq!(packet.get_earfcn(), 1849); let rsrp = packet.get_rsrp_dbm(); - assert!(rsrp <= -44 && rsrp >= -120, "RSRP {rsrp} dBm outside valid LTE range"); + assert!( + rsrp <= -44 && rsrp >= -120, + "RSRP {rsrp} dBm outside valid LTE range" + ); } else { panic!("unexpected message variant"); } diff --git a/lib/src/gsmtap/parser.rs b/lib/src/gsmtap/parser.rs index b45a12d..bc1e3ba 100644 --- a/lib/src/gsmtap/parser.rs +++ b/lib/src/gsmtap/parser.rs @@ -201,7 +201,8 @@ fn parse_rach_response(payload: &[u8]) -> Option { if sp_id == 0x06 { // RACH Attempt subpacket - if let Some(msg) = extract_rach_attempt_gsmtap(&payload[offset + 4..sp_end], sp_version) { + if let Some(msg) = extract_rach_attempt_gsmtap(&payload[offset + 4..sp_end], sp_version) + { return Some(msg); } } @@ -258,7 +259,10 @@ fn extract_rach_attempt_gsmtap(body: &[u8], version: u8) -> Option> 3) & 0xFF) as u8, ((ta & 0x07) as u8) << 5, @@ -278,6 +282,7 @@ fn extract_rach_attempt_gsmtap(body: &[u8], version: u8) -> Option Vec { + let rapid: u8 = 43; + let tc_rnti: u16 = 0x1234; + let [ta_lo, ta_hi] = ta_raw.to_le_bytes(); + let [rnti_lo, rnti_hi] = tc_rnti.to_le_bytes(); + // sp_size covers the 4-byte subpacket header + 6-byte body header + 7-byte MSG2 = 17 + vec![ + 0x01, 0x01, 0x00, 0x00, // outer: version=1, num_subpackets=1, reserved + 0x06, 0x03, 17, 0x00, // subpacket: id=0x06, version=0x03, size=17 LE + 0x00, 0x00, rapid, 0x00, 0x00, bitmask, // body header (6 bytes) + 0x00, 0x00, 0x01, rnti_lo, rnti_hi, ta_lo, ta_hi, // MSG2 (7 bytes) + ] + } + + #[test] + fn test_rach_response_valid_ta() { + let payload = make_rach_v03_payload(42, 0x02); // 0x02 = msg2 present, msg1 absent + let msg = parse_rach_response(&payload).expect("expected a GsmtapMessage for valid TA"); + assert_eq!(msg.header.gsmtap_type, GsmtapType::LteMacFramed); + // TA stored in frame_number for Wireshark compatibility (gsmtap.frame_nr) + assert_eq!(msg.header.frame_number, 42); + // MAC RAR PDU: 4-byte framing prefix + 7-byte RAR PDU = 11 bytes + assert_eq!(msg.payload.len(), 11); + // Verify TA encoding in RAR PDU bytes 5–6 (TA[10:3] and TA[2:0]) + // ta=42: ta>>3=5 in byte[5], (ta&7)<<5 = 2<<5 = 0x40 in byte[6] + assert_eq!(msg.payload[5], 5); + assert_eq!(msg.payload[6], 0x40); + } + + #[test] + fn test_rach_response_ffff_sentinel_returns_none() { + // 0xFFFF means RAR was received but TA was not valid; must be dropped + let payload = make_rach_v03_payload(0xFFFF, 0x02); + assert!(parse_rach_response(&payload).is_none()); + } + + #[test] + fn test_rach_response_no_msg2_returns_none() { + // bitmask=0x01 means only MSG1 present; no TA available + let payload = make_rach_v03_payload(42, 0x01); + assert!(parse_rach_response(&payload).is_none()); + } }