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:
parent
90a4c7928a
commit
293d89f083
11
src/TODO.txt
11
src/TODO.txt
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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';
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user