improve router-mstp app usage (#470)
* improve router-mstp app usage * add router-mstp app environment shell script --------- Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
+55
-21
@@ -35,6 +35,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "bacnet/bacdef.h"
|
#include "bacnet/bacdef.h"
|
||||||
#include "bacnet/config.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)];
|
static uint8_t Tx_Buffer[MAX(DLMSTP_MPDU_MAX, BIP_MPDU_MAX)];
|
||||||
/* main loop exit control */
|
/* main loop exit control */
|
||||||
static bool Exit_Requested;
|
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
|
* Search the router table to find a matching DNET entry
|
||||||
@@ -289,7 +313,7 @@ static void dnet_cleanup(DNET *dnets)
|
|||||||
{
|
{
|
||||||
DNET *dnet = dnets;
|
DNET *dnet = dnets;
|
||||||
while (dnet != NULL) {
|
while (dnet != NULL) {
|
||||||
debug_printf("DNET %u removed\n", (unsigned)dnet->net);
|
log_printf("DNET %u removed\n", (unsigned)dnet->net);
|
||||||
dnet = dnet->next;
|
dnet = dnet->next;
|
||||||
free(dnets);
|
free(dnets);
|
||||||
dnets = dnet;
|
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 snet - network number of the directly connected port to send
|
||||||
* @param dest - address to where packet is sent
|
* @param dest - address to where packet is sent
|
||||||
@@ -332,14 +356,14 @@ static int datalink_send_pdu(uint16_t snet,
|
|||||||
int bytes_sent = 0;
|
int bytes_sent = 0;
|
||||||
|
|
||||||
if (snet == 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 = bip_send_pdu(dest, npdu_data, pdu, pdu_len);
|
||||||
bytes_sent = dlmstp_send_pdu(dest, npdu_data, pdu, pdu_len);
|
bytes_sent = dlmstp_send_pdu(dest, npdu_data, pdu, pdu_len);
|
||||||
} else if (snet == BIP_Net) {
|
} 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);
|
bytes_sent = bip_send_pdu(dest, npdu_data, pdu, pdu_len);
|
||||||
} else if (snet == MSTP_Net) {
|
} 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);
|
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);
|
len = encode_unsigned16(&Tx_Buffer[pdu_len], net);
|
||||||
pdu_len += len;
|
pdu_len += len;
|
||||||
} else {
|
} else {
|
||||||
debug_printf("I-Am-Router-To-Network ");
|
log_printf("I-Am-Router-To-Network ");
|
||||||
/* Each router shall broadcast out each port
|
/* Each router shall broadcast out each port
|
||||||
an I-Am-Router-To-Network message containing the network
|
an I-Am-Router-To-Network message containing the network
|
||||||
numbers of each accessible network except the networks
|
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;
|
port = Router_Table_Head;
|
||||||
while (port != NULL) {
|
while (port != NULL) {
|
||||||
if (port->net != snet) {
|
if (port->net != snet) {
|
||||||
debug_printf("%u,", port->net);
|
log_printf("%u,", port->net);
|
||||||
len = encode_unsigned16(&Tx_Buffer[pdu_len], port->net);
|
len = encode_unsigned16(&Tx_Buffer[pdu_len], port->net);
|
||||||
pdu_len += len;
|
pdu_len += len;
|
||||||
dnet = port->dnets;
|
dnet = port->dnets;
|
||||||
while (dnet != NULL) {
|
while (dnet != NULL) {
|
||||||
debug_printf("%u,", dnet->net);
|
log_printf("%u,", dnet->net);
|
||||||
len = encode_unsigned16(&Tx_Buffer[pdu_len], dnet->net);
|
len = encode_unsigned16(&Tx_Buffer[pdu_len], dnet->net);
|
||||||
pdu_len += len;
|
pdu_len += len;
|
||||||
dnet = dnet->next;
|
dnet = dnet->next;
|
||||||
@@ -400,7 +424,7 @@ static void send_i_am_router_to_network(uint16_t snet, uint16_t net)
|
|||||||
}
|
}
|
||||||
port = port->next;
|
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);
|
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 network = 0;
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
|
|
||||||
|
(void)src;
|
||||||
|
(void)npdu_data;
|
||||||
if (npdu) {
|
if (npdu) {
|
||||||
if (npdu_len >= 2) {
|
if (npdu_len >= 2) {
|
||||||
len += decode_unsigned16(&npdu[len], &network);
|
len += decode_unsigned16(&npdu[len], &network);
|
||||||
@@ -652,6 +678,8 @@ static void network_control_handler(uint16_t snet,
|
|||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
const char *msg_name = NULL;
|
const char *msg_name = NULL;
|
||||||
|
|
||||||
|
(void)src;
|
||||||
|
(void)npdu_data;
|
||||||
msg_name = bactext_network_layer_msg_name(npdu_data->network_message_type);
|
msg_name = bactext_network_layer_msg_name(npdu_data->network_message_type);
|
||||||
fprintf(stderr, "Received %s\n", msg_name);
|
fprintf(stderr, "Received %s\n", msg_name);
|
||||||
switch (npdu_data->network_message_type) {
|
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);
|
npdu_encode_pdu(&Tx_Buffer[0], &local_dest, &router_src, npdu);
|
||||||
memmove(&Tx_Buffer[npdu_len], apdu, apdu_len);
|
memmove(&Tx_Buffer[npdu_len], apdu, apdu_len);
|
||||||
/* send to my other ports */
|
/* 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;
|
port = Router_Table_Head;
|
||||||
while (port != NULL) {
|
while (port != NULL) {
|
||||||
if (port->net != snet) {
|
if (port->net != snet) {
|
||||||
@@ -866,7 +894,7 @@ static void routed_apdu_handler(uint16_t snet,
|
|||||||
port = dnet_find(dest->net, &remote_dest);
|
port = dnet_find(dest->net, &remote_dest);
|
||||||
if (port) {
|
if (port) {
|
||||||
if (port->net == dest->net) {
|
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
|
/* Case 1: the router is directly
|
||||||
connected to the network referred to by DNET. */
|
connected to the network referred to by DNET. */
|
||||||
/* In the first case, DNET, DADR, and Hop
|
/* 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],
|
datalink_send_pdu(port->net, &local_dest, npdu, &Tx_Buffer[0],
|
||||||
npdu_len + apdu_len);
|
npdu_len + apdu_len);
|
||||||
} else {
|
} else {
|
||||||
debug_printf(
|
log_printf(
|
||||||
"Routing to another Router %u\n", (unsigned)remote_dest.net);
|
"Routing to another Router %u\n", (unsigned)remote_dest.net);
|
||||||
/* Case 2: the message must be
|
/* Case 2: the message must be
|
||||||
relayed to another router for further transmission */
|
relayed to another router for further transmission */
|
||||||
@@ -903,7 +931,7 @@ static void routed_apdu_handler(uint16_t snet,
|
|||||||
npdu_len + apdu_len);
|
npdu_len + apdu_len);
|
||||||
}
|
}
|
||||||
} else if (dest->net) {
|
} 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. */
|
/* Case 3: a global broadcast is required. */
|
||||||
dest->mac_len = 0;
|
dest->mac_len = 0;
|
||||||
npdu->hop_count--;
|
npdu->hop_count--;
|
||||||
@@ -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)
|
static void datalink_init(void)
|
||||||
{
|
{
|
||||||
char *pEnv = NULL;
|
char *pEnv = NULL;
|
||||||
BACNET_ADDRESS my_address = { 0 };
|
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 */
|
/* BACnet/IP Initialization */
|
||||||
bip_debug_enable();
|
|
||||||
pEnv = getenv("BACNET_IP_PORT");
|
pEnv = getenv("BACNET_IP_PORT");
|
||||||
if (pEnv) {
|
if (pEnv) {
|
||||||
bip_set_port((uint16_t)strtol(pEnv, NULL, 0));
|
bip_set_port((uint16_t)strtol(pEnv, NULL, 0));
|
||||||
@@ -1138,7 +1173,6 @@ static void control_c_hooks(void)
|
|||||||
|
|
||||||
|
|
||||||
#ifndef FUZZING
|
#ifndef FUZZING
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main function of simple router demo.
|
* Main function of simple router demo.
|
||||||
*
|
*
|
||||||
@@ -1154,6 +1188,8 @@ int main(int argc, char *argv[])
|
|||||||
time_t current_seconds = 0;
|
time_t current_seconds = 0;
|
||||||
uint32_t elapsed_seconds = 0;
|
uint32_t elapsed_seconds = 0;
|
||||||
|
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
printf("BACnet Simple MS/TP to IP Router Demo\n");
|
printf("BACnet Simple MS/TP to IP Router Demo\n");
|
||||||
printf("BACnet Stack Version %s\n", BACnet_Version);
|
printf("BACnet Stack Version %s\n", BACnet_Version);
|
||||||
datalink_init();
|
datalink_init();
|
||||||
@@ -1175,7 +1211,7 @@ int main(int argc, char *argv[])
|
|||||||
bip_receive(&src, &BIP_Rx_Buffer[0], sizeof(BIP_Rx_Buffer), 5);
|
bip_receive(&src, &BIP_Rx_Buffer[0], sizeof(BIP_Rx_Buffer), 5);
|
||||||
/* process */
|
/* process */
|
||||||
if (pdu_len) {
|
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);
|
my_routing_npdu_handler(BIP_Net, &src, &BIP_Rx_Buffer[0], pdu_len);
|
||||||
}
|
}
|
||||||
/* returns 0 bytes on timeout */
|
/* 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);
|
dlmstp_receive(&src, &MSTP_Rx_Buffer[0], sizeof(MSTP_Rx_Buffer), 5);
|
||||||
/* process */
|
/* process */
|
||||||
if (pdu_len) {
|
if (pdu_len) {
|
||||||
debug_printf("BACnet MS/TP Received packet\n");
|
log_printf("BACnet MS/TP Received packet\n");
|
||||||
my_routing_npdu_handler(
|
my_routing_npdu_handler(
|
||||||
MSTP_Net, &src, &MSTP_Rx_Buffer[0], pdu_len);
|
MSTP_Net, &src, &MSTP_Rx_Buffer[0], pdu_len);
|
||||||
}
|
}
|
||||||
@@ -1202,6 +1238,4 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // FUZZING
|
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ BACnet Simple Router Demo
|
|||||||
=========================
|
=========================
|
||||||
|
|
||||||
The Simple Router demo connects one BACnet/IP and one BACnet MS/TP network.
|
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
|
The router demo also includes a BBMD so that Foreign Device Registration can
|
||||||
to tunnel local command line demos to BACnet/IP and BACnet MS/TP networks.
|
be used to tunnel local command line demos to BACnet/IP and BACnet MS/TP
|
||||||
|
networks.
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
=============
|
=============
|
||||||
@@ -32,3 +33,19 @@ set BACNET_IP_NET=1
|
|||||||
set BACNET_MSTP_NET=2
|
set BACNET_MSTP_NET=2
|
||||||
|
|
||||||
Note: NET number must be unique and 1..65534 (never 0 or 65535)
|
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
|
||||||
|
|||||||
Executable
BIN
Binary file not shown.
Executable
+53
@@ -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
|
||||||
Reference in New Issue
Block a user