230 likes | 452 Views
BACnet IT prototype. Joint effort of Cimetrics and CiscoBased on BACnet IT discussions to dateTestbed for ideasProof of principle"Does this stuff actually work?How hard is it to implement?How hard is it to get two independent implementations to interoperate?How similar can we keep it to toda
E N D
1. BACnet IT prototype
2. BACnet IT prototype Joint effort of Cimetrics and Cisco
Based on BACnet IT discussions to date
Testbed for ideas
“Proof of principle”
Does this stuff actually work?
How hard is it to implement?
How hard is it to get two independent implementations to interoperate?
How similar can we keep it to today’s BACnet?
3. Prototypes Cimetrics
All new code, developed by the Cimetrics BACstac team
Python based implementation for rapid prototyping
Cisco
Minimal modifications to Steve Karg’s open source BACnet stack
Implemented in C
These are only experiments, not products!
4. Design decisions Use Internet Protocols (IPv4 & IPv6)
Device are IP hosts as per various IETF documents:
http://tools.ietf.org/html/rfc1123 (Requirements for Internet Hosts)
http://tools.ietf.org/html/draft-baker-ietf-core-11 (Internet Protocols for the Smart Grid)
mDNS/DNS-SD used for discovery
TCP transport
Certificate authentication via TLS
Encryption via TLS
Keep broadcasts to a minimum & link-local only
ASN-1 encoding as close to current BACnet as possible
5. Naming The following could all be ways of referring to a BACnet device:
BACnet “host” (i.e. IP hostname, port would default to 0xBAC2)
IP address + port
BACnet Name (DNS-SD service instance name)
Canonical Name in SSL Certificate (CN=)
For this prototype the namespace is similar to current BACnet
Unstructured string, not required to be a URI (but could be)
This bears further discussion
There are various discovery and lookup methods to resolve the various names
6. Service Discovery DNS-SD for service discovery
Discovery records hosted by mDNS for small, single link networks
Hosted by standard DNS servers (e.g. bind) for link networks
Co-existence between mDNS & DNS is possible
Typically corporate network would have DNS servers, but the printer on your floor is nonetheless advertising itself on the local link via mDNS
Service names are of the form: instance.type.location
Location is scope of the search. E.g. .local. for mDNS
Type indicates the protocol. E.g. _bacnet._tcp
Instance is the name of an instance of this service
7. Discovery sequence - mDNS Look PTR record query via local broadcast to port 5353
BACnet IT service type is _bacnet._tcp
Examples using dig:
dig –p 5353 @224.0.0.251 _bacnet._tcp.local PTRdig –p 5353 @ff02::1 _bacnet._tcp.local PTR
Both the IPv6 & IPv4 queries return the same records:
_bacnet._tcp.local. 10 IN PTR propserv._bacnet._tcp.local.
propserv._bacnet._tcp.local. 10 IN TXT "txtvers=1"
propserv._bacnet._tcp.local. 10 IN SRV 0 0 47810 fry-u.local.
fry-u.local. 10 IN AAAA fe80::a00:27ff:fe97:4408
fry-u.local. 10 IN A 10.111.0.31
TXT records might return more properties using key=value pairs
This could be used to enable filtering on desired properties without any further broadcast queries
An alternative filtering mechanisms could be using subtypes. E.g. _thermostat._sub._bacnet._tcp
By convention, the first key value pair would be the version number (e.g. txtvers=1 here) of the rest of the key value pairs (none in this example)
SRV record contains mapping to IP host name
A or AAAA records provide IP address resolution
Note, the default port of 0xBAC2 is assumed
8. Discovery sequence - DNS PTR record query directly to configured DNS host
DNS host address might be obtained via DHCP
Everything else is the same!
Examples using dig:
dig @DNSSERVER _bacnet._tcp.example.com PTR
The query returns the same records as mDNS, but this time in the example.com domain::
_bacnet._tcp..example.com. 10 IN PTR propserv._bacnet._tcp.example.com.
propserv._bacnet._tcp.example.com. 10 IN TXT "txtvers=1"
propserv._bacnet._tcp.example.com. 10 IN SRV 0 0 47810 fry-u.example.com.
fry-u.example.com. 10 IN AAAA fe80::a00:27ff:fe97:4408
fry-u.example.com. 10 IN A 10.111.0.31
9. Discovery notes The BACnet device name in our example was propserv.
The IP host name was fry-u
fry-u.example.com when discovered via mDNS
fry-u.example.com in our example DNS
example.com would presumably be replaced by the site’s local DNS zone
The BACnet device name is the canonical name of the device
That’s the name that must be validated by the device’s certificate!
10. Transport TLS provides reliable transport
TLS certificates are issued on a per-host basis
A single host could contain more than one BACnet address, accessible through on and the same access port (IPAddress:Port)
For hosts that support multiple devices
Client must resolve the device name to its device instance number
See Who-Is-Request below
Device Instance Numbers uniquely identify a device only for the duration of the current connection
11. Connections All connections use TLS
However, to make debugging easier in the prototypes, we have not turned on encryption of the data stream
But it is trivial to enable encryption
Mutual certificate-based authentication
There is a single root signing certificate
Each side must have its own certificate signed by that root certificate’s private key
In a production system, there’d likely be at least one additional level
12. Connections A TLS connection is somewhat expensive
It takes about 9 packets involving some fairly large keys to establish a connection
TLS connections are therefore kept open between pairs of communicating hosts
Multiple BACnet devices per host are supported
Responses can be received in a different order than requests were sent.
If connection drops, any outstanding requests are considered aborted
The outcome of any outstanding transaction is undetermined. The transaction may have succeed but its result was not delivered to the client or it may have failed before the server even started to execute it.
Note this behavior is consistent with current BACnet (consider that you sent the request and then cut the wire).
13. Device Communication All communication is based on the reliable transport, and therefore all BACnet-PDUs are unicast messages.
Typically, communication between devices is based on transactions (request/response).
Each transaction is identified by a 32-bit Invoke-ID, which is unique inside of the current connection.
Invoke-ID must be unique for each request inside of a connection regardless whether it is sent to one device or different devices.
There are no timeouts at the protocol level.
All confirmed requests should be eventually confirmed, or the connection broken. Timeouts may be implemented at the application level.
14. Resolving device instances These are confirmed services:
Who-Is-Request ::= SEQUENCE {
instanceName [0] CharacterString OPTIONAL
}
Who-Is-Response ::= SEQUENCE OF SEQUENCE {
instanceName [0] CharacterString
instanceNumber [1] Unsigned32
timeStamp [2] BACnetDateTime OPTIONAL
}
If the Who-Is-Request does not have any instanceName then Who-Is response shall contain the list of all devices. If the current BACnet Service Point is not a gateway then the list should be empty.
If the Who-Is-Request contains instanceName then Who-Is response shall have only one element that contains the canonical name of that device, the instance number to refer to it, and optionally timeStamp.
The optional timeStamp can be used to convey time when this device was discovered by gateway. This may be useful for an operator to find recently plugged devices. The precise meaning of timeStamp is a local matter.
15. Enumerating The procedure of enumerating of all devices, all objects, and all properties on the BACnet internetwork or in some given domain consist of:
enumerating all BACnet Service Points using DNS-SD and mDNS
establishing TLS connection with client authentication to each found BACnet service point
reading the list of available objects by reading the object-list property in the device
using ReadPropertyMultiple to read properties of each object
Issuing Who-Is-Request to find other devices inside of a gateway.
For each device inside of gateway repeating steps #3 and #4 using instanceNumber from Who-Is-Response.
16. Datagram header Each datagram starts with the header of 4 octets:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Control Flags | Datagram Type | Datagram Size |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The first octet is a control octet:
Bit 7: 1 indicates that it is a special control datagram, which are used to control messages during connection negations;
0 indicates a BACnet APDU.
Bit 6: 1 indicates it contains device instance
Bits 2..5: reserved; they must set to zero by sender and ignored by receiver.
Bits 1,0: Network priority where: B'11' = Life Safety messageB'10' = Critical Equipment messageB'01' = Urgent messageB'00' = Normal message
The second octet is Datagram Type. Its meaning depends on bit 7.
The third and fourth octets represent datagram length in the network order. It is interpreted as the number of octets after this header.
17. BACnet-PDU Each BACnet-PDU starts with the fixed part described in the following slides.
Note, we don’t use ASN.1 to describe this fixed part, as it is not used in current BACnet
All primitive data types have fixed size and are encoded in the network order.
Optional fields can be omitted based on flags in the diagram header, which was described above.
18. BACnetPDU BACnetPDU ::= CHOICE {
confirmed-request-PDU [0] BACnet-Confirmed-Request-PDU,
unconfirmed-request-PDU [1] BACnet-Unconfirmed-Request-PDU,
ACK-PDU [2] BACnet-SimpleACK-PDU,
error-PDU [3] BACnet-Error-PDU,
abort-PDU [4] BACnet-Client-Abort-PDU
Context-specific tags are NOT used, and the choice is determined by the Datagram Type (second octet) in the transmit header.
}
19. BACnet-Confirmed-Request BACnet-Confirmed-Request ::= SEQUENCE {
invoke-id [0] Unsigned32
device-instance [1] Unsigned32 OPTIONAL (See device flag)
service-choice [2] BACnetConfirmedServiceChoice
service-request [3] BACnet-Confirmed-Service-Request OPTIONAL
-- Context-specific tags 0..3 are NOT used in header encoding
}
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Invoke Id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Device Instance Number | (optional)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Service Choice| Service Request |
+-+-+-+-+-+-+-+-+ .
| |
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20. BACnet-Unconfirmed-Request BACnet-Unconfirmed-Request ::= SEQUENCE {
device-instance [0] Unsigned32 OPTIONAL (See device flag)
service-choice [1] BACnetUnconfirmedServiceChoice
service-request [2] BACnet-Unconfirmed-Service-Request
-- Context-specific tags 0..2 are NOT used in header encoding
}
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Device Instance Number | (optional)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Service Choice| Service Request |
+-+-+-+-+-+-+-+-+ .
| |
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21. BACnet-ACK-PDU BACnet-ACK-PDU ::= SEQUENCE {
invoke-id [0] Unsigned32
service-ACK [1] BACnet-Confirmed-Service-ACK OPTIONAL
-- Context-specific tags 0..1 are NOT used in header encoding
}
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Invoke Id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Service ACK |
. . (optional)
| |
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22. BACnet-Error-PDU BACnet-Error-PDU ::= SEQUENCE {
invoke-id [0] Unsigned32
error [1] BACnet-Error
-- Context-specific tags 0..1 are NOT used in header encoding
}
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Invoke Id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Error |
. .
| |
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23. BACnet-Client-Abort-PDU BACnet-Client-Abort-PDU ::= SEQUENCE {
invoke-id [0] Unsigned32
-- Context-specific tag 0 is NOT used in header encoding
}
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Invoke Id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+