How to determine with Wireshark when discovery is completed

This document describes how to check when the discovery process is completed. The tool that is going to be used is Wireshark. Before the analysis, these are some links that are of interest:

  • Link: where to download Wireshark and how to apply the colors that differentiate discovery and user data traffic.
  • Link: zip file containing the code that has been used for this analysis and the Wireshark trace.

Scenario

For this analysis, a DomainParticipant with 7 DataWriters will discover another DomainParticipant with 6 DataReaders. The scenario is as follows:

 

Built-in entities

There is a set of 6 built-in entities in every DomainParticipant that are going to handle the discovery process. This means that we use DDS not just for user traffic, but also for discovery itself.

  • The Participant Built-in DataWriter and DataReader handle the participant discovery phase. They will share DATA(p) packets. These packets contain the participant’s GUID, its locators, and some of the QoS of the participant.
  • The Publication Built-in DataWriter and DataReader handle the endpoint discovery phase for DataWriters. They will share DATA(w) packets. These packets contain the types for the DataWriter, the topic name, and the DataWriter’s QoS policies that are needed for matching. A DATA(w) submessage is shared for each DataWriter. This means that with the example above, a total of 7 DATA(w) submessages need to be shared.
  • The Subscription Built-in DataWriter and DataReader handle the endpoint discovery phase for DataReaders. They will share DATA(r) packets. These packets contain the types for the DataReader, the topic name, and the DataReader’s QoS policies that are needed for matching. A DATA(r) submessage is shared for each DataReader. This means that with the example above, a total of 6 DATA(r) submessages need to be shared.

The following image contains a summary showing the built-in DataWriters and DataReaders described above, along with the topics they share:

Wireshark trace

This section shows the Wireshark analysis that must be performed in order to check when the discovery phase between two endpoints is completed. In the following image, you can see how the subscriber and the publisher share the DATA(p) packets.

 

Endpoint discovery phase: DataReaders

After the DATA(p) packets have been received, we know that the participant discovery phase is over when the publication/subscription DataWriters send a heartbeat. In the following image, you can see how the subscription DataWriter for the subscriber sends a heartbeat:

As you can see, the firstAvailableSeqNumber field is 1 and the lastSeqNumber field is 6. These represent the number of DataReaders the subscribing application contains. This heartbeat is followed by an ACKNACK from the subscriptions DataWriter from the publisher:

With this ACKNACK, the publisher is letting the subscriber know that it needs to receive the 6 samples, that is, the 6 DATA(r). After that, the subscriptions DataWriter from the subscriber sends the 6 DATA(r):

DATA(r) submessages contain the types, topic names, and QoS policies of the DataReaders. Those 6 samples are sent through a reliable channel; that is why a heartbeat is sent along with the packet. With firstSeqNumber (1) and lastSeqNumber (6), the subscriptions DataWriter wants the publisher to confirm the reception of the 6 DATA(r).

Then, the subscriptions DataWriter on the publisher side will send an ACKNACK acknowledging the 6 DATA(r):

At this point, the discovery of remote readers is complete. 

Endpoint discovery phase: DataWriters

In the previous section, the endpoint discovery phase for DataReader entities has been analyzed. In this section, we will analyze the endpoint discovery phase for DataWriters.

Note: in DDS, it may be that the discovery of DataWriters happens before the discovery of DataReaders, or viceversa.

In the following image, you can see how the publications DataWriter for the publisher sends a heartbeat.

In this heartbeat, the firstAvailableSeqNumber field is 1 and the lastSeqNumber field is 7. These represent the number of DataWriters the publishing application contains (7). This heartbeat is followed by an ACKNACK from the publications DataWriter from the subscriber:

With this ACKNACK, the subscriber is telling the publisher it needs to receive the 7 samples, that is, the 7 DATA(w). After that, the publications DataWriter from the publisher can deliver the packet:

DATA(w) contain the types, topic names, and QoS policies of the DataWriters. Those 7 samples are also sent reliably, so a heartbeat follows them. With firstSeqNumber (1) and lastSeqNumber (7), the publications DataWriter wants the subscriber to confirm the reception of the 7 DATA(w).

Then, the publications DataWriter on the publisher side will send an ACKNACK acknowledging the 7 DATA(w):

At this point, the discovery of remote writers from the subscriber side is complete. 

Useful filters

The ID for the built-in writers and readers is defined in the DDS standard. These are the IDs:

  • Publications writer: 0x000003c2
  • Publications reader: 0x000003c7
  • Subscriptions writer: 0x000004c2
  • Subscriptions reader: 0x000004c7

Therefore, if you are interested in the packets that are shared during the discovery process, you may use a filter. For instance, the following filter will show the packets involved in the endpoint discovery phase for DataReaders:

rtps.sm.wrEntityId == 0x000004c2

In case you want to show the packets that are involved in the endpoint discovery phase for DataWriters, you should use the following filter:

rtps.sm.wrEntityId == 0x000003c2

The following graph represents a system in which three Connext DDS applications are involved. This is the I/O Graph, which can be brought up from Wireshark → Statistics → I/O Graph.In black, all the DDS traffic is shown with the rtps filter. In blue, the endpoint discovery traffic is represented with this filter:

rtps.sm.wrEntityId == 0x000003c2 || rtps.sm.wrEntityId == 0x000004c2

This is the order in which applications are launched in that scenario:

  • t = 0s: the first application is launched.
  • t = 38s: the second application is launched.
  • t = 65s: the third application is launched.

As you can observe, there are more packets captured every time a new application is launched. Every 30 seconds (t = 30s, t = 60s), the first application sends DATA(p) packets.

The first time we see the blue graph is in t = 38s, which is when the endpoint discovery packets are shared between applications. You may observe that for t = 42s, the blue graph goes down to 0 again. That indicates the endpoint discovery phase is over for those applications.

Then, at t = 65s, when the third application is launched, we see endpoint discovery traffic again. At t = 68s, there is no more blue graph, which implies that the endpoint discovery phase has successfully finished.

This way, you can use the I/O graph to detect when the endpoint discovery phase has successfully finished. 

DataWriters and DataReaders start communicating after discovery

In this example, the DataWriters had published some samples before discovering the DataReaders. Since their durability is VOLATILE, writers need to let the readers know that they will not receive the first samples. In this case, DataWriter 1 had already written one sample. Communication of the “already written” samples is done by means of a GAP message sent to every matched DataReader.

In the following image, you can see how the DataWriter sends 6 GAP messages (one per matched DataReader). With the information the message contains, the DataWriter is telling the DataReaders that the communication will start with the sample’s sequence number 2, so sequence number 1 has been skipped (already overwritten by the DataWriter before discovery occurred). In the image, you can also see that the next packet is a sample with sequence number 2 (in the second column from the right):