How to capture traffic if my Connext DDS applications are communicating through shared memory
Wireshark and tcpdump are very powerful tools which you can use to capture traffic. They may come in handy when debugging issues with your DDS applications. These tools can capture all kinds of packets: RTPS, UDP, TCP, IP… However, they cannot capture traffic if your applications are communicating through shared memory. This article will describe two different methods to capture this traffic.
Method 1. Change the transport to UDPv4
If you want to debug your applications which are communicating through shared memory, one of the approaches to capture RTPS packets would be to change the transport to UDPv4. By default, the transport mask is UDPv4|SHMEM
. This way, if the applications are in the same machine, they will communicate through shared memory. The transport can be changed to UDPv4 by simply using the following snippet. After applying this QoS, the applications will communicate through the loopback interface:
<participant_qos> <transport_builtin> <mask>UDPv4</mask> </transport_builtin> </participant_qos>
However, there is a side effect if you change the transport your applications use: the behavior in shared memory and UDPv4 is different. This way, if you want to debug your applications using this method, you won’t be capturing exactly the same traffic that was being sent through shared memory.
Method 2. Send all the traffic to a UDP socket apart from shared memory
Note: The following is an experimental feature that should not be used in production for versions prior to RTI Connext DDS Professional 6.0.0. For RTI Connext DDS Professional 6.0.0 and future versions, you have the enable_udp_debugging QoS policy available. Both are recommended only for debugging purposes.
This approach will let your applications continue communicating through shared memory. There is a functionality in the shared memory transport which will copy all the outgoing traffic to a UDP socket. By default, the traffic will be sent to the first available NIC, through the port 7399 and to the IP multicast address 239.255.1.2. Both the port and the IP address can be changed by configuring the DomainParticipant QoS.
These are the instructions you will need to follow to enable this functionality:
1. Create a disabled participant. This can be easily done by applying the following QoS settings:
<participant_factory_qos> <entity_factory> <autoenable_created_entities>0</autoenable_created_entities> </entity_factory> </participant_factory_qos>
2. Enable the CONTENT verbosity for the builtin shared memory transport. To do this, you will need to add this include:
#include "transport/transport_log.h"
Call this API after creating the DomainParticipant:
NDDS_Transport_Log_setBitmaps(NDDS_TRANSPORT_SUBMODULE_MASK_SHMEM, RTI_LOG_BIT_CONTENT);
3. Enable the DomainParticipant:
participant->enable();
4. Start a capture over all the interfaces. However, the first interface with a valid IPv4 address should be enough.
5. Set the following filter to analyze the capture if you are using the default address and port: udp.port == 7399
In order to change the default IP address and the port, you can use this snippet:
<participant_qos> <property> <value> <!-- Force traffic destination address to be 10.50.2.130 --> <!-- Use "," instead of "." for the IP address --> <element> <name>dds.transport.shmem.builtin.snifferAddress.network_ordered_value</name> <value>10,50,2,130</value> </element> <!-- Force the port to be to be 12345 --> <element> <name>dds.transport.shmem.builtin.snifferPort</name> <value>12345</value> </element> </value> </property> </participant_qos>
Example
You will find an example attached: shared_memory_and_udp.zip. In this example, you will see how to configure your applications so they can use Method 2 described above. All the necessary information to generate code, compile, and run the example is in the README.txt file.