Fallback to unicast should set options for unicast discovery (#104)

The default behaviour is to allow multicast, with a fallback of
disabling multicast altogether if the selected interface doesn't support
it. The trouble is that the default discovery configuration assumes that
multicast is available, avoiding the "well-known" port numbers and
avoiding sending any participant discovery messages via unicast. The
result is that the process will run in isolation, which is typically not
the desired result. (It is a quite annoying problem because it happens
on Linux when only a loopback interface is available. It appears that
multicast over loopback works fine, if only you try it, but the kernel
doesn't advertise it and so it doesn't get used.)

This commit changes two things: firstly, it this case it forces the
allocation of "well-known" unicast ports, and secondly, it automatically
adds the local interface's address to the discovery address set. This
way, at least communication inside the machine works.

(Note: AssumeMulticastCapable can be still be used to force it to treat
a Linux loopback interface has multicast capable. It is only the default
behaviour that has changed.)

With thanks to @jwcesign who did all the work except writing the commit
message.

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-02-04 13:35:49 +01:00
parent acec84cf0b
commit 69a493ebb3

View file

@ -862,6 +862,7 @@ int rtps_init (void)
{ {
uint32_t port_disc_uc = 0; uint32_t port_disc_uc = 0;
uint32_t port_data_uc = 0; uint32_t port_data_uc = 0;
bool mc_available = true;
/* Initialize implementation (Lite or OSPL) */ /* Initialize implementation (Lite or OSPL) */
@ -949,6 +950,11 @@ int rtps_init (void)
DDS_WARNING("selected interface is not multicast-capable: disabling multicast\n"); DDS_WARNING("selected interface is not multicast-capable: disabling multicast\n");
config.suppress_spdp_multicast = 1; config.suppress_spdp_multicast = 1;
config.allowMulticast = AMC_FALSE; config.allowMulticast = AMC_FALSE;
/* ensure discovery can work: firstly, that the process will be reachable on a "well-known" port
number, and secondly, that the local interface's IP address gets added to the discovery
address set */
config.participantIndex = PARTICIPANT_INDEX_AUTO;
mc_available = false;
} }
} }
if (set_recvips () < 0) if (set_recvips () < 0)
@ -1240,8 +1246,22 @@ int rtps_init (void)
gv.as_disc = new_addrset (); gv.as_disc = new_addrset ();
add_to_addrset (gv.as_disc, &gv.loc_spdp_mc); add_to_addrset (gv.as_disc, &gv.loc_spdp_mc);
/* If multicast was enabled but not available, always add the local interface to the discovery address set.
Conversion via string and add_peer_addresses has the benefit that the port number expansion happens
automatically. */
if (!mc_available)
{
struct config_peer_listelem peer_local;
char local_addr[DDSI_LOCSTRLEN];
ddsi_locator_to_string_no_port (local_addr, sizeof (local_addr), &gv.interfaces[gv.selected_interface].loc);
peer_local.next = NULL;
peer_local.peer = local_addr;
add_peer_addresses (gv.as_disc, &peer_local);
}
if (config.peers) if (config.peers)
{
add_peer_addresses (gv.as_disc, config.peers); add_peer_addresses (gv.as_disc, config.peers);
}
if (config.peers_group) if (config.peers_group)
{ {
gv.as_disc_group = new_addrset (); gv.as_disc_group = new_addrset ();