Configure RTI Connext DDS to not use Multicast

By default RTI Connext DDS will use multicast to discover other DDS Participants in the network. Unless explicitly configured to be differently, the multicast IP address used for discovery will be 239.255.0.1 as specified the OMG DDS Interoperability Wire Protocol (RTPS). The RTPS protocol also specifies that the port numbers used for multicast discovery will be obtained from the DDS DomainId using the formula:

multicastDiscoveryPort =  PB  +  DG*DomainId 

where:

PB (PortBase) = 7400,  DG (DomainIdGain) = 250

So for DomainId=0 (the default) the port will be 7400, for DomainId =1, it will be 7650, and so forth.

While this works well in many scenarios there are situations where it is desirable to disable the use of multicast both for discovery and for regular data communications.

To disable the use of multicast you must perform three steps:

  1. Disable multicast in the UDPv4 transport
  2. Configure the initial peers list not to use multicast
  3. Remove any multicast receive addresses

This can be done in various ways. The two simplest methods are:

  1. Using XML QoS
  2. Using the application API and the NDDS_DISCOVERY_PEERS environment variable. 

1. Using XML QoS

This method uses an XML QoS profile to configure the DomainParticipant and transport properties. The snippet below shows the settings in the participant_qos that disable the use of multicast: 

<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="Z:/dom/apps_rti/Foo/RTI/ndds.4.5f/resource/qos_profiles_4.5f/schema/rti_dds_qos_profiles.xsd"
     version="4.5f">
  <qos_library name="ExampleLibrary">
    <qos_profile name="NoMulticastProfile" is_default_qos="true">
      <participant_qos>
        <discovery>
          <!-- disable the reception multicast for discovery  -->
          <multicast_receive_addresses/>
          <!-- Configure the destinatons of disovery announcements. Do not list any multicast addresses -->
          <!--This is the list of transports destinations where the participant will announce its presence -->
          <initial_peers>
            <!-- use shared memory for participants the same computer -->
            <element>builtin.shmem://</element>
            <!-- also use IP loopback for  participants the same computer -->
            <element>builtin.udpv4://127.0.0.1</element>
            <!-- list here the IP addresses of all computers where thetre may be participants -->
            <!-- THIS IS ONLY AN EXAMPLE. YOU MUST ADJUST TO MATCH YOUR CONFIGURATION -->
            <element>builtin.udpv4://192.168.1.1</element>
            <element>builtin.udpv4://192.168.1.2</element>            
            <!-- You can also use machine names here -->
            <element>builtin.udpv4://mypeer1.acme.com</element>
            <element>builtin.udpv4://mypeer2.acme.com</element>
          </initial_peers>
        </discovery>
 
        <!-- disable the use of multicast at the UDP transport level -->
        <!-- see http://community.rti.com/docs/html/api_cpp/group__NDDS__Transport__UDPv4__Plugin.html -->
        <property>
          <value>
            <element>
              <name>dds.transport.UDPv4.builtin.multicast_enabled</name>
              <value>0</value>
           </element>
          </value>
        </property>
      </participant_qos>
    </qos_profile>
  </qos_library>
</dds>

The configuration of the participant_qos shown above must be done for the QoS Profile that the application uses. This can be done in various ways. For example including it in a file named USER_QOS_PROFILES.xml placed in the working directory from which the application is run. Other options are described in the RTI Connext Users Manual (e.g. for RTI Connext DDS version 4.5f this can be found in section 15.2 titled "How to Load XML-Specified QoS Settings").

2. Using the application API and the NDDS_DISCOVERY_PEERS environment variable.

If loading an XML configuration file is not desirable, this alternative mechanism uses only the application API and the setting of an environment variable. The code snippet shown here uses the C++ API. The method is available in all other language APIs as well.

DDS_DomainParticipantQos participant_qos;
DDS_ReturnCode retcode;

// Get the default value of the DomainParticipantQos what will be use to create the DDS DomainParticipant
retcode = DDSTheParticipantFactory->get_default_participant_qos(participant_qos);
if ( retcode != DDS_RETCODE_OK ) {
    puts("Error getting default participant QoS");
    return NULL;
}

// Indicate that the participant should not listen to multicast addresses for discovery
participant_qos.discovery.multicast_receive_addresses.length(0);

// Modify the  Property QoS inside the participant_qos to disable the use of multicast by the UDPv4 transport
retcode = DDSPropertyQosPolicyHelper::add_property( participant_qos.property,
          "dds.transport.UDPv4.builtin.multicast_enabled",  "0",
          DDS_BOOLEAN_FALSE);
    
if ( retcode != DDS_RETCODE_OK) {
    printf("Error, impossible add property");
    return NULL;
}
   
DDSDomainParticipant *participant;
DDS_DomainId_t   domainId = 0;

// Create the DomainParticipant specifying the modified  participant_qos
participant = DDSTheParticipantFactory->create_participant(
              domainId,  participant_qos, 
              NULL /* listener */,  DDS_STATUS_MASK_NONE);

The code snippet above configures the participant to not listen to multicast for discovery and also completely disables the use of multicast by the UDP transport. In addition to this we must indicate to the participant the addresses where it should announce its presence. This can also be done via code by setting the participant_qos.discovery.initial_peers array to contain the addresses of those peers. But this would become compiled in and hence hard to change. So it is often better to specefy this by setting the NDDS_DISCOVERY_PEERS environment variable as in:

On Linux/Unix/MacOS (these are example addresses, replace as appropriate)

export NDDS_DISCOVERY_PEERS=builtin.shmem://;127.0.0.1;192.168.1.1;192.168.1.2

On Windows (these are example addresses, replace as appropriate)

set NDDS_DISCOVERY_PEERS=builtin.shmem://;127.0.0.1;192.168.1.1;192.168.1.2

Note 1. It is possible to mix the above two approaches. For example use XML to just disable the use of multicast but not set the initial peers in the XML (the configuration between the <initial_peers> and tags). And instead set the NDDS_DISCOVERY_PEERS environment variable.

Note 2. If you disable the use of multicast as specified above, but do not also change the discovery peers, either via the XML directive <initial_peers> shown in Method 1 above, or else by changing the environment variable "NDDS_DISCOVERY_PEERS", as shown in Method 2 above you will encounter two problems: (a) You will some error messages, and (b) the applications running on different computers will not communicate.

The error messages you will see are similar to the ones shown here:

can't reach:
   locator:
      transport: 1
      address: 0000:0000:0000:0000:0000:0000:EFFF:0001
      port: 7400
      encapsulation:
   transport_priority: 0
   aliasList: ""
can't reach:
   locator:
      transport: 1
      address: 0000:0000:0000:0000:0000:0000:EFFF:0001
      port: 7400
      encapsulation:
   transport_priority: 0
   aliasList: ""
can't reach:
   locator:
 Writing Hello, count 0
     transport: 1
      address: 0000:0000:0000:0000:0000:0000:EFFF:0001
      port: 7400
      encapsulation:
   transport_priority: 0
   aliasList: ""
 

This error is caused by the fact that the discovery peers have not been changed from the default which include the multicast address 239.255.0.1 (which in hexadecimal is EF.FF.00.01) 

To resolve these two problems complete the steps specified above. Namely if you are using Method 1 configure the initial peers using the XML tag <initial_peers> and do not include any multicast addresses. If you are following Method 2 then also set the NDDS_DISCOVERY_PEERS environment variable as described.

Attachments: 

Comments

this tutorial worked like charm.