Corrected BVLC and BBMD code.

This commit is contained in:
skarg
2008-01-23 05:38:29 +00:00
parent c163a7cc93
commit d3ae827bf2
+67 -83
View File
@@ -85,6 +85,10 @@ static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES];
/* result from a client request */
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(
unsigned seconds)
{
@@ -271,7 +275,7 @@ int bvlc_encode_read_bdt_ack(
int bvlc_encode_forwarded_npdu(
uint8_t * pdu,
struct sockaddr_in *sin, /* the source address */
struct sockaddr_in *sin, /* source address in network order */
uint8_t * npdu,
unsigned npdu_length)
{
@@ -496,8 +500,8 @@ int bvlc_encode_original_broadcast_npdu(
/* FIXME: IPv6? */
void bvlc_internet_to_bacnet_address(
BACNET_ADDRESS * src, /* returns the BACnet source address */
struct sockaddr_in *sin)
{ /* source internet address */
struct sockaddr_in *sin) /* source address in network order */
{
int len = 0;
uint32_t address;
uint16_t port;
@@ -517,9 +521,8 @@ void bvlc_internet_to_bacnet_address(
/* copy the source internet address to the BACnet address */
/* FIXME: IPv6? */
/* FIXME: is sockaddr_in host or network order? */
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)
{ /* returns the BACnet source address */
int len = 0;
@@ -576,7 +579,7 @@ bool bvlc_create_bdt(
}
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)
{ /* time in seconds */
unsigned i = 0;
@@ -635,6 +638,27 @@ bool bvlc_delete_foreign_device(
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(
struct sockaddr_in *sin, /* the source address */
uint8_t * npdu, /* the NPDU */
@@ -646,13 +670,7 @@ void bvlc_bdt_forward_npdu(
unsigned i = 0; /* loop counter */
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);
/* load destination IP address */
bip_dest.sin_family = AF_INET;
/* loop through the BDT and send one to each entry, except us */
for (i = 0; i < MAX_BBMD_ENTRIES; i++) {
if (BBMD_Table[i].valid) {
@@ -674,10 +692,7 @@ void bvlc_bdt_forward_npdu(
(bip_dest.sin_port == htons(bip_get_port()))) {
continue;
}
/* Send the packet */
bytes_sent =
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
(struct sockaddr *) &bip_dest, sizeof(struct sockaddr));
bytes_sent = bvlc_send_mpdu(&bip_dest, mtu, mtu_len);
}
}
@@ -687,9 +702,23 @@ void bvlc_bdt_forward_npdu(
void bvlc_broadcast_forward_npdu(
struct sockaddr_in *sin, /* the source address */
uint8_t * npdu, /* returns the NPDU */
uint16_t npdu_len)
{ /* amount of space available in the NPDU */
/* FIXME: write the code... */
uint16_t npdu_len) /* size of the NPDU */
{
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(
@@ -703,52 +732,19 @@ void bvlc_fdt_forward_npdu(
unsigned i = 0; /* loop counter */
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);
/* load destination IP address */
bvlc_dest.sin_family = AF_INET;
/* loop through the FDT and send one to each entry */
for (i = 0; i < MAX_FD_ENTRIES; i++) {
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_port = htons(FD_Table[i].dest_port);
/* Send the packet */
bytes_sent =
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
(struct sockaddr *) &bvlc_dest, sizeof(struct sockaddr));
bytes_sent = bvlc_send_mpdu(&bvlc_dest, mtu, mtu_len);
}
}
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(
long bbmd_address, /* in network 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 };
int mtu_len = 0;
struct sockaddr_in dest;
dest.sin_addr.s_addr = bbmd_address;
dest.sin_port = htons(bbmd_port);
Remote_BBMD.sin_addr.s_addr = bbmd_address;
Remote_BBMD.sin_port = htons(bbmd_port);
/* In order for their broadcasts to get here,
we need to register our address with the remote BBMD using
Write Broadcast Distribution Table, or
@@ -767,11 +762,7 @@ void bvlc_register_with_bbmd(
mtu_len = bvlc_encode_register_foreign_device(
&mtu[0],
time_to_live_seconds);
bvlc_send_mpdu(&dest, &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);
bvlc_send_mpdu(&Remote_BBMD, &mtu[0], mtu_len);
}
void bvlc_send_result(
@@ -972,8 +963,10 @@ uint16_t bvlc_receive(
bvlc_send_mpdu(&dest, &npdu[4+6], npdu_len);
}
bvlc_fdt_forward_npdu(&sin, &npdu[4+6], npdu_len);
/* use the original source from the BVLC header */
bvlc_internet_to_bacnet_address(src, &original_sin);
/* use the original addr from the BVLC for src */
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) {
/* shift the buffer to return a valid PDU */
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
with a result code of X'0060' indicating that the forwarding
attempt was unsuccessful */
/* FIXME: complete the function code */
bvlc_broadcast_forward_npdu(&sin, &npdu[4], npdu_len);
bvlc_fdt_forward_npdu(&sin, &npdu[4], npdu_len);
break;
@@ -1117,24 +1109,24 @@ int bvlc_send_pdu(
struct sockaddr_in bvlc_dest;
uint8_t mtu[MAX_MPDU] = { 0 };
int mtu_len = 0;
int bytes_sent = 0;
/* addr and port in host format */
struct in_addr address;
uint16_t port = 0;
/* bip datalink doesn't need to know the 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;
bvlc_dest.sin_family = AF_INET;
if (dest->net == BACNET_BROADCAST_NETWORK) {
/* broadcast */
address.s_addr = bip_get_broadcast_addr();
port = bip_get_port();
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
/* if we are a foreign device */
if (Remote_BBMD.sin_port) {
mtu[1] = BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK;
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) {
/* valid unicast */
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_port = htons(port);
memset(&(bvlc_dest.sin_zero), '\0', 8);
mtu_len = 2;
mtu_len +=
encode_unsigned16(&mtu[mtu_len],
(uint16_t) (pdu_len + 4 /*inclusive */ ));
memcpy(&mtu[mtu_len], pdu, pdu_len);
mtu_len += pdu_len;
/* Send the packet */
bytes_sent =
sendto(bip_socket(), (char *) mtu, mtu_len, 0,
(struct sockaddr *) &bvlc_dest, sizeof(struct sockaddr));
return bytes_sent;
return bvlc_send_mpdu(&bvlc_dest, mtu, mtu_len);
}
#ifdef TEST