From 5c6f263a16d83b2d45dad9dca79a4ba59cb84e21 Mon Sep 17 00:00:00 2001 From: skarg Date: Wed, 20 Aug 2008 22:17:43 +0000 Subject: [PATCH] Added I-Am-Router-To-Network demo. Untested. --- bacnet-stack/Makefile | 12 +- bacnet-stack/demo/handler/s_router.c | 161 ++++++++++++++++++++++++--- bacnet-stack/demo/whoisrouter/main.c | 43 +------ bacnet-stack/include/client.h | 4 +- bacnet-stack/include/npdu.h | 10 ++ bacnet-stack/src/npdu.c | 9 +- 6 files changed, 175 insertions(+), 64 deletions(-) diff --git a/bacnet-stack/Makefile b/bacnet-stack/Makefile index 2d5517c2..67a036c4 100644 --- a/bacnet-stack/Makefile +++ b/bacnet-stack/Makefile @@ -1,5 +1,6 @@ all: library readprop writeprop readfile writefile reinit server dcc \ - whohas whois whoisrouter ucov timesync epics mstpcap + whohas whois ucov timesync epics mstpcap \ + whoisrouter iamrouter @echo "utilities are in the bin directory" clean: lib/Makefile\ @@ -72,9 +73,12 @@ ucov: demo/ucov/Makefile whois: demo/whois/Makefile ( cd demo/whois ; make ; cp bacwi ../../bin ) -whoisrouter: demo/whoisrouter/Makefile - ( cd demo/whoisrouter ; make ; cp bacwir ../../bin ) - mstpcap: demo/mstpcap/Makefile ( cd demo/mstpcap ; make clean all; cp mstpcap ../../bin ) +whoisrouter: demo/whoisrouter/Makefile + ( cd demo/whoisrouter ; make ; cp bacwir ../../bin ) + +iamrouter: demo/iamrouter/Makefile + ( cd demo/iamrouter ; make ; cp baciamr ../../bin ) + diff --git a/bacnet-stack/demo/handler/s_router.c b/bacnet-stack/demo/handler/s_router.c index 50908370..0db6f548 100644 --- a/bacnet-stack/demo/handler/s_router.c +++ b/bacnet-stack/demo/handler/s_router.c @@ -41,8 +41,24 @@ #include "handlers.h" #include "txbuf.h" -/* find a specific device, or use -1 for limit if you want unlimited */ -void Send_WhoIsRouterToNetwork( +static void npdu_encode_npdu_network( + BACNET_NPDU_DATA * npdu_data, + BACNET_NETWORK_MESSAGE_TYPE network_message_type, + BACNET_MESSAGE_PRIORITY priority) +{ + if (npdu_data) { + npdu_data->data_expecting_reply = false; + npdu_data->protocol_version = BACNET_PROTOCOL_VERSION; + npdu_data->network_layer_message = true; /* false if APDU */ + npdu_data->network_message_type = network_message_type; /* optional */ + npdu_data->vendor_id = 0; /* optional, if net message type is > 0x80 */ + npdu_data->priority = priority; + npdu_data->hop_count = 255; + } +} + +/* find a specific router, or use -1 for limit if you want unlimited */ +void Send_Who_Is_Router_To_Network( int dnet) { int len = 0; @@ -51,14 +67,9 @@ void Send_WhoIsRouterToNetwork( int bytes_sent = 0; BACNET_NPDU_DATA npdu_data; - /* encode the NPDU portion of the packet */ - npdu_data.data_expecting_reply = false; - npdu_data.protocol_version = BACNET_PROTOCOL_VERSION; - npdu_data.network_layer_message = true; /* false if APDU */ - npdu_data.network_message_type = NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK; - npdu_data.vendor_id = 0; /* optional, if net message type is > 0x80 */ - npdu_data.priority = MESSAGE_PRIORITY_NORMAL; - npdu_data.hop_count = 0; + npdu_encode_npdu_network(&npdu_data, + NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK, + MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data); /* encode the optional DNET portion of the packet */ @@ -66,14 +77,14 @@ void Send_WhoIsRouterToNetwork( len = encode_unsigned16(&Handler_Transmit_Buffer[pdu_len], dnet); pdu_len += len; #if PRINT_ENABLED - fprintf(stderr, "Send Who-Is-Router-To-Network Request to %u\n",dnet); + fprintf(stderr, "Send Who-Is-Router-To-Network message to %u\n",dnet); #endif } else { #if PRINT_ENABLED - fprintf(stderr, "Send Who-Is-Router-To-Network Request\n"); + fprintf(stderr, "Send Who-Is-Router-To-Network message\n"); #endif } - /* Who-Is-Router-To-Network is a global broadcast */ + /* Who-Is-Router-To-Network may be unicast or broadcast */ datalink_get_broadcast_address(&dest); bytes_sent = datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0], @@ -84,3 +95,127 @@ void Send_WhoIsRouterToNetwork( strerror(errno)); #endif } + +/* pDNET_list: list of networks for which I am a router, + terminated with -1 */ +void Send_I_Am_Router_To_Network( + const int *pDNET_list) +{ + int len = 0; + int pdu_len = 0; + BACNET_ADDRESS dest; + int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; + uint16_t dnet = 0; + + npdu_encode_npdu_network(&npdu_data, + NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK, + MESSAGE_PRIORITY_NORMAL); + pdu_len = + npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data); + /* encode the optional DNET list portion of the packet */ +#if PRINT_ENABLED + fprintf(stderr, "Send I-Am-Router-To-Network message to:\n"); +#endif + while ((*pDNET_list) != -1) { + dnet = (*pDNET_list); + len = encode_unsigned16(&Handler_Transmit_Buffer[pdu_len], dnet); + pdu_len += len; + pDNET_list++; +#if PRINT_ENABLED + fprintf(stderr, "%u\n",dnet); +#endif + } + /* I-Am-Router-To-Network shall always be transmitted with + a broadcast MAC address. */ + datalink_get_broadcast_address(&dest); + bytes_sent = + datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0], + pdu_len); +#if PRINT_ENABLED + if (bytes_sent <= 0) + fprintf(stderr, "Failed to send I-Am-Router-To-Network message (%s)!\n", + strerror(errno)); +#endif +} + +/* */ +void Send_Initialize_Routing_Table( + BACNET_ROUTER_PORT *router_port_list) +{ + int len = 0; + int pdu_len = 0; + BACNET_ADDRESS dest; + int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; + uint8_t number_of_ports = 0; + BACNET_ROUTER_PORT *router_port; + unsigned i = 0; /* counter */ + + npdu_encode_npdu_network(&npdu_data, + NETWORK_MESSAGE_INIT_RT_TABLE, + MESSAGE_PRIORITY_NORMAL); + pdu_len = + npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data); + /* encode the optional port_info list portion of the packet */ + router_port = router_port_list; + while (router_port) { + number_of_ports++; + router_port = router_port->next; + } + Handler_Transmit_Buffer[pdu_len++] = number_of_ports; + if (number_of_ports) { + router_port = router_port_list; + while (router_port) { + len = encode_unsigned16( + &Handler_Transmit_Buffer[pdu_len], + router_port->dnet); + pdu_len += len; + Handler_Transmit_Buffer[pdu_len++] = router_port->id; + Handler_Transmit_Buffer[pdu_len++] = router_port->info_len; + for (i = 0; i < router_port->info_len; i++) { + Handler_Transmit_Buffer[pdu_len++] = router_port->info[i]; + } + router_port = router_port->next; + } + } + /* Init Routing Table shall always be transmitted with + a broadcast MAC address. */ + datalink_get_broadcast_address(&dest); + bytes_sent = + datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0], + pdu_len); +#if PRINT_ENABLED + if (bytes_sent <= 0) + fprintf(stderr, "Failed to send Initialize-Routing-Table message (%s)!\n", + strerror(errno)); +#endif +} + +/* */ +void Send_Initialize_Routing_Table_Ack( + const int *port_info) +{ + int len = 0; + int pdu_len = 0; + BACNET_ADDRESS dest; + int bytes_sent = 0; + BACNET_NPDU_DATA npdu_data; + uint16_t dnet = 0; + + npdu_encode_npdu_network(&npdu_data, + NETWORK_MESSAGE_INIT_RT_TABLE_ACK, + MESSAGE_PRIORITY_NORMAL); + pdu_len = + npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data); + /* encode the optional DNET list portion of the packet */ + datalink_get_broadcast_address(&dest); + bytes_sent = + datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0], + pdu_len); +#if PRINT_ENABLED + if (bytes_sent <= 0) + fprintf(stderr, "Failed to Send I-Am-Router-To-Network message (%s)!\n", + strerror(errno)); +#endif +} diff --git a/bacnet-stack/demo/whoisrouter/main.c b/bacnet-stack/demo/whoisrouter/main.c index 56720afd..46b3ec81 100644 --- a/bacnet-stack/demo/whoisrouter/main.c +++ b/bacnet-stack/demo/whoisrouter/main.c @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (C) 2006 Steve Karg +* Copyright (C) 2008 Steve Karg * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -102,44 +102,6 @@ static void Init_Service_Handlers( apdu_set_reject_handler(MyRejectHandler); } -static void print_address_cache( - void) -{ - int i, j; - BACNET_ADDRESS address; - uint32_t device_id = 0; - unsigned max_apdu = 0; - - printf("%-7s %-14s %-4s %-5s %-14s\n", "Device", "MAC", "APDU", "SNET", - "SADR"); - printf("------- -------------- ---- ----- --------------\n"); - for (i = 0; i < MAX_ADDRESS_CACHE; i++) { - if (address_get_by_index(i, &device_id, &max_apdu, &address)) { - printf("%7u ", device_id); - for (j = 0; j < 7; j++) { - if (j < address.mac_len) { - printf("%02X", address.mac[j]); - } else { - printf(" "); - } - } - printf(" %4hu ", max_apdu); - printf("%5hu ", address.net); - if (address.net) { - for (j = 0; j < 7; j++) { - if (j < address.len) { - printf("%02X", address.adr[j]); - } else { - printf(" "); - } - printf(" "); - } - } - printf("\n"); - } - } -} - static void Init_DataLink( void) { @@ -274,7 +236,7 @@ int main(int argc, char *argv[]) { last_seconds = time(NULL); timeout_seconds = apdu_timeout() / 1000; /* send the request */ - Send_WhoIsRouterToNetwork(Target_Router_Network); + Send_Who_Is_Router_To_Network(Target_Router_Network); /* loop forever */ for (;;) { /* increment timer - exit if timed out */ @@ -300,7 +262,6 @@ int main(int argc, char *argv[]) { /* keep track of time for next check */ last_seconds = current_seconds; } - print_address_cache(); return 0; } diff --git a/bacnet-stack/include/client.h b/bacnet-stack/include/client.h index 06fb15ce..bfc50061 100644 --- a/bacnet-stack/include/client.h +++ b/bacnet-stack/include/client.h @@ -108,9 +108,9 @@ extern "C" { int fileStartPosition, BACNET_OCTET_STRING * fileData); - void Send_WhoIsRouterToNetwork( + void Send_Who_Is_Router_To_Network( int dnet); - + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bacnet-stack/include/npdu.h b/bacnet-stack/include/npdu.h index 3da5ec42..0abb9f6d 100644 --- a/bacnet-stack/include/npdu.h +++ b/bacnet-stack/include/npdu.h @@ -52,6 +52,16 @@ typedef struct bacnet_npdu_data_t { uint8_t hop_count; } BACNET_NPDU_DATA; +/* Port Info structure used by Routers */ +struct router_port_t; +typedef struct router_port_t { + uint16_t dnet; + uint8_t id; + uint8_t info[256]; /* size could be 1-255 */ + uint8_t info_len; + struct router_port_t *next; /* linked list */ +} BACNET_ROUTER_PORT; + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ diff --git a/bacnet-stack/src/npdu.c b/bacnet-stack/src/npdu.c index 7b48a5e4..a8069305 100644 --- a/bacnet-stack/src/npdu.c +++ b/bacnet-stack/src/npdu.c @@ -182,7 +182,7 @@ int npdu_encode_pdu( /* destined for a remote network, i.e., if DNET is present. */ /* This is a one-octet field that is initialized to a value of 0xff. */ if (dest && dest->net) { - npdu[len] = 0xFF; + npdu[len] = npdu_data->hop_count; len++; } if (npdu_data->network_layer_message) { @@ -243,7 +243,7 @@ void npdu_encode_npdu_data( npdu_data->network_message_type = NETWORK_MESSAGE_INVALID; /* optional */ npdu_data->vendor_id = 0; /* optional, if net message type is > 0x80 */ npdu_data->priority = priority; - npdu_data->hop_count = 0; + npdu_data->hop_count = 255; } } @@ -349,10 +349,11 @@ int npdu_decode( /* The Hop Count field shall be present only if the message is */ /* destined for a remote network, i.e., if DNET is present. */ /* This is a one-octet field that is initialized to a value of 0xff. */ - if (dest_net) + if (dest_net) { npdu_data->hop_count = npdu[len++]; - else + } else { npdu_data->hop_count = 0; + } /* Indicates that the NSDU conveys a network layer message. */ /* Message Type field is present. */ if (npdu_data->network_layer_message) {