Corrected BVLC and BBMD code.
This commit is contained in:
+67
-83
@@ -85,6 +85,10 @@ static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
|
|||||||
/* result from a client request */
|
/* result from a client request */
|
||||||
BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION;
|
BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION;
|
||||||
|
|
||||||
|
/* if we are a foreign device, store the
|
||||||
|
remote BBMD address/port here in network byte order */
|
||||||
|
static struct sockaddr_in Remote_BBMD;
|
||||||
|
|
||||||
void bvlc_maintenance_timer(
|
void bvlc_maintenance_timer(
|
||||||
unsigned seconds)
|
unsigned seconds)
|
||||||
{
|
{
|
||||||
@@ -271,7 +275,7 @@ int bvlc_encode_read_bdt_ack(
|
|||||||
|
|
||||||
int bvlc_encode_forwarded_npdu(
|
int bvlc_encode_forwarded_npdu(
|
||||||
uint8_t * pdu,
|
uint8_t * pdu,
|
||||||
struct sockaddr_in *sin, /* the source address */
|
struct sockaddr_in *sin, /* source address in network order */
|
||||||
uint8_t * npdu,
|
uint8_t * npdu,
|
||||||
unsigned npdu_length)
|
unsigned npdu_length)
|
||||||
{
|
{
|
||||||
@@ -496,8 +500,8 @@ int bvlc_encode_original_broadcast_npdu(
|
|||||||
/* FIXME: IPv6? */
|
/* FIXME: IPv6? */
|
||||||
void bvlc_internet_to_bacnet_address(
|
void bvlc_internet_to_bacnet_address(
|
||||||
BACNET_ADDRESS * src, /* returns the BACnet source address */
|
BACNET_ADDRESS * src, /* returns the BACnet source address */
|
||||||
struct sockaddr_in *sin)
|
struct sockaddr_in *sin) /* source address in network order */
|
||||||
{ /* source internet address */
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
@@ -517,9 +521,8 @@ void bvlc_internet_to_bacnet_address(
|
|||||||
|
|
||||||
/* copy the source internet address to the BACnet address */
|
/* copy the source internet address to the BACnet address */
|
||||||
/* FIXME: IPv6? */
|
/* FIXME: IPv6? */
|
||||||
/* FIXME: is sockaddr_in host or network order? */
|
|
||||||
void bvlc_bacnet_to_internet_address(
|
void bvlc_bacnet_to_internet_address(
|
||||||
struct sockaddr_in *sin, /* source internet address */
|
struct sockaddr_in *sin, /* source address in network order */
|
||||||
BACNET_ADDRESS * src)
|
BACNET_ADDRESS * src)
|
||||||
{ /* returns the BACnet source address */
|
{ /* returns the BACnet source address */
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -576,7 +579,7 @@ bool bvlc_create_bdt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool bvlc_register_foreign_device(
|
bool bvlc_register_foreign_device(
|
||||||
struct sockaddr_in * sin, /* the source address */
|
struct sockaddr_in * sin, /* source address in network order */
|
||||||
uint16_t time_to_live)
|
uint16_t time_to_live)
|
||||||
{ /* time in seconds */
|
{ /* time in seconds */
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
@@ -635,6 +638,27 @@ bool bvlc_delete_foreign_device(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bvlc_send_mpdu(
|
||||||
|
struct sockaddr_in *dest, /* the destination address */
|
||||||
|
uint8_t * mtu, /* the data */
|
||||||
|
uint16_t mtu_len) /* amount of data to send */
|
||||||
|
{
|
||||||
|
struct sockaddr_in bvlc_dest;
|
||||||
|
|
||||||
|
/* assumes that the driver has already been initialized */
|
||||||
|
if (bip_socket() < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* load destination IP address */
|
||||||
|
bvlc_dest.sin_family = AF_INET;
|
||||||
|
bvlc_dest.sin_addr.s_addr = dest->sin_addr.s_addr;
|
||||||
|
bvlc_dest.sin_port = dest->sin_port;
|
||||||
|
memset(&(bvlc_dest.sin_zero), '\0', 8);
|
||||||
|
/* Send the packet */
|
||||||
|
return sendto(bip_socket(), (char *) mtu, mtu_len, 0,
|
||||||
|
(struct sockaddr *) &bvlc_dest, sizeof(struct sockaddr));
|
||||||
|
}
|
||||||
|
|
||||||
void bvlc_bdt_forward_npdu(
|
void bvlc_bdt_forward_npdu(
|
||||||
struct sockaddr_in *sin, /* the source address */
|
struct sockaddr_in *sin, /* the source address */
|
||||||
uint8_t * npdu, /* the NPDU */
|
uint8_t * npdu, /* the NPDU */
|
||||||
@@ -646,13 +670,7 @@ void bvlc_bdt_forward_npdu(
|
|||||||
unsigned i = 0; /* loop counter */
|
unsigned i = 0; /* loop counter */
|
||||||
struct sockaddr_in bip_dest;
|
struct sockaddr_in bip_dest;
|
||||||
|
|
||||||
/* assumes that the driver has already been initialized */
|
|
||||||
if (bip_socket() < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mtu_len = bvlc_encode_forwarded_npdu(&mtu[0], sin, npdu, npdu_length);
|
mtu_len = bvlc_encode_forwarded_npdu(&mtu[0], sin, npdu, npdu_length);
|
||||||
/* load destination IP address */
|
|
||||||
bip_dest.sin_family = AF_INET;
|
|
||||||
/* loop through the BDT and send one to each entry, except us */
|
/* loop through the BDT and send one to each entry, except us */
|
||||||
for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
|
for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
|
||||||
if (BBMD_Table[i].valid) {
|
if (BBMD_Table[i].valid) {
|
||||||
@@ -674,10 +692,7 @@ void bvlc_bdt_forward_npdu(
|
|||||||
(bip_dest.sin_port == htons(bip_get_port()))) {
|
(bip_dest.sin_port == htons(bip_get_port()))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Send the packet */
|
bytes_sent = bvlc_send_mpdu(&bip_dest, mtu, mtu_len);
|
||||||
bytes_sent =
|
|
||||||
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
|
|
||||||
(struct sockaddr *) &bip_dest, sizeof(struct sockaddr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,9 +702,23 @@ void bvlc_bdt_forward_npdu(
|
|||||||
void bvlc_broadcast_forward_npdu(
|
void bvlc_broadcast_forward_npdu(
|
||||||
struct sockaddr_in *sin, /* the source address */
|
struct sockaddr_in *sin, /* the source address */
|
||||||
uint8_t * npdu, /* returns the NPDU */
|
uint8_t * npdu, /* returns the NPDU */
|
||||||
uint16_t npdu_len)
|
uint16_t npdu_len) /* size of the NPDU */
|
||||||
{ /* amount of space available in the NPDU */
|
{
|
||||||
/* FIXME: write the code... */
|
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||||
|
int mtu_len = 0;
|
||||||
|
struct sockaddr_in bvlc_dest;
|
||||||
|
|
||||||
|
mtu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
|
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
||||||
|
bvlc_dest.sin_addr.s_addr = htonl(bip_get_broadcast_addr());
|
||||||
|
bvlc_dest.sin_port = htons(bip_get_port());
|
||||||
|
mtu_len = 2;
|
||||||
|
mtu_len +=
|
||||||
|
encode_unsigned16(&mtu[mtu_len],
|
||||||
|
(uint16_t) (npdu_len + 4 /*inclusive */ ));
|
||||||
|
memcpy(&mtu[mtu_len], npdu, npdu_len);
|
||||||
|
mtu_len += npdu_len;
|
||||||
|
bvlc_send_mpdu(&bvlc_dest, mtu, mtu_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bvlc_fdt_forward_npdu(
|
void bvlc_fdt_forward_npdu(
|
||||||
@@ -703,52 +732,19 @@ void bvlc_fdt_forward_npdu(
|
|||||||
unsigned i = 0; /* loop counter */
|
unsigned i = 0; /* loop counter */
|
||||||
struct sockaddr_in bvlc_dest;
|
struct sockaddr_in bvlc_dest;
|
||||||
|
|
||||||
/* assumes that the driver has already been initialized */
|
|
||||||
if (bip_socket() < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mtu_len = bvlc_encode_forwarded_npdu(&mtu[0], sin, npdu, max_npdu);
|
mtu_len = bvlc_encode_forwarded_npdu(&mtu[0], sin, npdu, max_npdu);
|
||||||
/* load destination IP address */
|
|
||||||
bvlc_dest.sin_family = AF_INET;
|
|
||||||
/* loop through the FDT and send one to each entry */
|
/* loop through the FDT and send one to each entry */
|
||||||
for (i = 0; i < MAX_FD_ENTRIES; i++) {
|
for (i = 0; i < MAX_FD_ENTRIES; i++) {
|
||||||
if (FD_Table[i].valid && FD_Table[i].seconds_remaining) {
|
if (FD_Table[i].valid && FD_Table[i].seconds_remaining) {
|
||||||
bvlc_dest.sin_addr.s_addr = htonl(FD_Table[i].dest_address.s_addr);
|
bvlc_dest.sin_addr.s_addr = htonl(FD_Table[i].dest_address.s_addr);
|
||||||
bvlc_dest.sin_port = htons(FD_Table[i].dest_port);
|
bvlc_dest.sin_port = htons(FD_Table[i].dest_port);
|
||||||
/* Send the packet */
|
bytes_sent = bvlc_send_mpdu(&bvlc_dest, mtu, mtu_len);
|
||||||
bytes_sent =
|
|
||||||
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
|
|
||||||
(struct sockaddr *) &bvlc_dest, sizeof(struct sockaddr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bvlc_send_mpdu(
|
|
||||||
struct sockaddr_in *dest, /* the destination address */
|
|
||||||
uint8_t * mtu, /* the data */
|
|
||||||
uint16_t mtu_len)
|
|
||||||
{ /* amount of data to send */
|
|
||||||
int bytes_sent = 0;
|
|
||||||
struct sockaddr_in bvlc_dest;
|
|
||||||
|
|
||||||
/* assumes that the driver has already been initialized */
|
|
||||||
if (bip_socket() < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* load destination IP address */
|
|
||||||
bvlc_dest.sin_family = AF_INET;
|
|
||||||
bvlc_dest.sin_addr.s_addr = dest->sin_addr.s_addr;
|
|
||||||
bvlc_dest.sin_port = dest->sin_port;
|
|
||||||
/* Send the packet */
|
|
||||||
bytes_sent =
|
|
||||||
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
|
|
||||||
(struct sockaddr *) &bvlc_dest, sizeof(struct sockaddr));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bvlc_register_with_bbmd(
|
void bvlc_register_with_bbmd(
|
||||||
long bbmd_address, /* in network byte order */
|
long bbmd_address, /* in network byte order */
|
||||||
uint16_t bbmd_port, /* in host byte order */
|
uint16_t bbmd_port, /* in host byte order */
|
||||||
@@ -756,10 +752,9 @@ void bvlc_register_with_bbmd(
|
|||||||
{
|
{
|
||||||
uint8_t mtu[MAX_MPDU] = { 0 };
|
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||||
int mtu_len = 0;
|
int mtu_len = 0;
|
||||||
struct sockaddr_in dest;
|
|
||||||
|
|
||||||
dest.sin_addr.s_addr = bbmd_address;
|
Remote_BBMD.sin_addr.s_addr = bbmd_address;
|
||||||
dest.sin_port = htons(bbmd_port);
|
Remote_BBMD.sin_port = htons(bbmd_port);
|
||||||
/* In order for their broadcasts to get here,
|
/* In order for their broadcasts to get here,
|
||||||
we need to register our address with the remote BBMD using
|
we need to register our address with the remote BBMD using
|
||||||
Write Broadcast Distribution Table, or
|
Write Broadcast Distribution Table, or
|
||||||
@@ -767,11 +762,7 @@ void bvlc_register_with_bbmd(
|
|||||||
mtu_len = bvlc_encode_register_foreign_device(
|
mtu_len = bvlc_encode_register_foreign_device(
|
||||||
&mtu[0],
|
&mtu[0],
|
||||||
time_to_live_seconds);
|
time_to_live_seconds);
|
||||||
bvlc_send_mpdu(&dest, &mtu[0], mtu_len);
|
bvlc_send_mpdu(&Remote_BBMD, &mtu[0], mtu_len);
|
||||||
/* In order for our broadcasts to get there,
|
|
||||||
we have to put this BBMD into my BBMD table
|
|
||||||
or register it as a foreign device in my FDT. */
|
|
||||||
bvlc_register_foreign_device(&dest, time_to_live_seconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bvlc_send_result(
|
void bvlc_send_result(
|
||||||
@@ -972,8 +963,10 @@ uint16_t bvlc_receive(
|
|||||||
bvlc_send_mpdu(&dest, &npdu[4+6], npdu_len);
|
bvlc_send_mpdu(&dest, &npdu[4+6], npdu_len);
|
||||||
}
|
}
|
||||||
bvlc_fdt_forward_npdu(&sin, &npdu[4+6], npdu_len);
|
bvlc_fdt_forward_npdu(&sin, &npdu[4+6], npdu_len);
|
||||||
/* use the original source from the BVLC header */
|
/* use the original addr from the BVLC for src */
|
||||||
bvlc_internet_to_bacnet_address(src, &original_sin);
|
dest.sin_addr.s_addr = htonl(original_sin.sin_addr.s_addr);
|
||||||
|
dest.sin_port = htons(original_sin.sin_port);
|
||||||
|
bvlc_internet_to_bacnet_address(src, &dest);
|
||||||
if (npdu_len < max_npdu) {
|
if (npdu_len < max_npdu) {
|
||||||
/* shift the buffer to return a valid PDU */
|
/* shift the buffer to return a valid PDU */
|
||||||
for (i = 0; i < npdu_len; i++) {
|
for (i = 0; i < npdu_len; i++) {
|
||||||
@@ -1048,7 +1041,6 @@ uint16_t bvlc_receive(
|
|||||||
it shall return a BVLC-Result message to the foreign device
|
it shall return a BVLC-Result message to the foreign device
|
||||||
with a result code of X'0060' indicating that the forwarding
|
with a result code of X'0060' indicating that the forwarding
|
||||||
attempt was unsuccessful */
|
attempt was unsuccessful */
|
||||||
/* FIXME: complete the function code */
|
|
||||||
bvlc_broadcast_forward_npdu(&sin, &npdu[4], npdu_len);
|
bvlc_broadcast_forward_npdu(&sin, &npdu[4], npdu_len);
|
||||||
bvlc_fdt_forward_npdu(&sin, &npdu[4], npdu_len);
|
bvlc_fdt_forward_npdu(&sin, &npdu[4], npdu_len);
|
||||||
break;
|
break;
|
||||||
@@ -1117,24 +1109,24 @@ int bvlc_send_pdu(
|
|||||||
struct sockaddr_in bvlc_dest;
|
struct sockaddr_in bvlc_dest;
|
||||||
uint8_t mtu[MAX_MPDU] = { 0 };
|
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||||
int mtu_len = 0;
|
int mtu_len = 0;
|
||||||
int bytes_sent = 0;
|
|
||||||
/* addr and port in host format */
|
/* addr and port in host format */
|
||||||
struct in_addr address;
|
struct in_addr address;
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
|
|
||||||
/* bip datalink doesn't need to know the npdu data */
|
/* bip datalink doesn't need to know the npdu data */
|
||||||
(void) npdu_data;
|
(void) npdu_data;
|
||||||
/* assumes that the driver has already been initialized */
|
|
||||||
if (bip_socket() < 0)
|
|
||||||
return bip_socket();
|
|
||||||
|
|
||||||
mtu[0] = BVLL_TYPE_BACNET_IP;
|
mtu[0] = BVLL_TYPE_BACNET_IP;
|
||||||
bvlc_dest.sin_family = AF_INET;
|
|
||||||
if (dest->net == BACNET_BROADCAST_NETWORK) {
|
if (dest->net == BACNET_BROADCAST_NETWORK) {
|
||||||
/* broadcast */
|
/* if we are a foreign device */
|
||||||
address.s_addr = bip_get_broadcast_addr();
|
if (Remote_BBMD.sin_port) {
|
||||||
port = bip_get_port();
|
mtu[1] = BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK;
|
||||||
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
address.s_addr = ntohl(Remote_BBMD.sin_addr.s_addr);
|
||||||
|
port = ntohs(Remote_BBMD.sin_port);
|
||||||
|
} else {
|
||||||
|
address.s_addr = bip_get_broadcast_addr();
|
||||||
|
port = bip_get_port();
|
||||||
|
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
||||||
|
}
|
||||||
} else if (dest->mac_len == 6) {
|
} else if (dest->mac_len == 6) {
|
||||||
/* valid unicast */
|
/* valid unicast */
|
||||||
bvlc_decode_bip_address(&dest->mac[0], &address, &port);
|
bvlc_decode_bip_address(&dest->mac[0], &address, &port);
|
||||||
@@ -1145,21 +1137,13 @@ int bvlc_send_pdu(
|
|||||||
}
|
}
|
||||||
bvlc_dest.sin_addr.s_addr = htonl(address.s_addr);
|
bvlc_dest.sin_addr.s_addr = htonl(address.s_addr);
|
||||||
bvlc_dest.sin_port = htons(port);
|
bvlc_dest.sin_port = htons(port);
|
||||||
memset(&(bvlc_dest.sin_zero), '\0', 8);
|
|
||||||
|
|
||||||
mtu_len = 2;
|
mtu_len = 2;
|
||||||
mtu_len +=
|
mtu_len +=
|
||||||
encode_unsigned16(&mtu[mtu_len],
|
encode_unsigned16(&mtu[mtu_len],
|
||||||
(uint16_t) (pdu_len + 4 /*inclusive */ ));
|
(uint16_t) (pdu_len + 4 /*inclusive */ ));
|
||||||
memcpy(&mtu[mtu_len], pdu, pdu_len);
|
memcpy(&mtu[mtu_len], pdu, pdu_len);
|
||||||
mtu_len += pdu_len;
|
mtu_len += pdu_len;
|
||||||
|
return bvlc_send_mpdu(&bvlc_dest, mtu, mtu_len);
|
||||||
/* Send the packet */
|
|
||||||
bytes_sent =
|
|
||||||
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
|
|
||||||
(struct sockaddr *) &bvlc_dest, sizeof(struct sockaddr));
|
|
||||||
|
|
||||||
return bytes_sent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|||||||
Reference in New Issue
Block a user