Bugfix/dlmstp api missing in ports os (#1003)

* Added missing API defined in header into ports/win32/dlmstp.c module, added a PDU queue and refactored receive thread, and refactored MS/TP timing parameters.

* Added missing API defined in header into ports/linux/dlmstp.c module, and refactored MS/TP timing parameters.

* Added missing API defined in header into ports/bsd/dlmstp.c module, and refactored MS/TP timing parameters.

* Reduce default MS/TP APDU to 480 to avoid extended frames by default.
This commit is contained in:
Steve Karg
2025-05-27 10:14:15 -05:00
committed by GitHub
parent f5b5db445c
commit 442f408c1a
10 changed files with 2126 additions and 1043 deletions
+5 -1
View File
@@ -28,9 +28,13 @@ mingw32:
export CC=$(ORIGINAL_CC) ; \
export LD=$(ORIGINAL_LD)
.PHONY: mstpwin32-clean
mstpwin32-clean:
$(MAKE) LEGACY=true BACDL=mstp BACNET_PORT=win32 -s -C apps clean
.PHONY: mstpwin32
mstpwin32:
$(MAKE) BACDL=mstp BACNET_PORT=win32 -s -C apps all
$(MAKE) LEGACY=true BACDL=mstp BACNET_PORT=win32 -s -C apps all
.PHONY: mstp
mstp:
+675 -331
View File
File diff suppressed because it is too large Load Diff
+653 -324
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -129,7 +129,7 @@ bool datetime_local(
bool *dst_active)
{
bool status = false;
struct tm *tblock;
struct tm *tblock = NULL;
#if defined(_MSC_VER)
struct tm newtime = { 0 };
__time64_t long_time = 0;
+687 -358
View File
File diff suppressed because it is too large Load Diff
+15 -1
View File
@@ -187,7 +187,21 @@ static void RS485_Configure_Status(void)
fprintf(stderr, "Unable to set status on %s\n", RS485_Port_Name);
RS485_Print_Error();
}
/* configure the COM port timeout values */
/* configure the time-out parameters for a communications device. */
/* If an application sets ReadIntervalTimeout and
ReadTotalTimeoutMultiplier to MAXDWORD and
sets ReadTotalTimeoutConstant to a value greater
than zero and less than MAXDWORD, one of the following
occurs when the ReadFile function is called:
* If there are any bytes in the input buffer,
ReadFile returns immediately with the bytes in the buffer.
* If there are no bytes in the input buffer,
ReadFile waits until a byte arrives and then returns immediately.
* If no bytes arrive within the time specified
by ReadTotalTimeoutConstant, ReadFile times out.
Constant values are in milliseconds
*/
ctNew.ReadIntervalTimeout = MAXDWORD;
ctNew.ReadTotalTimeoutMultiplier = MAXDWORD;
ctNew.ReadTotalTimeoutConstant = 1;
+3
View File
@@ -45,6 +45,9 @@ void bacnet_port_task(void)
bacnet_port_ipv4_task(elapsed_seconds);
#elif defined(BACDL_BIP6)
bacnet_port_ipv6_task(elapsed_seconds);
#else
/* nothing to do */
(void)elapsed_seconds;
#endif
}
}
+1 -1
View File
@@ -139,7 +139,7 @@
#define MAX_APDU 1476
#elif defined(BACDL_MSTP) && !defined(BACNET_SECURITY)
/* note: MS/TP extended frames can be up to 1476 bytes */
#define MAX_APDU 1476
#define MAX_APDU 480
#elif defined(BACDL_ETHERNET) && !defined(BACNET_SECURITY)
#define MAX_APDU 1476
#elif defined(BACDL_ETHERNET) && defined(BACNET_SECURITY)
+65 -4
View File
@@ -34,6 +34,7 @@
/* enable debugging */
static bool Datalink_Debug;
static uint16_t Datalink_Debug_Timer_Seconds;
/* timer used to renew Foreign Device Registration */
static uint16_t BBMD_Timer_Seconds;
static uint16_t BBMD_TTL_Seconds = 60000;
@@ -41,7 +42,9 @@ static uint16_t BBMD_TTL_Seconds = 60000;
static BACNET_IP_ADDRESS BBMD_Address;
static bool BBMD_Address_Valid;
static uint16_t BBMD_Result = 0;
#if defined(BACDL_BIP) && BBMD_ENABLED
static BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY BBMD_Table_Entry;
#endif
static uint32_t Network_Port_Instance = 1;
/**
@@ -96,10 +99,13 @@ void dlenv_bbmd_ttl_set(uint16_t ttl_secs)
*/
int dlenv_bbmd_result(void)
{
if ((BBMD_Result > 0) &&
(bvlc_get_last_result() == BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK)) {
if (BBMD_Result > 0) {
#if defined(BACDL_BIP) && BBMD_ENABLED
if (bvlc_get_last_result() == BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK) {
return -1;
}
#endif
}
/* Else, show our send: */
return BBMD_Result;
}
@@ -439,6 +445,14 @@ void dlenv_network_port_mstp_init(uint32_t instance)
if (pEnv) {
mac_address = strtol(pEnv, NULL, 0);
}
if (Datalink_Debug) {
fprintf(
stderr,
"Network Port[%lu] mode=MSTP bitrate=%ld mac[0]=%ld "
"max_info_frames=%ld, max_master=%ld\n",
(unsigned long)instance, baud_rate, mac_address, max_info_frames,
max_master);
}
#ifdef BACDL_MSTP
dlmstp_set_max_info_frames(max_info_frames);
dlmstp_set_max_master(max_master);
@@ -714,6 +728,10 @@ void dlenv_network_port_bsc_init(void)
*/
void dlenv_maintenance_timer(uint16_t elapsed_seconds)
{
#ifdef BACDL_MSTP
struct dlmstp_statistics statistics = { 0 };
#endif
if (BBMD_Timer_Seconds) {
if (BBMD_Timer_Seconds <= elapsed_seconds) {
BBMD_Timer_Seconds = 0;
@@ -733,6 +751,27 @@ void dlenv_maintenance_timer(uint16_t elapsed_seconds)
BBMD_Timer_Seconds = (uint16_t)BBMD_TTL_Seconds;
}
}
if (Network_Port_Type(Network_Port_Instance) == PORT_TYPE_MSTP) {
Datalink_Debug_Timer_Seconds = elapsed_seconds;
if (Datalink_Debug_Timer_Seconds >= 60) {
Datalink_Debug_Timer_Seconds = 0;
if (Datalink_Debug) {
#ifdef BACDL_MSTP
dlmstp_fill_statistics(&statistics);
fprintf(
stderr,
"MSTP: Frames Rx:%u/%u Tx:%u PDU Rx:%u Tx:%u Lost:%u\n",
statistics.receive_valid_frame_counter,
statistics.receive_invalid_frame_counter,
statistics.transmit_frame_counter,
statistics.transmit_pdu_counter,
statistics.receive_pdu_counter,
statistics.lost_token_counter);
fflush(stderr);
#endif
}
}
}
}
/** Initialize the DataLink configuration from Environment variables,
@@ -838,7 +877,7 @@ void dlenv_init(void)
port_type = PORT_TYPE_BIP;
#elif defined(BACDL_BIP6)
datalink_set("bip6");
port_type = PORT_TYPE__BIP6;
port_type = PORT_TYPE_BIP6;
#elif defined(BACDL_MSTP)
datalink_set("mstp");
port_type = PORT_TYPE_MSTP;
@@ -856,6 +895,24 @@ void dlenv_init(void)
port_type = PORT_TYPE_NON_BACNET;
#endif
}
#else
/* if we are not compiling with multiple datalinks,
then we are using the only one available */
#if defined(BACDL_BIP)
port_type = PORT_TYPE_BIP;
#elif defined(BACDL_BIP6)
port_type = PORT_TYPE_BIP6;
#elif defined(BACDL_MSTP)
port_type = PORT_TYPE_MSTP;
#elif defined(BACDL_ETHERNET)
port_type = PORT_TYPE_ETHERNET;
#elif defined(BACDL_ARCNET)
port_type = PORT_TYPE_ARCNET;
#elif defined(BACDL_BSC)
port_type = PORT_TYPE_BSC;
#else
port_type = PORT_TYPE_NON_BACNET;
#endif
#endif
Network_Port_Type_Set(Network_Port_Instance, port_type);
switch (port_type) {
@@ -888,7 +945,11 @@ void dlenv_init(void)
apdu_retries_set((uint8_t)strtol(pEnv, NULL, 0));
}
/* === Initialize the Datalink Here === */
if (!datalink_init(getenv("BACNET_IFACE"))) {
pEnv = getenv("BACNET_IFACE");
if (Datalink_Debug) {
fprintf(stderr, "BACNET_IFACE=%s\n", pEnv ? pEnv : "none");
}
if (!datalink_init(pEnv)) {
exit(1);
}
#if (MAX_TSM_TRANSACTIONS)
+2 -3
View File
@@ -573,10 +573,8 @@ uint8_t dlmstp_max_info_frames(void)
void dlmstp_set_max_master(uint8_t max_master)
{
if (max_master <= 127) {
if (MSTP_Port->This_Station <= max_master) {
MSTP_Port->Nmax_master = max_master;
}
}
return;
}
@@ -957,7 +955,8 @@ void dlmstp_fill_statistics(struct dlmstp_statistics *statistics)
return;
}
if (statistics) {
*statistics = user->Statistics;
memmove(
statistics, &user->Statistics, sizeof(struct dlmstp_statistics));
}
}