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)
* 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?)
* 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?
- 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.
* 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?
- Since the matching is per-WRITER the assumption would be per-INSTANCE-and-WRITER
- 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?
* 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)
- fast-rtps assumes it is the Key Hash
- opendds sends Payload Encapsulation with a Key Holder Object (As defined in XType 7.6.8)
- 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
* 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?
* 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.
* 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
* 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?
@ -83,6 +80,8 @@
* 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?
* 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
- 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)
-- 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)
-- Particpant matches are checked by memory content, and Endpoint matches by match frame
-- The Participant
-- Particpant matches are checked by memory content, and Endpoint matches by the generated match frame.
-- The PIDs handled are:
-- * PID_PARTICIPANT_GUID
-- * PID_DOMAIN_ID

View File

@ -10,7 +10,7 @@ use work.user_config.all;
use work.rtps_config_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
end entity;
@ -91,12 +91,12 @@ begin
);
stimulus_prc : process
variable sub, sub_p, sub_s : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE;
variable RV : RandomPType;
variable p0, participant : PARTICIPANT_DATA_TYPE := DEFAULT_PARTICIPANT_DATA;
variable e0, e1, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA;
variable p_sn, p_snp : SEQUENCENUMBER_TYPE := FIRST_SEQUENCENUMBER;
variable wr_sig : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
variable sub, sub_p, sub_s, sub_m : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE;
variable RV : RandomPType;
variable p0, participant : PARTICIPANT_DATA_TYPE := DEFAULT_PARTICIPANT_DATA;
variable e0, e1, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA;
variable p_sn, p_snp : SEQUENCENUMBER_TYPE := FIRST_SEQUENCENUMBER;
variable wr_sig : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
-- Wrapper to use procedure as function
impure function gen_rand_loc_2 return LOCATOR_TYPE is
@ -135,6 +135,15 @@ begin
end if;
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
variable wr_sig : std_logic_vector(NUM_ENDPOINTS-1 downto 0) := (others => '1');
begin
@ -173,25 +182,32 @@ begin
RV.InitSeed(RV'instance_name);
-- Participant RTPS Submessage
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_DATA;
sub.writerId := ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER;
sub.readerId := ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR;
sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_DATA;
sub.writerId := ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER;
sub.readerId := ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR;
sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
-- Publisher Endpoint RTPS Submessage
sub_p := DEFAULT_RTPS_SUBMESSAGE;
sub_p.submessageID := SID_DATA;
sub_p.writerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
sub_p.readerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
sub_p.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
sub_p := DEFAULT_RTPS_SUBMESSAGE;
sub_p.submessageID := SID_DATA;
sub_p.writerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
sub_p.readerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
sub_p.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
-- Subscriber Endpoint RTPS Submessage
sub_s := DEFAULT_RTPS_SUBMESSAGE;
sub_s.submessageID := SID_DATA;
sub_s.writerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER;
sub_s.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
sub_s.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
sub_s := DEFAULT_RTPS_SUBMESSAGE;
sub_s.submessageID := SID_DATA;
sub_s.writerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER;
sub_s.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
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
p0.guidPrefix := gen_rand_guid_prefix;
@ -421,6 +437,70 @@ begin
reference := 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';
wait_on_complete;
TranscriptOpen(RESULTS_FILE, APPEND_MODE);

View File

@ -129,30 +129,36 @@ architecture testbench of L1_rtps_builtin_endpoint_test1 is
rtps_header.guidPrefix := GUIDPREFIX;
gen_rtps_header(rtps_header, output);
-- PUBLISHER ACKNACK
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_ACKNACK;
sub.writerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER;
sub.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
sub.readerSNState.base := pub_sn;
sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH));
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_ACKNACK;
sub.writerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER;
sub.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
sub.readerSNState.base := pub_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';
gen_rtps_submessage(sub, output);
-- SUBSCRIBER ACKNACK
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_ACKNACK;
sub.writerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
sub.readerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
sub.count := std_logic_vector(to_unsigned(count, CDR_LONG_WIDTH));
sub.readerSNState.base := sub_sn;
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_ACKNACK;
sub.writerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
sub.readerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
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';
gen_rtps_submessage(sub, output);
-- MESSAGE ACKNACK
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_ACKNACK;
sub.writerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
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 := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_ACKNACK;
sub.writerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
sub.readerId := ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
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';
gen_rtps_submessage(sub, output);
fix_output_packet(output);

View File

@ -124,7 +124,7 @@ architecture arch of rtps_builtin_endpoint is
--*****TYPE DECLARATION*****
-- 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,
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,
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,
@ -514,6 +514,7 @@ begin
-- 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
-- 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
-- LIVELINESS_UPDATE Propagate Liveliness Assertion of remote Participant to respective local Reader Endpoints
-- PROCESS_GAP Parse RTPS GAP Submessage
@ -1217,8 +1218,7 @@ begin
-- Override Endian Flag
endian_flag_next <= '0';
stage_next <= PROCESS_MESSAGE;
cnt_next <= 0;
stage_next <= PROCESS_MESSAGE_SEQUENCE_NUMBERS;
end if;
when CDR_LE =>
-- Accept CDR Representation only for Participant Messages
@ -1226,8 +1226,7 @@ begin
-- Override Endian Flag
endian_flag_next <= '1';
stage_next <= PROCESS_MESSAGE;
cnt_next <= 0;
stage_next <= PROCESS_MESSAGE_SEQUENCE_NUMBERS;
end if;
when others =>
-- Skip Packet
@ -1235,6 +1234,34 @@ begin
end case;
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 =>
-- Input FIFO Guard
if (empty = '0') then
@ -1263,7 +1290,7 @@ begin
-- NOTE: Rest of Participant Message is ignored
-- 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
-- high complexity this would add this is not supported.
-- high complexity this would add, this is currently not supported.
case (data_in) is
-- Automatic Liveliness Assertion
when PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE =>
@ -1410,17 +1437,21 @@ begin
mem_field_flags <= PMF_MES_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
end if;
next_seq_nr_next <= first_seq_nr;
tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY;
res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if (tmp_dw < check_time) then
check_time_next <= tmp_dw;
if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY;
res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if (tmp_dw < check_time) then
check_time_next <= tmp_dw;
end if;
else
res_time <= TIME_INVALID;
end if;
-- 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
mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT;
@ -1494,15 +1525,19 @@ begin
mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
extra_flags <= participant_data.extra_flags or EF_PUB_DATA_FLAG;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if (tmp_dw < check_time) then
check_time_next <= tmp_dw;
if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
extra_flags <= participant_data.extra_flags or EF_PUB_DATA_FLAG;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if (tmp_dw < check_time) then
check_time_next <= tmp_dw;
end if;
else
res_time <= TIME_INVALID;
end if;
end if;
-- Publisher Acknack
@ -1513,15 +1548,19 @@ begin
mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
extra_flags <= participant_data.extra_flags or EF_SUB_DATA_FLAG;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if (tmp_dw < check_time) then
check_time_next <= tmp_dw;
if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
extra_flags <= participant_data.extra_flags or EF_SUB_DATA_FLAG;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if (tmp_dw < check_time) then
check_time_next <= tmp_dw;
end if;
else
res_time <= TIME_INVALID;
end if;
end if;
end if;
@ -1534,16 +1573,20 @@ begin
mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
extra_flags <= participant_data.extra_flags or EF_MES_DATA_FLAG;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
extra_flags <= participant_data.extra_flags or EF_MES_DATA_FLAG;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if (tmp_dw < check_time) then
check_time_next <= tmp_dw;
end if;
else
res_time <= TIME_INVALID;
end if;
end if;
when others =>
null;
@ -1725,7 +1768,7 @@ begin
mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT;
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
res_time <= time + PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -1746,7 +1789,7 @@ begin
mem_opcode <= UPDATE_PARTICIPANT;
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));
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
res_time <= time + PARTICIPANT_ACKNACK_SUPPRESSION_DELAY;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -2889,7 +2932,7 @@ begin
-- ACKNACK RTPS SUBMESSAGE (Publication)
-- RTPS Submessage Header
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
when 1 =>
data_out <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
@ -2904,53 +2947,68 @@ begin
data_out <= std_logic_vector(participant_data.pub_seq_nr(1));
-- Sequence Number Set (NumBits)
when 5 =>
data_out <= (others => '0');
-- Count
data_out <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH));
-- Sequence Number Set (Bitmap)
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);
-- ACKNACK RTPS SUBMESSAGE (Subscription)
-- RTPS Submessage Header
when 7 =>
data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(24, 16));
-- Reader Entity ID
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;
-- Writer Entity ID
when 9 =>
when 10 =>
data_out <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
-- Sequence Number Set (Bitmap Base 1/2)
when 10 =>
when 11 =>
data_out <= std_logic_vector(participant_data.sub_seq_nr(0));
-- Sequence Number Set (Bitmap Base 2/2)
when 11 =>
when 12 =>
data_out <= std_logic_vector(participant_data.sub_seq_nr(1));
-- Sequence Number Set (NumBits)
when 12 =>
data_out <= (others => '0');
-- Count
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);
-- ACKNACK RTPS SUBMESSAGE (Message)
-- RTPS Submessage Header
when 14 =>
data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(24, 16));
when 16 =>
data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16));
-- Reader Entity ID
when 15 =>
when 17 =>
data_out <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
-- Writer Entity ID
when 16 =>
when 18 =>
data_out <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
-- Sequence Number Set (Bitmap Base 1/2)
when 17 =>
when 19 =>
data_out <= std_logic_vector(participant_data.mes_seq_nr(0));
-- Sequence Number Set (Bitmap Base 2/2)
when 18 =>
when 20 =>
data_out <= std_logic_vector(participant_data.mes_seq_nr(1));
-- Sequence Number Set (NumBits)
when 19 =>
data_out <= (others => '0');
when 21 =>
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
when 20 =>
when 23 =>
data_out <= std_logic_vector(count);
last_word_out <= '1';