From cc6d4b55bb1c3cb757cacbd3b527dfeb26d602e2 Mon Sep 17 00:00:00 2001 From: "Justin R. Wilson" Date: Thu, 28 Mar 2024 16:12:50 -0500 Subject: [PATCH] RtpsUdpDataLink sends nacks when writer has clearly moved on Problem ------- When doing interoperability testing, OpenDDS was observed to send a nack for a sequence number that is no longer available. The offending sequence is 1. Writer sends a HB for [X, X]. 2. OpenDDS Reader sends a NACK for X. 3. Writer sends DATA with sequence number X + 1. 4. Writer sends HB for [X+1, X+1]. 5. OpenDDS Reader sends a NACK for X. OpenDDS should treat X as unavailable. Solution -------- The RtpsUdpDataLink contains a code fragment that handles this case but it is limited to the first heartbeat that was received. Move this code out so that it is processed for each heartbeat. --- dds/DCPS/transport/rtps_udp/RtpsUdpDataLink.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dds/DCPS/transport/rtps_udp/RtpsUdpDataLink.cpp b/dds/DCPS/transport/rtps_udp/RtpsUdpDataLink.cpp index e02921c5dcd..cd3d90cfc20 100644 --- a/dds/DCPS/transport/rtps_udp/RtpsUdpDataLink.cpp +++ b/dds/DCPS/transport/rtps_udp/RtpsUdpDataLink.cpp @@ -1968,7 +1968,13 @@ RtpsUdpDataLink::RtpsReader::process_heartbeat_i(const RTPS::HeartBeatSubmessage log_progress("RTPS reader/writer association complete", id_, writer->id_, writer->participant_discovered_at_); } log_remote_counts("process_heartbeat_i"); + first_ever_hb = true; + } + + ACE_CDR::ULong cumulative_bits_added = 0; + if (!writer->recvd_.empty() || first_ever_hb) { + // "gap" everything before the heartbeat range const SequenceRange sr(zero, hb_first.previous()); writer->recvd_.insert(sr); while (!writer->held_.empty() && writer->held_.begin()->first <= sr.second) { @@ -1978,11 +1984,7 @@ RtpsUdpDataLink::RtpsReader::process_heartbeat_i(const RTPS::HeartBeatSubmessage writer->recvd_.insert(it->first); } link->receive_strategy()->remove_fragments(sr, writer->id_); - first_ever_hb = true; - } - ACE_CDR::ULong cumulative_bits_added = 0; - if (!writer->recvd_.empty()) { writer->hb_last_ = std::max(writer->hb_last_, hb_last); gather_ack_nacks_i(writer, link, !is_final, meta_submessages, cumulative_bits_added); }