NACK SN in ACKNACk Response of RTPS Builtin Endpoint

Until now the ACKNACK Response of the RTPS Builtin Endpoint had an empty
Bitmap, effectively ACKing SNs, but never NACKing any (i.e. not
requesting any).
Similar to the RTPS Endpoints we request the next 32 SNs on every
ACKNACK Response.
The ParticipantMessageData SN Handling was also implemented.
This commit is contained in:
Greek 2021-05-12 12:04:02 +02:00
parent 90a4c7928a
commit 293d89f083
5 changed files with 253 additions and 111 deletions

View File

@ -52,28 +52,25 @@
* Should a "Keyed" Endpoint communicate with a "Non-Keyed"? (In the sense of Entity Kind) * Should a "Keyed" Endpoint communicate with a "Non-Keyed"? (In the sense of Entity Kind)
* Is the empty String a valid Topic and Type Name? * Is the empty String a valid Topic and Type Name?
* We can determine if a Endpoint is a Reader or Writer via the Entity ID. Is it illegal to get a SEDP with incompatible source (Reader Entity ID from Publications Announcer?) * We can determine if a Endpoint is a Reader or Writer via the Entity ID. Is it illegal to get a SEDP with incompatible source (Reader Entity ID from Publications Announcer?)
* Can we make an array of records of uncontrained strings? That we we could make an array of variable sized strings... * Can we make an array of records of uncontrained strings? Than we could make an array of variable sized strings...
* Should I also check for Minor_Version >= 4? * Should I also check for Minor_Version >= 4?
- Yes: 8.6 Implementations of this version of the RTPS protocol should be able to process RTPS Messages not only with the same major version but possibly higher minor versions. - Yes: 8.6 Implementations of this version of the RTPS protocol should be able to process RTPS Messages not only with the same major version but possibly higher minor versions.
* If a DATA Submessage is invalid in any way, the Sequence Number is never marked as received, and thus processing of remote Endpoints could stall on corrupt Messages. * If a DATA Submessage is invalid in any way, the Sequence Number is never marked as received, and thus processing of remote Endpoints could stall on corrupt Messages.
* Can a Participant unmatch an Endpoint by marking it's announcing sequence number in a GAP message? * Can a Participant unmatch an Endpoint by marking it's announcing sequence number in a GAP message?
* Is DEADLINE per-INSTANCE or per-INSTANCE-and-WRITER? * Is DEADLINE per-INSTANCE or per-INSTANCE-and-WRITER?
- Since the matching is per-WRITER the assumption would be per-INSTANCE-and-WRITER
- It is per-INSTANCE - It is per-INSTANCE
* Only a sub-part of the DDS QOS are actually relevant for the RTPS. Should I remove the QoS Specifications from the RTPS Package? * Only a sub-part of the DDS QOS are actually relevant for the RTPS. Should I remove the QoS Specifications from the RTPS Package?
* What happens if we get a sample with a source timestamp earlier than the last sample that was accessed by the DataReader when using DESTINATION ORDER BY_SOURCE_TIMESTAMP? Is the smaple dropped? * What happens if we get a sample with a source timestamp earlier than the last sample that was accessed by the DataReader when using DESTINATION ORDER BY_SOURCE_TIMESTAMP? Is the sample dropped?
* The spec does not define the serialized Key (KEY=1 DATA MESSAGE) * The spec does not define the serialized Key (KEY=1 DATA MESSAGE)
- fast-rtps assumes it is the Key Hash - fast-rtps assumes it is the Key Hash
- opendds sends Payload Encapsulation with a Key Holder Object (As defined in XType 7.6.8) - opendds sends Payload Encapsulation with a Key Holder Object (As defined in XType 7.6.8)
- opensplice seems to do the same as opendds - opensplice seems to do the same as opendds
* Currently the builtin-endpoint does only acknowledge SN, but does not negatively acknowledge any SN (Bitamp is always empty).
A writer usually responds with repairs only to negative acknowledgements.
* Assert Heartbeat period > Heartbeat Suppression Period * Assert Heartbeat period > Heartbeat Suppression Period
* Can I request (NACK) SNs that were NOT announced by the writer (> last_sn in Heartbeat)? * Can I request (NACK) SNs that were NOT announced by the writer (> last_sn in Heartbeat)?
* Does AUTOMATIC Liveliness QoS also update the lease on write/assert_liveliness operations? * Does AUTOMATIC Liveliness QoS also update the lease on write/assert_liveliness operations?
* The Lease Duration is also updated if the Cache Change is not accepted by the DDS/HC. This in effect "skews" the "correctness" of the Writer Liveliness Protocol until the reader has no pending request from the Writer. * The Lease Duration is also updated if the Cache Change is not accepted by the DDS/HC. This in effect "skews" the "correctness" of the Writer Liveliness Protocol until the reader has no pending request from the Writer.
* If an Instance is DISPOSED, but later has no active writers, the Instance STAYS in the NOT_ALIVE_DISPOSED state. * If an Instance is DISPOSED, but later has no active writers, the Instance STAYS in the NOT_ALIVE_DISPOSED state.
* Is a Writer that is Disposing a Instance also Unregistering that instance? (Currently only Unregistering removes the remote Writer) * Is a Writer that is Disposing an Instance also Unregistering that instance? (Currently only Unregistering removes the remote Writer)
- No - No
* Since Lifespan is a duration, there is an inherent difference in the expiration time between writer and reader. This in addition to the fact that the reader may use the Reception time for the expiration time calculation could lead to an actual expiration duration almost double in length (If sent right before expiring locally in the writer). * Since Lifespan is a duration, there is an inherent difference in the expiration time between writer and reader. This in addition to the fact that the reader may use the Reception time for the expiration time calculation could lead to an actual expiration duration almost double in length (If sent right before expiring locally in the writer).
* The current implementation will sent a second unregister/dispose Sample, if the user does the unregister/dispose operation a second time. Should we handle that specially? * The current implementation will sent a second unregister/dispose Sample, if the user does the unregister/dispose operation a second time. Should we handle that specially?
@ -83,6 +80,8 @@
* Does the DEADLINE_QOS apply also to NOT_ALIVE Instances? (Current implementation makes no distinction) * Does the DEADLINE_QOS apply also to NOT_ALIVE Instances? (Current implementation makes no distinction)
* Does TIME_BASED_FILTER also apply to meta-samples (DISPOSED, NO_WRITERS)? That is an easy way to not get convergent state in different DDS Readers. What do other implementations do? * Does TIME_BASED_FILTER also apply to meta-samples (DISPOSED, NO_WRITERS)? That is an easy way to not get convergent state in different DDS Readers. What do other implementations do?
* In rtps_builtin_endpoint we initiate a participant memory search ASAP (in the PACKET_SRC_GUIDPREFIX stage). Further down we branch to several different branches, which each needing different Participant Data Fields. Currently we are fetching ALL needed Fields from ALL branches. Would it make sense to delay the search until the PACKET_DEST_ENTITYID/CHECK_SRC_ENTITYID stage, and only fetch the relevant Fields? * In rtps_builtin_endpoint we initiate a participant memory search ASAP (in the PACKET_SRC_GUIDPREFIX stage). Further down we branch to several different branches, which each needing different Participant Data Fields. Currently we are fetching ALL needed Fields from ALL branches. Would it make sense to delay the search until the PACKET_DEST_ENTITYID/CHECK_SRC_ENTITYID stage, and only fetch the relevant Fields?
* The Participant GUID of the ParticipantMessageData is theoretically not needed, since it is the same as the source GUID of the Packet. This is done, so that the ParticipantMessageData has a key and can be decrypted as every other DATA Message. Our implementation checks if it is the expected GUID and drops it otherwise.
- see (https://issues.omg.org/issues/DDSIRTP21-4)
* Fast-RTPS does not follow DDSI-RTPS Specification * Fast-RTPS does not follow DDSI-RTPS Specification
- Open Github Issue - Open Github Issue

View File

@ -13,8 +13,7 @@ use work.rtps_test_package.all;
-- This testbench tests the input handling of parameter lists. We issue one parameter list with invalid parameter length (less than expected) -- This testbench tests the input handling of parameter lists. We issue one parameter list with invalid parameter length (less than expected)
-- and one with valid larger parameter length (extra Bytes after expected parameter end) for each of the parameters that are handled by the built-in endpoint by checking if the Participant/Endpoint matched. -- and one with valid larger parameter length (extra Bytes after expected parameter end) for each of the parameters that are handled by the built-in endpoint by checking if the Participant/Endpoint matched.
-- (We also issue a parameter list that is missing its sentinel) -- (We also issue a parameter list that is missing its sentinel)
-- Particpant matches are checked by memory content, and Endpoint matches by match frame -- Particpant matches are checked by memory content, and Endpoint matches by the generated match frame.
-- The Participant
-- The PIDs handled are: -- The PIDs handled are:
-- * PID_PARTICIPANT_GUID -- * PID_PARTICIPANT_GUID
-- * PID_DOMAIN_ID -- * PID_DOMAIN_ID

View File

@ -10,7 +10,7 @@ use work.user_config.all;
use work.rtps_config_package.all; use work.rtps_config_package.all;
use work.rtps_test_package.all; use work.rtps_test_package.all;
-- This testbench tests the sequence number handling of the participant, subscriber, and publisher DATA Submessages. -- This testbench tests the sequence number handling of the participant, subscriber, publisher, and ParticipantMessage DATA Submessages.
entity L0_rtps_builtin_endpoint_test4 is entity L0_rtps_builtin_endpoint_test4 is
end entity; end entity;
@ -91,7 +91,7 @@ begin
); );
stimulus_prc : process stimulus_prc : process
variable sub, sub_p, sub_s : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; variable sub, sub_p, sub_s, sub_m : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE;
variable RV : RandomPType; variable RV : RandomPType;
variable p0, participant : PARTICIPANT_DATA_TYPE := DEFAULT_PARTICIPANT_DATA; variable p0, participant : PARTICIPANT_DATA_TYPE := DEFAULT_PARTICIPANT_DATA;
variable e0, e1, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; variable e0, e1, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA;
@ -135,6 +135,15 @@ begin
end if; end if;
end procedure; end procedure;
procedure push_liveliness_update is
begin
gen_liveliness_update_frame(participant, reference);
for i in 0 to reference.length-1 loop
SB_out.Push(wr_sig & reference.last(i) & reference.data(i));
end loop;
reference := EMPTY_TEST_PACKET;
end procedure;
procedure push_participant_reference is procedure push_participant_reference is
variable wr_sig : std_logic_vector(NUM_ENDPOINTS-1 downto 0) := (others => '1'); variable wr_sig : std_logic_vector(NUM_ENDPOINTS-1 downto 0) := (others => '1');
begin begin
@ -193,6 +202,13 @@ begin
sub_s.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR; sub_s.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
sub_s.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; sub_s.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
-- Participant Message RTPS Submessage
sub_m := DEFAULT_RTPS_SUBMESSAGE;
sub_m.submessageID := SID_DATA;
sub_m.writerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
sub_m.readerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
sub_m.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
-- Participant 0 -- Participant 0
p0.guidPrefix := gen_rand_guid_prefix; p0.guidPrefix := gen_rand_guid_prefix;
p0.nr := 0; p0.nr := 0;
@ -421,6 +437,70 @@ begin
reference := EMPTY_TEST_PACKET; reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET; sub_s.data := EMPTY_TEST_PACKET;
-- *MESSAGE*
Log("Accept Liveliness Update from Participant 0 [SN 1]", INFO);
sub_m.writerSN := gen_sn(1);
participant := p0;
participant.nr := 0;
participant.match := MATCH;
gen_liveliness_assertion(participant, FALSE, sub_m.data);
gen_rtps_handler_out(sub_m, participant, stimulus);
wr_sig := AUTOMATIC_LIVELINESS_READERS;
push_liveliness_update;
start_test;
wait_on_sent;
wait_on_mem_check;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_m.data := EMPTY_TEST_PACKET;
Log("Accept Liveliness Update from Participant 0 [SN 2]", INFO);
sub_m.writerSN := gen_sn(2);
participant := p0;
participant.nr := 0;
participant.match := MATCH;
gen_liveliness_assertion(participant, TRUE, sub_m.data);
gen_rtps_handler_out(sub_m, participant, stimulus);
wr_sig := MANUAL_BY_PARTICIPANT_LIVELINESS_READERS;
push_liveliness_update;
start_test;
wait_on_sent;
wait_on_mem_check;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_m.data := EMPTY_TEST_PACKET;
Log("Accept Liveliness Update from Participant 0 [SN 5]", INFO);
sub_m.writerSN := gen_sn(5);
participant := p0;
participant.nr := 0;
participant.match := MATCH;
gen_liveliness_assertion(participant, FALSE, sub_m.data);
gen_rtps_handler_out(sub_m, participant, stimulus);
wr_sig := AUTOMATIC_LIVELINESS_READERS;
push_liveliness_update;
start_test;
wait_on_sent;
wait_on_mem_check;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_m.data := EMPTY_TEST_PACKET;
Log("Ignore Liveliness Update from Participant 0 [SN 1]", INFO);
sub_m.writerSN := gen_sn(1);
participant := p0;
participant.nr := 0;
participant.match := MATCH;
gen_liveliness_assertion(participant, TRUE, sub_m.data);
gen_rtps_handler_out(sub_m, participant, stimulus);
start_test;
wait_on_sent;
wait_on_mem_check;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_m.data := EMPTY_TEST_PACKET;
stim_done <= '1'; stim_done <= '1';
wait_on_complete; wait_on_complete;
TranscriptOpen(RESULTS_FILE, APPEND_MODE); TranscriptOpen(RESULTS_FILE, APPEND_MODE);

View File

@ -134,7 +134,9 @@ architecture testbench of L1_rtps_builtin_endpoint_test1 is
sub.writerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER; sub.writerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER;
sub.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR; sub.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
sub.readerSNState.base := pub_sn; sub.readerSNState.base := pub_sn;
sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH)); sub.readerSNState.numBits := int(WORD_WIDTH, CDR_LONG_WIDTH);
sub.readerSNState.bitmap := (0 to WORD_WIDTH-1 => '1', others => '0');
sub.count := int(count, CDR_LONG_WIDTH);
sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1';
gen_rtps_submessage(sub, output); gen_rtps_submessage(sub, output);
-- SUBSCRIBER ACKNACK -- SUBSCRIBER ACKNACK
@ -142,8 +144,10 @@ architecture testbench of L1_rtps_builtin_endpoint_test1 is
sub.submessageID := SID_ACKNACK; sub.submessageID := SID_ACKNACK;
sub.writerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER; sub.writerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
sub.readerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR; sub.readerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH));
sub.readerSNState.base := sub_sn; sub.readerSNState.base := sub_sn;
sub.readerSNState.numBits := int(WORD_WIDTH, CDR_LONG_WIDTH);
sub.readerSNState.bitmap := (0 to WORD_WIDTH-1 => '1', others => '0');
sub.count := int(count, CDR_LONG_WIDTH);
sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1';
gen_rtps_submessage(sub, output); gen_rtps_submessage(sub, output);
-- MESSAGE ACKNACK -- MESSAGE ACKNACK
@ -151,8 +155,10 @@ architecture testbench of L1_rtps_builtin_endpoint_test1 is
sub.submessageID := SID_ACKNACK; sub.submessageID := SID_ACKNACK;
sub.writerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER; sub.writerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
sub.readerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER; sub.readerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH));
sub.readerSNState.base := mes_sn; sub.readerSNState.base := mes_sn;
sub.readerSNState.numBits := int(WORD_WIDTH, CDR_LONG_WIDTH);
sub.readerSNState.bitmap := (0 to WORD_WIDTH-1 => '1', others => '0');
sub.count := int(count, CDR_LONG_WIDTH);
sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1'; sub.flags(SUBMESSAGE_FINAL_FLAG_POS) := '1';
gen_rtps_submessage(sub, output); gen_rtps_submessage(sub, output);
fix_output_packet(output); fix_output_packet(output);

View File

@ -124,7 +124,7 @@ architecture arch of rtps_builtin_endpoint is
--*****TYPE DECLARATION***** --*****TYPE DECLARATION*****
-- FSM states. Explained below in detail -- FSM states. Explained below in detail
type STAGE_TYPE is (IDLE, PACKET_HEADER, PACKET_SRC_ADDR, PACKET_SRC_ENTITYID, PACKET_SRC_GUIDPREFIX, PACKET_DEST_ENTITYID, type STAGE_TYPE is (IDLE, PACKET_HEADER, PACKET_SRC_ADDR, PACKET_SRC_ENTITYID, PACKET_SRC_GUIDPREFIX, PACKET_DEST_ENTITYID,
CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, PROCESS_PL, CHECK_DEFAULT, CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE_SEQUENCE_NUMBERS, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, PROCESS_PL, CHECK_DEFAULT,
LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION, LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION,
RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, RXO_LATENCY_BUDGET, CHECK_MAX_SIZE_SERIALIZED, RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, RXO_LATENCY_BUDGET, CHECK_MAX_SIZE_SERIALIZED,
MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION, LATCH_LOCATOR, LATCH_EXPECTS_INLINE_QOS, MATCH_GUID, CHECK_REMOTE_BUILTIN_ENDPOINTS, MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION, LATCH_LOCATOR, LATCH_EXPECTS_INLINE_QOS, MATCH_GUID, CHECK_REMOTE_BUILTIN_ENDPOINTS,
@ -514,6 +514,7 @@ begin
-- This state is taken if the Packet content could not be determined in the PACKET_DEST_ENTITYID state. -- This state is taken if the Packet content could not be determined in the PACKET_DEST_ENTITYID state.
-- LATCH_SEQ_NR Store RTPS Data Submessage Sequence Number -- LATCH_SEQ_NR Store RTPS Data Submessage Sequence Number
-- PROCESS_DATA Parse RTPS Data Submessage Payload Header. Determine content of Data (Parameter List, Participant Message CDR Data) or if Data Message contains in-line QoS and initiate respective handling. -- PROCESS_DATA Parse RTPS Data Submessage Payload Header. Determine content of Data (Parameter List, Participant Message CDR Data) or if Data Message contains in-line QoS and initiate respective handling.
-- PROCESS_MESSAGE_SEQUENCE_NUMBERS Process ParticipantMessageData Sequence Numbers. Update Sequence Numbers if necessary and initiate Message processing
-- PROCESS_MESSAGE Parse Participant Data Message and extract liveliness assertion of remote Participant -- PROCESS_MESSAGE Parse Participant Data Message and extract liveliness assertion of remote Participant
-- LIVELINESS_UPDATE Propagate Liveliness Assertion of remote Participant to respective local Reader Endpoints -- LIVELINESS_UPDATE Propagate Liveliness Assertion of remote Participant to respective local Reader Endpoints
-- PROCESS_GAP Parse RTPS GAP Submessage -- PROCESS_GAP Parse RTPS GAP Submessage
@ -1217,8 +1218,7 @@ begin
-- Override Endian Flag -- Override Endian Flag
endian_flag_next <= '0'; endian_flag_next <= '0';
stage_next <= PROCESS_MESSAGE; stage_next <= PROCESS_MESSAGE_SEQUENCE_NUMBERS;
cnt_next <= 0;
end if; end if;
when CDR_LE => when CDR_LE =>
-- Accept CDR Representation only for Participant Messages -- Accept CDR Representation only for Participant Messages
@ -1226,8 +1226,7 @@ begin
-- Override Endian Flag -- Override Endian Flag
endian_flag_next <= '1'; endian_flag_next <= '1';
stage_next <= PROCESS_MESSAGE; stage_next <= PROCESS_MESSAGE_SEQUENCE_NUMBERS;
cnt_next <= 0;
end if; end if;
when others => when others =>
-- Skip Packet -- Skip Packet
@ -1235,6 +1234,34 @@ begin
end case; end case;
end if; end if;
end if; end if;
when PROCESS_MESSAGE_SEQUENCE_NUMBERS =>
-- Precondition: participant_data set (PMF_MES_SEQ_NR_FLAG)
assert (check_mask(current_pmf, PMF_MES_SEQ_NR_FLAG)) severity FAILURE;
-- Wait for Participant Data
if (mem_op_done = '1') then
-- Participant in Buffer
if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
-- NOTE: Since the BuiltinParticipantMessageWriter has a History Depth of 1 (see DDSI-RTPS 2.3 8.4.13.3), we accept all newer SNs, since
-- if the Writer has sent a newer SN he doesn't have the previous one anymore.
-- Next Valid Sequence Number
if (seq_nr >= mem_seq_nr) then
mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_MES_SEQ_NR_FLAG;
-- Process Message Data
stage_next <= PROCESS_MESSAGE;
cnt_next <= 0;
else
-- DONE
stage_next <= SKIP_PACKET;
end if;
else
-- DONE
stage_next <= SKIP_PACKET;
end if;
end if;
when PROCESS_MESSAGE => when PROCESS_MESSAGE =>
-- Input FIFO Guard -- Input FIFO Guard
if (empty = '0') then if (empty = '0') then
@ -1263,7 +1290,7 @@ begin
-- NOTE: Rest of Participant Message is ignored -- NOTE: Rest of Participant Message is ignored
-- XXX: The Participant Message Data may contain additional data, and according to DDSI-RTPS 2.3 -- XXX: The Participant Message Data may contain additional data, and according to DDSI-RTPS 2.3
-- implementations must be able to support up to 128 Bytes of additional data. Due to the unnecessary -- implementations must be able to support up to 128 Bytes of additional data. Due to the unnecessary
-- high complexity this would add this is not supported. -- high complexity this would add, this is currently not supported.
case (data_in) is case (data_in) is
-- Automatic Liveliness Assertion -- Automatic Liveliness Assertion
when PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE => when PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE =>
@ -1410,6 +1437,7 @@ begin
mem_field_flags <= PMF_MES_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; mem_field_flags <= PMF_MES_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
end if; end if;
next_seq_nr_next <= first_seq_nr; next_seq_nr_next <= first_seq_nr;
if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY; tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY;
res_time <= tmp_dw; res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay -- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -1419,8 +1447,11 @@ begin
if (tmp_dw < check_time) then if (tmp_dw < check_time) then
check_time_next <= tmp_dw; check_time_next <= tmp_dw;
end if; end if;
else
res_time <= TIME_INVALID;
end if;
-- If new Sequence Number is available or Writer expects ACKNACK -- If new Sequence Number is available or Writer expects ACKNACK
elsif (last_seq_nr >= mem_seq_nr or final_flag = '0') then elsif (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE and (last_seq_nr >= mem_seq_nr or final_flag = '0')) then
-- Set Response Delay -- Set Response Delay
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
@ -1494,6 +1525,7 @@ begin
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY; tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw; res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay -- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -1504,6 +1536,9 @@ begin
if (tmp_dw < check_time) then if (tmp_dw < check_time) then
check_time_next <= tmp_dw; check_time_next <= tmp_dw;
end if; end if;
else
res_time <= TIME_INVALID;
end if;
end if; end if;
-- Publisher Acknack -- Publisher Acknack
else else
@ -1513,6 +1548,7 @@ begin
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY; tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw; res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay -- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -1523,6 +1559,9 @@ begin
if (tmp_dw < check_time) then if (tmp_dw < check_time) then
check_time_next <= tmp_dw; check_time_next <= tmp_dw;
end if; end if;
else
res_time <= TIME_INVALID;
end if;
end if; end if;
end if; end if;
-- Message Acknack -- Message Acknack
@ -1534,6 +1573,7 @@ begin
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY; tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw; res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay -- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -1544,6 +1584,9 @@ begin
if (tmp_dw < check_time) then if (tmp_dw < check_time) then
check_time_next <= tmp_dw; check_time_next <= tmp_dw;
end if; end if;
else
res_time <= TIME_INVALID;
end if;
end if; end if;
when others => when others =>
null; null;
@ -1725,7 +1768,7 @@ begin
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG;
if (PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY /= 0) then if (PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY /= DURATION_ZERO and PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY /= DURATION_INFINITE) then
-- Set Heartbeat Suppression Time -- Set Heartbeat Suppression Time
res_time <= time + PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY; res_time <= time + PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay -- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -1746,7 +1789,7 @@ begin
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG;
extra_flags <= participant_data.extra_flags and (not (EF_PUB_DATA_FLAG or EF_SUB_DATA_FLAG or EF_MES_DATA_FLAG)); extra_flags <= participant_data.extra_flags and (not (EF_PUB_DATA_FLAG or EF_SUB_DATA_FLAG or EF_MES_DATA_FLAG));
if (PARTICIPANT_ACKNACK_SUPPRESSION_DELAY /= 0) then if (PARTICIPANT_ACKNACK_SUPPRESSION_DELAY /= DURATION_ZERO and PARTICIPANT_ACKNACK_SUPPRESSION_DELAY /= DURATION_INFINITE) then
-- Set Acknack Suppression Time -- Set Acknack Suppression Time
res_time <= time + PARTICIPANT_ACKNACK_SUPPRESSION_DELAY; res_time <= time + PARTICIPANT_ACKNACK_SUPPRESSION_DELAY;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay -- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -2889,7 +2932,7 @@ begin
-- ACKNACK RTPS SUBMESSAGE (Publication) -- ACKNACK RTPS SUBMESSAGE (Publication)
-- RTPS Submessage Header -- RTPS Submessage Header
when 0 => when 0 =>
data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(24, 16)); data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16));
-- Reader Entity ID -- Reader Entity ID
when 1 => when 1 =>
data_out <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR; data_out <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
@ -2904,53 +2947,68 @@ begin
data_out <= std_logic_vector(participant_data.pub_seq_nr(1)); data_out <= std_logic_vector(participant_data.pub_seq_nr(1));
-- Sequence Number Set (NumBits) -- Sequence Number Set (NumBits)
when 5 => when 5 =>
data_out <= (others => '0'); data_out <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH));
-- Count -- Sequence Number Set (Bitmap)
when 6 => when 6 =>
-- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet)
-- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist)
data_out <= (others => '1');
-- Count
when 7 =>
data_out <= std_logic_vector(count); data_out <= std_logic_vector(count);
-- ACKNACK RTPS SUBMESSAGE (Subscription) -- ACKNACK RTPS SUBMESSAGE (Subscription)
-- RTPS Submessage Header -- RTPS Submessage Header
when 7 =>
data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(24, 16));
-- Reader Entity ID
when 8 => when 8 =>
data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16));
-- Reader Entity ID
when 9 =>
data_out <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR; data_out <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
-- Writer Entity ID -- Writer Entity ID
when 9 => when 10 =>
data_out <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER; data_out <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
-- Sequence Number Set (Bitmap Base 1/2) -- Sequence Number Set (Bitmap Base 1/2)
when 10 => when 11 =>
data_out <= std_logic_vector(participant_data.sub_seq_nr(0)); data_out <= std_logic_vector(participant_data.sub_seq_nr(0));
-- Sequence Number Set (Bitmap Base 2/2) -- Sequence Number Set (Bitmap Base 2/2)
when 11 => when 12 =>
data_out <= std_logic_vector(participant_data.sub_seq_nr(1)); data_out <= std_logic_vector(participant_data.sub_seq_nr(1));
-- Sequence Number Set (NumBits) -- Sequence Number Set (NumBits)
when 12 =>
data_out <= (others => '0');
-- Count
when 13 => when 13 =>
data_out <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH));
-- Sequence Number Set (Bitmap)
when 14 =>
-- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet)
-- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist)
data_out <= (others => '1');
-- Count
when 15 =>
data_out <= std_logic_vector(count); data_out <= std_logic_vector(count);
-- ACKNACK RTPS SUBMESSAGE (Message) -- ACKNACK RTPS SUBMESSAGE (Message)
-- RTPS Submessage Header -- RTPS Submessage Header
when 14 => when 16 =>
data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(24, 16)); data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16));
-- Reader Entity ID -- Reader Entity ID
when 15 => when 17 =>
data_out <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER; data_out <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
-- Writer Entity ID -- Writer Entity ID
when 16 => when 18 =>
data_out <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER; data_out <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
-- Sequence Number Set (Bitmap Base 1/2) -- Sequence Number Set (Bitmap Base 1/2)
when 17 => when 19 =>
data_out <= std_logic_vector(participant_data.mes_seq_nr(0)); data_out <= std_logic_vector(participant_data.mes_seq_nr(0));
-- Sequence Number Set (Bitmap Base 2/2) -- Sequence Number Set (Bitmap Base 2/2)
when 18 => when 20 =>
data_out <= std_logic_vector(participant_data.mes_seq_nr(1)); data_out <= std_logic_vector(participant_data.mes_seq_nr(1));
-- Sequence Number Set (NumBits) -- Sequence Number Set (NumBits)
when 19 => when 21 =>
data_out <= (others => '0'); data_out <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH));
-- Sequence Number Set (Bitmap)
when 22 =>
-- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet)
-- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist)
data_out <= (others => '1');
-- Count -- Count
when 20 => when 23 =>
data_out <= std_logic_vector(count); data_out <= std_logic_vector(count);
last_word_out <= '1'; last_word_out <= '1';