diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cf7d8b58..f526c1fdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,7 @@ option(ENABLE_ZMQ_TEST "Enable ZMQ based E2E tests" OFF) option(BUILD_STATIC "Attempt to statically link external deps" OFF) option(RPATH "Enable RPATH" OFF) option(ENABLE_ASAN "Enable gcc/clang address sanitizer" OFF) -option(ENABLE_GCOV "Enable gcc/clang address sanitizer" OFF) +option(ENABLE_GCOV "Enable gcov" OFF) option(ENABLE_MSAN "Enable clang memory sanitizer" OFF) option(ENABLE_TSAN "Enable clang thread sanitizer" OFF) option(ENABLE_TIDY "Enable clang tidy" OFF) diff --git a/README.md b/README.md index 7d4070090..ed6633c16 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ srsRAN ====== +[![Build Status](https://github.com/srsran/srsRAN/actions/workflows/ccpp.yml/badge.svg?branch=master)](https://github.com/srsran/srsRAN/actions) [![Build Status](https://app.travis-ci.com/srsran/srsRAN.svg?branch=master)](https://app.travis-ci.com/github/srsran/srsRAN) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/srsran/srsRAN.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/srsran/srsRAN/context:cpp) [![Coverity](https://scan.coverity.com/projects/23045/badge.svg)](https://scan.coverity.com/projects/srsran) diff --git a/lib/src/pdcp/pdcp.cc b/lib/src/pdcp/pdcp.cc index bf529261f..f824e8cf8 100644 --- a/lib/src/pdcp/pdcp.cc +++ b/lib/src/pdcp/pdcp.cc @@ -120,12 +120,7 @@ int pdcp::add_bearer(uint32_t lcid, const pdcp_config_t& cfg) if (cfg.rat == srsran::srsran_rat_t::lte) { entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid}); } else if (cfg.rat == srsran::srsran_rat_t::nr) { -#ifdef USE_PDCP_NR -#pragma message "Compiling with PDCP NR entity" entity.reset(new pdcp_entity_nr{rlc, rrc, gw, task_sched, logger, lcid}); -#else - entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid}); -#endif } if (not entity->configure(cfg)) { diff --git a/lib/src/pdcp/pdcp_entity_nr.cc b/lib/src/pdcp/pdcp_entity_nr.cc index 312346dfc..1eb7a0831 100644 --- a/lib/src/pdcp/pdcp_entity_nr.cc +++ b/lib/src/pdcp/pdcp_entity_nr.cc @@ -58,13 +58,17 @@ bool pdcp_entity_nr::configure(const pdcp_config_t& cnfg_) rlc_mode = rlc->rb_is_um(lcid) ? rlc_mode_t::UM : rlc_mode_t::AM; - // Timers - reordering_timer = task_sched.get_unique_timer(); - - // configure timer - if (static_cast(cfg.t_reordering) > 0) { - reordering_timer.set(static_cast(cfg.t_reordering), *reordering_fnc); + // t-Reordering timer + if (cfg.t_reordering != pdcp_t_reordering_t::infinity) { + reordering_timer = task_sched.get_unique_timer(); + if (static_cast(cfg.t_reordering) > 0) { + reordering_timer.set(static_cast(cfg.t_reordering), *reordering_fnc); + } + } else if (rlc_mode == rlc_mode_t::UM) { + logger.warning("%s possible PDCP-NR misconfiguration: using infinite re-ordering timer with RLC UM bearer.", + rb_name); } + active = true; logger.info("%s PDCP-NR entity configured. SN_LEN=%d, Discard timer %d, Re-ordering timer %d, RLC=%s, RAT=%s", rb_name, @@ -276,10 +280,13 @@ void pdcp_entity_nr::write_pdu(unique_byte_buffer_t pdu) reordering_timer.stop(); } - if (not reordering_timer.is_running() and rx_deliv < rx_next) { - rx_reord = rx_next; - reordering_timer.run(); + if (cfg.t_reordering != pdcp_t_reordering_t::infinity) { + if (not reordering_timer.is_running() and rx_deliv < rx_next) { + rx_reord = rx_next; + reordering_timer.run(); + } } + logger.debug("Rx PDCP state - RX_NEXT=%u, RX_DELIV=%u, RX_REORD=%u", rx_next, rx_deliv, rx_reord); } diff --git a/lib/src/rlc/rlc_am_nr_packing.cc b/lib/src/rlc/rlc_am_nr_packing.cc index b84dcaf23..dc7456b09 100644 --- a/lib/src/rlc/rlc_am_nr_packing.cc +++ b/lib/src/rlc/rlc_am_nr_packing.cc @@ -351,6 +351,12 @@ rlc_am_nr_read_status_pdu_12bit_sn(const uint8_t* payload, const uint32_t nof_by ptr++; while (e1 != 0) { + // check buffer headroom + if (uint32_t(ptr - payload) >= nof_bytes) { + fprintf(stderr, "Malformed PDU, trying to read more bytes than it is available\n"); + return 0; + } + // E1 flag set, read a NACK_SN rlc_status_nack_t nack = {}; nack.nack_sn = (*ptr & 0xff) << 4; @@ -385,10 +391,6 @@ rlc_am_nr_read_status_pdu_12bit_sn(const uint8_t* payload, const uint32_t nof_by ptr++; } status->push_nack(nack); - if (uint32_t(ptr - payload) > nof_bytes) { - fprintf(stderr, "Malformed PDU, trying to read more bytes than it is available\n"); - return 0; - } } return SRSRAN_SUCCESS; @@ -430,6 +432,12 @@ rlc_am_nr_read_status_pdu_18bit_sn(const uint8_t* payload, const uint32_t nof_by ptr++; while (e1 != 0) { + // check buffer headroom + if (uint32_t(ptr - payload) >= nof_bytes) { + fprintf(stderr, "Malformed PDU, trying to read more bytes than it is available\n"); + return 0; + } + // E1 flag set, read a NACK_SN rlc_status_nack_t nack = {}; @@ -467,10 +475,6 @@ rlc_am_nr_read_status_pdu_18bit_sn(const uint8_t* payload, const uint32_t nof_by ptr++; } status->push_nack(nack); - if (uint32_t(ptr - payload) > nof_bytes) { - fprintf(stderr, "Malformed PDU, trying to read more bytes than it is available\n"); - return 0; - } } return SRSRAN_SUCCESS; diff --git a/srsgnb/hdr/stack/rrc/cell_asn1_config.h b/srsgnb/hdr/stack/rrc/cell_asn1_config.h index e6cb8ce6d..3f7e02fb8 100644 --- a/srsgnb/hdr/stack/rrc/cell_asn1_config.h +++ b/srsgnb/hdr/stack/rrc/cell_asn1_config.h @@ -53,11 +53,11 @@ bool compute_diff_radio_bearer_cfg(const rrc_nr_cfg_t& cfg, asn1::rrc_nr::radio_bearer_cfg_s& diff); /// Apply radioBearerConfig updates to CellGroupConfig -void fill_cellgroup_with_radio_bearer_cfg(const rrc_nr_cfg_t& cfg, - uint32_t rnti, - const enb_bearer_manager& bearer_mapper, - const asn1::rrc_nr::radio_bearer_cfg_s& bearers, - asn1::rrc_nr::cell_group_cfg_s& out); +int fill_cellgroup_with_radio_bearer_cfg(const rrc_nr_cfg_t& cfg, + uint32_t rnti, + const enb_bearer_manager& bearer_mapper, + const asn1::rrc_nr::radio_bearer_cfg_s& bearers, + asn1::rrc_nr::cell_group_cfg_s& out); } // namespace srsenb diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h index 712ffc16e..d41d18b02 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h @@ -196,6 +196,7 @@ private: sched_nr_interface::ue_cfg_t uecfg{}; const uint32_t drb1_lcid = 4; + uint32_t drb1_five_qi = 0; /// selected by 5GC // Security helper srsgnb::nr_security_context sec_ctx; diff --git a/srsgnb/src/stack/ngap/ngap_ue.cc b/srsgnb/src/stack/ngap/ngap_ue.cc index d6eda72aa..49166eed4 100644 --- a/srsgnb/src/stack/ngap/ngap_ue.cc +++ b/srsgnb/src/stack/ngap/ngap_ue.cc @@ -260,6 +260,11 @@ bool ngap::ue::send_ue_context_release_request(asn1::ngap::cause_c cause) return false; } + if (not ctxt.amf_ue_ngap_id.has_value()) { + logger.warning("Can't send release request. User 0x%x has no AMF UE Id.", ctxt.rnti); + return false; + } + if (was_ue_context_release_requested()) { // let timeout auto-remove user. return false; diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index f367b4165..9f6230ebf 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -1340,11 +1340,11 @@ bool compute_diff_radio_bearer_cfg(const rrc_nr_cfg_t& cfg, diff.drb_to_add_mod_list.size() > 0; } -void fill_cellgroup_with_radio_bearer_cfg(const rrc_nr_cfg_t& cfg, - const uint32_t rnti, - const enb_bearer_manager& bearer_mapper, - const asn1::rrc_nr::radio_bearer_cfg_s& bearers, - asn1::rrc_nr::cell_group_cfg_s& out) +int fill_cellgroup_with_radio_bearer_cfg(const rrc_nr_cfg_t& cfg, + const uint32_t rnti, + const enb_bearer_manager& bearer_mapper, + const asn1::rrc_nr::radio_bearer_cfg_s& bearers, + asn1::rrc_nr::cell_group_cfg_s& out) { out.rlc_bearer_to_add_mod_list.clear(); out.rlc_bearer_to_release_list.clear(); @@ -1359,13 +1359,19 @@ void fill_cellgroup_with_radio_bearer_cfg(const rrc_nr_cfg_t& out.rlc_bearer_to_add_mod_list.push_back({}); uint32_t lcid = drb.drb_id + (int)srsran::nr_srb::count - 1; enb_bearer_manager::radio_bearer_t rb = bearer_mapper.get_lcid_bearer(rnti, lcid); - fill_drb(cfg, rb, (srsran::nr_drb)drb.drb_id, out.rlc_bearer_to_add_mod_list.back()); + if (rb.is_valid() and cfg.five_qi_cfg.find(rb.five_qi) != cfg.five_qi_cfg.end()) { + fill_drb(cfg, rb, (srsran::nr_drb)drb.drb_id, out.rlc_bearer_to_add_mod_list.back()); + } else { + return SRSRAN_ERROR; + } } // Release DRBs for (uint8_t drb_id : bearers.drb_to_release_list) { out.rlc_bearer_to_release_list.push_back(drb_id); } + + return SRSRAN_SUCCESS; } } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 4eca86067..39d68f72e 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -909,8 +909,13 @@ void rrc_nr::ue::handle_rrc_reestablishment_request(const asn1::rrc_nr::rrc_rees // compute config and create SRB1 for new user asn1::rrc_nr::radio_bearer_cfg_s dummy_radio_bearer_cfg; // just to compute difference, it's never sent to UE compute_diff_radio_bearer_cfg(parent->cfg, radio_bearer_cfg, next_radio_bearer_cfg, dummy_radio_bearer_cfg); - fill_cellgroup_with_radio_bearer_cfg( - parent->cfg, old_rnti, *parent->bearer_mapper, dummy_radio_bearer_cfg, next_cell_group_cfg); + if (fill_cellgroup_with_radio_bearer_cfg( + parent->cfg, old_rnti, *parent->bearer_mapper, dummy_radio_bearer_cfg, next_cell_group_cfg) != + SRSRAN_SUCCESS) { + logger.error("Couldn't fill cellGroupCfg during RRC Reestablishment"); + send_rrc_reject(max_wait_time_secs); + return; + } // send RRC Reestablishment message and restore bearer configuration send_connection_reest(old_ue->sec_ctx.get_ncc()); @@ -929,6 +934,7 @@ void rrc_nr::ue::handle_rrc_reestablishment_request(const asn1::rrc_nr::rrc_rees // Reestablish E-RABs of old rnti later, during ConnectionReconfiguration // bearer_list.reestablish_bearers(std::move(old_ue->bearer_list)); + drb1_five_qi = old_ue->drb1_five_qi; // remove old RNTI old_ue->deactivate_bearers(); @@ -948,12 +954,14 @@ void rrc_nr::ue::send_connection_reest(uint8_t ncc) // set NCC reest.next_hop_chaining_count = ncc; - // add PDCP bearers - update_pdcp_bearers(next_radio_bearer_cfg, next_cell_group_cfg); - // add RLC bearers update_rlc_bearers(next_cell_group_cfg); + // add PDCP bearers + // this is done after updating the RLC bearers, + // so the PDCP can query the RLC mode + update_pdcp_bearers(next_radio_bearer_cfg, next_cell_group_cfg); + // add MAC bearers update_mac(next_cell_group_cfg, false); @@ -1003,8 +1011,14 @@ void rrc_nr::ue::send_rrc_setup() // - Setup masterCellGroup // - Derive master cell group config bearers - fill_cellgroup_with_radio_bearer_cfg( - parent->cfg, rnti, *parent->bearer_mapper, setup_ies.radio_bearer_cfg, next_cell_group_cfg); + if (fill_cellgroup_with_radio_bearer_cfg( + parent->cfg, rnti, *parent->bearer_mapper, setup_ies.radio_bearer_cfg, next_cell_group_cfg) != + SRSRAN_SUCCESS) { + logger.error("Couldn't fill cellGroupCfg during RRC Setup"); + send_rrc_reject(max_wait_time_secs); + return; + } + // - Pack masterCellGroup into container srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(next_cell_group_cfg, __FUNCTION__); if (pdu == nullptr) { @@ -1019,12 +1033,14 @@ void rrc_nr::ue::send_rrc_setup() logger.debug("Containerized MasterCellGroup: %s", js.to_string().c_str()); } - // add PDCP bearers - update_pdcp_bearers(setup_ies.radio_bearer_cfg, next_cell_group_cfg); - // add RLC bearers update_rlc_bearers(next_cell_group_cfg); + // add PDCP bearers + // this is done after updating the RLC bearers, + // so the PDCP can query the RLC mode + update_pdcp_bearers(next_radio_bearer_cfg, next_cell_group_cfg); + // add MAC bearers update_mac(next_cell_group_cfg, false); @@ -1146,8 +1162,12 @@ void rrc_nr::ue::send_rrc_reconfiguration() // Fill masterCellGroup cell_group_cfg_s master_cell_group; master_cell_group.cell_group_id = 0; - fill_cellgroup_with_radio_bearer_cfg( - parent->cfg, rnti, *parent->bearer_mapper, ies.radio_bearer_cfg, master_cell_group); + if (fill_cellgroup_with_radio_bearer_cfg( + parent->cfg, rnti, *parent->bearer_mapper, ies.radio_bearer_cfg, master_cell_group) != SRSRAN_SUCCESS) { + logger.error("Couldn't fill cellGroupCfg during RRC Reconfiguration"); + parent->ngap->user_release_request(rnti, asn1::ngap::cause_radio_network_opts::radio_res_not_available); + return; + } // Pack masterCellGroup into container srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(master_cell_group, __FUNCTION__); @@ -1171,6 +1191,8 @@ void rrc_nr::ue::send_rrc_reconfiguration() update_rlc_bearers(master_cell_group); // add PDCP bearers + // this is done after updating the RLC bearers, + // so the PDCP can query the RLC mode update_pdcp_bearers(ies.radio_bearer_cfg, master_cell_group); } @@ -1258,6 +1280,7 @@ void rrc_nr::ue::handle_rrc_reestablishment_complete(const asn1::rrc_nr::rrc_ree for (const auto& drb : next_radio_bearer_cfg.drb_to_add_mod_list) { uint16_t lcid = drb1_lcid; parent->bearer_mapper->add_eps_bearer(rnti, lcid - 3, srsran::srsran_rat_t::nr, lcid); + parent->bearer_mapper->set_five_qi(rnti, lcid - 3, drb1_five_qi); logger.info("Established EPS bearer for LCID %u and RNTI 0x%x", lcid, rnti); } @@ -1310,6 +1333,11 @@ void rrc_nr::ue::establish_eps_bearer(uint32_t pdu_session_id, uint32_t lcid, uint32_t five_qi) { + if (parent->cfg.five_qi_cfg.find(five_qi) == parent->cfg.five_qi_cfg.end()) { + parent->logger.error("No bearer config for 5QI %d present. Aborting DRB addition.", five_qi); + return; + } + // Enqueue NAS PDU srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); if (pdu == nullptr) { @@ -1345,6 +1373,9 @@ void rrc_nr::ue::establish_eps_bearer(uint32_t pdu_session_id, rnti, lcid - 3, srsran::srsran_rat_t::nr, lcid); // TODO: configurable bearer id <-> lcid mapping parent->bearer_mapper->set_five_qi(rnti, lcid - 3, five_qi); + // store 5QI for possible reestablishment of DRB + drb1_five_qi = five_qi; + logger.info("Established EPS bearer for LCID %u and RNTI 0x%x", lcid, rnti); } diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index 5252fbf70..5b2868e68 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -115,7 +115,7 @@ int test_rrc_setup() rrc_nr rrc_obj(&task_sched); // set cfg - rrc_nr_cfg_t rrc_cfg_nr; + rrc_nr_cfg_t rrc_cfg_nr = {}; rrc_cfg_nr.cell_list.emplace_back(); generate_default_nr_cell(rrc_cfg_nr.cell_list[0]); rrc_cfg_nr.cell_list[0].phy_cell.carrier.pci = 500; diff --git a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc index 516ac500d..36858ecb4 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc @@ -333,13 +333,13 @@ srsran::proc_outcome_t rrc_nr::connection_setup_proc::init(const asn1::rrc_nr::r // Stop T300 rrc_handle.t300.stop(); - // Apply the Radio Bearer configuration - if (!rrc_handle.apply_radio_bearer_cfg(radio_bearer_cfg_)) { + // Apply the Cell Group configuration + if (!rrc_handle.update_cell_group_cfg(cell_group_)) { return proc_outcome_t::error; } - // Apply the Cell Group configuration - if (!rrc_handle.update_cell_group_cfg(cell_group_)) { + // Apply the Radio Bearer configuration + if (!rrc_handle.apply_radio_bearer_cfg(radio_bearer_cfg_)) { return proc_outcome_t::error; }