Skip to content

Unique Network Flows and Static Endpoint Discovery are incompatible #6348

@thomasmoore-torc

Description

@thomasmoore-torc

Is there an already existing issue for this?

  • I have searched the existing issues

Expected behavior

Setting the "fastdds.unique_network_flows" property on a data reader with static endpoint discovery should result in successful communication between the data reader and matched data writers, or an error should be raised.

Current behavior

In ROS2 Jazzy and later, the "fastdds.unique_network_flows" property is set on the data reader for the ros_discovery_info topic. If static endpoint discovery is enabled for the participants, communication on the ros_discovery_info topic will silently fail because the data writers are unaware that the data reader is using a non-standard locator and will attempt to transmit data to the standard RTPS port for the reader's entity ID.

Steps to reproduce

The following script illustrates the issue:

## Reproducer: ros_discovery_info graph updates are lost with static EDP

# Requirements:
# - Linux host
# - Docker
# - Host networking available
#
# This shows:
# 1. Baseline ROS 2 Jazzy behavior without static EDP: `ros2 topic info -v /topic1`
#    shows normal graph information and messages are received.
# 2. Static EDP behavior with minimal Fast DDS XML: `ros2 topic info -v /topic1`
#    no longer shows the graph information for the publisher.

set -euo pipefail

docker rm -f jazzy-static-edp-repro >/dev/null 2>&1 || true
docker run -d --name jazzy-static-edp-repro --network host ros:jazzy-ros-base sleep infinity

cleanup() {
  docker rm -f jazzy-static-edp-repro >/dev/null 2>&1 || true
}
trap cleanup EXIT

echo
echo "=== Baseline: no static EDP ==="
docker exec jazzy-static-edp-repro bash -lc \
  'source /opt/ros/jazzy/setup.bash && ros2 daemon stop || true'

docker exec jazzy-static-edp-repro bash -lc \
  'source /opt/ros/jazzy/setup.bash && ros2 topic pub /topic1 std_msgs/msg/String "{data: baseline}" -r 1' \
  >/tmp/jazzy-baseline-pub.log 2>&1 &
BASELINE_PUB_PID=$!

sleep 3

echo "--- Topic info ---"
docker exec jazzy-static-edp-repro bash -lc \
  'source /opt/ros/jazzy/setup.bash && ros2 topic info -v /topic1'

echo "--- Topic echo (baseline: should receive one message) ---"
docker exec jazzy-static-edp-repro bash -lc \
  'source /opt/ros/jazzy/setup.bash && timeout 5 ros2 topic echo --once /topic1 || true'

kill "${BASELINE_PUB_PID}" >/dev/null 2>&1 || true
wait "${BASELINE_PUB_PID}" 2>/dev/null || true

cat >/tmp/endpoints.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<staticdiscovery>
  <!-- Publisher participant (ID 10) endpoints -->
  <participant>
    <name>pub_participant</name>
    <writer>
      <userId>1</userId>
      <topicName>ros_discovery_info</topicName>
      <topicDataType>rmw_dds_common::msg::dds_::ParticipantEntitiesInfo_</topicDataType>
      <reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
      <durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>
    </writer>
    <reader>
      <userId>2</userId>
      <topicName>ros_discovery_info</topicName>
      <topicDataType>rmw_dds_common::msg::dds_::ParticipantEntitiesInfo_</topicDataType>
      <reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
      <durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>
    </reader>
    <writer>
      <userId>3</userId>
      <topicName>rt/topic1</topicName>
      <topicDataType>std_msgs::msg::dds_::String_</topicDataType>
      <reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
      <durabilityQos>VOLATILE_DURABILITY_QOS</durabilityQos>
    </writer>
  </participant>

  <!-- CLI participant (ID 11) endpoints -->
  <participant>
    <name>cli_participant</name>
    <writer>
      <userId>4</userId>
      <topicName>ros_discovery_info</topicName>
      <topicDataType>rmw_dds_common::msg::dds_::ParticipantEntitiesInfo_</topicDataType>
      <reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
      <durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>
    </writer>
    <reader>
      <userId>5</userId>
      <topicName>ros_discovery_info</topicName>
      <topicDataType>rmw_dds_common::msg::dds_::ParticipantEntitiesInfo_</topicDataType>
      <reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
      <durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>
    </reader>
    <reader>
      <userId>6</userId>
      <topicName>rt/topic1</topicName>
      <topicDataType>std_msgs::msg::dds_::String_</topicDataType>
      <reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
      <durabilityQos>VOLATILE_DURABILITY_QOS</durabilityQos>
    </reader>
  </participant>
</staticdiscovery>
EOF

cat >/tmp/pub.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
  <participant profile_name="pub_profile" is_default_profile="true">
    <rtps>
      <name>pub</name>
      <participantID>10</participantID>
      <builtin>
        <discovery_config>
          <discoveryProtocol>SIMPLE</discoveryProtocol>
          <EDP>STATIC</EDP>
          <static_edp_xml_config>file:///tmp/endpoints.xml</static_edp_xml_config>
        </discovery_config>
      </builtin>
    </rtps>
  </participant>

  <data_writer profile_name="ros_discovery_info">
    <userDefinedID>1</userDefinedID>
    <topic>
      <name>ros_discovery_info</name>
      <dataType>rmw_dds_common::msg::dds_::ParticipantEntitiesInfo_</dataType>
    </topic>
  </data_writer>

  <data_reader profile_name="ros_discovery_info">
    <userDefinedID>2</userDefinedID>
    <topic>
      <name>ros_discovery_info</name>
      <dataType>rmw_dds_common::msg::dds_::ParticipantEntitiesInfo_</dataType>
    </topic>
  </data_reader>

  <data_writer profile_name="/topic1">
    <userDefinedID>3</userDefinedID>
    <topic>
      <name>rt/topic1</name>
      <dataType>std_msgs::msg::dds_::String_</dataType>
    </topic>
  </data_writer>
</profiles>
EOF

cat >/tmp/cli.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
  <participant profile_name="cli_profile" is_default_profile="true">
    <rtps>
      <name>cli</name>
      <participantID>11</participantID>
      <builtin>
        <discovery_config>
          <discoveryProtocol>SIMPLE</discoveryProtocol>
          <EDP>STATIC</EDP>
          <static_edp_xml_config>file:///tmp/endpoints.xml</static_edp_xml_config>
        </discovery_config>
      </builtin>
    </rtps>
  </participant>

  <data_writer profile_name="ros_discovery_info">
    <userDefinedID>4</userDefinedID>
    <topic>
      <name>ros_discovery_info</name>
      <dataType>rmw_dds_common::msg::dds_::ParticipantEntitiesInfo_</dataType>
    </topic>
  </data_writer>

  <data_reader profile_name="ros_discovery_info">
    <userDefinedID>5</userDefinedID>
    <topic>
      <name>ros_discovery_info</name>
      <dataType>rmw_dds_common::msg::dds_::ParticipantEntitiesInfo_</dataType>
    </topic>
  </data_reader>

  <data_reader profile_name="/topic1">
    <userDefinedID>6</userDefinedID>
    <topic>
      <name>rt/topic1</name>
      <dataType>std_msgs::msg::dds_::String_</dataType>
    </topic>
  </data_reader>
</profiles>
EOF

docker cp /tmp/endpoints.xml jazzy-static-edp-repro:/tmp/endpoints.xml
docker cp /tmp/pub.xml jazzy-static-edp-repro:/tmp/pub.xml
docker cp /tmp/cli.xml jazzy-static-edp-repro:/tmp/cli.xml

echo
echo "=== Static EDP: no node graph information is available ==="
docker exec jazzy-static-edp-repro bash -lc \
  'source /opt/ros/jazzy/setup.bash && ros2 daemon stop || true'

docker exec \
  -e RMW_IMPLEMENTATION=rmw_fastrtps_cpp \
  -e RMW_FASTRTPS_USE_QOS_FROM_XML=1 \
  -e FASTRTPS_DEFAULT_PROFILES_FILE=/tmp/pub.xml \
  jazzy-static-edp-repro bash -lc \
  'source /opt/ros/jazzy/setup.bash && ros2 topic pub /topic1 std_msgs/msg/String "{data: static_edp}" -r 1' \
  >/tmp/jazzy-static-edp-pub.log 2>&1 &
STATIC_PUB_PID=$!

sleep 3

echo "--- Topic info (static EDP: graph info is lost) ---"
docker exec \
  -e RMW_IMPLEMENTATION=rmw_fastrtps_cpp \
  -e RMW_FASTRTPS_USE_QOS_FROM_XML=1 \
  -e FASTRTPS_DEFAULT_PROFILES_FILE=/tmp/cli.xml \
  jazzy-static-edp-repro bash -lc \
  'source /opt/ros/jazzy/setup.bash && ros2 topic info -v /topic1'

echo "--- Topic echo (static EDP: should receive one message) ---"
docker exec \
  -e RMW_IMPLEMENTATION=rmw_fastrtps_cpp \
  -e RMW_FASTRTPS_USE_QOS_FROM_XML=1 \
  -e FASTRTPS_DEFAULT_PROFILES_FILE=/tmp/cli.xml \
  jazzy-static-edp-repro bash -lc \
  'source /opt/ros/jazzy/setup.bash && timeout 5 ros2 topic echo --once /topic1 || true'

echo
echo "=== Publisher process check ==="
docker exec jazzy-static-edp-repro bash -lc "ps -ef | grep '[r]os2 topic pub /topic1' || true"

kill "${STATIC_PUB_PID}" >/dev/null 2>&1 || true
wait "${STATIC_PUB_PID}" 2>/dev/null || true

Fast DDS version/commit

2.14.5

Platform/Architecture

Ubuntu Focal 20.04 amd64

Transport layer

Default configuration, UDPv4 & SHM

Additional context

No response

XML configuration file

Relevant log output

Network traffic capture

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageIssue pending classification

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions