Skip to content

Commit b2f4488

Browse files
lexus2kCopilot
andcommitted
NRM: P/F burst fix, CR bit fix, disconnected state filter, 9 new tests
Library fixes: - P/F bit now only set on last I-frame in NRM burst (enables full window throughput). S/U frames always get P/F for marker passing. - Add missing CR bit on idle-path SNRM (consistency with timeout path) - Add disconnected state filter in __on_u_frame_read(): rejects non-SABM/ SNRM/UI U-frames when peer is disconnected, sends DM for commands - Update ABM test to expect DM (not UA) for DISC when disconnected New NRM tests (9 added, 82 total): - PrimaryToSecondary_SingleIFrame: I-frame with P bit on single frame - MultiplIFrames_PFOnLastOnly: P/F burst - first frame no P, last has P - SecondaryToRrimary_IFrameReceive: data reception + RR acknowledgment - MarkerTimeoutRecovery: primary reclaims marker after retry_timeout - PrimaryDisconnect: DISC+P / UA+F exchange - DMResponseWhenDisconnected: DM+F for command when disconnected - RoundRobinPeerSwitching: alternating I-frames between 2 peers - FRMRRecovery: FRMR triggers disconnect + SNRM re-establishment - REJRecovery: REJ retransmission with proper round-robin cycle Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 1b297aa commit b2f4488

4 files changed

Lines changed: 320 additions & 15 deletions

File tree

src/proto/fd/tiny_fd.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ static uint8_t *tiny_fd_get_next_frame_to_send(tiny_fd_handle_t handle, int *len
531531
( handle->peers[peer].state == TINY_FD_STATE_DISCONNECTED || handle->peers[peer].state == TINY_FD_STATE_CONNECTING))
532532
{
533533
tiny_frame_header_t frame = {
534-
.address = address,
534+
.address = address | HDLC_CR_BIT,
535535
.control = HDLC_U_FRAME_TYPE_SNRM | HDLC_U_FRAME_BITS,
536536
};
537537
__put_u_s_frame_to_tx_queue(handle, TINY_FD_QUEUE_S_FRAME, &frame, 2);
@@ -552,8 +552,19 @@ static uint8_t *tiny_fd_get_next_frame_to_send(tiny_fd_handle_t handle, int *len
552552
tiny_frame_header_t *header = (tiny_frame_header_t *)data;
553553
if ( handle->mode == TINY_FD_MODE_NRM )
554554
{
555-
// NRM: Always set P/F bit for marker passing
556-
header->control |= HDLC_P_BIT;
555+
// NRM: P/F on last frame only. S/U frames always get P/F (marker passing).
556+
// I-frames get P/F only when no more I-frames remain for this peer.
557+
if ( (header->control & HDLC_I_FRAME_MASK) == HDLC_I_FRAME_BITS )
558+
{
559+
if ( __all_frames_are_sent(&handle->peers[peer].i_queue_control) )
560+
{
561+
header->control |= HDLC_P_BIT;
562+
}
563+
}
564+
else
565+
{
566+
header->control |= HDLC_P_BIT;
567+
}
557568
}
558569
else
559570
{

src/proto/fd/tiny_fd_on_rx_int.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,22 @@ static int __on_u_frame_read(tiny_fd_handle_t handle, uint8_t peer, void *data,
174174
uint8_t type = control & HDLC_U_FRAME_TYPE_MASK;
175175
int result = TINY_ERR_FAILED;
176176
LOG(TINY_LOG_INFO, "[%p] Receiving U-Frame type=%02X with address [%02X]\n", handle, type, ((uint8_t *)data)[0]);
177+
// In disconnected state, only accept connection setup (SABM/SNRM) and connectionless (UI) frames.
178+
// Respond with DM to commands; silently ignore responses.
179+
if ( handle->peers[peer].state == TINY_FD_STATE_DISCONNECTED &&
180+
type != HDLC_U_FRAME_TYPE_SABM && type != HDLC_U_FRAME_TYPE_SNRM && type != HDLC_U_FRAME_TYPE_UI )
181+
{
182+
LOG(TINY_LOG_WRN, "[%p] Ignoring U-frame type=%02X in disconnected state\n", handle, type);
183+
if ( ((uint8_t *)data)[0] & HDLC_CR_BIT )
184+
{
185+
tiny_frame_header_t frame = {
186+
.address = __peer_to_address_field( handle, peer ),
187+
.control = HDLC_U_FRAME_TYPE_DM | HDLC_U_FRAME_BITS,
188+
};
189+
__put_u_s_frame_to_tx_queue(handle, TINY_FD_QUEUE_U_FRAME, &frame, 2);
190+
}
191+
return result;
192+
}
177193
if ( type == HDLC_U_FRAME_TYPE_SABM || type == HDLC_U_FRAME_TYPE_SNRM )
178194
{
179195
tiny_frame_header_t frame = {

unittest/tiny_fd_abm_tests.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,10 @@ TEST(TINY_FD_ABM, ABM_DisconnectResponseWhenNotConnected)
181181
CHECK_EQUAL(TINY_SUCCESS, read_result);
182182
int len = tiny_fd_get_tx_data(handle, outBuffer.data(), outBuffer.size(), 100);
183183
CHECK_EQUAL(4, len);
184-
// Check UA frame
185-
// UA frame should be: 0x7E 0x03 0x00 0x7E
184+
// Per HDLC spec: DISC when disconnected gets DM response (not UA)
186185
CHECK_EQUAL(0x7E, outBuffer[0]); // Flag
187186
CHECK_EQUAL(0x01, outBuffer[1]); // address field - CR bit must be cleared
188-
CHECK_EQUAL(0x73, outBuffer[2]); // UA packet
187+
CHECK_EQUAL(0x1F, outBuffer[2]); // DM packet with P/F bit
189188
CHECK_EQUAL(0x7E, outBuffer[3]); // Flag
190189
CHECK(connected); // Connection should not be changed
191190
}

0 commit comments

Comments
 (0)