JoelBender / bacpypes

BACpypes provides a BACnet application layer and network layer written in Python for daemons, scripting, and graphical interfaces.
MIT License
303 stars 129 forks source link

SimpleApplication(s) not responding to all WhoIs Broadcasts #473

Closed jasonmckenna00 closed 2 years ago

jasonmckenna00 commented 2 years ago

First off, thank you for providing such an in-depth library.

I'm working on a ReadPropertyMultiple Object and noticed I cannot find a device via WhoIs with the YABE BACnet explorer. When I Wireshark my network I can see the broadcasted WhoIs message generated from YABE. YABE does discover the device when the I-AM is sent on object creation.

When I run the WhoIsIAm sample on a Raspberry Pi on the network, I can see all of my devices respond and present themselves.

One difference I noticed is the YABE sends the broadcast to Destination 255.255.255.255(and doesn't discover) while the WhoIs sample broadcasts to 192.168.1.255.

Any guidance would be useful. Thanks!

JoelBender commented 2 years ago

You're running into a mashup of terms and some old networking concepts. A broadcast address is received by all devices on a network, a multicast address is for a specific group of devices. Back in the days of one IPv4 network per Ethernet network sending a message to "everyone" was similar the Ethernet broadcast, or all 1's, but then the idea of multiple IPv4 subnets on the same Ethernet came around and you didn't necessarily want every device to process "broadcasts" from other subnets, so RFC 922 introduced using all 1's in just the host portion of the address.

BACnet uses the term broadcast the same way, how to reach all of the devices on a network, but with a bit of slight-of-hand makes the definition of a BACnet/IPv4 network to be those devices in the same IPv4 network and using the same UDP port number. That means that a BACnet/IPv4 broadcast is actually an IPv4 multicast. When you provide 192.168.1.12/24 to BACpypes it opens up two listening sockets, one for unicast traffic to 192.168.1.12 and another one for "BACnet broadcast" or IPv4 multicast traffic to 192.168.1.255, other addresses are going to be filtered out by the operating system before being given to BACpypes for processing.

YABE is sending Who-Is requests to the wrong destination, which is probably dependent on some configuration parameters that might need tweaking. There are also funny things (like funny-peculiar) when "binding" to an "any" address like 0.0.0.0 that are operating system dependent.

BACnet also has its own funny-peculiar concept that a BACnet network should be able to span multiple IPv4 networks because we envisioned that IPv4 networking was going to spread faster than the number of possible BACnet networks could keep up. The original idea was to used Class-D multicast addresses as the "broadcast address" for a BACnet/IP network (no v6 yet, that came later). But the problem was that the IP routers in use at the time had limited or no support for Class-D routing (Cisco routers were (and probably still are) quite expensive), so similar to the MBone project that defined mrouter things, the BACnet Broadcast Management Device (BBMD) was born.

jasonmckenna00 commented 2 years ago

Ahhh. Thank you for the clarification. To make sure I understand, a BN device is limited to its network and is listening for messages either directly to the IP address or to its multicast address. The BBMD communicates with the rest of the network to pass information to and from the subnet it resides on. Correct?

The device I'm building will work as either a normal device or a FD depending on the user configuration.

When running the BBMD.py service, my device was able to respond to the WHO-IS even across subnets. The IAM response, however, was a unicast message talking through the BBMD directly to the BACnet client. Is this normal? Shouldn't the BBMD see this message and broadcast it to it's network?