Control or Restrict the Network Interfaces (NICs) used for discovery and data distribution

In a machine with multiple NICs RTI will automatically use all available interfaces for both discovery and data-distribution. This is good for fault tolerance and ensures the data is sent to all subscribers reachable from the sender.

However there are situations when an application developer might want to control or limit which interfaces are used. For example:

  • Using all interfaces to send data will negatively impact performance. The sender will send data over multiple interfaces which will take additional CPU. The receiver might receive data over multiple interfaces, which will be discarded as duplicate by the RTI middleware but will nevertheless consume some CPU.
  • Using all interfaces may put discovery traffic on networks where there are no subscribers consuming network bandwidth.

To support these scenarios, RTI provides three equivalent alternative mechanisms that can be used to control the NICs that will be used for discovery and data distribution:

  1. Configuring the NICs via XML files (version 4.3 and higher)
  2. Configuring the NICs via properties (Version 4.2 and higher)
  3. Configuring the NICs via Transport Settings (Version 4.0 and higher)

1. Configuring the NICs via XML files (4.3 and higher)

One advantage of this method is that it can be used both with user applications that link RTI Data Distribution Service libraries as well as with all RTI tools and services (RTI Persistence Service, RTI Routing Service, RTI REcording Service, RTI Spreadsheet Addin for Excel, etc.)

Another advantage of this method is the ease of use. No compilation is required. The only thing required is modification or placing of an XML file in the right directory and re-starting the application.

This method uses an XML QoS profile to configure the DomainParticipant and transport properties.

<dds>
  <qos_library name="test"> 
    <qos_profile name="UDPv4_properties">
      <participant_qos>
        <property> 
          <value>
            <element>
              <name>dds.transport.UDPv4.builtin.parent.deny_interfaces</name>
              <value>10.15.*</value>
            </element>
            <element>
              <name>dds.transport.UDPv4.builtin.parent.allow_interfaces</name>
              <value>10.10.*,192.168.*</value>
            </element> 
          </value>
        </property>
      </participant_qos>
    </qos_profile>
 </qos_library>
</dds>

When using RTI Data Distribution Service 4.4 and higher, the XML file can be automatically loaded. If a file named NDDS_QOS_PROFILES.xml is in the $NDDSHOME/resource/xml directory, it will be automatically loaded.

Similarly, if a file named USER_QOS_PROFILES.xml is in the working directory, it will be automatically loaded. See the User’s Manual for more details on XML file loading.

If you are using RTI Data Distribution Service 4.3e, you must call DDSTheParticipantFactory->load_profiles() before creating the DomainParticipant with a profile.

2. Use the DomainParticipant's Property QoS (4.2 and higher)

This method involves using the Property QosPolicy to modify the UDP builtin transport properties. (The Property QoS policy is available in RTI Data Distribution Service 4.2 and higher.) This method is easier than Method 1 because you do not need to create the DomainParticipant disabled first.

2.1 Get the participant_qos and add the properties you want to modify to the QoS:

For example, in C++:

  #define NIC_IP   "10.10.*"
  #define NIC_IP_2 "10.15.*" 
  
  DDS_DomainParticipantQos domainparticipant_qos = DDS_PARTICIPANT_QOS_DEFAULT;
  retcode = DDSTheParticipantFactory->get_default_participant_qos(domainparticipant_qos); 
  if (retcode != DDS_RETCODE_OK) {
      puts("Error, impossible get default participant qos");
      return NULL;
  }

  retcode = DDSPropertyQosPolicyHelper::add_property (
              domainparticipant_qos.property,
              "dds.transport.UDPv4.builtin.parent.deny_interfaces",
              NIC_IP_2, DDS_BOOLEAN_FALSE);

  if (retcode != DDS_RETCODE_OK) {
      printf("Error, impossible add property1");
      return NULL;
  }

    retcode = DDSPropertyQosPolicyHelper::add_property(
              domainparticipant_qos.property,
              "dds.transport.UDPv4.builtin.parent.allow_interfaces", 
                            NIC_IP, DDS_BOOLEAN_FALSE);

    if (retcode != DDS_RETCODE_OK) {
      printf("Error, impossible add property2");
      return NULL;
  }

2.2 Create the DomainParticipant

For example, in C++:

#define DOMAIN_ID 0
DDSDomainParticipant *participant;
participant  = DDSTheParticipantFactory->create_domain_participant(
                                    DOMAIN_ID,
                                    domainparticipant_qos,
                                    NULL,  DDS_STATUS_MASK_NONE);

3. Use the Transport Settings (4.0 and above): 

If you are using versions of RTI DDS prior to 4.2. then the only option available is to explicitly set the transport properties. The result is the same but the code is a bit more complicated because the transport settings are an immutable QoS property that can only be set after the participant has been created but before it has been enabled.

3.1. Before creating the DomainParticipant, make sure the DomainParticipant will be created in a disabled state.

For example, in C++:

  retcode = DDSTheParticipantFactory->get_qos(factory_qos);
  factory_qos.entity_factory.autoenable_created_entities = DDS_BOOLEAN_FALSE;
  retcode = DDSTheParticipantFactory->set_qos(factory_qos);

3.2. Create the domain participant and get the builtin transport properties

For example, in C++:

#define DOMAIN_ID 0
DDS_DomainParticipantQos domainparticipant_qos = DDS_PARTICIPANT_QOS_DEFAULT;
DDSDomainParticipant *participant;
participant  = DDSTheParticipantFactory->create_domain_participant(
                                 DOMAIN_ID, 
                                 domainparticipant_qos, 
                                 NULL,  DDS_STATUS_MASK_NONE);

struct NDDS_Transport_UDPv4_Property_t property = NDDS_TRANSPORT_UDPV4_PROPERTY_DEFAULT;
              
if (NDDSTransportSupport::get_builtin_transport_property 
     (participant, DDS_TRANSPORTBUILTIN_UDPv4,
     (struct NDDS_Transport_Property_t&)property) != DDS_RETCODE_OK) 
  {
      printf("***Error: get builtin transport property\n");                           
  } 

3.3. Call set_builtin_transport_property() before the DomainParticipant is enabled.

For example, in C++:

#define NIC_IP "10.10.*"

  /* Set the allowed interface(s) */
  property.parent.allow_interfaces_list = (char **)calloc(1, sizeof(char*));
  property.parent.allow_interfaces_list[0] = (char *)strdup(NIC_IP);
  property.parent.allow_interfaces_list_length = 1;

  if (NDDSTransportSupport::set_builtin_transport_property 
             (participant, DDS_TRANSPORTBUILTIN_UDPv4,
             (struct NDDS_Transport_Property_t&)property) != DDS_RETCODE_OK) 
  {
    printf("***Error: set builtin transport property\n");                           
  }

To deny a subset of interfaces, you would do exactly the same as above, but use "deny_interfaces_list" instead of "allow_interfaces_list".

3.4. Enable the DomainParticipant:

For example, in C++:

retcode = participant->enable();

The allow/deny lists are only used during transport initialization; after the DomainParticipant has been enabled, you may dispose of the memory allocated for them.

Comments

Per the Connext 5.0.0 User's Manual, page 15-7, the variable name appears to be "parent.allow_interfaces_list" and not "parent.allow_interfaces" as shown in this article.  Which is correct?

Although I don't believe it is documented, both parent.allow_interfaces_list and parent.allow_interfaces are correct.

Hello,

I am running the Shapes Demo with RTI Connext 5.1.0  on two different machines. The one machine is connected to two networks and when I publish a data, it is found on both networks. I would like to use only the one and not the other. I read this article which seems to me to solve my problem but I don't understand how to use the xml file. Thank you!