diff --git a/apps/router-mstp/main.c b/apps/router-mstp/main.c index f161a7fd..8c018915 100644 --- a/apps/router-mstp/main.c +++ b/apps/router-mstp/main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "bacnet/bacdef.h" #include "bacnet/config.h" @@ -102,6 +103,29 @@ static uint8_t MSTP_Rx_Buffer[DLMSTP_MPDU_MAX]; static uint8_t Tx_Buffer[MAX(DLMSTP_MPDU_MAX, BIP_MPDU_MAX)]; /* main loop exit control */ static bool Exit_Requested; +/* debugging info */ +static bool Debug_Enabled; + +/** + * @brief print debug info if debug is enabled + * @param format - printf format string + * @param ... variable arguments + * @return number of bytes printed + */ +static int log_printf(const char *format, ...) +{ + int length = 0; + va_list ap; + + if (Debug_Enabled) { + va_start(ap, format); + length = vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); + } + + return length; +} /** * Search the router table to find a matching DNET entry @@ -289,7 +313,7 @@ static void dnet_cleanup(DNET *dnets) { DNET *dnet = dnets; while (dnet != NULL) { - debug_printf("DNET %u removed\n", (unsigned)dnet->net); + log_printf("DNET %u removed\n", (unsigned)dnet->net); dnet = dnet->next; free(dnets); dnets = dnet; @@ -313,7 +337,7 @@ static void datalink_get_broadcast_address(BACNET_ADDRESS *dest) } /** - * function to send a packet out the BACnet/IP and BACnet/IPv6 ports + * function to send a packet out the BACnet/IP and BACnet MSTP ports * * @param snet - network number of the directly connected port to send * @param dest - address to where packet is sent @@ -332,14 +356,14 @@ static int datalink_send_pdu(uint16_t snet, int bytes_sent = 0; if (snet == 0) { - debug_printf("BVLC & MS/TP Send to DNET %u\n", (unsigned)dest->net); + log_printf("BVLC & MS/TP Send to DNET %u\n", (unsigned)dest->net); bytes_sent = bip_send_pdu(dest, npdu_data, pdu, pdu_len); bytes_sent = dlmstp_send_pdu(dest, npdu_data, pdu, pdu_len); } else if (snet == BIP_Net) { - debug_printf("BVLC Send to DNET %u\n", (unsigned)dest->net); + log_printf("BVLC Send to DNET %u\n", (unsigned)dest->net); bytes_sent = bip_send_pdu(dest, npdu_data, pdu, pdu_len); } else if (snet == MSTP_Net) { - debug_printf("MS/TP Send to DNET %u\n", (unsigned)dest->net); + log_printf("MS/TP Send to DNET %u\n", (unsigned)dest->net); bytes_sent = dlmstp_send_pdu(dest, npdu_data, pdu, pdu_len); } @@ -376,7 +400,7 @@ static void send_i_am_router_to_network(uint16_t snet, uint16_t net) len = encode_unsigned16(&Tx_Buffer[pdu_len], net); pdu_len += len; } else { - debug_printf("I-Am-Router-To-Network "); + log_printf("I-Am-Router-To-Network "); /* Each router shall broadcast out each port an I-Am-Router-To-Network message containing the network numbers of each accessible network except the networks @@ -387,12 +411,12 @@ static void send_i_am_router_to_network(uint16_t snet, uint16_t net) port = Router_Table_Head; while (port != NULL) { if (port->net != snet) { - debug_printf("%u,", port->net); + log_printf("%u,", port->net); len = encode_unsigned16(&Tx_Buffer[pdu_len], port->net); pdu_len += len; dnet = port->dnets; while (dnet != NULL) { - debug_printf("%u,", dnet->net); + log_printf("%u,", dnet->net); len = encode_unsigned16(&Tx_Buffer[pdu_len], dnet->net); pdu_len += len; dnet = dnet->next; @@ -400,7 +424,7 @@ static void send_i_am_router_to_network(uint16_t snet, uint16_t net) } port = port->next; } - debug_printf("from %u\n", snet); + log_printf("from %u\n", snet); } datalink_send_pdu(snet, &dest, &npdu_data, &Tx_Buffer[0], pdu_len); } @@ -600,6 +624,8 @@ static void who_is_router_to_network_handler(uint16_t snet, uint16_t network = 0; uint16_t len = 0; + (void)src; + (void)npdu_data; if (npdu) { if (npdu_len >= 2) { len += decode_unsigned16(&npdu[len], &network); @@ -652,6 +678,8 @@ static void network_control_handler(uint16_t snet, uint16_t len = 0; const char *msg_name = NULL; + (void)src; + (void)npdu_data; msg_name = bactext_network_layer_msg_name(npdu_data->network_message_type); fprintf(stderr, "Received %s\n", msg_name); switch (npdu_data->network_message_type) { @@ -852,7 +880,7 @@ static void routed_apdu_handler(uint16_t snet, npdu_encode_pdu(&Tx_Buffer[0], &local_dest, &router_src, npdu); memmove(&Tx_Buffer[npdu_len], apdu, apdu_len); /* send to my other ports */ - debug_printf("Routing a BROADCAST from %u\n", (unsigned)snet); + log_printf("Routing a BROADCAST from %u\n", (unsigned)snet); port = Router_Table_Head; while (port != NULL) { if (port->net != snet) { @@ -866,7 +894,7 @@ static void routed_apdu_handler(uint16_t snet, port = dnet_find(dest->net, &remote_dest); if (port) { if (port->net == dest->net) { - debug_printf("Routing to Port %u\n", (unsigned)dest->net); + log_printf("Routing to Port %u\n", (unsigned)dest->net); /* Case 1: the router is directly connected to the network referred to by DNET. */ /* In the first case, DNET, DADR, and Hop @@ -885,7 +913,7 @@ static void routed_apdu_handler(uint16_t snet, datalink_send_pdu(port->net, &local_dest, npdu, &Tx_Buffer[0], npdu_len + apdu_len); } else { - debug_printf( + log_printf( "Routing to another Router %u\n", (unsigned)remote_dest.net); /* Case 2: the message must be relayed to another router for further transmission */ @@ -903,7 +931,7 @@ static void routed_apdu_handler(uint16_t snet, npdu_len + apdu_len); } } else if (dest->net) { - debug_printf("Routing to Unknown Route %u\n", (unsigned)dest->net); + log_printf("Routing to Unknown Route %u\n", (unsigned)dest->net); /* Case 3: a global broadcast is required. */ dest->mac_len = 0; npdu->hop_count--; @@ -915,7 +943,7 @@ static void routed_apdu_handler(uint16_t snet, port = Router_Table_Head; while (port != NULL) { if (port->net != snet) { - datalink_send_pdu(port->net, dest, npdu, &Tx_Buffer[0], + datalink_send_pdu(port->net, dest, npdu, &Tx_Buffer[0], npdu_len + apdu_len); } port = port->next; @@ -998,15 +1026,22 @@ static void my_routing_npdu_handler( } /** - * Initialize the BACnet/IPv6 and BACnet/IP data links + * Initialize the BACnet MSTP and BACnet/IP data links */ static void datalink_init(void) { char *pEnv = NULL; BACNET_ADDRESS my_address = { 0 }; + pEnv = getenv("BACNET_ROUTER_DEBUG"); + if (pEnv) { + bip_debug_enable(); + Debug_Enabled = true; + log_printf("Debug=enabled\n"); + } else { + fprintf(stderr, "Debug=disabled\n"); + } /* BACnet/IP Initialization */ - bip_debug_enable(); pEnv = getenv("BACNET_IP_PORT"); if (pEnv) { bip_set_port((uint16_t)strtol(pEnv, NULL, 0)); @@ -1138,7 +1173,6 @@ static void control_c_hooks(void) #ifndef FUZZING - /** * Main function of simple router demo. * @@ -1154,6 +1188,8 @@ int main(int argc, char *argv[]) time_t current_seconds = 0; uint32_t elapsed_seconds = 0; + (void)argc; + (void)argv; printf("BACnet Simple MS/TP to IP Router Demo\n"); printf("BACnet Stack Version %s\n", BACnet_Version); datalink_init(); @@ -1175,7 +1211,7 @@ int main(int argc, char *argv[]) bip_receive(&src, &BIP_Rx_Buffer[0], sizeof(BIP_Rx_Buffer), 5); /* process */ if (pdu_len) { - debug_printf("BACnet/IP Received packet\n"); + log_printf("BACnet/IP Received packet\n"); my_routing_npdu_handler(BIP_Net, &src, &BIP_Rx_Buffer[0], pdu_len); } /* returns 0 bytes on timeout */ @@ -1183,7 +1219,7 @@ int main(int argc, char *argv[]) dlmstp_receive(&src, &MSTP_Rx_Buffer[0], sizeof(MSTP_Rx_Buffer), 5); /* process */ if (pdu_len) { - debug_printf("BACnet MS/TP Received packet\n"); + log_printf("BACnet MS/TP Received packet\n"); my_routing_npdu_handler( MSTP_Net, &src, &MSTP_Rx_Buffer[0], pdu_len); } @@ -1202,6 +1238,4 @@ int main(int argc, char *argv[]) return 0; } - - -#endif // FUZZING +#endif diff --git a/apps/router-mstp/readme.txt b/apps/router-mstp/readme.txt index bff0cb8a..6a863101 100644 --- a/apps/router-mstp/readme.txt +++ b/apps/router-mstp/readme.txt @@ -2,8 +2,9 @@ BACnet Simple Router Demo ========================= The Simple Router demo connects one BACnet/IP and one BACnet MS/TP network. -It also includes a BBMD so that Foreign Device Registration can be used -to tunnel local command line demos to BACnet/IP and BACnet MS/TP networks. +The router demo also includes a BBMD so that Foreign Device Registration can +be used to tunnel local command line demos to BACnet/IP and BACnet MS/TP +networks. Configuration ============= @@ -31,4 +32,20 @@ set BACNET_IP_PORT=47808 set BACNET_IP_NET=1 set BACNET_MSTP_NET=2 -Note: NET number must be unique and 1..65534 (never 0 or 65535) \ No newline at end of file +Note: NET number must be unique and 1..65534 (never 0 or 65535) + +Example Usage +============= +Build the demo applications for BACnet/IP: +$ make +Build the simple router demo: +$ make router-mstp +Configure the router demo: +$ ./bin/router-mstp.sh enp0s3 /dev/ttyUSB0 +Run the router demo: +$ ./bin/router-mstp + +In another terminal, configure client apps for Foreign Device Registration: +$ ./bin/bvlc.sh 192.168.0.1 +$ ./bin/bacwi -1 +$ ./bin/bacepics 123 diff --git a/apps/router-mstp/router-mstp b/apps/router-mstp/router-mstp new file mode 100755 index 00000000..d0574b9a Binary files /dev/null and b/apps/router-mstp/router-mstp differ diff --git a/bin/router-mstp.sh b/bin/router-mstp.sh new file mode 100755 index 00000000..ac496f38 --- /dev/null +++ b/bin/router-mstp.sh @@ -0,0 +1,53 @@ +#!/bin/bash +echo Setting parameters for BACnet/IP to MSTP Router + +# BACnet/IP configuration +BACNET_IFACE=${1} +export BACNET_IFACE +echo "BACNET_IFACE=$BACNET_IFACE" + +BACNET_IP_PORT=47808 +export BACNET_IP_PORT +echo "BACNET_IP_PORT=$BACNET_IP_PORT" + +# BBMD port for local apps +BACNET_BBMD_PORT=47809 +export BACNET_BBMD_PORT +echo "BACNET_BBMD_PORT=$BACNET_BBMD_PORT" + +# BACnet MSTP settings +BACNET_MSTP_IFACE=${2} +export BACNET_MSTP_IFACE +echo "BACNET_MSTP_IFACE=$BACNET_MSTP_IFACE" + +BACNET_MSTP_BAUD=38400 +export BACNET_MSTP_BAUD +echo "BACNET_MSTP_BAUD=$BACNET_MSTP_BAUD" + +BACNET_MSTP_MAC=1 +export BACNET_MSTP_MAC +echo "BACNET_MSTP_MAC=$BACNET_MSTP_MAC" + +BACNET_MAX_INFO_FRAMES=128 +export BACNET_MAX_INFO_FRAMES +echo "BACNET_MAX_INFO_FRAMES=$BACNET_MAX_INFO_FRAMES" + +BACNET_MAX_MASTER=127 +export BACNET_MAX_MASTER +echo "BACNET_MAX_MASTER=$BACNET_MAX_MASTER" + +# Network Numbers +BACNET_IP_NET=1 +export BACNET_IP_NET +echo "BACNET_IP_NET=$BACNET_IP_NET" + +BACNET_MSTP_NET=2 +export BACNET_MSTP_NET +echo "BACNET_MSTP_NET=$BACNET_MSTP_NET" + +BACNET_ROUTER_DEBUG=1 +export BACNET_ROUTER_DEBUG +echo "BACNET_ROUTER_DEBUG=$BACNET_ROUTER_DEBUG" + +echo Launching new shell using the BACnet Router environment... +/bin/bash \ No newline at end of file