RTI Connext DDS Micro  Version 2.4.11
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
UDP Transport

This user guide explains the configuration of the built-in UDP transport.

Introduction

This document describes the built-in RTI Connext DDS Micro UDP transport and how to configure it.

Overview

The built-in UDP transport (UDP) is a fairly generic UDPv4 transport. The major functionality supported is:

Registering the UDP Transport

The built-in UDP transport is a RTI Connext DDS Micro component that is automatically registered when the DDS_DomainParticipantFactory_get_instance() method is called. In order to change the UDP configuration it is necessary to first unregister the transport as shown below:

DDS_DomainParticipantFactory *factory = NULL;
RT_Registry_T *registry = NULL;
/* The built-in transport does not return any properties (3rd param) or
listener (4th param)
*/
if (!RT_Registry_unregister(registry, "_udp", NULL, NULL))
{
/* ERROR */
}

When a component is registered, the registration takes the properties and a listener as the 3rd and 4th parameters. In general, it is up to the caller to manage the memory for the properties and the listeners. There is no guarantee that a component makes a copy.

The following code-snippet shows how to register the UDP transport with new parameters.

struct UDP_InterfaceFactoryProperty *udp_property = NULL;
/* Allocate a property structure for the heap, it must be valid as long
as the component is registered
*/
udp_property = (struct UDP_InterfaceFactoryProperty *)
malloc(sizeof(struct UDP_InterfaceFactoryProperty));
if (udp_property != NULL)
{
*udp_property = UDP_INTERFACE_FACTORY_PROPERTY_DEFAULT;
/* Only allow network interface "eth0" to be used;
*/
REDA_StringSeq_set_maximum(&udp_property->allow_interface, 1);
REDA_StringSeq_set_length(&udp_property->allow_interface, 1);
*REDA_StringSeq_get_reference(&udp_property->allow_interface, 0) =
REDA_String_dup("eth0");
/* Register the transport again, using the built-in name
*/
if (!RT_Registry_register(registry, "_udp",
(struct RT_ComponentFactoryProperty*)udp_property,
NULL))
{
/* ERROR */
}
}
else
{
/* ERROR */
}

It should be noted that the UDP transport can be registered with any name, but all transport QoS policies and initial peers must refer to this name. If a transport is referred to and it does not exist an error message is logged.

It is possible to register multiple UDP transports with a DomainParticipantFactory, and it is also possible to use different UDP transports within the same domain-participant when multiple network interfaces are available (either physical or virtual).

When UDP transformations are enabled this is feature is always enabled and determined by the allow_interface and deny_interface lists. If any of the lists are non-empty the UDP transports will bind each receive socket to the specific interfaces.

When UDP transformations are not enabled this feature is determined by the value of the enable_interface_bind. If this value is set to RTI_TRUE and the allow_interface and/or deny_interface properties are non-empty the receive sockets are bound to specific interfaces.

Threading Model

The UDP transport creates one receive thread for each unique UDP receive address and port. Thus, by default three UDP threads are created:

Additional threads may be created depending on the transport configuration for a domain-participant, data-reader and data-writer. The UDP transport creates threads based on the following criteria:

For example, if a data-reader specifies its own multicast receive address, a new receive thread will be created.

Configuring UDP Receive Threads

All threads in the UDP transport share the same thread settings. It is important to note that all the UDP properties must be set before the UDP transport is registered. RTI Connext DDS Micro preregisters the UDP transport with default settings when the DomainParticipantFactory is initialized. To change the UDP thread settings, use the following code.

struct UDP_InterfaceFactoryProperty *udp_property = NULL;
struct UDP_InterfaceFactoryProperty udp_property =
UDP_INTERFACE_FACTORY_PROPERTY_DEFAULT;
/* Allocate a property structure for the heap, it must be valid as long
as the component is registered
*/
udp_property = (struct UDP_InterfaceFactoryProperty *)
malloc(sizeof(struct UDP_InterfaceFactoryProperty));
*udp_property = UDP_INTERFACE_FACTORY_PROPERTY_DEFAULT;
/* Please refer to OSAPI_ThreadOptions for possible options */
udp_property->recv_thread.options = ...;
/* The stack-size is platform dependent, it is passed directly to the OS */
udp_property->recv_thread.stack_size = ....
/* The priority is platform dependent, it is passed directly to the OS */
udp_property->recv_thread.priority = ....
if (!RT_Registry_register(registry, "_udp",
(struct RT_ComponentFactoryProperty*)udp_property,
NULL))
{
/* ERROR */
}

UDP Configuration

All the configuration of the UDP transport is done via the struct UDP_InterfaceFactoryProperty structure:

{
/* Inherited from */
struct NETIO_InterfaceFactoryProperty _parent;
/* Sequence of allowed interface names */
struct REDA_StringSeq allow_interface;
/* Sequence of denied interface names */
struct REDA_StringSeq deny_interface;
/* The size of the send socket buffer */
/* The size of the receive socket buffer */
/* The maximum size of the message which can be received */
RTI_INT32 max_message_size;
/* The maximum TTL */
RTI_INT32 multicast_ttl;
#ifndef RTI_CERT
struct UDP_NatEntrySeq nat;
#endif
/* The interface table if interfaces are added manually */
struct UDP_InterfaceTableEntrySeq if_table;
/* The network interface to use to send to multicast */
REDA_String_T multicast_interface;
/* If this should be considered the default UDP interfaces if
no other UDP interface is found to handle a route
*/
/* Disable reading of available network interfaces using system
information and instead rely on the manually configured
interface table
*/
/* Thread properties for each receive thread created by this
NETIO interface.
*/
struct OSAPI_ThreadProperty recv_thread;
/* Bind to specific interfaces
*/
struct UDP_TransformRuleSeq source_rules;
/* Rules for how to transform sent UDP payloads based on the
destination address.
*/
struct UDP_TransformRuleSeq destination_rules;
/* Determines how regular UDP is supported when transformations
are supported.
*/
/* The locator to use for locators that have transformations.
*/
};

allow_interface

The allow_interface string sequence determines which interfaces are allowed to be used for communication. Each string element is the name of a network interface, such as "en0" or "eth1".

If this sequence is empty, all interface names pass the allow test. The default value is empty. Thus, all interfaces are allowed.

deny_interface

The deny_interface string sequence determines which interfaces are not allowed to be used for communication. Each string element is the name of a network interface, such as "en0" or "eth1".

If this sequence is empty, the test is false. That is the interface is allowed. Note that the deny list is checked after the allow list. Thus, if an interface appears in both, it is denied. The default value is empty, thus no interfaces are denied.

max_send_buffer_size

The max_send_buffer_size is the maximum size of the send socket buffer and it must be at least as big as the largest sample. Typically this buffer should be a multiple of the maximum number of samples that can be sent at any given time. The default value is 256KB.

max_receive_buffer_size

The max_receive_buffer_size is the maximum size of the receive socket buffer and it must be at least as big as the largest sample. Typically this buffer should be a multiple of the maximum number of samples that can be received at any given time. The default value is 256KB.

max_message_size

The max_message_size is the maximum size of the message which can be received including any packet overhead. The default value is 8KB. Note that RTI Connext DDS Micro does not support fragmentation.

multicast_ttl

The Time-To-Live (TTL) value is only used for multicast. It limits the number of hops a packet can pass through before it is dropped by a router. The default value is 1.

nat

RTI Connext DDS Micro supports firewalls with NAT. However, this feature has limited use and only supports translation between a private and public IP address. UDP ports are not translated. Furthermore, because RTI Connext DDS Micro does not support any hole punching technique or WAN server, this feature is only useful when the private and public address mapping is static and known in advance. For example, to test between an Android emulator and the host, the following configuration can be used:

UDP_NatEntrySeq_set_maximum(&udp_property->nat,2);
UDP_NatEntrySeq_set_length(&udp_property->nat,2);
/* Translate the local emulator eth0 address 10.10.2.f:7410 to
127.0.0.1:7410. This ensures that the address advertised by the
emulator to the host machine is the host's loopback interface, not
the emulator's host interface
*/
UDP_NatEntrySeq_get_reference(&udp_property->nat,0)->
local_address.kind = NETIO_ADDRESS_KIND_UDPv4;
UDP_NatEntrySeq_get_reference(&udp_property->nat,0)->
local_address.port = 7410;
UDP_NatEntrySeq_get_reference(&udp_property->nat,0)->
local_address.value.ipv4.address = 0x0a00020f;
UDP_NatEntrySeq_get_reference(&udp_property->nat,0)->
public_address.kind = NETIO_ADDRESS_KIND_UDPv4;
UDP_NatEntrySeq_get_reference(&udp_property->nat,0)->
public_address.port = 7410;
UDP_NatEntrySeq_get_reference(&udp_property->nat,0)->
public_address.value.ipv4.address = 0x7f000001;
/* Translate the local emulator eth0 address 10.10.2.f:7411 to
127.0.0.1:7411. This ensures that the address advertised by the
emulator to the host machine is the host's loopback interface
*/
UDP_NatEntrySeq_get_reference(&udp_property->nat,1)->
local_address.kind = NETIO_ADDRESS_KIND_UDPv4;
UDP_NatEntrySeq_get_reference(&udp_property->nat,1)->
local_address.port = 7411;
UDP_NatEntrySeq_get_reference(&udp_property->nat,1)->
local_address.value.ipv4.address = 0x0a00020f;
UDP_NatEntrySeq_get_reference(&udp_property->nat,1)->
public_address.kind = NETIO_ADDRESS_KIND_UDPv4;
UDP_NatEntrySeq_get_reference(&udp_property->nat,1)->
public_address.port = 7411;
UDP_NatEntrySeq_get_reference(&udp_property->nat,1)->
public_address.value.ipv4.address = 0x7f000001;

if_table

The if_table provides a method to manually configure which interfaces are available for use, for example when using IP stacks that do not support reading interface lists. The following example shows how to manually configure the interfaces.

/* The arguments to the UDP_InterfaceTable_add_entry functions are:
The if_table itself
The network address of the interface
The netmask of the interface
The name of the interface
Interface flags. Valid flags are:
UDP_INTERFACE_INTERFACE_UP_FLAG - The interface is UP
UDP_INTERFACE_INTERFACE_MULTICAST_FLAG - The interface supports multicast
*/
0x7f000001,0xff000000,"loopback",
UDP_INTERFACE_INTERFACE_UP_FLAG |
UDP_INTERFACE_INTERFACE_MULTICAST_FLAG))
{
/* Error */
}

multicast_interface

The multicast_interface may be used to select a particular network interface to be used to send multicast packets. The default value is any interface(that is, the OS selects the interface).

is_default_interface

The is_default_interface flag is used to indicate that this RTI Connext DDS Micro network transport shall be used if no other transport is found. The default value is RTI_TRUE.

disable_auto_interface_config

Normally, the UDP transport will try to read out the interface list (on platforms that support it). Setting disable_auto_interface_config to RTI_FALSE will prevent the UDP transport from reading the interface list.

recv_thread

The recv_thread field is used to configure all the receive threads. Please refer to Threading Model for details.

enable_interface_bind

When this is set to TRUE the UDP transport binds each receive port to a specific interface when the allow_interface/deny_interface lists are non-empty. This allows multiple UDP transports to be used by a single DomainParticipant at the expense of an increased number of threads. This property is ignored when transformations are enabled and the allow_interface/deny_interface lists are non-empty.

source_rules

Rules for how to transform received UDP payloads based on the source address.

destination_rules

Rules for how to transform sent UDP payloads based on the destination address.

transform_udp_mode

Determines how regular UDP is supported when transformations are supported. When transformations are enabled the default value is UDP_TRANSFORM_UDP_MODE_DISABLED.

transform_locator_kind

The locator to use for locators that have transformations. When transformation rules have been enabled they are announced as a vendor specific locator. This property overrides this value.

NOTE: Changing this value may prevent communication.


RTI Connext DDS Micro Version 2.4.11 Copyright © Mon Jul 23 2018 Real-Time Innovations, Inc