diff --git a/lib/include/srsran/interfaces/enb_rrc_interfaces.h b/lib/include/srsran/interfaces/enb_rrc_interfaces.h index 967426f50..961bd1a50 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/enb_rrc_interfaces.h @@ -91,6 +91,7 @@ class rrc_interface_rlc { public: virtual void max_retx_attempted(uint16_t rnti) = 0; + virtual void protocol_failure(uint16_t rnti) = 0; virtual void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) = 0; }; diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 35f19d651..50a3a5f0d 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -151,6 +151,7 @@ class rrc_interface_rlc_nr public: virtual void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) = 0; virtual void max_retx_attempted(uint16_t rnti) = 0; + virtual void protocol_failure(uint16_t rnti) = 0; virtual void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) = 0; virtual const char* get_rb_name(uint32_t lcid) = 0; }; diff --git a/lib/include/srsran/interfaces/ue_rrc_interfaces.h b/lib/include/srsran/interfaces/ue_rrc_interfaces.h index b72e59fdd..7b40ab483 100644 --- a/lib/include/srsran/interfaces/ue_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/ue_rrc_interfaces.h @@ -91,6 +91,7 @@ class rrc_interface_rlc { public: virtual void max_retx_attempted() = 0; + virtual void protocol_failure() = 0; virtual const char* get_rb_name(uint32_t lcid) = 0; virtual void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) = 0; }; diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index 89e163e60..5baa7907b 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -70,12 +70,14 @@ public: // RRC interface void max_retx_attempted() { max_retx_triggered = true; } + void protocol_failure() { protocol_failure_triggered = true; } const char* get_rb_name(uint32_t lcid) { return ""; } std::vector sdus; rlc_pcap* pcap = nullptr; bool max_retx_triggered = false; + bool protocol_failure_triggered = false; std::map notified_counts; // Map of PDCP SNs to number of notifications }; diff --git a/lib/test/upper/rlc_common_test.cc b/lib/test/upper/rlc_common_test.cc index 8437b5103..cdcf198c1 100644 --- a/lib/test/upper/rlc_common_test.cc +++ b/lib/test/upper/rlc_common_test.cc @@ -54,6 +54,7 @@ public: // RRC interface void max_retx_attempted() {} + void protocol_failure() {} const char* get_rb_name(uint32_t lcid) { return "TestRB"; } void set_expected_sdu_len(uint32_t len) { expected_sdu_len = len; } diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/upper/rlc_stress_test.cc index 5b2db1d91..bf7ed78f0 100644 --- a/lib/test/upper/rlc_stress_test.cc +++ b/lib/test/upper/rlc_stress_test.cc @@ -381,6 +381,12 @@ public: std::this_thread::sleep_for(std::chrono::seconds(1)); exit(1); } + void protocol_failure() + { + logger.error("RLC protocol error detected."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + exit(1); + } const char* get_rb_name(uint32_t rx_lcid) { return "DRB1"; } int get_nof_rx_pdus() { return rx_pdus; } diff --git a/lib/test/upper/rlc_test_common.h b/lib/test/upper/rlc_test_common.h index 0278bac39..494a09a60 100644 --- a/lib/test/upper/rlc_test_common.h +++ b/lib/test/upper/rlc_test_common.h @@ -56,6 +56,7 @@ public: // RRC interface void max_retx_attempted() {} + void protocol_failure() {} const char* get_rb_name(uint32_t lcid) { return ""; } void set_expected_sdu_len(uint32_t len) { expected_sdu_len = len; } diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 4e0b0c44b..274ae5d75 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -79,6 +79,7 @@ public: // rrc_interface_rlc void read_pdu_pcch(uint32_t tti_tx_dl, uint8_t* payload, uint32_t buffer_size) override; void max_retx_attempted(uint16_t rnti) override; + void protocol_failure(uint16_t rnti) override; // rrc_interface_s1ap void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) override; @@ -193,6 +194,7 @@ private: const static uint32_t LCID_RLC_RTX = 0xffff0005; const static uint32_t LCID_RADLINK_DL = 0xffff0006; const static uint32_t LCID_RADLINK_UL = 0xffff0007; + const static uint32_t LCID_PROT_FAIL = 0xffff0008; bool running = false; srsran::dyn_blocking_queue rx_pdu_queue; diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index b8fbf1622..70eebdecd 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -88,6 +88,7 @@ public: // TODO void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) {} void max_retx_attempted(uint16_t rnti) {} + void protocol_failure(uint16_t rnti) {} const char* get_rb_name(uint32_t lcid) { return "invalid"; } // PDCP interface void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) final; diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index b46302d62..2d1e0f171 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -46,6 +46,7 @@ public: void activity_timer_expired(const activity_timeout_type_t type); void rlf_timer_expired(uint32_t timeout_id); void max_rlc_retx_reached(); + void protocol_failure(); void deactivate_bearers() { mac_ctrl.set_radio_bearer_state(sched_interface::ue_bearer_cfg_t::IDLE); } rrc_state_t get_state(); @@ -62,6 +63,7 @@ public: error_unknown_rnti, radio_conn_with_ue_lost, msg3_timeout, + fail_in_radio_interface_proc, unspecified }; diff --git a/srsenb/hdr/stack/upper/rlc.h b/srsenb/hdr/stack/upper/rlc.h index a4a08ecfe..30fdc2875 100644 --- a/srsenb/hdr/stack/upper/rlc.h +++ b/srsenb/hdr/stack/upper/rlc.h @@ -78,6 +78,7 @@ private: void write_pdu_pcch(srsran::unique_byte_buffer_t sdu); void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} void max_retx_attempted(); + void protocol_failure(); const char* get_rb_name(uint32_t lcid); uint16_t rnti; diff --git a/srsenb/hdr/stack/upper/rlc_nr.h b/srsenb/hdr/stack/upper/rlc_nr.h index f655673e3..5e72e6382 100644 --- a/srsenb/hdr/stack/upper/rlc_nr.h +++ b/srsenb/hdr/stack/upper/rlc_nr.h @@ -67,6 +67,7 @@ private: void write_pdu_pcch(srsran::unique_byte_buffer_t sdu); void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} void max_retx_attempted() final; + void protocol_failure() final; const char* get_rb_name(uint32_t lcid) final; uint16_t rnti; diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index f9079443b..3d6992eb1 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -181,6 +181,14 @@ void rrc::max_retx_attempted(uint16_t rnti) } } +void rrc::protocol_failure(uint16_t rnti) +{ + rrc_pdu p = {rnti, LCID_PROT_FAIL, false, nullptr}; + if (not rx_pdu_queue.try_push(std::move(p))) { + logger.error("Failed to push protocol failure to RRC queue"); + } +} + // This function is called from PRACH worker (can wait) int rrc::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& sched_ue_cfg) { @@ -944,6 +952,9 @@ void rrc::tti_clock() case LCID_RLC_RTX: user_it->second->max_rlc_retx_reached(); break; + case LCID_PROT_FAIL: + user_it->second->protocol_failure(); + break; case LCID_EXIT: logger.info("Exiting thread"); break; diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 01d1d7cba..f1ad7d9a0 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -253,6 +253,17 @@ void rrc::ue::max_rlc_retx_reached() rlc_rlf_timer.run(); } +void rrc::ue::protocol_failure() +{ + parent->logger.info("RLC protocol failure for rnti=0x%x", rnti); + + // Release UE immediately with appropiate cause + state = RRC_STATE_RELEASE_REQUEST; + + parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::fail_in_radio_interface_proc); + con_release_result = procedure_result_code::fail_in_radio_interface_proc; +} + void rrc::ue::set_activity_timeout(activity_timeout_type_t type) { uint32_t deadline_ms = 0; diff --git a/srsenb/src/stack/upper/rlc.cc b/srsenb/src/stack/upper/rlc.cc index 6c43421aa..5f44dd2b7 100644 --- a/srsenb/src/stack/upper/rlc.cc +++ b/srsenb/src/stack/upper/rlc.cc @@ -255,6 +255,11 @@ void rlc::user_interface::max_retx_attempted() rrc->max_retx_attempted(rnti); } +void rlc::user_interface::protocol_failure() +{ + rrc->protocol_failure(rnti); +} + void rlc::user_interface::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { if (lcid == srb_to_lcid(lte_srb::srb0)) { diff --git a/srsenb/src/stack/upper/rlc_nr.cc b/srsenb/src/stack/upper/rlc_nr.cc index 67d079457..b441c83df 100644 --- a/srsenb/src/stack/upper/rlc_nr.cc +++ b/srsenb/src/stack/upper/rlc_nr.cc @@ -177,6 +177,11 @@ void rlc_nr::user_interface::max_retx_attempted() m_rrc->max_retx_attempted(rnti); } +void rlc_nr::user_interface::protocol_failure() +{ + m_rrc->protocol_failure(rnti); +} + void rlc_nr::user_interface::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { if (lcid == (int)srsran::nr_srb::srb0) { diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 003c6cb70..3125eaf2f 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -318,6 +318,7 @@ private: // RLC interface void max_retx_attempted(); + void protocol_failure(); // RRC NR interface void nr_scg_failure_information(const srsran::scg_failure_cause_t cause); diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index 605be42fe..80aee18b8 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -101,6 +101,7 @@ public: // RLC interface void max_retx_attempted() final; + void protocol_failure() final; // MAC interface void run_tti(uint32_t tti) final; diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 928547935..eca1a141f 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -719,6 +719,11 @@ void rrc::max_retx_attempted() radio_link_failure_push_cmd(); } +void rrc::protocol_failure() +{ + logger.warning("RLC protocol failure detected"); +} + void rrc::timer_expired(uint32_t timeout_id) { if (timeout_id == t310.id()) { diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 0ca80f752..7d0236aa2 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -1461,6 +1461,7 @@ bool rrc_nr::apply_radio_bearer_cfg(const radio_bearer_cfg_s& radio_bearer_cfg) } // RLC interface void rrc_nr::max_retx_attempted() {} +void rrc_nr::protocol_failure() {} // MAC interface void rrc_nr::ra_completed() {} diff --git a/srsue/test/ttcn3/hdr/ttcn3_syssim.h b/srsue/test/ttcn3/hdr/ttcn3_syssim.h index 1869b85dd..ffcfec54f 100644 --- a/srsue/test/ttcn3/hdr/ttcn3_syssim.h +++ b/srsue/test/ttcn3/hdr/ttcn3_syssim.h @@ -157,6 +157,7 @@ public: void write_pdu_pcch(unique_byte_buffer_t pdu); void write_pdu_mch(uint32_t lcid, unique_byte_buffer_t pdu); void max_retx_attempted(); + void protocol_failure(); const char* get_rb_name(uint32_t lcid); diff --git a/srsue/test/ttcn3/src/ttcn3_syssim.cc b/srsue/test/ttcn3/src/ttcn3_syssim.cc index c195dcd32..6ee227cba 100644 --- a/srsue/test/ttcn3/src/ttcn3_syssim.cc +++ b/srsue/test/ttcn3/src/ttcn3_syssim.cc @@ -1134,6 +1134,10 @@ void ttcn3_syssim::max_retx_attempted() { logger.error("%s not implemented.", __FUNCTION__); } +void ttcn3_syssim::protocol_failure() +{ + logger.error("%s not implemented.", __FUNCTION__); +} const char* ttcn3_syssim::get_rb_name(uint32_t lcid) {