From 12a5e48b3e6f31baed6f75b1f2c3d3a2716ac24f Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Sat, 2 Apr 2022 08:44:04 -0500 Subject: [PATCH] Bugfix/btl mstp local broadcast discard (#248) * Discard Confirmed PDU DNER on local broadcast. Discard DER on local broacast. Co-authored-by: Steve Karg --- Makefile | 4 ++-- ports/at91sam7s/dlmstp.c | 22 +++++++++++++++------ ports/atmega168/dlmstp.c | 22 +++++++++++++++------ ports/bdk-atxx4-mstp/dlmstp.c | 22 +++++++++++++++------ ports/pic18f6720/mstp.c | 37 +++++++++++++++++++++++------------ ports/pic18f97j60/mstp.c | 37 +++++++++++++++++++++++------------ ports/stm32f10x/dlmstp.c | 22 +++++++++++++++------ ports/stm32f4xx/dlmstp.c | 22 +++++++++++++++------ ports/xplained/dlmstp.c | 22 +++++++++++++++------ src/bacnet/datalink/mstp.c | 35 ++++++++++++++++++++++----------- 10 files changed, 170 insertions(+), 75 deletions(-) diff --git a/Makefile b/Makefile index 0649824c..6a094273 100644 --- a/Makefile +++ b/Makefile @@ -141,11 +141,11 @@ router-mstp: # Add "ports" to the build, if desired .PHONY: ports -ports: atmega168 bdk-atxx4-mstp at91sam7s stm32f10x +ports: atmega168 bdk-atxx4-mstp at91sam7s stm32f10x stm32f4xx @echo "Built the ARM7 and AVR ports" .PHONY: ports-clean -ports-clean: atmega168-clean bdk-atxx4-mstp-clean at91sam7s-clean stm32f10x-clean +ports-clean: atmega168-clean bdk-atxx4-mstp-clean at91sam7s-clean stm32f10x-clean stm32f4xx-clean .PHONY: atmega168 atmega168: ports/atmega168/Makefile diff --git a/ports/at91sam7s/dlmstp.c b/ports/at91sam7s/dlmstp.c index ca88bdbd..62fc7e88 100644 --- a/ports/at91sam7s/dlmstp.c +++ b/ports/at91sam7s/dlmstp.c @@ -704,14 +704,24 @@ static bool MSTP_Master_Node_FSM(void) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ - MSTP_Flag.ReceivePacketPending = true; + if ((DestinationAddress == MSTP_BROADCAST_ADDRESS) && + (npdu_confirmed_service(InputBuffer, 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 higher layer */ + MSTP_Flag.ReceivePacketPending = true; + } break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* indicate successful reception to higher layers */ - MSTP_Flag.ReceivePacketPending = true; - /* broadcast DER just remains IDLE */ - if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { + if (DestinationAddress == MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to higher layers */ + MSTP_Flag.ReceivePacketPending = true; Master_State = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } diff --git a/ports/atmega168/dlmstp.c b/ports/atmega168/dlmstp.c index 5fe5a4cc..2cc60186 100644 --- a/ports/atmega168/dlmstp.c +++ b/ports/atmega168/dlmstp.c @@ -613,14 +613,24 @@ static bool MSTP_Master_Node_FSM(void) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ - MSTP_Flag.ReceivePacketPending = true; + if ((DestinationAddress == MSTP_BROADCAST_ADDRESS) && + (npdu_confirmed_service(InputBuffer, 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 higher layer */ + MSTP_Flag.ReceivePacketPending = true; + } break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ - MSTP_Flag.ReceivePacketPending = true; - /* broadcast DER just remains IDLE */ - if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { + if (DestinationAddress == MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to higher layers */ + MSTP_Flag.ReceivePacketPending = true; Master_State = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } diff --git a/ports/bdk-atxx4-mstp/dlmstp.c b/ports/bdk-atxx4-mstp/dlmstp.c index e808be67..b0d8e726 100644 --- a/ports/bdk-atxx4-mstp/dlmstp.c +++ b/ports/bdk-atxx4-mstp/dlmstp.c @@ -726,14 +726,24 @@ static bool MSTP_Master_Node_FSM(void) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ - MSTP_Flag.ReceivePacketPending = true; + if ((DestinationAddress == MSTP_BROADCAST_ADDRESS) && + (npdu_confirmed_service(InputBuffer, 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 higher layer */ + MSTP_Flag.ReceivePacketPending = true; + } break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* indicate successful reception to higher layers */ - MSTP_Flag.ReceivePacketPending = true; - /* broadcast DER just remains IDLE */ - if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { + if (DestinationAddress == MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to higher layers */ + MSTP_Flag.ReceivePacketPending = true; Master_State = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } diff --git a/ports/pic18f6720/mstp.c b/ports/pic18f6720/mstp.c index 2ab77915..eaae855d 100644 --- a/ports/pic18f6720/mstp.c +++ b/ports/pic18f6720/mstp.c @@ -752,22 +752,33 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher - * layers */ - dlmstp_put_receive(mstp_port->SourceAddress, - (uint8_t *)&mstp_port->InputBuffer[0], - mstp_port->DataLength); + 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 */ + dlmstp_put_receive(mstp_port->SourceAddress, + (uint8_t *)&mstp_port->InputBuffer[0], + mstp_port->DataLength); + } break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /*mstp_port->ReplyPostponedTimer = 0; */ - /* indicate successful reception to the higher - * layers */ - dlmstp_put_receive(mstp_port->SourceAddress, - (uint8_t *)&mstp_port->InputBuffer[0], - mstp_port->DataLength); - /* broadcast DER just remains IDLE */ - if (mstp_port->DestinationAddress != + if (mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to the higher + * layers */ + dlmstp_put_receive(mstp_port->SourceAddress, + (uint8_t *)&mstp_port->InputBuffer[0], + mstp_port->DataLength); mstp_port->master_state = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } diff --git a/ports/pic18f97j60/mstp.c b/ports/pic18f97j60/mstp.c index 96e1ad30..b4344c61 100644 --- a/ports/pic18f97j60/mstp.c +++ b/ports/pic18f97j60/mstp.c @@ -760,22 +760,33 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher - * layers */ - dlmstp_put_receive(mstp_port->SourceAddress, - (uint8_t *)&mstp_port->InputBuffer[0], - mstp_port->DataLength); + 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 */ + dlmstp_put_receive(mstp_port->SourceAddress, + (uint8_t *)&mstp_port->InputBuffer[0], + mstp_port->DataLength); + } break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /*mstp_port->ReplyPostponedTimer = 0; */ - /* indicate successful reception to the higher - * layers */ - dlmstp_put_receive(mstp_port->SourceAddress, - (uint8_t *)&mstp_port->InputBuffer[0], - mstp_port->DataLength); - /* broadcast DER just remains IDLE */ - if (mstp_port->DestinationAddress != + if (mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to the higher + * layers */ + dlmstp_put_receive(mstp_port->SourceAddress, + (uint8_t *)&mstp_port->InputBuffer[0], + mstp_port->DataLength); mstp_port->master_state = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } diff --git a/ports/stm32f10x/dlmstp.c b/ports/stm32f10x/dlmstp.c index 1fede19a..5ecc2a6b 100644 --- a/ports/stm32f10x/dlmstp.c +++ b/ports/stm32f10x/dlmstp.c @@ -807,14 +807,24 @@ static bool MSTP_Master_Node_FSM(void) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ - MSTP_Flag.ReceivePacketPending = true; + if ((DestinationAddress == MSTP_BROADCAST_ADDRESS) && + (npdu_confirmed_service(InputBuffer, 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 higher layer */ + MSTP_Flag.ReceivePacketPending = true; + } break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* indicate successful reception to higher layers */ - MSTP_Flag.ReceivePacketPending = true; - /* broadcast DER just remains IDLE */ - if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { + if (DestinationAddress == MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to higher layers */ + MSTP_Flag.ReceivePacketPending = true; Master_State = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } diff --git a/ports/stm32f4xx/dlmstp.c b/ports/stm32f4xx/dlmstp.c index eb210d31..c6704de5 100644 --- a/ports/stm32f4xx/dlmstp.c +++ b/ports/stm32f4xx/dlmstp.c @@ -872,14 +872,24 @@ static bool MSTP_Master_Node_FSM(void) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ - MSTP_Flag.ReceivePacketPending = true; + if ((DestinationAddress == MSTP_BROADCAST_ADDRESS) && + (npdu_confirmed_service(InputBuffer, 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 higher layer */ + MSTP_Flag.ReceivePacketPending = true; + } break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* indicate successful reception to higher layers */ - MSTP_Flag.ReceivePacketPending = true; - /* broadcast DER just remains IDLE */ - if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { + if (DestinationAddress == MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to higher layers */ + MSTP_Flag.ReceivePacketPending = true; Master_State = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } diff --git a/ports/xplained/dlmstp.c b/ports/xplained/dlmstp.c index 5e76f3c4..351d223d 100644 --- a/ports/xplained/dlmstp.c +++ b/ports/xplained/dlmstp.c @@ -809,14 +809,24 @@ static bool MSTP_Master_Node_FSM(void) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher layers */ - MSTP_Flag.ReceivePacketPending = true; + if ((DestinationAddress == MSTP_BROADCAST_ADDRESS) && + (npdu_confirmed_service(InputBuffer, 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 higher layer */ + MSTP_Flag.ReceivePacketPending = true; + } break; case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - /* indicate successful reception to higher layers */ - MSTP_Flag.ReceivePacketPending = true; - /* broadcast DER just remains IDLE */ - if (DestinationAddress != MSTP_BROADCAST_ADDRESS) { + if (DestinationAddress == MSTP_BROADCAST_ADDRESS) { + /* broadcast DER just remains IDLE */ + } else { + /* indicate successful reception to higher layers */ + MSTP_Flag.ReceivePacketPending = true; Master_State = MSTP_MASTER_STATE_ANSWER_DATA_REQUEST; } diff --git a/src/bacnet/datalink/mstp.c b/src/bacnet/datalink/mstp.c index ea792c75..73c140d3 100644 --- a/src/bacnet/datalink/mstp.c +++ b/src/bacnet/datalink/mstp.c @@ -55,8 +55,10 @@ #include "crc.h" #include "rs485.h" #include "bacnet/datalink/mstptext.h" -#if !defined(DEBUG_ENABLED) -#define DEBUG_ENABLED 1 +#include "bacnet/npdu.h" + +#ifndef DEBUG_ENABLED +#define DEBUG_ENABLED 0 #endif #include "bacnet/basic/sys/debug.h" @@ -655,18 +657,29 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port) } break; case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - /* indicate successful reception to the higher - * layers */ - (void)MSTP_Put_Receive(mstp_port); + 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: - /*mstp_port->ReplyPostponedTimer = 0; */ - /* indicate successful reception to the higher - * layers */ - (void)MSTP_Put_Receive(mstp_port); - /* broadcast DER just remains IDLE */ - if (mstp_port->DestinationAddress != + 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; }