Generate (hopefully) decent DDSI2.2-compliant GUID

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-08-24 18:06:49 +02:00 committed by eboasson
parent a632f80000
commit 87398bdc98
3 changed files with 42 additions and 18 deletions

View file

@ -158,7 +158,7 @@ struct q_globals {
/* GUID to be used in next call to new_participant; also protected /* GUID to be used in next call to new_participant; also protected
by privileged_pp_lock */ by privileged_pp_lock */
struct nn_guid next_ppguid; struct nn_guid ppguid_base;
/* number of up, non-loopback, IPv4/IPv6 interfaces, the index of /* number of up, non-loopback, IPv4/IPv6 interfaces, the index of
the selected/preferred one, and the discovered interfaces. */ the selected/preferred one, and the discovered interfaces. */

View file

@ -701,18 +701,14 @@ dds_return_t new_participant_guid (const nn_guid_t *ppguid, struct q_globals *gv
dds_return_t new_participant (nn_guid_t *p_ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist) dds_return_t new_participant (nn_guid_t *p_ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
{ {
nn_guid_t ppguid; union { uint64_t u64; uint32_t u32[2]; } u;
u.u32[0] = gv->ppguid_base.prefix.u[1];
ddsrt_mutex_lock (&gv->privileged_pp_lock); u.u32[1] = gv->ppguid_base.prefix.u[2];
ppguid = gv->next_ppguid; u.u64 += ddsi_iid_gen ();
if (gv->next_ppguid.prefix.u[2]++ == ~0u) p_ppguid->prefix.u[0] = gv->ppguid_base.prefix.u[0];
{ p_ppguid->prefix.u[1] = u.u32[0];
ddsrt_mutex_unlock (&gv->privileged_pp_lock); p_ppguid->prefix.u[2] = u.u32[1];
return DDS_RETCODE_OUT_OF_RESOURCES; p_ppguid->entityid.u = NN_ENTITYID_PARTICIPANT;
}
ddsrt_mutex_unlock (&gv->privileged_pp_lock);
*p_ppguid = ppguid;
return new_participant_guid (p_ppguid, gv, flags, plist); return new_participant_guid (p_ppguid, gv, flags, plist);
} }

View file

@ -1033,11 +1033,39 @@ int rtps_init (struct q_globals *gv)
ddsrt_mutex_init (&gv->privileged_pp_lock); ddsrt_mutex_init (&gv->privileged_pp_lock);
gv->privileged_pp = NULL; gv->privileged_pp = NULL;
/* Template PP guid -- protected by privileged_pp_lock for simplicity */ /* Base participant GUID. IID initialisation should be from a really good random
gv->next_ppguid.prefix.u[0] = locator_to_hopefully_unique_uint32 (&gv->ownloc); generator and yield almost-unique numbers, and with a fallback of using process
gv->next_ppguid.prefix.u[1] = (unsigned) ddsrt_getpid (); id, timestamp and a counter, so incorporating that should do a lot to construct
gv->next_ppguid.prefix.u[2] = 1; a pseudo-random ID. (The assumption here is that feeding pseudo-random data in
gv->next_ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; MD5 will not change the randomness ...) Mix in the network configuration to
make machines with very reproducible boot sequences and low-resolution clocks
distinguishable.
This base is kept constant, prefix.u[1] and prefix.u[2] are then treated as a
64-bit unsigned integer to which we add IIDs to generate a hopping sequence
that won't repeat in the lifetime of the process. Seems like it ought to work
to keep the risks of collisions low. */
{
uint64_t iid = toBE8u (ddsi_iid_gen ());
ddsrt_md5_state_t st;
ddsrt_md5_byte_t digest[16];
ddsrt_md5_init (&st);
ddsrt_md5_append (&st, (const ddsrt_md5_byte_t *) &iid, sizeof (iid));
for (int i = 0; i < gv->n_interfaces; i++)
{
const struct nn_interface *intf = &gv->interfaces[i];
ddsrt_md5_append (&st, (const ddsrt_md5_byte_t *) &intf->loc.kind, sizeof (intf->loc.kind));
ddsrt_md5_append (&st, (const ddsrt_md5_byte_t *) intf->loc.address, sizeof (intf->loc.address));
}
ddsrt_md5_finish (&st, digest);
/* DDSI 2.2 requires the first two bytes of the GUID to be set to the vendor
code -- a terrible waste of entropy ... */
gv->ppguid_base.prefix.s[0] = NN_VENDORID_ECLIPSE.id[0];
gv->ppguid_base.prefix.s[1] = NN_VENDORID_ECLIPSE.id[1];
DDSRT_STATIC_ASSERT (sizeof (gv->ppguid_base.prefix.s) > 2 && sizeof (gv->ppguid_base.prefix.s) - 2 <= sizeof (digest));
memcpy (&gv->ppguid_base.prefix.s[2], digest, sizeof (gv->ppguid_base.prefix.s) - 2);
gv->ppguid_base.entityid.u = NN_ENTITYID_PARTICIPANT;
}
ddsrt_mutex_init (&gv->lock); ddsrt_mutex_init (&gv->lock);
ddsrt_mutex_init (&gv->spdp_lock); ddsrt_mutex_init (&gv->spdp_lock);