Files
bacnet_stack/src/bacnet/datalink/bvlc.h
T
Steve Karg 541f4024fb 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>
2021-08-03 09:55:01 -05:00

524 lines
17 KiB
C

/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef BVLC_H
#define BVLC_H
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "bacnet/bacdef.h"
#include "bacnet/npdu.h"
/**
* BVLL for BACnet/IPv4
* @{
*/
#define BVLL_TYPE_BACNET_IP (0x81)
/** @} */
/**
* B/IPv4 BVLL Messages
* @{
*/
#define BVLC_RESULT 0
#define BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE 1
#define BVLC_READ_BROADCAST_DIST_TABLE 2
#define BVLC_READ_BROADCAST_DIST_TABLE_ACK 3
#define BVLC_FORWARDED_NPDU 4
#define BVLC_REGISTER_FOREIGN_DEVICE 5
#define BVLC_READ_FOREIGN_DEVICE_TABLE 6
#define BVLC_READ_FOREIGN_DEVICE_TABLE_ACK 7
#define BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY 8
#define BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK 9
#define BVLC_ORIGINAL_UNICAST_NPDU 10
#define BVLC_ORIGINAL_BROADCAST_NPDU 11
#define BVLC_SECURE_BVLL 12
#define BVLC_INVALID 255
/** @} */
/**
* BVLC Result Code
* @{
*/
#define BVLC_RESULT_SUCCESSFUL_COMPLETION 0x0000
#define BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK 0x0010
#define BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK 0x0020
#define BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK 0X0030
#define BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK 0x0040
#define BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK 0x0050
#define BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK 0x0060
#define BVLC_RESULT_INVALID 0xFFFF
/* number of bytes in the IPv4 address */
#define IP_ADDRESS_MAX 4
/**
* BACnet IPv4 Address
*
* Data link layer addressing between B/IPv4 nodes consists of a 32-bit
* IPv4 address followed by a two-octet UDP port number (both of which
* shall be transmitted with the most significant octet first).
* This address shall be referred to as a B/IPv4 address.
* @{
*/
typedef struct BACnet_IP_Address {
uint8_t address[IP_ADDRESS_MAX];
uint16_t port;
} BACNET_IP_ADDRESS;
/* number of bytes in the B/IPv4 address */
#define BIP_ADDRESS_MAX 6
/**
* BACnet IPv4 Broadcast Distribution Mask
*
* The Broadcast Distribution Mask is a 4-octet field that
* indicates how broadcast messages are to be distributed on
* the IP subnet served by the BBMD.
* @{
*/
typedef struct BACnet_IP_Broadcast_Distribution_Mask {
uint8_t address[IP_ADDRESS_MAX];
} BACNET_IP_BROADCAST_DISTRIBUTION_MASK;
/* number of bytes in the B/IPv4 Broadcast Distribution Mask */
#define BACNET_IP_BDT_MASK_SIZE IP_ADDRESS_MAX
/** @} */
/**
* BACnet/IP Broadcast Distribution Table (BDT)
*
* The BDT consists of one entry for the address of the BBMD
* for the local IP subnet and an entry for the BBMD on each
* remote IP subnet to which broadcasts are to be forwarded.
* Each entry consists of the 6-octet B/IP address with which
* the BBMD is accessed and a 4-octet broadcast distribution mask.
* @{
*/
struct BACnet_IP_Broadcast_Distribution_Table_Entry;
typedef struct BACnet_IP_Broadcast_Distribution_Table_Entry {
/* true if valid entry - false if not */
bool valid;
/* BACnet/IP address */
BACNET_IP_ADDRESS dest_address;
/* Broadcast Distribution Mask */
BACNET_IP_BROADCAST_DISTRIBUTION_MASK broadcast_mask;
struct BACnet_IP_Broadcast_Distribution_Table_Entry *next;
} BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY;
/* number of bytes in a B/IPv4 roadcast Distribution Table entry */
#define BACNET_IP_BDT_ENTRY_SIZE (BIP_ADDRESS_MAX + BACNET_IP_BDT_MASK_SIZE)
/** @} */
/**
* Foreign Device Table (FDT)
*
* Each device that registers as a foreign device shall be placed
* in an entry in the BBMD's Foreign Device Table (FDT). Each
* entry shall consist of the 6-octet B/IP address of the registrant;
* the 2-octet Time-to-Live value supplied at the time of
* registration; and a 2-octet value representing the number of
* seconds remaining before the BBMD will purge the registrant's FDT
* entry if no re-registration occurs. This value will be initialized
* to the 2-octet Time-to-Live value supplied at the time of
* registration.
* @{
*/
struct BACnet_IP_Foreign_Device_Table_Entry;
typedef struct BACnet_IP_Foreign_Device_Table_Entry {
bool valid;
/* BACnet/IP address */
BACNET_IP_ADDRESS dest_address;
/* requested time-to-live value */
uint16_t ttl_seconds;
/* our counter - includes 30 second grace period */
uint16_t ttl_seconds_remaining;
struct BACnet_IP_Foreign_Device_Table_Entry *next;
} BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY;
#define BACNET_IP_FDT_ENTRY_SIZE 10
/** @} */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
BACNET_STACK_EXPORT
int bvlc_encode_address(
uint8_t *pdu, uint16_t pdu_size, const BACNET_IP_ADDRESS *ip_address);
BACNET_STACK_EXPORT
int bvlc_decode_address(
uint8_t *pdu, uint16_t pdu_len, BACNET_IP_ADDRESS *ip_address);
BACNET_STACK_EXPORT
bool bvlc_address_copy(BACNET_IP_ADDRESS *dst, const BACNET_IP_ADDRESS *src);
BACNET_STACK_EXPORT
bool bvlc_address_different(
const BACNET_IP_ADDRESS *dst, const BACNET_IP_ADDRESS *src);
BACNET_STACK_EXPORT
bool bvlc_address_from_ascii(BACNET_IP_ADDRESS *dst, const char *addrstr);
BACNET_STACK_EXPORT
bool bvlc_address_port_from_ascii(
BACNET_IP_ADDRESS *dst, const char *addrstr, const char *portstr);
BACNET_STACK_EXPORT
void bvlc_address_from_network(BACNET_IP_ADDRESS *dst, uint32_t addr);
BACNET_STACK_EXPORT
bool bvlc_address_set(BACNET_IP_ADDRESS *addr,
uint8_t addr0,
uint8_t addr1,
uint8_t addr2,
uint8_t addr3);
BACNET_STACK_EXPORT
bool bvlc_address_get(BACNET_IP_ADDRESS *addr,
uint8_t *addr0,
uint8_t *addr1,
uint8_t *addr2,
uint8_t *addr3);
BACNET_STACK_EXPORT
bool bvlc_ip_address_to_bacnet_local(
BACNET_ADDRESS *addr, BACNET_IP_ADDRESS *ipaddr);
BACNET_STACK_EXPORT
bool bvlc_ip_address_from_bacnet_local(
BACNET_IP_ADDRESS *ipaddr, BACNET_ADDRESS *addr);
BACNET_STACK_EXPORT
bool bvlc_ip_address_to_bacnet_remote(
BACNET_ADDRESS *addr, uint16_t dnet, BACNET_IP_ADDRESS *ipaddr);
BACNET_STACK_EXPORT
bool bvlc_ip_address_from_bacnet_remote(
BACNET_IP_ADDRESS *ipaddr, uint16_t *dnet, BACNET_ADDRESS *addr);
BACNET_STACK_EXPORT
int bvlc_encode_broadcast_distribution_mask(uint8_t *pdu,
uint16_t pdu_size,
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *bd_mask);
BACNET_STACK_EXPORT
int bvlc_decode_broadcast_distribution_mask(uint8_t *pdu,
uint16_t pdu_len,
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *bd_mask);
BACNET_STACK_EXPORT
int bvlc_encode_broadcast_distribution_table_entry(uint8_t *pdu,
uint16_t pdu_size,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry);
BACNET_STACK_EXPORT
int bvlc_decode_broadcast_distribution_table_entry(uint8_t *pdu,
uint16_t pdu_len,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry);
BACNET_STACK_EXPORT
void bvlc_broadcast_distribution_table_link_array(
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list,
const size_t bdt_array_size);
BACNET_STACK_EXPORT
uint16_t bvlc_broadcast_distribution_table_count(
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list);
BACNET_STACK_EXPORT
uint16_t bvlc_broadcast_distribution_table_valid_count(
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list);
BACNET_STACK_EXPORT
void bvlc_broadcast_distribution_table_valid_clear(
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_table_entry_different(
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *dst,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *src);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_table_entry_copy(
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *dst,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *src);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_mask_different(
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *dst,
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *src);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_mask_copy(
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *dst,
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *src);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_table_entry_append(
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_table_entry_set(
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry,
BACNET_IP_ADDRESS *addr,
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_table_entry_forward_address(
BACNET_IP_ADDRESS *addr,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry);
BACNET_STACK_EXPORT
bool bvlc_address_mask(
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);
BACNET_STACK_EXPORT
bool bvlc_broadcast_distribution_mask_to_host(
uint32_t *broadcast_mask, BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask);
BACNET_STACK_EXPORT
void bvlc_broadcast_distribution_mask_set(
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask,
uint8_t addr0,
uint8_t addr1,
uint8_t addr2,
uint8_t addr3);
BACNET_STACK_EXPORT
void bvlc_broadcast_distribution_mask_get(
BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask,
uint8_t *addr0,
uint8_t *addr1,
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,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list);
BACNET_STACK_EXPORT
int bvlc_decode_write_broadcast_distribution_table(uint8_t *pdu,
uint16_t pdu_len,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list);
BACNET_STACK_EXPORT
int bvlc_encode_read_broadcast_distribution_table(
uint8_t *pdu, uint16_t pdu_size);
BACNET_STACK_EXPORT
int bvlc_encode_read_broadcast_distribution_table_ack(uint8_t *pdu,
uint16_t pdu_size,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list);
BACNET_STACK_EXPORT
int bvlc_decode_read_broadcast_distribution_table_ack(uint8_t *pdu,
uint16_t pdu_len,
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list);
BACNET_STACK_EXPORT
int bvlc_encode_header(
uint8_t *pdu, uint16_t pdu_size, uint8_t message_type, uint16_t length);
BACNET_STACK_EXPORT
int bvlc_decode_header(
uint8_t *pdu, uint16_t pdu_len, uint8_t *message_type, uint16_t *length);
BACNET_STACK_EXPORT
void bvlc_foreign_device_table_maintenance_timer(
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list, uint16_t seconds);
BACNET_STACK_EXPORT
uint16_t bvlc_foreign_device_table_valid_count(
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list);
BACNET_STACK_EXPORT
uint16_t bvlc_foreign_device_table_count(
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list);
BACNET_STACK_EXPORT
void bvlc_foreign_device_table_link_array(
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list, const size_t array_size);
BACNET_STACK_EXPORT
bool bvlc_foreign_device_table_entry_different(
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *dst,
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *src);
BACNET_STACK_EXPORT
bool bvlc_foreign_device_table_entry_copy(
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *dst,
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *src);
BACNET_STACK_EXPORT
bool bvlc_foreign_device_table_entry_delete(
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list,
BACNET_IP_ADDRESS *ip_address);
BACNET_STACK_EXPORT
bool bvlc_foreign_device_table_entry_add(
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list,
BACNET_IP_ADDRESS *ip_address,
uint16_t ttl_seconds);
BACNET_STACK_EXPORT
int bvlc_encode_foreign_device_table_entry(uint8_t *pdu,
uint16_t pdu_size,
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_entry);
BACNET_STACK_EXPORT
int bvlc_decode_foreign_device_table_entry(uint8_t *pdu,
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);
BACNET_STACK_EXPORT
int bvlc_encode_read_foreign_device_table_ack(uint8_t *pdu,
uint16_t pdu_size,
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list);
BACNET_STACK_EXPORT
int bvlc_decode_read_foreign_device_table_ack(uint8_t *pdu,
uint16_t pdu_len,
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list);
BACNET_STACK_EXPORT
int bvlc_encode_result(uint8_t *pdu, uint16_t pdu_size, uint16_t result_code);
BACNET_STACK_EXPORT
int bvlc_decode_result(uint8_t *pdu, uint16_t pdu_len, uint16_t *result_code);
BACNET_STACK_EXPORT
int bvlc_encode_original_unicast(
uint8_t *pdu, uint16_t pdu_size, uint8_t *npdu, uint16_t npdu_len);
BACNET_STACK_EXPORT
int bvlc_decode_original_unicast(uint8_t *pdu,
uint16_t pdu_len,
uint8_t *npdu,
uint16_t npdu_size,
uint16_t *npdu_len);
BACNET_STACK_EXPORT
int bvlc_encode_original_broadcast(
uint8_t *pdu, uint16_t pdu_size, uint8_t *npdu, uint16_t npdu_len);
BACNET_STACK_EXPORT
int bvlc_decode_original_broadcast(uint8_t *pdu,
uint16_t pdu_len,
uint8_t *npdu,
uint16_t npdu_size,
uint16_t *npdu_len);
BACNET_STACK_EXPORT
int bvlc_encode_forwarded_npdu(uint8_t *pdu,
uint16_t pdu_size,
BACNET_IP_ADDRESS *address,
uint8_t *npdu,
uint16_t npdu_len);
BACNET_STACK_EXPORT
int bvlc_decode_forwarded_npdu(uint8_t *pdu,
uint16_t pdu_len,
BACNET_IP_ADDRESS *address,
uint8_t *npdu,
uint16_t npdu_size,
uint16_t *npdu_len);
BACNET_STACK_EXPORT
int bvlc_encode_register_foreign_device(
uint8_t *pdu, uint16_t pdu_size, uint16_t ttl_seconds);
BACNET_STACK_EXPORT
int bvlc_decode_register_foreign_device(
uint8_t *pdu, uint16_t pdu_len, uint16_t *ttl_seconds);
BACNET_STACK_EXPORT
int bvlc_encode_delete_foreign_device(
uint8_t *pdu, uint16_t pdu_size, BACNET_IP_ADDRESS *ip_address);
BACNET_STACK_EXPORT
int bvlc_decode_delete_foreign_device(
uint8_t *pdu, uint16_t pdu_len, BACNET_IP_ADDRESS *ip_address);
BACNET_STACK_EXPORT
int bvlc_encode_secure_bvll(
uint8_t *pdu, uint16_t pdu_size, uint8_t *sbuf, uint16_t sbuf_len);
BACNET_STACK_EXPORT
int bvlc_decode_secure_bvll(uint8_t *pdu,
uint16_t pdu_len,
uint8_t *sbuf,
uint16_t sbuf_size,
uint16_t *sbuf_len);
BACNET_STACK_EXPORT
int bvlc_encode_distribute_broadcast_to_network(
uint8_t *pdu, uint16_t pdu_size, uint8_t *npdu, uint16_t npdu_len);
BACNET_STACK_EXPORT
int bvlc_decode_distribute_broadcast_to_network(uint8_t *pdu,
uint16_t pdu_len,
uint8_t *npdu,
uint16_t npdu_size,
uint16_t *npdu_len);
BACNET_STACK_EXPORT
const char *bvlc_result_code_name(uint16_t result_code);
#ifdef BAC_TEST
#include "ctest.h"
BACNET_STACK_EXPORT
void test_BVLC(Test *pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* */