Skip to content

Fix content filtering on Windows with modern Connext DDS#226

Merged
sloretz merged 5 commits into
ros2:rollingfrom
mjcarroll:fix-windows-content-filter
May 12, 2026
Merged

Fix content filtering on Windows with modern Connext DDS#226
sloretz merged 5 commits into
ros2:rollingfrom
mjcarroll:fix-windows-content-filter

Conversation

@mjcarroll
Copy link
Copy Markdown
Member

Description

This PR fixes Content Filtering on Windows when using modern versions of RTI Connext DDS (6.x and 7.x).

The Problem

Previously, the rmw_connextdds implementation on Windows was forced into a "Compatibility Mode." This mode:

  1. Disabled Writer-side filtering: All samples were sent to all matching readers, regardless of whether they matched the filter.
  2. Forced Reader-side filtering: Filtering was performed after deserialization. However, the built-in RTI SQL filter expects samples in the Connext memory layout. Because ROS 2 uses its own internal format, the filter would fail "open" and accept all samples.

This led to failures in rcl, rclcpp, and rcl_action tests where samples were received by subscribers despite being explicitly filtered out by SQL expressions.

The Fix

  1. Enable Serialized Evaluation: Updated CMakeLists.txt to only enable RMW_CONNEXT_BUILTIN_CFT_COMPATIBILITY_MODE on Windows for Connext versions older than 6.0.0. For modern versions, we now use the internal register_contentfilterI API, which supports evaluation on CDR-serialized samples.
  2. Fix Redefinition Conflict: Adjusted custom_sql_filter.hpp to use the official RTI declaration of register_contentfilterI (available in modern headers) to avoid linkage errors on MSVC.
  3. Correct Cookie Handling: Fixed a bug in RTI_CustomSqlFilter_writer_evaluated_result where it assumed RTI's built-in filter always returned a discontiguous sequence of cookies. It now correctly handles both contiguous and discontiguous sequences.

Verification

Verified on Windows using a targeted CI run with Connext 7.7.0. All content filtering tests in rcl, rclcpp, and rcl_action passed.

CI Result (Windows 10, Connext 7.7.0): https://ci.ros2.org/job/ci_windows/27743/

Is this user-facing behavior change?

No, it fixes a regression in existing functionality.

Did you use Generative AI?

Yes. Gemini CLI:2.0-Flash [web_fetch, run_shell_command, replace, git, gh]

1. Fix a bug in writer-side filtering where it assumed the built-in SQL filter returned a discontiguous sequence of cookies. Fallback to taking addresses of contiguous cookies if necessary.

2. Disable RMW_CONNEXT_BUILTIN_CFT_COMPATIBILITY_MODE on Windows for Connext 6.0+ to enable serialized evaluation and internal registration, which is required for correct filtering of ROS 2 samples.

Assisted-by: Gemini CLI:2.0-Flash
…Windows

Modern RTI Connext headers (6.0.0+) already provide this declaration. Re-declaring it manually causes linkage errors on MSVC.

Assisted-by: Gemini CLI:2.0-Flash
RMW_CONNEXT_DDS_API_PRO_LEGACY is always defined (defaults to 0), so #if defined() was always true. Switching to #if value ensures correct skipping on modern Connext.

Assisted-by: Gemini CLI:2.0-Flash
@mjcarroll
Copy link
Copy Markdown
Member Author

Pulls: #226
Gist: https://gist.githubusercontent.com/mjcarroll/916220ac5820e6bc62eebe971ce41f85/raw/6a2085453c76d5d8154be7261de0001cc179ed38/ros2.repos
BUILD args:
TEST args:
ROS Distro: rolling
Job: ci_launcher
ci_launcher ran: https://ci.ros2.org/job/ci_launcher/19089

  • Linux Build Status
  • Linux-aarch64 Build Status
  • Linux-rhel Build Status
  • Windows Build Status

Copy link
Copy Markdown
Collaborator

@fujitatomoya fujitatomoya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, @fgallegosalido can you take a look?

@fgallegosalido
Copy link
Copy Markdown
Collaborator

fgallegosalido commented Apr 29, 2026

It looks good to me. I just have one question. Has the bug in the cookie handling actually happened while investigating this issue? I checked internally and that buffer is going to always be discontiguous (a buffer of pointers to DDS_Cookie_t). Therefore, that check is redundant. It doesn't hurt having it there, but unless there is an actual bug, it is not necessary.

Maybe, we can add a comment above that check explaining that the buffer is always going to be discontiguous.

Thank you very much @mjcarroll for looking into this!

@sloretz
Copy link
Copy Markdown
Contributor

sloretz commented May 8, 2026

Has the bug in the cookie handling actually happened while investigating this issue? I checked internally and that buffer is going to always be discontiguous (a buffer of pointers to DDS_Cookie_t). Therefore, that check is redundant. It doesn't hurt having it there, but unless there is an actual bug, it is not necessary.

Trying a windows run without the change to rmw_connextdds_common/src/ndds/custom_sql_filter.cpp (Branch compare with rolling: https://github.com/ros2/rmw_connextdds/compare/test_mjc_226_wo-custom_sql_filter )

Build Status

build: --packages-up-to rcl rcl_action rclpy ros2cli sros2 ros2multicast test_rmw_implementation rclcpp rosbag2_transport test_communication test_tf2 test_security
test: --packages-select rcl rcl_action rclpy ros2cli sros2 ros2multicast test_rmw_implementation rclcpp rosbag2_transport test_communication test_tf2 test_security

@sloretz
Copy link
Copy Markdown
Contributor

sloretz commented May 10, 2026

Trying another run with both connext and fastrtps so that connext isn't used for all tests as a better comparison:

Build Status

edit: using fastrtps instead of cylconedds as the other rmw Build Status

@fgallegosalido
Copy link
Copy Markdown
Collaborator

@sloretz I think the builds look mostly good for rmw_connextdds. I can recommend that, instead of checking if the buffer is dicontiguous or not, add an assert to make sure the buffer is discontiguous. I think this is the most efficient way of doing it.

Comment on lines +450 to +464
DDS_Cookie_t ** const sql_matched_discont_buffer =
DDS_CookieSeq_get_discontiguous_buffer(sql_matched);
memcpy(
&(writer_data->matched_readers_buffer[matched_readers_start]),
sql_matched_buffer,
sizeof(DDS_Cookie_t *) * sql_matched_len);
if (nullptr != sql_matched_discont_buffer) {
memcpy(
&(writer_data->matched_readers_buffer[matched_readers_start]),
sql_matched_discont_buffer,
sizeof(DDS_Cookie_t *) * sql_matched_len);
} else {
DDS_Cookie_t * const sql_matched_cont_buffer =
DDS_CookieSeq_get_contiguous_buffer(sql_matched);
for (size_t i = 0; i < sql_matched_len; ++i) {
writer_data->matched_readers_buffer[matched_readers_start + i] =
&sql_matched_cont_buffer[i];
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
DDS_Cookie_t ** const sql_matched_discont_buffer =
DDS_CookieSeq_get_discontiguous_buffer(sql_matched);
memcpy(
&(writer_data->matched_readers_buffer[matched_readers_start]),
sql_matched_buffer,
sizeof(DDS_Cookie_t *) * sql_matched_len);
if (nullptr != sql_matched_discont_buffer) {
memcpy(
&(writer_data->matched_readers_buffer[matched_readers_start]),
sql_matched_discont_buffer,
sizeof(DDS_Cookie_t *) * sql_matched_len);
} else {
DDS_Cookie_t * const sql_matched_cont_buffer =
DDS_CookieSeq_get_contiguous_buffer(sql_matched);
for (size_t i = 0; i < sql_matched_len; ++i) {
writer_data->matched_readers_buffer[matched_readers_start + i] =
&sql_matched_cont_buffer[i];
}
}
DDS_Cookie_t ** const sql_matched_buffer =
DDS_CookieSeq_get_discontiguous_buffer(sql_matched);
RMW_CONNEXT_ASSERT(nullptr != sql_matched_buffer)
memcpy(
&(writer_data->matched_readers_buffer[matched_readers_start]),
sql_matched_buffer,
sizeof(DDS_Cookie_t *) * sql_matched_len);

@sloretz
Copy link
Copy Markdown
Contributor

sloretz commented May 11, 2026

Interesting new test failures, but all the content filtering test failures are gone. I'm going to apply the above suggestion and start full CI.

@sloretz sloretz force-pushed the fix-windows-content-filter branch from 72121ba to 561d4b4 Compare May 11, 2026 18:58
@sloretz
Copy link
Copy Markdown
Contributor

sloretz commented May 11, 2026

Pulls: #226
Gist: https://gist.githubusercontent.com/sloretz/d68af20155f86d76b5775165d17a9a18/raw/6a2085453c76d5d8154be7261de0001cc179ed38/ros2.repos
BUILD args: --packages-above-and-dependencies rcl rcl_action rclpy ros2cli sros2 ros2multicast test_rmw_implementation rclcpp rosbag2_transport test_communication test_tf2 test_security
TEST args: --packages-above rcl rcl_action rclpy ros2cli sros2 ros2multicast test_rmw_implementation rclcpp rosbag2_transport test_communication test_tf2 test_security
ROS Distro: rolling
Job: ci_launcher
ci_launcher ran: https://ci.ros2.org/job/ci_launcher/19221

  • Linux Build Status
  • Linux-aarch64 Build Status
  • Linux-rhel Build Status Infra issue; rerun: Build Status
  • Windows Build Status

@sloretz
Copy link
Copy Markdown
Contributor

sloretz commented May 12, 2026

I think I see all the test failures in the latest nightlies, so I'm going to merge this.

@sloretz sloretz merged commit 9e3beb8 into ros2:rolling May 12, 2026
2 checks passed
@sloretz
Copy link
Copy Markdown
Contributor

sloretz commented May 12, 2026

@Mergifyio backport lyrical

@mergify
Copy link
Copy Markdown

mergify Bot commented May 12, 2026

backport lyrical

✅ Backports have been created

Details

sloretz added a commit that referenced this pull request May 12, 2026
* Fix content filtering on Windows with Connext 7

1. Fix a bug in writer-side filtering where it assumed the built-in SQL filter returned a discontiguous sequence of cookies. Fallback to taking addresses of contiguous cookies if necessary.

2. Disable RMW_CONNEXT_BUILTIN_CFT_COMPATIBILITY_MODE on Windows for Connext 6.0+ to enable serialized evaluation and internal registration, which is required for correct filtering of ROS 2 samples.

Assisted-by: Gemini CLI:2.0-Flash

* Fix redefinition of DDS_DomainParticipant_register_contentfilterI on Windows

Modern RTI Connext headers (6.0.0+) already provide this declaration. Re-declaring it manually causes linkage errors on MSVC.

Assisted-by: Gemini CLI:2.0-Flash

* Fix incorrect preprocessor check for legacy Connext API

RMW_CONNEXT_DDS_API_PRO_LEGACY is always defined (defaults to 0), so #if defined() was always true. Switching to #if value ensures correct skipping on modern Connext.

Assisted-by: Gemini CLI:2.0-Flash

* Apply @fgallegosalido suggestion to assert discontiguous buffer



---------



(cherry picked from commit 9e3beb8)

Signed-off-by: Shane Loretz <sloretz@intrinsic.ai>
Co-authored-by: Michael Carroll <carroll.michael@gmail.com>
Co-authored-by: Shane Loretz <sloretz@intrinsic.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants