Hello,
This isn't strictly about Avahi, but I have some questions to ask and
assertions I'd like to validate. What's led me down the rabbit hole of
Zeroconf, mDNS, DNS-SD, and friends is out of interest in making stuff easy to
use. For a specific example, GeoClue is configured to look for services of type
_nmea-0183._tcp to find services providing real-time geopositioning
information. This is a one-way data feed; the server simply sends a few lines
of US-ASCII every second and anything sent by the client can be ignored. Using
UDP over multicast would be a lot more efficient and better support the need
for low latency, so I've been researching how to do this. Many of you likely
already know much of what follows, but I'd like to know if I got anything wrong.
Pertinent standards such as POSIX
athttps://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_10_20_04 define much of
what's needed to use IPv6 multicast, including the IPV6_JOIN_GROUP socket options. When some protocol or
application always uses some fixed multicast address that can be determined ahead of time, like the one for
mDNS given
byhttps://www.iana.org/assignments/ipv6-multicast-addresses/ipv6-multicast-addresses.xhtml#xpointer(/html/body//table[@id="table-link-local"]/tbody/tr/td[text()="mDNSv6"]/..)
then this may be all that is needed. However many applications only need a transient multicast address, or
they're too esoteric to warrant an IANA registration (perhaps because interoperability with another
implementation isn't a concern). The question then is how should one "make up" a multicast address
on-the-fly?
One perk of using these IANA-assigned addresses is that the protocol or purpose
for some multicast group is already tied to the address. If you want to send a
message using SIP to anyone on your link that's listening, just send a datagram
to FF02::175. This differs when using a dynamic multicast address. Consider,
for my use case, if I had a GNSS receiver getting geolocation information and
wanted to share it on the local link as a server. Even if I come up with a
multicast address on-the-fly for this purpose, how will clients know to find
me? Fortunately this is just a service discovery problem and Avahi can solve it
in the same way as for the TCP service case: I can publish _nmea-0183._udp
DNS-SD information and based on the IPv6 address format it's clearly a
multicast address. Therefore any prospective clients can just join the group
and listen for datagrams on the port designated by the SRV record.
There are, of course, other methods of announcing and discovering services than
just DNS-SD. Any of those mechanisms ought to work to announce the birth of a
multicast group for some use case, even in conjunction with DNS-SD, so it's
easy to make such a service discoverable.
That means there's only one problem for application writers left: how do you
get a dynamic multicast address anyway? An application wishing to make a new
group should have a convenient way to do this, but as far as I know, there's
not any way for an application on GNU/Linux to do this correctly. I couldn't
even find a maintained third-party library after searching. There are a couple
different network protocols to solve this address allocation problem (more on
those in a moment), but is there any libre code that's able to use any of them?
The informational RFC 2771 (from the year 2000, before I was born!) articulates "An
Abstract API for Multicast Address Allocation". This document only uses pseudocode
and is intentionally programming-language-agnostic, but describes the considerations
needed to make an API for application instances to get multicast addresses to call their
very own. Despite its age, that document appears to still be a very good role model for
what an API should look like. It also demonstrates such an API can be designed so the
particular means by which an address is allocated is an implementation detail.
Application writers generally aren't concerned with how an appropriate address is
obtained and for the sake of portability this should be done however the operating system
or environment sees fit.
The most well-established scheme for multicast address allocation is MADCAP, which works in a
DHCP-like way with a central server that's authoritative over the scope in question and gives out
leases. This looks like the way Windows has gone, and in fact, Microsoft has a C/C++ API for
this:https://learn.microsoft.com/en-us/windows/win32/api/madcapcl/ and despite the name of the
header, the function names read as "multicast request address", "multicast release
address", and so forth. This is more DHCP-like than SLAAC-like which one might say is ugly in
the year 2025, but if that works for them (and I do believe it does in a Windows Server/Active
Directory business environment with Windows machines providing compatible DHCP and MADCAP server
implementations), that's good for them.
That Windows API doesn't seem to have any MADCAP assumptions baked into
it and instead is more generic like RFC 2771, so if it helps adoption by libre
applications, maybe an API-compatible shim could be helpful? (I wonder if
Winelib—which is like Cygwin in reverse, to allow compiling Windows application
source code for Unix-like systems—has this.)
As recently as this year the informational internet draft "Multicast Lessons Learned from
Decades of Deployment Experience" has analyzed what's gone wrong and caused trouble for uptake
of multicast outside specialized environments.
Athttps://www.ietf.org/archive/id/draft-ietf-pim-multicast-lessons-learned-05.html#name-dynamic-multicast-group-add
the authors make quite clear that MADCAP isn't the goal to set sight on anymore: "It was
later determined that multicast addresses really should be dynamically assigned by a decentralized,
and zero configuration, protocol for many of todays environments." The two strongest options
for moving forward are the Zeroconf Multicast Address Allocation Protocol (ZMAAP), which has been
in various drafts for decades, and the new Group Address Allocation Protocol (GAAP). Hereafter I'll
focus on the former, but I do wonder where in the GNU/Linux network stack an implementation of the
latter might sit.
A very old draft for ZMAAP is athttps://datatracker.ietf.org/doc/draft-ietf-zeroconf-zmaap/ but the only reason I mention this older version is because "An API for the Zeroconf Multicast Address Allocation Protocol (ZMAAP)" https://datatracker.ietf.org/doc/draft-ietf-zeroconf-zmaap-api/ was
also jointly published. That draft builds on the "abstract API" mentioned before and actually makes it concrete with C and Java interfaces. Please correct me if I'm wrong, but to the best of my knowledge there aren't any actual implementations of this, at least not surviving ones for GNU/Linux. The document is slightly misnamed; a more accurate title would be something like "An API for Mulicast Address Allocation with Due Consideration for the Capabilities of ZMAAP". As they say, "It should be transperant [sic] to the API whether the allocations are done using ZMAAP, MADCAP or some other mechanism."
From a brief skim the C API looks decent, except their data structures use
some not-POSIX-like conventions. In the 25 years since the document was
published a very good consensus (even with Windows) has been formed about the
use of data types and modernizing the interfaces would be nice. In particular:
• 'struct sockaddr' is used with the intent of holding both IPv4 and IPv6
addresses; 'struct sockaddr_storage' should be used instead
• they store the address family separately from the socket address structures
which is unnecessary, but also define the constants '1' for IPv4 and '2' for
IPv6; the (struct sockaddr){}.sa_family member should suffice and allow using
AF_INET, AF_INET6, etc. constants as usual
But in general, this API is the closest thing to exactly what I need to write a
nice multicast application. (Well, an actual implementation will be needed too,
but don't ruin my dream…)
Both that draft for ZMAAP and the one for the proposed C/Java APIs are from
2000 and long dead, but an active standards-track internet draft (yes, not
expired!) for the ZMAAP protocol is available
athttps://datatracker.ietf.org/doc/draft-ietf-pim-ipv6-zeroconf-assignment/ and
there's also a statement of exactly the problems it solves
athttps://datatracker.ietf.org/doc/html/draft-ietf-pim-zeroconf-mcast-addr-alloc-ps
In their usage of the term, they use "zeroconf" basically as a synonym for
Multicast DNS. There are other tools under the umbrella of zero configuration, and
strictly speaking, the alternative Group Address Allocation Protocol (GAAP) is probably
one of them. ZMAAP really should be on the radar of Avahi folks, and in fact, I think the
right place for an implementation is in Avahi directly. The method involved is basically
to synthesize a name under the 'eth-addr.arpa.' DNS zone and use Multicast DNS with the
appropriate scope to detect collisions. Because it's a bad idea to try running multiple
mDNS stacks—as remarked in avahi-daemon.conf(5)—any ZMAAP implementation will need to go
through whatever daemon has taken up responsibility for mDNS, be it Avahi,
systemd-resolved, or otherwise.
Additionally, as I described much earlier in this mail with regards to the "service discovery
problem" for applications wanting to join dynamic multicast groups that might've already been
created, many multicast applications will want Avahi's help to publish DNS-SD records anyway.
Lastly, for some use cases where you want everyone to converge on the same dynamic multicast group
(perhaps a multiplayer video game that lets players drop in and out at any time), there could be
race conditions or quirks from separating checks for an established multicast group for an
application versus deciding to allocate an address and spawn your own. (For example an application
may ask Avahi to "see if there's already a group for _bingo._udp, but if there's not, then I
must be the first one here so let's set one up".)
In conclusion, I've been puzzled trying to make a mostly-custom application using multicast and I asked
"How do other libre applications pick their multicast addresses for their own usage?". The
conclusion I've drawn is "They don't." I couldn't find any modern information about real-world
existing practice for these sorts of problems, so I've espoused it here for future reference and so you can
tell me what I got wrong. Otherwise it looks like Avahi should provide an API for multicast address
allocation, concentrating on ZMAAP, and which need not match the existing and proposed APIs but may still
borrow inspiration from them. I don't mean to "voluntell" the Avahi developers what to do but
instead articulate a problem statement and solution idea so it can be consciously accepted or declined.
Thanks,
John