From 4f11defc4e4793be7861cdeef98426d821d4f3d4 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Wed, 16 Jul 2025 10:04:45 -0500 Subject: [PATCH] Fixed MS/TP zero-config FSM getting stuck when duplicate address is detected. (#1048) --- src/bacnet/datalink/mstp.c | 1 + test/bacnet/datalink/mstp/src/main.c | 29 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/bacnet/datalink/mstp.c b/src/bacnet/datalink/mstp.c index 9e3ef0d2..df834bf4 100644 --- a/src/bacnet/datalink/mstp.c +++ b/src/bacnet/datalink/mstp.c @@ -641,6 +641,7 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port) (mstp_port->ReceivedValidFrame == true) && (mstp_port->SourceAddress == mstp_port->This_Station)) { /* DuplicateNode */ + mstp_port->This_Station = 255; mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_INIT; mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE; /* ignore the frame */ diff --git a/test/bacnet/datalink/mstp/src/main.c b/test/bacnet/datalink/mstp/src/main.c index bbf3d9ed..be62803b 100644 --- a/test/bacnet/datalink/mstp/src/main.c +++ b/test/bacnet/datalink/mstp/src/main.c @@ -1082,6 +1082,27 @@ static void testZeroConfigNode_Test_LURK_ClaimLostToken( mstp_port->Zero_Config_State, MSTP_ZERO_CONFIG_STATE_IDLE, NULL); } +static void +testZeroConfigNode_Test_DuplicateNode(struct mstp_port_struct_t *mstp_port) +{ + bool transition_now; + uint8_t station; + + /* ClaimAddressInUse */ + station = mstp_port->Zero_Config_Station; + mstp_port->SourceAddress = station; + mstp_port->DestinationAddress = 0; + mstp_port->FrameType = FRAME_TYPE_POLL_FOR_MASTER; + mstp_port->ReceivedValidFrame = true; + transition_now = MSTP_Master_Node_FSM(mstp_port); + zassert_false(transition_now, NULL); + zassert_true(mstp_port->ReceivedValidFrame == false, NULL); + zassert_equal( + mstp_port->Zero_Config_State, MSTP_ZERO_CONFIG_STATE_IDLE, NULL); + zassert_equal(mstp_port->master_state, MSTP_MASTER_STATE_INITIALIZE, NULL); + zassert_equal(mstp_port->This_Station, 255, NULL); +} + static void testZeroConfigNodeFSM(void) { struct mstp_port_struct_t MSTP_Port = { 0 }; /* port data */ @@ -1148,6 +1169,14 @@ static void testZeroConfigNodeFSM(void) testZeroConfigNode_Test_IDLE_ValidFrame(&MSTP_Port); testZeroConfigNode_Test_LURK_Claim(&MSTP_Port); testZeroConfigNode_Test_LURK_ClaimLostToken(&MSTP_Port); + /* test case: valid frame event LURK PFMs: ClaimAddress + ConfirmationSuccessful, DuplicateNode */ + testZeroConfigNode_Init(&MSTP_Port); + testZeroConfigNode_Test_IDLE_ValidFrame(&MSTP_Port); + testZeroConfigNode_Test_LURK_Claim(&MSTP_Port); + testZeroConfigNode_Test_LURK_ClaimTokenForUs(&MSTP_Port); + testZeroConfigNode_Test_LURK_ConfirmationSuccessful(&MSTP_Port); + testZeroConfigNode_Test_DuplicateNode(&MSTP_Port); /* test next station rollover */ station = 0; test_station = Nmin_poll_station;