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:
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user