Bugfix/network port object bdt required (#184)

* Added BDT encoding to network port object.

* Added BDT encoding rules from clause 21

* Added FDT encoding to network port object.

* added more unit tests for BVLC

* Fix network port and device object unit tests

* fix router build for bvlc dependencies

* fix router build for bvlc dependencies

* fix network port MSTP compile

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
Co-authored-by: Steve Karg <steve.karg@legrand.us>
This commit is contained in:
Steve Karg
2021-08-03 09:55:01 -05:00
committed by GitHub
parent 9acca32ba8
commit 541f4024fb
12 changed files with 591 additions and 23 deletions
+3
View File
@@ -35,7 +35,10 @@ SRCS = main.c \
${BACNET_SOURCE_DIR}/indtext.c \
${BACNET_SOURCE_DIR}/basic/sys/ringbuf.c \
${BACNET_SOURCE_DIR}/datalink/crc.c \
${BACNET_SOURCE_DIR}/bacdcode.c \
${BACNET_SOURCE_DIR}/bacint.c \
${BACNET_SOURCE_DIR}/bacreal.c \
${BACNET_SOURCE_DIR}/bacstr.c \
${BACNET_SOURCE_DIR}/npdu.c \
${BACNET_SOURCE_DIR}/bacaddr.c \
mstpmodule.c \
+9
View File
@@ -1257,6 +1257,15 @@ void bvlc_set_function_code(uint8_t function_code)
}
#if BBMD_ENABLED
/**
* @brief Get handle to foreign device table (FDT).
* @return pointer to first entry of foreign device table
*/
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *bvlc_fdt_list(void)
{
return &FD_Table[0];
}
/**
* @brief Get handle to broadcast distribution table (BDT).
* @return pointer to first entry of broadcast distribution table
+3
View File
@@ -113,6 +113,9 @@ BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bvlc_bdt_list(void);
BACNET_STACK_EXPORT
void bvlc_bdt_list_clear(void);
/* Get foreign device table list */
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *bvlc_fdt_list(void);
/* Backup broadcast distribution table to a file.
* Filename is the BBMD_BACKUP_FILE constant
*/
+129 -10
View File
@@ -44,10 +44,15 @@
#include "bacnet/bacdcode.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/datalink/datalink.h"
#include "bacnet/basic/object/device.h"
/* me */
#include "bacnet/basic/object/netport.h"
#ifndef BBMD_ENABLED
#define BBMD_ENABLED 1
#endif
#define BIP_DNS_MAX 3
struct bacnet_ipv4_port {
uint8_t IP_Address[4];
@@ -63,6 +68,8 @@ struct bacnet_ipv4_port {
bool IP_NAT_Traversal;
uint32_t IP_Global_Address[4];
bool BBMD_Accept_FD_Registrations;
void *BBMD_BD_Table;
void *BBMD_FD_Table;
};
#define IPV6_ADDR_SIZE 16
@@ -128,7 +135,7 @@ static const int MSTP_Port_Properties_Optional[] = { PROP_MAC_ADDRESS,
static const int BIP_Port_Properties_Optional[] = { PROP_MAC_ADDRESS,
PROP_BACNET_IP_MODE, PROP_IP_ADDRESS, PROP_BACNET_IP_UDP_PORT,
PROP_IP_SUBNET_MASK, PROP_IP_DEFAULT_GATEWAY, PROP_IP_DNS_SERVER,
#if defined(BBMD_ENABLED)
#if defined(BACDL_BIP) && BBMD_ENABLED
PROP_BBMD_ACCEPT_FD_REGISTRATIONS, PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE,
PROP_BBMD_FOREIGN_DEVICE_TABLE,
#endif
@@ -1281,6 +1288,113 @@ bool Network_Port_BBMD_Accept_FD_Registrations_Set(
return status;
}
/**
* For a given object instance-number, returns the BBMD-BD-Table head
* property value
*
* @param object_instance - object-instance number of the object
*
* @return BBMD-Accept-FD-Registrations property value
*/
void *Network_Port_BBMD_BD_Table(uint32_t object_instance)
{
void *bdt_head = NULL;
unsigned index = 0;
struct bacnet_ipv4_port *ipv4 = NULL;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
ipv4 = &Object_List[index].Network.IPv4;
bdt_head = ipv4->BBMD_BD_Table;
}
return bdt_head;
}
/**
* For a given object instance-number, sets the BBMD-BD-Table head
* property value
*
* @param object_instance - object-instance number of the object
* @param bdt_head - Broadcast Distribution Table linked list head
*
* @return true if the Broadcast Distribution Table linked list head
* property value was set
*/
bool Network_Port_BBMD_BD_Table_Set(
uint32_t object_instance,
void *bdt_head)
{
bool status = false;
unsigned index = 0;
struct bacnet_ipv4_port *ipv4 = NULL;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
ipv4 = &Object_List[index].Network.IPv4;
if (bdt_head != ipv4->BBMD_BD_Table) {
ipv4->BBMD_BD_Table = bdt_head;
Object_List[index].Changes_Pending = true;
}
status = true;
}
return status;
}
/**
* For a given object instance-number, returns the BBMD-FD-Table head
* property value
*
* @param object_instance - object-instance number of the object
*
* @return BBMD-Accept-FD-Registrations property value
*/
void *Network_Port_BBMD_FD_Table(uint32_t object_instance)
{
void *fdt_head = NULL;
unsigned index = 0;
struct bacnet_ipv4_port *ipv4 = NULL;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
ipv4 = &Object_List[index].Network.IPv4;
fdt_head = ipv4->BBMD_FD_Table;
}
return fdt_head;
}
/**
* For a given object instance-number, sets the BBMD-FD-Table head
* property value
*
* @param object_instance - object-instance number of the object
* @param fdt_head - Foreign Device Table linked list head
*
* @return true if the BBMD-Accept-FD-Registrations property value was set
*/
bool Network_Port_BBMD_FD_Table_Set(
uint32_t object_instance,
void *fdt_head)
{
bool status = false;
unsigned index = 0;
struct bacnet_ipv4_port *ipv4 = NULL;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
ipv4 = &Object_List[index].Network.IPv4;
if (fdt_head != ipv4->BBMD_FD_Table) {
ipv4->BBMD_FD_Table = fdt_head;
Object_List[index].Changes_Pending = true;
}
status = true;
}
return status;
}
/**
* For a given object instance-number, gets the BACnet/IP UDP Port number
* Note: depends on Network_Type being set to PORT_TYPE_BIP for this object
@@ -2003,17 +2117,21 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
apdu_len = BACNET_STATUS_ERROR;
}
break;
#if defined(BBMD_ENABLED)
#if defined(BACDL_BIP) && BBMD_ENABLED
case PROP_BBMD_ACCEPT_FD_REGISTRATIONS:
apdu_len = encode_application_boolean(&apdu[0],
Network_Port_BBMD_Accept_FD_Registrations(
rpdata->object_instance));
break;
case PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE:
apdu_len = bvlc_broadcast_distribution_table_encode(&apdu[0],
rpdata->application_data_len,
Network_Port_BBMD_BD_Table(rpdata->object_instance));
break;
case PROP_BBMD_FOREIGN_DEVICE_TABLE:
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_READ_ACCESS_DENIED;
apdu_len = BACNET_STATUS_ERROR;
apdu_len = bvlc_foreign_device_table_encode(&apdu[0],
rpdata->application_data_len,
Network_Port_BBMD_FD_Table(rpdata->object_instance));
break;
#endif
case PROP_BACNET_IPV6_MODE:
@@ -2258,22 +2376,23 @@ bool Network_Port_Read_Range(
#if defined(BACDL_MSTP)
case PROP_MAX_MASTER:
case PROP_MAX_INFO_FRAMES:
#elif defined(BACDL_BIP)
#endif
#if defined(BACDL_BIP)
case PROP_BACNET_IP_MODE:
case PROP_IP_ADDRESS:
case PROP_BACNET_IP_UDP_PORT:
case PROP_IP_SUBNET_MASK:
case PROP_IP_DEFAULT_GATEWAY:
case PROP_IP_DNS_SERVER:
#if defined(BBMD_ENABLED)
case PROP_BBMD_ACCEPT_FD_REGISTRATIONS:
#endif
#if defined(BACDL_BIP) && BBMD_ENABLED
case PROP_BBMD_ACCEPT_FD_REGISTRATIONS:
#endif
pRequest->error_class = ERROR_CLASS_SERVICES;
pRequest->error_code = ERROR_CODE_PROPERTY_IS_NOT_A_LIST;
break;
case PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE:
#if defined(BACDL_BIP) && defined(BBMD_ENABLED)
#if defined(BACDL_BIP) && BBMD_ENABLED
pInfo->RequestTypes = RR_BY_POSITION;
pInfo->Handler = Network_Port_Read_Range_BDT;
status = true;
@@ -2283,7 +2402,7 @@ bool Network_Port_Read_Range(
#endif
break;
case PROP_BBMD_FOREIGN_DEVICE_TABLE:
#if defined(BACDL_BIP) && defined(BBMD_ENABLED)
#if defined(BACDL_BIP) && BBMD_ENABLED
pInfo->RequestTypes = RR_BY_POSITION;
pInfo->Handler = Network_Port_Read_Range_FDT;
status = true;
+13
View File
@@ -245,6 +245,19 @@ extern "C" {
uint32_t object_instance,
bool value);
BACNET_STACK_EXPORT
void *Network_Port_BBMD_BD_Table(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Network_Port_BBMD_BD_Table_Set(
uint32_t object_instance,
void *bdt_head);
BACNET_STACK_EXPORT
void *Network_Port_BBMD_FD_Table(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Network_Port_BBMD_FD_Table_Set(
uint32_t object_instance,
void *fdt_head);
BACNET_STACK_EXPORT
BACNET_IP_MODE Network_Port_BIP6_Mode(
uint32_t object_instance);
+334
View File
@@ -520,6 +520,217 @@ bool bvlc_broadcast_distribution_table_entry_forward_address(
return status;
}
/**
* @brief Encode the Broadcast-Distribution-Table for Network Port object
*
* BACnetLIST of BACnetBDTEntry
*
* BACnetBDTEntry ::= SEQUENCE {
* bbmd-address [0] BACnetHostNPort,
* BACnetHostNPort ::= SEQUENCE {
* host [0] BACnetHostAddress,
* BACnetHostAddress ::= CHOICE {
* ip-address [1] OCTET STRING, -- 4 octets for B/IP
* }
* port [1] Unsigned16
* }
* broadcast-mask [1] OCTET STRING
* }
*
* @param apdu - the APDU buffer
* @param apdu_size - the APDU buffer size
* @param bdt_head - head of the BDT linked list
* @return length of the APDU buffer
*/
int bvlc_broadcast_distribution_table_encode(uint8_t *apdu,
uint16_t apdu_size,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_head)
{
int len = 0;
int apdu_len = 0;
int entry_size = 0;
BACNET_OCTET_STRING octet_string;
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry;
bdt_entry = bdt_head;
while (bdt_entry) {
if (bdt_entry->valid) {
/* bbmd-address [0] BACnetHostNPort - opening */
len = encode_opening_tag(&apdu[apdu_len], 0);
apdu_len += len;
/* host [0] BACnetHostAddress - opening */
len = encode_opening_tag(&apdu[apdu_len], 0);
apdu_len += len;
/* CHOICE - ip-address [1] OCTET STRING */
octetstring_init(&octet_string,
&bdt_entry->dest_address.address[0], IP_ADDRESS_MAX);
len = encode_context_octet_string(&apdu[apdu_len], 1,
&octet_string);
apdu_len += len;
/* host [0] BACnetHostAddress - closing */
len = encode_closing_tag(&apdu[apdu_len], 0);
apdu_len += len;
/* port [1] Unsigned16 */
len = encode_context_unsigned(
&apdu[apdu_len], 1, bdt_entry->dest_address.port);
apdu_len += len;
/* bbmd-address [0] BACnetHostNPort - closing */
len = encode_closing_tag(&apdu[apdu_len], 0);
apdu_len += len;
/* broadcast-mask [1] OCTET STRING */
octetstring_init(&octet_string,
&bdt_entry->broadcast_mask.address[0], IP_ADDRESS_MAX);
len = encode_context_octet_string(&apdu[apdu_len], 1,
&octet_string);
apdu_len += len;
}
if (!entry_size) {
entry_size = apdu_len;
}
/* next entry */
bdt_entry = bdt_entry->next;
if ((apdu_len + entry_size) > apdu_size) {
/* check for available space */
break;
}
}
return apdu_len;
}
/**
* @brief Decode the Broadcast-Distribution-Table for Network Port object
* @param apdu - the APDU buffer
* @param apdu_len - the APDU buffer length
* @param bdt_head - head of a BDT linked list
* @return length of the APDU buffer decoded, or ERROR, REJECT, or ABORT
*/
int bvlc_broadcast_distribution_table_decode(uint8_t *apdu,
uint16_t apdu_len,
BACNET_ERROR_CODE *error_code,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_head)
{
int len = 0;
BACNET_OCTET_STRING octet_string = { 0 };
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry = NULL;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
BACNET_UNSIGNED_INTEGER unsigned_value = 0;
/* default reject code */
if (error_code) {
*error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
}
/* check for value pointers */
if ((apdu_len == 0) || (!apdu)) {
return BACNET_STATUS_REJECT;
}
bdt_entry = bdt_head;
while (bdt_entry) {
/* bbmd-address [0] BACnetHostNPort - opening */
if (!decode_is_opening_tag_number(&apdu[len++], 0)) {
if (error_code) {
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
}
return BACNET_STATUS_REJECT;
}
if (len > apdu_len) {
return BACNET_STATUS_REJECT;
}
/* host [0] BACnetHostAddress - opening */
if (!decode_is_opening_tag_number(&apdu[len++], 0)) {
if (error_code) {
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
}
return BACNET_STATUS_REJECT;
}
if (len > apdu_len) {
return BACNET_STATUS_REJECT;
}
/* CHOICE - ip-address [1] OCTET STRING */
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value_type);
if (tag_number != 1) {
if (error_code) {
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
}
return BACNET_STATUS_REJECT;
}
len += decode_octet_string(&apdu[len], len_value_type,
&octet_string);
if (len > apdu_len) {
return BACNET_STATUS_REJECT;
}
octetstring_copy_value(&bdt_entry->dest_address.address[0],
IP_ADDRESS_MAX, &octet_string);
/* host [0] BACnetHostAddress - closing */
if (!decode_is_closing_tag_number(&apdu[len++], 0)) {
if (error_code) {
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
}
return BACNET_STATUS_REJECT;
}
if (len > apdu_len) {
return BACNET_STATUS_REJECT;
}
/* port [1] Unsigned16 */
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value_type);
if (tag_number != 1) {
if (error_code) {
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
}
return BACNET_STATUS_REJECT;
}
len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
if (len > apdu_len) {
return BACNET_STATUS_REJECT;
}
if (unsigned_value <= UINT16_MAX) {
bdt_entry->dest_address.port = unsigned_value;
} else {
if (error_code) {
*error_code = ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE;
}
return BACNET_STATUS_REJECT;
}
/* bbmd-address [0] BACnetHostNPort - closing */
if (!decode_is_closing_tag_number(&apdu[len++], 0)) {
if (error_code) {
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
}
return BACNET_STATUS_REJECT;
}
if (len > apdu_len) {
return BACNET_STATUS_REJECT;
}
/* broadcast-mask [1] OCTET STRING */
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value_type);
if (tag_number != 1) {
if (error_code) {
*error_code = ERROR_CODE_REJECT_INVALID_TAG;
}
return BACNET_STATUS_REJECT;
}
if (len > apdu_len) {
return BACNET_STATUS_REJECT;
}
len += decode_octet_string(&apdu[len], len_value_type,
&octet_string);
if (len > apdu_len) {
return BACNET_STATUS_REJECT;
}
octetstring_copy_value(&bdt_entry->broadcast_mask.address[0],
IP_ADDRESS_MAX, &octet_string);
bdt_entry->valid = true;
/* next entry */
bdt_entry = bdt_entry->next;
}
return apdu_len;
}
/**
* @brief J.2.2 Write-Broadcast-Distribution-Table: encode
*
@@ -906,6 +1117,69 @@ int bvlc_decode_register_foreign_device(
return bytes_consumed;
}
/**
* @brief Encode the Foreign_Device-Table for Network Port object
*
* BACnetLIST of BACnetFDTEntry
*
* BACnetFDTEntry ::= SEQUENCE {
* bacnetip-address [0] OCTET STRING, -- 6-octet B/IP registrant address
* time-to-live [1] Unsigned16, -- time to live in seconds
* remaining-time-to-live [2] Unsigned16 -- remaining time in seconds
* }
*
* @param apdu - the APDU buffer
* @param apdu_size - the APDU buffer size
* @param fdt_head - head of the BDT linked list
* @return length of the APDU buffer
*/
int bvlc_foreign_device_table_encode(uint8_t *apdu,
uint16_t apdu_size,
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_head)
{
int len = 0;
int apdu_len = 0;
int entry_size = 0;
BACNET_OCTET_STRING octet_string = { 0 };
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_entry;
fdt_entry = fdt_head;
while (fdt_entry) {
if (fdt_entry->valid) {
/* bacnetip-address [0] OCTET STRING */
len = bvlc_encode_address(
octetstring_value(&octet_string),
octetstring_capacity(&octet_string),
&fdt_entry->dest_address);
octetstring_truncate(&octet_string, len);
len = encode_context_octet_string(
&apdu[apdu_len], 0, &octet_string);
apdu_len += len;
/* time-to-live [1] Unsigned16 */
len = encode_context_unsigned(
&apdu[apdu_len], 1, fdt_entry->ttl_seconds);
apdu_len += len;
/* remaining-time-to-live [2] Unsigned16 */
len = encode_context_unsigned(
&apdu[apdu_len], 2, fdt_entry->ttl_seconds_remaining);
apdu_len += len;
}
if (!entry_size) {
entry_size = apdu_len;
}
/* next entry */
fdt_entry = fdt_entry->next;
if ((apdu_len + entry_size) > apdu_size) {
/* check for available space */
break;
}
}
return apdu_len;
}
/**
* @brief J.2.7 Read-Foreign-Device-Table: encode
*
@@ -2806,6 +3080,63 @@ static void test_BVLC_Write_Broadcast_Distribution_Table_Message(Test *pTest,
}
}
static void test_BVLC_Broadcast_Distribution_Table_Encode(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint16_t apdu_len = 0;
uint16_t test_apdu_len = 0;
uint16_t i = 0;
uint16_t count = 0;
uint16_t test_count = 0;
bool status = false;
BACNET_ERROR_CODE error_code;
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY bdt_list[5] = { 0 };
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY bdt_entry = { 0 };
BACNET_IP_ADDRESS dest_address = { 0 };
BACNET_IP_BROADCAST_DISTRIBUTION_MASK broadcast_mask = { 0 };
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY test_bdt_list[5] = { 0 };
/* configure a BDT entry */
count = sizeof(bdt_list) / sizeof(bdt_list[0]);
bvlc_broadcast_distribution_table_link_array(&bdt_list[0], count);
for (i = 0; i < count; i++) {
status = bvlc_address_port_from_ascii(
&dest_address, "192.168.0.255", "0xBAC0");
ct_test(pTest, status);
dest_address.port += i;
broadcast_mask.address[0] = 255;
broadcast_mask.address[1] = 255;
broadcast_mask.address[2] = 255;
broadcast_mask.address[3] = 255;
status = bvlc_broadcast_distribution_table_entry_set(
&bdt_entry, &dest_address, &broadcast_mask);
ct_test(pTest, status);
status = bvlc_broadcast_distribution_table_entry_append(
&bdt_list[0], &bdt_entry);
ct_test(pTest, status);
}
test_count = bvlc_broadcast_distribution_table_count(&bdt_list[0]);
if (test_count != count) {
printf("size=%u count=%u\n", count, test_count);
}
ct_test(pTest, test_count == count);
/* test the encode/decode pair */
apdu_len = bvlc_broadcast_distribution_table_encode(&apdu[0],
sizeof(apdu), &bdt_list[0]);
test_count = sizeof(test_bdt_list) / sizeof(test_bdt_list[0]);
bvlc_broadcast_distribution_table_link_array(&test_bdt_list[0], test_count);
test_apdu_len = bvlc_broadcast_distribution_table_decode(&apdu[0],
apdu_len, &error_code, &test_bdt_list[0]);
ct_test(pTest, test_apdu_len == apdu_len);
count = bvlc_broadcast_distribution_table_count(&test_bdt_list[0]);
ct_test(pTest, test_count == count);
for (i = 0; i < count; i++) {
status = bvlc_broadcast_distribution_table_entry_different(
&bdt_list[i], &test_bdt_list[i]);
ct_test(pTest, !status);
}
}
static void test_BVLC_Write_Broadcast_Distribution_Table(Test *pTest)
{
uint8_t npdu[480] = { 0 };
@@ -3183,6 +3514,9 @@ void test_BVLC(Test *pTest)
/* individual tests */
rc = ct_addTestFunction(pTest, test_BVLC_Result);
assert(rc);
rc = ct_addTestFunction(pTest,
test_BVLC_Broadcast_Distribution_Table_Encode);
assert(rc);
rc =
ct_addTestFunction(pTest, test_BVLC_Write_Broadcast_Distribution_Table);
assert(rc);
+16 -1
View File
@@ -294,7 +294,6 @@ extern "C" {
BACNET_IP_ADDRESS *dst, const BACNET_IP_ADDRESS *src,
const BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_mask_from_host(
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask, uint32_t broadcast_mask);
@@ -319,6 +318,17 @@ extern "C" {
uint8_t *addr2,
uint8_t *addr3);
BACNET_STACK_EXPORT
int bvlc_broadcast_distribution_table_decode(uint8_t *apdu,
uint16_t apdu_len,
BACNET_ERROR_CODE *error_code,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_head);
BACNET_STACK_EXPORT
int bvlc_broadcast_distribution_table_encode(uint8_t *apdu,
uint16_t apdu_size,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_head);
BACNET_STACK_EXPORT
int bvlc_encode_write_broadcast_distribution_table(uint8_t *pdu,
uint16_t pdu_size,
@@ -399,6 +409,11 @@ extern "C" {
uint16_t pdu_len,
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_entry);
BACNET_STACK_EXPORT
int bvlc_foreign_device_table_encode(uint8_t *apdu,
uint16_t apdu_size,
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_head);
BACNET_STACK_EXPORT
int bvlc_encode_read_foreign_device_table(uint8_t *pdu, uint16_t pdu_size);
+7
View File
@@ -41,6 +41,9 @@
/** @file dlenv.c Initialize the DataLink configuration. */
#if defined(BACDL_BIP)
#ifndef BBMD_ENABLED
#define BBMD_ENABLED 1
#endif
/* timer used to renew Foreign Device Registration */
static uint16_t BBMD_Timer_Seconds;
/* BBMD variables */
@@ -251,6 +254,10 @@ static void dlenv_network_port_init(void)
Network_Port_MAC_Address_Set(instance, &addr.address[0], 6);
Network_Port_IP_Subnet_Prefix_Set(instance, bip_get_subnet_prefix());
Network_Port_Link_Speed_Set(instance, 0.0);
#if BBMD_ENABLED
Network_Port_BBMD_BD_Table_Set(instance, bvlc_bdt_list());
Network_Port_BBMD_FD_Table_Set(instance, bvlc_fdt_list());
#endif
/* common NP data */
Network_Port_Reliability_Set(instance, RELIABILITY_NO_FAULT_DETECTED);
Network_Port_Out_Of_Service_Set(instance, false);
@@ -73,6 +73,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/service/h_wp.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/basic/tsm/tsm.c
${SRC_DIR}/bacnet/datalink/bvlc.c
${SRC_DIR}/bacnet/cov.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/dcc.c
@@ -43,6 +43,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/bacstr.c
${SRC_DIR}/bacnet/bactext.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/datalink/bvlc.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/lighting.c
+10 -4
View File
@@ -58,26 +58,32 @@ static void test_network_port(void)
rpdata.object_property = *pRequired;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Network_Port_Read_Property(&rpdata);
zassert_not_equal(len, 0, NULL);
test_len = bacapp_decode_application_data(rpdata.application_data,
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
if (len > 0) {
test_len = bacapp_decode_application_data(
rpdata.application_data,
(uint8_t)rpdata.application_data_len, &value);
zassert_true(test_len >= 0, NULL);
if (test_len < 0) {
printf("<decode failed!>\n");
}
}
pRequired++;
}
while ((*pOptional) != -1) {
rpdata.object_property = *pOptional;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Network_Port_Read_Property(&rpdata);
zassert_not_equal(len, 0, NULL);
test_len = bacapp_decode_application_data(rpdata.application_data,
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
if (len > 0) {
test_len = bacapp_decode_application_data(
rpdata.application_data,
(uint8_t)rpdata.application_data_len, &value);
zassert_true(test_len >= 0, NULL);
if (test_len < 0) {
printf("<decode failed!>\n");
}
}
pOptional++;
}
port++;
+57
View File
@@ -504,6 +504,63 @@ static void test_BVLC_Distribute_Broadcast_To_Network(void)
#endif
}
static void test_BVLC_Broadcast_Distribution_Table_Encode(void)
{
uint8_t apdu[480] = { 0 };
uint16_t apdu_len = 0;
uint16_t test_apdu_len = 0;
uint16_t i = 0;
uint16_t count = 0;
uint16_t test_count = 0;
bool status = false;
BACNET_ERROR_CODE error_code;
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY bdt_list[5] = { 0 };
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY bdt_entry = { 0 };
BACNET_IP_ADDRESS dest_address = { 0 };
BACNET_IP_BROADCAST_DISTRIBUTION_MASK broadcast_mask = { 0 };
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY test_bdt_list[5] = { 0 };
/* configure a BDT entry */
count = sizeof(bdt_list) / sizeof(bdt_list[0]);
bvlc_broadcast_distribution_table_link_array(&bdt_list[0], count);
for (i = 0; i < count; i++) {
status = bvlc_address_port_from_ascii(
&dest_address, "192.168.0.255", "0xBAC0");
zassert_true(status, NULL);
dest_address.port += i;
broadcast_mask.address[0] = 255;
broadcast_mask.address[1] = 255;
broadcast_mask.address[2] = 255;
broadcast_mask.address[3] = 255;
status = bvlc_broadcast_distribution_table_entry_set(
&bdt_entry, &dest_address, &broadcast_mask);
zassert_true(status, NULL);
status = bvlc_broadcast_distribution_table_entry_append(
&bdt_list[0], &bdt_entry);
zassert_true(status, NULL);
}
test_count = bvlc_broadcast_distribution_table_count(&bdt_list[0]);
if (test_count != count) {
printf("size=%u count=%u\n", count, test_count);
}
zassert_equal(test_count, count, NULL);
/* test the encode/decode pair */
apdu_len = bvlc_broadcast_distribution_table_encode(&apdu[0],
sizeof(apdu), &bdt_list[0]);
test_count = sizeof(test_bdt_list) / sizeof(test_bdt_list[0]);
bvlc_broadcast_distribution_table_link_array(&test_bdt_list[0], test_count);
test_apdu_len = bvlc_broadcast_distribution_table_decode(&apdu[0],
apdu_len, &error_code, &test_bdt_list[0]);
zassert_equal(test_apdu_len, apdu_len, NULL);
count = bvlc_broadcast_distribution_table_count(&test_bdt_list[0]);
zassert_equal(test_count, count, NULL);
for (i = 0; i < count; i++) {
status = bvlc_broadcast_distribution_table_entry_different(
&bdt_list[i], &test_bdt_list[i]);
zassert_false(status, NULL);
}
}
#if 0 /*TODO: Expose test_BVLC_Header */
static void test_BVLC_Write_Broadcast_Distribution_Table_Message(
uint8_t *npdu,