From f0cc1e54328351a0acfafeaee419c0a1ea8b4a72 Mon Sep 17 00:00:00 2001 From: Greek Date: Sun, 7 Feb 2021 17:52:34 +0100 Subject: [PATCH] Various fixes in RTPS Reader Ignore unknown Metatraffic Operations. Drop payload if not necessary (i.e. do not push payload if payload contains serialized Key, but Key Hash is already provided). Added Memory Reset State. Misc fixes --- src/rtps_reader.vhd | 203 +++++++++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 78 deletions(-) diff --git a/src/rtps_reader.vhd b/src/rtps_reader.vhd index fab130d..9b8285c 100644 --- a/src/rtps_reader.vhd +++ b/src/rtps_reader.vhd @@ -6,12 +6,7 @@ use work.rtps_package.all; use work.user_config.all; use work.rtps_config_package.all; --- TODO: Use TIME_INVALID instead of zero. (Backport to builtin_endpoint) [Pay atention to (0) bit of ACKNACK and HEARTBEAT Deadlines, if compatible] --- TODO: Check for special values of time/duration? --- TODO: Remove last_word flag from metattraffic operations --- TODO: Replace all ('range => 0) checks with defined constants, where possible -- TODO: Adding LIFESPAN Duration in the stored Endpoint Metatraffic Data would allow us to not expect in-line QoS (Which could be a significant overhead) --- TODO: Is mem_addr_base needed? Isn't it a direct mirror of addr_mem_base? mem_addr_base is only used in the same clock cycle as mem_op_done is pulled high. entity rtps_reader is @@ -31,12 +26,13 @@ entity rtps_reader is -- FROM RTPS_HANDLER (USER TRAFFIC) empty_user : in std_logic; rd_user : out std_logic; - last_word_in_user : in std_logic; data_in_user : in std_logic_vector(WORD_WIDTH-1 downto 0); + last_word_in_user : in std_logic; -- FROM RTPS_BUILTIN_ENDPOINT (META TRAFFIC) empty_meta : in std_logic; - data_in_meta : in std_logic_vector(WORD_WIDTH-1 downto 0); rd_meta : out std_logic; + data_in_meta : in std_logic_vector(WORD_WIDTH-1 downto 0); + last_word_in_meta : in std_logic; -- RTPS OUTPUT wr_rtps : out std_logic; full_rtps : in std_logic; @@ -95,10 +91,10 @@ architecture arch of rtps_reader is type STAGE_TYPE is (IDLE, LATCH_GUIDPREFIX, LATCH_ENTITYID, INITIATE_ENDPOINT_SEARCH, LATCH_ENDPOINT_DATA, METATRAFFIC_OPERATION, LATCH_SRC_ADDR, LATCH_EXTRA_DATA, LATCH_HEARTBEAT, PROCESS_HEARTBEAT, LATCH_GAP, PROCESS_GAP, FIND_NEXT_VALID_IN_BITMAP, PROCESS_INLINE_QOS, LATCH_LIFESPAN, LATCH_KEY_HASH, LATCH_STATUS_INFO, INITIATE_ADD_CACHE_CHANGE_REQUEST, ADD_CACHE_CHANGE, PUSH_PAYLOAD, FINALIZE_ADD_CACHE_CHANGE_REQUEST, - ENDPOINT_STALE_CHECK, SEND_HEADER, SEND_ACKNACK, SKIP_PARAMETER, SKIP_PACKET); + ENDPOINT_STALE_CHECK, SEND_HEADER, SEND_ACKNACK, SKIP_PARAMETER, SKIP_PACKET, SKIP_META_OPERATION); -- Memory FSM states. Explained below in detail type MEM_STAGE_TYPE is (IDLE, SEARCH_ENDPOINT, GET_ENDPOINT_DATA, INSERT_ENDPOINT, UPDATE_ENDPOINT, REMOVE_ENDPOINT, FIND_EMPTY_SLOT, - RESET_MAX_POINTER, GET_NEXT_ENDPOINT); + RESET_MAX_POINTER, GET_NEXT_ENDPOINT, RESET_MEMORY); -- *Memory FSM Opcodes* -- OPCODE DESCRIPTION -- SEARCH_ENDPOINT Find Endpoint with specified GUID in memory @@ -320,10 +316,10 @@ begin read => mem_read, ready_in => mem_ready_in, valid_in => mem_valid_in, - data_in_user => mem_write_data, + data_in => mem_write_data, ready_out => mem_ready_out, valid_out => mem_valid_out, - data_out_rtps => mem_read_data + data_out => mem_read_data ); -- Big Endian Representation @@ -357,6 +353,7 @@ begin -- SEND_ACKNACK Send ACKNACK Submessage -- SKIP_PARAMETER Skip rest of Parameter -- SKIP_PACKET Skip rest of Packet + -- SKIP_META_OPERATION Skip Metatraffic Operation parse_prc : process(all) variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0')); -- NOTE: We convert the bitamp to a slv to make operations easier (The tool should handle both cases equally) @@ -364,14 +361,14 @@ begin variable rd_guard : std_logic := '0'; variable tmp_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (others => '0'); begin - -- DEFAULT Registerd + -- DEFAULT Registered stage_next <= stage; meta_opcode_next <= meta_opcode; cnt_next <= cnt; + cnt2_next <= cnt2; guid_next <= guid; addr_next <= addr; portn_next <= portn; - expects_inline_qos_next <= expects_inline_qos; is_meta_next <= is_meta; opcode_next <= opcode; flags_next <= flags; @@ -399,9 +396,8 @@ begin rd_user <= '0'; mem_op_start <= '0'; start_dds <= '0'; - ready_out_dds <= '0'; valid_out_dds <= '0'; - last_word_out_dds <= '0'; + last_word_out_dds <= '0'; rd_guard := '0'; mem_field_flags <= (others => '0'); data_out_dds <= (others => '0'); @@ -446,8 +442,22 @@ begin -- Latch Endpoint Metatraffic Opcode meta_opcode_next <= data_in_meta; - stage_next <= LATCH_GUIDPREFIX; - cnt_next <= 0; + case (data_in_meta) is + when OPCODE_ENDPOINT_MATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when OPCODE_ENDPOINT_UNMATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when OPCODE_PARTICIPANT_UNMATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when OPCODE_LIVELINESS_UPDATE => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when others => + stage_next <= SKIP_META_OPERATION; + end case; -- Input FIFO Guard elsif (empty_user = '0') then rd_guard := '1'; @@ -499,6 +509,7 @@ begin end if; if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or meta_opcode = OPCODE_LIVELINESS_UPDATE)) then + assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE; -- DONE Parsing stage_next <= INITIATE_ENDPOINT_SEARCH; else @@ -510,6 +521,7 @@ begin -- Input FIFO Guard if ((is_meta = '1' and empty_meta = '0') or (is_meta = '0' and empty_user = '0')) then if (is_meta = '1') then + assert (meta_opcode /= OPCODE_ENDPOINT_UNMATCH or (meta_opcode = OPCODE_ENDPOINT_UNMATCH and last_word_in_meta = '1')) "last_word_in_meta not set" severity FAILURE; rd_meta <= '1'; guid_next(3) <= data_in_meta; -- Memory Operation Guard @@ -555,7 +567,6 @@ begin stage_next <= METATRAFFIC_OPERATION; cnt_next <= 0; when others => - assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE; null; end case; else @@ -569,7 +580,7 @@ begin cnt_next <= 0; when SID_HEARTBEAT => stage_next <= LATCH_HEARTBEAT; - mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG; + mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG or EMF_RES_TIME_FLAG; cnt_next <= 0; when SID_GAP => stage_next <= LATCH_GAP; @@ -594,6 +605,8 @@ begin addr_next <= data_in_meta; -- UDP Port when 1 => + assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE; + portn_next <= data_in_meta(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH-1); stage_next <= METATRAFFIC_OPERATION; @@ -724,7 +737,6 @@ begin null; end case; when others => - assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE; null; end case; end if; @@ -823,7 +835,7 @@ begin end if; -- No scheduled Heartbeat Response - if (mem_endpoint_data.res_time = 0) then + if (mem_endpoint_data.res_time = TIME_INVALID) then -- If current Sequence Number obsolete (removed from source history cache) if (first_seq_nr > mem_endpoint_data.next_seq_nr and first_seq_nr <= last_seq_nr) then -- Store new expected Sequence Number and set Response Dealy @@ -894,18 +906,18 @@ begin -- GapList.Base 2/2 when 3 => gap_list_base_next(1) <= unsigned(data_in_user); - -- ReaderSNState.NumBits + -- GapList.NumBits when 4 => gap_list_end_next <= gap_list_base + to_integer(unsigned(data_in_user)); bitmap_cnt_next <= unsigned(round_slv(data_in_user(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length)); cnt2_next <= 0; - -- ReaderSNState.Bitmap + -- GapList.Bitmap when 5 => -- Read Bitmap if (cnt2 < bitmap_cnt) then cnt2_next <= cnt2 + 1; - bitmap_latch_next(cnt2) <= data_in_swapped; + bitmap_latch_next(cnt2) <= data_in_user; -- Keep Sub-State cnt_next <= cnt; @@ -1120,12 +1132,17 @@ begin stage_next <= SKIP_PARAMETER; end if; when INITIATE_ADD_CACHE_CHANGE_REQUEST => - start_dds <= '1'; - opcode_dds <= ADD_CACHE_CHANGE; - -- Wait until History Cache acknowledges request - if (res_dds = ACK) then - stage_next <= ADD_CACHE_CHANGE; - cnt_next <= 0; + -- SANITY CHECK: Skip if no Hash Key and no payload + if (WITH_KEY and key_hash_rcvd = '0' and data_flag = '0' and key_flag = '0') then + stage_next <= SKIP_PACKET; + else + start_dds <= '1'; + opcode_dds <= ADD_CACHE_CHANGE; + -- Wait until History Cache acknowledges request + if (res_dds = ACK) then + stage_next <= ADD_CACHE_CHANGE; + cnt_next <= 0; + end if; end if; when ADD_CACHE_CHANGE => case (cnt) is @@ -1218,8 +1235,10 @@ begin -- Output Guard if (ready_out_dds = '1') then + -- NOTE: We only push the Payload if there is Data, or if the Key Hash was not received and we need to push + -- the serialized Key. -- Payload exists - if (data_flag = '1' or (WITH_KEY and key_flag = '1')) then + if (data_flag = '1' or (WITH_KEY and key_hash_rcvd = '0')) then stage_next <= PUSH_PAYLOAD; else -- DONE @@ -1331,7 +1350,7 @@ begin end if; else -- Update Check Time - if (mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.res_time < mem_endpoint_data.lease_deadline) then + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.res_time < mem_endpoint_data.lease_deadline) then if (mem_endpoint_data.res_time < check_time) then check_time_next <= mem_endpoint_data.res_time; end if; @@ -1369,7 +1388,7 @@ begin mem_field_flags <= RES_TIME_FLAG; -- Send ACKNACK - -- Increment Heartbeat/Acknack Counter + -- Increment Acknack Counter count_next <= count + 1; stage_next <= SEND_HEADER; return_stage_next <= SEND_ACKNACK; @@ -1510,6 +1529,14 @@ begin -- Skip-Read rd_guard := '1'; end if; + when SKIP_META_OPERATION => + -- Skip-Read + rd_meta <= '1'; + + -- Exit Condition + if (last_word_in_meta = '1') then + stage_next <= IDLE; + end if; when others => null; end case; @@ -1556,6 +1583,7 @@ begin -- FIND_EMPTY_SLOT Find first empty_user slot in memory. -- RESET_MAX_POINTER Reset the max_endpoint_addr pointer to last occupied slot in memory. -- GET_NEXT_ENDPOINT See Memory OPCODE Description + -- RESET_MEMORY Reset Endpoint Memory to Empty State mem_ctrl_prc : process(all) begin -- DEFAULT Registered @@ -1669,8 +1697,7 @@ begin end if; when SEARCH_ENDPOINT => case (mem_cnt) is - -- *READ ADDRESS* - -- Entity ID + -- GET Entity ID when 0 => mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; mem_read <= '1'; @@ -1679,7 +1706,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 1/3 + -- GET GUID Prefix 1/3 when 1 => mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET; mem_read <= '1'; @@ -1688,7 +1715,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 2/3 + -- GET GUID Prefix 2/3 when 2 => mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1; mem_read <= '1'; @@ -1697,7 +1724,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 3/3 + -- GET GUID Prefix 3/3 when 3 => mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2; mem_read <= '1'; @@ -1706,8 +1733,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- *READ DATA* - -- Entity ID + -- READ Entity ID when 4 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -1730,7 +1756,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- GUID Prefix 1/3 + -- READ GUID Prefix 1/3 when 5 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -1753,7 +1779,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- GUID Prefix 2/3 + -- READ GUID Prefix 2/3 when 6 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -1776,7 +1802,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- GUID Prefix 3/3 + -- READ GUID Prefix 3/3 when 7 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -1827,8 +1853,7 @@ begin when GET_ENDPOINT_DATA => case (mem_cnt) is - -- *READ ADDR* - -- Entity ID + -- GET Entity ID when 0 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; @@ -1851,7 +1876,7 @@ begin mem_cnt_next <= 12; end if; end if; - -- GUID Prefix 1/3 + -- GET GUID Prefix 1/3 when 1 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET; @@ -1860,7 +1885,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 2/3 + -- GET GUID Prefix 2/3 when 2 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1; @@ -1869,7 +1894,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 3/3 + -- GET GUID Prefix 3/3 when 3 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2; @@ -1894,7 +1919,7 @@ begin end if; end if; end if; - -- IPv4 Address + -- GET IPv4 Address when 4 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -1922,7 +1947,7 @@ begin end if; end if; end if; - -- UDP Port/ Flags + -- GET UDP Port/ Flags when 5 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -1950,7 +1975,7 @@ begin end if; end if; end if; - -- Next Sequence Number 1/2 + -- GET Next Sequence Number 1/2 when 6 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET; @@ -1959,7 +1984,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- Next Sequence Number 2/2 + -- GET Next Sequence Number 2/2 when 7 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1; @@ -1984,7 +2009,7 @@ begin end if; end if; end if; - -- Lease Deadline 1/2 + -- GET Lease Deadline 1/2 when 8 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET; @@ -1993,7 +2018,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- Lease Deadline 2/2 + -- GET Lease Deadline 2/2 when 9 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1; @@ -2018,7 +2043,7 @@ begin end if; end if; end if; - -- Response Time 1/2 + -- GET Response Time 1/2 when 10 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2030,7 +2055,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- Response Time 2/2 + -- GET Response Time 2/2 when 11 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2056,8 +2081,7 @@ begin end if; end if; end if; - -- *READ DATA* - -- Entity ID + -- READ Entity ID when 12 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2081,7 +2105,7 @@ begin mem_stage_next <= IDLE; end if; end if; - -- GUID Prefix 1/3 + -- READ GUID Prefix 1/3 when 13 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2090,7 +2114,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 2/3 + -- READ GUID Prefix 2/3 when 14 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2099,7 +2123,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 3/3 + -- READ GUID Prefix 3/3 when 15 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2121,7 +2145,7 @@ begin mem_stage_next <= IDLE; end if; end if; - -- IPv4 Address + -- READ IPv4 Address when 16 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2144,7 +2168,7 @@ begin end if; end if; end if; - -- UDP Port + -- READ UDP Port when 17 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2165,7 +2189,7 @@ begin end if; end if; end if; - -- Next Sequence Number 1/2 + -- READ Next Sequence Number 1/2 when 18 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2174,7 +2198,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; - -- Next Sequence Number 2/2 + -- READ Next Sequence Number 2/2 when 19 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2190,7 +2214,7 @@ begin mem_stage_next <= IDLE; end if; end if; - -- Lease Deadline 1/2 + -- READ Lease Deadline 1/2 when 20 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2199,7 +2223,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; - -- Lease Deadline 2/2 + -- READ Lease Deadline 2/2 when 21 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2213,7 +2237,7 @@ begin mem_stage_next <= IDLE; end if; end if; - -- Response Time 1/2 + -- READ Response Time 1/2 when 22 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2225,7 +2249,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- Response Time 2/2 + -- READ Response Time 2/2 when 23 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2415,7 +2439,8 @@ begin mem_write_data <= std_logic_vector(mem_endpoint_latch_data.next_seq_nr(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') - mem_cnt_next <= mem_cnt + 1; + mem_cnt_next <= mem_cnt + 1; + end if; -- Next Sequence Number 2/2 when 3 => mem_valid_in <= '1'; @@ -2561,8 +2586,7 @@ begin end case; when RESET_MAX_POINTER => case (mem_cnt) is - -- *READ ADDRESS* - -- Entity ID + -- GET Entity ID when 0 => mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; mem_read <= '1'; @@ -2572,8 +2596,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= 1; end if; - -- *READ DATA* - -- Entity ID + -- READ Entity ID when 1 => mem_ready_out <= '1'; @@ -2618,8 +2641,7 @@ begin end case; when GET_NEXT_ENDPOINT => case (mem_cnt) is - -- *READ ADDRESS* - -- Entity ID + -- GET Entity ID when 0 => mem_valid_in <= '1'; mem_read <= '1'; @@ -2629,8 +2651,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= 1; end if; - -- *READ DATA* - -- Entity ID + -- READ Entity ID when 1 => mem_ready_out <= '1'; @@ -2677,6 +2698,32 @@ begin when others => null; end case; + when RESET_MEMORY => + case (mem_cnt) is + -- Initiate Reset + when 0 => + mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; + mem_cnt_next <= mem_cnt + 1; + -- Reset Memory + when 1 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; + mem_write_data <= ENTITYID_UNKNOWN; + + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + -- End of Memory + if (mem_addr_base = MAX_ENDPOINT_ADDRESS) then + -- DONE + mem_stage_next <= IDLE; + else + -- Next Endpoint Frame + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + end if; + end if; + when others => + null; + end case; when others => null; end case;