From 52a2cd437afda2721f2b40c9eb11b917f25be6aa Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Thu, 10 Oct 2024 15:50:57 -0500 Subject: [PATCH] Fixed MS/TP FSM TS filter that was removed for zero-config permiscuous feature. (#803) --- ports/stm32f4xx/CMakeLists.txt | 24 +++++ src/bacnet/datalink/mstp.c | 164 +++++++++++++++++---------------- 2 files changed, 111 insertions(+), 77 deletions(-) diff --git a/ports/stm32f4xx/CMakeLists.txt b/ports/stm32f4xx/CMakeLists.txt index 8c88dff7..f46a49df 100644 --- a/ports/stm32f4xx/CMakeLists.txt +++ b/ports/stm32f4xx/CMakeLists.txt @@ -51,8 +51,11 @@ set(CMAKE_OBJCOPY arm-none-eabi-objcopy) set(CMAKE_OBJDUMP arm-none-eabi-objdump) set(CMAKE_SIZE arm-none-eabi-size) set(CMAKE_NM arm-none-eabi-nm) +set(CMAKE_GDB gdb-multiarch) +set(CMAKE_OPENOCD openocd) set(CMAKE_CSTACK "${CMAKE_SOURCE_DIR}/../../tools/check-stack-usage/checkStackUsage.py") set(CMAKE_MEMAP "${CMAKE_SOURCE_DIR}/../../tools/memap/memap.py") + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(EXECUTABLE ${PROJECT_NAME}.elf) @@ -322,3 +325,24 @@ add_custom_target(memmap COMMENT "Print file and library memory usage by size" COMMAND ${CMAKE_MEMAP} -t GCC_ARM ${PROJECT_NAME}.map ) + +# Run OpenOCD with ST Link to debug +add_custom_target(openocd + DEPENDS ${EXECUTABLE} + COMMENT "OpenOCD GDB Server via ST Link" + COMMAND ${CMAKE_OPENOCD} -f interface/stlink.cfg -f target/stm32f4x.cfg +) + +add_custom_target(gdb + DEPENDS ${EXECUTABLE} + COMMENT "GDB connection to GDB Server via ST Link" + COMMAND ${CMAKE_GDB} -q ${EXECUTABLE} -ex "target extended-remote localhost:3333" +) + +# Run OpenOCD with ST Link to flash +set(OPENOCD_FLASH_CMD "program ${EXECUTABLE} verify reset exit") +add_custom_target(flash + DEPENDS ${EXECUTABLE} + COMMENT "OpenOCD flash and verify using elf." + COMMAND ${CMAKE_OPENOCD} -f interface/stlink.cfg -f target/stm32f4x.cfg -c ${OPENOCD_FLASH_CMD} +) diff --git a/src/bacnet/datalink/mstp.c b/src/bacnet/datalink/mstp.c index 843b0cf4..f4c63125 100644 --- a/src/bacnet/datalink/mstp.c +++ b/src/bacnet/datalink/mstp.c @@ -623,6 +623,29 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port) (mstp_port->This_Station + 1) % (mstp_port->Nmax_master + 1); next_next_station = (mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + 1); + /* The zero config receive state machine does not + filter DestinationAddress for This_Station or Broadcast. + Check before running FSM: */ + if (mstp_port->ReceivedValidFrame == true) { + if ((mstp_port->master_state == MSTP_MASTER_STATE_INITIALIZE) && + (mstp_port->ZeroConfigEnabled)) { + /* zero config initialization processes all frames */ + } else { + if ((mstp_port->DestinationAddress == mstp_port->This_Station) || + (mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS)) { + /* process as-is */ + } else { + if ((mstp_port->ZeroConfigEnabled) && + (mstp_port->SourceAddress == mstp_port->This_Station)) { + /* DuplicateNode */ + mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_INIT; + mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE; + } + /* ignore the frame */ + mstp_port->ReceivedValidFrame = false; + } + } + } switch (mstp_port->master_state) { case MSTP_MASTER_STATE_INITIALIZE: if (mstp_port->ZeroConfigEnabled) { @@ -674,86 +697,73 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port) mstp_port->DataLength, mstp_port->FrameCount, mstp_port->SilenceTimer((void *)mstp_port), mstptext_frame_type((unsigned)mstp_port->FrameType)); - if (mstp_port->SourceAddress == mstp_port->This_Station) { - /* DuplicateNode */ - if (mstp_port->ZeroConfigEnabled) { - /* we are a zero config node - start over */ - mstp_port->Zero_Config_State = - MSTP_ZERO_CONFIG_STATE_INIT; - mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE; - } - mstp_port->ReceivedValidFrame = false; - } else { - /* destined for me! */ - switch (mstp_port->FrameType) { - case FRAME_TYPE_TOKEN: - /* ReceivedToken */ - /* tokens cannot be broadcast */ - if (mstp_port->DestinationAddress == - MSTP_BROADCAST_ADDRESS) { - break; - } - mstp_port->ReceivedValidFrame = false; - mstp_port->FrameCount = 0; - mstp_port->SoleMaster = false; - mstp_port->master_state = - MSTP_MASTER_STATE_USE_TOKEN; - transition_now = true; + /* destined for me! */ + switch (mstp_port->FrameType) { + case FRAME_TYPE_TOKEN: + /* ReceivedToken */ + /* tokens cannot be broadcast */ + if (mstp_port->DestinationAddress == + MSTP_BROADCAST_ADDRESS) { break; - case FRAME_TYPE_POLL_FOR_MASTER: - /* ReceivedPFM */ - /* DestinationAddress is equal to TS */ - if (mstp_port->DestinationAddress == - mstp_port->This_Station) { - MSTP_Create_And_Send_Frame( - mstp_port, - FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, - mstp_port->SourceAddress, - mstp_port->This_Station, NULL, 0); - } - break; - case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - case FRAME_TYPE_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY: - if ((mstp_port->DestinationAddress == - MSTP_BROADCAST_ADDRESS) && - (npdu_confirmed_service( - mstp_port->InputBuffer, - mstp_port->DataLength))) { - /* BTL test: verifies that the IUT will quietly - discard any Confirmed-Request-PDU, whose - destination address is a multicast or - broadcast address, received from the - network layer. */ - } else { - /* indicate successful reception to the higher - * layers */ - (void)MSTP_Put_Receive(mstp_port); - } - break; - case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - case FRAME_TYPE_BACNET_EXTENDED_DATA_EXPECTING_REPLY: - if (mstp_port->DestinationAddress == - MSTP_BROADCAST_ADDRESS) { - /* broadcast DER just remains IDLE */ - } else { - /* indicate successful reception to the higher - * layers */ - (void)MSTP_Put_Receive(mstp_port); - mstp_port->master_state = - MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; - } - break; - case FRAME_TYPE_TEST_REQUEST: + } + mstp_port->ReceivedValidFrame = false; + mstp_port->FrameCount = 0; + mstp_port->SoleMaster = false; + mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; + transition_now = true; + break; + case FRAME_TYPE_POLL_FOR_MASTER: + /* ReceivedPFM */ + /* DestinationAddress is equal to TS */ + if (mstp_port->DestinationAddress == + mstp_port->This_Station) { MSTP_Create_And_Send_Frame( - mstp_port, FRAME_TYPE_TEST_RESPONSE, + mstp_port, FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, mstp_port->SourceAddress, - mstp_port->This_Station, mstp_port->InputBuffer, - mstp_port->DataLength); - break; - case FRAME_TYPE_TEST_RESPONSE: - default: - break; - } + mstp_port->This_Station, NULL, 0); + } + break; + case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: + case FRAME_TYPE_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY: + if ((mstp_port->DestinationAddress == + MSTP_BROADCAST_ADDRESS) && + (npdu_confirmed_service( + mstp_port->InputBuffer, + mstp_port->DataLength))) { + /* BTL test: verifies that the IUT will + quietly discard any Confirmed-Request-PDU, + whose destination address is a multicast or + broadcast address, received from the + network layer. */ + } else { + /* ForUs */ + /* indicate successful reception + to the higher layers */ + (void)MSTP_Put_Receive(mstp_port); + } + break; + case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: + case FRAME_TYPE_BACNET_EXTENDED_DATA_EXPECTING_REPLY: + if (mstp_port->DestinationAddress == + MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to the higher + * layers */ + (void)MSTP_Put_Receive(mstp_port); + mstp_port->master_state = + MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; + } + break; + case FRAME_TYPE_TEST_REQUEST: + MSTP_Create_And_Send_Frame( + mstp_port, FRAME_TYPE_TEST_RESPONSE, + mstp_port->SourceAddress, mstp_port->This_Station, + mstp_port->InputBuffer, mstp_port->DataLength); + break; + case FRAME_TYPE_TEST_RESPONSE: + default: + break; } /* For DATA_EXPECTING_REPLY, we will keep the Rx Frame for reference, and the flag will be cleared in the next state */