From 05fbca43d11cee31e81a52035b7484c31dbab691 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 29 Jun 2021 14:46:52 +0100 Subject: [PATCH 01/50] Fix GCC 11 warning in dyn_array --- lib/include/srsran/asn1/asn1_utils.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/include/srsran/asn1/asn1_utils.h b/lib/include/srsran/asn1/asn1_utils.h index 0361359e9..f86f7eee1 100644 --- a/lib/include/srsran/asn1/asn1_utils.h +++ b/lib/include/srsran/asn1/asn1_utils.h @@ -227,11 +227,13 @@ public: size_ = new_size; return; } + T* old_data = data_; cap_ = new_size > new_cap ? new_size : new_cap; if (cap_ > 0) { data_ = new T[cap_]; if (old_data != NULL) { + srsran_assert(cap_ > size_, "Old size larger than new capacity in dyn_array\n"); std::copy(&old_data[0], &old_data[size_], data_); } } else { From 4ed33fed7df1fb251d71fc512bfe6af618bccd51 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Thu, 10 Jun 2021 19:36:26 +0200 Subject: [PATCH 02/50] Fixed unpack bytes limit --- lib/src/asn1/asn1_utils.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/src/asn1/asn1_utils.cc b/lib/src/asn1/asn1_utils.cc index 6433d8d7a..fc32bb770 100644 --- a/lib/src/asn1/asn1_utils.cc +++ b/lib/src/asn1/asn1_utils.cc @@ -237,15 +237,20 @@ SRSASN_CODE bit_ref_impl::unpack_bytes(uint8_t* buf, uint32_t n_bytes) if (n_bytes == 0) { return SRSASN_SUCCESS; } - if (ptr + n_bytes >= max_ptr) { - log_error("Buffer size limit was achieved"); - return SRSASN_ERROR_DECODE_FAIL; - } if (offset == 0) { // Aligned case + if (ptr + n_bytes > max_ptr) { + log_error("Buffer size limit was achieved"); + return SRSASN_ERROR_DECODE_FAIL; + } memcpy(buf, ptr, n_bytes); ptr += n_bytes; } else { + // Unaligned case + if (ptr + n_bytes >= max_ptr) { + log_error("Buffer size limit was achieved"); + return SRSASN_ERROR_DECODE_FAIL; + } for (uint32_t i = 0; i < n_bytes; ++i) { HANDLE_CODE(unpack(buf[i], 8)); } @@ -274,7 +279,7 @@ SRSASN_CODE bit_ref_impl::advance_bits(uint32_t n_bits) uint32_t bytes_required = ceilf((offset + n_bits) / 8.0f); uint32_t bytes_offset = floorf((offset + n_bits) / 8.0f); - if (ptr + bytes_required >= max_ptr) { + if (ptr + bytes_required > max_ptr) { log_error("Buffer size limit was achieved"); return SRSASN_ERROR_DECODE_FAIL; } From c0fd64c4e6aa6889d451c55256fc671d2f6f1084 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 1 Jul 2021 13:01:24 +0200 Subject: [PATCH 03/50] Fix data races in srsENB MAC --- srsenb/hdr/stack/mac/ta.h | 4 ++++ srsenb/hdr/stack/mac/ue.h | 1 + srsenb/src/stack/mac/ue.cc | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/srsenb/hdr/stack/mac/ta.h b/srsenb/hdr/stack/mac/ta.h index 068bb9227..1e7591dd9 100644 --- a/srsenb/hdr/stack/mac/ta.h +++ b/srsenb/hdr/stack/mac/ta.h @@ -67,6 +67,8 @@ private: float ta_us; ///< TA measurement in microseconds } ta_meas_t; + std::mutex mutex; + uint32_t meas_t_ms = 0; ///< Time counter in milliseconds uint32_t meas_count = 0; ///< Number of measures in the buffer uint32_t meas_idx = 0; ///< Next mesurement index in the buffer @@ -211,6 +213,7 @@ public: */ uint32_t push_value(float ta_us) { + std::lock_guard lock(mutex); // Put measurement if state is measurement if (state == state_measure) { // Set measurement @@ -238,6 +241,7 @@ public: */ uint32_t tick() { + std::lock_guard lock(mutex); // Increase measurement timestamp counter meas_t_ms++; diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 895466104..3718771ad 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -164,6 +164,7 @@ public: srsran::unique_byte_buffer_t release_pdu(uint32_t tti, uint32_t enb_cc_idx); void clear_old_buffers(uint32_t tti); + std::mutex metrics_mutex = {}; void metrics_read(mac_ue_metrics_t* metrics_); void metrics_rx(bool crc, uint32_t tbs); void metrics_tx(bool crc, uint32_t tbs); diff --git a/srsenb/src/stack/mac/ue.cc b/srsenb/src/stack/mac/ue.cc index 4a54a7294..cae9939f2 100644 --- a/srsenb/src/stack/mac/ue.cc +++ b/srsenb/src/stack/mac/ue.cc @@ -596,9 +596,13 @@ uint8_t* ue::generate_mch_pdu(uint32_t harq_pid, /******* METRICS interface ***************/ void ue::metrics_read(mac_ue_metrics_t* metrics_) { + uint32_t ul_buffer = sched->get_ul_buffer(rnti); + uint32_t dl_buffer = sched->get_dl_buffer(rnti); + + std::lock_guard lock(metrics_mutex); ue_metrics.rnti = rnti; - ue_metrics.ul_buffer = sched->get_ul_buffer(rnti); - ue_metrics.dl_buffer = sched->get_dl_buffer(rnti); + ue_metrics.ul_buffer = ul_buffer; + ue_metrics.dl_buffer = dl_buffer; // set PCell sector id std::array cc_list = sched->get_enb_ue_cc_map(rnti); @@ -614,12 +618,14 @@ void ue::metrics_read(mac_ue_metrics_t* metrics_) void ue::metrics_phr(float phr) { + std::lock_guard lock(metrics_mutex); ue_metrics.phr = SRSRAN_VEC_CMA(phr, ue_metrics.phr, phr_counter); phr_counter++; } void ue::metrics_dl_ri(uint32_t dl_ri) { + std::lock_guard lock(metrics_mutex); if (ue_metrics.dl_ri == 0.0f) { ue_metrics.dl_ri = (float)dl_ri + 1.0f; } else { @@ -630,18 +636,21 @@ void ue::metrics_dl_ri(uint32_t dl_ri) void ue::metrics_dl_pmi(uint32_t dl_ri) { + std::lock_guard lock(metrics_mutex); ue_metrics.dl_pmi = SRSRAN_VEC_CMA((float)dl_ri, ue_metrics.dl_pmi, dl_pmi_counter); dl_pmi_counter++; } void ue::metrics_dl_cqi(uint32_t dl_cqi) { + std::lock_guard lock(metrics_mutex); ue_metrics.dl_cqi = SRSRAN_VEC_CMA((float)dl_cqi, ue_metrics.dl_cqi, dl_cqi_counter); dl_cqi_counter++; } void ue::metrics_rx(bool crc, uint32_t tbs) { + std::lock_guard lock(metrics_mutex); if (crc) { ue_metrics.rx_brate += tbs * 8; } else { @@ -652,6 +661,7 @@ void ue::metrics_rx(bool crc, uint32_t tbs) void ue::metrics_tx(bool crc, uint32_t tbs) { + std::lock_guard lock(metrics_mutex); if (crc) { ue_metrics.tx_brate += tbs * 8; } else { @@ -662,6 +672,7 @@ void ue::metrics_tx(bool crc, uint32_t tbs) void ue::metrics_cnt() { + std::lock_guard lock(metrics_mutex); ue_metrics.nof_tti++; } From 4e39982a19f9e22ff477d79aa734607501d9e320 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 1 Jul 2021 17:39:54 +0200 Subject: [PATCH 04/50] Fix TSAN warnings in UE (#3021) * Protect PHY SR signal management in a class * Protect intra_freq_meas vector * Protect cell and srate shared variables in thread-safe classes * srsue,srsenb: include TSAN options header * Protect ue_rnti_t and rnti scheduling windows behind thread-safe classes * Protect access to state variable in sync_state * Protect access to metrics configuration * Protect access to is_pending_sr * Protect access to UE prach worker * Protect UE mux * Avoid unlocking mutex twice * Fix data races in RF/ZMQ * Fix data races in intra_measure and PHY * Fix minor data races in MAC * Make TSAN default behaviour to not halt on error * Fix blocking in intra cell measurement * Address comments Co-authored-by: Andre Puschmann --- .../srsran/interfaces/ue_mac_interfaces.h | 22 +-- lib/src/phy/rf/rf_imp.c | 4 +- lib/src/phy/rf/rf_zmq_imp.c | 15 +- lib/src/phy/rf/rf_zmq_imp_trx.h | 2 + lib/src/phy/rf/rf_zmq_imp_tx.c | 8 + srsenb/src/main.cc | 1 + srsue/hdr/metrics_json.h | 2 + srsue/hdr/metrics_stdout.h | 1 + srsue/hdr/phy/phy.h | 2 +- srsue/hdr/phy/phy_common.h | 50 +++++- srsue/hdr/phy/scell/intra_measure_base.h | 6 +- srsue/hdr/phy/scell/intra_measure_lte.h | 3 +- srsue/hdr/phy/scell/intra_measure_nr.h | 3 +- srsue/hdr/phy/sync.h | 93 ++++++++++- srsue/hdr/phy/sync_state.h | 12 +- srsue/hdr/stack/mac/dl_harq.h | 8 +- srsue/hdr/stack/mac/mac.h | 15 +- srsue/hdr/stack/mac/mux.h | 1 + srsue/hdr/stack/mac/proc_ra.h | 7 +- srsue/hdr/stack/mac/proc_sr.h | 4 + srsue/hdr/stack/mac/ul_harq.h | 7 +- srsue/hdr/stack/mac_common/mac_common.h | 157 ++++++++++++++++++ srsue/src/main.cc | 1 + srsue/src/metrics_csv.cc | 2 + srsue/src/metrics_json.cc | 2 + srsue/src/metrics_stdout.cc | 3 + srsue/src/phy/lte/cc_worker.cc | 10 +- srsue/src/phy/phy.cc | 14 +- srsue/src/phy/phy_common.cc | 5 +- srsue/src/phy/prach.cc | 5 + srsue/src/phy/scell/intra_measure_base.cc | 6 +- srsue/src/phy/scell/intra_measure_lte.cc | 4 +- srsue/src/phy/scell/intra_measure_nr.cc | 4 +- srsue/src/phy/sync.cc | 108 ++++++------ srsue/src/stack/mac/dl_harq.cc | 18 +- srsue/src/stack/mac/mac.cc | 127 ++++++-------- srsue/src/stack/mac/mux.cc | 14 +- srsue/src/stack/mac/proc_ra.cc | 34 ++-- srsue/src/stack/mac/proc_sr.cc | 64 ++++--- srsue/src/stack/mac/ul_harq.cc | 30 ++-- srsue/src/stack/rrc/rrc_procedures.cc | 12 +- srsue/src/stack/rrc/test/rrc_meas_test.cc | 6 +- 42 files changed, 616 insertions(+), 276 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_mac_interfaces.h b/lib/include/srsran/interfaces/ue_mac_interfaces.h index 540e5f130..d34a2fd8f 100644 --- a/lib/include/srsran/interfaces/ue_mac_interfaces.h +++ b/lib/include/srsran/interfaces/ue_mac_interfaces.h @@ -100,21 +100,7 @@ public: virtual void set_mbsfn_config(uint32_t nof_mbsfn_services) = 0; }; -class mac_interface_rrc_common -{ -public: - // Class to handle UE specific RNTIs between RRC and MAC - typedef struct { - uint16_t crnti; - uint16_t rar_rnti; - uint16_t temp_rnti; - uint16_t tpc_rnti; - uint16_t sps_rnti; - uint64_t contention_id; - } ue_rnti_t; -}; - -class mac_interface_rrc : public mac_interface_rrc_common +class mac_interface_rrc { public: /* Instructs the MAC to start receiving BCCH */ @@ -138,9 +124,9 @@ public: virtual void set_rach_ded_cfg(uint32_t preamble_index, uint32_t prach_mask) = 0; - virtual void get_rntis(ue_rnti_t* rntis) = 0; - virtual void set_contention_id(uint64_t uecri) = 0; - virtual void set_ho_rnti(uint16_t crnti, uint16_t target_pci) = 0; + virtual uint16_t get_crnti() = 0; + virtual void set_contention_id(uint64_t uecri) = 0; + virtual void set_ho_rnti(uint16_t crnti, uint16_t target_pci) = 0; virtual void reconfiguration(const uint32_t& cc_idx, const bool& enable) = 0; virtual void reset() = 0; diff --git a/lib/src/phy/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index eb0cac1ad..6da4fa88d 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -28,12 +28,12 @@ int rf_get_available_devices(char** devnames, int max_strlen) int srsran_rf_set_rx_gain_th(srsran_rf_t* rf, double gain) { + pthread_mutex_lock(&rf->mutex); if (gain > rf->cur_rx_gain + 2 || gain < rf->cur_rx_gain - 2) { - pthread_mutex_lock(&rf->mutex); rf->new_rx_gain = gain; pthread_cond_signal(&rf->cond); - pthread_mutex_unlock(&rf->mutex); } + pthread_mutex_unlock(&rf->mutex); return SRSRAN_SUCCESS; } diff --git a/lib/src/phy/rf/rf_zmq_imp.c b/lib/src/phy/rf/rf_zmq_imp.c index 793c0862b..e4f05a52c 100644 --- a/lib/src/phy/rf/rf_zmq_imp.c +++ b/lib/src/phy/rf/rf_zmq_imp.c @@ -53,6 +53,7 @@ typedef struct { pthread_mutex_t tx_config_mutex; pthread_mutex_t rx_config_mutex; pthread_mutex_t decim_mutex; + pthread_mutex_t rx_gain_mutex; } rf_zmq_handler_t; void update_rates(rf_zmq_handler_t* handler, double srate); @@ -196,7 +197,9 @@ int rf_zmq_open_multi(char* args, void** h, uint32_t nof_channels) bzero(handler, sizeof(rf_zmq_handler_t)); *h = handler; handler->base_srate = ZMQ_BASERATE_DEFAULT_HZ; // Sample rate for 100 PRB cell + pthread_mutex_lock(&handler->rx_gain_mutex); handler->rx_gain = 0.0; + pthread_mutex_unlock(&handler->rx_gain_mutex); handler->info.max_rx_gain = ZMQ_MAX_GAIN_DB; handler->info.min_rx_gain = ZMQ_MIN_GAIN_DB; handler->info.max_tx_gain = ZMQ_MAX_GAIN_DB; @@ -220,6 +223,9 @@ int rf_zmq_open_multi(char* args, void** h, uint32_t nof_channels) if (pthread_mutex_init(&handler->decim_mutex, NULL)) { perror("Mutex init"); } + if (pthread_mutex_init(&handler->rx_gain_mutex, NULL)) { + perror("Mutex init"); + } // parse args if (args && strlen(args)) { @@ -408,6 +414,7 @@ int rf_zmq_close(void* h) pthread_mutex_destroy(&handler->tx_config_mutex); pthread_mutex_destroy(&handler->rx_config_mutex); pthread_mutex_destroy(&handler->decim_mutex); + pthread_mutex_destroy(&handler->rx_gain_mutex); // Free all free(handler); @@ -463,7 +470,9 @@ int rf_zmq_set_rx_gain(void* h, double gain) { if (h) { rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h; + pthread_mutex_lock(&handler->rx_gain_mutex); handler->rx_gain = gain; + pthread_mutex_unlock(&handler->rx_gain_mutex); } return SRSRAN_SUCCESS; } @@ -488,7 +497,9 @@ double rf_zmq_get_rx_gain(void* h) double ret = 0.0; if (h) { rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h; + pthread_mutex_lock(&handler->rx_gain_mutex); ret = handler->rx_gain; + pthread_mutex_unlock(&handler->rx_gain_mutex); } return ret; } @@ -663,7 +674,7 @@ int rf_zmq_recv_with_time_multi(void* h, void** data, uint32_t nsamples, bool bl // receive samples srsran_timestamp_t ts_tx = {}, ts_rx = {}; - srsran_timestamp_init_uint64(&ts_tx, handler->transmitter[0].nsamples, handler->base_srate); + srsran_timestamp_init_uint64(&ts_tx, rf_zmq_tx_get_nsamples(&handler->transmitter[0]), handler->base_srate); srsran_timestamp_init_uint64(&ts_rx, handler->next_rx_ts, handler->base_srate); rf_zmq_info(handler->id, " - next rx time: %d + %.3f\n", ts_rx.full_secs, ts_rx.frac_secs); rf_zmq_info(handler->id, " - next tx time: %d + %.3f\n", ts_tx.full_secs, ts_tx.frac_secs); @@ -766,7 +777,9 @@ int rf_zmq_recv_with_time_multi(void* h, void** data, uint32_t nsamples, bool bl } // Set gain + pthread_mutex_lock(&handler->rx_gain_mutex); float scale = srsran_convert_dB_to_amplitude(handler->rx_gain); + pthread_mutex_unlock(&handler->rx_gain_mutex); for (uint32_t c = 0; c < handler->nof_channels; c++) { if (buffers[c]) { srsran_vec_sc_prod_cfc(buffers[c], scale, buffers[c], nsamples); diff --git a/lib/src/phy/rf/rf_zmq_imp_trx.h b/lib/src/phy/rf/rf_zmq_imp_trx.h index 1da44cac0..c574581a9 100644 --- a/lib/src/phy/rf/rf_zmq_imp_trx.h +++ b/lib/src/phy/rf/rf_zmq_imp_trx.h @@ -97,6 +97,8 @@ SRSRAN_API int rf_zmq_tx_align(rf_zmq_tx_t* q, uint64_t ts); SRSRAN_API int rf_zmq_tx_baseband(rf_zmq_tx_t* q, cf_t* buffer, uint32_t nsamples); +SRSRAN_API int rf_zmq_tx_get_nsamples(rf_zmq_tx_t* q); + SRSRAN_API int rf_zmq_tx_zeros(rf_zmq_tx_t* q, uint32_t nsamples); SRSRAN_API bool rf_zmq_tx_match_freq(rf_zmq_tx_t* q, uint32_t freq_hz); diff --git a/lib/src/phy/rf/rf_zmq_imp_tx.c b/lib/src/phy/rf/rf_zmq_imp_tx.c index 078a5b92f..3a53f1f49 100644 --- a/lib/src/phy/rf/rf_zmq_imp_tx.c +++ b/lib/src/phy/rf/rf_zmq_imp_tx.c @@ -200,6 +200,14 @@ int rf_zmq_tx_baseband(rf_zmq_tx_t* q, cf_t* buffer, uint32_t nsamples) return n; } +int rf_zmq_tx_get_nsamples(rf_zmq_tx_t* q) +{ + pthread_mutex_lock(&q->mutex); + int ret = q->nsamples; + pthread_mutex_unlock(&q->mutex); + return ret; +} + int rf_zmq_tx_zeros(rf_zmq_tx_t* q, uint32_t nsamples) { pthread_mutex_lock(&q->mutex); diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 6a94d7379..ba9c58477 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -21,6 +21,7 @@ #include "srsran/common/config_file.h" #include "srsran/common/crash_handler.h" #include "srsran/common/signal_handler.h" +#include "srsran/common/tsan_options.h" #include "srsran/srslog/event_trace.h" #include "srsran/srslog/srslog.h" diff --git a/srsue/hdr/metrics_json.h b/srsue/hdr/metrics_json.h index fcd863b6a..e35124223 100644 --- a/srsue/hdr/metrics_json.h +++ b/srsue/hdr/metrics_json.h @@ -35,6 +35,8 @@ public: private: srslog::log_channel& log_c; ue_metrics_interface* ue = nullptr; + + std::mutex mutex = {}; }; } // namespace srsue diff --git a/srsue/hdr/metrics_stdout.h b/srsue/hdr/metrics_stdout.h index 626a5f74a..c571dd7e6 100644 --- a/srsue/hdr/metrics_stdout.h +++ b/srsue/hdr/metrics_stdout.h @@ -54,6 +54,7 @@ private: bool table_has_neighbours = false; ///< state of last table head uint8_t n_reports = 10; ue_metrics_interface* ue = nullptr; + std::mutex mutex; }; } // namespace srsue diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 7c887c585..96a98611d 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -184,7 +184,7 @@ private: std::mutex config_mutex; std::condition_variable config_cond; - bool is_configured = false; + std::atomic is_configured = {false}; const static int SF_RECV_THREAD_PRIO = 0; const static int WORKERS_THREAD_PRIO = 2; diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index e850caac2..6a61f601b 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -138,8 +138,48 @@ public: void set_cell(const srsran_cell_t& c); - bool sr_enabled = false; - int sr_last_tx_tti = -1; + class sr_signal + { + public: + void reset() + { + std::lock_guard lock(mutex); + enabled = false; + last_tx_tti = -1; + } + bool is_triggered() + { + std::lock_guard lock(mutex); + return enabled; + } + void trigger() + { + std::lock_guard lock(mutex); + enabled = true; + last_tx_tti = -1; + } + int get_last_tx_tti() + { + std::lock_guard lock(mutex); + return last_tx_tti; + } + bool set_last_tx_tti(int last_tx_tti_) + { + std::lock_guard lock(mutex); + if (enabled) { + enabled = false; + last_tx_tti = last_tx_tti_; + return true; + } + return false; + } + + private: + std::mutex mutex; + bool enabled = false; + int last_tx_tti = -1; + }; + sr_signal sr; srsran::radio_interface_phy* get_radio(); @@ -212,7 +252,11 @@ public: return rx_gain_offset; } - void neighbour_cells_reset(uint32_t cc_idx) { avg_rsrp_neigh[cc_idx] = NAN; } + void neighbour_cells_reset(uint32_t cc_idx) + { + std::unique_lock lock(meas_mutex); + avg_rsrp_neigh[cc_idx] = NAN; + } void set_neighbour_cells(uint32_t cc_idx, const std::vector& meas) { diff --git a/srsue/hdr/phy/scell/intra_measure_base.h b/srsue/hdr/phy/scell/intra_measure_base.h index e4836d71b..b5b46fc9f 100644 --- a/srsue/hdr/phy/scell/intra_measure_base.h +++ b/srsue/hdr/phy/scell/intra_measure_base.h @@ -126,7 +126,6 @@ public: protected: struct measure_context_t { uint32_t cc_idx = 0; ///< Component carrier index - float rx_gain_offset_db = 0.0f; ///< Current gain offset std::set active_pci = {}; ///< Set with the active PCIs uint32_t sf_len = 0; ///< Subframe length in samples uint32_t meas_len_ms = 20; ///< Measure length in milliseconds/sub-frames @@ -138,6 +137,8 @@ protected: explicit measure_context_t(meas_itf& new_cell_itf_) : new_cell_itf(new_cell_itf_) {} }; + std::atomic rx_gain_offset_db = {0.0f}; ///< Current gain offset + /** * @brief Generic initialization method, necessary to configure main parameters * @param cc_idx_ Indicates the component carrier index linked to the intra frequency measurement instance @@ -261,9 +262,10 @@ private: * as it is protected by the state. * @param context Provides current measurement context * @param buffer Provides current measurement context + * @param rx_gain_offset Provides last received rx_gain_offset * @return True if the measurement functions are executed without errors, otherwise false */ - virtual bool measure_rat(measure_context_t context, std::vector& buffer) = 0; + virtual bool measure_rat(measure_context_t context, std::vector& buffer, float rx_gain_offset) = 0; /** * @brief Measurement process helper method. Encapsulates the neighbour cell measurement functionality diff --git a/srsue/hdr/phy/scell/intra_measure_lte.h b/srsue/hdr/phy/scell/intra_measure_lte.h index fab9df810..7a1b7a931 100644 --- a/srsue/hdr/phy/scell/intra_measure_lte.h +++ b/srsue/hdr/phy/scell/intra_measure_lte.h @@ -67,9 +67,10 @@ private: * @brief LTE specific measurement process * @param context Measurement context * @param buffer Provides the baseband buffer to perform the measurements + * @param rx_gain_offset Provides last received rx_gain_offset * @return True if no error happens, otherwise false */ - bool measure_rat(measure_context_t context, std::vector& buffer) override; + bool measure_rat(measure_context_t context, std::vector& buffer, float rx_gain_offset) override; srslog::basic_logger& logger; srsran_cell_t serving_cell = {}; ///< Current serving cell in the EARFCN, to avoid reporting it diff --git a/srsue/hdr/phy/scell/intra_measure_nr.h b/srsue/hdr/phy/scell/intra_measure_nr.h index 6477af0cd..391483248 100644 --- a/srsue/hdr/phy/scell/intra_measure_nr.h +++ b/srsue/hdr/phy/scell/intra_measure_nr.h @@ -106,9 +106,10 @@ private: * @attention It searches and measures the SSB with best SNR * @param context Measurement context * @param buffer Provides the baseband buffer to perform the measurements + * @param rx_gain_offset Provides last received rx_gain_offset * @return True if no error happen, otherwise false */ - bool measure_rat(measure_context_t context, std::vector& buffer) override; + bool measure_rat(measure_context_t context, std::vector& buffer, float rx_gain_offset) override; srslog::basic_logger& logger; uint32_t cc_idx = 0; diff --git a/srsue/hdr/phy/sync.h b/srsue/hdr/phy/sync.h index 9d8fe476b..97b3c91d7 100644 --- a/srsue/hdr/phy/sync.h +++ b/srsue/hdr/phy/sync.h @@ -206,6 +206,7 @@ private: search search_p; sfn_sync sfn_p; std::vector > intra_freq_meas; + std::mutex intra_freq_cfg_mutex; // Pointers to other classes stack_interface_phy_lte* stack = nullptr; @@ -259,11 +260,97 @@ private: search::ret_code cell_search_ret = search::CELL_NOT_FOUND; // Sampling rate mode (find is 1.96 MHz, camp is the full cell BW) - enum { SRATE_NONE = 0, SRATE_FIND, SRATE_CAMP } srate_mode = SRATE_NONE; - float current_srate = 0; + class srate_safe + { + public: + void reset() + { + std::lock_guard lock(mutex); + srate_mode = SRATE_NONE; + current_srate = 0; + } + float get_srate() + { + std::lock_guard lock(mutex); + return current_srate; + } + bool is_normal() + { + std::lock_guard lock(mutex); + return std::isnormal(current_srate) and current_srate > 0.0f; + } + bool set_camp(float new_srate) + { + std::lock_guard lock(mutex); + if (current_srate != new_srate || srate_mode != SRATE_CAMP) { + current_srate = new_srate; + srate_mode = SRATE_CAMP; + return true; + } + return false; + } + bool set_find() + { + std::lock_guard lock(mutex); + if (srate_mode != SRATE_FIND) { + srate_mode = SRATE_FIND; + current_srate = 1.92e6; + return true; + } + return false; + } + + private: + enum { SRATE_NONE = 0, SRATE_FIND, SRATE_CAMP } srate_mode = SRATE_NONE; + float current_srate = 0; + std::mutex mutex; + }; + // Protect sampling rate changes since accessed by multiple threads + srate_safe srate; // This is the primary cell - srsran_cell_t cell = {}; + class cell_safe + { + public: + void set_pci(uint32_t id) + { + std::lock_guard lock(mutex); + cell.id = id; + } + void reset() + { + std::lock_guard lock(mutex); + cell = {}; + } + bool is_valid() + { + std::lock_guard lock(mutex); + return srsran_cell_isvalid(&cell); + } + void set(srsran_cell_t& x) + { + std::lock_guard lock(mutex); + cell = x; + } + srsran_cell_t get() + { + std::lock_guard lock(mutex); + return cell; + } + bool equals(srsran_cell_t& x) + { + std::lock_guard lock(mutex); + return memcmp(&cell, &x, sizeof(srsran_cell_t)) == 0; + } + + private: + srsran_cell_t cell = {}; + std::mutex mutex; + }; + + // Protect access to cell configuration since it's accessed by multiple threads + cell_safe cell; + bool force_camping_sfn_sync = false; uint32_t tti = 0; srsran_timestamp_t stack_tti_ts_new = {}; diff --git a/srsue/hdr/phy/sync_state.h b/srsue/hdr/phy/sync_state.h index aa3338bf1..a014cc38f 100644 --- a/srsue/hdr/phy/sync_state.h +++ b/srsue/hdr/phy/sync_state.h @@ -82,8 +82,16 @@ public: } /* Helpers below this */ - bool is_idle() { return cur_state == IDLE; } - bool is_camping() { return cur_state == CAMPING; } + bool is_idle() + { + std::lock_guard lock(mutex); + return cur_state == IDLE; + } + bool is_camping() + { + std::lock_guard lock(mutex); + return cur_state == CAMPING; + } bool wait_idle(uint32_t timeout_ms) { std::unique_lock lock(mutex); diff --git a/srsue/hdr/stack/mac/dl_harq.h b/srsue/hdr/stack/mac/dl_harq.h index 035311fc1..0ca4cc60c 100644 --- a/srsue/hdr/stack/mac/dl_harq.h +++ b/srsue/hdr/stack/mac/dl_harq.h @@ -17,6 +17,7 @@ #include "dl_sps.h" #include "srsran/common/mac_pcap.h" #include "srsran/common/timers.h" +#include "srsue/hdr/stack/mac_common/mac_common.h" /* Downlink HARQ entity as defined in 5.3.2 of 36.321 */ @@ -27,7 +28,7 @@ class dl_harq_entity public: dl_harq_entity(uint8_t cc_idx_); - bool init(mac_interface_rrc::ue_rnti_t* rntis, demux* demux_unit); + bool init(ue_rnti* rntis, demux* demux_unit); void reset(); void start_pcap(srsran::mac_pcap* pcap_); @@ -38,6 +39,7 @@ public: void set_si_window_start(int si_window_start); float get_average_retx(); + void set_average_retx(uint32_t n_retx); private: class dl_harq_process @@ -112,10 +114,12 @@ private: demux* demux_unit = nullptr; srslog::basic_logger& logger; srsran::mac_pcap* pcap = nullptr; - mac_interface_rrc::ue_rnti_t* rntis = nullptr; + ue_rnti* rntis = nullptr; uint16_t last_temporal_crnti = 0; int si_window_start = 0; + std::mutex retx_cnt_mutex = {}; + float average_retx = 0.0; uint64_t nof_pkts = 0; uint8_t cc_idx = 0; diff --git a/srsue/hdr/stack/mac/mac.h b/srsue/hdr/stack/mac/mac.h index 66bd0c0ca..c71c131c7 100644 --- a/srsue/hdr/stack/mac/mac.h +++ b/srsue/hdr/stack/mac/mac.h @@ -84,8 +84,8 @@ public: void set_rach_ded_cfg(uint32_t preamble_index, uint32_t prach_mask); - void get_rntis(ue_rnti_t* rntis); - void set_ho_rnti(uint16_t crnti, uint16_t target_pci); + uint16_t get_crnti(); + void set_ho_rnti(uint16_t crnti, uint16_t target_pci); /*********** interface for stack ******************/ void process_pdus(); @@ -100,8 +100,6 @@ public: private: void clear_rntis(); - bool is_in_window(uint32_t tti, int* start, int* len); - // Interaction with PHY phy_interface_mac_lte* phy_h = nullptr; rlc_interface_mac* rlc_h = nullptr; @@ -110,13 +108,11 @@ private: srslog::basic_logger& logger; mac_interface_phy_lte::mac_phy_cfg_mbsfn_t phy_mbsfn_cfg = {}; - // RNTI search window scheduling - int si_window_length = -1, si_window_start = -1; - int ra_window_length = -1, ra_window_start = -1; - int p_window_start = -1; + // Control scheduling for SI/RA/P RNTIs + rnti_window_safe si_window, ra_window, p_window; // UE-specific RNTIs - ue_rnti_t uernti; + ue_rnti uernti; /* Multiplexing/Demultiplexing Units */ mux mux_unit; @@ -156,6 +152,7 @@ private: srsran::mac_pcap* pcap = nullptr; bool is_first_ul_grant = false; + std::mutex metrics_mutex = {}; mac_metrics_t metrics[SRSRAN_MAX_CARRIERS] = {}; std::atomic initialized = {false}; diff --git a/srsue/hdr/stack/mac/mux.h b/srsue/hdr/stack/mac/mux.h index dc7082f7a..46f8a322c 100644 --- a/srsue/hdr/stack/mac/mux.h +++ b/srsue/hdr/stack/mac/mux.h @@ -57,6 +57,7 @@ public: void print_logical_channel_state(const std::string& info); private: + uint8_t* pdu_get_unsafe(srsran::byte_buffer_t* payload, uint32_t pdu_sz); bool pdu_move_to_msg3(uint32_t pdu_sz); uint32_t allocate_sdu(uint32_t lcid, srsran::sch_pdu* pdu, int max_sdu_sz); bool sched_sdu(srsran::logical_channel_config_t* ch, int* sdu_space, int max_sdu_sz); diff --git a/srsue/hdr/stack/mac/proc_ra.h b/srsue/hdr/stack/mac/proc_ra.h index fdfc38fcb..5d62b55bc 100644 --- a/srsue/hdr/stack/mac/proc_ra.h +++ b/srsue/hdr/stack/mac/proc_ra.h @@ -22,6 +22,7 @@ #include "srsran/common/mac_pcap.h" #include "srsran/common/timers.h" #include "srsran/mac/pdu.h" +#include "srsue/hdr/stack/mac_common/mac_common.h" /* Random access procedure as specified in Section 5.1 of 36.321 */ @@ -36,7 +37,7 @@ public: void init(phy_interface_mac_lte* phy_h, rrc_interface_mac* rrc_, - mac_interface_rrc::ue_rnti_t* rntis, + ue_rnti* rntis, srsran::timer_handler::unique_timer* time_alignment_timer_, mux* mux_unit, srsran::ext_task_sched_handle* task_sched_); @@ -50,7 +51,7 @@ public: void start_mac_order(uint32_t msg_len_bits = 56); void step(uint32_t tti); - void update_rar_window(int& rar_window_start, int& rar_window_length); + void update_rar_window(rnti_window_safe& ra_window); bool is_contention_resolution(); void harq_retx(); void harq_max_retx(); @@ -140,7 +141,7 @@ private: srsran::timer_handler::unique_timer* time_alignment_timer = nullptr; srsran::timer_handler::unique_timer contention_resolution_timer; - mac_interface_rrc::ue_rnti_t* rntis = nullptr; + ue_rnti* rntis = nullptr; std::atomic transmitted_contention_id = {0}; std::atomic transmitted_crnti = {0}; diff --git a/srsue/hdr/stack/mac/proc_sr.h b/srsue/hdr/stack/mac/proc_sr.h index 1896cdc2e..1bd517cf6 100644 --- a/srsue/hdr/stack/mac/proc_sr.h +++ b/srsue/hdr/stack/mac/proc_sr.h @@ -15,6 +15,7 @@ #include "srsran/interfaces/ue_mac_interfaces.h" #include "srsran/srslog/srslog.h" +#include #include /* Scheduling Request procedure as defined in 5.4.4 of 36.321 */ @@ -48,6 +49,9 @@ private: phy_interface_mac_lte* phy_h; srslog::basic_logger& logger; + // Protects access to is_pending_sr, which can be accessed by PHY worker + std::mutex mutex = {}; + bool initiated; }; diff --git a/srsue/hdr/stack/mac/ul_harq.h b/srsue/hdr/stack/mac/ul_harq.h index 812fd9084..7507a69d8 100644 --- a/srsue/hdr/stack/mac/ul_harq.h +++ b/srsue/hdr/stack/mac/ul_harq.h @@ -29,7 +29,7 @@ class ul_harq_entity public: ul_harq_entity(const uint8_t cc_idx_); - bool init(mac_interface_rrc_common::ue_rnti_t* rntis_, ra_proc* ra_proc_h_, mux* mux_unit_); + bool init(ue_rnti* rntis_, ra_proc* ra_proc_h_, mux* mux_unit_); void reset(); void reset_ndi(); @@ -96,8 +96,9 @@ private: srsran::mac_pcap* pcap = nullptr; srslog::basic_logger& logger; - mac_interface_rrc_common::ue_rnti_t* rntis = nullptr; - srsran::ul_harq_cfg_t harq_cfg = {}; + ue_rnti* rntis = nullptr; + + srsran::ul_harq_cfg_t harq_cfg = {}; float average_retx = 0.0; uint64_t nof_pkts = 0; diff --git a/srsue/hdr/stack/mac_common/mac_common.h b/srsue/hdr/stack/mac_common/mac_common.h index 17aaf411b..7cb3eccbf 100644 --- a/srsue/hdr/stack/mac_common/mac_common.h +++ b/srsue/hdr/stack/mac_common/mac_common.h @@ -14,8 +14,10 @@ #define SRSUE_MAC_COMMON_H #include "srsran/common/string_helpers.h" +#include "srsran/phy/common/phy_common.h" #include "srsran/srslog/srslog.h" #include +#include /** * @brief Common definitions/interfaces between LTE/NR MAC components @@ -25,6 +27,161 @@ */ namespace srsue { +// Helper class to protect access to RNTIs +class ue_rnti +{ +public: + void reset() + { + std::lock_guard lock(mutex); + crnti = 0; + rar_rnti = 0; + temp_rnti = 0; + tpc_rnti = 0; + sps_rnti = 0; + contention_id = 0; + } + uint16_t get_crnti() + { + std::lock_guard lock(mutex); + return crnti; + } + uint16_t get_rar_rnti() + { + std::lock_guard lock(mutex); + return rar_rnti; + } + uint16_t get_temp_rnti() + { + std::lock_guard lock(mutex); + return temp_rnti; + } + uint16_t get_sps_rnti() + { + std::lock_guard lock(mutex); + return sps_rnti; + } + uint64_t get_contention_id() + { + std::lock_guard lock(mutex); + return contention_id; + } + void set_crnti(uint16_t rnti) + { + std::lock_guard lock(mutex); + crnti = rnti; + } + void set_rar_rnti(uint16_t rnti) + { + std::lock_guard lock(mutex); + rar_rnti = rnti; + } + void set_temp_rnti(uint16_t rnti) + { + std::lock_guard lock(mutex); + temp_rnti = rnti; + } + void set_contention_id(uint64_t id) + { + std::lock_guard lock(mutex); + contention_id = id; + } + void set_crnti_to_temp() + { + std::lock_guard lock(mutex); + crnti = temp_rnti; + } + void clear_temp_rnti() + { + std::lock_guard lock(mutex); + temp_rnti = SRSRAN_INVALID_RNTI; + } + void clear_rar_rnti() + { + std::lock_guard lock(mutex); + rar_rnti = SRSRAN_INVALID_RNTI; + } + void clear_crnti() + { + std::lock_guard lock(mutex); + crnti = SRSRAN_INVALID_RNTI; + } + +private: + std::mutex mutex; + uint16_t crnti = 0; + uint16_t rar_rnti = 0; + uint16_t temp_rnti = 0; + uint16_t tpc_rnti = 0; + uint16_t sps_rnti = 0; + uint64_t contention_id = 0; +}; + +// Helper class to control RNTI search windows in a protected manner +class rnti_window_safe +{ +public: + void reset() + { + std::lock_guard lock(mutex); + length = -1; + start = -1; + } + void set(int length_, int start_) + { + std::lock_guard lock(mutex); + length = length_; + start = start_; + } + int get_length() + { + std::lock_guard lock(mutex); + return length; + } + int get_start() + { + std::lock_guard lock(mutex); + return start; + } + bool is_set() + { + std::lock_guard lock(mutex); + return start > 0; + } + bool is_in_window(int tti) + { + std::lock_guard lock(mutex); + if (start == 0 || length == 0) { + return false; + } + if ((int)srsran_tti_interval(tti, start) < length + 5) { + if (tti > start) { + if (tti <= start + length) { + return true; + } else { + start = 0; + length = 0; + return false; + } + } else { + if (tti <= (start + length) % 10240) { + return true; + } else { + start = 0; + length = 0; + return false; + } + } + } + return false; + } + +private: + int length = -1; + int start = -1; + std::mutex mutex; +}; + // BSR trigger are common between LTE and NR typedef enum { NONE, REGULAR, PADDING, PERIODIC } bsr_trigger_type_t; char* bsr_trigger_type_tostring(bsr_trigger_type_t type); diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 4d61b1c8e..f7c700bc2 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -15,6 +15,7 @@ #include "srsran/common/crash_handler.h" #include "srsran/common/metrics_hub.h" #include "srsran/common/signal_handler.h" +#include "srsran/common/tsan_options.h" #include "srsran/srslog/event_trace.h" #include "srsran/srslog/srslog.h" #include "srsran/srsran.h" diff --git a/srsue/src/metrics_csv.cc b/srsue/src/metrics_csv.cc index 50f5643c0..bd8490f83 100644 --- a/srsue/src/metrics_csv.cc +++ b/srsue/src/metrics_csv.cc @@ -47,11 +47,13 @@ metrics_csv::~metrics_csv() void metrics_csv::set_ue_handle(ue_metrics_interface* ue_) { + std::lock_guard lock(mutex); ue = ue_; } void metrics_csv::set_flush_period(const uint32_t flush_period_sec_) { + std::lock_guard lock(mutex); flush_period_sec = flush_period_sec_; } diff --git a/srsue/src/metrics_json.cc b/srsue/src/metrics_json.cc index a012a8a74..e51ba7a38 100644 --- a/srsue/src/metrics_json.cc +++ b/srsue/src/metrics_json.cc @@ -17,6 +17,7 @@ using namespace srsue; void metrics_json::set_ue_handle(ue_metrics_interface* ue_) { + std::lock_guard lock(mutex); ue = ue_; } @@ -138,6 +139,7 @@ static double get_time_stamp() void metrics_json::set_metrics(const ue_metrics_t& metrics, const uint32_t period_usec) { + std::lock_guard lock(mutex); if (!ue) { return; } diff --git a/srsue/src/metrics_stdout.cc b/srsue/src/metrics_stdout.cc index 6818a019e..74efc9cd7 100644 --- a/srsue/src/metrics_stdout.cc +++ b/srsue/src/metrics_stdout.cc @@ -53,11 +53,13 @@ char const* const prefixes[2][9] = { void metrics_stdout::set_ue_handle(ue_metrics_interface* ue_) { + std::lock_guard lock(mutex); ue = ue_; } void metrics_stdout::toggle_print(bool b) { + std::lock_guard lock(mutex); do_print = b; } @@ -161,6 +163,7 @@ void metrics_stdout::set_metrics_helper(const phy_metrics_t& phy, void metrics_stdout::set_metrics(const ue_metrics_t& metrics, const uint32_t period_usec) { + std::lock_guard lock(mutex); if (ue == nullptr) { return; } diff --git a/srsue/src/phy/lte/cc_worker.cc b/srsue/src/phy/lte/cc_worker.cc index ddafb7efe..9fa2e921e 100644 --- a/srsue/src/phy/lte/cc_worker.cc +++ b/srsue/src/phy/lte/cc_worker.cc @@ -784,12 +784,10 @@ bool cc_worker::encode_uplink(mac_interface_phy_lte::tb_action_ul_t* action, srs void cc_worker::set_uci_sr(srsran_uci_data_t* uci_data) { - Debug("set_uci_sr() query: sr_enabled=%d, last_tx_tti=%d", phy->sr_enabled, phy->sr_last_tx_tti); - if (srsran_ue_ul_gen_sr(&ue_ul_cfg, &sf_cfg_ul, uci_data, phy->sr_enabled)) { - if (phy->sr_enabled) { - phy->sr_last_tx_tti = CURRENT_TTI_TX; - phy->sr_enabled = false; - Debug("set_uci_sr() sending SR: sr_enabled=%d, last_tx_tti=%d", phy->sr_enabled, phy->sr_last_tx_tti); + Debug("set_uci_sr() query: sr_enabled=%d, last_tx_tti=%d", phy->sr.is_triggered(), phy->sr.get_last_tx_tti()); + if (srsran_ue_ul_gen_sr(&ue_ul_cfg, &sf_cfg_ul, uci_data, phy->sr.is_triggered())) { + if (phy->sr.set_last_tx_tti(CURRENT_TTI_TX)) { + Debug("set_uci_sr() sending SR: sr_enabled=true, last_tx_tti=%d", CURRENT_TTI_TX); } } } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index e9d84e7c6..da093bd7c 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -240,8 +240,6 @@ void phy::configure_prach_params() { Debug("Configuring PRACH parameters"); - prach_cfg.tdd_config = tdd_config; - if (!prach_buffer.set_cell(selected_cell, prach_cfg)) { Error("Configuring PRACH parameters"); } @@ -294,7 +292,9 @@ void phy::set_cells_to_meas(uint32_t earfcn, const std::set& pci) void phy::meas_stop() { - sfsync.meas_stop(); + if (is_configured) { + sfsync.meas_stop(); + } } // This function executes one part of the procedure immediatly and returns to continue in the background. @@ -415,14 +415,13 @@ uint32_t phy::get_current_tti() void phy::sr_send() { - common.sr_enabled = true; - common.sr_last_tx_tti = -1; - Debug("sr_send(): sr_enabled=%d, last_tx_tti=%d", common.sr_enabled, common.sr_last_tx_tti); + common.sr.trigger(); + Debug("SR is triggered"); } int phy::sr_last_tx_tti() { - return common.sr_last_tx_tti; + return common.sr.get_last_tx_tti(); } void phy::set_rar_grant(uint8_t grant_payload[SRSRAN_RAR_GRANT_LEN], uint16_t rnti) @@ -460,6 +459,7 @@ bool phy::set_config(const srsran::phy_cfg_t& config_, uint32_t cc_idx) // - The PRACH configuration is present if (!cc_idx && config_.prach_cfg_present) { prach_cfg = config_.prach_cfg; + prach_cfg.tdd_config = tdd_config; } // Apply configurations asynchronously to avoid race conditions diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index 4803d5fce..91a0e4e45 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -49,7 +49,7 @@ void phy_common::init(phy_args_t* _args, stack = _stack; args = _args; insync_itf = _chest_loop; - sr_last_tx_tti = -1; + sr.reset(); // Instantiate UL channel emulator if (args->ul_channel_args.enable) { @@ -873,10 +873,9 @@ void phy_common::reset() { reset_radio(); - sr_enabled = false; + sr.reset(); cur_pathloss = 0; cur_pusch_power = 0; - sr_last_tx_tti = -1; last_ri = 0; // Reset all measurements diff --git a/srsue/src/phy/prach.cc b/srsue/src/phy/prach.cc index 86021bd95..9f679e5b5 100644 --- a/srsue/src/phy/prach.cc +++ b/srsue/src/phy/prach.cc @@ -32,6 +32,7 @@ using namespace srsue; void prach::init(uint32_t max_prb) { + std::lock_guard lock(mutex); for (auto& i : buffer) { for (auto& j : i) { j = srsran_vec_cf_malloc(SRSRAN_PRACH_MAX_LEN); @@ -65,6 +66,7 @@ void prach::init(uint32_t max_prb) void prach::stop() { + std::lock_guard lock(mutex); if (!mem_initiated) { return; } @@ -176,6 +178,7 @@ bool prach::is_ready_to_send(uint32_t current_tti_, uint32_t current_pci) { // Make sure the curernt PCI is the one we configured the PRACH for if (is_pending() && current_pci == cell.id) { + std::lock_guard lock(mutex); // consider the number of subframes the transmission must be anticipated uint32_t tti_tx = TTI_TX(current_tti_); if (srsran_prach_tti_opportunity(&prach_obj, tti_tx, allowed_subframe)) { @@ -189,6 +192,7 @@ bool prach::is_ready_to_send(uint32_t current_tti_, uint32_t current_pci) phy_interface_mac_lte::prach_info_t prach::get_info() const { + std::lock_guard lock(mutex); phy_interface_mac_lte::prach_info_t info = {}; info.preamble_format = prach_obj.config_idx / 16; @@ -207,6 +211,7 @@ phy_interface_mac_lte::prach_info_t prach::get_info() const cf_t* prach::generate(float cfo, uint32_t* nof_sf, float* target_power) { + std::lock_guard lock(mutex); if (!cell_initiated || preamble_idx < 0 || !nof_sf || unsigned(preamble_idx) >= max_preambles || !srsran_cell_isvalid(&cell) || len >= MAX_LEN_SF * 30720 || len == 0) { Error("PRACH: Invalid parameters: cell_initiated=%d, preamble_idx=%d, cell.nof_prb=%d, len=%d", diff --git a/srsue/src/phy/scell/intra_measure_base.cc b/srsue/src/phy/scell/intra_measure_base.cc index 986f850f2..11da6584d 100644 --- a/srsue/src/phy/scell/intra_measure_base.cc +++ b/srsue/src/phy/scell/intra_measure_base.cc @@ -36,7 +36,7 @@ void intra_measure_base::init_generic(uint32_t cc_idx_, const args_t& args) context.meas_period_ms = args.period_ms; context.trigger_tti_period = args.tti_period; context.trigger_tti_offset = args.tti_offset; - context.rx_gain_offset_db = args.rx_gain_offset_db; + rx_gain_offset_db = args.rx_gain_offset_db; // Compute subframe length from the sampling rate if available if (std::isnormal(args.srate_hz)) { @@ -86,7 +86,7 @@ void intra_measure_base::stop() void intra_measure_base::set_rx_gain_offset(float rx_gain_offset_db_) { - context.rx_gain_offset_db = rx_gain_offset_db_; + rx_gain_offset_db = rx_gain_offset_db_; } void intra_measure_base::meas_stop() @@ -179,7 +179,7 @@ void intra_measure_base::measure_proc() } // Perform measurements for the actual RAT - if (not measure_rat(context, search_buffer)) { + if (not measure_rat(context, search_buffer, rx_gain_offset_db)) { Log(error, "Error measuring RAT"); } } diff --git a/srsue/src/phy/scell/intra_measure_lte.cc b/srsue/src/phy/scell/intra_measure_lte.cc index a68af2991..7719a42c1 100644 --- a/srsue/src/phy/scell/intra_measure_lte.cc +++ b/srsue/src/phy/scell/intra_measure_lte.cc @@ -47,7 +47,7 @@ void intra_measure_lte::set_primary_cell(uint32_t earfcn, srsran_cell_t cell) set_current_sf_len((uint32_t)SRSRAN_SF_LEN_PRB(cell.nof_prb)); } -bool intra_measure_lte::measure_rat(measure_context_t context, std::vector& buffer) +bool intra_measure_lte::measure_rat(measure_context_t context, std::vector& buffer, float rx_gain_offset) { std::set cells_to_measure = context.active_pci; @@ -84,7 +84,7 @@ bool intra_measure_lte::measure_rat(measure_context_t context, std::vector m.rat = srsran::srsran_rat_t::lte; m.pci = cell.id; m.earfcn = current_earfcn; - m.rsrp = refsignal_dl_sync.rsrp_dBfs - context.rx_gain_offset_db; + m.rsrp = refsignal_dl_sync.rsrp_dBfs - rx_gain_offset_db; m.rsrq = refsignal_dl_sync.rsrq_dB; m.cfo_hz = refsignal_dl_sync.cfo_Hz; neighbour_cells.push_back(m); diff --git a/srsue/src/phy/scell/intra_measure_nr.cc b/srsue/src/phy/scell/intra_measure_nr.cc index 6fd63a43d..bef371190 100644 --- a/srsue/src/phy/scell/intra_measure_nr.cc +++ b/srsue/src/phy/scell/intra_measure_nr.cc @@ -81,7 +81,7 @@ bool intra_measure_nr::set_config(const config_t& cfg) return true; } -bool intra_measure_nr::measure_rat(const measure_context_t context, std::vector& buffer) +bool intra_measure_nr::measure_rat(const measure_context_t context, std::vector& buffer, float rx_gain_offset) { std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); @@ -117,7 +117,7 @@ bool intra_measure_nr::measure_rat(const measure_context_t context, std::vector< // Prepare found measurements std::vector meas_list(1); meas_list[0].rat = get_rat(); - meas_list[0].rsrp = meas.rsrp_dB + context.rx_gain_offset_db; + meas_list[0].rsrp = meas.rsrp_dB + rx_gain_offset_db; meas_list[0].cfo_hz = meas.cfo_hz; meas_list[0].earfcn = get_earfcn(); meas_list[0].pci = N_id; diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 040320e45..046f653f0 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -88,14 +88,17 @@ void sync::init(srsran::radio_interface_phy* _radio, sfn_p.init(&ue_sync, worker_com->args, sf_buffer, sf_buffer.size()); // Start intra-frequency measurement - for (uint32_t i = 0; i < worker_com->args->nof_lte_carriers; i++) { - scell::intra_measure_lte* q = new scell::intra_measure_lte(phy_logger, *this); - scell::intra_measure_base::args_t args = {}; - args.len_ms = worker_com->args->intra_freq_meas_len_ms; - args.period_ms = worker_com->args->intra_freq_meas_period_ms; - args.rx_gain_offset_db = worker_com->args->rx_gain_offset; - q->init(i, args); - intra_freq_meas.push_back(std::unique_ptr(q)); + { + std::lock_guard lock(intra_freq_cfg_mutex); + for (uint32_t i = 0; i < worker_com->args->nof_lte_carriers; i++) { + scell::intra_measure_lte* q = new scell::intra_measure_lte(phy_logger, *this); + scell::intra_measure_base::args_t args = {}; + args.len_ms = worker_com->args->intra_freq_meas_len_ms; + args.period_ms = worker_com->args->intra_freq_meas_period_ms; + args.rx_gain_offset_db = worker_com->args->rx_gain_offset; + q->init(i, args); + intra_freq_meas.push_back(std::unique_ptr(q)); + } } // Allocate Secondary serving cell synchronization @@ -125,6 +128,7 @@ sync::~sync() void sync::stop() { + std::lock_guard lock(intra_freq_cfg_mutex); worker_com->semaphore.wait_all(); for (auto& q : intra_freq_meas) { q->stop(); @@ -142,7 +146,7 @@ void sync::reset() in_sync_cnt = 0; out_of_sync_cnt = 0; current_earfcn = -1; - srate_mode = SRATE_NONE; + srate.reset(); sfn_p.reset(); search_p.reset(); } @@ -219,8 +223,7 @@ rrc_interface_phy_lte::cell_search_ret_t sync::cell_search_start(phy_cell_t* fou rrc_proc_state = PROC_SEARCH_RUNNING; - if (srate_mode != SRATE_FIND) { - srate_mode = SRATE_FIND; + if (srate.set_find()) { radio_h->set_rx_srate(1.92e6); radio_h->set_tx_srate(1.92e6); Info("SYNC: Setting Cell Search sampling rate"); @@ -244,10 +247,10 @@ rrc_interface_phy_lte::cell_search_ret_t sync::cell_search_start(phy_cell_t* fou // Check return state switch (cell_search_ret) { case search::CELL_FOUND: - phy_logger.info("Cell Search: Found cell with PCI=%d with %d PRB", cell.id, cell.nof_prb); + phy_logger.info("Cell Search: Found cell with PCI=%d with %d PRB", cell.get().id, cell.get().nof_prb); if (found_cell) { found_cell->earfcn = current_earfcn; - found_cell->pci = cell.id; + found_cell->pci = cell.get().id; found_cell->cfo_hz = search_p.get_last_cfo(); } ret.found = rrc_interface_phy_lte::cell_search_ret_t::CELL_FOUND; @@ -328,7 +331,7 @@ bool sync::cell_select_start(phy_cell_t new_cell) search_p.reset(); // Reconfigure cell if necessary - cell.id = new_cell.pci; + cell.set_pci(new_cell.pci); if (not set_cell(new_cell.cfo_hz)) { Error("Cell Select: Reconfiguring cell"); goto clean_exit; @@ -346,19 +349,16 @@ bool sync::cell_select_start(phy_cell_t new_cell) } // Reconfigure first intra-frequency measurement - intra_freq_meas[0]->set_primary_cell(current_earfcn, cell); + intra_freq_meas[0]->set_primary_cell(current_earfcn, cell.get()); // Reconfigure secondary serving cell synchronization assuming the same BW than the primary // The secondary serving cell synchronization will not resize again when the SCell gets configured for (auto& e : scell_sync) { - e.second->set_bw(cell.nof_prb); + e.second->set_bw(cell.get().nof_prb); } // Change sampling rate if necessary - if (srate_mode != SRATE_CAMP) { - phy_logger.info("Cell Select: Setting CAMPING sampling rate"); - set_sampling_rate(); - } + set_sampling_rate(); // SFN synchronization phy_state.run_sfn_sync(); @@ -402,8 +402,10 @@ bool sync::wait_idle() void sync::run_cell_search_state() { - cell_search_ret = search_p.run(&cell, mib); + srsran_cell_t tmp_cell = cell.get(); + cell_search_ret = search_p.run(&tmp_cell, mib); if (cell_search_ret == search::CELL_FOUND) { + cell.set(tmp_cell); stack->bch_decoded_ok(SYNC_CC_IDX, mib.data(), mib.size() / 8); } phy_state.state_exit(); @@ -411,12 +413,11 @@ void sync::run_cell_search_state() void sync::run_sfn_sync_state() { - srsran_cell_t temp_cell = cell; - switch (sfn_p.run_subframe(&temp_cell, &tti, mib)) { + srsran_cell_t old_cell = cell.get(); + switch (sfn_p.run_subframe(&old_cell, &tti, mib)) { case sfn_sync::SFN_FOUND: - if (memcmp(&cell, &temp_cell, sizeof(srsran_cell_t)) != 0) { - srsran_cell_fprint(stdout, &cell, 0); - srsran_cell_fprint(stdout, &temp_cell, 0); + if (!cell.equals(old_cell)) { + srsran_cell_fprint(stdout, &old_cell, 0); phy_logger.error("Detected cell during SFN synchronization differs from configured cell. Cell reselection to " "cells with different MIB is not supported"); srsran::console("Detected cell during SFN synchronization differs from configured cell. Cell reselection " @@ -465,7 +466,7 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, // Force decode MIB if required if (force_camping_sfn_sync) { uint32_t _tti = 0; - srsran_cell_t temp_cell = cell; + srsran_cell_t temp_cell = cell.get(); sfn_sync::ret_code ret = sfn_p.decode_mib(&temp_cell, &_tti, &sync_buffer, mib); if (ret == sfn_sync::SFN_FOUND) { @@ -475,7 +476,7 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, // Disable force_camping_sfn_sync = false; - if (memcmp(&cell, &temp_cell, sizeof(srsran_cell_t)) != 0) { + if (!cell.equals(temp_cell)) { phy_logger.error("Detected cell during SFN synchronization differs from configured cell. Cell " "reselection to cells with different MIB is not supported"); srsran::console("Detected cell during SFN synchronization differs from configured cell. Cell " @@ -499,14 +500,15 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, } // Check if we need to TX a PRACH - if (prach_buffer->is_ready_to_send(tti, cell.id)) { + if (prach_buffer->is_ready_to_send(tti, cell.get().id)) { prach_ptr = prach_buffer->generate(get_tx_cfo(), &prach_nof_sf, &prach_power); if (prach_ptr == nullptr) { Error("Generating PRACH"); } } - lte_worker->set_prach(prach_ptr ? &prach_ptr[prach_sf_cnt * SRSRAN_SF_LEN_PRB(cell.nof_prb)] : nullptr, prach_power); + lte_worker->set_prach(prach_ptr ? &prach_ptr[prach_sf_cnt * SRSRAN_SF_LEN_PRB(cell.get().nof_prb)] : nullptr, + prach_power); // Execute Serving Cell state FSM worker_com->cell_state.run_tti(tti); @@ -618,8 +620,8 @@ void sync::run_idle_state() { if (radio_h->is_init()) { uint32_t nsamples = 1920; - if (std::isnormal(current_srate) and current_srate > 0.0f) { - nsamples = current_srate / 1000; + if (srate.is_normal()) { + nsamples = srate.get_srate() / 1000; } Debug("Discarding %d samples", nsamples); srsran_timestamp_t rx_time = {}; @@ -812,18 +814,21 @@ void sync::set_ue_sync_opts(srsran_ue_sync_t* q, float cfo_) bool sync::set_cell(float cfo_in) { - if (!srsran_cell_isvalid(&cell)) { - Error("SYNC: Setting cell: invalid cell (nof_prb=%d, pci=%d, ports=%d)", cell.nof_prb, cell.id, cell.nof_ports); + if (!cell.is_valid()) { + Error("SYNC: Setting cell: invalid cell (nof_prb=%d, pci=%d, ports=%d)", + cell.get().nof_prb, + cell.get().id, + cell.get().nof_ports); return false; } // Set cell in all objects - if (srsran_ue_sync_set_cell(&ue_sync, cell)) { + if (srsran_ue_sync_set_cell(&ue_sync, cell.get())) { Error("SYNC: Setting cell: initiating ue_sync"); return false; } - sfn_p.set_cell(cell); - worker_com->set_cell(cell); + sfn_p.set_cell(cell.get()); + worker_com->set_cell(cell.get()); // Reset cell configuration for (uint32_t i = 0; i < worker_com->args->nof_phy_threads; i++) { @@ -834,7 +839,7 @@ bool sync::set_cell(float cfo_in) for (uint32_t i = 0; i < worker_com->args->nof_phy_threads; i++) { lte::sf_worker* w = lte_worker_pool->wait_worker_id(i); if (w) { - success &= w->set_cell_unlocked(0, cell); + success &= w->set_cell_unlocked(0, cell.get()); w->release(); } } @@ -895,21 +900,18 @@ bool sync::set_frequency() void sync::set_sampling_rate() { - float new_srate = (float)srsran_sampling_freq_hz(cell.nof_prb); + float new_srate = (float)srsran_sampling_freq_hz(cell.get().nof_prb); if (new_srate < 0.0) { - Error("Invalid sampling rate for %d PRBs. keeping same.", cell.nof_prb); + Error("Invalid sampling rate for %d PRBs. keeping same.", cell.get().nof_prb); return; } - if (current_srate != new_srate || srate_mode != SRATE_CAMP) { - current_srate = new_srate; - Info("SYNC: Setting sampling rate %.2f MHz", current_srate / 1000000); - - srate_mode = SRATE_CAMP; - radio_h->set_rx_srate(current_srate); - radio_h->set_tx_srate(current_srate); + if (srate.set_camp(new_srate)) { + Info("SYNC: Setting sampling rate %.2f MHz", new_srate / 1000000); + radio_h->set_rx_srate(new_srate); + radio_h->set_tx_srate(new_srate); } else { - Error("Error setting sampling rate for cell with %d PRBs", cell.nof_prb); + Error("Error setting sampling rate for cell with %d PRBs", cell.get().nof_prb); } } @@ -921,7 +923,7 @@ uint32_t sync::get_current_tti() void sync::get_current_cell(srsran_cell_t* cell_, uint32_t* earfcn_) { if (cell_) { - *cell_ = cell; + *cell_ = cell.get(); } if (earfcn_) { *earfcn_ = current_earfcn; @@ -959,12 +961,13 @@ int sync::radio_recv_fnc(srsran::rf_buffer_t& data, srsran_timestamp_t* rx_time) // Execute channel DL emulator if (channel_emulator and rx_time) { - channel_emulator->set_srate((uint32_t)current_srate); + channel_emulator->set_srate((uint32_t)srate.get_srate()); channel_emulator->run(data.to_cf_t(), data.to_cf_t(), data.get_nof_samples(), *rx_time); } // Save signal for Intra-frequency measurement - if (srsran_cell_isvalid(&cell)) { + if (cell.is_valid()) { + std::lock_guard lock(intra_freq_cfg_mutex); for (uint32_t i = 0; (uint32_t)i < intra_freq_meas.size(); i++) { // Feed the exact number of base-band samples for avoiding an invalid buffer read intra_freq_meas[i]->run_tti(tti, data.get(i, 0, worker_com->args->nof_rx_ant), data.get_nof_samples()); @@ -1031,12 +1034,14 @@ void sync::set_rx_gain(float gain) void sync::set_inter_frequency_measurement(uint32_t cc_idx, uint32_t earfcn_, srsran_cell_t cell_) { + std::lock_guard lock(intra_freq_cfg_mutex); if (cc_idx < intra_freq_meas.size()) { intra_freq_meas[cc_idx]->set_primary_cell(earfcn_, cell_); } } void sync::set_cells_to_meas(uint32_t earfcn_, const std::set& pci) { + std::lock_guard lock(intra_freq_cfg_mutex); bool found = false; for (size_t i = 0; i < intra_freq_meas.size() and not found; i++) { if (earfcn_ == intra_freq_meas[i]->get_earfcn()) { @@ -1051,6 +1056,7 @@ void sync::set_cells_to_meas(uint32_t earfcn_, const std::set& pci) void sync::meas_stop() { + std::lock_guard lock(intra_freq_cfg_mutex); for (auto& q : intra_freq_meas) { q->meas_stop(); } diff --git a/srsue/src/stack/mac/dl_harq.cc b/srsue/src/stack/mac/dl_harq.cc index f72533780..900cfe4b8 100644 --- a/srsue/src/stack/mac/dl_harq.cc +++ b/srsue/src/stack/mac/dl_harq.cc @@ -25,7 +25,7 @@ dl_harq_entity::dl_harq_entity(uint8_t cc_idx_) : proc(SRSRAN_MAX_HARQ_PROC), logger(srslog::fetch_basic_logger("MAC")), cc_idx(cc_idx_) {} -bool dl_harq_entity::init(mac_interface_rrc::ue_rnti_t* rntis_, demux* demux_unit_) +bool dl_harq_entity::init(ue_rnti* rntis_, demux* demux_unit_) { demux_unit = demux_unit_; rntis = rntis_; @@ -45,7 +45,7 @@ void dl_harq_entity::new_grant_dl(mac_interface_phy_lte::mac_grant_dl_t grant, { bzero(action, sizeof(mac_interface_phy_lte::tb_action_dl_t)); - if (grant.rnti != rntis->sps_rnti) { + if (grant.rnti != rntis->get_sps_rnti()) { // Set BCCH PID for SI RNTI dl_harq_process* proc_ptr = NULL; if (grant.rnti == SRSRAN_SIRNTI) { @@ -58,8 +58,8 @@ void dl_harq_entity::new_grant_dl(mac_interface_phy_lte::mac_grant_dl_t grant, proc_ptr = &proc[grant.pid]; } // Consider the NDI to have been toggled - if (grant.rnti == rntis->temp_rnti && last_temporal_crnti != rntis->temp_rnti) { - last_temporal_crnti = rntis->temp_rnti; + if (grant.rnti == rntis->get_temp_rnti() && last_temporal_crnti != rntis->get_temp_rnti()) { + last_temporal_crnti = rntis->get_temp_rnti(); proc_ptr->reset_ndi(); Info("Considering NDI in pid=%d to be toggled for first Temporal C-RNTI", grant.pid); } @@ -103,8 +103,14 @@ void dl_harq_entity::set_si_window_start(int si_window_start_) float dl_harq_entity::get_average_retx() { + std::unique_lock lock(retx_cnt_mutex); return average_retx; } +void dl_harq_entity::set_average_retx(uint32_t n_retx) +{ + std::unique_lock lock(retx_cnt_mutex); + average_retx = SRSRAN_VEC_CMA((float)n_retx, average_retx, nof_pkts++); +} dl_harq_entity::dl_harq_process::dl_harq_process() : subproc(SRSRAN_MAX_TB) {} @@ -320,7 +326,7 @@ void dl_harq_entity::dl_harq_process::dl_tb_process::tb_decoded(mac_interface_ph harq_entity->pcap->write_dl_crnti( payload_buffer_ptr, cur_grant.tb[tid].tbs, cur_grant.rnti, ack, cur_grant.tti, harq_entity->cc_idx); } - if (cur_grant.rnti == harq_entity->rntis->temp_rnti) { + if (cur_grant.rnti == harq_entity->rntis->get_temp_rnti()) { Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)", cur_grant.tb[tid].tbs); harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.tb[tid].tbs); @@ -332,7 +338,7 @@ void dl_harq_entity::dl_harq_process::dl_tb_process::tb_decoded(mac_interface_ph harq_entity->demux_unit->push_pdu(payload_buffer_ptr, cur_grant.tb[tid].tbs, grant.tti); // Compute average number of retransmissions per packet - harq_entity->average_retx = SRSRAN_VEC_CMA((float)n_retx, harq_entity->average_retx, harq_entity->nof_pkts++); + harq_entity->set_average_retx(n_retx); } } diff --git a/srsue/src/stack/mac/mac.cc b/srsue/src/stack/mac/mac.cc index ecd283490..4ee3d5e55 100644 --- a/srsue/src/stack/mac/mac.cc +++ b/srsue/src/stack/mac/mac.cc @@ -198,7 +198,7 @@ void mac::run_tti(const uint32_t tti) sr_procedure.step(tti); phr_procedure.step(); ra_procedure.step(tti); - ra_procedure.update_rar_window(ra_window_start, ra_window_length); + ra_procedure.update_rar_window(ra_window); // Count TTI for metrics for (uint32_t i = 0; i < SRSRAN_MAX_CARRIERS; i++) { @@ -210,13 +210,13 @@ void mac::bcch_start_rx(int si_window_start_, int si_window_length_) { if (si_window_length_ >= 0 && si_window_start_ >= 0) { dl_harq.at(0)->set_si_window_start(si_window_start_); - si_window_length = si_window_length_; - si_window_start = si_window_start_; + si_window.set(si_window_length_, si_window_start_); } else { - si_window_length = 0; - si_window_start = 0; + si_window.reset(); } - Info("SCHED: Searching for DL dci for SI-RNTI window_st=%d, window_len=%d", si_window_start, si_window_length); + Info("SCHED: Searching for DL dci for SI-RNTI window_st=%d, window_len=%d", + si_window.get_start(), + si_window.get_length()); } void mac::bcch_stop_rx() @@ -226,28 +226,25 @@ void mac::bcch_stop_rx() void mac::pcch_start_rx() { - this->p_window_start = 1; + this->p_window.set(0, 1); } void mac::clear_rntis() { - p_window_start = 0; - si_window_start = 0; - ra_window_start = -1; - ra_window_length = -1; - bzero(&uernti, sizeof(ue_rnti_t)); + p_window.reset(); + si_window.reset(); + ra_window.reset(); + uernti.reset(); } -void mac::get_rntis(ue_rnti_t* rntis) +uint16_t mac::get_crnti() { - if (rntis) { - *rntis = uernti; - } + return uernti.get_crnti(); } void mac::set_ho_rnti(uint16_t crnti, uint16_t target_pci) { - uernti.crnti = crnti; + uernti.set_crnti(crnti); if (pcap) { pcap->set_ue_id(target_pci); } @@ -255,71 +252,44 @@ void mac::set_ho_rnti(uint16_t crnti, uint16_t target_pci) uint16_t mac::get_ul_sched_rnti(uint32_t tti) { - if (uernti.temp_rnti && !uernti.crnti) { - return uernti.temp_rnti; + if (uernti.get_temp_rnti() && !uernti.get_crnti()) { + return uernti.get_temp_rnti(); } - if (uernti.crnti) { - return uernti.crnti; + if (uernti.get_crnti()) { + return uernti.get_crnti(); } return SRSRAN_INVALID_RNTI; } -bool mac::is_in_window(uint32_t tti, int* start, int* len) -{ - uint32_t st = (uint32_t)*start; - uint32_t l = (uint32_t)*len; - - if (srsran_tti_interval(tti, st) < l + 5) { - if (tti > st) { - if (tti <= st + l) { - return true; - } else { - *start = 0; - *len = 0; - return false; - } - } else { - if (tti <= (st + l) % 10240) { - return true; - } else { - *start = 0; - *len = 0; - return false; - } - } - } - return false; -} - uint16_t mac::get_dl_sched_rnti(uint32_t tti) { // Priority: SI-RNTI, P-RNTI, RA-RNTI, Temp-RNTI, CRNTI - if (si_window_start > 0) { - if (is_in_window(tti, &si_window_start, &si_window_length)) { - // TODO: This scheduling decision belongs to RRC - if (si_window_length > 1) { // This is not a SIB1 - if ((tti / 10) % 2 == 0 && (tti % 10) == 5) { // Skip subframe #5 for which SFN mod 2 = 0 - return SRSRAN_INVALID_RNTI; - } + if (si_window.is_in_window(tti)) { + // TODO: This scheduling decision belongs to RRC + if (si_window.get_length() > 1) { // This is not a SIB1 + if ((tti / 10) % 2 == 0 && (tti % 10) == 5) { // Skip subframe #5 for which SFN mod 2 = 0 + return SRSRAN_INVALID_RNTI; } - Debug("SCHED: Searching SI-RNTI, tti=%d, window start=%d, length=%d", tti, si_window_start, si_window_length); - return SRSRAN_SIRNTI; } + Debug("SCHED: Searching SI-RNTI, tti=%d, window start=%d, length=%d", + tti, + si_window.get_start(), + si_window.get_length()); + return SRSRAN_SIRNTI; } - if (uernti.rar_rnti && ra_window_start > 0 && ra_window_length > 0 && - is_in_window(tti, &ra_window_start, &ra_window_length)) { - Debug("SCHED: Searching RAR-RNTI=0x%x, tti=%d", uernti.rar_rnti, tti); - return uernti.rar_rnti; + if (uernti.get_rar_rnti() && ra_window.is_in_window(tti)) { + Debug("SCHED: Searching RAR-RNTI=0x%x, tti=%d", uernti.get_rar_rnti(), tti); + return uernti.get_rar_rnti(); } - if (uernti.temp_rnti && !uernti.crnti) { - Debug("SCHED: Searching Temp-RNTI=0x%x", uernti.temp_rnti); - return uernti.temp_rnti; + if (uernti.get_temp_rnti() && !uernti.get_crnti()) { + Debug("SCHED: Searching Temp-RNTI=0x%x", uernti.get_temp_rnti()); + return uernti.get_temp_rnti(); } - if (uernti.crnti) { - Debug("SCHED: Searching C-RNTI=0x%x", uernti.crnti); - return uernti.crnti; + if (uernti.get_crnti()) { + Debug("SCHED: Searching C-RNTI=0x%x", uernti.get_crnti()); + return uernti.get_crnti(); } - if (p_window_start > 0) { + if (p_window.is_set()) { Debug("SCHED: Searching P-RNTI"); return SRSRAN_PRNTI; } @@ -419,14 +389,17 @@ void mac::tb_decoded(uint32_t cc_idx, mac_grant_dl_t grant, bool ack[SRSRAN_MAX_ dl_harq.at(cc_idx)->tb_decoded(grant, ack); process_pdus(); - for (uint32_t tb = 0; tb < SRSRAN_MAX_CODEWORDS; tb++) { - if (grant.tb[tb].tbs) { - if (ack[tb]) { - metrics[cc_idx].rx_brate += grant.tb[tb].tbs * 8; - } else { - metrics[cc_idx].rx_errors++; + { + std::lock_guard lock(metrics_mutex); + for (uint32_t tb = 0; tb < SRSRAN_MAX_CODEWORDS; tb++) { + if (grant.tb[tb].tbs) { + if (ack[tb]) { + metrics[cc_idx].rx_brate += grant.tb[tb].tbs * 8; + } else { + metrics[cc_idx].rx_errors++; + } + metrics[cc_idx].rx_pkts++; } - metrics[cc_idx].rx_pkts++; } } } @@ -452,7 +425,7 @@ void mac::new_grant_dl(uint32_t cc_idx, } } else if (!(grant.rnti == SRSRAN_SIRNTI && cc_idx != 0)) { // If PDCCH for C-RNTI and RA procedure in Contention Resolution, notify it - if (grant.rnti == uernti.crnti && ra_procedure.is_contention_resolution()) { + if (grant.rnti == uernti.get_crnti() && ra_procedure.is_contention_resolution()) { ra_procedure.pdcch_to_crnti(false); } // Assert DL HARQ entity @@ -580,7 +553,7 @@ void mac::timer_alignment_expire() void mac::set_contention_id(uint64_t uecri) { - uernti.contention_id = uecri; + uernti.set_contention_id(uecri); } void mac::set_rach_ded_cfg(uint32_t preamble_index, uint32_t prach_mask) diff --git a/srsue/src/stack/mac/mux.cc b/srsue/src/stack/mac/mux.cc index bc3986f04..654f329e5 100644 --- a/srsue/src/stack/mac/mux.cc +++ b/srsue/src/stack/mac/mux.cc @@ -96,11 +96,15 @@ srsran::ul_sch_lcid bsr_format_convert(bsr_proc::bsr_format_t format) } } -// Multiplexing and logical channel priorization as defined in Section 5.4.3 uint8_t* mux::pdu_get(srsran::byte_buffer_t* payload, uint32_t pdu_sz) { std::lock_guard lock(mutex); + return pdu_get_unsafe(payload, pdu_sz); +} +// Multiplexing and logical channel priorization as defined in Section 5.4.3 +uint8_t* mux::pdu_get_unsafe(srsran::byte_buffer_t* payload, uint32_t pdu_sz) +{ // Logical Channel Procedure payload->clear(); pdu_msg.init_tx(payload, pdu_sz, true); @@ -240,6 +244,7 @@ uint8_t* mux::pdu_get(srsran::byte_buffer_t* payload, uint32_t pdu_sz) void mux::append_crnti_ce_next_tx(uint16_t crnti) { + std::lock_guard lock(mutex); pending_crnti_ce = crnti; } @@ -321,6 +326,7 @@ uint32_t mux::allocate_sdu(uint32_t lcid, srsran::sch_pdu* pdu_msg, int max_sdu_ void mux::msg3_flush() { + std::lock_guard lock(mutex); Debug("Msg3 buffer flushed"); msg3_buff.clear(); msg3_has_been_transmitted = false; @@ -329,17 +335,20 @@ void mux::msg3_flush() bool mux::msg3_is_transmitted() { + std::lock_guard lock(mutex); return msg3_has_been_transmitted; } void mux::msg3_prepare() { + std::lock_guard lock(mutex); msg3_has_been_transmitted = false; msg3_pending = true; } bool mux::msg3_is_pending() { + std::lock_guard lock(mutex); return msg3_pending; } @@ -351,9 +360,10 @@ bool mux::msg3_is_empty() /* Returns a pointer to the Msg3 buffer */ uint8_t* mux::msg3_get(srsran::byte_buffer_t* payload, uint32_t pdu_sz) { + std::lock_guard lock(mutex); if (pdu_sz < msg3_buff.get_tailroom()) { if (msg3_is_empty()) { - if (!pdu_get(&msg3_buff, pdu_sz)) { + if (!pdu_get_unsafe(&msg3_buff, pdu_sz)) { Error("Moving PDU from Mux unit to Msg3 buffer"); return NULL; } diff --git a/srsue/src/stack/mac/proc_ra.cc b/srsue/src/stack/mac/proc_ra.cc index c38f8ac39..902b09b58 100644 --- a/srsue/src/stack/mac/proc_ra.cc +++ b/srsue/src/stack/mac/proc_ra.cc @@ -45,7 +45,7 @@ int delta_preamble_db_table[5] = {0, 0, -3, -3, 8}; // Initializes memory and pointers to other objects void ra_proc::init(phy_interface_mac_lte* phy_h_, rrc_interface_mac* rrc_, - mac_interface_rrc::ue_rnti_t* rntis_, + ue_rnti* rntis_, srsran::timer_handler::unique_timer* time_alignment_timer_, mux* mux_unit_, srsran::ext_task_sched_handle* task_sched_) @@ -153,7 +153,7 @@ void ra_proc::state_pdcch_setup() srsran::console( "Random Access Transmission: seq=%d, tti=%d, ra-rnti=0x%x\n", sel_preamble.load(), info.tti_ra, ra_rnti); rar_window_st = ra_tti + 3; - rntis->rar_rnti = ra_rnti; + rntis->set_rar_rnti(ra_rnti); state = RESPONSE_RECEPTION; } else { rDebug("preamble not yet transmitted"); @@ -304,7 +304,7 @@ void ra_proc::preamble_transmission() (preambleTransmissionCounter - 1) * rach_cfg.powerRampingStep; phy_h->prach_send(sel_preamble, sel_maskIndex - 1, received_target_power_dbm); - rntis->rar_rnti = SRSRAN_INVALID_RNTI; + rntis->clear_rar_rnti(); ra_tti = 0; rar_received = false; backoff_interval_start = -1; @@ -396,7 +396,7 @@ void ra_proc::tb_decoded_ok(const uint8_t cc_idx, const uint32_t tti) uint8_t grant[srsran::rar_subh::RAR_GRANT_LEN] = {}; rar_pdu_msg.get()->get_sched_grant(grant); - rntis->rar_rnti = SRSRAN_INVALID_RNTI; + rntis->clear_rar_rnti(); phy_h->set_rar_grant(grant, rar_pdu_msg.get()->get_temp_crnti()); current_ta = rar_pdu_msg.get()->get_ta_cmd(); @@ -407,7 +407,7 @@ void ra_proc::tb_decoded_ok(const uint8_t cc_idx, const uint32_t tti) rar_pdu_msg.get()->get_temp_crnti()); // Save Temp-CRNTI before generating the reply - rntis->temp_rnti = rar_pdu_msg.get()->get_temp_crnti(); + rntis->set_temp_rnti(rar_pdu_msg.get()->get_temp_crnti()); // Perform actions when preamble was selected by UE MAC if (preambleIndex <= 0) { @@ -416,7 +416,7 @@ void ra_proc::tb_decoded_ok(const uint8_t cc_idx, const uint32_t tti) // If this is the first successfully received RAR within this procedure, Msg3 is empty if (mux_unit->msg3_is_empty()) { // Save transmitted C-RNTI (if any) - transmitted_crnti = rntis->crnti; + transmitted_crnti = rntis->get_crnti(); // If we have a C-RNTI, tell Mux unit to append C-RNTI CE if no CCCH SDU transmission if (transmitted_crnti) { @@ -426,7 +426,7 @@ void ra_proc::tb_decoded_ok(const uint8_t cc_idx, const uint32_t tti) } // Save transmitted UE contention id, as defined by higher layers - transmitted_contention_id = rntis->contention_id; + transmitted_contention_id = rntis->get_contention_id(); task_queue.push([this]() { rDebug("Waiting for Contention Resolution"); @@ -449,7 +449,7 @@ void ra_proc::tb_decoded_ok(const uint8_t cc_idx, const uint32_t tti) */ void ra_proc::response_error() { - rntis->temp_rnti = 0; + rntis->clear_temp_rnti(); preambleTransmissionCounter++; contention_resolution_timer.stop(); if (preambleTransmissionCounter >= rach_cfg.preambleTransMax + 1) { @@ -483,16 +483,16 @@ void ra_proc::complete() { // Start looking for PDCCH CRNTI if (!transmitted_crnti) { - rntis->crnti = rntis->temp_rnti; + rntis->set_crnti_to_temp(); } - rntis->temp_rnti = 0; + rntis->clear_temp_rnti(); mux_unit->msg3_flush(); rrc->ra_completed(); - srsran::console("Random Access Complete. c-rnti=0x%x, ta=%d\n", rntis->crnti, current_ta); - rInfo("Random Access Complete. c-rnti=0x%x, ta=%d", rntis->crnti, current_ta); + srsran::console("Random Access Complete. c-rnti=0x%x, ta=%d\n", rntis->get_crnti(), current_ta); + rInfo("Random Access Complete. c-rnti=0x%x, ta=%d", rntis->get_crnti(), current_ta); state = IDLE; } @@ -591,17 +591,15 @@ void ra_proc::pdcch_to_crnti(bool is_new_uplink_transmission) } // Called from the Stack thread -void ra_proc::update_rar_window(int& rar_window_start, int& rar_window_length) +void ra_proc::update_rar_window(rnti_window_safe& ra_window) { if (state != RESPONSE_RECEPTION) { // reset RAR window params to default values to disable RAR search - rar_window_start = -1; - rar_window_length = -1; + ra_window.reset(); } else { - rar_window_length = rach_cfg.responseWindowSize; - rar_window_start = rar_window_st; + ra_window.set(rach_cfg.responseWindowSize, rar_window_st); } - rDebug("rar_window_start=%d, rar_window_length=%d", rar_window_start, rar_window_length); + rDebug("rar_window_start=%d, rar_window_length=%d", ra_window.get_start(), ra_window.get_length()); } // Restart timer at each Msg3 HARQ retransmission (5.1.5) diff --git a/srsue/src/stack/mac/proc_sr.cc b/srsue/src/stack/mac/proc_sr.cc index fe6e1b5ce..e08968b6e 100644 --- a/srsue/src/stack/mac/proc_sr.cc +++ b/srsue/src/stack/mac/proc_sr.cc @@ -39,6 +39,7 @@ void sr_proc::init(ra_proc* ra_, phy_interface_mac_lte* phy_h_, rrc_interface_ma void sr_proc::reset() { + std::lock_guard lock(mutex); is_pending_sr = false; } @@ -75,37 +76,56 @@ void sr_proc::set_config(srsran::sr_cfg_t& cfg) void sr_proc::step(uint32_t tti) { - if (initiated) { - if (is_pending_sr) { - if (sr_cfg.enabled) { - if (sr_counter < sr_cfg.dsr_transmax) { - if (sr_counter == 0 || need_tx(tti)) { - sr_counter++; - Info("SR: Signalling PHY sr_counter=%d", sr_counter); - phy_h->sr_send(); - } - } else { - if (need_tx(tti)) { - Info("SR: Releasing PUCCH/SRS resources, sr_counter=%d, dsr_transmax=%d", - sr_counter, - sr_cfg.dsr_transmax); - srsran::console("Scheduling request failed: releasing RRC connection...\n"); - rrc->release_pucch_srs(); - ra->start_mac_order(); - reset(); + bool do_mac_order = false; + bool do_release_pucch = false; + bool do_sr = false; + + { + std::lock_guard lock(mutex); + if (initiated) { + if (is_pending_sr) { + if (sr_cfg.enabled) { + if (sr_counter < sr_cfg.dsr_transmax) { + if (sr_counter == 0 || need_tx(tti)) { + sr_counter++; + Info("SR: Signalling PHY sr_counter=%d", sr_counter); + do_sr = true; + } + } else { + if (need_tx(tti)) { + Info("SR: Releasing PUCCH/SRS resources, sr_counter=%d, dsr_transmax=%d", + sr_counter, + sr_cfg.dsr_transmax); + srsran::console("Scheduling request failed: releasing RRC connection...\n"); + do_mac_order = true; + do_release_pucch = true; + is_pending_sr = false; + } } + } else if (ra->is_idle()) { + Info("SR: PUCCH not configured. Starting RA procedure"); + do_mac_order = true; + is_pending_sr = false; } - } else if (ra->is_idle()) { - Info("SR: PUCCH not configured. Starting RA procedure"); - ra->start_mac_order(); - reset(); } } } + + // These calls go out of this component, so call them with mutex unlocked + if (do_sr) { + phy_h->sr_send(); + } + if (do_release_pucch) { + rrc->release_pucch_srs(); + } + if (do_mac_order) { + ra->start_mac_order(); + } } void sr_proc::start() { + std::lock_guard lock(mutex); if (initiated) { if (!is_pending_sr) { sr_counter = 0; diff --git a/srsue/src/stack/mac/ul_harq.cc b/srsue/src/stack/mac/ul_harq.cc index ada9f2db8..f7456a9ce 100644 --- a/srsue/src/stack/mac/ul_harq.cc +++ b/srsue/src/stack/mac/ul_harq.cc @@ -26,7 +26,7 @@ ul_harq_entity::ul_harq_entity(const uint8_t cc_idx_) : proc(SRSRAN_MAX_HARQ_PROC), logger(srslog::fetch_basic_logger("MAC")), cc_idx(cc_idx_) {} -bool ul_harq_entity::init(mac_interface_rrc_common::ue_rnti_t* rntis_, ra_proc* ra_procedure_, mux* mux_unit_) +bool ul_harq_entity::init(ue_rnti* rntis_, ra_proc* ra_procedure_, mux* mux_unit_) { mux_unit = mux_unit_; ra_procedure = ra_procedure_; @@ -75,12 +75,12 @@ void ul_harq_entity::new_grant_ul(mac_interface_phy_lte::mac_grant_ul_t grant, Error("Invalid PID: %d", grant.pid); return; } - if (grant.rnti == rntis->crnti || grant.rnti == rntis->temp_rnti || SRSRAN_RNTI_ISRAR(grant.rnti)) { - if (grant.rnti == rntis->crnti && proc[grant.pid].is_sps()) { + if (grant.rnti == rntis->get_crnti() || grant.rnti == rntis->get_temp_rnti() || SRSRAN_RNTI_ISRAR(grant.rnti)) { + if (grant.rnti == rntis->get_crnti() && proc[grant.pid].is_sps()) { grant.tb.ndi = true; } proc[grant.pid].new_grant_ul(grant, action); - } else if (grant.rnti == rntis->sps_rnti) { + } else if (grant.rnti == rntis->get_sps_rnti()) { if (grant.tb.ndi) { grant.tb.ndi = proc[grant.pid].get_ndi(); proc[grant.pid].new_grant_ul(grant, action); @@ -174,7 +174,7 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr // Get maximum retransmissions uint32_t max_retx; - if (grant.rnti == harq_entity->rntis->temp_rnti) { + if (grant.rnti == harq_entity->rntis->get_temp_rnti()) { max_retx = harq_entity->harq_cfg.max_harq_msg3_tx; } else { max_retx = harq_entity->harq_cfg.max_harq_tx; @@ -183,11 +183,11 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr // Check maximum retransmissions, do not consider last retx ACK if (current_tx_nb >= max_retx && !grant.hi_value) { Info("UL %d: Maximum number of ReTX reached (%d). Discarding TB.", pid, max_retx); - if (grant.rnti == harq_entity->rntis->temp_rnti) { + if (grant.rnti == harq_entity->rntis->get_temp_rnti()) { harq_entity->ra_procedure->harq_max_retx(); } reset(); - } else if (grant.rnti == harq_entity->rntis->temp_rnti && current_tx_nb && !grant.hi_value) { + } else if (grant.rnti == harq_entity->rntis->get_temp_rnti() && current_tx_nb && !grant.hi_value) { harq_entity->ra_procedure->harq_retx(); } } @@ -206,9 +206,9 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr action->tb.enabled = true; // Decide if adaptive retx or new tx. 3 checks in 5.4.2.1 - } else if ((grant.rnti != harq_entity->rntis->temp_rnti && + } else if ((grant.rnti != harq_entity->rntis->get_temp_rnti() && grant.tb.ndi != get_ndi()) || // If not addressed to T-CRNTI and NDI toggled - (grant.rnti == harq_entity->rntis->crnti && + (grant.rnti == harq_entity->rntis->get_crnti() && !has_grant()) || // If addressed to C-RNTI and buffer is empty (grant.is_rar)) // Grant received in a RAR { @@ -245,7 +245,7 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr } } - if (grant.rnti == harq_entity->rntis->crnti && harq_entity->ra_procedure->is_contention_resolution()) { + if (grant.rnti == harq_entity->rntis->get_crnti() && harq_entity->ra_procedure->is_contention_resolution()) { harq_entity->ra_procedure->pdcch_to_crnti(true); } } else if (has_grant()) { @@ -256,10 +256,10 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr } if (harq_entity->pcap) { uint16_t rnti; - if (grant.rnti == harq_entity->rntis->temp_rnti && harq_entity->rntis->temp_rnti) { - rnti = harq_entity->rntis->temp_rnti; + if (grant.rnti == harq_entity->rntis->get_temp_rnti() && harq_entity->rntis->get_temp_rnti()) { + rnti = harq_entity->rntis->get_temp_rnti(); } else { - rnti = harq_entity->rntis->crnti; + rnti = harq_entity->rntis->get_crnti(); } harq_entity->pcap->write_ul_crnti(pdu_ptr, grant.tb.tbs, rnti, get_nof_retx(), grant.tti_tx, harq_entity->cc_idx); } @@ -355,11 +355,11 @@ void ul_harq_entity::ul_harq_process::generate_new_tx(mac_interface_phy_lte::mac current_tx_nb = 0; current_irv = 0; - action->is_rar = grant.is_rar || (grant.rnti == harq_entity->rntis->temp_rnti); + action->is_rar = grant.is_rar || (grant.rnti == harq_entity->rntis->get_temp_rnti()); Info("UL %d: New TX%s, RV=%d, TBS=%d", pid, - grant.rnti == harq_entity->rntis->temp_rnti ? " for Msg3" : "", + grant.rnti == harq_entity->rntis->get_temp_rnti() ? " for Msg3" : "", get_rv(), cur_grant.tb.tbs); generate_tx(action); diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index d391c2d4f..1dc96cf76 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -1361,13 +1361,11 @@ rrc::connection_reest_proc::connection_reest_proc(srsue::rrc* rrc_) : rrc_ptr(rr proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) { // Save Current RNTI before MAC Reset - mac_interface_rrc::ue_rnti_t uernti; - rrc_ptr->mac->get_rntis(&uernti); + uint16_t crnti = rrc_ptr->mac->get_crnti(); size_t nof_scells_active = rrc_ptr->phy_ctrl->current_config_scells().count(); // 5.3.7.1 - Conditions for Reestablishment procedure - if (not rrc_ptr->security_is_activated or rrc_ptr->state != RRC_STATE_CONNECTED or - uernti.crnti == SRSRAN_INVALID_RNTI) { + if (not rrc_ptr->security_is_activated or rrc_ptr->state != RRC_STATE_CONNECTED or crnti == SRSRAN_INVALID_RNTI) { Warning("Conditions are NOT met to start procedure."); return proc_outcome_t::error; } @@ -1379,7 +1377,7 @@ proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) reest_source_pci = rrc_ptr->ho_handler.get()->ho_src_cell.pci; reest_source_freq = rrc_ptr->ho_handler.get()->ho_src_cell.earfcn; } else { - reest_rnti = uernti.crnti; + reest_rnti = crnti; reest_source_pci = rrc_ptr->meas_cells.serving_cell().get_pci(); // needed for reestablishment with another cell reest_source_freq = rrc_ptr->meas_cells.serving_cell().get_earfcn(); } @@ -1651,9 +1649,7 @@ srsran::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc // Save serving cell and current configuration ho_src_cell = rrc_ptr->meas_cells.serving_cell().phy_cell; - mac_interface_rrc::ue_rnti_t uernti; - rrc_ptr->mac->get_rntis(&uernti); - ho_src_rnti = uernti.crnti; + ho_src_rnti = rrc_ptr->mac->get_crnti(); // Section 5.3.5.4 rrc_ptr->t310.stop(); diff --git a/srsue/src/stack/rrc/test/rrc_meas_test.cc b/srsue/src/stack/rrc/test/rrc_meas_test.cc index 7c3756d58..1c438ebf0 100644 --- a/srsue/src/stack/rrc/test/rrc_meas_test.cc +++ b/srsue/src/stack/rrc/test/rrc_meas_test.cc @@ -155,9 +155,9 @@ public: void set_config(srsran::sr_cfg_t& sr_cfg) override {} void set_rach_ded_cfg(uint32_t preamble_index, uint32_t prach_mask) override {} - void get_rntis(ue_rnti_t* rntis) override {} - void set_contention_id(uint64_t uecri) override {} - void set_ho_rnti(uint16_t crnti, uint16_t target_pci) override {} + uint16_t get_crnti() override { return 0; } + void set_contention_id(uint64_t uecri) override {} + void set_ho_rnti(uint16_t crnti, uint16_t target_pci) override {} void reconfiguration(const uint32_t& cc_idx, const bool& enable) override {} void reset() override {} From 0e6e3d201e277e598101ac175aafeb1c0bdc57ec Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 30 Jun 2021 19:42:54 +0200 Subject: [PATCH 05/50] sys_metrics: reduce log level when measurement interval is shorter than expected on highly loaded systems it can happen that the get_metrics() is called twice within a few houndred milliseconds. Logging a warning in this case isn't needed, so reduce to info. on the other hand, 100ms might be to convervative. Patch also lowers the smallest interval to 10ms --- lib/src/system/sys_metrics_processor.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/system/sys_metrics_processor.cc b/lib/src/system/sys_metrics_processor.cc index d5d616cf6..218bb2d72 100644 --- a/lib/src/system/sys_metrics_processor.cc +++ b/lib/src/system/sys_metrics_processor.cc @@ -69,9 +69,9 @@ sys_metrics_t sys_metrics_processor::get_metrics() uint32_t measure_interval_ms = std::chrono::duration_cast(current_time - last_query_time).count(); - // The time elapsed between 2 measures must be greater that 100 milliseconds. - if (measure_interval_ms < 100u) { - logger.warning("Interval less than 100ms, skipping measurement."); + // The time elapsed between 2 measures must be greater that 10 milliseconds. + if (measure_interval_ms < 10u) { + logger.info("Interval less than 10ms, skipping measurement."); return create_null_metrics(); } From fb4dd3ba7bc274f987377e6aa1b5dba8fe243bf4 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 1 Jun 2021 20:45:08 +0200 Subject: [PATCH 06/50] ttcn3: fix various races between SS and Stack thread detected by TSAN fixed through the right usage of mutexes in both TTCN PHY and syssim. nested mutex locking is solved by calling SS from the PHY after releaseing the PHY lock again. --- srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h | 2 +- srsue/src/test/ttcn3/hdr/ttcn3_syssim.h | 5 +- srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc | 77 ++++++++++++++--------- srsue/src/test/ttcn3/src/ttcn3_dut.cc | 1 + srsue/src/test/ttcn3/src/ttcn3_syssim.cc | 13 +++- 5 files changed, 66 insertions(+), 32 deletions(-) diff --git a/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h b/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h index 72ebf41ed..6a38708ba 100644 --- a/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h +++ b/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h @@ -122,7 +122,7 @@ private: int sr_tx_tti = -1; bool sr_pending = false; - std::mutex mutex; + std::mutex phy_mutex; srsran::task_scheduler task_sched; diff --git a/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h b/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h index 029f41dd9..1c18195d7 100644 --- a/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h +++ b/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h @@ -242,7 +242,7 @@ private: uint32_t prach_preamble_index = 0; uint16_t dl_rnti = 0; int force_lcid = -1; - srsue::stack_test_dummy stack; + srsue::stack_test_dummy stack; // helper to run queue pending tasks bool last_dl_ndi[SRSRAN_FDD_NOF_HARQ] = {}; bool last_ul_ndi[SRSRAN_FDD_NOF_HARQ] = {}; @@ -276,6 +276,9 @@ private: std::vector cells; int32_t pcell_idx = -1; + // Main mutex to protect access from syssim's main thread (epoll handlers) and calls from UE's stack thread + std::mutex syssim_mutex; + // Internal function void update_cell_map(); bool syssim_has_cell(std::string cell_name); diff --git a/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc b/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc index 05b8f31a4..2d0fcf6fd 100644 --- a/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc +++ b/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc @@ -55,7 +55,7 @@ void lte_ttcn3_phy::get_metrics(const srsran::srsran_rat_t& rat, phy_metrics_t* // The interface for the SS void lte_ttcn3_phy::set_cell_map(const cell_list_t& cells_) { - std::lock_guard lock(mutex); + std::lock_guard lock(phy_mutex); cells = cells_; } @@ -95,7 +95,7 @@ void lte_ttcn3_phy::meas_stop() {} // are actually visible though. bool lte_ttcn3_phy::cell_search() { - std::lock_guard lock(mutex); + std::lock_guard lock(phy_mutex); logger.info("Running cell search in PHY"); @@ -135,28 +135,44 @@ bool lte_ttcn3_phy::cell_search() return true; } +// Called from RRC/Stack thread bool lte_ttcn3_phy::cell_select(phy_cell_t rrc_cell) { - // try to find RRC cell in current cell map - for (auto& cell : cells) { - if (cell.info.id == rrc_cell.pci && cell.earfcn == rrc_cell.earfcn) { - if (cell.power >= SUITABLE_CELL_RS_EPRE) { - pcell = cell; - pcell_set = true; - syssim->select_cell(pcell.info); - logger.info("Select PCell with %.2f on PCI=%d on EARFCN=%d.", cell.power, rrc_cell.pci, rrc_cell.earfcn); - } else { - pcell_set = false; - logger.error("Power of selected cell too low (%.2f < %.2f)", cell.power, SUITABLE_CELL_RS_EPRE); - } + bool ret = false; - stack->cell_select_complete(pcell_set); - return true; + { + std::lock_guard lock(phy_mutex); + // try to find RRC cell in current cell map + for (auto& cell : cells) { + if (cell.info.id == rrc_cell.pci && cell.earfcn == rrc_cell.earfcn) { + if (cell.power >= SUITABLE_CELL_RS_EPRE) { + pcell = cell; + pcell_set = true; + logger.info("Select PCell with %.2f on PCI=%d on EARFCN=%d.", cell.power, rrc_cell.pci, rrc_cell.earfcn); + } else { + pcell_set = false; + logger.error("Power of selected cell too low (%.2f < %.2f)", cell.power, SUITABLE_CELL_RS_EPRE); + } + // update return value + ret = pcell_set; + break; + } } } - logger.error("Couldn't find RRC cell with PCI=%d on EARFCN=%d in cell map.", rrc_cell.pci, rrc_cell.earfcn); - return false; + if (ret) { + // cell has been selected + syssim->select_cell(pcell.info); + } else { + logger.error( + "Couldn't find (suitable) RRC cell with PCI=%d on EARFCN=%d in cell map.", rrc_cell.pci, rrc_cell.earfcn); + } + + // inform stack about result asynchronously + task_sched.defer_task([this, ret]() { stack->cell_select_complete(ret); }); + + // regardless of actual result, return True to tell RRC that we entered the cell select state at PHY + return true; } bool lte_ttcn3_phy::cell_is_camping() @@ -169,15 +185,19 @@ bool lte_ttcn3_phy::cell_is_camping() } // The interface for MAC (called from Stack thread context) - void lte_ttcn3_phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec) { - std::lock_guard lock(mutex); - logger.info("Sending PRACH with preamble %d on PCID=%d", preamble_idx, pcell.info.id); - prach_tti_tx = current_tti; - ra_trans_cnt++; + uint32_t pcell_pci = 0; + { + std::lock_guard lock(phy_mutex); + pcell_pci = pcell.info.id; + + logger.info("Sending PRACH with preamble %d on PCID=%d", preamble_idx, pcell_pci); + prach_tti_tx = current_tti; + ra_trans_cnt++; + } - syssim->prach_indication(preamble_idx, pcell.info.id); + syssim->prach_indication(preamble_idx, pcell_pci); }; std::string lte_ttcn3_phy::get_type() @@ -187,7 +207,7 @@ std::string lte_ttcn3_phy::get_type() phy_interface_mac_lte::prach_info_t lte_ttcn3_phy::prach_get_info() { - std::lock_guard lock(mutex); + std::lock_guard lock(phy_mutex); prach_info_t info = {}; if (prach_tti_tx != -1) { info.is_transmitted = true; @@ -231,7 +251,7 @@ void lte_ttcn3_phy::set_rar_grant(uint8_t grant_payload[SRSRAN_RAR_GRANT_LEN], u // Called from the SYSSIM to configure the current TTI void lte_ttcn3_phy::set_current_tti(uint32_t tti) { - std::lock_guard lock(mutex); + std::lock_guard lock(phy_mutex); current_tti = tti; run_tti(); @@ -240,6 +260,7 @@ void lte_ttcn3_phy::set_current_tti(uint32_t tti) // Called from MAC to retrieve the current TTI uint32_t lte_ttcn3_phy::get_current_tti() { + std::lock_guard lock(phy_mutex); return current_tti; } @@ -259,7 +280,7 @@ float lte_ttcn3_phy::get_pathloss_db() // Calling function hold mutex void lte_ttcn3_phy::new_grant_ul(mac_interface_phy_lte::mac_grant_ul_t ul_mac_grant) { - std::lock_guard lock(mutex); + std::lock_guard lock(phy_mutex); mac_interface_phy_lte::tb_action_ul_t ul_action = {}; @@ -275,7 +296,7 @@ void lte_ttcn3_phy::new_grant_ul(mac_interface_phy_lte::mac_grant_ul_t ul_mac_gr // Provides DL grant, copy data into DL action and pass up to MAC void lte_ttcn3_phy::new_tb(const srsue::mac_interface_phy_lte::mac_grant_dl_t dl_grant, const uint8_t* data) { - std::lock_guard lock(mutex); + std::lock_guard lock(phy_mutex); if (data == nullptr) { logger.error("Invalid data buffer passed"); diff --git a/srsue/src/test/ttcn3/src/ttcn3_dut.cc b/srsue/src/test/ttcn3/src/ttcn3_dut.cc index a39f8d64c..f50e2d64a 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_dut.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_dut.cc @@ -11,6 +11,7 @@ */ #include "srsran/build_info.h" +#include "srsran/common/tsan_options.h" #include "srsran/srslog/srslog.h" #include "srsue/hdr/ue.h" #include "swappable_sink.h" diff --git a/srsue/src/test/ttcn3/src/ttcn3_syssim.cc b/srsue/src/test/ttcn3/src/ttcn3_syssim.cc index 698411149..71c92cfca 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_syssim.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_syssim.cc @@ -52,7 +52,9 @@ ttcn3_syssim::ttcn3_syssim(ttcn3_ue* ue_) : signal_handler(running), timer_handler(create_tti_timer(), [&](uint64_t res) { new_tti_indication(res); }) { - if (ue->init(all_args_t{}, this, "INIT_TEST") != SRSRAN_SUCCESS) { + all_args_t args = {}; + args.stack.sync_queue_size = MULTIQUEUE_DEFAULT_CAPACITY; + if (ue->init(args, this, "INIT_TEST") != SRSRAN_SUCCESS) { ue->stop(); fprintf(stderr, "Couldn't initialize UE.\n"); } @@ -193,6 +195,8 @@ int ttcn3_syssim::add_port_handler() ///< Function called by epoll timer handler when TTI timer expires void ttcn3_syssim::new_tti_indication(uint64_t res) { + std::lock_guard lock(syssim_mutex); + tti = (tti + 1) % 10240; logger.set_context(tti); @@ -384,6 +388,7 @@ void ttcn3_syssim::stop() void ttcn3_syssim::reset() { + std::lock_guard lock(syssim_mutex); logger.info("Resetting SS"); cells.clear(); pcell_idx = -1; @@ -480,9 +485,11 @@ void ttcn3_syssim::disable_data() event_queue.push(DISABLE_DATA); } -// Called from PHY but always from the SS main thread with lock being hold +// Called from PHY through RA procedure running on Stack thread void ttcn3_syssim::prach_indication(uint32_t preamble_index_, const uint32_t& cell_id) { + std::lock_guard lock(syssim_mutex); + // verify that UE intends to send PRACH on current Pcell if (cells[pcell_idx]->config.phy_cell.id != cell_id) { logger.error( @@ -1261,8 +1268,10 @@ void ttcn3_syssim::release_as_security_impl(const std::string cell_name) cell->pending_bearer_config.clear(); } +// Called from PHY in Stack context void ttcn3_syssim::select_cell(srsran_cell_t phy_cell) { + std::lock_guard lock(syssim_mutex); // find matching cell in SS cell list for (uint32_t i = 0; i < cells.size(); ++i) { if (cells[i]->config.phy_cell.id == phy_cell.id) { From 626f24c9f9a5ed89afc83cac45ac19d5d0682b0c Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 7 Jun 2021 11:51:54 +0200 Subject: [PATCH 07/50] block_queue: use class mutex to protect size() getter detected with TSAN --- lib/include/srsran/common/block_queue.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/include/srsran/common/block_queue.h b/lib/include/srsran/common/block_queue.h index 7982d191c..479f474d2 100644 --- a/lib/include/srsran/common/block_queue.h +++ b/lib/include/srsran/common/block_queue.h @@ -121,7 +121,14 @@ public: const myobj& front() const { return q.front(); } - size_t size() { return q.size(); } + size_t size() + { + size_t len = 0; + pthread_mutex_lock(&mutex); + len = q.size(); + pthread_mutex_unlock(&mutex); + return len; + } private: bool pop_(myobj* value, bool block) From a9ad408f513df530ea43a929d52d7d07106f0a39 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 7 Jun 2021 11:53:00 +0200 Subject: [PATCH 08/50] task_scheduler: use block_queue for internal tasks TSAN detected wrong use of the old deque-based internal queue. To avoid unwanted/undetected mis-use the patch uses the thread-safe block_queue data structure instead. --- lib/include/srsran/common/task_scheduler.h | 29 +++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/include/srsran/common/task_scheduler.h b/lib/include/srsran/common/task_scheduler.h index fc0b5d3c5..c1a8b0004 100644 --- a/lib/include/srsran/common/task_scheduler.h +++ b/lib/include/srsran/common/task_scheduler.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_TASK_SCHEDULER_H #define SRSRAN_TASK_SCHEDULER_H +#include "block_queue.h" #include "interfaces_common.h" #include "multiqueue.h" #include "thread_pool.h" @@ -24,7 +25,7 @@ class task_scheduler { public: explicit task_scheduler(uint32_t default_extern_tasks_size = 512, uint32_t nof_timers_prealloc = 100) : - external_tasks{default_extern_tasks_size}, timers{nof_timers_prealloc} + external_tasks{default_extern_tasks_size}, timers{nof_timers_prealloc}, internal_tasks(512) { background_queue = external_tasks.add_queue(); } @@ -49,7 +50,12 @@ public: } //! Enqueues internal task to be run in next tic - void defer_task(srsran::move_task_t func) { internal_tasks.push_back(std::move(func)); } + void defer_task(srsran::move_task_t func) + { + if (not internal_tasks.try_push(std::move(func))) { + srslog::fetch_basic_logger("COMN", false).warning("Couldn't add new internal task"); + } + } //! Defer the handling of the result of a background task to next tic void notify_background_task_result(srsran::move_task_t task) @@ -90,21 +96,20 @@ public: srsran::timer_handler* get_timer_handler() { return &timers; } private: + // Perform pending stack deferred tasks void run_all_internal_tasks() { - // Perform pending stack deferred tasks - // Note: Using a deque because tasks can enqueue new tasks, which would lead to - // reference invalidation in case of vector - while (not internal_tasks.empty()) { - internal_tasks.front()(); - internal_tasks.pop_front(); + srsran::move_task_t task{}; + while (internal_tasks.try_pop(task)) { + task(); } } - srsran::task_multiqueue external_tasks; - srsran::task_queue_handle background_queue; ///< Queue for handling the outcomes of tasks run in the background - srsran::timer_handler timers; - std::deque internal_tasks; ///< enqueues stack tasks from within main thread. Avoids locking + srsran::task_multiqueue external_tasks; + srsran::task_queue_handle background_queue; ///< Queue for handling the outcomes of tasks run in the background + srsran::timer_handler timers; + srsran::dyn_blocking_queue + internal_tasks; ///< enqueues stack tasks from within main thread. Avoids locking }; //! Task scheduler handle given to classes/functions running within the main control thread From 3173dedf0a3804985f252e72b4b768d6566d1827 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 9 Jun 2021 16:39:54 +0200 Subject: [PATCH 09/50] ue_stack_lte: make sure to execute stack commands on Stack thread some commands were executed from the calling thread which may lead to concurrent access to members. Detected by TSAN. The patch moves all remaining calls (the majority was alread moved) to the Stack task queue. --- srsue/src/stack/ue_stack_lte.cc | 51 ++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 94adee7dd..56f164c1d 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -271,35 +271,46 @@ bool ue_stack_lte::switch_on() bool ue_stack_lte::switch_off() { - // generate detach request with switch-off flag - nas.switch_off(); - - // wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2) - int cnt = 0, timeout_ms = 5000; - while (not rrc.srbs_flushed() && ++cnt <= timeout_ms) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - bool detach_sent = true; - if (not rrc.srbs_flushed()) { - srslog::fetch_basic_logger("NAS").warning("Detach couldn't be sent after %dms.", timeout_ms); - detach_sent = false; + if (running) { + ue_task_queue.try_push([this]() { + // generate detach request with switch-off flag + nas.switch_off(); + + // wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2) + int cnt = 0, timeout_ms = 5000; + while (not rrc.srbs_flushed() && ++cnt <= timeout_ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + if (not rrc.srbs_flushed()) { + srslog::fetch_basic_logger("NAS").warning("Detach couldn't be sent after %dms.", timeout_ms); + } + }); } - - return detach_sent; + return true; } bool ue_stack_lte::enable_data() { - // perform attach request - srsran::console("Turning off airplane mode.\n"); - return nas.enable_data(); + if (running) { + ue_task_queue.try_push([this]() { + // perform attach request + srsran::console("Turning off airplane mode.\n"); + nas.enable_data(); + }); + } + return true; } bool ue_stack_lte::disable_data() { - // generate detach request - srsran::console("Turning on airplane mode.\n"); - return nas.disable_data(); + if (running) { + ue_task_queue.try_push([this]() { + // generate detach request + srsran::console("Turning on airplane mode.\n"); + nas.disable_data(); + }); + } + return true; } bool ue_stack_lte::start_service_request() From bbcaa4942936d45506cfa013cdf7ee77f6514b6f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 14 Jun 2021 12:51:30 +0200 Subject: [PATCH 10/50] network_utils: fix TSAN detected race --- lib/include/srsran/common/network_utils.h | 2 +- lib/src/common/network_utils.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/include/srsran/common/network_utils.h b/lib/include/srsran/common/network_utils.h index 8f19dd5d2..d9f4fc93d 100644 --- a/lib/include/srsran/common/network_utils.h +++ b/lib/include/srsran/common/network_utils.h @@ -154,7 +154,7 @@ private: // state std::mutex socket_mutex; std::map active_sockets; - bool running = false; + std::atomic running = {false}; int pipefd[2] = {-1, -1}; std::vector rem_fd_tmp_list; std::condition_variable rem_cvar; diff --git a/lib/src/common/network_utils.cc b/lib/src/common/network_utils.cc index bd21546c4..232c091ea 100644 --- a/lib/src/common/network_utils.cc +++ b/lib/src/common/network_utils.cc @@ -459,7 +459,7 @@ void socket_manager::run_thread() FD_SET(pipefd[0], &total_fd_set); max_fd = std::max(pipefd[0], max_fd); - while (running) { + while (running.load(std::memory_order_relaxed)) { memcpy(&read_fd_set, &total_fd_set, sizeof(total_fd_set)); int n = select(max_fd + 1, &read_fd_set, nullptr, nullptr, nullptr); From 5999b0d3a5e8ad5c8863961de0464009f9190a30 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 28 Jun 2021 11:00:17 +0200 Subject: [PATCH 11/50] ue: move blocking wait for detach outside of stack class the thread sleep waiting for the UE release should not run on the stack thread. Move it to the UE class therefore. --- srsue/src/stack/ue_stack_lte.cc | 9 --------- srsue/src/ue.cc | 21 ++++++++++++++++++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 56f164c1d..4bef269a1 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -275,15 +275,6 @@ bool ue_stack_lte::switch_off() ue_task_queue.try_push([this]() { // generate detach request with switch-off flag nas.switch_off(); - - // wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2) - int cnt = 0, timeout_ms = 5000; - while (not rrc.srbs_flushed() && ++cnt <= timeout_ms) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - if (not rrc.srbs_flushed()) { - srslog::fetch_basic_logger("NAS").warning("Detach couldn't be sent after %dms.", timeout_ms); - } }); } return true; diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index ac2ab2951..6e8914ff6 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -301,7 +301,26 @@ bool ue::switch_off() if (gw_inst) { gw_inst->stop(); } - return stack->switch_off(); + + // send switch off + stack->switch_off(); + + // wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2) + int cnt = 0, timeout_s = 5; + stack_metrics_t metrics = {}; + stack->get_metrics(&metrics); + + while (metrics.rrc.state != RRC_STATE_IDLE && ++cnt <= timeout_s) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + stack->get_metrics(&metrics); + } + + if (metrics.rrc.state != RRC_STATE_IDLE) { + srslog::fetch_basic_logger("NAS").warning("Detach couldn't be sent after %ds.", timeout_s); + return false; + } + + return true; } void ue::start_plot() From f90e35920866cc0faf897dbc0e7c6a359289f868 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Thu, 1 Jul 2021 13:32:21 +0200 Subject: [PATCH 12/50] Moved cp to test common --- lib/include/srsran/common/test_common.h | 8 ++++++++ srsenb/test/mac/nr/sched_nr_sim_ue.cc | 2 +- srsenb/test/rrc/rrc_mobility_test.cc | 20 ++++++++++---------- srsenb/test/rrc/test_helpers.h | 7 ------- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/lib/include/srsran/common/test_common.h b/lib/include/srsran/common/test_common.h index 8e3785c85..19d86f731 100644 --- a/lib/include/srsran/common/test_common.h +++ b/lib/include/srsran/common/test_common.h @@ -17,6 +17,7 @@ #ifdef __cplusplus +#include "srsran/common/buffer_pool.h" #include "srsran/common/crash_handler.h" #include "srsran/common/srsran_assert.h" #include "srsran/common/standard_streams.h" @@ -141,6 +142,13 @@ inline void test_init(int argc, char** argv) srslog::init(); } +inline void copy_msg_to_buffer(unique_byte_buffer_t& pdu, const_byte_span msg) +{ + pdu = srsran::make_byte_buffer(); + memcpy(pdu->msg, msg.data(), msg.size()); + pdu->N_bytes = msg.size(); +} + } // namespace srsran #define CONDERROR(cond, fmt, ...) srsran_assert(not(cond), fmt, ##__VA_ARGS__) diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index 807ac7a53..e6d9bffd7 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -11,7 +11,7 @@ */ #include "sched_nr_sim_ue.h" -#include "lib/include/srsran/common/test_common.h" +#include "srsran/common/test_common.h" namespace srsenb { diff --git a/srsenb/test/rrc/rrc_mobility_test.cc b/srsenb/test/rrc/rrc_mobility_test.cc index 95f5a843f..0c7ac9838 100644 --- a/srsenb/test/rrc/rrc_mobility_test.cc +++ b/srsenb/test/rrc/rrc_mobility_test.cc @@ -183,10 +183,10 @@ int test_s1ap_mobility(srsran::log_sink_spy& spy, test_event test_params) /* Receive MeasReport from UE (correct if PCI=2) */ if (test_params == test_event::wrong_measreport) { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x0D, 0xBC, 0x80}; // PCI == 3 - test_helpers::copy_msg_to_buffer(pdu, meas_report); + copy_msg_to_buffer(pdu, meas_report); } else { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x09, 0xBC, 0x80}; // PCI == 2 - test_helpers::copy_msg_to_buffer(pdu, meas_report); + copy_msg_to_buffer(pdu, meas_report); } tester.rrc.write_pdu(tester.rnti, 1, std::move(pdu)); tester.tic(); @@ -203,7 +203,7 @@ int test_s1ap_mobility(srsran::log_sink_spy& spy, test_event test_params) if (test_params == test_event::concurrent_ho) { s1ap.last_ho_required = {}; uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x09, 0xBC, 0x80}; // PCI == 2 - test_helpers::copy_msg_to_buffer(pdu, meas_report); + copy_msg_to_buffer(pdu, meas_report); tester.rrc.write_pdu(tester.rnti, 1, std::move(pdu)); tester.tic(); TESTASSERT(s1ap.last_ho_required.rrc_container == nullptr); @@ -241,7 +241,7 @@ int test_s1ap_mobility(srsran::log_sink_spy& spy, test_event test_params) 0x01, 0x48, 0x04, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0xa0, 0x07, 0xa0, 0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0xa7, 0xd0, 0xc1, 0xf6, 0xaf, 0x3e, 0x12, 0xcc, 0x86, 0x0d, 0x30, 0x00, 0x0b, 0x5a, 0x02, 0x17, 0x86, 0x00, 0x05, 0xa0, 0x20}; - test_helpers::copy_msg_to_buffer(pdu, ho_cmd_rrc_container); + copy_msg_to_buffer(pdu, ho_cmd_rrc_container); TESTASSERT(s1ap.last_enb_status.rnti != tester.rnti); tester.rrc.ho_preparation_complete(tester.rnti, rrc::ho_prep_result::success, asn1::s1ap::ho_cmd_s{}, std::move(pdu)); TESTASSERT(s1ap.last_enb_status.status_present); @@ -381,7 +381,7 @@ int test_s1ap_tenb_mobility(test_event test_params) tester.rrc.upd_user(0x47, 0x46); uint8_t recfg_complete[] = {0x10, 0x00}; - test_helpers::copy_msg_to_buffer(pdu, recfg_complete); + copy_msg_to_buffer(pdu, recfg_complete); tester.rrc.write_pdu(0x46, srb_to_lcid(lte_srb::srb1), std::move(pdu)); tester.tic(); TESTASSERT(mac_ue.ue_bearers[srb_to_lcid(lte_srb::srb1)].direction == sched_interface::ue_bearer_cfg_t::BOTH); @@ -421,10 +421,10 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) /* Receive MeasReport from UE (correct if PCI=2) */ if (test_params == test_event::wrong_measreport) { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x0D, 0xBC, 0x80}; // PCI == 3 - test_helpers::copy_msg_to_buffer(pdu, meas_report); + copy_msg_to_buffer(pdu, meas_report); } else { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x09, 0xBC, 0x80}; // PCI == 2 - test_helpers::copy_msg_to_buffer(pdu, meas_report); + copy_msg_to_buffer(pdu, meas_report); } tester.rrc.write_pdu(tester.rnti, 1, std::move(pdu)); tester.tic(); @@ -444,7 +444,7 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) if (test_params == test_event::concurrent_ho) { tester.pdcp.last_sdu = {}; uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x09, 0xBC, 0x80}; // PCI == 2 - test_helpers::copy_msg_to_buffer(pdu, meas_report); + copy_msg_to_buffer(pdu, meas_report); tester.rrc.write_pdu(tester.rnti, 1, std::move(pdu)); tester.tic(); TESTASSERT(tester.pdcp.last_sdu.sdu == nullptr); @@ -503,7 +503,7 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) /* Test Case: Terminate first Handover. No extra messages should be sent DL. SR/CQI resources match recfg message */ uint8_t recfg_complete[] = {0x10, 0x00}; - test_helpers::copy_msg_to_buffer(pdu, recfg_complete); + copy_msg_to_buffer(pdu, recfg_complete); tester.rrc.write_pdu(tester.rnti, srb_to_lcid(lte_srb::srb2), std::move(pdu)); TESTASSERT(tester.pdcp.last_sdu.sdu == nullptr); ue_cfg = &tester.mac.ue_db[tester.rnti]; @@ -516,7 +516,7 @@ int test_intraenb_mobility(srsran::log_sink_spy& spy, test_event test_params) /* Test Case: The RRC should be able to start a new handover */ uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x05, 0xBC, 0x80}; // PCI == 1 - test_helpers::copy_msg_to_buffer(pdu, meas_report); + copy_msg_to_buffer(pdu, meas_report); tester.rrc.write_pdu(tester.rnti, 1, std::move(pdu)); tester.tic(); TESTASSERT(tester.s1ap.last_ho_required.rrc_container == nullptr); diff --git a/srsenb/test/rrc/test_helpers.h b/srsenb/test/rrc/test_helpers.h index ecd0823e6..1f4923e6d 100644 --- a/srsenb/test/rrc/test_helpers.h +++ b/srsenb/test/rrc/test_helpers.h @@ -218,13 +218,6 @@ bool unpack_asn1(ASN1Type& asn1obj, srsran::const_byte_span pdu) return true; } -inline void copy_msg_to_buffer(srsran::unique_byte_buffer_t& pdu, srsran::const_byte_span msg) -{ - pdu = srsran::make_byte_buffer(); - memcpy(pdu->msg, msg.data(), msg.size()); - pdu->N_bytes = msg.size(); -} - int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srsran::timer_handler& timers, uint16_t rnti); } // namespace test_helpers From 5dbeecdbb5a80cd70c3e7ef4eb4ac043be8d3b4c Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 08:59:19 +0200 Subject: [PATCH 13/50] ue,upper: fix linking on 32bit platforms with missing atomic libs --- srsue/src/stack/upper/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srsue/src/stack/upper/CMakeLists.txt b/srsue/src/stack/upper/CMakeLists.txt index 9d814f985..426c38a73 100644 --- a/srsue/src/stack/upper/CMakeLists.txt +++ b/srsue/src/stack/upper/CMakeLists.txt @@ -15,7 +15,8 @@ if(HAVE_PCSC) endif(HAVE_PCSC) add_library(srsue_upper STATIC ${SOURCES}) +target_link_libraries(srsue_upper ${ATOMIC_LIBS}) if(HAVE_PCSC) target_link_libraries(srsue_upper ${PCSCLITE_LIBRARY}) -endif(HAVE_PCSC) +endif(HAVE_PCSC) \ No newline at end of file From a9d21696c5ab7bb6ac2336749500f5a833c9f76a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 2 Jul 2021 11:40:02 +0200 Subject: [PATCH 14/50] rlc_am_lte: make number of RLC SDUs per PDU a compile-time parameter this allows to set the maximum number of RLC SDUs included in a single PDU at compile time. --- lib/src/rlc/rlc_am_lte.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index 4704e3cc2..36852d776 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -22,6 +22,7 @@ #define TX_MOD_BASE(x) (((x)-vt_a) % 1024) #define LCID (parent->lcid) #define RB_NAME (parent->rb_name.c_str()) +#define MAX_SDUS_PER_PDU (128) namespace srsran { @@ -1047,7 +1048,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt } // Pull SDUs from queue - while (pdu_space > head_len && tx_sdu_queue.get_n_sdus() > 0 && header.N_li < RLC_AM_WINDOW_SIZE) { + while (pdu_space > head_len && tx_sdu_queue.get_n_sdus() > 0 && header.N_li < MAX_SDUS_PER_PDU) { if (not segment_pool.has_segments()) { logger.info("Can't build a PDU segment - No segment resources available"); if (pdu_ptr != pdu->msg) { From f292042f665cebcd4c74e2a24a408befa53986a2 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 2 Jul 2021 11:41:11 +0200 Subject: [PATCH 15/50] rlc_am_lte: use try-lock when building status PDU the patch uses try-lock whenever a status PDU is tried to be built. This makes sure that when the lock is currently hold (e.g. by a thread processing rx PDUs) the generation of the status PDUs is not taking too long and blocking the calling thread. Instead the status PDU generation is deferred to the next Tx opportunity. It's a probabilistic approach that assumes that at some stage the lock can in fact be acquired. --- lib/src/rlc/rlc_am_lte.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index 36852d776..967cf5a55 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -666,8 +666,10 @@ bool rlc_am_lte::rlc_am_lte_tx::poll_required() int rlc_am_lte::rlc_am_lte_tx::build_status_pdu(uint8_t* payload, uint32_t nof_bytes) { int pdu_len = parent->rx.get_status_pdu(&tx_status, nof_bytes); - log_rlc_am_status_pdu_to_string(logger.debug, "%s", &tx_status); - if (pdu_len > 0 && nof_bytes >= static_cast(pdu_len)) { + if (pdu_len == SRSRAN_ERROR) { + logger.debug("%s Deferred Status PDU. Cause: Failed to acquire Rx lock", RB_NAME); + pdu_len = 0; + } else if (pdu_len > 0 && nof_bytes >= static_cast(pdu_len)) { log_rlc_am_status_pdu_to_string(logger.info, "%s Tx status PDU - %s", &tx_status, RB_NAME); parent->rx.reset_status(); @@ -1922,9 +1924,14 @@ void rlc_am_lte::rlc_am_lte_rx::timer_expired(uint32_t timeout_id) } // Called from Tx object to pack status PDU that doesn't exceed a given size +// If lock-acquisition fails, return -1. Otherwise it returns the length of the generated PDU. int rlc_am_lte::rlc_am_lte_rx::get_status_pdu(rlc_status_pdu_t* status, const uint32_t max_pdu_size) { - std::lock_guard lock(mutex); + std::unique_lock lock(mutex, std::try_to_lock); + if (not lock.owns_lock()) { + return SRSRAN_ERROR; + } + status->N_nack = 0; status->ack_sn = vr_r; // start with lower edge of the rx window @@ -1970,7 +1977,10 @@ int rlc_am_lte::rlc_am_lte_rx::get_status_pdu(rlc_status_pdu_t* status, const ui // Called from Tx object to obtain length of the full status PDU int rlc_am_lte::rlc_am_lte_rx::get_status_pdu_length() { - std::lock_guard lock(mutex); + std::unique_lock lock(mutex, std::try_to_lock); + if (not lock.owns_lock()) { + return 0; + } rlc_status_pdu_t status = {}; status.ack_sn = vr_ms; uint32_t i = vr_r; From 6372f89c09b428f1224066fe77e7c7bd560b456f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 12:29:49 +0200 Subject: [PATCH 16/50] s1ap_test: fix compilation on 32bit --- lib/test/asn1/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/test/asn1/CMakeLists.txt b/lib/test/asn1/CMakeLists.txt index cb883b5e4..cd8565060 100644 --- a/lib/test/asn1/CMakeLists.txt +++ b/lib/test/asn1/CMakeLists.txt @@ -7,7 +7,7 @@ # add_executable(s1ap_asn1_test s1ap_test.cc) -target_link_libraries(s1ap_asn1_test srsran_common srsran_asn1 s1ap_asn1) +target_link_libraries(s1ap_asn1_test srsran_common srsran_asn1 s1ap_asn1 ${ATOMIC_LIBS}) add_test(s1ap_asn1_test s1ap_asn1_test) add_executable(srsran_asn1_rrc_mcch_test srsran_asn1_rrc_mcch_test.cc) From eecaccb541aa53ee4142b6916eed07a1e34b1b1b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 28 Jun 2021 15:18:13 +0200 Subject: [PATCH 17/50] Added NR PHY helpers --- lib/include/srsran/asn1/rrc_nr_utils.h | 2 +- lib/include/srsran/common/phy_cfg_nr.h | 136 ++++++++ .../interfaces/rrc_nr_interface_types.h | 138 --------- .../srsran/interfaces/ue_nr_interfaces.h | 2 +- lib/include/srsran/phy/phch/ra_nr.h | 2 + lib/include/srsran/phy/phch/sch_cfg_nr.h | 3 +- lib/src/common/CMakeLists.txt | 1 + lib/src/common/phy_cfg_nr.cc | 293 ++++++++++++++++++ lib/src/phy/phch/ra_dl_nr.c | 2 +- lib/src/phy/phch/ra_nr.c | 7 + srsue/hdr/phy/nr/state.h | 19 +- srsue/src/phy/nr/cc_worker.cc | 8 +- srsue/src/phy/nr/worker_pool.cc | 4 +- test/phy/dummy_gnb_stack.h | 84 ++--- test/phy/nr_dl_flood.cc | 8 +- 15 files changed, 487 insertions(+), 222 deletions(-) create mode 100644 lib/include/srsran/common/phy_cfg_nr.h delete mode 100644 lib/include/srsran/interfaces/rrc_nr_interface_types.h create mode 100644 lib/src/common/phy_cfg_nr.cc diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index 398f79f8c..e6a26859b 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -13,10 +13,10 @@ #ifndef SRSRAN_RRC_NR_UTILS_H #define SRSRAN_RRC_NR_UTILS_H +#include "srsran/common/phy_cfg_nr.h" #include "srsran/interfaces/mac_interface_types.h" #include "srsran/interfaces/pdcp_interface_types.h" #include "srsran/interfaces/rlc_interface_types.h" -#include "srsran/interfaces/rrc_nr_interface_types.h" #include "srsran/interfaces/sched_interface.h" /************************ diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h new file mode 100644 index 000000000..3bf59c690 --- /dev/null +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -0,0 +1,136 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_PHY_CFG_NR_H +#define SRSRAN_PHY_CFG_NR_H + +#include "srsran/config.h" +#include "srsran/srsran.h" +#include +#include +#include + +namespace srsran { + +/*************************** + * PHY Config + **************************/ + +struct phy_cfg_nr_t { + /** + * SSB configuration + */ + struct ssb_cfg_t { + uint32_t periodicity_ms = 0; + std::array position_in_burst = {}; + srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz; + }; + + srsran_tdd_config_nr_t tdd = {}; + srsran_sch_hl_cfg_nr_t pdsch = {}; + srsran_sch_hl_cfg_nr_t pusch = {}; + srsran_pucch_nr_hl_cfg_t pucch = {}; + srsran_prach_cfg_t prach = {}; + srsran_pdcch_cfg_nr_t pdcch = {}; + srsran_ue_dl_nr_harq_ack_cfg_t harq_ack = {}; + srsran_csi_hl_cfg_t csi = {}; + srsran_carrier_nr_t carrier = {}; + ssb_cfg_t ssb; + + phy_cfg_nr_t() {} + + /** + * @brief Computes the DCI configuration for the current UE configuration + */ + srsran_dci_cfg_nr_t get_dci_cfg() const; + + /** + * @brief Asserts that the PDCCH configuration is valid for a given Search Space identifier + * @param ss_id Identifier + * @return true if the configuration is valid, false otherwise + */ + bool assert_ss_id(uint32_t ss_id) const; + + /** + * @brief Calculates the DCI location candidates for a given search space and aggregation level + * @param slot_idx Slot index + * @param rnti UE temporal identifier + * @param ss_id Search Space identifier + * @param L Aggregation level + * @param[out] locations DCI candidate locations + * @return true if the configuration is valid, false otherwise + */ + bool get_dci_locations( + const uint32_t& slot_idx, + const uint16_t& rnti, + const uint32_t& ss_id, + const uint32_t& L, + srsran::bounded_vector& locations) const; + + /** + * @brief Selects a valid DCI format for scheduling PDSCH and given Search Space identifier + * @param ss_id Identifier + * @return A valid DCI format if available, SRSRAN_DCI_FORMAT_NR_COUNT otherwise + */ + srsran_dci_format_nr_t get_dci_format_pdsch(uint32_t ss_id) const; + + /** + * @brief Selects a valid DCI format for scheduling PUSCH and given Search Space identifier + * @param ss_id Identifier + * @return A valid DCI format if available, SRSRAN_DCI_FORMAT_NR_COUNT otherwise + */ + srsran_dci_format_nr_t get_dci_format_pusch(uint32_t ss_id) const; + + /** + * @brief Fills PDSCH DCI context for C-RNTI using a search space identifier, DCI candidate location and RNTI + */ + bool get_dci_ctx_pdsch_rnti_c(uint32_t ss_id, + const srsran_dci_location_t& location, + const uint16_t& rnti, + srsran_dci_ctx_t& ctx) const; + + /** + * @brief Fills PUSCH DCI context for C-RNTI using a search space identifier, DCI candidate location and RNTI + */ + bool get_dci_ctx_pusch_rnti_c(uint32_t ss_id, + const srsran_dci_location_t& location, + const uint16_t& rnti, + srsran_dci_ctx_t& ctx) const; + + /** + * @brief Get PDSCH configuration for a given slot and DCI + */ + bool + get_pdsch_cfg(const srsran_slot_cfg_t& slot_cfg, const srsran_dci_dl_nr_t& dci, srsran_sch_cfg_nr_t& pdsch_cfg) const; + + /** + * @brief Get PUSCH configuration for a given slot and DCI + */ + bool + get_pusch_cfg(const srsran_slot_cfg_t& slot_cfg, const srsran_dci_ul_nr_t& dci, srsran_sch_cfg_nr_t& pdsch_cfg) const; + + /** + * @brief Get PDSCH ACK resource for a given PDSCH transmission + */ + bool get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, srsran_pdsch_ack_resource_nr_t& ack_resource) const; + + /** + * @brief Compute UCI configuration for the given slot from the pending PDSCH ACK resources, periodic CSI, + * periodic SR resources and so on. + */ + bool get_uci_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_pdsch_ack_nr_t& pdsch_ack, + srsran_uci_cfg_nr_t& uci_cfg) const; +}; +} // namespace srsran + +#endif // SRSRAN_PHY_CFG_NR_H diff --git a/lib/include/srsran/interfaces/rrc_nr_interface_types.h b/lib/include/srsran/interfaces/rrc_nr_interface_types.h deleted file mode 100644 index 436cbb3da..000000000 --- a/lib/include/srsran/interfaces/rrc_nr_interface_types.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSRAN_RRC_NR_INTERFACE_TYPES_H -#define SRSRAN_RRC_NR_INTERFACE_TYPES_H - -#include "srsran/config.h" -#include "srsran/srsran.h" -#include -#include - -namespace srsran { - -/*************************** - * PHY Config - **************************/ - -struct phy_cfg_nr_t { - /** - * SSB configuration - */ - struct ssb_cfg_t { - uint32_t periodicity_ms = 0; - std::array position_in_burst = {}; - srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz; - }; - - srsran_tdd_config_nr_t tdd = {}; - srsran_sch_hl_cfg_nr_t pdsch = {}; - srsran_sch_hl_cfg_nr_t pusch = {}; - srsran_pucch_nr_hl_cfg_t pucch = {}; - srsran_prach_cfg_t prach = {}; - srsran_pdcch_cfg_nr_t pdcch = {}; - srsran_ue_dl_nr_harq_ack_cfg_t harq_ack = {}; - srsran_csi_hl_cfg_t csi = {}; - srsran_carrier_nr_t carrier = {}; - ssb_cfg_t ssb; - - phy_cfg_nr_t() {} - - /** - * @param carrier - */ - srsran_dci_cfg_nr_t get_dci_cfg() const - { - srsran_dci_cfg_nr_t dci_cfg = {}; - - // Assume BWP bandwidth equals full channel bandwidth - dci_cfg.coreset0_bw = pdcch.coreset_present[0] ? srsran_coreset_get_bw(&pdcch.coreset[0]) : 0; - dci_cfg.bwp_dl_initial_bw = carrier.nof_prb; - dci_cfg.bwp_dl_active_bw = carrier.nof_prb; - dci_cfg.bwp_ul_initial_bw = carrier.nof_prb; - dci_cfg.bwp_ul_active_bw = carrier.nof_prb; - - // Iterate over all SS to select monitoring options - for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; i++) { - // Skip not configured SS - if (not pdcch.search_space_present[i]) { - continue; - } - - // Iterate all configured formats - for (uint32_t j = 0; j < pdcch.search_space[i].nof_formats; j++) { - if (pdcch.search_space[i].type == srsran_search_space_type_common_3 && - pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) { - dci_cfg.monitor_common_0_0 = true; - } else if (pdcch.search_space[i].type == srsran_search_space_type_ue && - pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) { - dci_cfg.monitor_0_0_and_1_0 = true; - } else if (pdcch.search_space[i].type == srsran_search_space_type_ue && - pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_1) { - dci_cfg.monitor_0_1_and_1_1 = true; - } - } - } - - // Set PUSCH parameters - dci_cfg.enable_sul = false; - dci_cfg.enable_hopping = false; - - // Set Format 0_1 and 1_1 parameters - dci_cfg.carrier_indicator_size = 0; - dci_cfg.harq_ack_codebok = harq_ack.harq_ack_codebook; - dci_cfg.nof_rb_groups = 0; - - // Format 0_1 specific configuration (for PUSCH only) - dci_cfg.nof_ul_bwp = 0; - dci_cfg.nof_ul_time_res = (pusch.nof_dedicated_time_ra > 0) - ? pusch.nof_dedicated_time_ra - : (pusch.nof_common_time_ra > 0) ? pusch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA; - dci_cfg.nof_srs = 1; - dci_cfg.nof_ul_layers = 1; - dci_cfg.pusch_nof_cbg = 0; - dci_cfg.report_trigger_size = 0; - dci_cfg.enable_transform_precoding = false; - dci_cfg.dynamic_dual_harq_ack_codebook = false; - dci_cfg.pusch_tx_config_non_codebook = false; - dci_cfg.pusch_ptrs = false; - dci_cfg.pusch_dynamic_betas = false; - dci_cfg.pusch_alloc_type = pusch.alloc; - dci_cfg.pusch_dmrs_type = pusch.dmrs_type; - dci_cfg.pusch_dmrs_max_len = pusch.dmrs_max_length; - - // Format 1_1 specific configuration (for PDSCH only) - dci_cfg.nof_dl_bwp = 0; - dci_cfg.nof_dl_time_res = (pdsch.nof_dedicated_time_ra > 0) - ? pdsch.nof_dedicated_time_ra - : (pdsch.nof_common_time_ra > 0) ? pdsch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA; - dci_cfg.nof_aperiodic_zp = 0; - dci_cfg.pdsch_nof_cbg = 0; - dci_cfg.nof_dl_to_ul_ack = harq_ack.nof_dl_data_to_ul_ack; - dci_cfg.pdsch_inter_prb_to_prb = false; - dci_cfg.pdsch_rm_pattern1 = false; - dci_cfg.pdsch_rm_pattern2 = false; - dci_cfg.pdsch_2cw = false; - dci_cfg.multiple_scell = false; - dci_cfg.pdsch_tci = false; - dci_cfg.pdsch_cbg_flush = false; - dci_cfg.pdsch_dynamic_bundling = false; - dci_cfg.pdsch_alloc_type = pdsch.alloc; - dci_cfg.pdsch_dmrs_type = pdsch.dmrs_type; - dci_cfg.pdsch_dmrs_max_len = pdsch.dmrs_max_length; - - return dci_cfg; - }; -}; -} // namespace srsran - -#endif // SRSRAN_RRC_NR_INTERFACE_TYPES_H diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index faed69fa2..b59626a48 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -14,8 +14,8 @@ #define SRSRAN_UE_NR_INTERFACES_H #include "srsran/common/interfaces_common.h" +#include "srsran/common/phy_cfg_nr.h" #include "srsran/interfaces/mac_interface_types.h" -#include "srsran/interfaces/rrc_nr_interface_types.h" #include #include #include diff --git a/lib/include/srsran/phy/phch/ra_nr.h b/lib/include/srsran/phy/phch/ra_nr.h index eb008ed1d..4944a42e3 100644 --- a/lib/include/srsran/phy/phch/ra_nr.h +++ b/lib/include/srsran/phy/phch/ra_nr.h @@ -111,6 +111,7 @@ SRSRAN_API int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrie * Note: Only TypeA PUSCH mapping type is supported * * @param carrier Carrier information struct + * @param slot Slot configuration * @param pusch_hl_cfg PUSCH configuration provided by higher layers * @param dci_ul DCI uplink (format 0_0 or 0_1) * @param pusch_cfg PUSCH configuration after applying the procedure @@ -118,6 +119,7 @@ SRSRAN_API int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrie * @return 0 on success, -1 on error */ SRSRAN_API int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrier, + const srsran_slot_cfg_t* slot, const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, const srsran_dci_ul_nr_t* dci_ul, srsran_sch_cfg_nr_t* pusch_cfg, diff --git a/lib/include/srsran/phy/phch/sch_cfg_nr.h b/lib/include/srsran/phy/phch/sch_cfg_nr.h index 8c4d8159c..31c3f5af6 100644 --- a/lib/include/srsran/phy/phch/sch_cfg_nr.h +++ b/lib/include/srsran/phy/phch/sch_cfg_nr.h @@ -28,7 +28,8 @@ typedef struct SRSRAN_API { uint32_t N_L; ///< the number of transmission layers that the transport block is mapped onto uint32_t mcs; ///< Modulation Code Scheme (MCS) for debug and trace purpose int tbs; ///< Payload size, TS 38.212 refers to it as A - double R; ///< Target LDPC rate + double R; ///< Target code rate + double R_prime; ///< Actual code rate int rv; ///< Redundancy version int ndi; ///< New Data Indicator uint32_t nof_re; ///< Number of available resource elements to transmit ULSCH (data) and UCI (control) diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 3c6bf3104..498d7d504 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -22,6 +22,7 @@ set(SOURCES arch_select.cc network_utils.cc mac_pcap_net.cc pcap.c + phy_cfg_nr.cc rlc_pcap.cc s1ap_pcap.cc security.cc diff --git a/lib/src/common/phy_cfg_nr.cc b/lib/src/common/phy_cfg_nr.cc new file mode 100644 index 000000000..115fa81c1 --- /dev/null +++ b/lib/src/common/phy_cfg_nr.cc @@ -0,0 +1,293 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/common/phy_cfg_nr.h" +#include "srsran/srsran.h" + +namespace srsran { + +srsran_dci_cfg_nr_t phy_cfg_nr_t::get_dci_cfg() const + +{ + srsran_dci_cfg_nr_t dci_cfg = {}; + + // Assume BWP bandwidth equals full channel bandwidth + dci_cfg.coreset0_bw = pdcch.coreset_present[0] ? srsran_coreset_get_bw(&pdcch.coreset[0]) : 0; + dci_cfg.bwp_dl_initial_bw = carrier.nof_prb; + dci_cfg.bwp_dl_active_bw = carrier.nof_prb; + dci_cfg.bwp_ul_initial_bw = carrier.nof_prb; + dci_cfg.bwp_ul_active_bw = carrier.nof_prb; + + // Iterate over all SS to select monitoring options + for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; i++) { + // Skip not configured SS + if (not pdcch.search_space_present[i]) { + continue; + } + + // Iterate all configured formats + for (uint32_t j = 0; j < pdcch.search_space[i].nof_formats; j++) { + if (pdcch.search_space[i].type == srsran_search_space_type_common_3 && + pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) { + dci_cfg.monitor_common_0_0 = true; + } else if (pdcch.search_space[i].type == srsran_search_space_type_ue && + pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) { + dci_cfg.monitor_0_0_and_1_0 = true; + } else if (pdcch.search_space[i].type == srsran_search_space_type_ue && + pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_1) { + dci_cfg.monitor_0_1_and_1_1 = true; + } + } + } + + // Set PUSCH parameters + dci_cfg.enable_sul = false; + dci_cfg.enable_hopping = false; + + // Set Format 0_1 and 1_1 parameters + dci_cfg.carrier_indicator_size = 0; + dci_cfg.harq_ack_codebok = harq_ack.harq_ack_codebook; + dci_cfg.nof_rb_groups = 0; + + // Format 0_1 specific configuration (for PUSCH only) + dci_cfg.nof_ul_bwp = 0; + dci_cfg.nof_ul_time_res = (pusch.nof_dedicated_time_ra > 0) + ? pusch.nof_dedicated_time_ra + : (pusch.nof_common_time_ra > 0) ? pusch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA; + dci_cfg.nof_srs = 1; + dci_cfg.nof_ul_layers = 1; + dci_cfg.pusch_nof_cbg = 0; + dci_cfg.report_trigger_size = 0; + dci_cfg.enable_transform_precoding = false; + dci_cfg.dynamic_dual_harq_ack_codebook = false; + dci_cfg.pusch_tx_config_non_codebook = false; + dci_cfg.pusch_ptrs = false; + dci_cfg.pusch_dynamic_betas = false; + dci_cfg.pusch_alloc_type = pusch.alloc; + dci_cfg.pusch_dmrs_type = pusch.dmrs_type; + dci_cfg.pusch_dmrs_max_len = pusch.dmrs_max_length; + + // Format 1_1 specific configuration (for PDSCH only) + dci_cfg.nof_dl_bwp = 0; + dci_cfg.nof_dl_time_res = (pdsch.nof_dedicated_time_ra > 0) + ? pdsch.nof_dedicated_time_ra + : (pdsch.nof_common_time_ra > 0) ? pdsch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA; + dci_cfg.nof_aperiodic_zp = 0; + dci_cfg.pdsch_nof_cbg = 0; + dci_cfg.nof_dl_to_ul_ack = harq_ack.nof_dl_data_to_ul_ack; + dci_cfg.pdsch_inter_prb_to_prb = false; + dci_cfg.pdsch_rm_pattern1 = false; + dci_cfg.pdsch_rm_pattern2 = false; + dci_cfg.pdsch_2cw = false; + dci_cfg.multiple_scell = false; + dci_cfg.pdsch_tci = false; + dci_cfg.pdsch_cbg_flush = false; + dci_cfg.pdsch_dynamic_bundling = false; + dci_cfg.pdsch_alloc_type = pdsch.alloc; + dci_cfg.pdsch_dmrs_type = pdsch.dmrs_type; + dci_cfg.pdsch_dmrs_max_len = pdsch.dmrs_max_length; + + return dci_cfg; +} + +bool phy_cfg_nr_t::assert_ss_id(uint32_t ss_id) const +{ + // Make sure SS access if bounded + if (ss_id > SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE) { + return false; + } + + // Check SS is present + if (not pdcch.search_space_present[ss_id]) { + return false; + } + + // Extract CORESET id + uint32_t coreset_id = pdcch.search_space[ss_id].coreset_id; + + // Make sure CORESET id is bounded + if (coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET) { + return false; + } + + // Check CORESET is present + if (not pdcch.coreset_present[coreset_id]) { + return false; + } + + return true; +} + +bool phy_cfg_nr_t::get_dci_locations( + const uint32_t& slot_idx, + const uint16_t& rnti, + const uint32_t& ss_id, + const uint32_t& L, + srsran::bounded_vector& locations) const +{ + // Assert search space + if (not assert_ss_id(ss_id)) { + return SRSRAN_ERROR; + } + + // Select SS and CORESET + const srsran_search_space_t& ss = pdcch.search_space[ss_id]; + const srsran_coreset_t& coreset = pdcch.coreset[ss.coreset_id]; + + // Compute NCCE + std::array ncce = {}; + int n = srsran_pdcch_nr_locations_coreset(&coreset, &ss, rnti, L, slot_idx, ncce.data()); + if (n < SRSRAN_SUCCESS) { + return false; + } + + // Push locations + for (uint32_t i = 0; i < (uint32_t)n; i++) { + locations.push_back({L, ncce[i]}); + } + + return true; +} + +srsran_dci_format_nr_t phy_cfg_nr_t::get_dci_format_pdsch(uint32_t ss_id) const +{ + // Assert search space + if (not assert_ss_id(ss_id)) { + return SRSRAN_DCI_FORMAT_NR_COUNT; + } + + // Select SS + const srsran_search_space_t& ss = pdcch.search_space[ss_id]; + + // Extract number of formats + uint32_t nof_formats = SRSRAN_MIN(ss.nof_formats, SRSRAN_DCI_FORMAT_NR_COUNT); + + // Select DCI formats + for (uint32_t i = 0; i < nof_formats; i++) { + // Select DL format + if (ss.formats[i] == srsran_dci_format_nr_1_0 or ss.formats[i] == srsran_dci_format_nr_1_1) { + return ss.formats[i]; + } + } + + // If reached here, no valid DCI format is available + return SRSRAN_DCI_FORMAT_NR_COUNT; +} + +srsran_dci_format_nr_t phy_cfg_nr_t::get_dci_format_pusch(uint32_t ss_id) const +{ + // Assert search space + if (not assert_ss_id(ss_id)) { + return SRSRAN_DCI_FORMAT_NR_COUNT; + } + + // Select SS + const srsran_search_space_t& ss = pdcch.search_space[ss_id]; + + // Extract number of formats + uint32_t nof_formats = SRSRAN_MIN(ss.nof_formats, SRSRAN_DCI_FORMAT_NR_COUNT); + + // Select DCI formats + for (uint32_t i = 0; i < nof_formats; i++) { + // Select DL format + if (ss.formats[i] == srsran_dci_format_nr_0_0 or ss.formats[i] == srsran_dci_format_nr_0_1) { + return ss.formats[i]; + } + } + + // If reached here, no valid DCI format is available + return SRSRAN_DCI_FORMAT_NR_COUNT; +} + +bool phy_cfg_nr_t::get_dci_ctx_pdsch_rnti_c(uint32_t ss_id, + const srsran_dci_location_t& location, + const uint16_t& rnti, + srsran_dci_ctx_t& ctx) const +{ + // Get DCI format, includes SS Id assertion + srsran_dci_format_nr_t format = get_dci_format_pdsch(ss_id); + if (format == SRSRAN_DCI_FORMAT_NR_COUNT) { + return false; + } + + // Select search space + const srsran_search_space_t& ss = pdcch.search_space[ss_id]; + + // Fill context + ctx.location = location; + ctx.ss_type = ss.type; + ctx.coreset_id = ss.coreset_id; + ctx.rnti_type = srsran_rnti_type_c; + ctx.format = format; + ctx.rnti = rnti; + + return true; +} + +bool phy_cfg_nr_t::get_dci_ctx_pusch_rnti_c(uint32_t ss_id, + const srsran_dci_location_t& location, + const uint16_t& rnti, + srsran_dci_ctx_t& ctx) const +{ + // Get DCI format, includes SS Id assertion + srsran_dci_format_nr_t format = get_dci_format_pusch(ss_id); + if (format == SRSRAN_DCI_FORMAT_NR_COUNT) { + return false; + } + + // Select search space + const srsran_search_space_t& ss = pdcch.search_space[ss_id]; + + // Fill context + ctx.location = location; + ctx.ss_type = ss.type; + ctx.coreset_id = ss.coreset_id; + ctx.rnti_type = srsran_rnti_type_c; + ctx.format = format; + ctx.rnti = rnti; + + return true; +} + +bool phy_cfg_nr_t::get_pdsch_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_dci_dl_nr_t& dci, + srsran_sch_cfg_nr_t& pdsch_cfg) const +{ + return srsran_ra_dl_dci_to_grant_nr(&carrier, &slot_cfg, &pdsch, &dci, &pdsch_cfg, &pdsch_cfg.grant) == + SRSRAN_SUCCESS; +} + +bool phy_cfg_nr_t::get_pusch_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_dci_ul_nr_t& dci, + srsran_sch_cfg_nr_t& pusch_cfg) const +{ + return srsran_ra_ul_dci_to_grant_nr(&carrier, &slot_cfg, &pusch, &dci, &pusch_cfg, &pusch_cfg.grant) == + SRSRAN_SUCCESS; +} + +bool phy_cfg_nr_t::get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, + srsran_pdsch_ack_resource_nr_t& ack_resource) const +{ + return srsran_ue_dl_nr_pdsch_ack_resource(&harq_ack, &dci_dl, &ack_resource) == SRSRAN_SUCCESS; +} + +bool phy_cfg_nr_t::get_uci_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_pdsch_ack_nr_t& pdsch_ack, + srsran_uci_cfg_nr_t& uci_cfg) const +{ + // TBD + // ... + + return true; +} + +} // namespace srsran \ No newline at end of file diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index 78eb6856f..caa8adb83 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -277,7 +277,7 @@ int srsran_ra_dl_nr_nof_dmrs_cdm_groups_without_data(const srsran_sch_hl_cfg_nr_ ERROR("Unhandled case (%d, %d)", cfg->dmrs_type, cfg->dmrs_max_length); return SRSRAN_ERROR; default: - ERROR("Invalid UL DCI format %s", srsran_dci_format_nr_string(dci->ctx.format)); + ERROR("Invalid DL DCI format %s", srsran_dci_format_nr_string(dci->ctx.format)); } return SRSRAN_ERROR; diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 5e397ebaf..5a7009f33 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -521,6 +521,12 @@ int srsran_ra_nr_fill_tb(const srsran_sch_cfg_nr_t* pdsch_cfg, tb->nof_bits = tb->nof_re * Qm; tb->enabled = true; + // Calculate actual rate + tb->R_prime = 0.0; + if (tb->nof_re != 0) { + tb->R_prime = (double)tb->tbs / (double)tb->nof_bits; + } + return SRSRAN_SUCCESS; } @@ -755,6 +761,7 @@ ra_ul_dmrs(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, const srsran_dci_ul_nr_t* } int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrier, + const srsran_slot_cfg_t* slot_cfg, const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, const srsran_dci_ul_nr_t* dci_ul, srsran_sch_cfg_nr_t* pusch_cfg, diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index fbac9a8e8..356e13232 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -83,7 +83,7 @@ public: /// Semaphore for aligning UL work srsran::tti_semaphore dl_ul_semaphore; - uint32_t rar_grant_tti = 0; + srsran_slot_cfg_t rar_grant_slot = {}; state() { @@ -96,14 +96,14 @@ public: /** * @brief Stores a received UL DCI into the pending UL grant list - * @param tti_rx The TTI in which the grant was received + * @param slot_rx The TTI in which the grant was received * @param dci_ul The UL DCI message to store */ - void set_ul_pending_grant(uint32_t tti_rx, const srsran_dci_ul_nr_t& dci_ul) + void set_ul_pending_grant(const srsran_slot_cfg_t& slot_rx, const srsran_dci_ul_nr_t& dci_ul) { // Convert UL DCI to grant srsran_sch_cfg_nr_t pusch_cfg = {}; - if (srsran_ra_ul_dci_to_grant_nr(&cfg.carrier, &cfg.pusch, &dci_ul, &pusch_cfg, &pusch_cfg.grant)) { + if (not cfg.get_pusch_cfg(slot_rx, dci_ul, pusch_cfg)) { std::array str; srsran_dci_ul_nr_to_str(NULL, &dci_ul, str.data(), str.size()); ERROR("Computing UL grant %s", str.data()); @@ -111,7 +111,7 @@ public: } // Calculate Transmit TTI - uint32_t tti_tx = TTI_ADD(tti_rx, pusch_cfg.grant.k); + uint32_t tti_tx = TTI_ADD(slot_rx.idx, pusch_cfg.grant.k); // Scope mutex to protect read/write the list std::lock_guard lock(pending_ul_grant_mutex); @@ -162,14 +162,17 @@ public: { // Convert DL DCI to grant srsran_sch_cfg_nr_t pdsch_cfg = {}; - if (srsran_ra_dl_dci_to_grant_nr(&cfg.carrier, &slot, &cfg.pdsch, &dci_dl, &pdsch_cfg, &pdsch_cfg.grant)) { - ERROR("Computing UL grant"); + + if (not cfg.get_pdsch_cfg(slot, dci_dl, pdsch_cfg)) { + std::array str; + srsran_dci_dl_nr_to_str(NULL, &dci_dl, str.data(), str.size()); + ERROR("Computing DL grant %s", str.data()); return; } // Calculate DL DCI to PDSCH ACK resource srsran_pdsch_ack_resource_nr_t ack_resource = {}; - if (srsran_ue_dl_nr_pdsch_ack_resource(&cfg.harq_ack, &dci_dl, &ack_resource) < SRSRAN_SUCCESS) { + if (not cfg.get_pdsch_ack_resource(dci_dl, ack_resource)) { ERROR("Computing UL ACK resource"); return; } diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 0fa3c1bbf..46c6cdead 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -18,9 +18,7 @@ namespace srsue { namespace nr { cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& log, state& phy_state_) : - cc_idx(cc_idx_), - phy(phy_state_), - logger(log) + cc_idx(cc_idx_), phy(phy_state_), logger(log) { cf_t* rx_buffer_c[SRSRAN_MAX_PORTS] = {}; @@ -221,7 +219,7 @@ void cc_worker::decode_pdcch_ul() } // Enqueue UL grants - phy.set_ul_pending_grant(dl_slot_cfg.idx, dci_rx[i]); + phy.set_ul_pending_grant(dl_slot_cfg, dci_rx[i]); } } @@ -314,7 +312,7 @@ bool cc_worker::decode_pdsch_dl() phy.stack->tb_decoded(cc_idx, mac_dl_grant, std::move(mac_dl_result)); if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_ra) { - phy.rar_grant_tti = dl_slot_cfg.idx; + phy.rar_grant_slot = dl_slot_cfg; } if (pdsch_res.tb[0].crc) { diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index 9ac4daede..13cb11983 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -118,11 +118,11 @@ int worker_pool::set_ul_grant(std::array pac if (logger.info.enabled()) { std::array str; srsran_dci_ul_nr_to_str(NULL, &dci_ul, str.data(), str.size()); - logger.set_context(phy_state.rar_grant_tti); + logger.set_context(phy_state.rar_grant_slot.idx); logger.info("Setting RAR Grant %s", str.data()); } - phy_state.set_ul_pending_grant(phy_state.rar_grant_tti, dci_ul); + phy_state.set_ul_pending_grant(phy_state.rar_grant_slot, dci_ul); return SRSRAN_SUCCESS; } diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 8162dcac4..155d1cb7c 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -14,8 +14,8 @@ #define SRSRAN_DUMMY_GNB_STACK_H #include +#include #include -#include class gnb_dummy_stack : public srsenb::stack_interface_phy_nr { @@ -26,7 +26,7 @@ private: srsran::circular_array dci_dl_location; srsran::circular_array dci_ul_location; srsran::circular_array dl_data_to_ul_ack; - srsran_search_space_t ss = {}; + uint32_t ss_id = 0; srsran_dci_format_nr_t dci_format_ul = SRSRAN_DCI_FORMAT_NR_COUNT; srsran_dci_format_nr_t dci_format_dl = SRSRAN_DCI_FORMAT_NR_COUNT; uint32_t dl_freq_res = 0; @@ -70,82 +70,45 @@ public: uint32_t dl_time_res = 0; ///< PDSCH time resource }; - gnb_dummy_stack(args_t args) : mcs(args.mcs), rnti(args.rnti), dl_time_res(args.dl_time_res), phy_cfg(args.phy_cfg) + gnb_dummy_stack(args_t args) : + mcs(args.mcs), rnti(args.rnti), dl_time_res(args.dl_time_res), phy_cfg(args.phy_cfg), ss_id(args.ss_id) { random_gen = srsran_random_init(0x1234); - // Select search space - if (args.ss_id >= SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE) { - logger.error("Search Space Id (%d) is out-of-range (%d)", args.ss_id, SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE); - return; - } - if (not args.phy_cfg.pdcch.search_space_present[args.ss_id]) { - logger.error("Search Space Id (%d) is not present", args.ss_id); - return; - } - ss = args.phy_cfg.pdcch.search_space[args.ss_id]; - - // Select CORESET - if (ss.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET) { - logger.error("CORESET Id (%d) is out-of-range (%d)", ss.coreset_id, SRSRAN_UE_DL_NR_MAX_NOF_CORESET); - return; - } - if (not args.phy_cfg.pdcch.coreset_present[ss.coreset_id]) { - logger.error("CORESET Id (%d) is not present", args.ss_id); - return; - } - const srsran_coreset_t& coreset = args.phy_cfg.pdcch.coreset[ss.coreset_id]; - // Select DCI locations for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) { - std::array ncce = {}; - int n = srsran_pdcch_nr_locations_coreset(&coreset, &ss, rnti, args.pdcch_aggregation_level, slot++, ncce.data()); - if (n < SRSRAN_SUCCESS) { + srsran::bounded_vector locations; + + if (not phy_cfg.get_dci_locations(slot, rnti, args.ss_id, args.pdcch_aggregation_level, locations)) { logger.error( "Error generating locations for slot %d and aggregation level %d", slot, args.pdcch_aggregation_level); return; } - uint32_t nof_candidates = (uint32_t)n; // DCI DL - if (args.pdcch_dl_candidate_index >= nof_candidates or - args.pdcch_dl_candidate_index >= SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR) { + if (args.pdcch_dl_candidate_index >= locations.size()) { logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", args.pdcch_dl_candidate_index, - n, + (uint32_t)locations.size(), args.pdcch_aggregation_level); return; } - dci_dl_location[slot].L = args.pdcch_aggregation_level; - dci_dl_location[slot].ncce = ncce[args.pdcch_dl_candidate_index]; + dci_dl_location[slot] = locations[args.pdcch_dl_candidate_index]; // DCI UL - if (args.pdcch_ul_candidate_index >= nof_candidates or - args.pdcch_ul_candidate_index >= SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR) { + if (args.pdcch_ul_candidate_index >= locations.size()) { logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", args.pdcch_ul_candidate_index, - n, + (uint32_t)locations.size(), args.pdcch_aggregation_level); return; } - dci_ul_location[slot].L = args.pdcch_aggregation_level; - dci_ul_location[slot].ncce = ncce[args.pdcch_ul_candidate_index]; + dci_ul_location[slot] = locations[args.pdcch_ul_candidate_index]; } // Select DCI formats - for (uint32_t i = 0; i < ss.nof_formats; i++) { - // Select DL format - if (ss.formats[i] == srsran_dci_format_nr_1_0 or ss.formats[i] == srsran_dci_format_nr_1_1) { - dci_format_dl = ss.formats[i]; - } - - // Select DL format - if (ss.formats[i] == srsran_dci_format_nr_0_0 or ss.formats[i] == srsran_dci_format_nr_0_1) { - dci_format_ul = ss.formats[i]; - } - } - - // Validate that a DCI format is selected + dci_format_dl = phy_cfg.get_dci_format_pdsch(args.ss_id); + dci_format_ul = phy_cfg.get_dci_format_pusch(args.ss_id); if (dci_format_dl == SRSRAN_DCI_FORMAT_NR_COUNT or dci_format_ul == SRSRAN_DCI_FORMAT_NR_COUNT) { logger.error("Missing valid DL or UL DCI format in search space"); return; @@ -190,14 +153,14 @@ public: // Fill DCI configuration pdcch.dci_cfg = phy_cfg.get_dci_cfg(); - // Fill DCI + // Fill DCI context + if (not phy_cfg.get_dci_ctx_pdsch_rnti_c(ss_id, dci_dl_location[slot_cfg.idx], rnti, pdcch.dci.ctx)) { + logger.error("Error filling PDSCH DCI context"); + return SRSRAN_ERROR; + } + + // Fill DCI fields srsran_dci_dl_nr_t& dci = pdcch.dci; - dci.ctx.location = dci_dl_location[slot_cfg.idx]; - dci.ctx.ss_type = ss.type; - dci.ctx.coreset_id = ss.coreset_id; - dci.ctx.rnti_type = srsran_rnti_type_c; - dci.ctx.format = dci_format_dl; - dci.ctx.rnti = rnti; dci.freq_domain_assigment = dl_freq_res; dci.time_domain_assigment = dl_time_res; dci.mcs = mcs; @@ -210,8 +173,7 @@ public: dci.harq_feedback = dl_data_to_ul_ack[TTI_TX(slot_cfg.idx)]; // Create PDSCH configuration - if (srsran_ra_dl_dci_to_grant_nr(&phy_cfg.carrier, &slot_cfg, &phy_cfg.pdsch, &dci, &pdsch.sch, &pdsch.sch.grant) < - SRSRAN_SUCCESS) { + if (not phy_cfg.get_pdsch_cfg(slot_cfg, dci, pdsch.sch)) { logger.error("Error converting DCI to grant"); return SRSRAN_ERROR; } diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_dl_flood.cc index 26c5bd04e..a6428b553 100644 --- a/test/phy/nr_dl_flood.cc +++ b/test/phy/nr_dl_flood.cc @@ -67,8 +67,8 @@ test_bench::args_t::args_t(int argc, char** argv) phy_cfg.pdcch.search_space[1].nof_candidates[2] = 1; phy_cfg.pdcch.search_space[1].nof_candidates[3] = 0; phy_cfg.pdcch.search_space[1].nof_candidates[4] = 0; - phy_cfg.pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; - phy_cfg.pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; + phy_cfg.pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; // DCI format for PUSCH + phy_cfg.pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; // DCI format for PDSCH phy_cfg.pdcch.search_space[1].nof_formats = 2; phy_cfg.pdcch.search_space[1].type = srsran_search_space_type_common_3; @@ -81,8 +81,8 @@ test_bench::args_t::args_t(int argc, char** argv) phy_cfg.pdcch.search_space[2].nof_candidates[2] = 1; phy_cfg.pdcch.search_space[2].nof_candidates[3] = 0; phy_cfg.pdcch.search_space[2].nof_candidates[4] = 0; - phy_cfg.pdcch.search_space[2].formats[0] = srsran_dci_format_nr_0_0; - phy_cfg.pdcch.search_space[2].formats[1] = srsran_dci_format_nr_1_0; + phy_cfg.pdcch.search_space[2].formats[0] = srsran_dci_format_nr_0_1; + phy_cfg.pdcch.search_space[2].formats[1] = srsran_dci_format_nr_1_1; phy_cfg.pdcch.search_space[2].nof_formats = 2; phy_cfg.pdcch.search_space[2].type = srsran_search_space_type_ue; From f6fc2155415b7fd05aaff6a9876d4b4018a0c641 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 28 Jun 2021 17:03:34 +0200 Subject: [PATCH 18/50] Refactored enb_dl_nr to gnb_dl and initial gnb_ul --- lib/include/srsran/phy/enb/enb_dl_nr.h | 82 --------- lib/include/srsran/phy/gnb/gnb_dl.h | 79 ++++++++ lib/include/srsran/phy/gnb/gnb_ul.h | 61 +++++++ lib/include/srsran/phy/phch/pusch_nr.h | 2 +- lib/include/srsran/srsran.h | 2 +- lib/src/phy/CMakeLists.txt | 2 + lib/src/phy/gnb/CMakeLists.txt | 10 ++ lib/src/phy/{enb/enb_dl_nr.c => gnb/gnb_dl.c} | 63 +++---- lib/src/phy/gnb/gnb_ul.c | 169 ++++++++++++++++++ lib/src/phy/phch/pusch_nr.c | 4 +- lib/src/phy/phch/test/pusch_nr_test.c | 4 +- lib/test/phy/phy_dl_nr_test.c | 34 ++-- srsenb/hdr/phy/nr/slot_worker.h | 2 +- srsenb/src/phy/nr/slot_worker.cc | 42 ++--- 14 files changed, 391 insertions(+), 165 deletions(-) delete mode 100644 lib/include/srsran/phy/enb/enb_dl_nr.h create mode 100644 lib/include/srsran/phy/gnb/gnb_dl.h create mode 100644 lib/include/srsran/phy/gnb/gnb_ul.h create mode 100644 lib/src/phy/gnb/CMakeLists.txt rename lib/src/phy/{enb/enb_dl_nr.c => gnb/gnb_dl.c} (70%) create mode 100644 lib/src/phy/gnb/gnb_ul.c diff --git a/lib/include/srsran/phy/enb/enb_dl_nr.h b/lib/include/srsran/phy/enb/enb_dl_nr.h deleted file mode 100644 index edc7c8ac5..000000000 --- a/lib/include/srsran/phy/enb/enb_dl_nr.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSRAN_ENB_DL_NR_H -#define SRSRAN_ENB_DL_NR_H - -#include "srsran/phy/common/phy_common_nr.h" -#include "srsran/phy/dft/ofdm.h" -#include "srsran/phy/phch/pdcch_cfg_nr.h" -#include "srsran/phy/phch/pdcch_nr.h" -#include "srsran/phy/phch/pdsch_nr.h" - -typedef struct SRSRAN_API { - srsran_pdsch_nr_args_t pdsch; - srsran_pdcch_nr_args_t pdcch; - uint32_t nof_tx_antennas; - uint32_t nof_max_prb; -} srsran_enb_dl_nr_args_t; - -typedef struct SRSRAN_API { - uint32_t max_prb; - uint32_t nof_tx_antennas; - srsran_carrier_nr_t carrier; - srsran_pdcch_cfg_nr_t pdcch_cfg; - - srsran_ofdm_t fft[SRSRAN_MAX_PORTS]; - - cf_t* sf_symbols[SRSRAN_MAX_PORTS]; - srsran_pdsch_nr_t pdsch; - srsran_dmrs_sch_t dmrs; - - srsran_dci_nr_t dci; ///< Stores DCI configuration - srsran_pdcch_nr_t pdcch; -} srsran_enb_dl_nr_t; - -SRSRAN_API int -srsran_enb_dl_nr_init(srsran_enb_dl_nr_t* q, cf_t* output[SRSRAN_MAX_PORTS], const srsran_enb_dl_nr_args_t* args); - -SRSRAN_API int srsran_enb_dl_nr_set_carrier(srsran_enb_dl_nr_t* q, const srsran_carrier_nr_t* carrier); - -SRSRAN_API int srsran_enb_dl_nr_set_pdcch_config(srsran_enb_dl_nr_t* q, - const srsran_pdcch_cfg_nr_t* cfg, - const srsran_dci_cfg_nr_t* dci_cfg); - -SRSRAN_API void srsran_enb_dl_nr_free(srsran_enb_dl_nr_t* q); - -SRSRAN_API int srsran_enb_dl_nr_base_zero(srsran_enb_dl_nr_t* q); - -SRSRAN_API void srsran_enb_dl_nr_gen_signal(srsran_enb_dl_nr_t* q); - -SRSRAN_API int srsran_enb_dl_nr_pdcch_put_dl(srsran_enb_dl_nr_t* q, - const srsran_slot_cfg_t* slot_cfg, - const srsran_dci_dl_nr_t* dci_dl); - -SRSRAN_API int srsran_enb_dl_nr_pdcch_put_ul(srsran_enb_dl_nr_t* q, - const srsran_slot_cfg_t* slot_cfg, - const srsran_dci_ul_nr_t* dci_ul); - -SRSRAN_API int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q, - const srsran_slot_cfg_t* slot, - const srsran_sch_cfg_nr_t* cfg, - uint8_t* data[SRSRAN_MAX_TB]); - -SRSRAN_API int -srsran_enb_dl_nr_pdsch_info(const srsran_enb_dl_nr_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len); - -SRSRAN_API int -srsran_enb_dl_nr_pdcch_dl_info(const srsran_enb_dl_nr_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len); - -SRSRAN_API int -srsran_enb_dl_nr_pdcch_ul_info(const srsran_enb_dl_nr_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len); - -#endif // SRSRAN_ENB_DL_NR_H diff --git a/lib/include/srsran/phy/gnb/gnb_dl.h b/lib/include/srsran/phy/gnb/gnb_dl.h new file mode 100644 index 000000000..680fdacbe --- /dev/null +++ b/lib/include/srsran/phy/gnb/gnb_dl.h @@ -0,0 +1,79 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_GNB_DL_H +#define SRSRAN_GNB_DL_H + +#include "srsran/phy/common/phy_common_nr.h" +#include "srsran/phy/dft/ofdm.h" +#include "srsran/phy/phch/pdcch_cfg_nr.h" +#include "srsran/phy/phch/pdcch_nr.h" +#include "srsran/phy/phch/pdsch_nr.h" + +typedef struct SRSRAN_API { + srsran_pdsch_nr_args_t pdsch; + srsran_pdcch_nr_args_t pdcch; + uint32_t nof_tx_antennas; + uint32_t nof_max_prb; +} srsran_gnb_dl_args_t; + +typedef struct SRSRAN_API { + uint32_t max_prb; + uint32_t nof_tx_antennas; + srsran_carrier_nr_t carrier; + srsran_pdcch_cfg_nr_t pdcch_cfg; + + srsran_ofdm_t fft[SRSRAN_MAX_PORTS]; + + cf_t* sf_symbols[SRSRAN_MAX_PORTS]; + srsran_pdsch_nr_t pdsch; + srsran_dmrs_sch_t dmrs; + + srsran_dci_nr_t dci; ///< Stores DCI configuration + srsran_pdcch_nr_t pdcch; +} srsran_gnb_dl_t; + +SRSRAN_API int srsran_gnb_dl_init(srsran_gnb_dl_t* q, cf_t* output[SRSRAN_MAX_PORTS], const srsran_gnb_dl_args_t* args); + +SRSRAN_API int srsran_gnb_dl_set_carrier(srsran_gnb_dl_t* q, const srsran_carrier_nr_t* carrier); + +SRSRAN_API int srsran_gnb_dl_set_pdcch_config(srsran_gnb_dl_t* q, + const srsran_pdcch_cfg_nr_t* cfg, + const srsran_dci_cfg_nr_t* dci_cfg); + +SRSRAN_API void srsran_gnb_dl_free(srsran_gnb_dl_t* q); + +SRSRAN_API int srsran_gnb_dl_base_zero(srsran_gnb_dl_t* q); + +SRSRAN_API void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q); + +SRSRAN_API int +srsran_gnb_dl_pdcch_put_dl(srsran_gnb_dl_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_dl_nr_t* dci_dl); + +SRSRAN_API int +srsran_gnb_dl_pdcch_put_ul(srsran_gnb_dl_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_ul_nr_t* dci_ul); + +SRSRAN_API int srsran_gnb_dl_pdsch_put(srsran_gnb_dl_t* q, + const srsran_slot_cfg_t* slot, + const srsran_sch_cfg_nr_t* cfg, + uint8_t* data[SRSRAN_MAX_TB]); + +SRSRAN_API int +srsran_gnb_dl_pdsch_info(const srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len); + +SRSRAN_API int +srsran_gnb_dl_pdcch_dl_info(const srsran_gnb_dl_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len); + +SRSRAN_API int +srsran_gnb_dl_pdcch_ul_info(const srsran_gnb_dl_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len); + +#endif // SRSRAN_GNB_DL_H diff --git a/lib/include/srsran/phy/gnb/gnb_ul.h b/lib/include/srsran/phy/gnb/gnb_ul.h new file mode 100644 index 000000000..7fa392c17 --- /dev/null +++ b/lib/include/srsran/phy/gnb/gnb_ul.h @@ -0,0 +1,61 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_GNB_UL_H +#define SRSRAN_GNB_UL_H + +#include "srsran/phy/common/phy_common_nr.h" +#include "srsran/phy/dft/ofdm.h" +#include "srsran/phy/phch/pucch_nr.h" +#include "srsran/phy/phch/pusch_nr.h" + +typedef struct SRSRAN_API { + srsran_pusch_nr_args_t pusch; + srsran_pucch_nr_args_t pucch; + uint32_t nof_max_prb; +} srsran_gnb_ul_args_t; + +typedef struct SRSRAN_API { + uint32_t max_prb; + srsran_carrier_nr_t carrier; + + srsran_ofdm_t fft; + + cf_t* sf_symbols[SRSRAN_MAX_PORTS]; + srsran_pusch_nr_t pusch; + srsran_pucch_nr_t pucch; + srsran_dmrs_sch_t dmrs; + srsran_chest_dl_res_t chest; +} srsran_gnb_ul_t; + +SRSRAN_API int srsran_gnb_ul_init(srsran_gnb_ul_t* q, cf_t* input, const srsran_gnb_ul_args_t* args); + +SRSRAN_API void srsran_gnb_ul_free(srsran_gnb_ul_t* q); + +SRSRAN_API int srsran_gnb_ul_set_carrier(srsran_gnb_ul_t* q, const srsran_carrier_nr_t* carrier); + +SRSRAN_API int srsran_gnb_ul_fft(srsran_gnb_ul_t* q); + +SRSRAN_API int srsran_gnb_ul_get_pusch(srsran_gnb_ul_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_sch_cfg_nr_t* cfg, + const srsran_sch_grant_nr_t* grant, + srsran_pusch_res_nr_t* data); + +SRSRAN_API int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_pucch_nr_common_cfg_t* cfg, + const srsran_pucch_nr_resource_t* resource, + const srsran_uci_cfg_nr_t* uci_cfg, + srsran_uci_value_nr_t* uci_value); + +#endif // SRSRAN_GNB_UL_H diff --git a/lib/include/srsran/phy/phch/pusch_nr.h b/lib/include/srsran/phy/phch/pusch_nr.h index f917dd195..146831a12 100644 --- a/lib/include/srsran/phy/phch/pusch_nr.h +++ b/lib/include/srsran/phy/phch/pusch_nr.h @@ -104,7 +104,7 @@ SRSRAN_API int srsran_pusch_nr_decode(srsran_pusch_nr_t* q, const srsran_sch_grant_nr_t* grant, srsran_chest_dl_res_t* channel, cf_t* sf_symbols[SRSRAN_MAX_PORTS], - srsran_pusch_res_nr_t* data[SRSRAN_MAX_TB]); + srsran_pusch_res_nr_t* data); SRSRAN_API uint32_t srsran_pusch_nr_rx_info(const srsran_pusch_nr_t* q, const srsran_sch_cfg_nr_t* cfg, diff --git a/lib/include/srsran/srsran.h b/lib/include/srsran/srsran.h index b3bfd641f..0e379a2dc 100644 --- a/lib/include/srsran/srsran.h +++ b/lib/include/srsran/srsran.h @@ -116,8 +116,8 @@ extern "C" { #include "srsran/phy/ue/ue_ul_nr.h" #include "srsran/phy/enb/enb_dl.h" -#include "srsran/phy/enb/enb_dl_nr.h" #include "srsran/phy/enb/enb_ul.h" +#include "srsran/phy/gnb/gnb_dl.h" #include "srsran/phy/scrambling/scrambling.h" diff --git a/lib/src/phy/CMakeLists.txt b/lib/src/phy/CMakeLists.txt index 8c166ba89..66018f1dc 100644 --- a/lib/src/phy/CMakeLists.txt +++ b/lib/src/phy/CMakeLists.txt @@ -23,6 +23,7 @@ add_subdirectory(resampling) add_subdirectory(scrambling) add_subdirectory(ue) add_subdirectory(enb) +add_subdirectory(gnb) set(srsran_srcs $ $ $ @@ -39,6 +40,7 @@ set(srsran_srcs $ $ $ $ + $ ) add_library(srsran_phy STATIC ${srsran_srcs} ) diff --git a/lib/src/phy/gnb/CMakeLists.txt b/lib/src/phy/gnb/CMakeLists.txt new file mode 100644 index 000000000..a4950c24b --- /dev/null +++ b/lib/src/phy/gnb/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright 2013-2021 Software Radio Systems Limited +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the distribution. +# + +file(GLOB SOURCES "*.c") +add_library(srsran_gnb OBJECT ${SOURCES}) diff --git a/lib/src/phy/enb/enb_dl_nr.c b/lib/src/phy/gnb/gnb_dl.c similarity index 70% rename from lib/src/phy/enb/enb_dl_nr.c rename to lib/src/phy/gnb/gnb_dl.c index f98cc411c..0f83f0233 100644 --- a/lib/src/phy/enb/enb_dl_nr.c +++ b/lib/src/phy/gnb/gnb_dl.c @@ -10,10 +10,10 @@ * */ -#include "srsran/phy/enb/enb_dl_nr.h" +#include "srsran/phy/gnb/gnb_dl.h" #include -static int enb_dl_alloc_prb(srsran_enb_dl_nr_t* q, uint32_t new_nof_prb) +static int gnb_dl_alloc_prb(srsran_gnb_dl_t* q, uint32_t new_nof_prb) { if (q->max_prb < new_nof_prb) { q->max_prb = new_nof_prb; @@ -34,7 +34,7 @@ static int enb_dl_alloc_prb(srsran_enb_dl_nr_t* q, uint32_t new_nof_prb) return SRSRAN_SUCCESS; } -int srsran_enb_dl_nr_init(srsran_enb_dl_nr_t* q, cf_t* output[SRSRAN_MAX_PORTS], const srsran_enb_dl_nr_args_t* args) +int srsran_gnb_dl_init(srsran_gnb_dl_t* q, cf_t* output[SRSRAN_MAX_PORTS], const srsran_gnb_dl_args_t* args) { if (!q || !output || !args) { return SRSRAN_ERROR_INVALID_INPUTS; @@ -51,7 +51,7 @@ int srsran_enb_dl_nr_init(srsran_enb_dl_nr_t* q, cf_t* output[SRSRAN_MAX_PORTS], return SRSRAN_ERROR; } - if (enb_dl_alloc_prb(q, args->nof_max_prb) < SRSRAN_SUCCESS) { + if (gnb_dl_alloc_prb(q, args->nof_max_prb) < SRSRAN_SUCCESS) { ERROR("Error allocating"); return SRSRAN_ERROR; } @@ -80,7 +80,7 @@ int srsran_enb_dl_nr_init(srsran_enb_dl_nr_t* q, cf_t* output[SRSRAN_MAX_PORTS], return SRSRAN_SUCCESS; } -void srsran_enb_dl_nr_free(srsran_enb_dl_nr_t* q) +void srsran_gnb_dl_free(srsran_gnb_dl_t* q) { if (q == NULL) { return; @@ -99,10 +99,10 @@ void srsran_enb_dl_nr_free(srsran_enb_dl_nr_t* q) srsran_pdcch_nr_free(&q->pdcch); - SRSRAN_MEM_ZERO(q, srsran_enb_dl_nr_t, 1); + SRSRAN_MEM_ZERO(q, srsran_gnb_dl_t, 1); } -int srsran_enb_dl_nr_set_carrier(srsran_enb_dl_nr_t* q, const srsran_carrier_nr_t* carrier) +int srsran_gnb_dl_set_carrier(srsran_gnb_dl_t* q, const srsran_carrier_nr_t* carrier) { if (srsran_pdsch_nr_set_carrier(&q->pdsch, carrier) < SRSRAN_SUCCESS) { return SRSRAN_ERROR; @@ -113,7 +113,7 @@ int srsran_enb_dl_nr_set_carrier(srsran_enb_dl_nr_t* q, const srsran_carrier_nr_ return SRSRAN_ERROR; } - if (enb_dl_alloc_prb(q, carrier->nof_prb) < SRSRAN_SUCCESS) { + if (gnb_dl_alloc_prb(q, carrier->nof_prb) < SRSRAN_SUCCESS) { ERROR("Error allocating"); return SRSRAN_ERROR; } @@ -135,9 +135,9 @@ int srsran_enb_dl_nr_set_carrier(srsran_enb_dl_nr_t* q, const srsran_carrier_nr_ return SRSRAN_SUCCESS; } -int srsran_enb_dl_nr_set_pdcch_config(srsran_enb_dl_nr_t* q, - const srsran_pdcch_cfg_nr_t* cfg, - const srsran_dci_cfg_nr_t* dci_cfg) +int srsran_gnb_dl_set_pdcch_config(srsran_gnb_dl_t* q, + const srsran_pdcch_cfg_nr_t* cfg, + const srsran_dci_cfg_nr_t* dci_cfg) { if (q == NULL || cfg == NULL) { return SRSRAN_ERROR_INVALID_INPUTS; @@ -156,7 +156,7 @@ int srsran_enb_dl_nr_set_pdcch_config(srsran_enb_dl_nr_t* q, return SRSRAN_SUCCESS; } -void srsran_enb_dl_nr_gen_signal(srsran_enb_dl_nr_t* q) +void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q) { if (q == NULL) { return; @@ -167,7 +167,7 @@ void srsran_enb_dl_nr_gen_signal(srsran_enb_dl_nr_t* q) } } -int srsran_enb_dl_nr_base_zero(srsran_enb_dl_nr_t* q) +int srsran_gnb_dl_base_zero(srsran_gnb_dl_t* q) { if (q == NULL) { return SRSRAN_ERROR_INVALID_INPUTS; @@ -181,7 +181,7 @@ int srsran_enb_dl_nr_base_zero(srsran_enb_dl_nr_t* q) } static int -enb_dl_nr_pdcch_put_msg(srsran_enb_dl_nr_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_msg_nr_t* dci_msg) +gnb_dl_pdcch_put_msg(srsran_gnb_dl_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_msg_nr_t* dci_msg) { if (dci_msg->ctx.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET || !q->pdcch_cfg.coreset_present[dci_msg->ctx.coreset_id]) { @@ -213,9 +213,7 @@ enb_dl_nr_pdcch_put_msg(srsran_enb_dl_nr_t* q, const srsran_slot_cfg_t* slot_cfg return SRSRAN_SUCCESS; } -int srsran_enb_dl_nr_pdcch_put_dl(srsran_enb_dl_nr_t* q, - const srsran_slot_cfg_t* slot_cfg, - const srsran_dci_dl_nr_t* dci_dl) +int srsran_gnb_dl_pdcch_put_dl(srsran_gnb_dl_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_dl_nr_t* dci_dl) { if (q == NULL || slot_cfg == NULL || dci_dl == NULL) { return SRSRAN_ERROR_INVALID_INPUTS; @@ -230,12 +228,10 @@ int srsran_enb_dl_nr_pdcch_put_dl(srsran_enb_dl_nr_t* q, INFO("DCI DL NR: L=%d; ncce=%d;", dci_dl->ctx.location.L, dci_dl->ctx.location.ncce); - return enb_dl_nr_pdcch_put_msg(q, slot_cfg, &dci_msg); + return gnb_dl_pdcch_put_msg(q, slot_cfg, &dci_msg); } -int srsran_enb_dl_nr_pdcch_put_ul(srsran_enb_dl_nr_t* q, - const srsran_slot_cfg_t* slot_cfg, - const srsran_dci_ul_nr_t* dci_ul) +int srsran_gnb_dl_pdcch_put_ul(srsran_gnb_dl_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_ul_nr_t* dci_ul) { if (q == NULL || slot_cfg == NULL || dci_ul == NULL) { return SRSRAN_ERROR_INVALID_INPUTS; @@ -250,13 +246,13 @@ int srsran_enb_dl_nr_pdcch_put_ul(srsran_enb_dl_nr_t* q, INFO("DCI DL NR: L=%d; ncce=%d;", dci_ul->ctx.location.L, dci_ul->ctx.location.ncce); - return enb_dl_nr_pdcch_put_msg(q, slot_cfg, &dci_msg); + return gnb_dl_pdcch_put_msg(q, slot_cfg, &dci_msg); } -int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q, - const srsran_slot_cfg_t* slot, - const srsran_sch_cfg_nr_t* cfg, - uint8_t* data[SRSRAN_MAX_TB]) +int srsran_gnb_dl_pdsch_put(srsran_gnb_dl_t* q, + const srsran_slot_cfg_t* slot, + const srsran_sch_cfg_nr_t* cfg, + uint8_t* data[SRSRAN_MAX_TB]) { if (srsran_dmrs_sch_put_sf(&q->dmrs, slot, cfg, &cfg->grant, q->sf_symbols[0]) < SRSRAN_SUCCESS) { return SRSRAN_ERROR; @@ -269,10 +265,7 @@ int srsran_enb_dl_nr_pdsch_put(srsran_enb_dl_nr_t* q, return SRSRAN_SUCCESS; } -int srsran_enb_dl_nr_pdsch_info(const srsran_enb_dl_nr_t* q, - const srsran_sch_cfg_nr_t* cfg, - char* str, - uint32_t str_len) +int srsran_gnb_dl_pdsch_info(const srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len) { int len = 0; @@ -282,10 +275,7 @@ int srsran_enb_dl_nr_pdsch_info(const srsran_enb_dl_nr_t* q, return len; } -int srsran_enb_dl_nr_pdcch_dl_info(const srsran_enb_dl_nr_t* q, - const srsran_dci_dl_nr_t* dci, - char* str, - uint32_t str_len) +int srsran_gnb_dl_pdcch_dl_info(const srsran_gnb_dl_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len) { int len = 0; @@ -295,10 +285,7 @@ int srsran_enb_dl_nr_pdcch_dl_info(const srsran_enb_dl_nr_t* q, return len; } -int srsran_enb_dl_nr_pdcch_ul_info(const srsran_enb_dl_nr_t* q, - const srsran_dci_ul_nr_t* dci, - char* str, - uint32_t str_len) +int srsran_gnb_dl_pdcch_ul_info(const srsran_gnb_dl_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len) { int len = 0; diff --git a/lib/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c new file mode 100644 index 000000000..616dae751 --- /dev/null +++ b/lib/src/phy/gnb/gnb_ul.c @@ -0,0 +1,169 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/phy/gnb/gnb_ul.h" + +/** + * @brief Shifts FFT window a fraction of the cyclic prefix. Set to 0.0f for disabling. + * @note Increases protection against inter-symbol interference in case of synchronization error in expense of computing + * performance + */ +#define GNB_UL_NR_FFT_WINDOW_OFFSET 0.5f + +static int gnb_ul_alloc_prb(srsran_gnb_ul_t* q, uint32_t new_nof_prb) +{ + if (q->max_prb < new_nof_prb) { + q->max_prb = new_nof_prb; + + srsran_chest_dl_res_free(&q->chest); + if (srsran_chest_dl_res_init(&q->chest, q->max_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (q->sf_symbols[0] != NULL) { + free(q->sf_symbols[0]); + } + + q->sf_symbols[0] = srsran_vec_cf_malloc(SRSRAN_SLOT_LEN_RE_NR(q->max_prb)); + if (q->sf_symbols[0] == NULL) { + ERROR("Malloc"); + return SRSRAN_ERROR; + } + } + + return SRSRAN_SUCCESS; +} + +int srsran_gnb_ul_init(srsran_gnb_ul_t* q, cf_t* input, const srsran_gnb_ul_args_t* args) +{ + if (q == NULL || args == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + if (gnb_ul_alloc_prb(q, args->nof_max_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (srsran_pusch_nr_init_gnb(&q->pusch, &args->pusch) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (srsran_pucch_nr_init(&q->pucch, &args->pucch) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (srsran_dmrs_sch_init(&q->dmrs, true) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + srsran_ofdm_cfg_t ofdm_cfg = {}; + ofdm_cfg.nof_prb = args->nof_max_prb; + ofdm_cfg.in_buffer = input; + ofdm_cfg.out_buffer = q->sf_symbols[0]; + ofdm_cfg.rx_window_offset = GNB_UL_NR_FFT_WINDOW_OFFSET; + ofdm_cfg.symbol_sz = srsran_min_symbol_sz_rb(args->nof_max_prb); + ofdm_cfg.keep_dc = true; + + if (srsran_ofdm_rx_init_cfg(&q->fft, &ofdm_cfg) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + return SRSRAN_SUCCESS; +} + +void srsran_gnb_ul_free(srsran_gnb_ul_t* q) +{ + if (q == NULL) { + return; + } + + srsran_ofdm_tx_free(&q->fft); + srsran_pusch_nr_free(&q->pusch); + srsran_pucch_nr_free(&q->pucch); + srsran_dmrs_sch_free(&q->dmrs); + srsran_chest_dl_res_free(&q->chest); + + if (q->sf_symbols[0] != NULL) { + free(q->sf_symbols[0]); + } + + SRSRAN_MEM_ZERO(q, srsran_gnb_ul_t, 1); +} + +int srsran_gnb_ul_set_carrier(srsran_gnb_ul_t* q, const srsran_carrier_nr_t* carrier) +{ + if (q == NULL || carrier == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + q->carrier = *carrier; + + if (gnb_ul_alloc_prb(q, carrier->nof_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (srsran_pusch_nr_set_carrier(&q->pusch, carrier) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (srsran_pucch_nr_set_carrier(&q->pucch, carrier) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (srsran_dmrs_sch_set_carrier(&q->dmrs, carrier) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + srsran_ofdm_cfg_t ofdm_cfg = {}; + ofdm_cfg.nof_prb = carrier->nof_prb; + ofdm_cfg.rx_window_offset = GNB_UL_NR_FFT_WINDOW_OFFSET; + ofdm_cfg.symbol_sz = srsran_min_symbol_sz_rb(carrier->nof_prb); + ofdm_cfg.keep_dc = true; + + if (srsran_ofdm_rx_init_cfg(&q->fft, &ofdm_cfg) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + return SRSRAN_SUCCESS; +} + +int srsran_gnb_ul_fft(srsran_gnb_ul_t* q) +{ + if (q == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + srsran_ofdm_rx_sf(&q->fft); + + return SRSRAN_SUCCESS; +} + +int srsran_gnb_ul_get_pusch(srsran_gnb_ul_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_sch_cfg_nr_t* cfg, + const srsran_sch_grant_nr_t* grant, + srsran_pusch_res_nr_t* data) +{ + if (q == NULL || cfg == NULL || grant == NULL || data == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + if (srsran_dmrs_sch_estimate(&q->dmrs, slot_cfg, cfg, grant, q->sf_symbols[0], &q->chest) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (srsran_pusch_nr_decode(&q->pusch, cfg, grant, &q->chest, q->sf_symbols, data) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + return SRSRAN_SUCCESS; +} \ No newline at end of file diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 504136d06..df155d9fe 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -909,7 +909,7 @@ int srsran_pusch_nr_decode(srsran_pusch_nr_t* q, const srsran_sch_grant_nr_t* grant, srsran_chest_dl_res_t* channel, cf_t* sf_symbols[SRSRAN_MAX_PORTS], - srsran_pusch_res_nr_t* data[SRSRAN_MAX_TB]) + srsran_pusch_res_nr_t* data) { // Check input pointers if (!q || !cfg || !grant || !data || !sf_symbols || !channel) { @@ -978,7 +978,7 @@ int srsran_pusch_nr_decode(srsran_pusch_nr_t* q, // SCH decode for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) { - if (pusch_nr_decode_codeword(q, cfg, &grant->tb[tb], data[0], grant->rnti) < SRSRAN_SUCCESS) { + if (pusch_nr_decode_codeword(q, cfg, &grant->tb[tb], data, grant->rnti) < SRSRAN_SUCCESS) { ERROR("Error encoding TB %d", tb); return SRSRAN_ERROR; } diff --git a/lib/src/phy/phch/test/pusch_nr_test.c b/lib/src/phy/phch/test/pusch_nr_test.c index f1357c130..f88e1b938 100644 --- a/lib/src/phy/phch/test/pusch_nr_test.c +++ b/lib/src/phy/phch/test/pusch_nr_test.c @@ -266,9 +266,7 @@ int main(int argc, char** argv) } chest.nof_re = pusch_cfg.grant.tb->nof_re; - srsran_pusch_res_nr_t* data_rx_vec[SRSRAN_MAX_TB] = {}; - data_rx_vec[0] = &data_rx; - if (srsran_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &chest, sf_symbols, data_rx_vec) < + if (srsran_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &chest, sf_symbols, &data_rx) < SRSRAN_SUCCESS) { ERROR("Error encoding"); goto clean_exit; diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index c07bed2a9..07b342b83 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -10,7 +10,7 @@ * */ -#include "srsran/phy/enb/enb_dl_nr.h" +#include "srsran/phy/gnb/gnb_dl.h" #include "srsran/phy/phch/ra_dl_nr.h" #include "srsran/phy/phch/ra_nr.h" #include "srsran/phy/ue/ue_dl_nr.h" @@ -144,13 +144,13 @@ static int parse_args(int argc, char** argv) return SRSRAN_SUCCESS; } -static int work_gnb_dl(srsran_enb_dl_nr_t* enb_dl, +static int work_gnb_dl(srsran_gnb_dl_t* gnb_dl, srsran_slot_cfg_t* slot, srsran_search_space_t* search_space, srsran_dci_location_t* dci_location, uint8_t** data_tx) { - if (srsran_enb_dl_nr_base_zero(enb_dl) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_base_zero(gnb_dl) < SRSRAN_SUCCESS) { ERROR("Error setting base to zero"); return SRSRAN_ERROR; } @@ -170,18 +170,18 @@ static int work_gnb_dl(srsran_enb_dl_nr_t* enb_dl, dci_dl.rv = 0; // Put actual DCI - if (srsran_enb_dl_nr_pdcch_put_dl(enb_dl, slot, &dci_dl) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_pdcch_put_dl(gnb_dl, slot, &dci_dl) < SRSRAN_SUCCESS) { ERROR("Error putting PDCCH"); return SRSRAN_ERROR; } // Put PDSCH transmission - if (srsran_enb_dl_nr_pdsch_put(enb_dl, slot, &pdsch_cfg, data_tx) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_pdsch_put(gnb_dl, slot, &pdsch_cfg, data_tx) < SRSRAN_SUCCESS) { ERROR("Error putting PDSCH"); return SRSRAN_ERROR; } - srsran_enb_dl_nr_gen_signal(enb_dl); + srsran_gnb_dl_gen_signal(gnb_dl); return SRSRAN_SUCCESS; } @@ -214,7 +214,7 @@ static int work_ue_dl(srsran_ue_dl_nr_t* ue_dl, srsran_slot_cfg_t* slot, srsran_ int main(int argc, char** argv) { int ret = SRSRAN_ERROR; - srsran_enb_dl_nr_t enb_dl = {}; + srsran_gnb_dl_t gnb_dl = {}; srsran_ue_dl_nr_t ue_dl = {}; srsran_pdsch_res_nr_t pdsch_res = {}; srsran_random_t rand_gen = srsran_random_init(1234); @@ -251,11 +251,11 @@ int main(int argc, char** argv) ue_dl_args.pdcch.measure_evm = true; ue_dl_args.nof_max_prb = carrier.nof_prb; - srsran_enb_dl_nr_args_t enb_dl_args = {}; - enb_dl_args.nof_tx_antennas = 1; - enb_dl_args.pdsch.sch.disable_simd = false; - enb_dl_args.pdcch.disable_simd = false; - enb_dl_args.nof_max_prb = carrier.nof_prb; + srsran_gnb_dl_args_t gnb_dl_args = {}; + gnb_dl_args.nof_tx_antennas = 1; + gnb_dl_args.pdsch.sch.disable_simd = false; + gnb_dl_args.pdcch.disable_simd = false; + gnb_dl_args.nof_max_prb = carrier.nof_prb; srsran_pdcch_cfg_nr_t pdcch_cfg = {}; @@ -285,7 +285,7 @@ int main(int argc, char** argv) goto clean_exit; } - if (srsran_enb_dl_nr_init(&enb_dl, buffer_gnb, &enb_dl_args)) { + if (srsran_gnb_dl_init(&gnb_dl, buffer_gnb, &gnb_dl_args)) { ERROR("Error UE DL"); goto clean_exit; } @@ -304,12 +304,12 @@ int main(int argc, char** argv) goto clean_exit; } - if (srsran_enb_dl_nr_set_carrier(&enb_dl, &carrier)) { + if (srsran_gnb_dl_set_carrier(&gnb_dl, &carrier)) { ERROR("Error setting SCH NR carrier"); goto clean_exit; } - if (srsran_enb_dl_nr_set_pdcch_config(&enb_dl, &pdcch_cfg, &dci_cfg)) { + if (srsran_gnb_dl_set_pdcch_config(&gnb_dl, &pdcch_cfg, &dci_cfg)) { ERROR("Error setting CORESET"); goto clean_exit; } @@ -410,7 +410,7 @@ int main(int argc, char** argv) dci_location.L = L; gettimeofday(&t[1], NULL); - if (work_gnb_dl(&enb_dl, &slot, search_space, &dci_location, data_tx) < SRSRAN_ERROR) { + if (work_gnb_dl(&gnb_dl, &slot, search_space, &dci_location, data_tx) < SRSRAN_ERROR) { ERROR("Error running eNb DL"); goto clean_exit; } @@ -501,7 +501,7 @@ int main(int argc, char** argv) clean_exit: srsran_random_free(rand_gen); - srsran_enb_dl_nr_free(&enb_dl); + srsran_gnb_dl_free(&gnb_dl); srsran_ue_dl_nr_free(&ue_dl); for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) { if (data_tx[i]) { diff --git a/srsenb/hdr/phy/nr/slot_worker.h b/srsenb/hdr/phy/nr/slot_worker.h index 7756b2116..dd5fd3985 100644 --- a/srsenb/hdr/phy/nr/slot_worker.h +++ b/srsenb/hdr/phy/nr/slot_worker.h @@ -79,7 +79,7 @@ private: srsran_slot_cfg_t ul_slot_cfg = {}; srsran_pdcch_cfg_nr_t pdcch_cfg = {}; srsran::rf_timestamp_t tx_time = {}; - srsran_enb_dl_nr_t gnb_dl = {}; + srsran_gnb_dl_t gnb_dl = {}; std::vector tx_buffer; ///< Baseband transmit buffers std::vector rx_buffer; ///< Baseband receive buffers }; diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 9bb1fa0bf..411e319e8 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -18,7 +18,9 @@ namespace nr { slot_worker::slot_worker(srsran::phy_common_interface& common_, stack_interface_phy_nr& stack_, srslog::basic_logger& logger_) : - common(common_), stack(stack_), logger(logger_) + common(common_), + stack(stack_), + logger(logger_) { // Do nothing } @@ -53,21 +55,21 @@ bool slot_worker::init(const args_t& args) } // Prepare DL arguments - srsran_enb_dl_nr_args_t dl_args = {}; - dl_args.pdsch.measure_time = true; - dl_args.pdsch.max_layers = args.carrier.max_mimo_layers; - dl_args.pdsch.max_prb = args.carrier.nof_prb; - dl_args.nof_tx_antennas = args.nof_tx_ports; - dl_args.nof_max_prb = args.carrier.nof_prb; + srsran_gnb_dl_args_t dl_args = {}; + dl_args.pdsch.measure_time = true; + dl_args.pdsch.max_layers = args.carrier.max_mimo_layers; + dl_args.pdsch.max_prb = args.carrier.nof_prb; + dl_args.nof_tx_antennas = args.nof_tx_ports; + dl_args.nof_max_prb = args.carrier.nof_prb; // Initialise DL - if (srsran_enb_dl_nr_init(&gnb_dl, tx_buffer.data(), &dl_args) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_init(&gnb_dl, tx_buffer.data(), &dl_args) < SRSRAN_SUCCESS) { logger.error("Error gNb PHY init"); return false; } // Set gNb carrier - if (srsran_enb_dl_nr_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) { logger.error("Error setting carrier"); return false; } @@ -89,7 +91,7 @@ slot_worker::~slot_worker() b = nullptr; } } - srsran_enb_dl_nr_free(&gnb_dl); + srsran_gnb_dl_free(&gnb_dl); } cf_t* slot_worker::get_buffer_rx(uint32_t antenna_idx) @@ -153,7 +155,7 @@ bool slot_worker::work_dl() return false; } - if (srsran_enb_dl_nr_base_zero(&gnb_dl) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_base_zero(&gnb_dl) < SRSRAN_SUCCESS) { logger.error("Error zeroeing RE grid"); return false; } @@ -161,13 +163,13 @@ bool slot_worker::work_dl() // Encode PDCCH for DL transmissions for (const stack_interface_phy_nr::pdcch_dl_t& pdcch : dl_sched.pdcch_dl) { // Set PDCCH configuration, including DCI dedicated - if (srsran_enb_dl_nr_set_pdcch_config(&gnb_dl, &pdcch_cfg, &pdcch.dci_cfg) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_set_pdcch_config(&gnb_dl, &pdcch_cfg, &pdcch.dci_cfg) < SRSRAN_SUCCESS) { logger.error("PDCCH: Error setting DL configuration"); return false; } // Put PDCCH message - if (srsran_enb_dl_nr_pdcch_put_dl(&gnb_dl, &dl_slot_cfg, &pdcch.dci) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_pdcch_put_dl(&gnb_dl, &dl_slot_cfg, &pdcch.dci) < SRSRAN_SUCCESS) { logger.error("PDCCH: Error putting DL message"); return false; } @@ -175,7 +177,7 @@ bool slot_worker::work_dl() // Log PDCCH information if (logger.info.enabled()) { std::array str = {}; - srsran_enb_dl_nr_pdcch_dl_info(&gnb_dl, &pdcch.dci, str.data(), (uint32_t)str.size()); + srsran_gnb_dl_pdcch_dl_info(&gnb_dl, &pdcch.dci, str.data(), (uint32_t)str.size()); logger.info("PDCCH: cc=%d %s tti_tx=%d", cell_index, str.data(), dl_slot_cfg.idx); } } @@ -183,13 +185,13 @@ bool slot_worker::work_dl() // Encode PDCCH for UL transmissions for (const stack_interface_phy_nr::pdcch_ul_t& pdcch : dl_sched.pdcch_ul) { // Set PDCCH configuration, including DCI dedicated - if (srsran_enb_dl_nr_set_pdcch_config(&gnb_dl, &pdcch_cfg, &pdcch.dci_cfg) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_set_pdcch_config(&gnb_dl, &pdcch_cfg, &pdcch.dci_cfg) < SRSRAN_SUCCESS) { logger.error("PDCCH: Error setting DL configuration"); return false; } // Put PDCCH message - if (srsran_enb_dl_nr_pdcch_put_ul(&gnb_dl, &dl_slot_cfg, &pdcch.dci) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_pdcch_put_ul(&gnb_dl, &dl_slot_cfg, &pdcch.dci) < SRSRAN_SUCCESS) { logger.error("PDCCH: Error putting DL message"); return false; } @@ -197,7 +199,7 @@ bool slot_worker::work_dl() // Log PDCCH information if (logger.info.enabled()) { std::array str = {}; - srsran_enb_dl_nr_pdcch_ul_info(&gnb_dl, &pdcch.dci, str.data(), (uint32_t)str.size()); + srsran_gnb_dl_pdcch_ul_info(&gnb_dl, &pdcch.dci, str.data(), (uint32_t)str.size()); logger.info("PDCCH: cc=%d %s tti_tx=%d", cell_index, str.data(), dl_slot_cfg.idx); } } @@ -205,7 +207,7 @@ bool slot_worker::work_dl() // Encode PDSCH for (stack_interface_phy_nr::pdsch_t& pdsch : dl_sched.pdsch) { // Put PDSCH message - if (srsran_enb_dl_nr_pdsch_put(&gnb_dl, &dl_slot_cfg, &pdsch.sch, pdsch.data.data()) < SRSRAN_SUCCESS) { + if (srsran_gnb_dl_pdsch_put(&gnb_dl, &dl_slot_cfg, &pdsch.sch, pdsch.data.data()) < SRSRAN_SUCCESS) { logger.error("PDSCH: Error putting DL message"); return false; } @@ -213,7 +215,7 @@ bool slot_worker::work_dl() // Log PDSCH information if (logger.info.enabled()) { std::array str = {}; - srsran_enb_dl_nr_pdsch_info(&gnb_dl, &pdsch.sch, str.data(), (uint32_t)str.size()); + srsran_gnb_dl_pdsch_info(&gnb_dl, &pdsch.sch, str.data(), (uint32_t)str.size()); logger.info("PDSCH: cc=%d %s tti_tx=%d", cell_index, str.data(), dl_slot_cfg.idx); } } @@ -224,7 +226,7 @@ bool slot_worker::work_dl() } // Generate baseband signal - srsran_enb_dl_nr_gen_signal(&gnb_dl); + srsran_gnb_dl_gen_signal(&gnb_dl); // Add SSB to the baseband signal for (const stack_interface_phy_nr::ssb_t& ssb : dl_sched.ssb) { From 89994cd5a8d97bad8c4a109b65c739bdd66d0538 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 29 Jun 2021 11:07:30 +0200 Subject: [PATCH 19/50] change ERROR macro format to be parsed by IDE --- lib/include/srsran/phy/utils/debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/include/srsran/phy/utils/debug.h b/lib/include/srsran/phy/utils/debug.h index c1b4d556f..114734a61 100644 --- a/lib/include/srsran/phy/utils/debug.h +++ b/lib/include/srsran/phy/utils/debug.h @@ -68,7 +68,7 @@ SRSRAN_API extern int handler_registered; #define ERROR(_fmt, ...) \ do { \ if (!handler_registered) { \ - fprintf(stderr, "\e[31m%s.%d: " _fmt "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__); \ + fprintf(stderr, "\e[31m%s:%d: " _fmt "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__); \ } else { \ srsran_phy_log_print(LOG_LEVEL_ERROR_S, _fmt, ##__VA_ARGS__); \ } \ From 658b47d917210fbc8a351d3c5d1086b40821e9a3 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 29 Jun 2021 11:08:11 +0200 Subject: [PATCH 20/50] Added NR PUSCH and PUCCH decoder in gnb_ul --- .../srsran/phy/ch_estimation/dmrs_pucch.h | 4 - lib/include/srsran/phy/gnb/gnb_ul.h | 3 +- lib/include/srsran/srsran.h | 1 + lib/src/phy/ch_estimation/dmrs_pucch.c | 46 ++++---- lib/src/phy/gnb/gnb_ul.c | 105 +++++++++++++++++- lib/src/phy/phch/test/pucch_nr_test.c | 6 +- srsenb/hdr/phy/nr/slot_worker.h | 1 + srsenb/src/phy/nr/slot_worker.cc | 31 ++++-- 8 files changed, 152 insertions(+), 45 deletions(-) diff --git a/lib/include/srsran/phy/ch_estimation/dmrs_pucch.h b/lib/include/srsran/phy/ch_estimation/dmrs_pucch.h index e8ef7f5d5..56f83466e 100644 --- a/lib/include/srsran/phy/ch_estimation/dmrs_pucch.h +++ b/lib/include/srsran/phy/ch_estimation/dmrs_pucch.h @@ -49,7 +49,6 @@ SRSRAN_API int srsran_dmrs_pucch_format1_put(const srsran_pucch_nr_t* /** * @brief Estimates NR-PUCCH format 1 resource elements from their DMRS in the provided resource grid * @param[in] q NR-PUCCH encoder/decoder object - * @param[in] carrier Carrier configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 1 resource @@ -58,7 +57,6 @@ SRSRAN_API int srsran_dmrs_pucch_format1_put(const srsran_pucch_nr_t* * @return SRSRAN_SUCCESS if successful, SRSRAN_ERROR code otherwise */ SRSRAN_API int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q, - const srsran_carrier_nr_t* carrier, const srsran_pucch_nr_common_cfg_t* cfg, const srsran_slot_cfg_t* slot, const srsran_pucch_nr_resource_t* resource, @@ -85,7 +83,6 @@ int srsran_dmrs_pucch_format2_put(const srsran_pucch_nr_t* q, /** * @brief Estimates NR-PUCCH format 2 resource elements from their DMRS in the provided resource grid * @param[in] q NR-PUCCH encoder/decoder object - * @param[in] carrier Carrier configuration * @param[in] cfg PUCCH common configuration * @param[in] slot slot configuration * @param[in] resource PUCCH format 2 resource @@ -94,7 +91,6 @@ int srsran_dmrs_pucch_format2_put(const srsran_pucch_nr_t* q, * @return SRSRAN_SUCCESS if successful, SRSRAN_ERROR code otherwise */ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q, - const srsran_carrier_nr_t* carrier, const srsran_pucch_nr_common_cfg_t* cfg, const srsran_slot_cfg_t* slot, const srsran_pucch_nr_resource_t* resource, diff --git a/lib/include/srsran/phy/gnb/gnb_ul.h b/lib/include/srsran/phy/gnb/gnb_ul.h index 7fa392c17..6440a4512 100644 --- a/lib/include/srsran/phy/gnb/gnb_ul.h +++ b/lib/include/srsran/phy/gnb/gnb_ul.h @@ -34,7 +34,8 @@ typedef struct SRSRAN_API { srsran_pusch_nr_t pusch; srsran_pucch_nr_t pucch; srsran_dmrs_sch_t dmrs; - srsran_chest_dl_res_t chest; + srsran_chest_dl_res_t chest_pusch; + srsran_chest_ul_res_t chest_pucch; } srsran_gnb_ul_t; SRSRAN_API int srsran_gnb_ul_init(srsran_gnb_ul_t* q, cf_t* input, const srsran_gnb_ul_args_t* args); diff --git a/lib/include/srsran/srsran.h b/lib/include/srsran/srsran.h index 0e379a2dc..7588caf18 100644 --- a/lib/include/srsran/srsran.h +++ b/lib/include/srsran/srsran.h @@ -118,6 +118,7 @@ extern "C" { #include "srsran/phy/enb/enb_dl.h" #include "srsran/phy/enb/enb_ul.h" #include "srsran/phy/gnb/gnb_dl.h" +#include "srsran/phy/gnb/gnb_ul.h" #include "srsran/phy/scrambling/scrambling.h" diff --git a/lib/src/phy/ch_estimation/dmrs_pucch.c b/lib/src/phy/ch_estimation/dmrs_pucch.c index 2d036e9f7..7a045c325 100644 --- a/lib/src/phy/ch_estimation/dmrs_pucch.c +++ b/lib/src/phy/ch_estimation/dmrs_pucch.c @@ -121,7 +121,7 @@ int srsran_dmrs_pucch_format1_put(const srsran_pucch_nr_t* q, uint32_t l = m * 2; // Get start of the sequence in resource grid - cf_t* slot_symbols_ptr = &slot_symbols[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE]; + cf_t* slot_symbols_ptr = &slot_symbols[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE]; // Get Alpha index uint32_t alpha_idx = 0; @@ -152,15 +152,13 @@ int srsran_dmrs_pucch_format1_put(const srsran_pucch_nr_t* q, } int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q, - const srsran_carrier_nr_t* carrier, const srsran_pucch_nr_common_cfg_t* cfg, const srsran_slot_cfg_t* slot, const srsran_pucch_nr_resource_t* resource, const cf_t* slot_symbols, srsran_chest_ul_res_t* res) { - if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL || - res == NULL) { + if (q == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL || res == NULL) { return SRSRAN_ERROR_INVALID_INPUTS; } @@ -172,7 +170,7 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q, // Get group sequence uint32_t u = 0; uint32_t v = 0; - if (srsran_pucch_nr_group_sequence(carrier, cfg, &u, &v) < SRSRAN_SUCCESS) { + if (srsran_pucch_nr_group_sequence(&q->carrier, cfg, &u, &v) < SRSRAN_SUCCESS) { ERROR("Error getting group sequence"); return SRSRAN_ERROR; } @@ -191,11 +189,11 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q, // Get start of the sequence in resource grid const cf_t* slot_symbols_ptr = - &slot_symbols[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE]; + &slot_symbols[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE]; // Get Alpha index uint32_t alpha_idx = 0; - if (srsran_pucch_nr_alpha_idx(carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, 0, &alpha_idx) < + if (srsran_pucch_nr_alpha_idx(&q->carrier, cfg, slot, l, l_prime, resource->initial_cyclic_shift, 0, &alpha_idx) < SRSRAN_SUCCESS) { ERROR("Calculating alpha"); } @@ -247,9 +245,9 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q, // Compute Time Aligment error in microseconds if (isnormal(ta_err)) { - ta_err /= 15e3f * (float)(1U << carrier->scs); // Convert from normalized frequency to seconds - ta_err *= 1e6f; // Convert to micro-seconds - ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second + ta_err /= 15e3f * (float)(1U << q->carrier.scs); // Convert from normalized frequency to seconds + ta_err *= 1e6f; // Convert to micro-seconds + ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second res->ta_us = ta_err; } else { res->ta_us = 0.0f; @@ -264,7 +262,7 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q, // Interpolates between DMRS symbols for (uint32_t m = 0; m < n_pucch; m++) { uint32_t l = m * 2 + 1; - cf_t* ce_ptr = &res->ce[(carrier->nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE]; + cf_t* ce_ptr = &res->ce[(q->carrier.nof_prb * (l + l_prime) + resource->starting_prb) * SRSRAN_NRE]; if (m != n_pucch - 1) { // If it is not the last symbol with DMRS, average between @@ -313,8 +311,8 @@ int srsran_dmrs_pucch_format2_put(const srsran_pucch_nr_t* q, uint32_t l_start = resource->start_symbol_idx; uint32_t l_end = resource->start_symbol_idx + resource->nof_symbols; - uint32_t k_start = SRSRAN_MIN(carrier->nof_prb - 1, resource->starting_prb) * SRSRAN_NRE + 1; - uint32_t k_end = SRSRAN_MIN(carrier->nof_prb, resource->starting_prb + resource->nof_prb) * SRSRAN_NRE; + uint32_t k_start = SRSRAN_MIN(q->carrier.nof_prb - 1, resource->starting_prb) * SRSRAN_NRE + 1; + uint32_t k_end = SRSRAN_MIN(q->carrier.nof_prb, resource->starting_prb + resource->nof_prb) * SRSRAN_NRE; for (uint32_t l = l_start; l < l_end; l++) { // Compute sequence initial state uint32_t cinit = dmrs_pucch_format2_cinit(carrier, cfg, slot, l); @@ -330,22 +328,20 @@ int srsran_dmrs_pucch_format2_put(const srsran_pucch_nr_t* q, // Put sequence in k = 3 * m + 1 for (uint32_t k = k_start, i = 0; k < k_end; k += 3, i++) { - slot_symbols[l * carrier->nof_prb * SRSRAN_NRE + k] = r_l[i]; + slot_symbols[l * q->carrier.nof_prb * SRSRAN_NRE + k] = r_l[i]; } } return SRSRAN_SUCCESS; } int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q, - const srsran_carrier_nr_t* carrier, const srsran_pucch_nr_common_cfg_t* cfg, const srsran_slot_cfg_t* slot, const srsran_pucch_nr_resource_t* resource, const cf_t* slot_symbols, srsran_chest_ul_res_t* res) { - if (q == NULL || carrier == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL || - res == NULL) { + if (q == NULL || cfg == NULL || slot == NULL || resource == NULL || slot_symbols == NULL || res == NULL) { return SRSRAN_ERROR_INVALID_INPUTS; } @@ -358,12 +354,12 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q, uint32_t l_start = resource->start_symbol_idx; uint32_t l_end = resource->start_symbol_idx + resource->nof_symbols; - uint32_t k_start = SRSRAN_MIN(carrier->nof_prb - 1, resource->starting_prb) * SRSRAN_NRE + 1; - uint32_t k_end = SRSRAN_MIN(carrier->nof_prb, resource->starting_prb + resource->nof_prb) * SRSRAN_NRE; + uint32_t k_start = SRSRAN_MIN(q->carrier.nof_prb - 1, resource->starting_prb) * SRSRAN_NRE + 1; + uint32_t k_end = SRSRAN_MIN(q->carrier.nof_prb, resource->starting_prb + resource->nof_prb) * SRSRAN_NRE; uint32_t nof_ref = 4 * resource->nof_prb; for (uint32_t l = l_start, j = 0; l < l_end; l++, j++) { // Compute sequence initial state - uint32_t cinit = dmrs_pucch_format2_cinit(carrier, cfg, slot, l); + uint32_t cinit = dmrs_pucch_format2_cinit(&q->carrier, cfg, slot, l); srsran_sequence_state_t sequence = {}; srsran_sequence_state_init(&sequence, cinit); @@ -376,7 +372,7 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q, // Put sequence in k = 3 * m + 1 for (uint32_t k = k_start, i = 0; k < k_end; k += 3, i++) { - ce[j][i] = slot_symbols[l * carrier->nof_prb * SRSRAN_NRE + k]; + ce[j][i] = slot_symbols[l * q->carrier.nof_prb * SRSRAN_NRE + k]; } srsran_vec_prod_conj_ccc(ce[j], r_l, ce[j], nof_ref); @@ -409,9 +405,9 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q, // Compute Time Aligment error in microseconds if (isnormal(ta_err)) { - ta_err /= 15e3f * (float)(1U << carrier->scs) * 3; // Convert from normalized frequency to seconds - ta_err *= 1e6f; // Convert to micro-seconds - ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second + ta_err /= 15e3f * (float)(1U << q->carrier.scs) * 3; // Convert from normalized frequency to seconds + ta_err *= 1e6f; // Convert to micro-seconds + ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second res->ta_us = ta_err; } else { res->ta_us = 0.0f; @@ -423,7 +419,7 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q, // Zero order hold for (uint32_t l = l_start, j = 0; l < l_end; l++, j++) { for (uint32_t k = k_start - 1, i = 0; k < k_end; k++, i++) { - res->ce[l * carrier->nof_prb * SRSRAN_NRE + k] = ce[j][i / 3]; + res->ce[l * q->carrier.nof_prb * SRSRAN_NRE + k] = ce[j][i / 3]; } } diff --git a/lib/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c index 616dae751..ab85c3df9 100644 --- a/lib/src/phy/gnb/gnb_ul.c +++ b/lib/src/phy/gnb/gnb_ul.c @@ -11,6 +11,7 @@ */ #include "srsran/phy/gnb/gnb_ul.h" +#include "srsran/phy/ch_estimation/dmrs_pucch.h" /** * @brief Shifts FFT window a fraction of the cyclic prefix. Set to 0.0f for disabling. @@ -24,8 +25,13 @@ static int gnb_ul_alloc_prb(srsran_gnb_ul_t* q, uint32_t new_nof_prb) if (q->max_prb < new_nof_prb) { q->max_prb = new_nof_prb; - srsran_chest_dl_res_free(&q->chest); - if (srsran_chest_dl_res_init(&q->chest, q->max_prb) < SRSRAN_SUCCESS) { + srsran_chest_dl_res_free(&q->chest_pusch); + if (srsran_chest_dl_res_init(&q->chest_pusch, q->max_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + srsran_chest_ul_res_free(&q->chest_pucch); + if (srsran_chest_ul_res_init(&q->chest_pucch, q->max_prb) < SRSRAN_SUCCESS) { return SRSRAN_ERROR; } @@ -90,7 +96,8 @@ void srsran_gnb_ul_free(srsran_gnb_ul_t* q) srsran_pusch_nr_free(&q->pusch); srsran_pucch_nr_free(&q->pucch); srsran_dmrs_sch_free(&q->dmrs); - srsran_chest_dl_res_free(&q->chest); + srsran_chest_dl_res_free(&q->chest_pusch); + srsran_chest_ul_res_free(&q->chest_pucch); if (q->sf_symbols[0] != NULL) { free(q->sf_symbols[0]); @@ -157,13 +164,101 @@ int srsran_gnb_ul_get_pusch(srsran_gnb_ul_t* q, return SRSRAN_ERROR_INVALID_INPUTS; } - if (srsran_dmrs_sch_estimate(&q->dmrs, slot_cfg, cfg, grant, q->sf_symbols[0], &q->chest) < SRSRAN_SUCCESS) { + if (srsran_dmrs_sch_estimate(&q->dmrs, slot_cfg, cfg, grant, q->sf_symbols[0], &q->chest_pusch) < SRSRAN_SUCCESS) { return SRSRAN_ERROR; } - if (srsran_pusch_nr_decode(&q->pusch, cfg, grant, &q->chest, q->sf_symbols, data) < SRSRAN_SUCCESS) { + if (srsran_pusch_nr_decode(&q->pusch, cfg, grant, &q->chest_pusch, q->sf_symbols, data) < SRSRAN_SUCCESS) { return SRSRAN_ERROR; } return SRSRAN_SUCCESS; +} + +static int gnb_ul_decode_pucch_format1(srsran_gnb_ul_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_pucch_nr_common_cfg_t* cfg, + const srsran_pucch_nr_resource_t* resource, + const srsran_uci_cfg_nr_t* uci_cfg, + srsran_uci_value_nr_t* uci_value) +{ + uint8_t b[SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS] = {}; + + // Set ACK bits + uint32_t nof_bits = SRSRAN_MIN(SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS, uci_cfg->o_ack); + + // Set SR bits + // For a positive SR transmission using PUCCH format 1, the UE transmits the PUCCH as described in [4, TS + // 38.211] by setting b ( 0 ) = 0 . + if (nof_bits == 0 && uci_cfg->o_sr > 0) { + nof_bits = 1; + } + + if (srsran_dmrs_pucch_format1_estimate(&q->pucch, cfg, slot_cfg, resource, q->sf_symbols[0], &q->chest_pucch) < + SRSRAN_SUCCESS) { + ERROR("Error in PUCCH format 1 estimation"); + return SRSRAN_ERROR; + } + + if (srsran_pucch_nr_format1_decode( + &q->pucch, cfg, slot_cfg, resource, &q->chest_pucch, q->sf_symbols[0], b, nof_bits) < SRSRAN_SUCCESS) { + ERROR("Error in PUCCH format 1 decoding"); + return SRSRAN_ERROR; + } + + // De-multiplex ACK bits + for (uint32_t i = 0; i < nof_bits; i++) { + uci_value->ack[i] = b[i]; + } + + return SRSRAN_SUCCESS; +} + +static int gnb_ul_decode_pucch_format2(srsran_gnb_ul_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_pucch_nr_common_cfg_t* cfg, + const srsran_pucch_nr_resource_t* resource, + const srsran_uci_cfg_nr_t* uci_cfg, + srsran_uci_value_nr_t* uci_value) +{ + if (srsran_dmrs_pucch_format2_estimate(&q->pucch, cfg, slot_cfg, resource, q->sf_symbols[0], &q->chest_pucch) < + SRSRAN_SUCCESS) { + ERROR("Error in PUCCH format 2 estimation"); + return SRSRAN_ERROR; + } + + if (srsran_pucch_nr_format_2_3_4_decode( + &q->pucch, cfg, slot_cfg, resource, uci_cfg, &q->chest_pucch, q->sf_symbols[0], uci_value) < SRSRAN_SUCCESS) { + ERROR("Error in PUCCH format 2 decoding"); + return SRSRAN_ERROR; + } + + return SRSRAN_SUCCESS; +} + +int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_pucch_nr_common_cfg_t* cfg, + const srsran_pucch_nr_resource_t* resource, + const srsran_uci_cfg_nr_t* uci_cfg, + srsran_uci_value_nr_t* uci_value) +{ + if (q == NULL || slot_cfg == NULL || cfg == NULL || resource == NULL || uci_cfg == NULL || uci_value == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Estimate channel + switch (resource->format) { + case SRSRAN_PUCCH_NR_FORMAT_1: + return gnb_ul_decode_pucch_format1(q, slot_cfg, cfg, resource, uci_cfg, uci_value); + case SRSRAN_PUCCH_NR_FORMAT_2: + return gnb_ul_decode_pucch_format2(q, slot_cfg, cfg, resource, uci_cfg, uci_value); + case SRSRAN_PUCCH_NR_FORMAT_0: + case SRSRAN_PUCCH_NR_FORMAT_3: + case SRSRAN_PUCCH_NR_FORMAT_4: + case SRSRAN_PUCCH_NR_FORMAT_ERROR: + ERROR("Invalid or not implemented PUCCH-NR format %d", (int)resource->format); + } + + return SRSRAN_ERROR; } \ No newline at end of file diff --git a/lib/src/phy/phch/test/pucch_nr_test.c b/lib/src/phy/phch/test/pucch_nr_test.c index 455787cf7..5b99ab0c8 100644 --- a/lib/src/phy/phch/test/pucch_nr_test.c +++ b/lib/src/phy/phch/test/pucch_nr_test.c @@ -130,7 +130,7 @@ static int test_pucch_format1(srsran_pucch_nr_t* pucch, // Estimate channel TESTASSERT(srsran_dmrs_pucch_format1_estimate( - pucch, &carrier, cfg, &slot, &resource, slot_symbols, chest_res) == SRSRAN_SUCCESS); + pucch, cfg, &slot, &resource, slot_symbols, chest_res) == SRSRAN_SUCCESS); TESTASSERT(fabsf(chest_res->rsrp_dBfs - 0.0f) < 3.0f); TESTASSERT(fabsf(chest_res->epre_dBfs - 0.0f) < 3.0f); @@ -215,8 +215,8 @@ static int test_pucch_format2(srsran_pucch_nr_t* pucch, &awgn, slot_symbols, slot_symbols, carrier.nof_prb * SRSRAN_NRE * SRSRAN_NSYMB_PER_SLOT_NR); // Estimate channel - TESTASSERT(srsran_dmrs_pucch_format2_estimate( - pucch, &carrier, cfg, &slot, &resource, slot_symbols, chest_res) == SRSRAN_SUCCESS); + TESTASSERT(srsran_dmrs_pucch_format2_estimate(pucch, cfg, &slot, &resource, slot_symbols, chest_res) == + SRSRAN_SUCCESS); INFO("RSRP=%+.2f; EPRE=%+.2f; SNR=%+.2f;", chest_res->rsrp_dBfs, chest_res->epre_dBfs, diff --git a/srsenb/hdr/phy/nr/slot_worker.h b/srsenb/hdr/phy/nr/slot_worker.h index dd5fd3985..ec079f4a2 100644 --- a/srsenb/hdr/phy/nr/slot_worker.h +++ b/srsenb/hdr/phy/nr/slot_worker.h @@ -80,6 +80,7 @@ private: srsran_pdcch_cfg_nr_t pdcch_cfg = {}; srsran::rf_timestamp_t tx_time = {}; srsran_gnb_dl_t gnb_dl = {}; + srsran_gnb_ul_t gnb_ul = {}; std::vector tx_buffer; ///< Baseband transmit buffers std::vector rx_buffer; ///< Baseband receive buffers }; diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 411e319e8..9b73a73ed 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -18,9 +18,7 @@ namespace nr { slot_worker::slot_worker(srsran::phy_common_interface& common_, stack_interface_phy_nr& stack_, srslog::basic_logger& logger_) : - common(common_), - stack(stack_), - logger(logger_) + common(common_), stack(stack_), logger(logger_) { // Do nothing } @@ -62,15 +60,34 @@ bool slot_worker::init(const args_t& args) dl_args.nof_tx_antennas = args.nof_tx_ports; dl_args.nof_max_prb = args.carrier.nof_prb; - // Initialise DL + // Initialise DL if (srsran_gnb_dl_init(&gnb_dl, tx_buffer.data(), &dl_args) < SRSRAN_SUCCESS) { - logger.error("Error gNb PHY init"); + logger.error("Error gNb DL init"); return false; } - // Set gNb carrier + // Set gNb DL carrier if (srsran_gnb_dl_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) { - logger.error("Error setting carrier"); + logger.error("Error setting DL carrier"); + return false; + } + + // Prepare UL arguments + srsran_gnb_ul_args_t ul_args = {}; + ul_args.pusch.measure_time = true; + ul_args.pusch.max_layers = args.carrier.max_mimo_layers; + ul_args.pusch.max_prb = args.carrier.nof_prb; + ul_args.nof_max_prb = args.carrier.nof_prb; + + // Initialise UL + if (srsran_gnb_ul_init(&gnb_ul, rx_buffer[0], &ul_args) < SRSRAN_SUCCESS) { + logger.error("Error gNb DL init"); + return false; + } + + // Set gNb UL carrier + if (srsran_gnb_ul_set_carrier(&gnb_ul, &args.carrier) < SRSRAN_SUCCESS) { + logger.error("Error setting UL carrier"); return false; } From e3afd945bca40d174eadba3deea6d2c1454e229f Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 29 Jun 2021 14:09:03 +0200 Subject: [PATCH 21/50] Refactored NR HARQ ACK feedback --- lib/include/srsran/asn1/rrc_nr_utils.h | 2 +- lib/include/srsran/common/phy_cfg_nr.h | 22 +- lib/include/srsran/phy/phch/harq_ack.h | 36 +++ lib/include/srsran/phy/phch/harq_ack_cfg.h | 107 +++++++ lib/include/srsran/phy/phch/uci_cfg_nr.h | 14 +- lib/include/srsran/phy/ue/ue_dl_nr.h | 55 ---- lib/include/srsran/srsran.h | 1 + lib/src/asn1/rrc_nr_utils.cc | 6 +- lib/src/common/phy_cfg_nr.cc | 6 +- lib/src/phy/gnb/gnb_ul.c | 2 +- lib/src/phy/phch/harq_ack.c | 346 +++++++++++++++++++++ lib/src/phy/phch/phch_cfg_nr.c | 2 +- lib/src/phy/phch/pusch_nr.c | 14 +- lib/src/phy/phch/ra_nr.c | 10 +- lib/src/phy/phch/ra_ul_nr.c | 8 +- lib/src/phy/phch/test/pucch_nr_test.c | 11 +- lib/src/phy/phch/test/pusch_nr_test.c | 2 +- lib/src/phy/phch/uci_nr.c | 40 +-- lib/src/phy/ue/test/gen_ack_nr_test.c | 62 ++-- lib/src/phy/ue/ue_dl_nr.c | 249 --------------- lib/src/phy/ue/ue_ul_nr.c | 2 +- lib/test/asn1/rrc_nr_utils_test.cc | 2 +- srsue/hdr/phy/nr/state.h | 30 +- srsue/src/phy/nr/cc_worker.cc | 10 +- srsue/src/stack/rrc/rrc_nr.cc | 2 +- 25 files changed, 616 insertions(+), 425 deletions(-) create mode 100644 lib/include/srsran/phy/phch/harq_ack.h create mode 100644 lib/include/srsran/phy/phch/harq_ack_cfg.h create mode 100644 lib/src/phy/phch/harq_ack.c diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index e6a26859b..42d834f42 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -75,7 +75,7 @@ bool make_phy_rach_cfg(const asn1::rrc_nr::rach_cfg_common_s& asn1_type, srsran_ bool make_phy_tdd_cfg(const asn1::rrc_nr::tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, srsran_tdd_config_nr_t* srsran_tdd_config_nr); bool make_phy_harq_ack_cfg(const asn1::rrc_nr::phys_cell_group_cfg_s& phys_cell_group_cfg, - srsran_ue_dl_nr_harq_ack_cfg_t* srsran_ue_dl_nr_harq_ack_cfg); + srsran_harq_ack_cfg_hl_t* srsran_ue_dl_nr_harq_ack_cfg); bool make_phy_coreset_cfg(const asn1::rrc_nr::ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* srsran_coreset); bool make_phy_search_space_cfg(const asn1::rrc_nr::search_space_s& search_space, srsran_search_space_t* srsran_search_space); diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index 3bf59c690..c29c90f11 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -35,16 +35,16 @@ struct phy_cfg_nr_t { srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz; }; - srsran_tdd_config_nr_t tdd = {}; - srsran_sch_hl_cfg_nr_t pdsch = {}; - srsran_sch_hl_cfg_nr_t pusch = {}; - srsran_pucch_nr_hl_cfg_t pucch = {}; - srsran_prach_cfg_t prach = {}; - srsran_pdcch_cfg_nr_t pdcch = {}; - srsran_ue_dl_nr_harq_ack_cfg_t harq_ack = {}; - srsran_csi_hl_cfg_t csi = {}; - srsran_carrier_nr_t carrier = {}; - ssb_cfg_t ssb; + srsran_tdd_config_nr_t tdd = {}; + srsran_sch_hl_cfg_nr_t pdsch = {}; + srsran_sch_hl_cfg_nr_t pusch = {}; + srsran_pucch_nr_hl_cfg_t pucch = {}; + srsran_prach_cfg_t prach = {}; + srsran_pdcch_cfg_nr_t pdcch = {}; + srsran_harq_ack_cfg_hl_t harq_ack = {}; + srsran_csi_hl_cfg_t csi = {}; + srsran_carrier_nr_t carrier = {}; + ssb_cfg_t ssb; phy_cfg_nr_t() {} @@ -121,7 +121,7 @@ struct phy_cfg_nr_t { /** * @brief Get PDSCH ACK resource for a given PDSCH transmission */ - bool get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, srsran_pdsch_ack_resource_nr_t& ack_resource) const; + bool get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, srsran_harq_ack_resource_t& ack_resource) const; /** * @brief Compute UCI configuration for the given slot from the pending PDSCH ACK resources, periodic CSI, diff --git a/lib/include/srsran/phy/phch/harq_ack.h b/lib/include/srsran/phy/phch/harq_ack.h new file mode 100644 index 000000000..e926ae606 --- /dev/null +++ b/lib/include/srsran/phy/phch/harq_ack.h @@ -0,0 +1,36 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_HARQ_ACK_H +#define SRSRAN_HARQ_ACK_H + +#include "srsran/phy/phch/dci_nr.h" +#include "srsran/phy/phch/harq_ack_cfg.h" +#include "srsran/phy/phch/uci_cfg_nr.h" + +SRSRAN_API int srsran_harq_ack_resource(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_dci_dl_nr_t* dci_dl, + srsran_harq_ack_resource_t* pdsch_ack_resource); + +SRSRAN_API int srsran_harq_ack_pack(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_pdsch_ack_nr_t* ack_info, + srsran_uci_data_nr_t* uci_data); + +SRSRAN_API int srsran_harq_ack_unpack(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_uci_data_nr_t* uci_data, + srsran_pdsch_ack_nr_t* ack_info); + +SRSRAN_API int srsran_harq_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_harq_ack_m_t* m); + +SRSRAN_API uint32_t srsran_harq_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len); + +#endif // SRSRAN_HARQ_ACK_H diff --git a/lib/include/srsran/phy/phch/harq_ack_cfg.h b/lib/include/srsran/phy/phch/harq_ack_cfg.h new file mode 100644 index 000000000..870947e93 --- /dev/null +++ b/lib/include/srsran/phy/phch/harq_ack_cfg.h @@ -0,0 +1,107 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_HARQ_ACK_CFG_H +#define SRSRAN_HARQ_ACK_CFG_H + +#include "srsran/phy/common/phy_common_nr.h" +#include +#include + +/** + * @brief Maximum number of HARQ ACK feedback bits that can be carried in Uplink Control Information (UCI) message + */ +#define SRSRAN_HARQ_ACK_MAX_NOF_BITS 360 + +/** + * @brief Describes a HARQ ACK resource configuration + */ +typedef struct { + uint32_t scell_idx; ///< Serving cell index + uint32_t v_dai_dl; ///< Downlink Assigment Index + bool dci_format_1_1; ///< Set to true if the PDSCH transmission is triggered by a PDCCH DCI format 1_1 transmission + uint32_t k1; ///< HARQ feedback timing + uint32_t pid; ///< HARQ process identifier + uint16_t rnti; + uint32_t pucch_resource_id; +} srsran_harq_ack_resource_t; + +/** + * @brief Describes a single PDSCH transmission HARQ ACK feedback + */ +typedef struct { + srsran_harq_ack_resource_t resource; + uint8_t value[SRSRAN_MAX_CODEWORDS]; // 0/1 or 2 for DTX + bool present; // set to true if there is a PDSCH on serving cell c associated with PDCCH in PDCCH monitoring occasion + // m, or there is a PDCCH indicating SPS PDSCH release on serving cell c + bool dl_bwp_changed; // set to true if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c + bool ul_bwp_changed; // set to true if an active UL BWP change on the PCell and an active DL BWP change is not + // triggered by a DCI format 1_1 in PDCCH monitoring occasion m + bool second_tb_present; // set to true if two TB were detected in the PDCCH monitoring occasion m +} srsran_harq_ack_m_t; + +#define SRSRAN_UCI_NR_MAX_M 10 + +/** + * @brief Describes a collection of PDSCH HARQ ACK feedback for a number of PDSCH transmissions within a component + * carrier + */ +typedef struct { + uint32_t M; + srsran_harq_ack_m_t m[SRSRAN_UCI_NR_MAX_M]; +} srsran_harq_ack_cc_t; + +/** + * @brief Describes a collection of PDSCH HARQ ACK feedback for a number of component carriers + */ +typedef struct { + srsran_harq_ack_cc_t cc[SRSRAN_MAX_CARRIERS]; + uint32_t nof_cc; + bool use_pusch; // Set to true, if UCI bits are carried by PUSCH +} srsran_pdsch_ack_nr_t; + +/** + * @brief Describes higher layer HARQ ACK feedback for PDSCH configuration + */ +typedef struct SRSRAN_API { + bool harq_ack_spatial_bundling_pucch; ///< Param harq-ACK-SpatialBundlingPUCCH, set to true if provided + bool harq_ack_spatial_bundling_pusch; ///< Param harq-ACK-SpatialBundlingPUSCH, set to true if provided + srsran_harq_ack_codebook_t harq_ack_codebook; ///< pdsch-HARQ-ACK-Codebook configuration + bool max_cw_sched_dci_is_2; ///< Param maxNrofCodeWordsScheduledByDCI, set to true if present and equal to 2 + + uint32_t dl_data_to_ul_ack[SRSRAN_MAX_NOF_DL_DATA_TO_UL]; + uint32_t nof_dl_data_to_ul_ack; +} srsran_harq_ack_cfg_hl_t; + +/** + * @brief Describes HARQ ACK bit configuration for UCI encoding/decoding + * @note if tb0 and tb1 are false, the HARQ ACK bit is not used + * @note if tb0 and tb1 are true, the HARQ ACK feedback are bundled, the actual HARQ ACK feedback bit is the result of + * the AND operation + */ +typedef struct SRSRAN_API { + bool tb0; ///< Set to true if this ACK bit is mapped into TB index 0 + bool tb1; ///< Set to true if this ACK bit is mapped into TB index 1 + uint32_t cc_idx; ///< Component carrier index + uint32_t m_idx; ///< M resource index for packing/unpacking + uint32_t pid; ///< HARQ process identifier +} srsran_harq_ack_bit_t; + +/** + * @brief Describes HARQ ACK feedback configuration for UCI encoding/decoding + */ +typedef struct SRSRAN_API { + srsran_harq_ack_bit_t bits[SRSRAN_HARQ_ACK_MAX_NOF_BITS]; ///< HARQ-ACK feedback bits + uint32_t count; ///< Number of ACK bits +} srsran_harq_ack_cfg_t; + +#endif // SRSRAN_HARQ_ACK_CFG_H diff --git a/lib/include/srsran/phy/phch/uci_cfg_nr.h b/lib/include/srsran/phy/phch/uci_cfg_nr.h index 7330333d5..cb1e104ca 100644 --- a/lib/include/srsran/phy/phch/uci_cfg_nr.h +++ b/lib/include/srsran/phy/phch/uci_cfg_nr.h @@ -14,6 +14,7 @@ #define SRSRAN_UCI_CFG_NR_H #include "csi_cfg.h" +#include "harq_ack_cfg.h" #include "srsran/phy/common/phy_common_nr.h" #include #include @@ -24,11 +25,6 @@ */ #define SRSRAN_UCI_NR_MAX_NOF_BITS 1706U -/** - * @brief Maximum number of HARQ ACK feedback bits that can be carried in Uplink Control Information (UCI) message - */ -#define SRSRAN_UCI_NR_MAX_ACK_BITS 360 - /** * @brief Maximum number of Channel State Information part 1 (CSI1) bits that can be carried in Uplink Control * Information (UCI) message @@ -72,7 +68,7 @@ typedef struct { */ typedef struct SRSRAN_API { /// Common Parameters - uint32_t o_ack; ///< Number of HARQ-ACK bits + srsran_harq_ack_cfg_t ack; ///< HARQ-ACK configuration uint32_t o_sr; ///< Number of SR bits srsran_csi_report_cfg_t csi[SRSRAN_CSI_MAX_NOF_REPORT]; ///< CSI report configuration uint32_t nof_csi; ///< Number of CSI reports @@ -86,9 +82,9 @@ typedef struct SRSRAN_API { * @brief Uplink Control Information (UCI) message packed information */ typedef struct SRSRAN_API { - uint8_t ack[SRSRAN_UCI_NR_MAX_ACK_BITS]; ///< HARQ ACK feedback bits - uint32_t sr; ///< Number of positive SR - srsran_csi_report_value_t csi[SRSRAN_CSI_MAX_NOF_REPORT]; ///< Packed CSI report values + uint8_t ack[SRSRAN_HARQ_ACK_MAX_NOF_BITS]; ///< HARQ ACK feedback bits + uint32_t sr; ///< Number of positive SR + srsran_csi_report_value_t csi[SRSRAN_CSI_MAX_NOF_REPORT]; ///< Packed CSI report values bool valid; ///< Indicates whether the message has been decoded successfully, ignored in the transmitter } srsran_uci_value_nr_t; diff --git a/lib/include/srsran/phy/ue/ue_dl_nr.h b/lib/include/srsran/phy/ue/ue_dl_nr.h index 3fecb8008..f1f1240ce 100644 --- a/lib/include/srsran/phy/ue/ue_dl_nr.h +++ b/lib/include/srsran/phy/ue/ue_dl_nr.h @@ -38,49 +38,6 @@ typedef struct SRSRAN_API { float pdcch_dmrs_epre_thr; } srsran_ue_dl_nr_args_t; -typedef struct { - uint32_t scell_idx; ///< Serving cell index - uint32_t v_dai_dl; ///< Downlink Assigment Index - bool dci_format_1_1; ///< Set to true if the PDSCH transmission is triggered by a PDCCH DCI format 1_1 transmission - uint32_t k1; ///< HARQ feedback timing - uint16_t rnti; - uint32_t pucch_resource_id; -} srsran_pdsch_ack_resource_nr_t; - -typedef struct { - srsran_pdsch_ack_resource_nr_t resource; - uint8_t value[SRSRAN_MAX_CODEWORDS]; // 0/1 or 2 for DTX - bool present; // set to true if there is a PDSCH on serving cell c associated with PDCCH in PDCCH monitoring occasion - // m, or there is a PDCCH indicating SPS PDSCH release on serving cell c - bool dl_bwp_changed; // set to true if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c - bool ul_bwp_changed; // set to true if an active UL BWP change on the PCell and an active DL BWP change is not - // triggered by a DCI format 1_1 in PDCCH monitoring occasion m - bool second_tb_present; // set to true if two TB were detected in the PDCCH monitoring occasion m -} srsran_pdsch_ack_m_nr_t; - -#define SRSRAN_UCI_NR_MAX_M 10 - -typedef struct { - uint32_t M; - srsran_pdsch_ack_m_nr_t m[SRSRAN_UCI_NR_MAX_M]; -} srsran_pdsch_ack_cc_nr_t; - -typedef struct { - srsran_pdsch_ack_cc_nr_t cc[SRSRAN_MAX_CARRIERS]; - uint32_t nof_cc; - bool use_pusch; // Set to true, if UCI bits are carried by PUSCH -} srsran_pdsch_ack_nr_t; - -typedef struct SRSRAN_API { - bool harq_ack_spatial_bundling_pucch; ///< Param harq-ACK-SpatialBundlingPUCCH, set to true if provided - bool harq_ack_spatial_bundling_pusch; ///< Param harq-ACK-SpatialBundlingPUSCH, set to true if provided - srsran_harq_ack_codebook_t harq_ack_codebook; ///< pdsch-HARQ-ACK-Codebook configuration - bool max_cw_sched_dci_is_2; ///< Param maxNrofCodeWordsScheduledByDCI, set to true if present and equal to 2 - - uint32_t dl_data_to_ul_ack[SRSRAN_MAX_NOF_DL_DATA_TO_UL]; - uint32_t nof_dl_data_to_ul_ack; -} srsran_ue_dl_nr_harq_ack_cfg_t; - typedef struct SRSRAN_API { srsran_dci_ctx_t dci_ctx; srsran_dmrs_pdcch_measure_t measure; @@ -161,18 +118,6 @@ SRSRAN_API int srsran_ue_dl_nr_pdsch_info(const srsran_ue_dl_nr_t* q, char* str, uint32_t str_len); -SRSRAN_API int srsran_ue_dl_nr_pdsch_ack_resource(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg, - const srsran_dci_dl_nr_t* dci_dl, - srsran_pdsch_ack_resource_nr_t* pdsch_ack_resource); - -SRSRAN_API int srsran_ue_dl_nr_gen_ack(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg, - const srsran_pdsch_ack_nr_t* ack_info, - srsran_uci_data_nr_t* uci_data); - -SRSRAN_API int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_pdsch_ack_m_nr_t* m); - -SRSRAN_API uint32_t srsran_ue_dl_nr_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len); - SRSRAN_API int srsran_ue_dl_nr_csi_measure_trs(const srsran_ue_dl_nr_t* q, const srsran_slot_cfg_t* slot_cfg, diff --git a/lib/include/srsran/srsran.h b/lib/include/srsran/srsran.h index 7588caf18..b0bf16998 100644 --- a/lib/include/srsran/srsran.h +++ b/lib/include/srsran/srsran.h @@ -85,6 +85,7 @@ extern "C" { #include "srsran/phy/phch/csi.h" #include "srsran/phy/phch/dci.h" #include "srsran/phy/phch/dci_nr.h" +#include "srsran/phy/phch/harq_ack.h" #include "srsran/phy/phch/pbch.h" #include "srsran/phy/phch/pbch_nr.h" #include "srsran/phy/phch/pcfich.h" diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index d6cbd9165..df0770e76 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -342,10 +342,10 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, return true; } -bool make_phy_harq_ack_cfg(const phys_cell_group_cfg_s& phys_cell_group_cfg, - srsran_ue_dl_nr_harq_ack_cfg_t* in_srsran_ue_dl_nr_harq_ack_cfg) +bool make_phy_harq_ack_cfg(const phys_cell_group_cfg_s& phys_cell_group_cfg, + srsran_harq_ack_cfg_hl_t* in_srsran_ue_dl_nr_harq_ack_cfg) { - srsran_ue_dl_nr_harq_ack_cfg_t srsran_ue_dl_nr_harq_ack_cfg = {}; + srsran_harq_ack_cfg_hl_t srsran_ue_dl_nr_harq_ack_cfg = {}; switch (phys_cell_group_cfg.pdsch_harq_ack_codebook) { case phys_cell_group_cfg_s::pdsch_harq_ack_codebook_opts::dynamic_value: srsran_ue_dl_nr_harq_ack_cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; diff --git a/lib/src/common/phy_cfg_nr.cc b/lib/src/common/phy_cfg_nr.cc index 115fa81c1..471a6ea62 100644 --- a/lib/src/common/phy_cfg_nr.cc +++ b/lib/src/common/phy_cfg_nr.cc @@ -274,10 +274,10 @@ bool phy_cfg_nr_t::get_pusch_cfg(const srsran_slot_cfg_t& slot_cfg, SRSRAN_SUCCESS; } -bool phy_cfg_nr_t::get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, - srsran_pdsch_ack_resource_nr_t& ack_resource) const +bool phy_cfg_nr_t::get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, + srsran_harq_ack_resource_t& ack_resource) const { - return srsran_ue_dl_nr_pdsch_ack_resource(&harq_ack, &dci_dl, &ack_resource) == SRSRAN_SUCCESS; + return srsran_harq_ack_resource(&harq_ack, &dci_dl, &ack_resource) == SRSRAN_SUCCESS; } bool phy_cfg_nr_t::get_uci_cfg(const srsran_slot_cfg_t& slot_cfg, diff --git a/lib/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c index ab85c3df9..c76e7a1c8 100644 --- a/lib/src/phy/gnb/gnb_ul.c +++ b/lib/src/phy/gnb/gnb_ul.c @@ -185,7 +185,7 @@ static int gnb_ul_decode_pucch_format1(srsran_gnb_ul_t* q, uint8_t b[SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS] = {}; // Set ACK bits - uint32_t nof_bits = SRSRAN_MIN(SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS, uci_cfg->o_ack); + uint32_t nof_bits = SRSRAN_MIN(SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS, uci_cfg->ack.count); // Set SR bits // For a positive SR transmission using PUCCH format 1, the UE transmits the PUCCH as described in [4, TS diff --git a/lib/src/phy/phch/harq_ack.c b/lib/src/phy/phch/harq_ack.c new file mode 100644 index 000000000..bd99cd1da --- /dev/null +++ b/lib/src/phy/phch/harq_ack.c @@ -0,0 +1,346 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/phy/phch/harq_ack.h" +#include "srsran/phy/utils/debug.h" +#include "srsran/phy/utils/vector.h" + +// Implements TS 38.213 Table 9.1.3-1: Value of counter DAI in DCI format 1_0 and of counter DAI or total DAI DCI format +// 1_1 +static uint32_t ue_dl_nr_V_DL_DAI(uint32_t dai) +{ + return dai + 1; +} + +static int harq_ack_gen_ack_type2(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_pdsch_ack_nr_t* ack_info, + srsran_uci_cfg_nr_t* uci_cfg) +{ + bool harq_ack_spatial_bundling = + ack_info->use_pusch ? cfg->harq_ack_spatial_bundling_pusch : cfg->harq_ack_spatial_bundling_pucch; + uint32_t m = 0; // PDCCH with DCI format 1_0 or DCI format 1_1 monitoring occasion index: lower index corresponds to + // earlier PDCCH with DCI format 1_0 or DCI format 1_1 monitoring occasion + uint32_t j = 0; + uint32_t V_temp = 0; + uint32_t V_temp2 = 0; + + uint32_t N_DL_cells = ack_info->nof_cc; // number of serving cells configured by higher layers for the UE + + // Initialise ACK bits + SRSRAN_MEM_ZERO(uci_cfg->ack.bits, srsran_harq_ack_bit_t, SRSRAN_HARQ_ACK_MAX_NOF_BITS); + + // The following code follows the exact pseudo-code provided in TS 38.213 9.1.3.1 Type-2 HARQ-ACK codebook ... + while (m < SRSRAN_UCI_NR_MAX_M) { + uint32_t c = 0; // serving cell index: lower indexes correspond to lower RRC indexes of corresponding cell + while (c < N_DL_cells) { + // Get ACK information of serving cell c for the PDCH monitoring occasion m + const srsran_harq_ack_m_t* ack = &ack_info->cc[c].m[m]; + + // Get DAI counter value + uint32_t V_DL_CDAI = ue_dl_nr_V_DL_DAI(ack->resource.v_dai_dl); + uint32_t V_DL_TDAI = ack->resource.dci_format_1_1 ? ue_dl_nr_V_DL_DAI(ack->resource.v_dai_dl) : UINT32_MAX; + + // Get ACK values + srsran_harq_ack_bit_t ack_tb0 = {}; + ack_tb0.tb0 = true; + ack_tb0.cc_idx = c; + ack_tb0.m_idx = m; + ack_tb0.pid = ack->resource.pid; + srsran_harq_ack_bit_t ack_tb1 = {}; + ack_tb1.tb1 = true; + ack_tb1.cc_idx = c; + ack_tb1.m_idx = m; + ack_tb1.pid = ack->resource.pid; + + // For a PDCCH monitoring occasion with DCI format 1_0 or DCI format 1_1 in the active DL BWP of a serving cell, + // when a UE receives a PDSCH with one transport block and the value of maxNrofCodeWordsScheduledByDCI is 2, the + // HARQ-ACK information is associated with the first transport block and the UE generates a NACK for the second + // transport block if harq-ACK-SpatialBundlingPUCCH is not provided and generates HARQ-ACK information with + // value of ACK for the second transport block if harq-ACK-SpatialBundlingPUCCH is provided. + if (cfg->max_cw_sched_dci_is_2 && !ack->second_tb_present) { + ack_tb1.tb1 = false; + } + + // if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c or an active UL + // BWP change on the PCell and an active DL BWP change is not triggered by a DCI format 1_1 in PDCCH + // monitoring occasion m + if (ack->dl_bwp_changed || ack->ul_bwp_changed) { + c = c + 1; + } else { + if (ack->present) { + // Load ACK resource data into UCI info + uci_cfg->pucch.resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id; + uci_cfg->pucch.rnti = ack_info->cc[c].m[m].resource.rnti; + + if (V_DL_CDAI <= V_temp) { + j = j + 1; + } + + V_temp = V_DL_CDAI; + + if (V_DL_TDAI == UINT32_MAX) { + V_temp2 = V_DL_CDAI; + } else { + V_temp2 = V_DL_TDAI; + } + + // if harq-ACK-SpatialBundlingPUCCH is not provided and m is a monitoring occasion for PDCCH with DCI format + // 1_0 or DCI format 1_1 and the UE is configured by maxNrofCodeWordsScheduledByDCI with reception of two + // transport blocks for at least one configured DL BWP of at least one serving cell, + if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) { + uci_cfg->ack.bits[8 * j + 2 * (V_DL_CDAI - 1) + 0] = ack_tb0; + uci_cfg->ack.bits[8 * j + 2 * (V_DL_CDAI - 1) + 1] = ack_tb1; + } + // elseif harq-ACK-SpatialBundlingPUCCH is provided to the UE and m is a monitoring occasion for + // PDCCH with DCI format 1_1 and the UE is configured by maxNrofCodeWordsScheduledByDCI with + // reception of two transport blocks in at least one configured DL BWP of a serving cell, + else if (harq_ack_spatial_bundling && ack->resource.dci_format_1_1 && cfg->max_cw_sched_dci_is_2) { + ack_tb0.tb1 = true; + uci_cfg->ack.bits[4 * j + (V_DL_CDAI - 1)] = ack_tb0; + } + // else + else { + uci_cfg->ack.bits[4 * j + (V_DL_CDAI - 1)] = ack_tb0; + } + } + c = c + 1; + } + } + m = m + 1; + } + if (V_temp2 < V_temp) { + j = j + 1; + } + + // if harq-ACK-SpatialBundlingPUCCH is not provided to the UE and the UE is configured by + // maxNrofCodeWordsScheduledByDCI with reception of two transport blocks for at least one configured DL BWP of a + // serving cell, + if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) { + uci_cfg->ack.count = 2 * (4 * j + V_temp2); + } else { + uci_cfg->ack.count = 4 * j + V_temp2; + } + + // Implement here SPS PDSCH reception + // ... + + return SRSRAN_SUCCESS; +} + +static int harq_ack_k1(const srsran_harq_ack_cfg_hl_t* cfg, const srsran_dci_dl_nr_t* dci_dl) +{ + // For DCI format 1_0, the PDSCH-to-HARQ_feedback timing indicator field values map to {1, 2, 3, 4, 5, 6, 7, 8} + if (dci_dl->ctx.format == srsran_dci_format_nr_1_0) { + return (int)dci_dl->harq_feedback + 1; + } + + // For DCI format 1_1, if present, the PDSCH-to-HARQ_feedback timing indicator field values map to values for a set of + // number of slots provided by dl-DataToUL-ACK as defined in Table 9.2.3-1. + if (dci_dl->harq_feedback >= SRSRAN_MAX_NOF_DL_DATA_TO_UL || dci_dl->harq_feedback >= cfg->nof_dl_data_to_ul_ack) { + ERROR("Out-of-range PDSCH-to-HARQ feedback index (%d, max %d)", dci_dl->harq_feedback, cfg->nof_dl_data_to_ul_ack); + return SRSRAN_ERROR; + } + + return (int)cfg->dl_data_to_ul_ack[dci_dl->harq_feedback]; +} + +int srsran_harq_ack_resource(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_dci_dl_nr_t* dci_dl, + srsran_harq_ack_resource_t* pdsch_ack_resource) +{ + if (cfg == NULL || dci_dl == NULL || pdsch_ack_resource == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Calculate Data to UL ACK timing k1 + int k1 = harq_ack_k1(cfg, dci_dl); + if (k1 < SRSRAN_ERROR) { + ERROR("Error calculating K1"); + return SRSRAN_ERROR; + } + + // Fill PDSCH resource + pdsch_ack_resource->dci_format_1_1 = (dci_dl->ctx.format == srsran_dci_format_nr_1_1); + pdsch_ack_resource->k1 = k1; + pdsch_ack_resource->v_dai_dl = dci_dl->dai; + pdsch_ack_resource->rnti = dci_dl->ctx.rnti; + pdsch_ack_resource->pucch_resource_id = dci_dl->pucch_resource; + pdsch_ack_resource->pid = dci_dl->pid; + + return SRSRAN_SUCCESS; +} + +int srsran_harq_ack_gen_uci_cfg(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_pdsch_ack_nr_t* ack_info, + srsran_uci_cfg_nr_t* uci_cfg) +{ + // Check inputs + if (cfg == NULL || ack_info == NULL || uci_cfg == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // According TS 38.213 9.1.2 Type-1 HARQ-ACK codebook determination + if (cfg->harq_ack_codebook == srsran_pdsch_harq_ack_codebook_semi_static) { + // This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = semi-static. + ERROR("Type-1 HARQ-ACK codebook determination is NOT implemented"); + return SRSRAN_ERROR; + } + + // According TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination + if (cfg->harq_ack_codebook == srsran_pdsch_harq_ack_codebook_dynamic) { + // This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = dynamic. + return harq_ack_gen_ack_type2(cfg, ack_info, uci_cfg); + } + + ERROR("No HARQ-ACK codebook determination is NOT implemented"); + return SRSRAN_ERROR; +} + +int srsran_harq_ack_pack(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_pdsch_ack_nr_t* ack_info, + srsran_uci_data_nr_t* uci_data) +{ + // Check inputs + if (cfg == NULL || ack_info == NULL || uci_data == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Generate configuration + if (srsran_harq_ack_gen_uci_cfg(cfg, ack_info, &uci_data->cfg) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + // Actual packing + for (uint32_t i = 0; i < uci_data->cfg.ack.count; i++) { + srsran_harq_ack_bit_t* ack_bit = &uci_data->cfg.ack.bits[i]; + + // Skip bit if no TB is used + if (!ack_bit->tb0 && !ack_bit->tb1) { + uci_data->value.ack[i] = 0; + continue; + } + + // Only TB0 + if (ack_bit->tb0 && !ack_bit->tb1) { + uci_data->value.ack[i] = ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[0]; + continue; + } + + // Only TB1 + if (!ack_bit->tb0 && ack_bit->tb1) { + uci_data->value.ack[i] = ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[1]; + continue; + } + + // Both TB with bundling + uci_data->value.ack[i] = ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[0]; + uci_data->value.ack[i] &= ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[1]; + } + + return SRSRAN_SUCCESS; +} + +int srsran_harq_ack_unpack(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_uci_data_nr_t* uci_data, + srsran_pdsch_ack_nr_t* ack_info) +{ + // Check inputs + if (cfg == NULL || ack_info == NULL || uci_data == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Actual packing + for (uint32_t i = 0; i < uci_data->cfg.ack.count; i++) { + const srsran_harq_ack_bit_t* ack_bit = &uci_data->cfg.ack.bits[i]; + + // Extract TB0 + if (ack_bit->tb0) { + ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[0] = uci_data->value.ack[i]; + } + + // Extract TB1 + if (ack_bit->tb1) { + ack_info->cc[ack_bit->cc_idx].m[ack_bit->m_idx].value[1] = uci_data->value.ack[i]; + } + } + + return SRSRAN_SUCCESS; +} + +int srsran_harq_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_harq_ack_m_t* m) +{ + // Check inputs + if (ack_info == NULL || m == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Protect SCell index and extract information + if (m->resource.scell_idx >= SRSRAN_MAX_CARRIERS) { + ERROR("Serving cell index (%d) exceeds maximum", m->resource.scell_idx); + return SRSRAN_ERROR; + } + srsran_harq_ack_cc_t* cc = &ack_info->cc[m->resource.scell_idx]; + + // Find insertion index + uint32_t idx = cc->M; // Append at the end by default + for (uint32_t i = 0; i < cc->M; i++) { + if (cc->m[i].resource.k1 < m->resource.k1) { + idx = i; + break; + } + } + + // Increment count + cc->M += 1; + + // Make space for insertion + for (uint32_t i = cc->M - 1; i > idx; i--) { + cc->m[i] = cc->m[i - 1]; + } + + // Actual insertion + cc->m[idx] = *m; + + return SRSRAN_SUCCESS; +} + +uint32_t srsran_harq_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len) +{ + uint32_t len = 0; + + if (ack_info == NULL || str == NULL) { + return 0; + } + + // Print base info + len = srsran_print_check( + str, str_len, len, "use_pusch=%c nof_cc=%d\n", ack_info->use_pusch ? 'y' : 'n', ack_info->nof_cc); + + // Iterate all carriers + for (uint32_t cc = 0; cc < ack_info->nof_cc; cc++) { + len = srsran_print_check(str, str_len, len, " CC %d: M=%d\n", cc, ack_info->cc[cc].M); + for (uint32_t m = 0; m < ack_info->cc[cc].M; m++) { + if (ack_info->cc[cc].m[m].present) { + len = srsran_print_check(str, + str_len, + len, + " m %d: k1=%d dai=%d ack=%d\n", + m, + ack_info->cc[cc].m[m].resource.k1, + ack_info->cc[cc].m[m].resource.v_dai_dl, + ack_info->cc[cc].m[m].value[0]); + } + } + } + + return len; +} \ No newline at end of file diff --git a/lib/src/phy/phch/phch_cfg_nr.c b/lib/src/phy/phch/phch_cfg_nr.c index 246367aa1..cb34a4d8e 100644 --- a/lib/src/phy/phch/phch_cfg_nr.c +++ b/lib/src/phy/phch/phch_cfg_nr.c @@ -229,7 +229,7 @@ static uint32_t phch_cfg_uci_to_str(const srsran_uci_cfg_nr_t* uci, char* str, u len = srsran_print_check(str, str_len, len, " beta_csi_part1_offset=%.2f\n", uci->pusch.beta_csi1_offset); len = srsran_print_check(str, str_len, len, " beta_csi_part2_offset=%.2f\n", uci->pusch.beta_csi1_offset); len = srsran_print_check(str, str_len, len, " o_csi1=%d\n", srsran_csi_part1_nof_bits(uci->csi, uci->nof_csi)); - len = srsran_print_check(str, str_len, len, " o_ack=%d\n", uci->o_ack); + len = srsran_print_check(str, str_len, len, " o_ack=%d\n", uci->ack.count); return len; } diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index df155d9fe..184ac6f62 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -374,7 +374,7 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t* // if the number of HARQ-ACK information bits to be transmitted on PUSCH is 0, 1 or 2 bits uint32_t G_ack_rvd = 0; - if (cfg->o_ack <= 2) { + if (cfg->ack.count <= 2) { // the number of reserved resource elements for potential HARQ-ACK transmission is calculated according to Clause // 6.3.2.4.2.1, by setting O_ACK = 2 ; G_ack_rvd = srsran_uci_nr_pusch_ack_nof_bits(&cfg->pusch, 2); @@ -412,7 +412,7 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t* uint32_t ack_d = 0; uint32_t ack_m_re_count = 0; if (l >= l1) { - if (cfg->o_ack <= 2 && m_ack_count < G_ack_rvd) { + if (cfg->ack.count <= 2 && m_ack_count < G_ack_rvd) { ack_d = 1; ack_m_re_count = M_ulsch_sc; if (G_ack_rvd - m_ack_count < M_uci_sc * Nl * Qm) { @@ -498,7 +498,7 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t* // Set reserved bits only if there are ACK bits if (reserved) { - if (cfg->o_ack > 0) { + if (cfg->ack.count > 0) { for (uint32_t j = 0; j < Nl * Qm; j++) { pos_ack[m_ack_count++] = m_all_count + j; } @@ -531,7 +531,7 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t* q->G_ulsch = m_ulsch_count; // Assert Number of bits - if (G_ack_rvd != 0 && G_ack_rvd != m_ack_count && cfg->o_ack > 0) { + if (G_ack_rvd != 0 && G_ack_rvd != m_ack_count && cfg->ack.count > 0) { ERROR("Not matched %d!=%d", G_ack_rvd, m_ack_count); } if (G_ack != 0 && G_ack != m_ack_count) { @@ -551,7 +551,7 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t* DEBUG("UL-SCH bit positions:"); srsran_vec_fprint_i(stdout, (int*)pos_ulsch, m_ulsch_count); } - if (m_ack_count != 0 && cfg->o_ack > 0) { + if (m_ack_count != 0 && cfg->ack.count > 0) { DEBUG("HARQ-ACK bit positions [%d]:", m_ack_count); srsran_vec_fprint_i(stdout, (int*)pos_ack, m_ack_count); } @@ -662,7 +662,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q, srsran_sequence_apply_bit(b, q->b[tb->cw_idx], nof_bits, cinit); // Special Scrambling condition - if (cfg->uci.o_ack <= 2) { + if (cfg->uci.ack.count <= 2) { for (uint32_t i = 0; i < q->G_ack; i++) { uint32_t idx = q->pos_ack[i]; if (q->g_ack[i] == (uint8_t)UCI_BIT_REPETITION) { @@ -793,7 +793,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, uint32_t nof_bits = tb->nof_re * srsran_mod_bits_x_symbol(tb->mod); // Calculate HARQ-ACK bits - int n = srsran_uci_nr_pusch_ack_nof_bits(&cfg->uci.pusch, cfg->uci.o_ack); + int n = srsran_uci_nr_pusch_ack_nof_bits(&cfg->uci.pusch, cfg->uci.ack.count); if (n < SRSRAN_SUCCESS) { ERROR("Calculating G_ack"); return SRSRAN_ERROR; diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 5a7009f33..fd58a698a 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -824,9 +824,9 @@ static float ra_ul_beta_offset_ack_semistatic(const srsran_beta_offsets_t* beta_ // Select Beta Offset index from the number of HARQ-ACK bits uint32_t beta_offset_index = beta_offsets->ack_index1; - if (uci_cfg->o_ack > 11) { + if (uci_cfg->ack.count > 11) { beta_offset_index = beta_offsets->ack_index3; - } else if (uci_cfg->o_ack > 2) { + } else if (uci_cfg->ack.count > 2) { beta_offset_index = beta_offsets->ack_index2; } @@ -834,7 +834,7 @@ static float ra_ul_beta_offset_ack_semistatic(const srsran_beta_offsets_t* beta_ if (beta_offset_index >= RA_NR_BETA_OFFSET_HARQACK_SIZE) { ERROR("Beta offset index for HARQ-ACK (%d) for O_ack=%d exceeds table size (%d)", beta_offset_index, - uci_cfg->o_ack, + uci_cfg->ack.count, RA_NR_BETA_OFFSET_HARQACK_SIZE); return NAN; } @@ -1022,8 +1022,8 @@ int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carrier, // Calculate number of UCI encoded bits int Gack = 0; - if (pusch_cfg->uci.o_ack > 2) { - Gack = srsran_uci_nr_pusch_ack_nof_bits(&pusch_cfg->uci.pusch, pusch_cfg->uci.o_ack); + if (pusch_cfg->uci.ack.count > 2) { + Gack = srsran_uci_nr_pusch_ack_nof_bits(&pusch_cfg->uci.pusch, pusch_cfg->uci.ack.count); if (Gack < SRSRAN_SUCCESS) { ERROR("Error calculating Qdack"); return SRSRAN_ERROR; diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index 065ef8736..ce4e722bd 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -420,7 +420,7 @@ int srsran_ra_ul_nr_pucch_format_2_3_min_prb(const srsran_pucch_nr_resource_t* r } // Compute total number of UCI bits - uint32_t O_total = uci_cfg->o_ack + uci_cfg->o_sr + srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); + uint32_t O_total = uci_cfg->ack.count + uci_cfg->o_sr + srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); // Add CRC bits if any O_total += srsran_uci_nr_crc_len(O_total); @@ -530,7 +530,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // - At least one positive SR // - up to 2 HARQ-ACK // - No CSI report - if (uci_cfg->pucch.sr_positive_present > 0 && uci_cfg->o_ack <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && + if (uci_cfg->pucch.sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) { uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id; if (sr_resource_id >= SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES) { @@ -554,7 +554,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // - Irrelevant SR opportunities // - More than 2 HARQ-ACK // - No CSI report - if (uci_cfg->o_sr > 0 && uci_cfg->o_ack > SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) { + if (uci_cfg->o_sr > 0 && uci_cfg->ack.count > SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) { return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, resource); } @@ -562,7 +562,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // - Irrelevant SR opportunities // - No HARQ-ACK // - Single periodic CSI report - if (uci_cfg->o_ack == 0 && uci_cfg->nof_csi == 1 && uci_cfg->csi[0].type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) { + if (uci_cfg->ack.count == 0 && uci_cfg->nof_csi == 1 && uci_cfg->csi[0].type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) { *resource = uci_cfg->csi[0].pucch_resource; return SRSRAN_SUCCESS; } diff --git a/lib/src/phy/phch/test/pucch_nr_test.c b/lib/src/phy/phch/test/pucch_nr_test.c index 5b99ab0c8..933f3661a 100644 --- a/lib/src/phy/phch/test/pucch_nr_test.c +++ b/lib/src/phy/phch/test/pucch_nr_test.c @@ -177,13 +177,14 @@ static int test_pucch_format2(srsran_pucch_nr_t* pucch, resource.start_symbol_idx += starting_symbol_stride) { srsran_uci_cfg_nr_t uci_cfg = {}; - for (uci_cfg.o_ack = SRSRAN_PUCCH_NR_FORMAT2_MIN_NOF_BITS; uci_cfg.o_ack <= SRSRAN_UCI_NR_MAX_ACK_BITS; - uci_cfg.o_ack++) { + for (uci_cfg.ack.count = SRSRAN_PUCCH_NR_FORMAT2_MIN_NOF_BITS; + uci_cfg.ack.count <= SRSRAN_HARQ_ACK_MAX_NOF_BITS; + uci_cfg.ack.count++) { srsran_uci_value_nr_t uci_value = {}; // Maximum code rate is reserved uint32_t max_code_rate_end = SRSRAN_PUCCH_NR_MAX_CODE_RATE; - if (uci_cfg.o_ack == 11) { + if (uci_cfg.ack.count == 11) { max_code_rate_end = SRSRAN_PUCCH_NR_MAX_CODE_RATE - 1; } @@ -198,7 +199,7 @@ static int test_pucch_format2(srsran_pucch_nr_t* pucch, for (resource.starting_prb = 0; resource.starting_prb < (carrier.nof_prb - resource.nof_prb); resource.starting_prb += starting_prb_stride) { // Generate ACKs - for (uint32_t i = 0; i < uci_cfg.o_ack; i++) { + for (uint32_t i = 0; i < uci_cfg.ack.count; i++) { uci_value.ack[i] = (uint8_t)srsran_random_uniform_int_dist(random_gen, 0, 1); } @@ -234,7 +235,7 @@ static int test_pucch_format2(srsran_pucch_nr_t* pucch, TESTASSERT(uci_value_rx.valid == true); // Check received ACKs - for (uint32_t i = 0; i < uci_cfg.o_ack; i++) { + for (uint32_t i = 0; i < uci_cfg.ack.count; i++) { TESTASSERT(uci_value.ack[i] == uci_value_rx.ack[i]); } } diff --git a/lib/src/phy/phch/test/pusch_nr_test.c b/lib/src/phy/phch/test/pusch_nr_test.c index f88e1b938..508649ab7 100644 --- a/lib/src/phy/phch/test/pusch_nr_test.c +++ b/lib/src/phy/phch/test/pusch_nr_test.c @@ -225,7 +225,7 @@ int main(int argc, char** argv) // Generate HARQ ACK bits if (nof_ack_bits > 0) { - pusch_cfg.uci.o_ack = nof_ack_bits; + pusch_cfg.uci.ack.count = nof_ack_bits; for (uint32_t i = 0; i < nof_ack_bits; i++) { data_tx.uci.ack[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, 1); } diff --git a/lib/src/phy/phch/uci_nr.c b/lib/src/phy/phch/uci_nr.c index 2968d173d..14e169441 100644 --- a/lib/src/phy/phch/uci_nr.c +++ b/lib/src/phy/phch/uci_nr.c @@ -156,8 +156,8 @@ static int uci_nr_pack_ack_sr(const srsran_uci_cfg_nr_t* cfg, const srsran_uci_v int A = 0; // Append ACK bits - srsran_vec_u8_copy(&sequence[A], value->ack, cfg->o_ack); - A += cfg->o_ack; + srsran_vec_u8_copy(&sequence[A], value->ack, cfg->ack.count); + A += cfg->ack.count; // Append SR bits uint8_t* bits = &sequence[A]; @@ -177,8 +177,8 @@ static int uci_nr_unpack_ack_sr(const srsran_uci_cfg_nr_t* cfg, uint8_t* sequenc int A = 0; // Append ACK bits - srsran_vec_u8_copy(value->ack, &sequence[A], cfg->o_ack); - A += cfg->o_ack; + srsran_vec_u8_copy(value->ack, &sequence[A], cfg->ack.count); + A += cfg->ack.count; // Append SR bits uint8_t* bits = &sequence[A]; @@ -198,8 +198,8 @@ static int uci_nr_pack_ack_sr_csi(const srsran_uci_cfg_nr_t* cfg, const srsran_u int A = 0; // Append ACK bits - srsran_vec_u8_copy(&sequence[A], value->ack, cfg->o_ack); - A += cfg->o_ack; + srsran_vec_u8_copy(&sequence[A], value->ack, cfg->ack.count); + A += cfg->ack.count; // Append SR bits uint8_t* bits = &sequence[A]; @@ -227,8 +227,8 @@ static int uci_nr_unpack_ack_sr_csi(const srsran_uci_cfg_nr_t* cfg, uint8_t* seq int A = 0; // Append ACK bits - srsran_vec_u8_copy(value->ack, &sequence[A], cfg->o_ack); - A += cfg->o_ack; + srsran_vec_u8_copy(value->ack, &sequence[A], cfg->ack.count); + A += cfg->ack.count; // Append SR bits uint8_t* bits = &sequence[A]; @@ -256,11 +256,11 @@ static int uci_nr_A(const srsran_uci_cfg_nr_t* cfg) // 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation if (o_csi == 0) { - return cfg->o_ack + cfg->o_sr; + return cfg->ack.count + cfg->o_sr; } // 6.3.1.1.2 CSI only - if (cfg->o_ack == 0 && cfg->o_sr == 0) { + if (cfg->ack.count == 0 && cfg->o_sr == 0) { return o_csi; } @@ -279,7 +279,7 @@ static int uci_nr_pack_pucch(const srsran_uci_cfg_nr_t* cfg, const srsran_uci_va } // 6.3.1.1.2 CSI only - if (cfg->o_ack == 0 && cfg->o_sr == 0) { + if (cfg->ack.count == 0 && cfg->o_sr == 0) { return srsran_csi_part1_pack(cfg->csi, value->csi, cfg->nof_csi, sequence, SRSRAN_UCI_NR_MAX_NOF_BITS); } @@ -297,7 +297,7 @@ static int uci_nr_unpack_pucch(const srsran_uci_cfg_nr_t* cfg, uint8_t* sequence } // 6.3.1.1.2 CSI only - if (cfg->o_ack == 0 && cfg->o_sr == 0) { + if (cfg->ack.count == 0 && cfg->o_sr == 0) { ERROR("CSI only are not implemented"); return SRSRAN_ERROR; } @@ -980,16 +980,16 @@ uint32_t srsran_uci_nr_total_bits(const srsran_uci_cfg_nr_t* uci_cfg) return 0; } - return uci_cfg->o_ack + uci_cfg->o_sr + srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); + return uci_cfg->ack.count + uci_cfg->o_sr + srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); } uint32_t srsran_uci_nr_info(const srsran_uci_data_nr_t* uci_data, char* str, uint32_t str_len) { uint32_t len = 0; - if (uci_data->cfg.o_ack > 0) { + if (uci_data->cfg.ack.count > 0) { char str_ack[10]; - srsran_vec_sprint_bin(str_ack, (uint32_t)sizeof(str_ack), uci_data->value.ack, uci_data->cfg.o_ack); + srsran_vec_sprint_bin(str_ack, (uint32_t)sizeof(str_ack), uci_data->value.ack, uci_data->cfg.ack.count); len = srsran_print_check(str, str_len, len, "ack=%s ", str_ack); } @@ -1066,7 +1066,7 @@ int srsran_uci_nr_encode_pusch_ack(srsran_uci_nr_t* q, return SRSRAN_ERROR_INVALID_INPUTS; } - int A = cfg->o_ack; + int A = cfg->ack.count; // 6.3.2.1 UCI bit sequence generation // 6.3.2.1.1 HARQ-ACK @@ -1079,7 +1079,7 @@ int srsran_uci_nr_encode_pusch_ack(srsran_uci_nr_t* q, UCI_NR_INFO_TX("No HARQ-ACK to mux"); return SRSRAN_SUCCESS; } else { - srsran_vec_u8_copy(q->bit_sequence, value->ack, cfg->o_ack); + srsran_vec_u8_copy(q->bit_sequence, value->ack, cfg->ack.count); } // Compute total of encoded bits according to 6.3.2.4 Rate matching @@ -1102,12 +1102,12 @@ int srsran_uci_nr_decode_pusch_ack(srsran_uci_nr_t* q, return SRSRAN_ERROR_INVALID_INPUTS; } - int A = cfg->o_ack; + int A = cfg->ack.count; // 6.3.2.1 UCI bit sequence generation // 6.3.2.1.1 HARQ-ACK bool has_csi_part2 = srsran_csi_has_part2(cfg->csi, cfg->nof_csi); - if (cfg->pusch.K_sum == 0 && cfg->nof_csi > 1 && !has_csi_part2 && cfg->o_ack < 2) { + if (cfg->pusch.K_sum == 0 && cfg->nof_csi > 1 && !has_csi_part2 && cfg->ack.count < 2) { A = 2; } @@ -1178,7 +1178,7 @@ int srsran_uci_nr_pusch_csi1_nof_bits(const srsran_uci_cfg_nr_t* cfg) ERROR("Errpr calculating CSI part 1 number of bits"); return SRSRAN_ERROR; } - uint32_t O_ack = SRSRAN_MAX(2, cfg->o_ack); + uint32_t O_ack = SRSRAN_MAX(2, cfg->ack.count); int Q_csi1_prime = uci_nr_pusch_Q_prime_csi1(&cfg->pusch, (uint32_t)O_csi1, O_ack); if (Q_csi1_prime < SRSRAN_SUCCESS) { diff --git a/lib/src/phy/ue/test/gen_ack_nr_test.c b/lib/src/phy/ue/test/gen_ack_nr_test.c index 378df6b5b..7a95e98c9 100644 --- a/lib/src/phy/ue/test/gen_ack_nr_test.c +++ b/lib/src/phy/ue/test/gen_ack_nr_test.c @@ -11,57 +11,58 @@ */ #include "srsran/common/test_common.h" -#include "srsran/phy/ue/ue_dl_nr.h" +#include "srsran/phy/phch/harq_ack.h" +#include "srsran/phy/utils/debug.h" #include static int test_case_1() { // Set configuration - srsran_ue_dl_nr_harq_ack_cfg_t cfg = {}; - cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; + srsran_harq_ack_cfg_hl_t cfg = {}; + cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; // Generate ACK information srsran_pdsch_ack_nr_t ack_info = {}; ack_info.nof_cc = 1; ack_info.use_pusch = true; - srsran_pdsch_ack_m_nr_t m = {}; - m.value[0] = 1; - m.present = true; + srsran_harq_ack_m_t m = {}; + m.value[0] = 1; + m.present = true; m.resource.k1 = 8; m.resource.v_dai_dl = 0; m.value[0] = 1; m.present = true; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); m.resource.k1 = 5; m.resource.v_dai_dl = 2; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); m.resource.k1 = 6; m.resource.v_dai_dl = 1; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); m.resource.k1 = 4; m.resource.v_dai_dl = 3; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); m.resource.k1 = 3; m.resource.v_dai_dl = 0; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); // Print trace char str[512] = {}; - TESTASSERT(srsran_ue_dl_nr_ack_info(&ack_info, str, (uint32_t)sizeof(str)) > SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_info(&ack_info, str, (uint32_t)sizeof(str)) > SRSRAN_SUCCESS); INFO("%s", str); // Generate UCI data srsran_uci_data_nr_t uci_data = {}; - TESTASSERT(srsran_ue_dl_nr_gen_ack(&cfg, &ack_info, &uci_data) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_pack(&cfg, &ack_info, &uci_data) == SRSRAN_SUCCESS); // Assert UCI data - TESTASSERT(uci_data.cfg.o_ack == 5); + TESTASSERT(uci_data.cfg.ack.count == 5); return SRSRAN_SUCCESS; } @@ -69,49 +70,56 @@ static int test_case_1() static int test_case_2() { // Set configuration - srsran_ue_dl_nr_harq_ack_cfg_t cfg = {}; - cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; + srsran_harq_ack_cfg_hl_t cfg = {}; + cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; // Generate ACK information srsran_pdsch_ack_nr_t ack_info = {}; ack_info.nof_cc = 1; ack_info.use_pusch = true; - srsran_pdsch_ack_m_nr_t m = {}; - m.value[0] = 1; - m.present = true; + srsran_harq_ack_m_t m = {}; + m.value[0] = 1; + m.present = true; m.resource.k1 = 7; m.resource.v_dai_dl = 1; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); m.resource.k1 = 6; m.resource.v_dai_dl = 2; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); m.resource.k1 = 8; m.resource.v_dai_dl = 0; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); m.resource.k1 = 5; m.resource.v_dai_dl = 3; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); m.resource.k1 = 4; m.resource.v_dai_dl = 0; - TESTASSERT(srsran_ue_dl_nr_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_insert_m(&ack_info, &m) == SRSRAN_SUCCESS); // Print trace char str[512] = {}; - TESTASSERT(srsran_ue_dl_nr_ack_info(&ack_info, str, (uint32_t)sizeof(str)) > SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_info(&ack_info, str, (uint32_t)sizeof(str)) > SRSRAN_SUCCESS); INFO("%s", str); // Generate UCI data srsran_uci_data_nr_t uci_data = {}; - TESTASSERT(srsran_ue_dl_nr_gen_ack(&cfg, &ack_info, &uci_data) == SRSRAN_SUCCESS); + TESTASSERT(srsran_harq_ack_pack(&cfg, &ack_info, &uci_data) == SRSRAN_SUCCESS); // Assert UCI data - TESTASSERT(uci_data.cfg.o_ack == 5); + TESTASSERT(uci_data.cfg.ack.count == 5); + + // Unpack HARQ ACK UCI data + srsran_pdsch_ack_nr_t ack_info_rx = ack_info; + TESTASSERT(srsran_harq_ack_unpack(&cfg, &uci_data, &ack_info_rx) == SRSRAN_SUCCESS); + + // Assert unpacked data + TESTASSERT(memcmp(&ack_info, &ack_info_rx, sizeof(srsran_pdsch_ack_nr_t)) == 0); return SRSRAN_SUCCESS; } diff --git a/lib/src/phy/ue/ue_dl_nr.c b/lib/src/phy/ue/ue_dl_nr.c index 9693b55bd..74777cf0e 100644 --- a/lib/src/phy/ue/ue_dl_nr.c +++ b/lib/src/phy/ue/ue_dl_nr.c @@ -590,255 +590,6 @@ int srsran_ue_dl_nr_pdsch_info(const srsran_ue_dl_nr_t* q, return len; } -// Implements TS 38.213 Table 9.1.3-1: Value of counter DAI in DCI format 1_0 and of counter DAI or total DAI DCI format -// 1_1 -static uint32_t ue_dl_nr_V_DL_DAI(uint32_t dai) -{ - return dai + 1; -} - -static int ue_dl_nr_gen_ack_type2(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg, - const srsran_pdsch_ack_nr_t* ack_info, - srsran_uci_data_nr_t* uci_data) -{ - bool harq_ack_spatial_bundling = - ack_info->use_pusch ? cfg->harq_ack_spatial_bundling_pusch : cfg->harq_ack_spatial_bundling_pucch; - uint8_t* o_ack = uci_data->value.ack; - - uint32_t m = 0; // PDCCH with DCI format 1_0 or DCI format 1_1 monitoring occasion index: lower index corresponds to - // earlier PDCCH with DCI format 1_0 or DCI format 1_1 monitoring occasion - uint32_t j = 0; - uint32_t V_temp = 0; - uint32_t V_temp2 = 0; - - uint32_t N_DL_cells = ack_info->nof_cc; // number of serving cells configured by higher layers for the UE - - // The following code follows the exact pseudo-code provided in TS 38.213 9.1.3.1 Type-2 HARQ-ACK codebook ... - while (m < SRSRAN_UCI_NR_MAX_M) { - uint32_t c = 0; // serving cell index: lower indexes correspond to lower RRC indexes of corresponding cell - while (c < N_DL_cells) { - // Get ACK information of serving cell c for the PDCH monitoring occasion m - const srsran_pdsch_ack_m_nr_t* ack = &ack_info->cc[c].m[m]; - - // Get DAI counter value - uint32_t V_DL_CDAI = ue_dl_nr_V_DL_DAI(ack->resource.v_dai_dl); - uint32_t V_DL_TDAI = ack->resource.dci_format_1_1 ? ue_dl_nr_V_DL_DAI(ack->resource.v_dai_dl) : UINT32_MAX; - - // Get ACK values - uint32_t ack_tb0 = ack->value[0]; - uint32_t ack_tb1 = ack->value[1]; - - // For a PDCCH monitoring occasion with DCI format 1_0 or DCI format 1_1 in the active DL BWP of a serving cell, - // when a UE receives a PDSCH with one transport block and the value of maxNrofCodeWordsScheduledByDCI is 2, the - // HARQ-ACK information is associated with the first transport block and the UE generates a NACK for the second - // transport block if harq-ACK-SpatialBundlingPUCCH is not provided and generates HARQ-ACK information with - // value of ACK for the second transport block if harq-ACK-SpatialBundlingPUCCH is provided. - if (cfg->max_cw_sched_dci_is_2 && ack->second_tb_present) { - ack_tb1 = harq_ack_spatial_bundling ? 1 : 0; - } - - // if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c or an active UL - // BWP change on the PCell and an active DL BWP change is not triggered by a DCI format 1_1 in PDCCH - // monitoring occasion m - if (ack->dl_bwp_changed || ack->ul_bwp_changed) { - c = c + 1; - } else { - if (ack->present) { - // Load ACK resource data into UCI info - uci_data->cfg.pucch.resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id; - uci_data->cfg.pucch.rnti = ack_info->cc[c].m[m].resource.rnti; - - if (V_DL_CDAI <= V_temp) { - j = j + 1; - } - - V_temp = V_DL_CDAI; - - if (V_DL_TDAI == UINT32_MAX) { - V_temp2 = V_DL_CDAI; - } else { - V_temp2 = V_DL_TDAI; - } - - // if harq-ACK-SpatialBundlingPUCCH is not provided and m is a monitoring occasion for PDCCH with DCI format - // 1_0 or DCI format 1_1 and the UE is configured by maxNrofCodeWordsScheduledByDCI with reception of two - // transport blocks for at least one configured DL BWP of at least one serving cell, - if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) { - o_ack[8 * j + 2 * (V_DL_CDAI - 1) + 0] = ack_tb0; - o_ack[8 * j + 2 * (V_DL_CDAI - 1) + 1] = ack_tb1; - } - // elseif harq-ACK-SpatialBundlingPUCCH is provided to the UE and m is a monitoring occasion for - // PDCCH with DCI format 1_1 and the UE is configured by maxNrofCodeWordsScheduledByDCI with - // reception of two transport blocks in at least one configured DL BWP of a serving cell, - else if (harq_ack_spatial_bundling && ack->resource.dci_format_1_1 && cfg->max_cw_sched_dci_is_2) { - o_ack[4 * j + (V_DL_CDAI - 1)] = ack_tb0 & ack_tb1; - } - // else - else { - o_ack[4 * j + (V_DL_CDAI - 1)] = ack_tb0; - } - } - c = c + 1; - } - } - m = m + 1; - } - if (V_temp2 < V_temp) { - j = j + 1; - } - - // if harq-ACK-SpatialBundlingPUCCH is not provided to the UE and the UE is configured by - // maxNrofCodeWordsScheduledByDCI with reception of two transport blocks for at least one configured DL BWP of a - // serving cell, - if (!harq_ack_spatial_bundling && cfg->max_cw_sched_dci_is_2) { - uci_data->cfg.o_ack = 2 * (4 * j + V_temp2); - } else { - uci_data->cfg.o_ack = 4 * j + V_temp2; - } - - // Implement here SPS PDSCH reception - // ... - - return SRSRAN_SUCCESS; -} - -int ue_dl_nr_pdsch_k1(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg, const srsran_dci_dl_nr_t* dci_dl) -{ - // For DCI format 1_0, the PDSCH-to-HARQ_feedback timing indicator field values map to {1, 2, 3, 4, 5, 6, 7, 8} - if (dci_dl->ctx.format == srsran_dci_format_nr_1_0) { - return (int)dci_dl->harq_feedback + 1; - } - - // For DCI format 1_1, if present, the PDSCH-to-HARQ_feedback timing indicator field values map to values for a set of - // number of slots provided by dl-DataToUL-ACK as defined in Table 9.2.3-1. - if (dci_dl->harq_feedback >= SRSRAN_MAX_NOF_DL_DATA_TO_UL || dci_dl->harq_feedback >= cfg->nof_dl_data_to_ul_ack) { - ERROR("Out-of-range PDSCH-to-HARQ feedback index (%d, max %d)", dci_dl->harq_feedback, cfg->nof_dl_data_to_ul_ack); - return SRSRAN_ERROR; - } - - return (int)cfg->dl_data_to_ul_ack[dci_dl->harq_feedback]; -} - -int srsran_ue_dl_nr_pdsch_ack_resource(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg, - const srsran_dci_dl_nr_t* dci_dl, - srsran_pdsch_ack_resource_nr_t* pdsch_ack_resource) -{ - if (cfg == NULL || dci_dl == NULL || pdsch_ack_resource == NULL) { - return SRSRAN_ERROR_INVALID_INPUTS; - } - - // Calculate Data to UL ACK timing k1 - int k1 = ue_dl_nr_pdsch_k1(cfg, dci_dl); - if (k1 < SRSRAN_ERROR) { - ERROR("Error calculating K1"); - return SRSRAN_ERROR; - } - - // Fill PDSCH resource - pdsch_ack_resource->dci_format_1_1 = (dci_dl->ctx.format == srsran_dci_format_nr_1_1); - pdsch_ack_resource->k1 = k1; - pdsch_ack_resource->v_dai_dl = dci_dl->dai; - pdsch_ack_resource->rnti = dci_dl->ctx.rnti; - pdsch_ack_resource->pucch_resource_id = dci_dl->pucch_resource; - - return SRSRAN_SUCCESS; -} - -int srsran_ue_dl_nr_gen_ack(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg, - const srsran_pdsch_ack_nr_t* ack_info, - srsran_uci_data_nr_t* uci_data) -{ - // Check inputs - if (cfg == NULL || ack_info == NULL || uci_data == NULL) { - return SRSRAN_ERROR_INVALID_INPUTS; - } - - // According TS 38.213 9.1.2 Type-1 HARQ-ACK codebook determination - if (cfg->harq_ack_codebook == srsran_pdsch_harq_ack_codebook_semi_static) { - // This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = semi-static. - ERROR("Type-1 HARQ-ACK codebook determination is NOT implemented"); - return SRSRAN_ERROR; - } - - // According TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination - if (cfg->harq_ack_codebook == srsran_pdsch_harq_ack_codebook_dynamic) { - // This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = dynamic. - return ue_dl_nr_gen_ack_type2(cfg, ack_info, uci_data); - } - - ERROR("No HARQ-ACK codebook determination is NOT implemented"); - return SRSRAN_ERROR; -} - -int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, const srsran_pdsch_ack_m_nr_t* m) -{ - // Check inputs - if (ack_info == NULL || m == NULL) { - return SRSRAN_ERROR_INVALID_INPUTS; - } - - // Protect SCell index and extract information - if (m->resource.scell_idx >= SRSRAN_MAX_CARRIERS) { - ERROR("Serving cell index (%d) exceeds maximum", m->resource.scell_idx); - return SRSRAN_ERROR; - } - srsran_pdsch_ack_cc_nr_t* cc = &ack_info->cc[m->resource.scell_idx]; - - // Find insertion index - uint32_t idx = cc->M; // Append at the end by default - for (uint32_t i = 0; i < cc->M; i++) { - if (cc->m[i].resource.k1 < m->resource.k1) { - idx = i; - break; - } - } - - // Increment count - cc->M += 1; - - // Make space for insertion - for (uint32_t i = cc->M - 1; i > idx; i--) { - cc->m[i] = cc->m[i - 1]; - } - - // Actual insertion - cc->m[idx] = *m; - - return SRSRAN_SUCCESS; -} - -uint32_t srsran_ue_dl_nr_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len) -{ - uint32_t len = 0; - - if (ack_info == NULL || str == NULL) { - return 0; - } - - // Print base info - len = srsran_print_check( - str, str_len, len, "use_pusch=%c nof_cc=%d\n", ack_info->use_pusch ? 'y' : 'n', ack_info->nof_cc); - - // Iterate all carriers - for (uint32_t cc = 0; cc < ack_info->nof_cc; cc++) { - len = srsran_print_check(str, str_len, len, " CC %d: M=%d\n", cc, ack_info->cc[cc].M); - for (uint32_t m = 0; m < ack_info->cc[cc].M; m++) { - if (ack_info->cc[cc].m[m].present) { - len = srsran_print_check(str, - str_len, - len, - " m %d: k1=%d dai=%d ack=%d\n", - m, - ack_info->cc[cc].m[m].resource.k1, - ack_info->cc[cc].m[m].resource.v_dai_dl, - ack_info->cc[cc].m[m].value[0]); - } - } - } - - return len; -} - int srsran_ue_dl_nr_csi_measure_trs(const srsran_ue_dl_nr_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_csi_rs_nzp_set_t* csi_rs_nzp_set, diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index 9f61052d7..8ce0ab5a1 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -150,7 +150,7 @@ static int ue_ul_nr_encode_pucch_format1(srsran_ue_ul_nr_t* q, uint8_t b[SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS] = {}; // Set ACK bits - uint32_t nof_bits = SRSRAN_MIN(SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS, uci_data->cfg.o_ack); + uint32_t nof_bits = SRSRAN_MIN(SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS, uci_data->cfg.ack.count); for (uint32_t i = 0; i < nof_bits; i++) { b[i] = uci_data->value.ack[i]; } diff --git a/lib/test/asn1/rrc_nr_utils_test.cc b/lib/test/asn1/rrc_nr_utils_test.cc index 82c1431ff..6dfc6b234 100644 --- a/lib/test/asn1/rrc_nr_utils_test.cc +++ b/lib/test/asn1/rrc_nr_utils_test.cc @@ -107,7 +107,7 @@ int make_phy_harq_ack_cfg_test() phys_cell_group_cfg_s phys_cell_group_cfg = {}; phys_cell_group_cfg.pdsch_harq_ack_codebook = phys_cell_group_cfg_s::pdsch_harq_ack_codebook_opts::dynamic_value; - srsran_ue_dl_nr_harq_ack_cfg_t srsran_ue_dl_nr_harq_ack_cfg; + srsran_harq_ack_cfg_hl_t srsran_ue_dl_nr_harq_ack_cfg; TESTASSERT(make_phy_harq_ack_cfg(phys_cell_group_cfg, &srsran_ue_dl_nr_harq_ack_cfg) == true); TESTASSERT(srsran_ue_dl_nr_harq_ack_cfg.harq_ack_codebook == srsran_pdsch_harq_ack_codebook_dynamic); diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index 356e13232..fef7d2986 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -37,10 +37,10 @@ private: mutable std::mutex pending_ul_grant_mutex; struct pending_dl_grant_t { - bool enable; - uint32_t pid; - srsran_sch_cfg_nr_t sch_cfg; - srsran_pdsch_ack_resource_nr_t ack_resource; + bool enable; + uint32_t pid; + srsran_sch_cfg_nr_t sch_cfg; + srsran_harq_ack_resource_t ack_resource; }; srsran::circular_array pending_dl_grant = {}; mutable std::mutex pending_dl_grant_mutex; @@ -171,7 +171,7 @@ public: } // Calculate DL DCI to PDSCH ACK resource - srsran_pdsch_ack_resource_nr_t ack_resource = {}; + srsran_harq_ack_resource_t ack_resource = {}; if (not cfg.get_pdsch_ack_resource(dci_dl, ack_resource)) { ERROR("Computing UL ACK resource"); return; @@ -199,10 +199,10 @@ public: * @param pid Provides the HARQ process identifier * @return true if there is a pending grant for the given TX tti, false otherwise */ - bool get_dl_pending_grant(uint32_t tti_rx, - srsran_sch_cfg_nr_t& pdsch_cfg, - srsran_pdsch_ack_resource_nr_t& ack_resource, - uint32_t& pid) + bool get_dl_pending_grant(uint32_t tti_rx, + srsran_sch_cfg_nr_t& pdsch_cfg, + srsran_harq_ack_resource_t& ack_resource, + uint32_t& pid) { // Scope mutex to protect read/write the list std::lock_guard lock(pending_dl_grant_mutex); @@ -231,16 +231,16 @@ public: * @param tti_rx The TTI in which the PDSCH transmission was received * @param dci_dl The DL DCI message to store */ - void set_pending_ack(const uint32_t& tti_rx, const srsran_pdsch_ack_resource_nr_t& ack_resource, const bool& crc_ok) + void set_pending_ack(const uint32_t& tti_rx, const srsran_harq_ack_resource_t& ack_resource, const bool& crc_ok) { // Calculate Receive TTI uint32_t tti_tx = TTI_ADD(tti_rx, ack_resource.k1); // Prepare ACK information - srsran_pdsch_ack_m_nr_t ack_m = {}; - ack_m.resource = ack_resource; - ack_m.value[0] = crc_ok ? 1 : 0; - ack_m.present = true; + srsran_harq_ack_m_t ack_m = {}; + ack_m.resource = ack_resource; + ack_m.value[0] = crc_ok ? 1 : 0; + ack_m.present = true; // Scope mutex to protect read/write the list std::lock_guard lock(pending_ack_mutex); @@ -250,7 +250,7 @@ public: ack.nof_cc = 1; // Insert PDSCH transmission information - if (srsran_ue_dl_nr_ack_insert_m(&ack, &ack_m) < SRSRAN_SUCCESS) { + if (srsran_harq_ack_insert_m(&ack, &ack_m) < SRSRAN_SUCCESS) { ERROR("Error inserting ACK m value"); } } diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 46c6cdead..e9c4cbde2 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -226,9 +226,9 @@ void cc_worker::decode_pdcch_ul() bool cc_worker::decode_pdsch_dl() { // Get DL grant for this TTI, if available - uint32_t pid = 0; - srsran_sch_cfg_nr_t pdsch_cfg = {}; - srsran_pdsch_ack_resource_nr_t ack_resource = {}; + uint32_t pid = 0; + srsran_sch_cfg_nr_t pdsch_cfg = {}; + srsran_harq_ack_resource_t ack_resource = {}; if (not phy.get_dl_pending_grant(dl_slot_cfg.idx, pdsch_cfg, ack_resource, pid)) { // Early return if no grant was available return true; @@ -526,12 +526,12 @@ bool cc_worker::work_ul() if (logger.debug.enabled()) { std::array str = {}; - if (srsran_ue_dl_nr_ack_info(&pdsch_ack, str.data(), (uint32_t)str.size()) > 0) { + if (srsran_harq_ack_info(&pdsch_ack, str.data(), (uint32_t)str.size()) > 0) { logger.debug("%s", str.data()); } } - if (srsran_ue_dl_nr_gen_ack(&phy.cfg.harq_ack, &pdsch_ack, &uci_data) < SRSRAN_SUCCESS) { + if (srsran_harq_ack_pack(&phy.cfg.harq_ack, &pdsch_ack, &uci_data) < SRSRAN_SUCCESS) { ERROR("Filling UCI ACK bits"); return false; } diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 079a97e39..27be3d7e6 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -1274,7 +1274,7 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) bool rrc_nr::apply_phy_cell_group_cfg(const phys_cell_group_cfg_s& phys_cell_group_cfg) { - srsran_ue_dl_nr_harq_ack_cfg_t harq_ack; + srsran_harq_ack_cfg_hl_t harq_ack; if (make_phy_harq_ack_cfg(phys_cell_group_cfg, &harq_ack) == true) { phy_cfg.harq_ack = harq_ack; } else { From 3fe91767500d06d166185e20b7978515cc6e05a1 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 29 Jun 2021 14:59:11 +0200 Subject: [PATCH 22/50] Added PUCCH dedocder to slot worker --- .../srsran/interfaces/gnb_interfaces.h | 5 +++-- lib/include/srsran/phy/gnb/gnb_ul.h | 6 ++++++ lib/include/srsran/phy/phch/pucch_nr.h | 8 ++++---- lib/src/phy/gnb/gnb_ul.c | 20 +++++++++++++++++++ lib/src/phy/phch/pucch_nr.c | 8 ++++---- lib/src/phy/ue/ue_ul_nr.c | 2 +- srsenb/src/phy/nr/slot_worker.cc | 19 +++++++++++++++++- 7 files changed, 56 insertions(+), 12 deletions(-) diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index d0c9fd902..f27b5d8f2 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -248,8 +248,9 @@ public: }; struct pucch_t { - srsran_uci_cfg_nr_t uci_cfg; - srsran_pucch_nr_resource_t resource; + srsran_uci_cfg_nr_t uci_cfg; ///< UCI configuration + srsran_pucch_nr_common_cfg_t pucch_cfg; ///< UE dedicated PUCCH configuration + srsran_pucch_nr_resource_t resource; ///< PUCCH resource }; struct ul_sched_t { diff --git a/lib/include/srsran/phy/gnb/gnb_ul.h b/lib/include/srsran/phy/gnb/gnb_ul.h index 6440a4512..856cd539f 100644 --- a/lib/include/srsran/phy/gnb/gnb_ul.h +++ b/lib/include/srsran/phy/gnb/gnb_ul.h @@ -59,4 +59,10 @@ SRSRAN_API int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q, const srsran_uci_cfg_nr_t* uci_cfg, srsran_uci_value_nr_t* uci_value); +SRSRAN_API uint32_t srsran_gnb_ul_pucch_info(srsran_gnb_ul_t* q, + const srsran_pucch_nr_resource_t* resource, + const srsran_uci_data_nr_t* uci_data, + char* str, + uint32_t str_len); + #endif // SRSRAN_GNB_UL_H diff --git a/lib/include/srsran/phy/phch/pucch_nr.h b/lib/include/srsran/phy/phch/pucch_nr.h index cb532fbe1..a562e7b03 100644 --- a/lib/include/srsran/phy/phch/pucch_nr.h +++ b/lib/include/srsran/phy/phch/pucch_nr.h @@ -239,9 +239,9 @@ SRSRAN_API int srsran_pucch_nr_format_2_3_4_decode(srsran_pucch_nr_t* cf_t* slot_symbols, srsran_uci_value_nr_t* uci_value); -SRSRAN_API uint32_t srsran_pucch_nr_tx_info(const srsran_pucch_nr_resource_t* resource, - const srsran_uci_data_nr_t* uci_data, - char* str, - uint32_t str_len); +SRSRAN_API uint32_t srsran_pucch_nr_info(const srsran_pucch_nr_resource_t* resource, + const srsran_uci_data_nr_t* uci_data, + char* str, + uint32_t str_len); #endif // SRSRAN_PUCCH_NR_H diff --git a/lib/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c index c76e7a1c8..0072adcbe 100644 --- a/lib/src/phy/gnb/gnb_ul.c +++ b/lib/src/phy/gnb/gnb_ul.c @@ -261,4 +261,24 @@ int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q, } return SRSRAN_ERROR; +} + +uint32_t srsran_gnb_ul_pucch_info(srsran_gnb_ul_t* q, + const srsran_pucch_nr_resource_t* resource, + const srsran_uci_data_nr_t* uci_data, + char* str, + uint32_t str_len) +{ + if (q == NULL || uci_data == NULL) { + return 0; + } + + uint32_t len = 0; + + len += srsran_pucch_nr_info(resource, uci_data, str, str_len - len); + + len = srsran_print_check( + str, str_len, len, "snr=%+.1f valid=%c", q->chest_pucch.snr_db, uci_data->value.valid ? 'y' : 'n'); + + return len; } \ No newline at end of file diff --git a/lib/src/phy/phch/pucch_nr.c b/lib/src/phy/phch/pucch_nr.c index 6dfb055eb..f7a7d1b80 100644 --- a/lib/src/phy/phch/pucch_nr.c +++ b/lib/src/phy/phch/pucch_nr.c @@ -762,10 +762,10 @@ static uint32_t pucch_nr_resource_info(const srsran_pucch_nr_resource_t* r, char return len; } -uint32_t srsran_pucch_nr_tx_info(const srsran_pucch_nr_resource_t* resource, - const srsran_uci_data_nr_t* uci_data, - char* str, - uint32_t str_len) +uint32_t srsran_pucch_nr_info(const srsran_pucch_nr_resource_t* resource, + const srsran_uci_data_nr_t* uci_data, + char* str, + uint32_t str_len) { uint32_t len = 0; diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index 8ce0ab5a1..3b0073985 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -260,7 +260,7 @@ int srsran_ue_ul_nr_pucch_info(const srsran_pucch_nr_resource_t* resource, int len = 0; // Append PDSCH info - len += srsran_pucch_nr_tx_info(resource, uci_data, &str[len], str_len - len); + len += srsran_pucch_nr_info(resource, uci_data, &str[len], str_len - len); return len; } diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 9b73a73ed..ee4ec1755 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -150,9 +150,26 @@ bool slot_worker::work_ul() return false; } + // Demodulate + if (srsran_gnb_ul_fft(&gnb_ul) < SRSRAN_SUCCESS) { + logger.error("Error in demodulation"); + return false; + } + // Decode PUCCH for (stack_interface_phy_nr::pucch_t& pucch : ul_sched.pucch) { - // ... + srsran_uci_value_nr_t uci_value; + if (srsran_gnb_ul_get_pucch(&gnb_ul, &ul_slot_cfg, &pucch.pucch_cfg, &pucch.resource, &pucch.uci_cfg, &uci_value) < + SRSRAN_SUCCESS) { + logger.error("Error getting PUCCH"); + return false; + } + + if (logger.info.enabled()) { + std::array str; + srsran_uci_data_nr_t uci_data = {.cfg = pucch.uci_cfg, .value = uci_value}; + srsran_gnb_ul_pucch_info(&gnb_ul, &pucch.resource, &uci_data, str.data(), (uint32_t)str.size()); + } } // Decode PUSCH From e764a26136caba84d982be7137ab0ad40b1dbb0b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 29 Jun 2021 18:41:37 +0200 Subject: [PATCH 23/50] Integrated PUCCH decoding in gNb --- lib/include/srsran/common/phy_cfg_nr.h | 8 ++- lib/include/srsran/phy/phch/harq_ack.h | 4 ++ lib/src/common/phy_cfg_nr.cc | 20 ++++-- srsenb/src/phy/nr/slot_worker.cc | 5 +- srsue/src/phy/nr/sf_worker.cc | 1 + test/phy/dummy_gnb_stack.h | 97 +++++++++++++++++++++++++- test/phy/nr_dl_flood.cc | 17 ++--- 7 files changed, 132 insertions(+), 20 deletions(-) diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index c29c90f11..c61dc245d 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -127,9 +127,11 @@ struct phy_cfg_nr_t { * @brief Compute UCI configuration for the given slot from the pending PDSCH ACK resources, periodic CSI, * periodic SR resources and so on. */ - bool get_uci_cfg(const srsran_slot_cfg_t& slot_cfg, - const srsran_pdsch_ack_nr_t& pdsch_ack, - srsran_uci_cfg_nr_t& uci_cfg) const; + bool get_pucch(const srsran_slot_cfg_t& slot_cfg, + const srsran_pdsch_ack_nr_t& pdsch_ack, + srsran_pucch_nr_common_cfg_t& cfg, + srsran_uci_cfg_nr_t& uci_cfg, + srsran_pucch_nr_resource_t& resource) const; }; } // namespace srsran diff --git a/lib/include/srsran/phy/phch/harq_ack.h b/lib/include/srsran/phy/phch/harq_ack.h index e926ae606..bba7719ac 100644 --- a/lib/include/srsran/phy/phch/harq_ack.h +++ b/lib/include/srsran/phy/phch/harq_ack.h @@ -21,6 +21,10 @@ SRSRAN_API int srsran_harq_ack_resource(const srsran_harq_ack_cfg_hl_t* cfg, const srsran_dci_dl_nr_t* dci_dl, srsran_harq_ack_resource_t* pdsch_ack_resource); +SRSRAN_API int srsran_harq_ack_gen_uci_cfg(const srsran_harq_ack_cfg_hl_t* cfg, + const srsran_pdsch_ack_nr_t* ack_info, + srsran_uci_cfg_nr_t* uci_cfg); + SRSRAN_API int srsran_harq_ack_pack(const srsran_harq_ack_cfg_hl_t* cfg, const srsran_pdsch_ack_nr_t* ack_info, srsran_uci_data_nr_t* uci_data); diff --git a/lib/src/common/phy_cfg_nr.cc b/lib/src/common/phy_cfg_nr.cc index 471a6ea62..729839084 100644 --- a/lib/src/common/phy_cfg_nr.cc +++ b/lib/src/common/phy_cfg_nr.cc @@ -280,12 +280,22 @@ bool phy_cfg_nr_t::get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, return srsran_harq_ack_resource(&harq_ack, &dci_dl, &ack_resource) == SRSRAN_SUCCESS; } -bool phy_cfg_nr_t::get_uci_cfg(const srsran_slot_cfg_t& slot_cfg, - const srsran_pdsch_ack_nr_t& pdsch_ack, - srsran_uci_cfg_nr_t& uci_cfg) const +bool phy_cfg_nr_t::get_pucch(const srsran_slot_cfg_t& slot_cfg, + const srsran_pdsch_ack_nr_t& ack_info, + srsran_pucch_nr_common_cfg_t& cfg, + srsran_uci_cfg_nr_t& uci_cfg, + srsran_pucch_nr_resource_t& resource) const { - // TBD - // ... + // Generate configuration for HARQ feedback + if (srsran_harq_ack_gen_uci_cfg(&harq_ack, &ack_info, &uci_cfg) < SRSRAN_SUCCESS) { + return false; + } + + // Select PUCCH resource + if (srsran_ra_ul_nr_pucch_resource(&pucch, &uci_cfg, &resource) < SRSRAN_SUCCESS) { + ERROR("Selecting PUCCH resource"); + return false; + } return true; } diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index ee4ec1755..bd89652ba 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -109,6 +109,7 @@ slot_worker::~slot_worker() } } srsran_gnb_dl_free(&gnb_dl); + srsran_gnb_ul_free(&gnb_ul); } cf_t* slot_worker::get_buffer_rx(uint32_t antenna_idx) @@ -169,6 +170,8 @@ bool slot_worker::work_ul() std::array str; srsran_uci_data_nr_t uci_data = {.cfg = pucch.uci_cfg, .value = uci_value}; srsran_gnb_ul_pucch_info(&gnb_ul, &pucch.resource, &uci_data, str.data(), (uint32_t)str.size()); + + logger.info("PUCCH: %s", str.data()); } } @@ -184,7 +187,7 @@ bool slot_worker::work_dl() { // Retrieve Scheduling for the current processing DL slot stack_interface_phy_nr::dl_sched_t dl_sched = {}; - if (stack.get_dl_sched(ul_slot_cfg, dl_sched) < SRSRAN_SUCCESS) { + if (stack.get_dl_sched(dl_slot_cfg, dl_sched) < SRSRAN_SUCCESS) { logger.error("Error retrieving DL scheduling"); return false; } diff --git a/srsue/src/phy/nr/sf_worker.cc b/srsue/src/phy/nr/sf_worker.cc index b761c0c8a..99436f87c 100644 --- a/srsue/src/phy/nr/sf_worker.cc +++ b/srsue/src/phy/nr/sf_worker.cc @@ -116,6 +116,7 @@ void sf_worker::work_imp() for (uint32_t i = 0; i < (uint32_t)cc_workers.size(); i++) { tx_buffer.set(i, cc_workers[i]->get_tx_buffer(0)); } + tx_buffer.set_nof_samples(SRSRAN_SF_LEN_PRB_NR(phy_state.cfg.carrier.nof_prb)); // Always call worker_end before returning common.worker_end(this, true, tx_buffer, tx_time, true); diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 155d1cb7c..5705d78ee 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_DUMMY_GNB_STACK_H #define SRSRAN_DUMMY_GNB_STACK_H +#include #include #include #include @@ -35,6 +36,49 @@ private: srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; + // HARQ feedback + class pending_ack_t + { + private: + std::mutex mutex; + srsran_pdsch_ack_nr_t ack = {}; + + public: + void push_ack(srsran_harq_ack_resource_t& ack_resource) + { + // Prepare ACK information + srsran_harq_ack_m_t ack_m = {}; + ack_m.resource = ack_resource; + ack_m.present = true; + + std::unique_lock lock(mutex); + + ack.nof_cc = 1; + + srsran_harq_ack_insert_m(&ack, &ack_m); + } + + srsran_pdsch_ack_nr_t get_ack() + { + std::unique_lock lock(mutex); + + return ack; + } + uint32_t get_dai() + { + std::unique_lock lock(mutex); + return ack.cc[0].M % 4; + } + + void reset() + { + std::unique_lock lock(mutex); + + ack = {}; + } + }; + srsran::circular_array pending_ack; + struct dummy_harq_proc { static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; std::vector data; @@ -68,12 +112,14 @@ public: uint32_t dl_start_rb = 0; ///< Start resource block uint32_t dl_length_rb = 0l; ///< Number of resource blocks uint32_t dl_time_res = 0; ///< PDSCH time resource + std::string log_level = "debug"; }; gnb_dummy_stack(args_t args) : mcs(args.mcs), rnti(args.rnti), dl_time_res(args.dl_time_res), phy_cfg(args.phy_cfg), ss_id(args.ss_id) { random_gen = srsran_random_init(0x1234); + logger.set_level(srslog::str_to_basic_level(args.log_level)); // Select DCI locations for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) { @@ -135,6 +181,8 @@ public: int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override { + logger.set_context(slot_cfg.idx); + // Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) { return SRSRAN_SUCCESS; @@ -159,6 +207,9 @@ public: return SRSRAN_ERROR; } + uint32_t harq_feedback = dl_data_to_ul_ack[slot_cfg.idx]; + uint32_t harq_ack_slot_idx = TTI_ADD(slot_cfg.idx, harq_feedback); + // Fill DCI fields srsran_dci_dl_nr_t& dci = pdcch.dci; dci.freq_domain_assigment = dl_freq_res; @@ -167,10 +218,14 @@ public: dci.rv = 0; dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; - dci.dai = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; + dci.dai = pending_ack[harq_ack_slot_idx].get_dai(); dci.tpc = 1; dci.pucch_resource = 0; - dci.harq_feedback = dl_data_to_ul_ack[TTI_TX(slot_cfg.idx)]; + if (dci.ctx.format == srsran_dci_format_nr_1_0) { + dci.harq_feedback = dl_data_to_ul_ack[slot_cfg.idx] - 1; + } else { + dci.harq_feedback = slot_cfg.idx; + } // Create PDSCH configuration if (not phy_cfg.get_pdsch_cfg(slot_cfg, dci, pdsch.sch)) { @@ -191,10 +246,46 @@ public: dl_sched.pdcch_dl.push_back(pdcch); dl_sched.pdsch.push_back(pdsch); + // Generate PDSCH HARQ Feedback + srsran_harq_ack_resource_t ack_resource = {}; + if (not phy_cfg.get_pdsch_ack_resource(dci, ack_resource)) { + logger.error("Error getting ack resource"); + return SRSRAN_ERROR; + } + + // Calculate PUCCH slot and push resource + pending_ack[harq_ack_slot_idx].push_ack(ack_resource); + return SRSRAN_SUCCESS; } - int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override { return 0; } + int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override + { + logger.set_context(slot_cfg.idx); + + srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx].get_ack(); + pending_ack[slot_cfg.idx].reset(); + + if (ack.nof_cc > 0) { + mac_interface_phy_nr::pucch_t pucch = {}; + + if (logger.debug.enabled()) { + std::array str = {}; + if (srsran_harq_ack_info(&ack, str.data(), (uint32_t)str.size()) > 0) { + logger.debug("HARQ feedback:\n%s", str.data()); + } + } + + if (not phy_cfg.get_pucch(slot_cfg, ack, pucch.pucch_cfg, pucch.uci_cfg, pucch.resource)) { + logger.error("Error getting UCI CFG"); + return SRSRAN_ERROR; + } + + ul_sched.pucch.push_back(pucch); + } + + return 0; + } }; #endif // SRSRAN_DUMMY_GNB_STACK_H diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_dl_flood.cc index a6428b553..56bb8e87f 100644 --- a/test/phy/nr_dl_flood.cc +++ b/test/phy/nr_dl_flood.cc @@ -108,10 +108,10 @@ test_bench::args_t::args_t(int argc, char** argv) phy_cfg.pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; phy_cfg.tdd.pattern1.period_ms = 10; - phy_cfg.tdd.pattern1.nof_dl_slots = 7; - phy_cfg.tdd.pattern1.nof_dl_symbols = 6; - phy_cfg.tdd.pattern1.nof_ul_slots = 4; - phy_cfg.tdd.pattern1.nof_ul_symbols = 4; + phy_cfg.tdd.pattern1.nof_dl_slots = 5; + phy_cfg.tdd.pattern1.nof_dl_symbols = 0; + phy_cfg.tdd.pattern1.nof_ul_slots = 5; + phy_cfg.tdd.pattern1.nof_ul_symbols = 0; phy_cfg.pdsch.dmrs_typeA.additional_pos = srsran_dmrs_sch_add_pos_1; phy_cfg.pdsch.dmrs_typeA.present = true; @@ -206,8 +206,9 @@ test_bench::args_t::args_t(int argc, char** argv) phy_cfg.harq_ack.dl_data_to_ul_ack[2] = 6; phy_cfg.harq_ack.dl_data_to_ul_ack[3] = 5; phy_cfg.harq_ack.dl_data_to_ul_ack[4] = 4; - phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 12; - phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 11; + phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 4; + phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 4; + phy_cfg.harq_ack.dl_data_to_ul_ack[7] = 4; phy_cfg.harq_ack.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; phy_cfg.prach.freq_offset = 2; @@ -272,10 +273,10 @@ int main(int argc, char** argv) // Parse test bench arguments test_bench::args_t args(argc, argv); args.gnb_args.log_id_preamble = "GNB/"; - args.gnb_args.log_level = "warning"; + args.gnb_args.log_level = "info"; args.gnb_args.nof_phy_threads = 1; args.ue_args.log.id_preamble = " UE/"; - args.ue_args.log.phy_level = "warning"; + args.ue_args.log.phy_level = "info"; args.ue_args.log.phy_hex_limit = 0; args.ue_args.nof_phy_threads = 1; From 320aabec1362d77afd5f5752bab622f65cdfee7c Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 30 Jun 2021 09:23:22 +0200 Subject: [PATCH 24/50] Initial PHY NR configuration --- lib/include/srsran/common/phy_cfg_nr.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index c61dc245d..644614ed5 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -133,6 +133,26 @@ struct phy_cfg_nr_t { srsran_uci_cfg_nr_t& uci_cfg, srsran_pucch_nr_resource_t& resource) const; }; + +struct phy_cfg_nr_default_t : public phy_cfg_nr_t { + /** + * @brief DL reference configurations defined in TS 38.101-4 User Equipment (UE) radio transmission and reception; + * Part 4: Performance requirements + */ + typedef enum { + R_PDSCH_2_1_1 = 0, // R.PDSCH.2-1.1 TDD + } dl_reference_t; + + /** + * @brief UL reference configurations defined in TS 38.104 Base Station (BS) radio transmission and reception + */ + typedef enum { + G_FR1_A3_8 = 0, // G-FR1-A3-8 + } ul_reference_t; + + phy_cfg_nr_default_t(const dl_reference_t& dl_reference, const ul_reference_t& ul_reference); +}; + } // namespace srsran #endif // SRSRAN_PHY_CFG_NR_H From 2fbd172888c0e46c7ef2ba13db639f22d3a6618b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 30 Jun 2021 17:12:17 +0200 Subject: [PATCH 25/50] Initial PHY NR configuration generator --- lib/include/srsran/common/phy_cfg_nr.h | 19 -- .../srsran/common/phy_cfg_nr_default.h | 146 ++++++++++++ lib/src/common/CMakeLists.txt | 1 + lib/src/common/phy_cfg_nr_default.cc | 221 ++++++++++++++++++ test/phy/nr_dl_flood.cc | 197 +--------------- 5 files changed, 372 insertions(+), 212 deletions(-) create mode 100644 lib/include/srsran/common/phy_cfg_nr_default.h create mode 100644 lib/src/common/phy_cfg_nr_default.cc diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index 644614ed5..b37e6291d 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -134,25 +134,6 @@ struct phy_cfg_nr_t { srsran_pucch_nr_resource_t& resource) const; }; -struct phy_cfg_nr_default_t : public phy_cfg_nr_t { - /** - * @brief DL reference configurations defined in TS 38.101-4 User Equipment (UE) radio transmission and reception; - * Part 4: Performance requirements - */ - typedef enum { - R_PDSCH_2_1_1 = 0, // R.PDSCH.2-1.1 TDD - } dl_reference_t; - - /** - * @brief UL reference configurations defined in TS 38.104 Base Station (BS) radio transmission and reception - */ - typedef enum { - G_FR1_A3_8 = 0, // G-FR1-A3-8 - } ul_reference_t; - - phy_cfg_nr_default_t(const dl_reference_t& dl_reference, const ul_reference_t& ul_reference); -}; - } // namespace srsran #endif // SRSRAN_PHY_CFG_NR_H diff --git a/lib/include/srsran/common/phy_cfg_nr_default.h b/lib/include/srsran/common/phy_cfg_nr_default.h new file mode 100644 index 000000000..ee781f79a --- /dev/null +++ b/lib/include/srsran/common/phy_cfg_nr_default.h @@ -0,0 +1,146 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_PHY_CFG_NR_DEFAULT_H +#define SRSRAN_PHY_CFG_NR_DEFAULT_H + +#include "phy_cfg_nr.h" + +namespace srsran { + +class phy_cfg_nr_default_t : public phy_cfg_nr_t +{ +public: + struct reference_cfg_t { + enum { + /** + * @brief Carrier reference configuration for 10MHz serving cell bandwidth + * - BW: 10 MHZ (52 PRB) + * - PCI: 500 + * - SCS: 15 kHz + * - SSB: 5ms + */ + R_CARRIER_CUSTOM_10MHZ = 0, + } carrier = R_CARRIER_CUSTOM_10MHZ; + + enum { + /** + * @brief TDD custom reference 5 slot DL and 5 slot UL + */ + R_TDD_CUSTOM_6_4 = 0, + } tdd = R_TDD_CUSTOM_6_4; + + enum { + /** + * @brief Carrier reference configuration for 10MHz serving cell bandwidth + * - CORESET: all channel, 1 symbol + * - Single common Search Space + */ + R_PDCCH_CUSTOM_COMMON_SS = 0, + } pdcch = R_PDCCH_CUSTOM_COMMON_SS; + + enum { + /** + * @brief Custom fallback baseline configuration, designed for component testing + * - Defined single common PDSCH time allocation starting at symbol index 1 and length 13 + * - No DMRS dedicated configuration + */ + R_PDSCH_DEFAULT = 0, + } pdsch = R_PDSCH_DEFAULT; + + enum { + /** + * @brief Custom fallback baseline configuration, designed for component testing + * - Single Time resource allocation + * - transmission starts at symbol index 0 for 14 symbols + * - k is 4 slots + * - No DMRS dedicated configuration + */ + R_PUSCH_DEFAULT = 0, + } pusch = R_PUSCH_DEFAULT; + + enum { + /** + * @brief Custom single PUCCH resource per set + * - Format 1 for 1 or 2 bits + * - Format 2 for more than 2 bits + */ + R_PUCCH_CUSTOM_ONE = 0, + } pucch = R_PUCCH_CUSTOM_ONE; + + enum { + /** + * @brief Sets the delay between PDSCH and HARQ feedback timing automatically + * - Dynamic HARQ ACK codebook + * - Guarantees a minimum delay of 4ms + */ + R_HARQ_AUTO = 0, + } harq = R_HARQ_AUTO; + + enum { + /** + * @brief Sets the PRACH configuration to an LTE compatible configuration + * - Configuration index 0 + * - Frequency offset 2 PRB + * - Root sequence 2 + */ + R_PRACH_DEFAULT_LTE, + } prach = R_PRACH_DEFAULT_LTE; + }; + + phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg); + +private: + /** + * Carrier make helper methods + */ + static void make_carrier_custom_10MHz(srsran_carrier_nr_t& carrier); + + /** + * TDD make helper methods + */ + static void make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd); + + /** + * PDCCH make helper methods + */ + static void make_pdcch_custom_common_ss(srsran_pdcch_cfg_nr_t& pdcch, const srsran_carrier_nr_t& carrier); + + /** + * PDSCH make helper methods + */ + static void make_pdsch_default(srsran_sch_hl_cfg_nr_t& pdsch); + + /** + * PUSCH make helper methods + */ + static void make_pusch_default(srsran_sch_hl_cfg_nr_t& pusch); + + /** + * PUCCH make helper methods + */ + static void make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch); + + /** + * HARQ make helper methods + */ + static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, const srsran_tdd_config_nr_t& tdd_cfg); + + /** + * PRACH make helper methods + */ + static void make_prach_default_lte(srsran_prach_cfg_t& prach); +}; + +} // namespace srsran + +#endif // SRSRAN_PHY_CFG_NR_DEFAULT_H diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 498d7d504..8c0f15aa0 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -23,6 +23,7 @@ set(SOURCES arch_select.cc mac_pcap_net.cc pcap.c phy_cfg_nr.cc + phy_cfg_nr_default.cc rlc_pcap.cc s1ap_pcap.cc security.cc diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc new file mode 100644 index 000000000..4acf90b9c --- /dev/null +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -0,0 +1,221 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/common/phy_cfg_nr_default.h" +#include "srsran/srsran.h" + +namespace srsran { + +void phy_cfg_nr_default_t::make_carrier_custom_10MHz(srsran_carrier_nr_t& carrier) +{ + carrier.nof_prb = 52; + carrier.max_mimo_layers = 1; + carrier.pci = 500; + carrier.absolute_frequency_point_a = 633928; + carrier.absolute_frequency_ssb = 634176; + carrier.offset_to_carrier = 0; + carrier.scs = srsran_subcarrier_spacing_15kHz; +} + +void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd) +{ + tdd.pattern1.period_ms = 10; + tdd.pattern1.nof_dl_slots = 6; + tdd.pattern1.nof_dl_symbols = 0; + tdd.pattern1.nof_ul_slots = 4; + tdd.pattern1.nof_ul_symbols = 0; + + // Disable pattern 2 + tdd.pattern2.period_ms = 0; +} + +void phy_cfg_nr_default_t::make_pdcch_custom_common_ss(srsran_pdcch_cfg_nr_t& pdcch, const srsran_carrier_nr_t& carrier) +{ + pdcch.coreset_present[1] = true; + pdcch.coreset[1].id = 1; + for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { + pdcch.coreset[1].freq_resources[0] = i < SRSRAN_FLOOR(carrier.nof_prb, 6); + } + pdcch.coreset[1].duration = 1; + pdcch.coreset[1].mapping_type = srsran_coreset_mapping_type_non_interleaved; + pdcch.coreset[1].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + + pdcch.search_space_present[1] = true; + pdcch.search_space[1].id = 1; + pdcch.search_space[1].coreset_id = 1; + pdcch.search_space[1].duration = 1; + pdcch.search_space[1].nof_candidates[0] = 0; + pdcch.search_space[1].nof_candidates[1] = 0; + pdcch.search_space[1].nof_candidates[2] = 0; + pdcch.search_space[1].nof_candidates[3] = 1; + pdcch.search_space[1].nof_candidates[4] = 0; + pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; // DCI format for PUSCH + pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; // DCI format for PDSCH + pdcch.search_space[1].nof_formats = 2; + pdcch.search_space[1].type = srsran_search_space_type_common_3; +} + +void phy_cfg_nr_default_t::make_pdsch_default(srsran_sch_hl_cfg_nr_t& pdsch) +{ + // Select PDSCH time resource allocation + pdsch.common_time_ra[0].k = 0; + pdsch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A; + pdsch.common_time_ra[0].sliv = srsran_ra_type2_to_riv(SRSRAN_NSYMB_PER_SLOT_NR - 1, 1, SRSRAN_NSYMB_PER_SLOT_NR); + pdsch.nof_common_time_ra = 1; + + // Setup PDSCH DMRS type A position + pdsch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; +} + +void phy_cfg_nr_default_t::make_pusch_default(srsran_sch_hl_cfg_nr_t& pusch) +{ + // Select PUSCH time resource allocation + pusch.common_time_ra[0].k = 4; + pusch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A; + pusch.common_time_ra[0].sliv = srsran_ra_type2_to_riv(SRSRAN_NSYMB_PER_SLOT_NR, 0, SRSRAN_NSYMB_PER_SLOT_NR); + pusch.nof_common_time_ra = 1; + + // Setup PUSCH DMRS type A position + pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; +} + +void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch) +{ + // PUCCH Resource for format 1 + srsran_pucch_nr_resource_t resource_small = {}; + resource_small.starting_prb = 0; + resource_small.format = SRSRAN_PUCCH_NR_FORMAT_1; + resource_small.initial_cyclic_shift = 0; + resource_small.nof_symbols = 14; + resource_small.start_symbol_idx = 0; + resource_small.time_domain_occ = 0; + + // PUCCH Resource for format 2 + srsran_pucch_nr_resource_t resource_big = {}; + resource_big.starting_prb = 51; + resource_big.format = SRSRAN_PUCCH_NR_FORMAT_2; + resource_big.nof_prb = 1; + resource_big.nof_symbols = 2; + resource_big.start_symbol_idx = 0; + + // Resource for SR + srsran_pucch_nr_resource_t resource_sr = {}; + resource_sr.starting_prb = 51; + resource_sr.format = SRSRAN_PUCCH_NR_FORMAT_1; + resource_sr.initial_cyclic_shift = 0; + resource_sr.nof_symbols = 14; + resource_sr.start_symbol_idx = 0; + resource_sr.time_domain_occ = 0; + + pucch.enabled = true; + + // Set format 1 for 1-2 bits + pucch.sets[0].resources[0] = resource_small; + pucch.sets[0].resources[1] = resource_small; + pucch.sets[0].resources[2] = resource_small; + pucch.sets[0].resources[3] = resource_small; + pucch.sets[0].resources[4] = resource_small; + pucch.sets[0].resources[5] = resource_small; + pucch.sets[0].resources[6] = resource_small; + pucch.sets[0].resources[7] = resource_small; + pucch.sets[0].nof_resources = 8; + + // Set format 2 for more bits + pucch.sets[1].resources[0] = resource_big; + pucch.sets[1].resources[1] = resource_big; + pucch.sets[1].resources[2] = resource_big; + pucch.sets[1].resources[3] = resource_big; + pucch.sets[1].resources[4] = resource_big; + pucch.sets[1].resources[5] = resource_big; + pucch.sets[1].resources[6] = resource_big; + pucch.sets[1].resources[7] = resource_big; + pucch.sets[1].nof_resources = 8; + + // Configure scheduling request + pucch.sr_resources[1].configured = true; + pucch.sr_resources[1].sr_id = 0; + pucch.sr_resources[1].period = 40; + pucch.sr_resources[1].offset = 8; + pucch.sr_resources[1].resource = resource_sr; +} + +void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, const srsran_tdd_config_nr_t& tdd_cfg) +{ + harq.nof_dl_data_to_ul_ack = SRSRAN_MAX(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); + for (uint32_t i = 0; i < harq.nof_dl_data_to_ul_ack; i++) { + harq.dl_data_to_ul_ack[i] = ((harq.nof_dl_data_to_ul_ack - 4) > i) ? (harq.nof_dl_data_to_ul_ack - i) : 4; + } + + for (uint32_t i = harq.nof_dl_data_to_ul_ack; i < SRSRAN_MAX_NOF_DL_DATA_TO_UL; i++) { + harq.dl_data_to_ul_ack[i] = 0; + } +} + +void phy_cfg_nr_default_t::make_prach_default_lte(srsran_prach_cfg_t& prach) +{ + prach.config_idx = 0; + prach.freq_offset = 2; + prach.root_seq_idx = 0; +} + +phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) +{ + switch (reference_cfg.carrier) { + case reference_cfg_t::R_CARRIER_CUSTOM_10MHZ: + make_carrier_custom_10MHz(carrier); + break; + } + + switch (reference_cfg.tdd) { + case reference_cfg_t::R_TDD_CUSTOM_6_4: + make_tdd_custom_6_4(tdd); + break; + } + + switch (reference_cfg.pdcch) { + case reference_cfg_t::R_PDCCH_CUSTOM_COMMON_SS: + make_pdcch_custom_common_ss(pdcch, carrier); + break; + } + + switch (reference_cfg.pdsch) { + case reference_cfg_t::R_PDSCH_DEFAULT: + make_pdsch_default(pdsch); + break; + } + + switch (reference_cfg.pusch) { + case reference_cfg_t::R_PUSCH_DEFAULT: + make_pusch_default(pusch); + break; + } + + switch (reference_cfg.pucch) { + case reference_cfg_t::R_PUCCH_CUSTOM_ONE: + make_pusch_default(pusch); + break; + } + + switch (reference_cfg.harq) { + case reference_cfg_t::R_HARQ_AUTO: + make_harq_auto(harq_ack, tdd); + break; + } + + switch (reference_cfg.prach) { + case reference_cfg_t::R_PRACH_DEFAULT_LTE: + make_prach_default_lte(prach); + break; + } +} + +} // namespace srsran \ No newline at end of file diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_dl_flood.cc index 56bb8e87f..5476c93d0 100644 --- a/test/phy/nr_dl_flood.cc +++ b/test/phy/nr_dl_flood.cc @@ -11,6 +11,7 @@ */ #include "dummy_gnb_stack.h" +#include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/test_common.h" #include "test_bench.h" @@ -19,199 +20,9 @@ test_bench::args_t::args_t(int argc, char** argv) // Flag configuration as valid valid = true; - phy_cfg.carrier.nof_prb = 52; - phy_cfg.carrier.max_mimo_layers = 1; - phy_cfg.carrier.pci = 500; - phy_cfg.carrier.absolute_frequency_point_a = 633928; - phy_cfg.carrier.absolute_frequency_ssb = 634176; - phy_cfg.carrier.offset_to_carrier = 0; - phy_cfg.carrier.scs = srsran_subcarrier_spacing_15kHz; - - phy_cfg.ssb.periodicity_ms = 5; - phy_cfg.ssb.position_in_burst[0] = true; - phy_cfg.ssb.scs = srsran_subcarrier_spacing_30kHz; - - phy_cfg.pdcch.coreset_present[1] = true; - phy_cfg.pdcch.coreset[1].id = 1; - phy_cfg.pdcch.coreset[1].freq_resources[0] = true; - phy_cfg.pdcch.coreset[1].freq_resources[1] = true; - phy_cfg.pdcch.coreset[1].freq_resources[2] = true; - phy_cfg.pdcch.coreset[1].freq_resources[3] = true; - phy_cfg.pdcch.coreset[1].freq_resources[4] = true; - phy_cfg.pdcch.coreset[1].freq_resources[5] = true; - phy_cfg.pdcch.coreset[1].freq_resources[6] = true; - phy_cfg.pdcch.coreset[1].freq_resources[7] = true; - phy_cfg.pdcch.coreset[1].duration = 1; - phy_cfg.pdcch.coreset[1].mapping_type = srsran_coreset_mapping_type_non_interleaved; - phy_cfg.pdcch.coreset[1].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; - phy_cfg.pdcch.coreset_present[2] = true; - phy_cfg.pdcch.coreset[2].id = 2; - phy_cfg.pdcch.coreset[2].freq_resources[0] = true; - phy_cfg.pdcch.coreset[2].freq_resources[1] = true; - phy_cfg.pdcch.coreset[2].freq_resources[2] = true; - phy_cfg.pdcch.coreset[2].freq_resources[3] = true; - phy_cfg.pdcch.coreset[2].freq_resources[4] = true; - phy_cfg.pdcch.coreset[2].freq_resources[5] = true; - phy_cfg.pdcch.coreset[2].freq_resources[6] = true; - phy_cfg.pdcch.coreset[2].freq_resources[7] = true; - phy_cfg.pdcch.coreset[2].duration = 1; - phy_cfg.pdcch.coreset[2].mapping_type = srsran_coreset_mapping_type_non_interleaved; - phy_cfg.pdcch.coreset[2].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; - - phy_cfg.pdcch.search_space_present[1] = true; - phy_cfg.pdcch.search_space[1].id = 1; - phy_cfg.pdcch.search_space[1].coreset_id = 1; - phy_cfg.pdcch.search_space[1].duration = 1; - phy_cfg.pdcch.search_space[1].nof_candidates[0] = 1; - phy_cfg.pdcch.search_space[1].nof_candidates[1] = 1; - phy_cfg.pdcch.search_space[1].nof_candidates[2] = 1; - phy_cfg.pdcch.search_space[1].nof_candidates[3] = 0; - phy_cfg.pdcch.search_space[1].nof_candidates[4] = 0; - phy_cfg.pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; // DCI format for PUSCH - phy_cfg.pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; // DCI format for PDSCH - phy_cfg.pdcch.search_space[1].nof_formats = 2; - phy_cfg.pdcch.search_space[1].type = srsran_search_space_type_common_3; - - phy_cfg.pdcch.search_space_present[2] = true; - phy_cfg.pdcch.search_space[2].id = 2; - phy_cfg.pdcch.search_space[2].coreset_id = 2; - phy_cfg.pdcch.search_space[2].duration = 1; - phy_cfg.pdcch.search_space[2].nof_candidates[0] = 0; - phy_cfg.pdcch.search_space[2].nof_candidates[1] = 2; - phy_cfg.pdcch.search_space[2].nof_candidates[2] = 1; - phy_cfg.pdcch.search_space[2].nof_candidates[3] = 0; - phy_cfg.pdcch.search_space[2].nof_candidates[4] = 0; - phy_cfg.pdcch.search_space[2].formats[0] = srsran_dci_format_nr_0_1; - phy_cfg.pdcch.search_space[2].formats[1] = srsran_dci_format_nr_1_1; - phy_cfg.pdcch.search_space[2].nof_formats = 2; - phy_cfg.pdcch.search_space[2].type = srsran_search_space_type_ue; - - phy_cfg.pdcch.ra_search_space_present = true; - phy_cfg.pdcch.ra_search_space = phy_cfg.pdcch.search_space[1]; - phy_cfg.pdcch.ra_search_space.type = srsran_search_space_type_common_1; - - phy_cfg.pdsch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A; - phy_cfg.pdsch.common_time_ra[0].sliv = 40; - phy_cfg.pdsch.common_time_ra[1].mapping_type = srsran_sch_mapping_type_A; - phy_cfg.pdsch.common_time_ra[1].sliv = 57; - phy_cfg.pdsch.nof_common_time_ra = 2; - - phy_cfg.pusch.common_time_ra[0].k = 4; - phy_cfg.pusch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A; - phy_cfg.pusch.common_time_ra[0].sliv = 27; - phy_cfg.pusch.common_time_ra[1].k = 5; - phy_cfg.pusch.common_time_ra[1].mapping_type = srsran_sch_mapping_type_A; - phy_cfg.pusch.common_time_ra[1].sliv = 27; - phy_cfg.pusch.nof_common_time_ra = 2; - - phy_cfg.pdsch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; - phy_cfg.pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; - - phy_cfg.tdd.pattern1.period_ms = 10; - phy_cfg.tdd.pattern1.nof_dl_slots = 5; - phy_cfg.tdd.pattern1.nof_dl_symbols = 0; - phy_cfg.tdd.pattern1.nof_ul_slots = 5; - phy_cfg.tdd.pattern1.nof_ul_symbols = 0; - - phy_cfg.pdsch.dmrs_typeA.additional_pos = srsran_dmrs_sch_add_pos_1; - phy_cfg.pdsch.dmrs_typeA.present = true; - phy_cfg.pdsch.alloc = srsran_resource_alloc_type1; - - phy_cfg.pucch.enabled = true; - srsran_pucch_nr_resource_t& pucch0 = phy_cfg.pucch.sets[0].resources[0]; - srsran_pucch_nr_resource_t& pucch1 = phy_cfg.pucch.sets[0].resources[1]; - srsran_pucch_nr_resource_t& pucch2 = phy_cfg.pucch.sets[0].resources[2]; - srsran_pucch_nr_resource_t& pucch3 = phy_cfg.pucch.sets[0].resources[3]; - srsran_pucch_nr_resource_t& pucch4 = phy_cfg.pucch.sets[0].resources[4]; - srsran_pucch_nr_resource_t& pucch5 = phy_cfg.pucch.sets[0].resources[5]; - srsran_pucch_nr_resource_t& pucch6 = phy_cfg.pucch.sets[0].resources[6]; - srsran_pucch_nr_resource_t& pucch7 = phy_cfg.pucch.sets[0].resources[7]; - phy_cfg.pucch.sets[0].nof_resources = 8; - srsran_pucch_nr_resource_t& pucch8 = phy_cfg.pucch.sets[1].resources[0]; - srsran_pucch_nr_resource_t& pucch9 = phy_cfg.pucch.sets[1].resources[1]; - srsran_pucch_nr_resource_t& pucch10 = phy_cfg.pucch.sets[1].resources[2]; - srsran_pucch_nr_resource_t& pucch11 = phy_cfg.pucch.sets[1].resources[3]; - srsran_pucch_nr_resource_t& pucch12 = phy_cfg.pucch.sets[1].resources[4]; - srsran_pucch_nr_resource_t& pucch13 = phy_cfg.pucch.sets[1].resources[5]; - srsran_pucch_nr_resource_t& pucch14 = phy_cfg.pucch.sets[1].resources[6]; - srsran_pucch_nr_resource_t& pucch15 = phy_cfg.pucch.sets[1].resources[7]; - phy_cfg.pucch.sets[1].nof_resources = 8; - - pucch0.starting_prb = 0; - pucch0.format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch0.initial_cyclic_shift = 0; - pucch0.nof_symbols = 14; - pucch0.start_symbol_idx = 0; - pucch0.time_domain_occ = 0; - pucch1 = pucch0; - pucch1.initial_cyclic_shift = 4; - pucch1.time_domain_occ = 0; - pucch2 = pucch0; - pucch2.initial_cyclic_shift = 8; - pucch2.time_domain_occ = 0; - pucch3 = pucch0; - pucch3.initial_cyclic_shift = 0; - pucch3.time_domain_occ = 1; - pucch4 = pucch0; - pucch4.initial_cyclic_shift = 0; - pucch4.time_domain_occ = 1; - pucch5 = pucch0; - pucch5.initial_cyclic_shift = 4; - pucch5.time_domain_occ = 1; - pucch6 = pucch0; - pucch6.initial_cyclic_shift = 0; - pucch6.time_domain_occ = 2; - pucch7 = pucch0; - pucch7.initial_cyclic_shift = 4; - pucch7.time_domain_occ = 2; - - pucch8.starting_prb = 51; - pucch8.format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch8.nof_prb = 1; - pucch8.nof_symbols = 2; - pucch8.start_symbol_idx = 0; - - pucch9 = pucch8; - pucch9.start_symbol_idx = 2; - pucch10 = pucch8; - pucch10.start_symbol_idx = 4; - pucch11 = pucch8; - pucch11.start_symbol_idx = 6; - pucch12 = pucch8; - pucch12.start_symbol_idx = 8; - pucch13 = pucch8; - pucch13.start_symbol_idx = 10; - pucch14 = pucch8; - pucch14.start_symbol_idx = 12; - pucch15 = pucch8; - pucch15.starting_prb = 1; - pucch15.start_symbol_idx = 0; - - srsran_pucch_nr_resource_t& pucch16 = phy_cfg.pucch.sr_resources[1].resource; - pucch16.starting_prb = 0; - pucch16.format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch16.initial_cyclic_shift = 8; - pucch16.nof_symbols = 14; - pucch16.start_symbol_idx = 0; - pucch16.time_domain_occ = 2; - - phy_cfg.pucch.sr_resources[1].configured = true; - phy_cfg.pucch.sr_resources[1].sr_id = 0; - phy_cfg.pucch.sr_resources[1].period = 40; - phy_cfg.pucch.sr_resources[1].offset = 8; - phy_cfg.pucch.sr_resources[1].resource = pucch16; - - phy_cfg.harq_ack.dl_data_to_ul_ack[0] = 8; - phy_cfg.harq_ack.dl_data_to_ul_ack[1] = 7; - phy_cfg.harq_ack.dl_data_to_ul_ack[2] = 6; - phy_cfg.harq_ack.dl_data_to_ul_ack[3] = 5; - phy_cfg.harq_ack.dl_data_to_ul_ack[4] = 4; - phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 4; - phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 4; - phy_cfg.harq_ack.dl_data_to_ul_ack[7] = 4; - phy_cfg.harq_ack.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; - - phy_cfg.prach.freq_offset = 2; + // Load default reference configuration + srsran::phy_cfg_nr_default_t::reference_cfg_t reference_cfg; + phy_cfg = srsran::phy_cfg_nr_default_t(reference_cfg); cell_list.resize(1); cell_list[0].carrier = phy_cfg.carrier; From cf496e75eb8f9f252bb94ede78d9675e49e70468 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 30 Jun 2021 18:33:23 +0200 Subject: [PATCH 26/50] Fix default PHY NR configuration --- .../srsran/common/phy_cfg_nr_default.h | 7 +- lib/src/common/phy_cfg_nr_default.cc | 71 +++++++++++++------ 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/lib/include/srsran/common/phy_cfg_nr_default.h b/lib/include/srsran/common/phy_cfg_nr_default.h index ee781f79a..56854f821 100644 --- a/lib/include/srsran/common/phy_cfg_nr_default.h +++ b/lib/include/srsran/common/phy_cfg_nr_default.h @@ -44,6 +44,7 @@ public: * @brief Carrier reference configuration for 10MHz serving cell bandwidth * - CORESET: all channel, 1 symbol * - Single common Search Space + * - 1 possible candidate per aggregation level */ R_PDCCH_CUSTOM_COMMON_SS = 0, } pdcch = R_PDCCH_CUSTOM_COMMON_SS; @@ -82,6 +83,8 @@ public: * @brief Sets the delay between PDSCH and HARQ feedback timing automatically * - Dynamic HARQ ACK codebook * - Guarantees a minimum delay of 4ms + * - Assume 15kHz SCS + * - Assume TDD pattern2 is not enabled */ R_HARQ_AUTO = 0, } harq = R_HARQ_AUTO; @@ -133,7 +136,9 @@ private: /** * HARQ make helper methods */ - static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, const srsran_tdd_config_nr_t& tdd_cfg); + static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, + const srsran_carrier_nr_t& carrier, + const srsran_tdd_config_nr_t& tdd_cfg); /** * PRACH make helper methods diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index 4acf90b9c..becebda6a 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -40,28 +40,33 @@ void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd) void phy_cfg_nr_default_t::make_pdcch_custom_common_ss(srsran_pdcch_cfg_nr_t& pdcch, const srsran_carrier_nr_t& carrier) { - pdcch.coreset_present[1] = true; - pdcch.coreset[1].id = 1; - for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { - pdcch.coreset[1].freq_resources[0] = i < SRSRAN_FLOOR(carrier.nof_prb, 6); - } + // Configure CORESET ID 1 + pdcch.coreset_present[1] = true; + pdcch.coreset[1].id = 1; pdcch.coreset[1].duration = 1; pdcch.coreset[1].mapping_type = srsran_coreset_mapping_type_non_interleaved; pdcch.coreset[1].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; - pdcch.search_space_present[1] = true; - pdcch.search_space[1].id = 1; - pdcch.search_space[1].coreset_id = 1; - pdcch.search_space[1].duration = 1; - pdcch.search_space[1].nof_candidates[0] = 0; - pdcch.search_space[1].nof_candidates[1] = 0; - pdcch.search_space[1].nof_candidates[2] = 0; - pdcch.search_space[1].nof_candidates[3] = 1; - pdcch.search_space[1].nof_candidates[4] = 0; - pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; // DCI format for PUSCH - pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; // DCI format for PDSCH - pdcch.search_space[1].nof_formats = 2; - pdcch.search_space[1].type = srsran_search_space_type_common_3; + // Generate frequency resources for the full BW + for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { + pdcch.coreset[1].freq_resources[i] = i < SRSRAN_FLOOR(carrier.nof_prb, 6); + } + + // Configure Search Space 1 as common + pdcch.search_space_present[1] = true; + pdcch.search_space[1].id = 1; + pdcch.search_space[1].coreset_id = 1; + pdcch.search_space[1].duration = 1; + pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; // DCI format for PUSCH + pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; // DCI format for PDSCH + pdcch.search_space[1].nof_formats = 2; + pdcch.search_space[1].type = srsran_search_space_type_common_3; + + // Generate 1 candidate for each aggregation level if possible + for (uint32_t L = 0; L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) { + pdcch.search_space[1].nof_candidates[L] = + SRSRAN_MIN(1, srsran_pdcch_nr_max_candidates_coreset(&pdcch.coreset[1], L)); + } } void phy_cfg_nr_default_t::make_pdsch_default(srsran_sch_hl_cfg_nr_t& pdsch) @@ -148,16 +153,38 @@ void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch pucch.sr_resources[1].resource = resource_sr; } -void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, const srsran_tdd_config_nr_t& tdd_cfg) +void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, + const srsran_carrier_nr_t& carrier, + const srsran_tdd_config_nr_t& tdd_cfg) { + // Generate as many entries as DL slots harq.nof_dl_data_to_ul_ack = SRSRAN_MAX(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); - for (uint32_t i = 0; i < harq.nof_dl_data_to_ul_ack; i++) { - harq.dl_data_to_ul_ack[i] = ((harq.nof_dl_data_to_ul_ack - 4) > i) ? (harq.nof_dl_data_to_ul_ack - i) : 4; + + // Set PDSCH to ACK timing delay to 4 or more + for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { + // Set the first slots into the first UL slot + if (n < (harq.nof_dl_data_to_ul_ack - 4)) { + harq.dl_data_to_ul_ack[n] = harq.nof_dl_data_to_ul_ack - n; + continue; + } + + // After that try if n+4 is UL slot + if (srsran_tdd_nr_is_ul(&tdd_cfg, carrier.scs, n + 4)) { + harq.dl_data_to_ul_ack[n] = 4; + continue; + } + + // Otherwise set delay to the first UL slot of the next TDD period + harq.dl_data_to_ul_ack[n] = 2 * harq.nof_dl_data_to_ul_ack - n; } + // Zero the rest for (uint32_t i = harq.nof_dl_data_to_ul_ack; i < SRSRAN_MAX_NOF_DL_DATA_TO_UL; i++) { harq.dl_data_to_ul_ack[i] = 0; } + + // Select dynamic HARQ-ACK codebook + harq.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; } void phy_cfg_nr_default_t::make_prach_default_lte(srsran_prach_cfg_t& prach) @@ -207,7 +234,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) switch (reference_cfg.harq) { case reference_cfg_t::R_HARQ_AUTO: - make_harq_auto(harq_ack, tdd); + make_harq_auto(harq_ack, carrier, tdd); break; } From 5307fec2f0a7c76f06c9cd92f859965572cb1d91 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 1 Jul 2021 16:17:15 +0200 Subject: [PATCH 27/50] Added GNB MAC UL info initial interface and fix PHY implementation --- .../srsran/interfaces/gnb_interfaces.h | 19 ++++++-- lib/include/srsran/phy/phch/pucch_nr.h | 4 +- lib/src/common/phy_cfg_nr_default.cc | 2 +- lib/src/phy/gnb/gnb_ul.c | 9 +++- lib/src/phy/phch/pucch_nr.c | 9 +++- lib/src/phy/phch/test/pucch_nr_test.c | 2 +- srsenb/hdr/stack/gnb_stack_nr.h | 2 + srsenb/hdr/stack/mac/mac_nr.h | 2 + srsenb/src/phy/nr/slot_worker.cc | 23 +++++++-- srsenb/src/stack/gnb_stack_nr.cc | 8 ++++ srsenb/src/stack/mac/nr/mac_nr.cc | 8 ++++ test/phy/dummy_gnb_stack.h | 48 +++++++++++++++---- test/phy/nr_dl_flood.cc | 30 +++++++++++- test/phy/test_bench.h | 4 +- 14 files changed, 145 insertions(+), 25 deletions(-) diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index f27b5d8f2..4dc8af583 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -258,9 +258,22 @@ public: srsran::bounded_vector pucch; }; - virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0; - virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0; - virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0; + struct pucch_info_t { + srsran_uci_data_nr_t uci_data; ///< RNTI is available under cfg->pucch->rnti + // ... add signal measurements here + }; + + struct pusch_info_t { + uint16_t rnti; + srsran_pusch_res_nr_t pusch_data; + // ... add signal measurements here + }; + + virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0; + virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0; + virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0; + virtual int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) = 0; + virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) = 0; }; class stack_interface_phy_nr : public mac_interface_phy_nr, public srsran::stack_interface_phy_nr diff --git a/lib/include/srsran/phy/phch/pucch_nr.h b/lib/include/srsran/phy/phch/pucch_nr.h index a562e7b03..c652c148c 100644 --- a/lib/include/srsran/phy/phch/pucch_nr.h +++ b/lib/include/srsran/phy/phch/pucch_nr.h @@ -188,6 +188,7 @@ SRSRAN_API int srsran_pucch_nr_format1_encode(const srsran_pucch_nr_t* * @param[in] slot_symbols Resource grid of the given slot * @param[out] b Bits to decode * @param[in] nof_bits Number of bits to decode in the message + * @param[out] norm_corr Normalised correlation * @return SRSRAN_SUCCESS if successful, SRSRAN_ERROR code otherwise */ SRSRAN_API int srsran_pucch_nr_format1_decode(srsran_pucch_nr_t* q, @@ -197,7 +198,8 @@ SRSRAN_API int srsran_pucch_nr_format1_decode(srsran_pucch_nr_t* srsran_chest_ul_res_t* chest_res, cf_t* slot_symbols, uint8_t b[SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS], - uint32_t nof_bits); + uint32_t nof_bits, + float* norm_corr); /** * @brief Encoder NR-PUCCH formats 2, 3 and 4. The NR-PUCCH format is selected by resource->format. diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index becebda6a..b674ea8d8 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -228,7 +228,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) switch (reference_cfg.pucch) { case reference_cfg_t::R_PUCCH_CUSTOM_ONE: - make_pusch_default(pusch); + make_pucch_custom_one(pucch); break; } diff --git a/lib/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c index 0072adcbe..b8961c682 100644 --- a/lib/src/phy/gnb/gnb_ul.c +++ b/lib/src/phy/gnb/gnb_ul.c @@ -194,18 +194,25 @@ static int gnb_ul_decode_pucch_format1(srsran_gnb_ul_t* q, nof_bits = 1; } + // Channel estimation if (srsran_dmrs_pucch_format1_estimate(&q->pucch, cfg, slot_cfg, resource, q->sf_symbols[0], &q->chest_pucch) < SRSRAN_SUCCESS) { ERROR("Error in PUCCH format 1 estimation"); return SRSRAN_ERROR; } + // Actual decode + float norm_corr = 0.0f; if (srsran_pucch_nr_format1_decode( - &q->pucch, cfg, slot_cfg, resource, &q->chest_pucch, q->sf_symbols[0], b, nof_bits) < SRSRAN_SUCCESS) { + &q->pucch, cfg, slot_cfg, resource, &q->chest_pucch, q->sf_symbols[0], b, nof_bits, &norm_corr) < + SRSRAN_SUCCESS) { ERROR("Error in PUCCH format 1 decoding"); return SRSRAN_ERROR; } + // Take valid decision + uci_value->valid = (norm_corr > 0.5f); + // De-multiplex ACK bits for (uint32_t i = 0; i < nof_bits; i++) { uci_value->ack[i] = b[i]; diff --git a/lib/src/phy/phch/pucch_nr.c b/lib/src/phy/phch/pucch_nr.c index f7a7d1b80..58264f449 100644 --- a/lib/src/phy/phch/pucch_nr.c +++ b/lib/src/phy/phch/pucch_nr.c @@ -452,7 +452,8 @@ int srsran_pucch_nr_format1_decode(srsran_pucch_nr_t* q, srsran_chest_ul_res_t* chest_res, cf_t* slot_symbols, uint8_t b[SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS], - uint32_t nof_bits) + uint32_t nof_bits, + float* norm_corr) { uint32_t m_cs = 0; @@ -524,8 +525,14 @@ int srsran_pucch_nr_format1_decode(srsran_pucch_nr_t* q, srsran_demod_soft_demodulate((nof_bits == 1) ? SRSRAN_MOD_BPSK : SRSRAN_MOD_QPSK, &d, llr, 1); // Hard decision + float corr = 0.0f; for (uint32_t i = 0; i < nof_bits; i++) { b[i] = llr[i] > 0.0f ? 1 : 0; + corr += fabsf(llr[i]); + } + + if (norm_corr != NULL && nof_bits > 0) { + *norm_corr = corr / nof_bits; } return SRSRAN_SUCCESS; diff --git a/lib/src/phy/phch/test/pucch_nr_test.c b/lib/src/phy/phch/test/pucch_nr_test.c index 933f3661a..067c3b8ad 100644 --- a/lib/src/phy/phch/test/pucch_nr_test.c +++ b/lib/src/phy/phch/test/pucch_nr_test.c @@ -139,7 +139,7 @@ static int test_pucch_format1(srsran_pucch_nr_t* pucch, // Decode PUCCH uint8_t b_rx[SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS]; TESTASSERT(srsran_pucch_nr_format1_decode( - pucch, cfg, &slot, &resource, chest_res, slot_symbols, b_rx, nof_bits) == + pucch, cfg, &slot, &resource, chest_res, slot_symbols, b_rx, nof_bits, NULL) == SRSRAN_SUCCESS); // Check received bits diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 328348e4c..556e349a8 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -75,6 +75,8 @@ public: int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; + int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override; + int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override; private: void run_thread() final; diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index 7290dfcbd..94ab96e56 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -68,6 +68,8 @@ public: int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; + int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override; + int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override; private: void get_dl_config(const uint32_t tti, diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index bd89652ba..b355f8b55 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -159,17 +159,30 @@ bool slot_worker::work_ul() // Decode PUCCH for (stack_interface_phy_nr::pucch_t& pucch : ul_sched.pucch) { - srsran_uci_value_nr_t uci_value; - if (srsran_gnb_ul_get_pucch(&gnb_ul, &ul_slot_cfg, &pucch.pucch_cfg, &pucch.resource, &pucch.uci_cfg, &uci_value) < - SRSRAN_SUCCESS) { + stack_interface_phy_nr::pucch_info_t pucch_info = {}; + pucch_info.uci_data.cfg = pucch.uci_cfg; + + // Decode PUCCH + if (srsran_gnb_ul_get_pucch(&gnb_ul, + &ul_slot_cfg, + &pucch.pucch_cfg, + &pucch.resource, + &pucch_info.uci_data.cfg, + &pucch_info.uci_data.value) < SRSRAN_SUCCESS) { logger.error("Error getting PUCCH"); return false; } + // Inform stack + if (stack.pucch_info(ul_slot_cfg, pucch_info) < SRSRAN_SUCCESS) { + logger.error("Error pushing PUCCH information to stack"); + return false; + } + + // Log PUCCH decoding if (logger.info.enabled()) { std::array str; - srsran_uci_data_nr_t uci_data = {.cfg = pucch.uci_cfg, .value = uci_value}; - srsran_gnb_ul_pucch_info(&gnb_ul, &pucch.resource, &uci_data, str.data(), (uint32_t)str.size()); + srsran_gnb_ul_pucch_info(&gnb_ul, &pucch.resource, &pucch_info.uci_data, str.data(), (uint32_t)str.size()); logger.info("PUCCH: %s", str.data()); } diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index 54a25b4bc..1247d9b2d 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -189,5 +189,13 @@ int gnb_stack_nr::get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul { return m_mac->get_ul_sched(slot_cfg, ul_sched); } +int gnb_stack_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pucch_info_t& pucch_info) +{ + return m_mac->pucch_info(slot_cfg, pucch_info); +} +int gnb_stack_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pusch_info_t& pusch_info) +{ + return m_mac->pusch_info(slot_cfg, pusch_info); +} } // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index f03dec542..def64c456 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -276,5 +276,13 @@ int mac_nr::get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched { return 0; } +int mac_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pucch_info_t& pucch_info) +{ + return 0; +} +int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pusch_info_t& pusch_info) +{ + return 0; +} } // namespace srsenb diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 5705d78ee..1d1008c9a 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -14,8 +14,10 @@ #define SRSRAN_DUMMY_GNB_STACK_H #include +#include #include #include +#include #include class gnb_dummy_stack : public srsenb::stack_interface_phy_nr @@ -36,6 +38,9 @@ private: srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; + std::mutex mac_metrics_mutex; + srsenb::mac_ue_metrics_t mac_metrics = {}; + // HARQ feedback class pending_ack_t { @@ -61,21 +66,15 @@ private: srsran_pdsch_ack_nr_t get_ack() { std::unique_lock lock(mutex); - - return ack; + srsran_pdsch_ack_nr_t ret = ack; + ack = {}; + return ret; } uint32_t get_dai() { std::unique_lock lock(mutex); return ack.cc[0].M % 4; } - - void reset() - { - std::unique_lock lock(mutex); - - ack = {}; - } }; srsran::circular_array pending_ack; @@ -264,7 +263,6 @@ public: logger.set_context(slot_cfg.idx); srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx].get_ack(); - pending_ack[slot_cfg.idx].reset(); if (ack.nof_cc > 0) { mac_interface_phy_nr::pucch_t pucch = {}; @@ -286,6 +284,36 @@ public: return 0; } + + int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override + { + std::unique_lock lock(mac_metrics_mutex); + + for (uint32_t i = 0; i < pucch_info.uci_data.cfg.ack.count; i++) { + const srsran_harq_ack_bit_t* ack_bit = &pucch_info.uci_data.cfg.ack.bits[i]; + bool is_ok = (pucch_info.uci_data.value.ack[i] == 1) and pucch_info.uci_data.value.valid; + uint32_t tb_count = (ack_bit->tb0 ? 1 : 0) + (ack_bit->tb1 ? 1 : 0); + mac_metrics.tx_pkts += tb_count; + if (not is_ok) { + mac_metrics.tx_errors += tb_count; + logger.debug("NACK received!"); + } + } + return SRSRAN_SUCCESS; + } + + int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override + { + // ... Not implemented + return SRSRAN_ERROR; + } + + srsenb::mac_ue_metrics_t get_metrics() + { + std::unique_lock lock(mac_metrics_mutex); + + return mac_metrics; + } }; #endif // SRSRAN_DUMMY_GNB_STACK_H diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_dl_flood.cc index 5476c93d0..270e74894 100644 --- a/test/phy/nr_dl_flood.cc +++ b/test/phy/nr_dl_flood.cc @@ -120,10 +120,38 @@ int main(int argc, char** argv) // Assert bench is initialised correctly TESTASSERT(tb.is_initialised()); - for (uint32_t i = 0; i < 20; i++) { + // Run per TTI basis + for (uint32_t i = 0; i < 1000; i++) { TESTASSERT(tb.run_tti()); } + // Stop test bench + tb.stop(); + + // Flush log + srslog::flush(); + + // Retrieve MAC metrics + srsenb::mac_ue_metrics_t mac_metrics = gnb_stack.get_metrics(); + + // Print metrics + float pdsch_bler = 0.0f; + if (mac_metrics.tx_pkts != 0) { + pdsch_bler = (float)mac_metrics.tx_errors / (float)mac_metrics.tx_pkts; + } + float pdsch_rate = 0.0f; + if (mac_metrics.tx_pkts != 0) { + pdsch_rate = (float)mac_metrics.tx_brate / (float)mac_metrics.tx_pkts / 1000.0f; + } + + srsran::console("PDSCH:\n"); + srsran::console(" Count: %d\n", mac_metrics.tx_pkts); + srsran::console(" BLER: %f\n", pdsch_bler); + srsran::console(" Rate: %f Mbps\n", pdsch_rate); + + // Assert metrics + TESTASSERT(mac_metrics.tx_errors == 0); + // If reached here, the test is successful return SRSRAN_SUCCESS; } diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index 11425de6f..91282ed4c 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -75,7 +75,7 @@ public: initialised = true; } - ~test_bench() + void stop() { ue_phy_com.stop(); gnb_phy_com.stop(); @@ -83,6 +83,8 @@ public: ue_phy.stop(); } + ~test_bench() = default; + bool is_initialised() const { return initialised; } bool run_tti() From a7c728c1894907ee9ba753746f34cb870eda46fe Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 2 Jul 2021 14:33:00 +0200 Subject: [PATCH 28/50] Fix old gcc compilation --- test/phy/dummy_gnb_stack.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 1d1008c9a..e8837b39d 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -49,6 +49,7 @@ private: srsran_pdsch_ack_nr_t ack = {}; public: + pending_ack_t() = default; void push_ack(srsran_harq_ack_resource_t& ack_resource) { // Prepare ACK information @@ -76,7 +77,7 @@ private: return ack.cc[0].M % 4; } }; - srsran::circular_array pending_ack; + srsran::circular_array pending_ack = {}; struct dummy_harq_proc { static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; From c11a5cc2c8e9c2a05bf136cdc4f355319a6c0347 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 5 Jul 2021 10:54:48 +0200 Subject: [PATCH 29/50] Walk around GCC 4.8 compilation --- CMakeLists.txt | 4 ++-- test/phy/dummy_gnb_stack.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5cae6c3f..25878d16d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -509,8 +509,8 @@ endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # Add colored output when using the Ninja generator if("Ninja" STREQUAL ${CMAKE_GENERATOR}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") + ADD_C_COMPILER_FLAG_IF_AVAILABLE("-fdiagnostics-color=always" HAVE_DIAGNOSTIC_COLOR_C) + ADD_CXX_COMPILER_FLAG_IF_AVAILABLE("-fdiagnostics-color=always" HAVE_DIAGNOSTIC_COLOR_CXX) endif() # Add -Werror to C/C++ flags for newer compilers diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index e8837b39d..42c2d9c5d 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -77,7 +77,7 @@ private: return ack.cc[0].M % 4; } }; - srsran::circular_array pending_ack = {}; + std::array pending_ack = {}; struct dummy_harq_proc { static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; @@ -218,7 +218,7 @@ public: dci.rv = 0; dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; - dci.dai = pending_ack[harq_ack_slot_idx].get_dai(); + dci.dai = pending_ack[harq_ack_slot_idx % pending_ack.size()].get_dai(); dci.tpc = 1; dci.pucch_resource = 0; if (dci.ctx.format == srsran_dci_format_nr_1_0) { @@ -254,7 +254,7 @@ public: } // Calculate PUCCH slot and push resource - pending_ack[harq_ack_slot_idx].push_ack(ack_resource); + pending_ack[harq_ack_slot_idx % pending_ack.size()].push_ack(ack_resource); return SRSRAN_SUCCESS; } @@ -263,7 +263,7 @@ public: { logger.set_context(slot_cfg.idx); - srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx].get_ack(); + srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx % pending_ack.size()].get_ack(); if (ack.nof_cc > 0) { mac_interface_phy_nr::pucch_t pucch = {}; From 19996a405955f6538103fb6056617866d46691d5 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 6 Jul 2021 10:11:50 +0200 Subject: [PATCH 30/50] sched_nr: fix compilation --- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 10ec47495..edbc47e95 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -16,9 +16,9 @@ #include "srsran/adt/bounded_bitset.h" #include "srsran/adt/bounded_vector.h" #include "srsran/adt/span.h" +#include "srsran/common/phy_cfg_nr.h" #include "srsran/common/tti_point.h" #include "srsran/interfaces/gnb_interfaces.h" -#include "srsran/interfaces/rrc_nr_interface_types.h" #include "srsran/phy/phch/dci_nr.h" namespace srsenb { From ec3465bb983582b8f9e45766b6c36dc4e92ae498 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 6 Jul 2021 12:48:41 +0200 Subject: [PATCH 31/50] s1ap: fix compilation of test on 32bit --- srsenb/test/s1ap/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/srsenb/test/s1ap/CMakeLists.txt b/srsenb/test/s1ap/CMakeLists.txt index 6419653ef..3025734a1 100644 --- a/srsenb/test/s1ap/CMakeLists.txt +++ b/srsenb/test/s1ap/CMakeLists.txt @@ -7,6 +7,5 @@ # add_executable(s1ap_test s1ap_test.cc) -target_link_libraries(s1ap_test srsran_common s1ap_asn1 srsenb_s1ap srsenb_upper s1ap_asn1 ${SCTP_LIBRARIES}) -add_test(s1ap_test s1ap_test) - +target_link_libraries(s1ap_test srsran_common s1ap_asn1 srsenb_s1ap srsenb_upper s1ap_asn1 ${SCTP_LIBRARIES} ${ATOMIC_LIBS}) +add_test(s1ap_test s1ap_test) \ No newline at end of file From 53a7dc78ee72db1e2f32afcdbd86dbc734cce7a3 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 16:10:39 +0200 Subject: [PATCH 32/50] rlc_am_lte: replace do_status boolean with atomic the do_status is queried from the Tx code frequently. To reduce chances to delay the execution because the RLC Rx side is currently holding the mutex we can use an atomic. --- lib/include/srsran/rlc/rlc_am_lte.h | 4 ++-- lib/src/rlc/rlc_am_lte.cc | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index 6574e8297..4de710f38 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -527,8 +527,8 @@ private: rlc_ringbuffer_t rx_window; std::map rx_segments; - bool poll_received = false; - bool do_status = false; + bool poll_received = false; + std::atomic do_status = {false}; // light-weight access from Tx entity /**************************************************************************** * Timers diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index 967cf5a55..c0848e5a8 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -1852,8 +1852,7 @@ void rlc_am_lte::rlc_am_lte_rx::reset_status() bool rlc_am_lte::rlc_am_lte_rx::get_do_status() { - std::lock_guard lock(mutex); - return do_status; + return do_status.load(std::memory_order_relaxed); } void rlc_am_lte::rlc_am_lte_rx::write_pdu(uint8_t* payload, const uint32_t nof_bytes) From 4379c20eb92879a0fdc42099320311b0d196af92 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 16:32:52 +0200 Subject: [PATCH 33/50] rlc_am_lte: avoid locking of Rx mutex twice when generating status PDU call reset_status(), which now is an private method directly when building a status PDU. No need for the Tx side to call Rx again. --- lib/include/srsran/rlc/rlc_am_lte.h | 2 +- lib/src/rlc/rlc_am_lte.cc | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index 4de710f38..9066f3236 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -484,7 +484,6 @@ private: int get_status_pdu_length(); int get_status_pdu(rlc_status_pdu_t* status, const uint32_t nof_bytes); bool get_do_status(); - void reset_status(); // called when status PDU has been sent private: void handle_data_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_amd_pdu_header_t& header); @@ -494,6 +493,7 @@ private: void debug_state(); void print_rx_segments(); bool add_segment_and_check(rlc_amd_rx_pdu_segments_t* pdu, rlc_amd_rx_pdu* segment); + void reset_status(); rlc_am_lte* parent = nullptr; byte_buffer_pool* pool = nullptr; diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index c0848e5a8..6cc8ab07a 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -671,9 +671,6 @@ int rlc_am_lte::rlc_am_lte_tx::build_status_pdu(uint8_t* payload, uint32_t nof_b pdu_len = 0; } else if (pdu_len > 0 && nof_bytes >= static_cast(pdu_len)) { log_rlc_am_status_pdu_to_string(logger.info, "%s Tx status PDU - %s", &tx_status, RB_NAME); - - parent->rx.reset_status(); - if (cfg.t_status_prohibit > 0 && status_prohibit_timer.is_valid()) { // re-arm timer status_prohibit_timer.run(); @@ -1845,7 +1842,6 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus() void rlc_am_lte::rlc_am_lte_rx::reset_status() { - std::lock_guard lock(mutex); do_status = false; poll_received = false; } @@ -1970,6 +1966,9 @@ int rlc_am_lte::rlc_am_lte_rx::get_status_pdu(rlc_status_pdu_t* status, const ui i = (i + 1) % MOD; } + // valid PDU could be generated + reset_status(); + return rlc_am_packed_length(status); } From fa461f01291bd4bee4a1c20e0e914d651450e967 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 2 Jul 2021 13:15:23 +0200 Subject: [PATCH 34/50] rrc_nr: fix linker error in setup_release_c move implementation to cc file to avoid [build] /bin/ld: CMakeFiles/rrc_nr_asn1_test.dir/rrc_nr_test.cc.o: in function `asn1::rrc_nr::setup_release_c::set_setup()': [build] /home/anpu/src/srsLTE/lib/include/srsran/asn1/rrc_nr.h:2276: undefined reference to `asn1::rrc_nr::setup_release_c::set(asn1::rrc_nr::setup_release_c::types_opts::options)' [build] clang: error: linker command failed with exit code 1 (use -v to see invocation) --- lib/include/srsran/asn1/rrc_nr.h | 56 +++++++++++++++++++++++++++++--- lib/src/asn1/rrc_nr.cc | 55 ------------------------------- 2 files changed, 52 insertions(+), 59 deletions(-) diff --git a/lib/include/srsran/asn1/rrc_nr.h b/lib/include/srsran/asn1/rrc_nr.h index 4638045ab..8e1362f56 100644 --- a/lib/include/srsran/asn1/rrc_nr.h +++ b/lib/include/srsran/asn1/rrc_nr.h @@ -2254,11 +2254,8 @@ struct setup_release_c { // choice methods setup_release_c() = default; - void set(typename types::options e = types::nulltype); types type() const { return type_; } - SRSASN_CODE pack(bit_ref& bref) const; - SRSASN_CODE unpack(cbit_ref& bref); - void to_json(json_writer& j) const; + // getters elem_type_paramT_& setup() { @@ -2271,6 +2268,57 @@ struct setup_release_c { return c; } void set_release() { set(types::release); } + + void set(typename types::options e) { type_ = e; } + + void to_json(json_writer& j) const + { + j.start_obj(); + switch (type_) { + case types::release: + break; + case types::setup: + break; + default: + log_invalid_choice_id(type_, "setup_release_c"); + } + j.end_obj(); + } + + SRSASN_CODE pack(bit_ref& bref) const + { + type_.pack(bref); + switch (type_) { + case types::release: + break; + case types::setup: + HANDLE_CODE(c.pack(bref)); + break; + default: + log_invalid_choice_id(type_, "setup_release_c"); + return SRSASN_ERROR_ENCODE_FAIL; + } + return SRSASN_SUCCESS; + } + + SRSASN_CODE unpack(cbit_ref& bref) + { + types e; + e.unpack(bref); + set(e); + switch (type_) { + case types::release: + break; + case types::setup: + HANDLE_CODE(c.unpack(bref)); + break; + default: + log_invalid_choice_id(type_, "setup_release_c"); + return SRSASN_ERROR_DECODE_FAIL; + } + return SRSASN_SUCCESS; + } + elem_type_paramT_& set_setup() { set(types::setup); diff --git a/lib/src/asn1/rrc_nr.cc b/lib/src/asn1/rrc_nr.cc index 4ceb86fe7..f940f3375 100644 --- a/lib/src/asn1/rrc_nr.cc +++ b/lib/src/asn1/rrc_nr.cc @@ -4484,61 +4484,6 @@ uint8_t sib_type_info_s::type_opts::to_number() const return map_enum_number(options, 8, value, "sib_type_info_s::type_e_"); } -// SetupRelease{ElementTypeParam} ::= CHOICE -template -void setup_release_c::set(typename types::options e) -{ - type_ = e; -} -template -void setup_release_c::to_json(json_writer& j) const -{ - j.start_obj(); - switch (type_) { - case types::release: - break; - case types::setup: - break; - default: - log_invalid_choice_id(type_, "setup_release_c"); - } - j.end_obj(); -} -template -SRSASN_CODE setup_release_c::pack(bit_ref& bref) const -{ - type_.pack(bref); - switch (type_) { - case types::release: - break; - case types::setup: - HANDLE_CODE(c.pack(bref)); - break; - default: - log_invalid_choice_id(type_, "setup_release_c"); - return SRSASN_ERROR_ENCODE_FAIL; - } - return SRSASN_SUCCESS; -} -template -SRSASN_CODE setup_release_c::unpack(cbit_ref& bref) -{ - types e; - e.unpack(bref); - set(e); - switch (type_) { - case types::release: - break; - case types::setup: - HANDLE_CODE(c.unpack(bref)); - break; - default: - log_invalid_choice_id(type_, "setup_release_c"); - return SRSASN_ERROR_DECODE_FAIL; - } - return SRSASN_SUCCESS; -} - // UAC-BarringPerCat ::= SEQUENCE SRSASN_CODE uac_barr_per_cat_s::pack(bit_ref& bref) const { From c9e87b2cf3529c34ba3c88bc1046be77528fc111 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 28 Jun 2021 12:35:03 +0200 Subject: [PATCH 35/50] config_file: print message when config file couldn't be read this prints an message on stdout so config files are not simply skipped and the default one is read instead. --- lib/include/srsran/common/config_file.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/include/srsran/common/config_file.h b/lib/include/srsran/common/config_file.h index 264f670d1..56c6d4530 100644 --- a/lib/include/srsran/common/config_file.h +++ b/lib/include/srsran/common/config_file.h @@ -35,6 +35,7 @@ bool config_exists(std::string& filename, std::string default_name) homedir = "."; } snprintf(full_path, sizeof(full_path), "%s/.config/srsran/%s", homedir, default_name.c_str()); + printf("Couldn't open %s, trying %s\n", filename.c_str(), full_path); filename = std::string(full_path); // try to open again @@ -43,6 +44,7 @@ bool config_exists(std::string& filename, std::string default_name) // Last chance, try to find file in /etc/srsran ZERO_OBJECT(full_path); snprintf(full_path, sizeof(full_path), "/etc/srsran/%s", default_name.c_str()); + printf("Couldn't open %s either, trying %s\n", filename.c_str(), full_path); filename = std::string(full_path); // try to open again From 8dd7075d12b2723bda7a1434dd6142fced150a2e Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 28 Jun 2021 12:36:39 +0200 Subject: [PATCH 36/50] enb,stack: add NR components for NSA mode adds the main NR components for RLC, PDCP, MAC and RRC for NSA operation. --- srsenb/hdr/stack/enb_stack_lte.h | 12 ++++++++++++ srsenb/hdr/stack/mac/mac_nr.h | 6 +++++- srsenb/hdr/stack/rrc/rrc_nr.h | 4 ++-- srsenb/src/stack/enb_stack_lte.cc | 20 +++++++++++++++++--- srsenb/src/stack/gnb_stack_nr.cc | 4 ++-- srsenb/src/stack/mac/nr/mac_nr.cc | 4 +++- srsenb/src/stack/rrc/rrc_nr.cc | 6 ++++-- srsenb/test/rrc/rrc_nr_test.cc | 10 +++++----- 8 files changed, 50 insertions(+), 16 deletions(-) diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 0cd47e7db..64e5c4ec7 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -19,7 +19,9 @@ #define SRSRAN_ENB_STACK_LTE_H #include "mac/mac.h" +#include "mac/mac_nr.h" #include "rrc/rrc.h" +#include "rrc/rrc_nr.h" #include "s1ap/s1ap.h" #include "srsran/common/task_scheduler.h" #include "upper/gtpu.h" @@ -119,6 +121,10 @@ private: srslog::basic_logger& s1ap_logger; srslog::basic_logger& gtpu_logger; srslog::basic_logger& stack_logger; + srslog::basic_logger& rrc_nr_logger; + srslog::basic_logger& mac_nr_logger; + srslog::basic_logger& rlc_nr_logger; + srslog::basic_logger& pdcp_nr_logger; // PCAP and trace option srsran::mac_pcap mac_pcap; @@ -136,6 +142,12 @@ private: srsenb::gtpu gtpu; srsenb::s1ap s1ap; + // NR components for NSA mode + srsenb::mac_nr mac_nr; + srsenb::rlc rlc_nr; + srsenb::pdcp pdcp_nr; + srsenb::rrc_nr rrc_nr; + // RAT-specific interfaces phy_interface_stack_lte* phy = nullptr; diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index 94ab96e56..418fa1dc2 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -18,6 +18,7 @@ #include "srsran/mac/mac_sch_pdu_nr.h" #include "srsenb/hdr/stack/enb_stack_base.h" +#include "srsran/common/task_scheduler.h" #include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/gnb_interfaces.h" @@ -40,7 +41,7 @@ struct mac_nr_args_t { class mac_nr final : public mac_interface_phy_nr, public mac_interface_rrc_nr, public mac_interface_rlc_nr { public: - mac_nr(); + mac_nr(srsran::task_sched_handle task_sched_); ~mac_nr(); int init(const mac_nr_args_t& args_, @@ -85,6 +86,9 @@ private: rlc_interface_mac_nr* rlc_h = nullptr; rrc_interface_mac_nr* rrc_h = nullptr; + // args + srsran::task_sched_handle task_sched; + std::unique_ptr pcap = nullptr; mac_nr_args_t args = {}; srslog::basic_logger& logger; diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index b36ff70c0..ead9c9102 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -63,7 +63,7 @@ class rrc_nr final : public rrc_interface_pdcp_nr, public rrc_interface_ngap_nr { public: - explicit rrc_nr(srsran::timer_handler* timers_); + explicit rrc_nr(srsran::task_sched_handle task_sched_); int32_t init(const rrc_nr_cfg_t& cfg, phy_interface_stack_nr* phy, @@ -132,7 +132,7 @@ private: ngap_interface_rrc_nr* ngap = nullptr; // args - srsran::timer_handler* timers = nullptr; + srsran::task_sched_handle task_sched; // derived uint32_t slot_dur_ms = 0; diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index e8918fb77..af7b4ea8f 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -24,19 +24,27 @@ namespace srsenb { enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : thread("STACK"), mac_logger(srslog::fetch_basic_logger("MAC", log_sink)), + mac_nr_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)), rlc_logger(srslog::fetch_basic_logger("RLC", log_sink, false)), + rlc_nr_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)), pdcp_logger(srslog::fetch_basic_logger("PDCP", log_sink, false)), + pdcp_nr_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)), rrc_logger(srslog::fetch_basic_logger("RRC", log_sink, false)), + rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)), s1ap_logger(srslog::fetch_basic_logger("S1AP", log_sink, false)), gtpu_logger(srslog::fetch_basic_logger("GTPU", log_sink, false)), stack_logger(srslog::fetch_basic_logger("STCK", log_sink, false)), task_sched(512, 128), pdcp(&task_sched, pdcp_logger), + pdcp_nr(&task_sched, pdcp_nr_logger), mac(&task_sched, mac_logger), + mac_nr(&task_sched), rlc(rlc_logger), + rlc_nr(rlc_nr_logger), gtpu(&task_sched, gtpu_logger, &rx_sockets), s1ap(&task_sched, s1ap_logger, &rx_sockets), rrc(&task_sched), + rrc_nr(&task_sched), mac_pcap(), pending_stack_metrics(64) { @@ -78,19 +86,25 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) // setup logging for each layer mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); - mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); - - // Init logs + mac_nr_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); + rlc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); + pdcp_nr_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); + rrc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); gtpu_logger.set_level(srslog::str_to_basic_level(args.log.gtpu_level)); s1ap_logger.set_level(srslog::str_to_basic_level(args.log.s1ap_level)); stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level)); + mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); + mac_nr_logger.set_hex_dump_max_size(args.log.mac_hex_limit); rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); + rlc_nr_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); + pdcp_nr_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); + rrc_nr_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit); s1ap_logger.set_hex_dump_max_size(args.log.s1ap_hex_limit); stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit); diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index 1247d9b2d..f103c2d89 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -18,10 +18,10 @@ namespace srsenb { gnb_stack_nr::gnb_stack_nr() : task_sched{512, 128}, thread("gNB"), rlc_logger(srslog::fetch_basic_logger("RLC-NR")) { - m_mac.reset(new mac_nr()); + m_mac.reset(new mac_nr(&task_sched)); m_rlc.reset(new rlc_nr("RLC-NR")); m_pdcp.reset(new pdcp_nr(&task_sched, "PDCP-NR")); - m_rrc.reset(new rrc_nr(task_sched.get_timer_handler())); + m_rrc.reset(new rrc_nr(&task_sched)); m_sdap.reset(new sdap()); m_gw.reset(new srsue::gw()); // m_gtpu.reset(new srsenb::gtpu()); diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index def64c456..5e8acf1ad 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -20,7 +20,9 @@ namespace srsenb { -mac_nr::mac_nr() : logger(srslog::fetch_basic_logger("MAC-NR")) {} +mac_nr::mac_nr(srsran::task_sched_handle task_sched_) : + logger(srslog::fetch_basic_logger("MAC-NR")), task_sched(task_sched_) +{} mac_nr::~mac_nr() { diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index b8c0f407d..1d74129d1 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -19,7 +19,9 @@ using namespace asn1::rrc_nr; namespace srsenb { -rrc_nr::rrc_nr(srsran::timer_handler* timers_) : logger(srslog::fetch_basic_logger("RRC-NR")), timers(timers_) {} +rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) : + logger(srslog::fetch_basic_logger("RRC-NR")), task_sched(task_sched_) +{} int rrc_nr::init(const rrc_nr_cfg_t& cfg_, phy_interface_stack_nr* phy_, @@ -357,7 +359,7 @@ void rrc_nr::notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) {} rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_) : parent(parent_), rnti(rnti_) { // setup periodic RRCSetup send - rrc_setup_periodic_timer = parent->timers->get_unique_timer(); + rrc_setup_periodic_timer = parent->task_sched.get_unique_timer(); rrc_setup_periodic_timer.set(5000, [this](uint32_t tid) { send_connection_setup(); rrc_setup_periodic_timer.run(); diff --git a/srsenb/test/rrc/rrc_nr_test.cc b/srsenb/test/rrc/rrc_nr_test.cc index 466b9b65f..bd1c79e84 100644 --- a/srsenb/test/rrc/rrc_nr_test.cc +++ b/srsenb/test/rrc/rrc_nr_test.cc @@ -35,12 +35,12 @@ int test_cell_cfg(const srsenb::sched_interface::cell_cfg_t& cellcfg) */ int test_sib_generation() { - srsran::timer_handler timers_db(128); + srsran::task_scheduler task_sched; mac_dummy mac_obj; rlc_dummy rlc_obj; pdcp_dummy pdcp_obj; - rrc_nr rrc_obj(&timers_db); + rrc_nr rrc_obj(&task_sched); // set cfg rrc_nr_cfg_t default_cfg = {}; @@ -63,12 +63,12 @@ int test_sib_generation() int test_rrc_setup() { - srsran::timer_handler timers_db(128); + srsran::task_scheduler task_sched; mac_dummy mac_obj; rlc_dummy rlc_obj; pdcp_dummy pdcp_obj; - rrc_nr rrc_obj(&timers_db); + rrc_nr rrc_obj(&task_sched); // set cfg rrc_nr_cfg_t default_cfg = {}; @@ -78,7 +78,7 @@ int test_rrc_setup() for (uint32_t n = 0; n < 2; ++n) { uint32_t timeout = 5500; for (uint32_t i = 0; i < timeout and rlc_obj.last_sdu == nullptr; ++i) { - timers_db.step_all(); + task_sched.tic(); } TESTASSERT(rlc_obj.last_sdu != nullptr); } From 6bf3feda92dec0839648130766563a15cad48f5d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 29 Jun 2021 14:57:00 +0200 Subject: [PATCH 37/50] rrc_nr_test: add packing test for NR radio bearer config also add (still incomplete) secondary cell group config pack test --- lib/test/asn1/rrc_nr_test.cc | 200 +++++++++++++++++++++++++++++++++-- 1 file changed, 189 insertions(+), 11 deletions(-) diff --git a/lib/test/asn1/rrc_nr_test.cc b/lib/test/asn1/rrc_nr_test.cc index 1d89111f8..cb4c2665a 100644 --- a/lib/test/asn1/rrc_nr_test.cc +++ b/lib/test/asn1/rrc_nr_test.cc @@ -14,6 +14,8 @@ #include "srsran/common/test_common.h" #include +#define JSON_OUTPUT 0 + using namespace asn1; using namespace asn1::rrc_nr; @@ -175,9 +177,11 @@ int test_ue_rrc_reconfiguration() TESTASSERT(rrc_recfg.unpack(bref) == SRSASN_SUCCESS); TESTASSERT(rrc_recfg.rrc_transaction_id == 0); +#if JSON_OUTPUT json_writer jw; rrc_recfg.to_json(jw); srslog::fetch_basic_logger("RRC").info("RRC Reconfig: \n %s", jw.to_string().c_str()); +#endif TESTASSERT(rrc_recfg.crit_exts.type() == asn1::rrc_nr::rrc_recfg_s::crit_exts_c_::types::rrc_recfg); TESTASSERT(rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group_present == true); @@ -186,9 +190,11 @@ int test_ue_rrc_reconfiguration() cbit_ref bref0(rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group.data(), rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group.size()); TESTASSERT(cell_group_cfg.unpack(bref0) == SRSASN_SUCCESS); - // json_writer jw1; - // cell_group_cfg.to_json(jw1); - // srslog::fetch_basic_logger("RRC").info("RRC Secondary Cell Group: \n %s", jw1.to_string().c_str()); +#if JSON_OUTPUT + json_writer jw1; + cell_group_cfg.to_json(jw1); + srslog::fetch_basic_logger("RRC").info("RRC Secondary Cell Group: \n %s", jw1.to_string().c_str()); +#endif TESTASSERT(cell_group_cfg.cell_group_id == 1); TESTASSERT(cell_group_cfg.rlc_bearer_to_add_mod_list_present == true); TESTASSERT(cell_group_cfg.rlc_bearer_to_add_mod_list.size() == 1); @@ -201,18 +207,76 @@ int test_ue_rrc_reconfiguration() int test_radio_bearer_config() { uint8_t rrc_msg[] = "\x14\x09\x28\x17\x87\xc0\x0c\x28"; - uint32_t rrc_msg_len = sizeof(rrc_msg); cbit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); radio_bearer_cfg_s radio_bearer_cfg; TESTASSERT(radio_bearer_cfg.unpack(bref) == SRSASN_SUCCESS); - // json_writer jw; - // radio_bearer_cfg.to_json(jw); - // srslog::fetch_basic_logger("RRC").info("RRC Bearer CFG Message: \n %s", jw.to_string().c_str()); +#if JSON_OUTPUT + json_writer jw; + radio_bearer_cfg.to_json(jw); + srslog::fetch_basic_logger("RRC").info("RRC Bearer CFG Message: \n %s", jw.to_string().c_str()); +#endif TESTASSERT(radio_bearer_cfg.drb_to_add_mod_list_present == true); TESTASSERT(radio_bearer_cfg.drb_to_add_mod_list.size() == 1); TESTASSERT(radio_bearer_cfg.security_cfg_present == true); TESTASSERT(radio_bearer_cfg.security_cfg.security_algorithm_cfg_present == true); TESTASSERT(radio_bearer_cfg.security_cfg.key_to_use_present == true); + + // full RRC reconfig pack + rrc_recfg_s reconfig; + reconfig.rrc_transaction_id = 0; + rrc_recfg_ies_s& recfg_ies = reconfig.crit_exts.set_rrc_recfg(); + + recfg_ies.radio_bearer_cfg_present = true; + recfg_ies.radio_bearer_cfg.drb_to_add_mod_list_present = true; + recfg_ies.radio_bearer_cfg.drb_to_add_mod_list.resize(1); + + auto& drb_item = recfg_ies.radio_bearer_cfg.drb_to_add_mod_list[0]; + drb_item.drb_id = 1; + drb_item.cn_assoc_present = true; + drb_item.cn_assoc.set_eps_bearer_id() = 5; + drb_item.pdcp_cfg_present = true; + drb_item.pdcp_cfg.ciphering_disabled_present = true; + drb_item.pdcp_cfg.drb_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_dl_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_dl = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_dl_opts::len18bits; + drb_item.pdcp_cfg.drb.pdcp_sn_size_ul_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_ul = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_ul_opts::len18bits; + drb_item.pdcp_cfg.drb.discard_timer_present = true; + drb_item.pdcp_cfg.drb.discard_timer = asn1::rrc_nr::pdcp_cfg_s::drb_s_::discard_timer_opts::ms100; + drb_item.pdcp_cfg.drb.hdr_compress.set_not_used(); + drb_item.pdcp_cfg.t_reordering_present = true; + drb_item.pdcp_cfg.t_reordering = asn1::rrc_nr::pdcp_cfg_s::t_reordering_opts::ms0; + + recfg_ies.radio_bearer_cfg.security_cfg_present = true; + recfg_ies.radio_bearer_cfg.security_cfg.key_to_use_present = true; + recfg_ies.radio_bearer_cfg.security_cfg.key_to_use = asn1::rrc_nr::security_cfg_s::key_to_use_opts::secondary; + recfg_ies.radio_bearer_cfg.security_cfg.security_algorithm_cfg_present = true; + recfg_ies.radio_bearer_cfg.security_cfg.security_algorithm_cfg.ciphering_algorithm = ciphering_algorithm_opts::nea2; + + uint8_t buffer[1024]; + asn1::bit_ref bref_pack(buffer, sizeof(buffer)); + TESTASSERT(reconfig.pack(bref_pack) == asn1::SRSASN_SUCCESS); + TESTASSERT(test_pack_unpack_consistency(reconfig) == SRSASN_SUCCESS); + +#if JSON_OUTPUT + reconfig.to_json(jw); + srslog::fetch_basic_logger("RRC").info("RRC Reconfig Message: \n %s", jw.to_string().c_str()); +#endif + + // only pack the radio bearer config to compare against TV + asn1::bit_ref bref_pack2(buffer, sizeof(buffer)); + radio_bearer_cfg_s& radio_bearer_cfg_pack = recfg_ies.radio_bearer_cfg; + TESTASSERT(radio_bearer_cfg_pack.pack(bref_pack2) == asn1::SRSASN_SUCCESS); + +#if JSON_OUTPUT + radio_bearer_cfg_pack.to_json(jw); + srslog::fetch_basic_logger("RRC").info("Radio bearer config Message: \n %s", jw.to_string().c_str()); +#endif + + // TODO: messages don't match yet + // TESTASSERT(bref_pack2.distance_bytes() == sizeof(rrc_msg)); + // TESTASSERT(memcmp(rrc_msg, buffer, sizeof(rrc_msg)) == 0); + return SRSRAN_SUCCESS; } @@ -262,7 +326,7 @@ int test_cell_group_config() TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg_present == true); TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg_present == true); TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present == true); - TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync_present = true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync_present == true); TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present == true); TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present == true); TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci == 500); @@ -291,9 +355,123 @@ int test_cell_group_config() TESTASSERT(rach_cfg_common.rach_cfg_generic.ra_resp_win == asn1::rrc_nr::rach_cfg_generic_s::ra_resp_win_opts::sl10); TESTASSERT(rach_cfg_common.ssb_per_rach_occasion_and_cb_preambs_per_ssb_present == true); - // asn1::json_writer json_writer; - // cell_group_cfg.to_json(json_writer); - // srslog::fetch_basic_logger("RRC").info("RRC Secondary Cell Group: Content: %s\n", json_writer.to_string().c_str()); +#if JSON_OUTPUT + asn1::json_writer json_writer; + cell_group_cfg.to_json(json_writer); + srslog::fetch_basic_logger("RRC").info("RRC Secondary Cell Group: Content: %s\n", json_writer.to_string().c_str()); +#endif + + // pack it again + cell_group_cfg_s cell_group_cfg_pack; + cell_group_cfg_pack.sp_cell_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.serv_cell_idx_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + + // TODO: add setup + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg_present = true; + auto& pdcch_cfg = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg.set_setup(); + // TODO: add PDCCH config + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg_present = true; + auto& pdsch_cfg = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.set_setup(); + // TODO: add PDSCH config + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.set_setup(); + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.new_ue_id = 17943; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release(); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.t304 = recfg_with_sync_s::t304_opts::ms1000; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = 0; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dmrs_type_a_position = + asn1::rrc_nr::serving_cell_cfg_common_s::dmrs_type_a_position_opts::pos2; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci = 500; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing = + subcarrier_spacing_opts::khz30; + + // DL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .absolute_freq_ssb_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb = + 632640; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list + .push_back(78); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = + 632316; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .scs_specific_carrier_list.resize(1); + auto& dl_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .scs_specific_carrier_list[0]; + dl_carrier.offset_to_carrier = 0; + dl_carrier.subcarrier_spacing = subcarrier_spacing_opts::khz15; + dl_carrier.carrier_bw = 52; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.generic_params + .location_and_bw = 14025; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.generic_params + .subcarrier_spacing = subcarrier_spacing_opts::khz15; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdcch_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common + .set_setup(); + // TODO: add PDCCH config + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdsch_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdsch_cfg_common + .set_setup(); + // TODO: add PDSCH config + + // UL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.dummy = time_align_timer_opts::ms500; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul + .scs_specific_carrier_list.resize(1); + auto& ul_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul + .scs_specific_carrier_list[0]; + ul_carrier.offset_to_carrier = 0; + ul_carrier.subcarrier_spacing = subcarrier_spacing_opts::khz15; + ul_carrier.carrier_bw = 52; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.generic_params + .location_and_bw = 14025; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.generic_params + .subcarrier_spacing = subcarrier_spacing_opts::khz15; + + // TODO: add config field for RACH +#if 0 + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present=true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.set_setup(); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.setup().prach_root_seq_idx = 10; +#endif + + uint8_t buffer[1024]; + asn1::bit_ref bref_pack(buffer, sizeof(buffer)); + TESTASSERT(cell_group_cfg_pack.pack(bref_pack) == asn1::SRSASN_SUCCESS); + TESTASSERT(test_pack_unpack_consistency(cell_group_cfg_pack) == SRSASN_SUCCESS); + +#if JSON_OUTPUT + int packed_len = bref_pack.distance_bytes(); + asn1::json_writer json_writer2; + cell_group_cfg_pack.to_json(json_writer2); + srslog::fetch_basic_logger("RRC").info( + buffer, packed_len, "Cell group config repacked (%d B): \n %s", packed_len, json_writer2.to_string().c_str()); +#endif + return SRSRAN_SUCCESS; } From fd7b9a05757e1c35c6a0216c8d7570d7430eea68 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 29 Jun 2021 15:00:40 +0200 Subject: [PATCH 38/50] enb,nsa: add basic RRC EUTRA<>RRC NR interface for SgNB addition --- .../srsran/interfaces/enb_rrc_interfaces.h | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/include/srsran/interfaces/enb_rrc_interfaces.h b/lib/include/srsran/interfaces/enb_rrc_interfaces.h index 092c36316..dac845bc7 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/enb_rrc_interfaces.h @@ -120,6 +120,30 @@ public: virtual void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) = 0; }; +// RRC interfaces for NSA operation + +/// X2AP inspired interface to allow EUTRA RRC to call NR RRC +class rrc_nr_interface_rrc +{ +public: + /// Request addition of NR carrier for UE (TODO: add configuration check, QCI, security, etc.) + virtual int sgnb_addition_request(uint16_t rnti) = 0; + + /// Provide information whether the requested configuration was applied successfully by the UE + virtual int sgnb_reconfiguration_complete(uint16_t rnti, asn1::dyn_octstring reconfig_response) = 0; +}; + +/// X2AP inspired interface for response from NR RRC to EUTRA RRC +class rrc_eutra_interface_rrc_nr +{ +public: + /// Signal successful addition of UE + virtual void sgnb_addition_ack(uint16_t rnti, + const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, + const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) = 0; + virtual void sgnb_addition_reject(uint16_t rnti) = 0; +}; + } // namespace srsenb #endif // SRSRAN_ENB_RRC_INTERFACES_H From 8d443d79e5ccd72833e6c678cd6f27ea4c46c291 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 29 Jun 2021 15:01:47 +0200 Subject: [PATCH 39/50] enb,rrc: add skeleton code for new RRC internal interface for SgNB addition --- srsenb/hdr/stack/rrc/rrc.h | 19 ++++- srsenb/hdr/stack/rrc/rrc_endc.h | 112 ++++++++++++++++++++++++++++ srsenb/hdr/stack/rrc/rrc_nr.h | 26 +++++-- srsenb/hdr/stack/rrc/rrc_ue.h | 7 ++ srsenb/src/stack/enb_stack_lte.cc | 2 +- srsenb/src/stack/gnb_stack_nr.cc | 2 +- srsenb/src/stack/rrc/CMakeLists.txt | 2 +- srsenb/src/stack/rrc/rrc.cc | 42 +++++++++-- srsenb/src/stack/rrc/rrc_endc.cc | 95 +++++++++++++++++++++++ srsenb/src/stack/rrc/rrc_nr.cc | 55 ++++++++++++-- srsenb/src/stack/rrc/rrc_ue.cc | 19 +++++ srsenb/test/rrc/rrc_nr_test.cc | 6 +- 12 files changed, 360 insertions(+), 27 deletions(-) create mode 100644 srsenb/hdr/stack/rrc/rrc_endc.h create mode 100644 srsenb/src/stack/rrc/rrc_endc.cc diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 56994573b..2a7861e3e 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -49,7 +49,8 @@ static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", class rrc final : public rrc_interface_pdcp, public rrc_interface_mac, public rrc_interface_rlc, - public rrc_interface_s1ap + public rrc_interface_s1ap, + public rrc_eutra_interface_rrc_nr { public: explicit rrc(srsran::task_sched_handle task_sched_); @@ -63,6 +64,15 @@ public: s1ap_interface_rrc* s1ap, gtpu_interface_rrc* gtpu); + int32_t init(const rrc_cfg_t& cfg_, + phy_interface_rrc_lte* phy, + mac_interface_rrc* mac, + rlc_interface_rrc* rlc, + pdcp_interface_rrc* pdcp, + s1ap_interface_rrc* s1ap, + gtpu_interface_rrc* gtpu, + rrc_nr_interface_rrc* rrc_nr); + void stop(); void get_metrics(rrc_metrics_t& m); void tti_clock(); @@ -115,6 +125,12 @@ public: int notify_ue_erab_updates(uint16_t rnti, srsran::const_byte_span nas_pdu) override; + // rrc_eutra_interface_rrc_nr + void sgnb_addition_ack(uint16_t rnti, + const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, + const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) override; + void sgnb_addition_reject(uint16_t rnti) override; + // rrc_interface_pdcp void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override; void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) override; @@ -155,6 +171,7 @@ private: pdcp_interface_rrc* pdcp = nullptr; gtpu_interface_rrc* gtpu = nullptr; s1ap_interface_rrc* s1ap = nullptr; + rrc_nr_interface_rrc* rrc_nr = nullptr; srslog::basic_logger& logger; // derived params diff --git a/srsenb/hdr/stack/rrc/rrc_endc.h b/srsenb/hdr/stack/rrc/rrc_endc.h new file mode 100644 index 000000000..cd8ad31d3 --- /dev/null +++ b/srsenb/hdr/stack/rrc/rrc_endc.h @@ -0,0 +1,112 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSENB_RRC_ENDC_H +#define SRSENB_RRC_ENDC_H + +#include "rrc.h" +#include "rrc_ue.h" +#include "srsran/adt/fsm.h" +#include + +namespace srsenb { + +/** + * @brief This procedure handles the secondary node (SgNB) addition for + * EUTRA-NR Dual connectivity (ENDC) + * + */ + +class rrc::ue::rrc_endc : public srsran::fsm_t +{ +public: + // public events + struct user_crnti_upd_ev { + uint16_t crnti; + uint16_t temp_crnti; + }; + struct ho_cancel_ev { + asn1::s1ap::cause_c cause; + + ho_cancel_ev(const asn1::s1ap::cause_c& cause_) : cause(cause_) {} + }; + + rrc_endc(srsenb::rrc::ue* outer_ue); + + bool fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg); + void handle_ue_meas_report(const asn1::rrc::meas_report_s& msg, srsran::unique_byte_buffer_t pdu); + + void handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, + const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15); + void handle_sgnb_addition_reject(); + +private: + // Send SgNB addition request to gNB + bool start_sgnb_addition(); + + bool is_endc_activation_running() const { return not is_in_state(); } + + rrc::ue* rrc_ue = nullptr; + rrc* rrc_enb = nullptr; + srslog::basic_logger& logger; + + // vars + asn1::rrc::rrc_conn_recfg_complete_s pending_recfg_complete; + + // events + struct sgnb_add_req_sent_ev {}; + struct sgnb_add_req_ack_ev {}; + struct sgnb_add_req_reject_ev {}; + struct prach_nr_received_ev {}; + + using recfg_complete_ev = asn1::rrc::rrc_conn_recfg_complete_s; + using status_transfer_ev = asn1::s1ap::bearers_subject_to_status_transfer_list_l; + + // states + struct idle_st {}; + struct wait_sgnb_add_req_resp {}; + struct wait_recfg_comp {}; + struct wait_prach_nr {}; + + // FSM guards + + // FSM transition handlers + void handle_recfg_complete(wait_recfg_comp& s, const recfg_complete_ev& ev); + void handle_sgnb_addition_request_sent(const sgnb_add_req_sent_ev& ev); + +protected: + // states + state_list states{this, + idle_st{}, + wait_sgnb_add_req_resp{}, + wait_recfg_comp{}, + wait_prach_nr{}}; + + // transitions + using fsm = rrc_endc; + // clang-format off + using transitions = transition_table< + // Start Target Event Action Guard + // +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+ + row< idle_st, wait_sgnb_add_req_resp, sgnb_add_req_sent_ev, nullptr >, + // +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+ + row< wait_sgnb_add_req_resp, wait_recfg_comp, sgnb_add_req_ack_ev >, + row< wait_sgnb_add_req_resp, idle_st, sgnb_add_req_reject_ev >, + row< wait_recfg_comp, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete > + // +----------------+-------------------+---------------------+----------------------------+-------------------------+ + >; + // clang-format on +}; + +} // namespace srsenb + +#endif // SRSENB_RRC_ENDC_H diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index ead9c9102..b6dc82b70 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -23,6 +23,7 @@ #include "srsran/common/task_scheduler.h" #include "srsran/common/threads.h" #include "srsran/common/timeout.h" +#include "srsran/interfaces/enb_rrc_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" @@ -60,18 +61,20 @@ struct rrc_nr_cfg_t { class rrc_nr final : public rrc_interface_pdcp_nr, public rrc_interface_mac_nr, public rrc_interface_rlc_nr, - public rrc_interface_ngap_nr + public rrc_interface_ngap_nr, + public rrc_nr_interface_rrc { public: explicit rrc_nr(srsran::task_sched_handle task_sched_); - int32_t init(const rrc_nr_cfg_t& cfg, - phy_interface_stack_nr* phy, - mac_interface_rrc_nr* mac, - rlc_interface_rrc_nr* rlc, - pdcp_interface_rrc_nr* pdcp, - ngap_interface_rrc_nr* ngap_, - gtpu_interface_rrc_nr* gtpu); + int32_t init(const rrc_nr_cfg_t& cfg, + phy_interface_stack_nr* phy, + mac_interface_rrc_nr* mac, + rlc_interface_rrc_nr* rlc, + pdcp_interface_rrc_nr* pdcp, + ngap_interface_rrc_nr* ngap_, + gtpu_interface_rrc_nr* gtpu, + rrc_eutra_interface_rrc_nr* rrc_eutra_); void stop(); @@ -95,6 +98,10 @@ public: void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) final; void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) final; + // Interface for EUTRA RRC + int sgnb_addition_request(uint16_t rnti); + int sgnb_reconfiguration_complete(uint16_t rnti, asn1::dyn_octstring reconfig_response); + class ue { public: @@ -103,6 +110,8 @@ public: void send_connection_setup(); void send_dl_ccch(asn1::rrc_nr::dl_ccch_msg_s* dl_dcch_msg); + int handle_sgnb_addition_request(); + // getters bool is_connected() { return state == rrc_nr_state_t::RRC_CONNECTED; } bool is_idle() { return state == rrc_nr_state_t::RRC_IDLE; } @@ -130,6 +139,7 @@ private: pdcp_interface_rrc_nr* pdcp = nullptr; gtpu_interface_rrc_nr* gtpu = nullptr; ngap_interface_rrc_nr* ngap = nullptr; + rrc_eutra_interface_rrc_nr* rrc_eutra = nullptr; // args srsran::task_sched_handle task_sched; diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index 38eeffd62..91b8a6fcf 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -25,6 +25,7 @@ class rrc::ue { public: class rrc_mobility; + class rrc_endc; enum activity_timeout_type_t { MSG3_RX_TIMEOUT = 0, ///< Msg3 has its own timeout to quickly remove fake UEs from random PRACHs UE_INACTIVITY_TIMEOUT, ///< UE inactivity timeout (usually bigger than reestablishment timeout) @@ -108,6 +109,11 @@ public: bool handle_ue_ctxt_mod_req(const asn1::s1ap::ue_context_mod_request_s& msg); void handle_ue_info_resp(const asn1::rrc::ue_info_resp_r9_s& msg, srsran::unique_byte_buffer_t pdu); + // SgNB handler + void handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, + const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15); + void handle_sgnb_addition_reject(); + void set_bitrates(const asn1::s1ap::ue_aggregate_maximum_bitrate_s& rates); /// Helper to check UE ERABs @@ -154,6 +160,7 @@ public: bool connect_notified = false; unique_rnti_ptr mobility_handler; + unique_rnti_ptr endc_handler; bool is_csfb = false; diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index af7b4ea8f..627239fa1 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -138,7 +138,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) } rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); pdcp.init(&rlc, &rrc, >pu); - if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu) != SRSRAN_SUCCESS) { + if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, &rrc_nr) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize RRC"); return SRSRAN_ERROR; } diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index f103c2d89..d355f9fad 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -79,7 +79,7 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr pdcp_args.log_hex_limit = args.log.pdcp_hex_limit; m_pdcp->init(pdcp_args, m_rlc.get(), m_rrc.get(), m_sdap.get()); - m_rrc->init(rrc_cfg_, phy, m_mac.get(), m_rlc.get(), m_pdcp.get(), nullptr, nullptr); + m_rrc->init(rrc_cfg_, phy, m_mac.get(), m_rlc.get(), m_pdcp.get(), nullptr, nullptr, nullptr); m_sdap->init(m_pdcp.get(), nullptr, m_gw.get()); diff --git a/srsenb/src/stack/rrc/CMakeLists.txt b/srsenb/src/stack/rrc/CMakeLists.txt index b6e415f0d..98bc31e70 100644 --- a/srsenb/src/stack/rrc/CMakeLists.txt +++ b/srsenb/src/stack/rrc/CMakeLists.txt @@ -6,7 +6,7 @@ # the distribution. # -set(SOURCES rrc.cc rrc_ue.cc rrc_mobility.cc rrc_cell_cfg.cc rrc_bearer_cfg.cc mac_controller.cc ue_rr_cfg.cc ue_meas_cfg.cc) +set(SOURCES rrc.cc rrc_ue.cc rrc_mobility.cc rrc_cell_cfg.cc rrc_bearer_cfg.cc mac_controller.cc ue_rr_cfg.cc ue_meas_cfg.cc rrc_endc.cc) add_library(srsenb_rrc STATIC ${SOURCES}) set(SOURCES rrc_nr.cc) diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 9eb276698..cd157ae3f 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -12,6 +12,7 @@ #include "srsenb/hdr/stack/rrc/rrc.h" #include "srsenb/hdr/stack/rrc/rrc_cell_cfg.h" +#include "srsenb/hdr/stack/rrc/rrc_endc.h" #include "srsenb/hdr/stack/rrc/rrc_mobility.h" #include "srsenb/hdr/stack/rrc/rrc_paging.h" #include "srsenb/hdr/stack/s1ap/s1ap.h" @@ -45,12 +46,25 @@ int32_t rrc::init(const rrc_cfg_t& cfg_, s1ap_interface_rrc* s1ap_, gtpu_interface_rrc* gtpu_) { - phy = phy_; - mac = mac_; - rlc = rlc_; - pdcp = pdcp_; - gtpu = gtpu_; - s1ap = s1ap_; + return init(cfg_, phy_, mac_, rlc_, pdcp_, s1ap_, gtpu_, nullptr); +} + +int32_t rrc::init(const rrc_cfg_t& cfg_, + phy_interface_rrc_lte* phy_, + mac_interface_rrc* mac_, + rlc_interface_rrc* rlc_, + pdcp_interface_rrc* pdcp_, + s1ap_interface_rrc* s1ap_, + gtpu_interface_rrc* gtpu_, + rrc_nr_interface_rrc* rrc_nr_) +{ + phy = phy_; + mac = mac_; + rlc = rlc_; + pdcp = pdcp_; + gtpu = gtpu_; + s1ap = s1ap_; + rrc_nr = rrc_nr_; cfg = cfg_; @@ -528,6 +542,22 @@ void rrc::set_erab_status(uint16_t rnti, const asn1::s1ap::bearers_subject_to_st ue_it->second->mobility_handler->trigger(erabs); } +/******************************************************************************* + EN-DC/NSA helper functions +*******************************************************************************/ + +void rrc::sgnb_addition_ack(uint16_t rnti, + const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, + const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) +{ + users.at(rnti)->endc_handler->handle_sgnb_addition_ack(nr_secondary_cell_group_cfg_r15, nr_radio_bearer_cfg1_r15); +} + +void rrc::sgnb_addition_reject(uint16_t rnti) +{ + users.at(rnti)->endc_handler->handle_sgnb_addition_reject(); +} + /******************************************************************************* Private functions All private functions are not mutexed and must be called from a mutexed environment diff --git a/srsenb/src/stack/rrc/rrc_endc.cc b/srsenb/src/stack/rrc/rrc_endc.cc new file mode 100644 index 000000000..581e13990 --- /dev/null +++ b/srsenb/src/stack/rrc/rrc_endc.cc @@ -0,0 +1,95 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsenb/hdr/stack/rrc/rrc_endc.h" + +namespace srsenb { + +#define Info(fmt, ...) logger.info("ENDC: " fmt, ##__VA_ARGS__) +#define Error(fmt, ...) logger.error("ENDC: " fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) logger.warning("ENDC: " fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) logger.debug("ENDC: " fmt, ##__VA_ARGS__) + +#define procInfo(fmt, ...) parent->logger.info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define procWarning(fmt, ...) parent->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define procError(fmt, ...) parent->logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) + +using namespace asn1::rrc; + +/************************************************************************************************* + * rrc_endc class + ************************************************************************************************/ + +rrc::ue::rrc_endc::rrc_endc(rrc::ue* outer_ue) : + base_t(outer_ue->parent->logger), rrc_ue(outer_ue), rrc_enb(outer_ue->parent), logger(outer_ue->parent->logger) +{} + +//! Method to add NR fields to a RRC Connection Reconfiguration Message +bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg) +{ + if (not is_endc_activation_running()) { + // TODO: add measConfig related field to enable measurements on NR carrier + return false; + } else { + // only add reconfigure EN-DC extension/release 15.10 field if ENDC activation is active + conn_recfg->non_crit_ext_present = true; + conn_recfg->non_crit_ext.non_crit_ext_present = true; + conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext_present = true; + conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = true; + conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = true; + conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = true; + conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = + true; + conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext_present = true; + rrc_conn_recfg_v1510_ies_s& reconf_v1510 = conn_recfg->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext; + reconf_v1510.nr_cfg_r15_present = true; + reconf_v1510.sk_counter_r15_present = true; + reconf_v1510.sk_counter_r15 = 0; + return true; + } +} + +//! Method called whenever the eNB receives a MeasReport from the UE +void rrc::ue::rrc_endc::handle_ue_meas_report(const meas_report_s& msg, srsran::unique_byte_buffer_t pdu) +{ + // Start EN-DC activation + logger.info("Triggering SgNB addition"); + rrc_enb->rrc_nr->sgnb_addition_request(rrc_ue->rnti); +} + +void rrc::ue::rrc_endc::handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, + const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) +{ + logger.info("Received SgNB addition acknowledgement for rnti=%d", rrc_ue->rnti); + + // prepare reconfiguration message with NR fields + srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (pdu == nullptr) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return; + } + // rrc_enb->send_connection_reconf(std::move(pdu)); +} + +void rrc::ue::rrc_endc::handle_sgnb_addition_reject() +{ + logger.error("Received SgNB addition reject for rnti=%d", rrc_ue->rnti); +} + +void rrc::ue::rrc_endc::handle_recfg_complete(wait_recfg_comp& s, const recfg_complete_ev& ev) +{ + logger.info("User rnti=0x%x successfully enabled EN-DC", rrc_ue->rnti); +} + +} // namespace srsenb diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index 1d74129d1..7c59e14ce 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -23,13 +23,14 @@ rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) : logger(srslog::fetch_basic_logger("RRC-NR")), task_sched(task_sched_) {} -int rrc_nr::init(const rrc_nr_cfg_t& cfg_, - phy_interface_stack_nr* phy_, - mac_interface_rrc_nr* mac_, - rlc_interface_rrc_nr* rlc_, - pdcp_interface_rrc_nr* pdcp_, - ngap_interface_rrc_nr* ngap_, - gtpu_interface_rrc_nr* gtpu_) +int rrc_nr::init(const rrc_nr_cfg_t& cfg_, + phy_interface_stack_nr* phy_, + mac_interface_rrc_nr* mac_, + rlc_interface_rrc_nr* rlc_, + pdcp_interface_rrc_nr* pdcp_, + ngap_interface_rrc_nr* ngap_, + gtpu_interface_rrc_nr* gtpu_, + rrc_eutra_interface_rrc_nr* rrc_eutra_) { phy = phy_; mac = mac_; @@ -350,6 +351,23 @@ void rrc_nr::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_ void rrc_nr::notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) {} +/******************************************************************************* + Interface for EUTRA RRC +*******************************************************************************/ + +int rrc_nr::sgnb_addition_request(uint16_t rnti) +{ + // try to allocate new user + task_sched.defer_task([]() {}); + + // return straight away + return SRSRAN_SUCCESS; +} +int rrc_nr::sgnb_reconfiguration_complete(uint16_t rnti, asn1::dyn_octstring reconfig_response) +{ + return SRSRAN_SUCCESS; +} + /******************************************************************************* UE class @@ -409,4 +427,27 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) parent->rlc->write_sdu(rnti, (uint32_t)srsran::nr_srb::srb0, std::move(pdu)); } +int rrc_nr::ue::handle_sgnb_addition_request() +{ + // provide hard-coded NR configs + asn1::dyn_octstring nr_config; + + rrc_recfg_s reconfig; + reconfig.rrc_transaction_id = ((transaction_id++) % 4u); + rrc_recfg_ies_s& recfg_ies = reconfig.crit_exts.set_rrc_recfg(); + + recfg_ies.radio_bearer_cfg_present = true; + recfg_ies.radio_bearer_cfg.drb_to_add_mod_list_present = true; + recfg_ies.radio_bearer_cfg.drb_to_release_list.resize(1); + // recfg_ies.radio_bearer_cfg.drb_to_release_list[0].set_eps_bearer_id(5); + + // TODO: fill configs + asn1::dyn_octstring nr_secondary_cell_group_cfg; + asn1::dyn_octstring nr_radio_bearer_config; + + parent->rrc_eutra->sgnb_addition_ack(rnti, nr_secondary_cell_group_cfg, nr_radio_bearer_config); + + return SRSRAN_SUCCESS; +} + } // namespace srsenb diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 81f6871f9..c0686e5da 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -13,6 +13,7 @@ #include "srsenb/hdr/stack/rrc/rrc_ue.h" #include "srsenb/hdr/common/common_enb.h" #include "srsenb/hdr/stack/rrc/mac_controller.h" +#include "srsenb/hdr/stack/rrc/rrc_endc.h" #include "srsenb/hdr/stack/rrc/rrc_mobility.h" #include "srsenb/hdr/stack/rrc/ue_rr_cfg.h" #include "srsran/asn1/rrc_utils.h" @@ -78,6 +79,8 @@ int rrc::ue::init() } mobility_handler = make_rnti_obj(rnti, this); + endc_handler = make_rnti_obj(rnti, this); + return SRSRAN_SUCCESS; } @@ -785,6 +788,10 @@ void rrc::ue::send_connection_reconf(srsran::unique_byte_buffer_t pdu, } } + if (endc_handler != nullptr) { + endc_handler->fill_conn_recfg(&recfg_r8); + } + // Reuse same PDU if (pdu != nullptr) { pdu->clear(); @@ -1141,6 +1148,18 @@ void rrc::ue::update_scells() parent->logger.info("SCells activated for rnti=0x%x", rnti); } +/// EN-DC helper +void rrc::ue::handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, + const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15) +{ + endc_handler->handle_sgnb_addition_ack(nr_secondary_cell_group_cfg_r15, nr_radio_bearer_cfg1_r15); +} + +void rrc::ue::handle_sgnb_addition_reject() +{ + endc_handler->handle_sgnb_addition_reject(); +} + /********************** HELPERS ***************************/ void rrc::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg, std::string* octet_str) diff --git a/srsenb/test/rrc/rrc_nr_test.cc b/srsenb/test/rrc/rrc_nr_test.cc index bd1c79e84..eb7f68965 100644 --- a/srsenb/test/rrc/rrc_nr_test.cc +++ b/srsenb/test/rrc/rrc_nr_test.cc @@ -47,7 +47,8 @@ int test_sib_generation() rrc_nr_cfg_t rrc_cfg = rrc_obj.update_default_cfg(default_cfg); auto& sched_elem = rrc_cfg.sib1.si_sched_info.sched_info_list[0]; - TESTASSERT(rrc_obj.init(rrc_cfg, nullptr, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr) == SRSRAN_SUCCESS); + TESTASSERT(rrc_obj.init(rrc_cfg, nullptr, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) == + SRSRAN_SUCCESS); TESTASSERT(test_cell_cfg(mac_obj.cellcfgobj) == SRSRAN_SUCCESS); // TEMP tests @@ -73,7 +74,8 @@ int test_rrc_setup() // set cfg rrc_nr_cfg_t default_cfg = {}; rrc_nr_cfg_t rrc_cfg = rrc_obj.update_default_cfg(default_cfg); - TESTASSERT(rrc_obj.init(rrc_cfg, nullptr, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr) == SRSRAN_SUCCESS); + TESTASSERT(rrc_obj.init(rrc_cfg, nullptr, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) == + SRSRAN_SUCCESS); for (uint32_t n = 0; n < 2; ++n) { uint32_t timeout = 5500; From a2dd83a7e9fc5e6f1759fa3801d273949a3b9602 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 12:16:46 +0200 Subject: [PATCH 40/50] asn1: rename RRC NR test to avoid confusion with component test --- lib/test/asn1/CMakeLists.txt | 6 +++--- .../asn1/{rrc_nr_test.cc => srsran_asn1_rrc_nr_test.cc} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename lib/test/asn1/{rrc_nr_test.cc => srsran_asn1_rrc_nr_test.cc} (100%) diff --git a/lib/test/asn1/CMakeLists.txt b/lib/test/asn1/CMakeLists.txt index cd8565060..5ee4ff156 100644 --- a/lib/test/asn1/CMakeLists.txt +++ b/lib/test/asn1/CMakeLists.txt @@ -42,9 +42,9 @@ add_executable(rrc_asn1_test rrc_test.cc) target_link_libraries(rrc_asn1_test rrc_asn1 asn1_utils srsran_common) add_test(rrc_asn1_test rrc_asn1_test) -add_executable(rrc_nr_asn1_test rrc_nr_test.cc) -target_link_libraries(rrc_nr_asn1_test rrc_nr_asn1 asn1_utils srsran_common) -add_test(rrc_nr_asn1_test rrc_nr_asn1_test) +add_executable(srsran_asn1_rrc_nr_test srsran_asn1_rrc_nr_test.cc) +target_link_libraries(srsran_asn1_rrc_nr_test rrc_nr_asn1 asn1_utils srsran_common) +add_test(srsran_asn1_rrc_nr_test srsran_asn1_rrc_nr_test) add_executable(ngap_asn1_test ngap_test.cc) target_link_libraries(ngap_asn1_test ngap_nr_asn1 srsran_common) diff --git a/lib/test/asn1/rrc_nr_test.cc b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc similarity index 100% rename from lib/test/asn1/rrc_nr_test.cc rename to lib/test/asn1/srsran_asn1_rrc_nr_test.cc From e330f50ef83784920152f0a3253569e29486b287 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 12:18:14 +0200 Subject: [PATCH 41/50] rrc_meas_test: add packing test for measObjectNR --- lib/test/asn1/srsran_asn1_rrc_meas_test.cc | 143 +++++++++++++++++++-- 1 file changed, 135 insertions(+), 8 deletions(-) diff --git a/lib/test/asn1/srsran_asn1_rrc_meas_test.cc b/lib/test/asn1/srsran_asn1_rrc_meas_test.cc index 898d714fc..faab3b8dc 100644 --- a/lib/test/asn1/srsran_asn1_rrc_meas_test.cc +++ b/lib/test/asn1/srsran_asn1_rrc_meas_test.cc @@ -10,19 +10,15 @@ * */ +#include "srsran/asn1/rrc/dl_dcch_msg.h" #include "srsran/asn1/rrc/ul_dcch_msg.h" #include "srsran/asn1/rrc_utils.h" #include "srsran/common/bcd_helpers.h" +#include "srsran/common/test_common.h" #include "srsran/interfaces/rrc_interface_types.h" #include -#define TESTASSERT(cond) \ - { \ - if (!(cond)) { \ - std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \ - return -1; \ - } \ - } +#define JSON_OUTPUT 0 using namespace asn1; using namespace asn1::rrc; @@ -83,6 +79,136 @@ int meas_obj_test() return 0; } +int test_meas_config() +{ + // RRC reconfig with NR meas config + uint8_t tv[] = {0x20, 0x10, 0x15, 0xc0, 0x40, 0x00, 0x00, 0x96, 0x32, 0x18, 0x10, 0xa8, 0x04, 0xd6, 0xa0, + 0x10, 0x02, 0x01, 0x02, 0x18, 0x9a, 0x00, 0x03, 0x41, 0x81, 0x0e, 0x00, 0x01, 0x38, 0x00, + 0xc0, 0x40, 0x61, 0xc0, 0x00, 0x83, 0x00, 0x31, 0x02, 0x90, 0x60, 0x88, 0x00}; + + asn1::SRSASN_CODE err; + + cbit_ref bref(tv, sizeof(tv)); + + dl_dcch_msg_s recfg_msg_unpacked; + + TESTASSERT(recfg_msg_unpacked.unpack(bref) == SRSASN_SUCCESS); + + TESTASSERT(test_pack_unpack_consistency(recfg_msg_unpacked) == SRSASN_SUCCESS); + +#if JSON_OUTPUT + int unpacked_len = bref.distance_bytes(); + asn1::json_writer json_writer1; + recfg_msg_unpacked.to_json(json_writer1); + srslog::fetch_basic_logger("ASN1").info( + tv, sizeof(tv), "RRC config unpacked (%d B): \n %s", unpacked_len, json_writer1.to_string().c_str()); +#endif + + dl_dcch_msg_s recfg_msg_packed; + + recfg_msg_packed.msg.set_c1(); + recfg_msg_packed.msg.c1().set_rrc_conn_recfg(); // = dl_dcch_msg_type_c::c1_c_::types::rrc_conn_recfg; + recfg_msg_packed.msg.c1().rrc_conn_recfg().crit_exts.set_c1(); + recfg_msg_packed.msg.c1().rrc_conn_recfg().crit_exts.c1().set_rrc_conn_recfg_r8(); + recfg_msg_packed.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8().meas_cfg_present = true; + + meas_cfg_s& meas_cfg = recfg_msg_packed.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8().meas_cfg; + + meas_cfg.meas_obj_to_add_mod_list_present = true; + meas_cfg.meas_obj_to_add_mod_list.resize(2); + + auto& meas_obj = meas_cfg.meas_obj_to_add_mod_list[0]; + meas_obj.meas_obj_id = 1; + meas_obj.meas_obj.set_meas_obj_eutra(); + meas_obj.meas_obj.meas_obj_eutra().carrier_freq = 300; + meas_obj.meas_obj.meas_obj_eutra().allowed_meas_bw = allowed_meas_bw_opts::mbw50; + meas_obj.meas_obj.meas_obj_eutra().presence_ant_port1 = false; + meas_obj.meas_obj.meas_obj_eutra().neigh_cell_cfg.from_number(0b01); + + auto& meas_obj2 = meas_cfg.meas_obj_to_add_mod_list[1]; + meas_obj2.meas_obj_id = 2; + meas_obj2.meas_obj.set_meas_obj_nr_r15(); + meas_obj2.meas_obj.meas_obj_nr_r15().carrier_freq_r15 = 634176; + meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.periodicity_and_offset_r15.set_sf20_r15(); + meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.ssb_dur_r15 = + asn1::rrc::mtc_ssb_nr_r15_s::ssb_dur_r15_opts::sf1; + meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.subcarrier_spacing_ssb_r15 = + asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_opts::khz30; + meas_obj2.meas_obj.meas_obj_nr_r15().ext = true; + meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.set_present(true); + meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.get()->set_setup() = 78; + + // report config + meas_cfg.report_cfg_to_add_mod_list_present = true; + meas_cfg.report_cfg_to_add_mod_list.resize(1); + auto& report_cfg = meas_cfg.report_cfg_to_add_mod_list[0]; + + report_cfg.report_cfg_id = 1; + report_cfg.report_cfg.set_report_cfg_inter_rat(); + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.set_event(); + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().event_id.set_event_b1_nr_r15(); + report_cfg.report_cfg.report_cfg_inter_rat() + .trigger_type.event() + .event_id.event_b1_nr_r15() + .b1_thres_nr_r15.set_nr_rsrp_r15(); + report_cfg.report_cfg.report_cfg_inter_rat() + .trigger_type.event() + .event_id.event_b1_nr_r15() + .b1_thres_nr_r15.nr_rsrp_r15() = 56; + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().event_id.event_b1_nr_r15().report_on_leave_r15 = + false; + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().hysteresis = 0; + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().time_to_trigger = time_to_trigger_opts::ms100; + + report_cfg.report_cfg.report_cfg_inter_rat().max_report_cells = 8; + report_cfg.report_cfg.report_cfg_inter_rat().report_interv = report_interv_opts::ms120; + report_cfg.report_cfg.report_cfg_inter_rat().report_amount = report_cfg_inter_rat_s::report_amount_opts::r1; + report_cfg.report_cfg.report_cfg_inter_rat().ext = true; + report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.set_present(true); + report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrp = true; + report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrq = true; + report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_sinr = true; + + // measIdToAddModList + meas_cfg.meas_id_to_add_mod_list_present = true; + meas_cfg.meas_id_to_add_mod_list.resize(1); + auto& meas_id = meas_cfg.meas_id_to_add_mod_list[0]; + meas_id.meas_id = 1; + meas_id.meas_obj_id = 2; + meas_id.report_cfg_id = 1; + + // quantityConfig + meas_cfg.quant_cfg_present = true; + meas_cfg.quant_cfg.quant_cfg_eutra_present = true; + meas_cfg.quant_cfg.ext = true; + meas_cfg.quant_cfg.quant_cfg_nr_list_r15.set_present(true); + meas_cfg.quant_cfg.quant_cfg_nr_list_r15.get()->resize(1); + auto& meas_quant = meas_cfg.quant_cfg.quant_cfg_nr_list_r15.get()[0]; + meas_quant[0].meas_quant_cell_nr_r15.filt_coeff_rsrp_r15_present = true; + meas_quant[0].meas_quant_cell_nr_r15.filt_coeff_rsrp_r15 = filt_coef_opts::fc3; + + // measGapConfig + meas_cfg.meas_gap_cfg_present = true; + meas_cfg.meas_gap_cfg.set_setup(); + meas_cfg.meas_gap_cfg.setup().gap_offset.set_gp0() = 16; + + uint8_t pack_buffer[1024]; + bit_ref bref2(pack_buffer, sizeof(pack_buffer)); + recfg_msg_packed.pack(bref2); + int packed_len = bref2.distance_bytes(); + TESTASSERT(sizeof(tv) == packed_len); + TESTASSERT(memcmp(pack_buffer, tv, packed_len) == 0); + +#if JSON_OUTPUT + asn1::json_writer json_writer2; + recfg_msg_packed.to_json(json_writer2); + srslog::fetch_basic_logger("ASN1").info( + pack_buffer, packed_len, "RRC config packed (%d B): \n %s", packed_len, json_writer2.to_string().c_str()); +#endif + + return SRSRAN_SUCCESS; +} + int main(int argc, char** argv) { auto& asn1_logger = srslog::fetch_basic_logger("ASN1", false); @@ -91,7 +217,8 @@ int main(int argc, char** argv) srslog::init(); - TESTASSERT(meas_obj_test() == 0); + TESTASSERT(meas_obj_test() == SRSRAN_SUCCESS); + TESTASSERT(test_meas_config() == SRSRAN_SUCCESS); return 0; } From f2f9082d09182c2316798e6970d18637d4645daf Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 13:37:29 +0200 Subject: [PATCH 42/50] ue,rrc_meas: fix invalid access to field when eport_quant_cell_nr_r15 is not present --- srsue/src/stack/rrc/rrc_meas.cc | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/srsue/src/stack/rrc/rrc_meas.cc b/srsue/src/stack/rrc/rrc_meas.cc index bfc6d8d6f..3e0804ff7 100644 --- a/srsue/src/stack/rrc/rrc_meas.cc +++ b/srsue/src/stack/rrc/rrc_meas.cc @@ -370,21 +370,28 @@ void rrc::rrc_meas::var_meas_report_list::generate_report_interrat(meas_results_ rc.pci_r15 = (uint16_t)cell.pci; // Set quantity to report - if (var_meas.report_cfg_inter.report_quant_cell_nr_r15->ss_rsrp == true) { + if (var_meas.report_cfg_inter.report_quant_cell_nr_r15.is_present()) { + if (var_meas.report_cfg_inter.report_quant_cell_nr_r15->ss_rsrp == true) { + rc.meas_result_cell_r15.rsrp_result_r15_present = true; + rc.meas_result_cell_r15.rsrp_result_r15 = + value_to_range_nr(asn1::rrc::thres_nr_r15_c::types_opts::options::nr_rsrp_r15, rsrp_value); + } + if (var_meas.report_cfg_inter.report_quant_cell_nr_r15->ss_rsrq == true) { + rc.meas_result_cell_r15.rsrq_result_r15_present = true; + rc.meas_result_cell_r15.rsrq_result_r15 = + value_to_range_nr(asn1::rrc::thres_nr_r15_c::types_opts::options::nr_rsrq_r15, rsrq_value); + } + if (var_meas.report_cfg_inter.report_quant_cell_nr_r15->ss_sinr == true) { + rc.meas_result_cell_r15.rs_sinr_result_r15_present = true; + rc.meas_result_cell_r15.rs_sinr_result_r15 = + value_to_range_nr(asn1::rrc::thres_nr_r15_c::types_opts::options::nr_sinr_r15, 1.0); + } + } else { + logger.warning("Report quantity for NR cells not present in measurement config. Sending RSRP anyway."); rc.meas_result_cell_r15.rsrp_result_r15_present = true; rc.meas_result_cell_r15.rsrp_result_r15 = value_to_range_nr(asn1::rrc::thres_nr_r15_c::types_opts::options::nr_rsrp_r15, rsrp_value); } - if (var_meas.report_cfg_inter.report_quant_cell_nr_r15->ss_rsrq == true) { - rc.meas_result_cell_r15.rsrq_result_r15_present = true; - rc.meas_result_cell_r15.rsrq_result_r15 = - value_to_range_nr(asn1::rrc::thres_nr_r15_c::types_opts::options::nr_rsrq_r15, rsrq_value); - } - if (var_meas.report_cfg_inter.report_quant_cell_nr_r15->ss_sinr == true) { - rc.meas_result_cell_r15.rs_sinr_result_r15_present = true; - rc.meas_result_cell_r15.rs_sinr_result_r15 = - value_to_range_nr(asn1::rrc::thres_nr_r15_c::types_opts::options::nr_sinr_r15, 1.0); - } logger.info("MEAS: Adding to report neighbour=%d, pci=%d, earfcn=%d, rsrp=%+.1f, rsrq=%+.1f", neigh_list.size(), From 3f81d3e969ef3c246f6c634cdaaf6d480ce04e03 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 17:25:40 +0200 Subject: [PATCH 43/50] enb,rrc_endc: add handler for measurements and UE capabilities --- srsenb/hdr/stack/rrc/rrc_endc.h | 7 +- srsenb/src/stack/rrc/rrc_endc.cc | 165 ++++++++++++++++++++++++++++++- srsenb/src/stack/rrc/rrc_ue.cc | 3 + 3 files changed, 168 insertions(+), 7 deletions(-) diff --git a/srsenb/hdr/stack/rrc/rrc_endc.h b/srsenb/hdr/stack/rrc/rrc_endc.h index cd8ad31d3..80032f470 100644 --- a/srsenb/hdr/stack/rrc/rrc_endc.h +++ b/srsenb/hdr/stack/rrc/rrc_endc.h @@ -43,8 +43,8 @@ public: rrc_endc(srsenb::rrc::ue* outer_ue); bool fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg); - void handle_ue_meas_report(const asn1::rrc::meas_report_s& msg, srsran::unique_byte_buffer_t pdu); - + void handle_ue_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps); + void handle_ue_meas_report(const asn1::rrc::meas_report_s& msg); void handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, const asn1::dyn_octstring& nr_radio_bearer_cfg1_r15); void handle_sgnb_addition_reject(); @@ -60,6 +60,7 @@ private: srslog::basic_logger& logger; // vars + bool endc_supported = false; asn1::rrc::rrc_conn_recfg_complete_s pending_recfg_complete; // events @@ -102,7 +103,7 @@ protected: row< wait_sgnb_add_req_resp, wait_recfg_comp, sgnb_add_req_ack_ev >, row< wait_sgnb_add_req_resp, idle_st, sgnb_add_req_reject_ev >, row< wait_recfg_comp, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete > - // +----------------+-------------------+---------------------+----------------------------+-------------------------+ + // +-----------------------+-----------------------+------------------------+----------------------------+-------------------------+ >; // clang-format on }; diff --git a/srsenb/src/stack/rrc/rrc_endc.cc b/srsenb/src/stack/rrc/rrc_endc.cc index 581e13990..7c6a1fc49 100644 --- a/srsenb/src/stack/rrc/rrc_endc.cc +++ b/srsenb/src/stack/rrc/rrc_endc.cc @@ -36,9 +36,93 @@ rrc::ue::rrc_endc::rrc_endc(rrc::ue* outer_ue) : //! Method to add NR fields to a RRC Connection Reconfiguration Message bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg) { - if (not is_endc_activation_running()) { - // TODO: add measConfig related field to enable measurements on NR carrier + if (not endc_supported) { + // skipping ENDC-related field return false; + } + + if (not is_endc_activation_running()) { + // add hard-coded measConfig + conn_recfg->meas_cfg_present = true; + meas_cfg_s& meas_cfg = conn_recfg->meas_cfg; + + meas_cfg.meas_obj_to_add_mod_list_present = true; + meas_cfg.meas_obj_to_add_mod_list.resize(2); + + auto& meas_obj = meas_cfg.meas_obj_to_add_mod_list[0]; + meas_obj.meas_obj_id = 1; + meas_obj.meas_obj.set_meas_obj_eutra(); + meas_obj.meas_obj.meas_obj_eutra().carrier_freq = 300; + meas_obj.meas_obj.meas_obj_eutra().allowed_meas_bw = allowed_meas_bw_opts::mbw50; + meas_obj.meas_obj.meas_obj_eutra().presence_ant_port1 = false; + meas_obj.meas_obj.meas_obj_eutra().neigh_cell_cfg.from_number(0b01); + + auto& meas_obj2 = meas_cfg.meas_obj_to_add_mod_list[1]; + meas_obj2.meas_obj_id = 2; + meas_obj2.meas_obj.set_meas_obj_nr_r15(); + meas_obj2.meas_obj.meas_obj_nr_r15().carrier_freq_r15 = 634176; + meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.periodicity_and_offset_r15.set_sf20_r15(); + meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.ssb_dur_r15 = + asn1::rrc::mtc_ssb_nr_r15_s::ssb_dur_r15_opts::sf1; + meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.subcarrier_spacing_ssb_r15 = + asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_opts::khz30; + meas_obj2.meas_obj.meas_obj_nr_r15().ext = true; + meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.set_present(true); + meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.get()->set_setup() = 78; + + // report config + meas_cfg.report_cfg_to_add_mod_list_present = true; + meas_cfg.report_cfg_to_add_mod_list.resize(1); + auto& report_cfg = meas_cfg.report_cfg_to_add_mod_list[0]; + + report_cfg.report_cfg_id = 1; + report_cfg.report_cfg.set_report_cfg_inter_rat(); + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.set_event(); + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().event_id.set_event_b1_nr_r15(); + report_cfg.report_cfg.report_cfg_inter_rat() + .trigger_type.event() + .event_id.event_b1_nr_r15() + .b1_thres_nr_r15.set_nr_rsrp_r15(); + report_cfg.report_cfg.report_cfg_inter_rat() + .trigger_type.event() + .event_id.event_b1_nr_r15() + .b1_thres_nr_r15.nr_rsrp_r15() = 56; + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().event_id.event_b1_nr_r15().report_on_leave_r15 = + false; + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().hysteresis = 0; + report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().time_to_trigger = time_to_trigger_opts::ms100; + + report_cfg.report_cfg.report_cfg_inter_rat().max_report_cells = 1; + report_cfg.report_cfg.report_cfg_inter_rat().report_interv = report_interv_opts::ms120; + report_cfg.report_cfg.report_cfg_inter_rat().report_amount = report_cfg_inter_rat_s::report_amount_opts::r1; + report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.set_present(true); + report_cfg.report_cfg.report_cfg_inter_rat().ext = true; + report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrp = true; + report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrq = true; + report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_sinr = true; + + // measIdToAddModList + meas_cfg.meas_id_to_add_mod_list_present = true; + meas_cfg.meas_id_to_add_mod_list.resize(1); + auto& meas_id = meas_cfg.meas_id_to_add_mod_list[0]; + meas_id.meas_id = 1; + meas_id.meas_obj_id = 2; + meas_id.report_cfg_id = 1; + + // quantityConfig + meas_cfg.quant_cfg_present = true; + meas_cfg.quant_cfg.quant_cfg_eutra_present = true; + meas_cfg.quant_cfg.quant_cfg_nr_list_r15.set_present(true); + meas_cfg.quant_cfg.quant_cfg_nr_list_r15.get()->resize(1); + meas_cfg.quant_cfg.ext = true; + auto& meas_quant = meas_cfg.quant_cfg.quant_cfg_nr_list_r15.get()[0]; + meas_quant[0].meas_quant_cell_nr_r15.filt_coeff_rsrp_r15_present = true; + meas_quant[0].meas_quant_cell_nr_r15.filt_coeff_rsrp_r15 = filt_coef_opts::fc3; + + // measGapConfig + meas_cfg.meas_gap_cfg_present = true; + meas_cfg.meas_gap_cfg.set_setup(); + meas_cfg.meas_gap_cfg.setup().gap_offset.set_gp0() = 16; } else { // only add reconfigure EN-DC extension/release 15.10 field if ENDC activation is active conn_recfg->non_crit_ext_present = true; @@ -56,16 +140,89 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn reconf_v1510.nr_cfg_r15_present = true; reconf_v1510.sk_counter_r15_present = true; reconf_v1510.sk_counter_r15 = 0; - return true; + } + + return true; +} + +//! Called when UE capabilities are received +void rrc::ue::rrc_endc::handle_ue_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps) +{ + // Only enabled ENDC support if UE caps have been exchanged and UE signals support + if (eutra_caps.non_crit_ext_present) { + if (eutra_caps.non_crit_ext.non_crit_ext_present) { + if (eutra_caps.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present) { + if (eutra_caps.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present) { + auto& ue_cap_v1170 = + eutra_caps.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext; + if (ue_cap_v1170.non_crit_ext_present) { + if (ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext_present) { + if (ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present) { + if (ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext_present) { + if (ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.non_crit_ext_present) { + auto& ue_cap_v1330 = ue_cap_v1170.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext; + if (ue_cap_v1330.non_crit_ext_present) { + if (ue_cap_v1330.non_crit_ext.non_crit_ext.non_crit_ext_present) { + if (ue_cap_v1330.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present) { + if (ue_cap_v1330.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext_present) { + auto& ue_cap_v1510 = ue_cap_v1330.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext; + if (ue_cap_v1510.irat_params_nr_r15_present) { + if (ue_cap_v1510.irat_params_nr_r15.en_dc_r15_present) { + logger.info("Enabling ENDC support for rnti=%d", rrc_ue->rnti); + endc_supported = true; + } + } + } + } + } + } + } + } + } + } + } + } + } + } } } //! Method called whenever the eNB receives a MeasReport from the UE -void rrc::ue::rrc_endc::handle_ue_meas_report(const meas_report_s& msg, srsran::unique_byte_buffer_t pdu) +void rrc::ue::rrc_endc::handle_ue_meas_report(const meas_report_s& msg) { + // Ignore event if ENDC isn't supported + if (not endc_supported) { + return; + } + + if (not is_in_state()) { + Info("Received a MeasReport while already enabling ENDC support. Ignoring..."); + return; + } + // Check if meas_id is valid + const meas_results_s& meas_res = msg.crit_exts.c1().meas_report_r8().meas_results; + if (not meas_res.meas_result_neigh_cells_present) { + Info("Received a MeasReport, but the UE did not detect any cell."); + return; + } + + // only handle NR cells here, EUTRA is handled in mobility class + if (meas_res.meas_result_neigh_cells.type().value != + meas_results_s::meas_result_neigh_cells_c_::types::meas_result_neigh_cell_list_nr_r15) { + return; + } + // Start EN-DC activation logger.info("Triggering SgNB addition"); rrc_enb->rrc_nr->sgnb_addition_request(rrc_ue->rnti); + + sgnb_add_req_sent_ev sgnb_add_req{}; + trigger(sgnb_add_req); } void rrc::ue::rrc_endc::handle_sgnb_addition_ack(const asn1::dyn_octstring& nr_secondary_cell_group_cfg_r15, diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index c0686e5da..72dd7bf07 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -376,6 +376,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) } else { parent->logger.warning("Received MeasReport but no mobility configuration is available"); } + endc_handler->handle_ue_meas_report(ul_dcch_msg.msg.c1().meas_report()); break; case ul_dcch_msg_type_c::c1_c_::types::ue_info_resp_r9: handle_ue_info_resp(ul_dcch_msg.msg.c1().ue_info_resp_r9(), std::move(original_pdu)); @@ -945,6 +946,8 @@ bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) ue_capabilities = srsran::make_rrc_ue_capabilities(eutra_capabilities); parent->logger.info("UE rnti: 0x%x category: %d", rnti, eutra_capabilities.ue_category); + + endc_handler->handle_ue_capabilities(eutra_capabilities); } if (eutra_capabilities_unpacked) { From e4607391522e00d483687238d8e68d9b01500aa1 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 5 Jul 2021 17:32:16 +0200 Subject: [PATCH 44/50] rrc_ue: only create and call endc_handler if NR RRC is available --- srsenb/src/stack/rrc/rrc_ue.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 72dd7bf07..a634bf5a6 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -79,7 +79,9 @@ int rrc::ue::init() } mobility_handler = make_rnti_obj(rnti, this); - endc_handler = make_rnti_obj(rnti, this); + if (parent->rrc_nr != nullptr) { + endc_handler = make_rnti_obj(rnti, this); + } return SRSRAN_SUCCESS; } @@ -376,7 +378,9 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) } else { parent->logger.warning("Received MeasReport but no mobility configuration is available"); } - endc_handler->handle_ue_meas_report(ul_dcch_msg.msg.c1().meas_report()); + if (endc_handler) { + endc_handler->handle_ue_meas_report(ul_dcch_msg.msg.c1().meas_report()); + } break; case ul_dcch_msg_type_c::c1_c_::types::ue_info_resp_r9: handle_ue_info_resp(ul_dcch_msg.msg.c1().ue_info_resp_r9(), std::move(original_pdu)); @@ -947,7 +951,9 @@ bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) parent->logger.info("UE rnti: 0x%x category: %d", rnti, eutra_capabilities.ue_category); - endc_handler->handle_ue_capabilities(eutra_capabilities); + if (endc_handler) { + endc_handler->handle_ue_capabilities(eutra_capabilities); + } } if (eutra_capabilities_unpacked) { From 724af2b060b0481c75a161335ee1c49ff0b3426a Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 30 Jun 2021 12:59:32 +0200 Subject: [PATCH 45/50] Added nas 5g msg packing and unpacking --- lib/include/srsran/asn1/nas_5g_ies.h | 2699 +++++++++++++++ lib/include/srsran/asn1/nas_5g_msg.h | 2390 +++++++++++++ lib/include/srsran/asn1/nas_5g_utils.h | 87 + lib/src/asn1/CMakeLists.txt | 5 + lib/src/asn1/nas_5g_ies.cc | 4359 ++++++++++++++++++++++++ lib/src/asn1/nas_5g_msg.cc | 4198 +++++++++++++++++++++++ lib/src/asn1/nas_5g_utils.cc | 56 + lib/test/asn1/CMakeLists.txt | 3 + lib/test/asn1/nas_5g_msg_test.cc | 1610 +++++++++ 9 files changed, 15407 insertions(+) create mode 100644 lib/include/srsran/asn1/nas_5g_ies.h create mode 100644 lib/include/srsran/asn1/nas_5g_msg.h create mode 100644 lib/include/srsran/asn1/nas_5g_utils.h create mode 100644 lib/src/asn1/nas_5g_ies.cc create mode 100644 lib/src/asn1/nas_5g_msg.cc create mode 100644 lib/src/asn1/nas_5g_utils.cc create mode 100644 lib/test/asn1/nas_5g_msg_test.cc diff --git a/lib/include/srsran/asn1/nas_5g_ies.h b/lib/include/srsran/asn1/nas_5g_ies.h new file mode 100644 index 000000000..2c780076c --- /dev/null +++ b/lib/include/srsran/asn1/nas_5g_ies.h @@ -0,0 +1,2699 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ +#ifndef SRSRAN_NAS_5G_IES_H +#define SRSRAN_NAS_5G_IES_H +#include "nas_5g_utils.h" + +#include "srsran/asn1/asn1_utils.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/common.h" +#include "srsran/config.h" + +#include +#include +#include + +namespace srsran { +namespace nas_5g { + +// IEs + +// IE: 5GS registration type +// Reference: 9.11.3.7 +class registration_type_5gs_t +{ +public: + struct registration_type_type_ { + enum options { + initial_registration = 0b001, + mobility_registration_updating = 0b010, + periodic_registration_updating = 0b011, + emergency_registration = 0b100, + reserved = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated registration_type_type; + + struct follow_on_request_bit_type_ { + enum options { + no_follow_on_request_pending = 0b0, + follow_on_request_pending = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated follow_on_request_bit_type; + + uint32_t length; + follow_on_request_bit_type follow_on_request_bit; + registration_type_type registration_type; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // registration_type_5gs_t + +// IE: key set identifier +// Reference: 9.11.3.32 +class key_set_identifier_t +{ +public: + struct security_context_flag_type_ { + enum options { + native_security_context = 0b0, + mapped_security_context = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated security_context_flag_type; + + struct nas_key_set_identifier_type_ { + enum options { + no_key_is_available_or_reserved = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated nas_key_set_identifier_type; + + uint32_t length; + security_context_flag_type security_context_flag; + nas_key_set_identifier_type nas_key_set_identifier; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // key_set_identifier_t + +// IE: 5GS mobile identity +// Reference: 9.11.3.4 +class mobile_identity_5gs_t +{ +public: + struct identity_types_ { + enum options { + no_identity = 0b000, + suci = 0b001, + guti_5g = 0b010, + imei = 0b011, + s_tmsi_5g = 0b100, + imeisv = 0b101, + mac_address = 0b110, + eui_64 = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated identity_types; + + void set(identity_types::options e = identity_types::no_identity) { type_ = e; }; + identity_types type() const { return type_; } + + class suci_s + { + public: + struct supi_format_type_ { + enum options { + imsi = 0b000, + network_specific_identifier = 0b010, + gci = 0b011, + gli = 0b100, + + } value; + const char* to_string(); + }; + typedef nas_enumerated supi_format_type; + + struct protection_scheme_id_type_ { + enum options { + null_scheme = 0b0000, + ecies_scheme_profile_a = 0b0001, + ecies_scheme_profile_b = 0b0010, + + } value; + const char* to_string(); + }; + typedef nas_enumerated protection_scheme_id_type; + + supi_format_type supi_format = supi_format_type_::options::imsi; + std::array mcc; + std::array mnc; + std::array routing_indicator; + protection_scheme_id_type protection_scheme_id = protection_scheme_id_type_::options::null_scheme; + uint8_t home_network_public_key_identifier; + std::vector scheme_output; + + SRSASN_CODE pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp); + SRSASN_CODE unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length); + + }; // suci + class guti_5g_s + { + public: + std::array mcc; + std::array mnc; + uint8_t amf_region_id; + uint16_t amf_set_id; + uint8_t amf_pointer; + uint32_t tmsi_5g; + + SRSASN_CODE pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp); + SRSASN_CODE unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length); + + }; // guti_5g + class imei_s + { + public: + bool odd_even_indicator; + std::array imei; + + SRSASN_CODE pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp); + SRSASN_CODE unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length); + + }; // imei + class s_tmsi_5g_s + { + public: + uint16_t amf_set_id; + uint8_t amf_pointer; + uint32_t tmsi_5g; + + SRSASN_CODE pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp); + SRSASN_CODE unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length); + + }; // s_tmsi_5g + class imeisv_s + { + public: + bool odd_even_indicator; + std::array imeisv; + + SRSASN_CODE pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp); + SRSASN_CODE unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length); + + }; // imeisv + class mac_address_s + { + public: + std::array mac_address; + + SRSASN_CODE pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp); + SRSASN_CODE unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length); + + }; // mac_address + class eui_64_s + { + public: + std::array eui_64; + + SRSASN_CODE pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp); + SRSASN_CODE unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length); + + }; // eui_64 + + uint32_t length; + // Getters + + suci_s& suci() + { + asn1::assert_choice_type(identity_types::suci, type_, "suci"); + return *srslog::detail::any_cast(&choice_container); + } + + guti_5g_s& guti_5g() + { + asn1::assert_choice_type(identity_types::guti_5g, type_, "guti_5g"); + return *srslog::detail::any_cast(&choice_container); + } + + imei_s& imei() + { + asn1::assert_choice_type(identity_types::imei, type_, "imei"); + return *srslog::detail::any_cast(&choice_container); + } + + s_tmsi_5g_s& s_tmsi_5g() + { + asn1::assert_choice_type(identity_types::s_tmsi_5g, type_, "s_tmsi_5g"); + return *srslog::detail::any_cast(&choice_container); + } + + imeisv_s& imeisv() + { + asn1::assert_choice_type(identity_types::imeisv, type_, "imeisv"); + return *srslog::detail::any_cast(&choice_container); + } + + mac_address_s& mac_address() + { + asn1::assert_choice_type(identity_types::mac_address, type_, "mac_address"); + return *srslog::detail::any_cast(&choice_container); + } + + eui_64_s& eui_64() + { + asn1::assert_choice_type(identity_types::eui_64, type_, "eui_64"); + return *srslog::detail::any_cast(&choice_container); + } + + suci_s& set_suci() + { + set(identity_types::suci); + choice_container = srslog::detail::any{suci_s()}; + return *srslog::detail::any_cast(&choice_container); + } + + guti_5g_s& set_guti_5g() + { + set(identity_types::guti_5g); + choice_container = srslog::detail::any{guti_5g_s()}; + return *srslog::detail::any_cast(&choice_container); + } + + imei_s& set_imei() + { + set(identity_types::imei); + choice_container = srslog::detail::any{imei_s()}; + return *srslog::detail::any_cast(&choice_container); + } + + s_tmsi_5g_s& set_s_tmsi_5g() + { + set(identity_types::s_tmsi_5g); + choice_container = srslog::detail::any{s_tmsi_5g_s()}; + return *srslog::detail::any_cast(&choice_container); + } + + imeisv_s& set_imeisv() + { + set(identity_types::imeisv); + choice_container = srslog::detail::any{imeisv_s()}; + return *srslog::detail::any_cast(&choice_container); + } + + mac_address_s& set_mac_address() + { + set(identity_types::mac_address); + choice_container = srslog::detail::any{mac_address_s()}; + return *srslog::detail::any_cast(&choice_container); + } + + eui_64_s& set_eui_64() + { + set(identity_types::eui_64); + choice_container = srslog::detail::any{eui_64_s()}; + return *srslog::detail::any_cast(&choice_container); + } + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +private: + identity_types type_; + srslog::detail::any choice_container; + +}; // mobile_identity_5gs_t + +// IE: 5GMM capability +// Reference: 9.11.3.1 +class capability_5gmm_t +{ +public: + uint32_t length; + bool sgc; + bool iphc_cp_c_io_t_5g; + bool n3_data; + bool cp_c_io_t_5g; + bool restrict_ec; + bool lpp; + bool ho_attach; + bool s1_mode; + bool racs; + bool nssaa; + bool lcs_5g; + bool v2_xcnpc5; + bool v2_xcepc5; + bool v2_x; + bool up_c_io_t_5g; + bool srvcc_5g; + bool ehc_cp_c_io_t_5g; + bool multiple_up; + bool wusa; + bool cag; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // capability_5gmm_t + +// IE: UE security capability +// Reference: 9.11.3.54 +class ue_security_capability_t +{ +public: + uint32_t length; + bool ea0_5g_supported; + bool ea1_128_5g_supported; + bool ea2_128_5g_supported; + bool ea3_128_5g_supported; + bool ea4_5g_supported; + bool ea5_5g_supported; + bool ea6_5g_supported; + bool ea7_5g_supported; + bool ia0_5g_supported; + bool ia1_128_5g_supported; + bool ia2_128_5g_supported; + bool ia3_128_5g_supported; + bool ia4_5g_supported; + bool ia5_5g_supported; + bool ia6_5g_supported; + bool ia7_5g_supported; + bool eps_caps_present; + bool eea0_supported; + bool eea1_128_supported; + bool eea2_128_supported; + bool eea3_128_supported; + bool eea4_supported; + bool eea5_supported; + bool eea6_supported; + bool eea7_supported; + bool eia0_supported; + bool eia1_128_supported; + bool eia2_128_supported; + bool eia3_128_supported; + bool eia4_supported; + bool eia5_supported; + bool eia6_supported; + bool eia7_supported; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ue_security_capability_t + +// IE: S-NSSAI +// Reference: 9.11.2.8 +class s_nssai_t +{ +public: + struct SST_type_ { + enum options { + sst = 0b00000001, + sst_and_mapped_hplmn_sst = 0b00000010, + sst_and_sd = 0b00000100, + sst_sd_and_mapped_hplmn_sst = 0b00000101, + sst_sd_mapped_hplmn_sst_and_mapped_hplmn_sd = 0b00001000, + + } value; + const char* to_string(); + }; + typedef nas_enumerated SST_type; + + uint32_t length; + uint8_t sst; + uint32_t sd; + uint8_t mapped_hplmn_sst; + uint32_t mapped_hplmn_sd; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // s_nssai_t + +// IE: NSSAI +// Reference: 9.11.3.37 +class nssai_t +{ +public: + uint32_t length; + std::vector s_nssai_list; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // nssai_t + +// IE: 5GS tracking area identity +// Reference: 9.11.3.8 +class tracking_area_identity_5gs_t +{ +public: + uint32_t length; + std::array mcc; + std::array mnc; + uint32_t tac; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // tracking_area_identity_5gs_t + +// IE: S1 UE network capability +// Reference: 9.11.3.48 +class s1_ue_network_capability_t +{ +public: + uint32_t length; + bool eea0_supported; + bool eea1_128_supported; + bool eea2_128_supported; + bool eea3_128_supported; + bool eea4_supported; + bool eea5_supported; + bool eea6_supported; + bool eea7_supported; + bool eia0_supported; + bool eia1_128_supported; + bool eia2_128_supported; + bool eia3_128_supported; + bool eia4_supported; + bool eia5_supported; + bool eia6_supported; + bool eia7_supported; + bool uea0_supported; + bool uea1_128_supported; + bool uea2_128_supported; + bool uea3_128_supported; + bool uea4_supported; + bool uea5_supported; + bool uea6_supported; + bool uea7_supported; + bool ucs2_support; + bool uia1_128_supported; + bool uia2_128_supported; + bool uia3_128_supported; + bool uia4_supported; + bool uia5_supported; + bool uia6_supported; + bool uia7_supported; + bool pro_se_dd_supported; + bool pro_se_supported; + bool h245_ash_supported; + bool acc_csfb_supported; + bool llp_supported; + bool lcs_supported; + bool srvcc_capability_supported; + bool nf_capability_supported; + bool e_pco_supported; + bool hc_cp_c_io_t_supported; + bool e_rw_o_pdn_supported; + bool s1_u_data_supported; + bool up_c_io_t_supported; + bool cp_c_io_t_supported; + bool pro_se_relay_supported; + bool pro_se_dc_supported; + bool max_15_eps_bearer_supported; + bool sgc_supported; + bool n1mode_supported; + bool dcnr_supported; + bool cp_backoff_supported; + bool restrict_ec_supported; + bool v2_x_pc5_supported; + bool multiple_drb_supported; + bool nr_pc5_supported; + bool up_mt_edt_supported; + bool cp_mt_edt_supported; + bool wus_supported; + bool racs_supported; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // s1_ue_network_capability_t + +// IE: Uplink data status +// Reference: 9.11.3.57 +class uplink_data_status_t +{ +public: + uint32_t length; + bool psi_7; + bool psi_6; + bool psi_5; + bool psi_4; + bool psi_3; + bool psi_2; + bool psi_1; + bool psi_0; + bool psi_15; + bool psi_14; + bool psi_13; + bool psi_12; + bool psi_11; + bool psi_10; + bool psi_9; + bool psi_8; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // uplink_data_status_t + +// IE: PDU session status +// Reference: 9.11.3.44 +class pdu_session_status_t +{ +public: + uint32_t length; + bool psi_7; + bool psi_6; + bool psi_5; + bool psi_4; + bool psi_3; + bool psi_2; + bool psi_1; + bool psi_0; + bool psi_15; + bool psi_14; + bool psi_13; + bool psi_12; + bool psi_11; + bool psi_10; + bool psi_9; + bool psi_8; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_status_t + +// IE: MICO indication +// Reference: 9.11.3.31 +class mico_indication_t +{ +public: + uint32_t length; + bool sprti; + bool aai; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // mico_indication_t + +// IE: UE status +// Reference: 9.11.3.56 +class ue_status_t +{ +public: + uint32_t length; + bool n1_mode_reg; + bool s1_mode_reg; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ue_status_t + +// IE: Allowed PDU session status +// Reference: 9.11.3.13 +class allowed_pdu_session_status_t +{ +public: + uint32_t length; + bool psi_7; + bool psi_6; + bool psi_5; + bool psi_4; + bool psi_3; + bool psi_2; + bool psi_1; + bool psi_0; + bool psi_15; + bool psi_14; + bool psi_13; + bool psi_12; + bool psi_11; + bool psi_10; + bool psi_9; + bool psi_8; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // allowed_pdu_session_status_t + +// IE: UE usage setting +// Reference: 9.11.3.55 +class ue_usage_setting_t +{ +public: + struct UE_usage_setting_type_ { + enum options { + voice_centric = 0b0, + data_centric = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated UE_usage_setting_type; + + uint32_t length; + UE_usage_setting_type ue_usage_setting; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ue_usage_setting_t + +// IE: 5GS DRX parameters +// Reference: 9.11.3.2A +class drx_parameters_5gs_t +{ +public: + struct drx_value_type_ { + enum options { + drx_value_not_specified = 0b0000, + drx_cycle_parameter_t_32 = 0b0001, + drx_cycle_parameter_t_64 = 0b0010, + drx_cycle_parameter_t_128 = 0b0011, + drx_cycle_parameter_t_256 = 0b0100, + + } value; + const char* to_string(); + }; + typedef nas_enumerated drx_value_type; + + uint32_t length; + drx_value_type drx_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // drx_parameters_5gs_t + +// IE: EPS NAS message container +// Reference: 9.11.3.24 +class eps_nas_message_container_t +{ +public: + uint32_t length; + std::vector eps_nas_message_container; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // eps_nas_message_container_t + +// IE: DNN +// Reference: 9.11.2.1B +class dnn_t +{ +public: + uint32_t length; + std::vector dnn_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // dnn_t + +// IE: LADN indication +// Reference: 9.11.3.29 +class ladn_indication_t +{ +public: + uint32_t length; + std::vector ladn_dnn_values; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ladn_indication_t + +// IE: Payload container type +// Reference: 9.11.3.40 +class payload_container_type_t +{ +public: + struct Payload_container_type_type_ { + enum options { + n1_sm_information = 0b0001, + sms = 0b0010, + lte_positioning_protocol_lpp_message_container = 0b0011, + sor_transparent_container = 0b0100, + ue_policy_container = 0b0101, + ue_parameters_update_transparent_container = 0b0110, + location_services_message_container = 0b0111, + c_io_t_user_data_container = 0b1000, + multiple_payloads = 0b1111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Payload_container_type_type; + + uint32_t length; + Payload_container_type_type payload_container_type; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // payload_container_type_t + +// IE: Payload container +// Reference: 9.11.3.39 +class payload_container_t +{ +public: + uint32_t length; + std::vector payload_container_contents; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // payload_container_t + +// IE: Network slicing indication +// Reference: 9.11.3.36 +class network_slicing_indication_t +{ +public: + uint32_t length; + bool nssci; + bool dcni; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // network_slicing_indication_t + +// IE: 5GS update type +// Reference: 9.11.3.9A +class update_type_5gs_t +{ +public: + struct SMS_requested_type_ { + enum options { + sms_over_nas_not_supported = 0b0, + sms_over_nas_supported = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated SMS_requested_type; + + struct NG_RAN_RCU_type_ { + enum options { + ue_radio_capability_update_not_needed = 0b0, + ue_radio_capability_update_needed = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated NG_RAN_RCU_type; + + struct PNB_5GS_CIoT_type_ { + enum options { + no_additional_information = 0b00, + control_plane_c_io_t_5gs_optimization = 0b01, + user_plane_c_io_t_5gs_optimization = 0b10, + reserved = 0b11, + + } value; + const char* to_string(); + }; + typedef nas_enumerated PNB_5GS_CIoT_type; + + struct PNB_EPS_CIoT_type_ { + enum options { + no_additional_information = 0b00, + control_plane_c_io_t_eps_optimization = 0b01, + user_plane_c_io_t_eps_optimization = 0b10, + reserved = 0b11, + + } value; + const char* to_string(); + }; + typedef nas_enumerated PNB_EPS_CIoT_type; + + uint32_t length; + PNB_EPS_CIoT_type pnb_eps_c_io_t; + PNB_5GS_CIoT_type pnb_5gs_c_io_t; + NG_RAN_RCU_type ng_ran_rcu; + SMS_requested_type sms_requested; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // update_type_5gs_t + +// IE: Mobile station classmark 2 +// Reference: 9.11.3.31C +class mobile_station_classmark_2_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // mobile_station_classmark_2_t + +// IE: Supported codec list +// Reference: 9.11.3.51A +class supported_codec_list_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // supported_codec_list_t + +// IE: message container +// Reference: 9.11.3.33 +class message_container_t +{ +public: + uint32_t length; + std::vector nas_message_container; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // message_container_t + +// IE: EPS bearer context status +// Reference: 9.11.3.23A +class eps_bearer_context_status_t +{ +public: + uint32_t length; + bool ebi_7; + bool ebi_6; + bool ebi_5; + bool ebi_4; + bool ebi_3; + bool ebi_2; + bool ebi_1; + bool ebi_0; + bool ebi_15; + bool ebi_14; + bool ebi_13; + bool ebi_12; + bool ebi_11; + bool ebi_10; + bool ebi_9; + bool ebi_8; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // eps_bearer_context_status_t + +// IE: Extended DRX parameters +// Reference: 9.11.3.26A +class extended_drx_parameters_t +{ +public: + struct Paging_Time_Window_type_ { + enum options { + seconds_0 = 0b0000, + second_1 = 0b0001, + seconds_2 = 0b0010, + seconds_3 = 0b0011, + seconds_4 = 0b0100, + seconds_5 = 0b0101, + seconds_6 = 0b0110, + seconds_7 = 0b0111, + seconds_8 = 0b1000, + seconds_9 = 0b1001, + seconds_10 = 0b1010, + seconds_12 = 0b1011, + seconds_14 = 0b1100, + seconds_16 = 0b1101, + seconds_18 = 0b1110, + seconds_20 = 0b1111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Paging_Time_Window_type; + + struct eDRX_value_type_ { + enum options { + second_1_28 = 0b0000, + second_2_56 = 0b0001, + second_3_84 = 0b0010, + second_5_12 = 0b0011, + second_6_4 = 0b0100, + second_7_68 = 0b0101, + second_8_96 = 0b0110, + second_10_24 = 0b0111, + second_11_52 = 0b1000, + second_12_8 = 0b1001, + second_14_08 = 0b1010, + second_15_36 = 0b1011, + second_16_64 = 0b1100, + second_17_92 = 0b1101, + second_19_20 = 0b1110, + second_20_48 = 0b1111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated eDRX_value_type; + + uint32_t length; + Paging_Time_Window_type paging__time__window; + eDRX_value_type e_drx_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // extended_drx_parameters_t + +// IE: GPRS timer 3 +// Reference: 9.11.2.5 +class gprs_timer_3_t +{ +public: + struct Unit_type_ { + enum options { + value_is_incremented_in_multiples_of_10_minutes = 0b000, + value_is_incremented_in_multiples_of_1_hour = 0b001, + value_is_incremented_in_multiples_of_10_hours = 0b010, + value_is_incremented_in_multiples_of_2_seconds = 0b011, + value_is_incremented_in_multiples_of_30_seconds = 0b100, + value_is_incremented_in_multiples_of_1_minute = 0b101, + value_is_incremented_in_multiples_of_320_hours = 0b110, + value_indicates_that_the_timer_is_deactivated = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Unit_type; + + uint32_t length; + Unit_type unit; + uint8_t timer_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // gprs_timer_3_t + +// IE: UE radio capability ID +// Reference: 9.11.3.68 +class ue_radio_capability_id_t +{ +public: + uint32_t length; + std::vector ue_radio_capability_id; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ue_radio_capability_id_t + +// IE: Mapped NSSAI +// Reference: 9.11.3.31B +class mapped_nssai_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // mapped_nssai_t + +// IE: Additional information requested +// Reference: 9.11.3.12A +class additional_information_requested_t +{ +public: + uint32_t length; + bool cipher_key; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // additional_information_requested_t + +// IE: WUS assistance information +// Reference: 9.11.3.71 +class wus_assistance_information_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // wus_assistance_information_t + +// IE: N5GC indication +// Reference: 9.11.3.72 +class n5gc_indication_t +{ +public: + uint32_t length; + bool n5gcreg; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // n5gc_indication_t + +// IE: NB-N1 mode DRX parameters +// Reference: 9.11.3.73 +class nb_n1_mode_drx_parameters_t +{ +public: + struct nb_n1_mode_drx_value_type_ { + enum options { + drx_value_not_specified = 0b0000, + drx_cycle_parameter_t_32 = 0b0001, + drx_cycle_parameter_t_64 = 0b0010, + drx_cycle_parameter_t_128 = 0b0011, + drx_cycle_parameter_t_256 = 0b0100, + drx_cycle_parameter_t_512 = 0b0101, + drx_cycle_parameter_t_1024 = 0b0111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated nb_n1_mode_drx_value_type; + + uint32_t length; + nb_n1_mode_drx_value_type nb_n1_mode_drx_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // nb_n1_mode_drx_parameters_t + +// IE: 5GS registration result +// Reference: 9.11.3.6 +class registration_result_5gs_t +{ +public: + struct Emergency_registered_type_ { + enum options { + not_registered_for_emergency_services = 0b0, + registered_for_emergency_services = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Emergency_registered_type; + + struct NSSAA_to_be_performed_type_ { + enum options { + nssaa_is_not_to_be_performed = 0b0, + nssaa_is_to_be_performed = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated NSSAA_to_be_performed_type; + + struct SMS_allowed_type_ { + enum options { + sms_over_nas_not_allowed = 0b0, + sms_over_nas_allowed = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated SMS_allowed_type; + + struct registration_result_type_ { + enum options { + access_3_gpp = 0b001, + non_3_gpp_access = 0b010, + access_3_gpp_and_non_3_gpp_access = 0b011, + reserved = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated registration_result_type; + + uint32_t length; + Emergency_registered_type emergency_registered; + NSSAA_to_be_performed_type nssaa_to_be_performed; + SMS_allowed_type sms_allowed; + registration_result_type registration_result; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // registration_result_5gs_t + +// IE: PLMN list +// Reference: 9.11.3.45 +class plmn_list_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // plmn_list_t + +// IE: 5GS tracking area identity list +// Reference: 9.11.3.9 +class tracking_area_identity_list_5gs_t +{ +public: + struct type_of_list_type_ { + enum options { + list_of_ta_cs_belonging_to_one_plmn_or_snpn_with_non_consecutive_tac_values = 0b00, + list_of_ta_cs_belonging_to_one_plmn_or_snpn_with_consecutive_tac_values = 0b01, + list_of_ta_is_belonging_to_different_plm_ns = 0b10, + reserved = 0b11, + + } value; + const char* to_string(); + }; + typedef nas_enumerated type_of_list_type; + + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // tracking_area_identity_list_5gs_t + +// IE: Rejected NSSAI +// Reference: 9.11.3.46 +class rejected_nssai_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // rejected_nssai_t + +// IE: 5GS network feature support +// Reference: 9.11.3.5 +class network_feature_support_5gs_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // network_feature_support_5gs_t + +// IE: PDU session reactivation result +// Reference: 9.11.3.42 +class pdu_session_reactivation_result_t +{ +public: + uint32_t length; + bool psi_7; + bool psi_6; + bool psi_5; + bool psi_4; + bool psi_3; + bool psi_2; + bool psi_1; + bool psi_0; + bool psi_15; + bool psi_14; + bool psi_13; + bool psi_12; + bool psi_11; + bool psi_10; + bool psi_9; + bool psi_8; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_reactivation_result_t + +// IE: PDU session reactivation result error cause +// Reference: 9.11.3.43 +class pdu_session_reactivation_result_error_cause_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_reactivation_result_error_cause_t + +// IE: LADN information +// Reference: 9.11.3.30 +class ladn_information_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ladn_information_t + +// IE: Service area list +// Reference: 9.11.3.49 +class service_area_list_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // service_area_list_t + +// IE: GPRS timer 2 +// Reference: 9.11.2.4 +class gprs_timer_2_t +{ +public: + uint32_t length; + uint8_t timer_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // gprs_timer_2_t + +// IE: Emergency number list +// Reference: 9.11.3.23 +class emergency_number_list_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // emergency_number_list_t + +// IE: Extended emergency number list +// Reference: 9.11.3.26 +class extended_emergency_number_list_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // extended_emergency_number_list_t + +// IE: SOR transparent container +// Reference: 9.11.3.51 +class sor_transparent_container_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // sor_transparent_container_t + +// IE: EAP message +// Reference: 9.11.2.2 +class eap_message_t +{ +public: + uint32_t length; + std::vector eap_message; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // eap_message_t + +// IE: NSSAI inclusion mode +// Reference: 9.11.3.37A +class nssai_inclusion_mode_t +{ +public: + struct NSSAI_inclusion_mode_type_ { + enum options { + nssai_inclusion_mode_a = 0b00, + nssai_inclusion_mode_b = 0b01, + nssai_inclusion_mode_c = 0b10, + nssai_inclusion_mode_d = 0b11, + + } value; + const char* to_string(); + }; + typedef nas_enumerated NSSAI_inclusion_mode_type; + + uint32_t length; + NSSAI_inclusion_mode_type nssai_inclusion_mode; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // nssai_inclusion_mode_t + +// IE: Operator-defined access category definitions +// Reference: 9.11.3.38 +class operator_defined_access_category_definitions_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // operator_defined_access_category_definitions_t + +// IE: Non-3GPP NW provided policies +// Reference: 9.11.3.36A +class non_3_gpp_nw_provided_policies_t +{ +public: + uint32_t length; + bool n3_en; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // non_3_gpp_nw_provided_policies_t + +// IE: UE radio capability ID deletion indication +// Reference: 9.11.3.69 +class ue_radio_capability_id_deletion_indication_t +{ +public: + struct Deletion_request_type_ { + enum options { + ue_radio_capability_id_deletion_not_requested = 0b000, + network_assigned_ue_radio_capability_i_ds_deletion_requested = 0b001, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Deletion_request_type; + + uint32_t length; + Deletion_request_type deletion_request; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ue_radio_capability_id_deletion_indication_t + +// IE: Ciphering key data +// Reference: 9.11.3.18C +class ciphering_key_data_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ciphering_key_data_t + +// IE: CAG information list +// Reference: 9.11.3.18A +class cag_information_list_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // cag_information_list_t + +// IE: Truncated 5G-S-TMSI configuration +// Reference: 9.11.3.70 +class truncated_5g_s_tmsi_configuration_t +{ +public: + uint32_t length; + uint8_t truncated_amf__set_id_value; + uint8_t truncated_amf__pointer_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // truncated_5g_s_tmsi_configuration_t + +// IE: 5GMM cause +// Reference: 9.11.3.2 +class cause_5gmm_t +{ +public: + struct cause_5gmm_type_ { + enum options { + illegal_ue = 0b00000011, + pei_not_accepted = 0b00000101, + illegal_me = 0b00000110, + services_not_allowed_5gs = 0b00000111, + ue_identity_cannot_be_derived_by_the_network = 0b00001001, + implicitly_de_registered = 0b00001010, + plmn_not_allowed = 0b00001011, + tracking_area_not_allowed = 0b00001100, + roaming_not_allowed_in_this_tracking_area = 0b00001101, + no_suitable_cells_in_tracking_area = 0b00001111, + mac_failure = 0b00010100, + synch_failure = 0b00010101, + congestion = 0b00010110, + ue_security_capabilities_mismatch = 0b00010111, + security_mode_rejected_unspecified = 0b00011000, + non_5g_authentication_unacceptable = 0b00011010, + n1_mode_not_allowed = 0b00011011, + restricted_service_area = 0b00011100, + redirection_to_epc_required = 0b00011111, + ladn_not_available = 0b00101011, + no_network_slices_available = 0b00111110, + maximum_number_of_pdu_sessions_reached_ = 0b01000001, + insufficient_resources_for_specific_slice_and_dnn = 0b01000011, + insufficient_resources_for_specific_slice = 0b01000101, + ng_ksi_already_in_use = 0b01000111, + non_3_gpp_access_to_5gcn_not_allowed = 0b01001000, + serving_network_not_authorized = 0b01001001, + temporarily_not_authorized_for_this_snpn = 0b01001010, + permanently_not_authorized_for_this_snpn = 0b01001011, + not_authorized_for_this_cag_or_authorized_for_cag_cells_only = 0b01001100, + wireline_access_area_not_allowed = 0b01001101, + payload_was_not_forwarded = 0b01011010, + dnn_not_supported_or_not_subscribed_in_the_slice = 0b01011011, + insufficient_user_plane_resources_for_the_pdu_session = 0b01011100, + semantically_incorrect_message = 0b01011111, + invalid_mandatory_information = 0b01100000, + message_type_non_existent_or_not_implemented = 0b01100001, + message_type_not_compatible_with_the_protocol_state = 0b01100010, + information_element_non_existent_or_not_implemented = 0b01100011, + conditional_ie_error = 0b01100100, + message_not_compatible_with_the_protocol_state = 0b01100101, + protocol_error_unspecified = 0b01101111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated cause_5gmm_type; + + uint32_t length; + cause_5gmm_type cause_5gmm; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // cause_5gmm_t + +// IE: De-registration type +// Reference: 9.11.3.20 +class de_registration_type_t +{ +public: + struct switch_off_type_ { + enum options { + normal_de_registration = 0b0, + switch_off = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated switch_off_type; + + struct re_registration_required_type_ { + enum options { + re_registration_not_required = 0b0, + re_registration_required = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated re_registration_required_type; + + struct access_type_type_ { + enum options { + access_3_gpp = 0b01, + non_3_gpp_access = 0b10, + access_3_gpp_and_non_3_gpp_access = 0b11, + + } value; + const char* to_string(); + }; + typedef nas_enumerated access_type_type; + + uint32_t length; + switch_off_type switch_off; + re_registration_required_type re_registration_required; + access_type_type access_type; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // de_registration_type_t + +// IE: Spare half octet +// Reference: 9.5 +class spare_half_octet_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // spare_half_octet_t + +// IE: Service type +// Reference: 9.11.3.50 +class service_type_t +{ +public: + struct Service_type_value_type_ { + enum options { + signalling = 0b0000, + data = 0b0001, + mobile_terminated_services = 0b0010, + emergency_services = 0b0011, + emergency_services_fallback = 0b0100, + high_priority_access = 0b0101, + elevated_signalling = 0b0110, + unused_shall_be_interpreted_as_signalling = 0b0111, + unused_shall_be_interpreted_as_signalling_1 = 0b1000, + unused_shall_be_interpreted_as_data = 0b1001, + unused_shall_be_interpreted_as_data_1 = 0b1010, + unused_shall_be_interpreted_as_data_2 = 0b1011, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Service_type_value_type; + + uint32_t length; + Service_type_value_type service_type_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // service_type_t + +// IE: Configuration update indication +// Reference: 9.11.3.18 +class configuration_update_indication_t +{ +public: + struct control_plane_service_type_value_type_ { + enum options { + mobile_originating_request = 0b000, + mobile_terminating_request = 0b001, + emergency_services = 0b010, + emergency_services_fallback = 0b100, + + } value; + const char* to_string(); + }; + typedef nas_enumerated control_plane_service_type_value_type; + + uint32_t length; + control_plane_service_type_value_type control_plane_service_type_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // configuration_update_indication_t + +// IE: Network name +// Reference: 9.11.3.35 +class network_name_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // network_name_t + +// IE: Time zone +// Reference: 9.11.3.52 +class time_zone_t +{ +public: + uint32_t length; + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t second; + uint8_t time_zone; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // time_zone_t + +// IE: Time zone and time +// Reference: 9.11.3.53 +class time_zone_and_time_t +{ +public: + uint32_t length; + uint8_t time_zone; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // time_zone_and_time_t + +// IE: Daylight saving time +// Reference: 9.11.3.19 +class daylight_saving_time_t +{ +public: + struct value_type_ { + enum options { + no_adjustment_for_daylight_saving_time = 0b00, + hour_1_adjustment_for_daylight_saving_time = 0b01, + hours_2_adjustment_for_daylight_saving_time = 0b10, + reserved = 0b11, + + } value; + const char* to_string(); + }; + typedef nas_enumerated value_type; + + uint32_t length; + value_type value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // daylight_saving_time_t + +// IE: SMS indication +// Reference: 9.11.3.50A +class sms_indication_t +{ +public: + uint32_t length; + bool sms_availability_indication; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // sms_indication_t + +// IE: Additional configuration indication +// Reference: 9.11.3.74 +class additional_configuration_indication_t +{ +public: + struct SCMR_type_ { + enum options { + no_additional_information = 0b0, + release_of_n1_nas_signalling_connection_not_required = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated SCMR_type; + + uint32_t length; + SCMR_type scmr; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // additional_configuration_indication_t + +// IE: ABBA +// Reference: 9.11.3.10 +class abba_t +{ +public: + uint32_t length; + std::vector abba_contents; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // abba_t + +// IE: Authentication parameter RAND +// Reference: 9.11.3.16 +class authentication_parameter_rand_t +{ +public: + uint32_t length; + std::array rand; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_parameter_rand_t + +// IE: Authentication parameter AUTN +// Reference: 9.11.3.15 +class authentication_parameter_autn_t +{ +public: + uint32_t length; + std::vector autn; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_parameter_autn_t + +// IE: Authentication response parameter +// Reference: 9.11.3.17 +class authentication_response_parameter_t +{ +public: + uint32_t length; + std::vector res; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_response_parameter_t + +// IE: Authentication failure parameter +// Reference: 9.11.3.14 +class authentication_failure_parameter_t +{ +public: + uint32_t length; + std::vector auth_failure; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_failure_parameter_t + +// IE: 5GS identity type +// Reference: 9.11.3.3 +class identity_type_5gs_t +{ +public: + struct identity_types_ { + enum options { + suci = 0b001, + guti_5g = 0b010, + imei = 0b011, + s_tmsi_5g = 0b100, + imeisv = 0b101, + mac_address = 0b110, + eui_64 = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated identity_types; + + uint32_t length; + identity_types type_of_identity; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // identity_type_5gs_t + +// IE: security algorithms +// Reference: 9.11.3.34 +class security_algorithms_t +{ +public: + struct integrity_protection_algorithm_type_ { + enum options { + ia0_5g = 0b0000, + ia1_128_5g = 0b0001, + ia2_128_5g = 0b0010, + ia3_128_5g = 0b0011, + ia4_5g = 0b0100, + ia5_5g = 0b0101, + ia6_5g = 0b0110, + ia7_5g = 0b0111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated integrity_protection_algorithm_type; + + struct ciphering_algorithm_type_ { + enum options { + ea0_5g = 0b0000, + ea1_128_5g = 0b0001, + ea2_128_5g = 0b0010, + ea3_128_5g = 0b0011, + ea4_5g = 0b0100, + ea5_5g = 0b0101, + ea6_5g = 0b0110, + ea7_5g = 0b0111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated ciphering_algorithm_type; + + uint32_t length; + ciphering_algorithm_type ciphering_algorithm; + integrity_protection_algorithm_type integrity_protection_algorithm; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // security_algorithms_t + +// IE: IMEISV request +// Reference: 9.11.3.28 +class imeisv_request_t +{ +public: + struct imeisv_request_type_ { + enum options { + imeisv_not_requested = 0b000, + imeisv_requested = 0b001, + + } value; + const char* to_string(); + }; + typedef nas_enumerated imeisv_request_type; + + uint32_t length; + imeisv_request_type imeisv_request; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // imeisv_request_t + +// IE: EPS NAS security algorithms +// Reference: 9.11.3.25 +class eps_nas_security_algorithms_t +{ +public: + struct integrity_protection_algorithm_type_ { + enum options { + eia0 = 0b000, + eia1_128 = 0b001, + eia2_128 = 0b010, + eia3_128 = 0b011, + eia4 = 0b100, + eia5 = 0b101, + eia6 = 0b110, + eia7 = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated integrity_protection_algorithm_type; + + struct ciphering_algorithm_type_ { + enum options { + eea0 = 0b000, + eea1_128 = 0b001, + eea2_128 = 0b010, + eea3_128 = 0b011, + eea4 = 0b100, + eea5 = 0b101, + eea6 = 0b110, + eea7 = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated ciphering_algorithm_type; + + uint32_t length; + ciphering_algorithm_type ciphering_algorithm; + integrity_protection_algorithm_type integrity_protection_algorithm; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // eps_nas_security_algorithms_t + +// IE: Additional 5G security information +// Reference: 9.11.3.12 +class additional_5g_security_information_t +{ +public: + uint32_t length; + bool rinmr; + bool hdp; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // additional_5g_security_information_t + +// IE: S1 UE security capability +// Reference: 9.11.3.48A +class s1_ue_security_capability_t +{ +public: + uint32_t length; + bool eea0; + bool eea1_128; + bool eea2_128; + bool eea3_128; + bool eea4; + bool eea5; + bool eea6; + bool eea7; + bool eia0; + bool eia1_128; + bool eia2_128; + bool eia3_128; + bool eia4; + bool eia5; + bool eia6; + bool eia7; + bool uea0; + bool uea1; + bool uea2; + bool uea3; + bool uea4; + bool uea5; + bool uea6; + bool uea7; + bool uia1; + bool uia2; + bool uia3; + bool uia4; + bool uia5; + bool uia6; + bool uia7; + bool gea1; + bool gea2; + bool gea3; + bool gea4; + bool gea5; + bool gea6; + bool gea7; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // s1_ue_security_capability_t + +// IE: Access type +// Reference: 9.11.2.1A +class access_type_t +{ +public: + struct Access_type_value_type_ { + enum options { + access_3_gpp = 0b01, + non_3_gpp_access = 0b10, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Access_type_value_type; + + uint32_t length; + Access_type_value_type access_type_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // access_type_t + +// IE: PDU session identity 2 +// Reference: 9.11.3.41 +class pdu_session_identity_2_t +{ +public: + uint32_t length; + uint8_t pdu_session_identity_2_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_identity_2_t + +// IE: Request type +// Reference: 9.11.3.47 +class request_type_t +{ +public: + struct Request_type_value_type_ { + enum options { + initial_request = 0b001, + existing_pdu_session = 0b010, + initial_emergency_request = 0b011, + existing_emergency_pdu_session = 0b100, + modification_request = 0b101, + ma_pdu_request = 0b110, + reserved = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Request_type_value_type; + + uint32_t length; + Request_type_value_type request_type_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // request_type_t + +// IE: Additional information +// Reference: 9.11.2.1 +class additional_information_t +{ +public: + uint32_t length; + std::vector additional_information_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // additional_information_t + +// IE: MA PDU session information +// Reference: 9.11.3.31A +class ma_pdu_session_information_t +{ +public: + struct MA_PDU_session_information_value_type_ { + enum options { + ma_pdu_session_network_upgrade_is_allowed = 0b0001, + + } value; + const char* to_string(); + }; + typedef nas_enumerated MA_PDU_session_information_value_type; + + uint32_t length; + MA_PDU_session_information_value_type ma_pdu_session_information_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ma_pdu_session_information_t + +// IE: Release assistance indication +// Reference: 9.11.3.46A +class release_assistance_indication_t +{ +public: + struct Downlink_data_expected_type_ { + enum options { + no_information_regarding_ddx_is_conveyed = 0b00, + no_further_uplink_and_no_further_downlink_data = 0b01, + only_a_single_downlink_data_transmission = 0b10, + reserved = 0b11, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Downlink_data_expected_type; + + uint32_t length; + Downlink_data_expected_type downlink_data_expected; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // release_assistance_indication_t + +// IE: Integrity protection maximum data rate +// Reference: 9.11.4.7 +class integrity_protection_maximum_data_rate_t +{ +public: + struct max_data_rate_UPIP_uplink_type_ { + enum options { + kbps_64 = 0b00000000, + null = 0b00000001, + full_data_rate = 0b11111111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated max_data_rate_UPIP_uplink_type; + + struct max_data_rate_UPIP_downlink_type_ { + enum options { + kbps_64 = 0b00000000, + null = 0b00000001, + full_data_rate = 0b11111111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated max_data_rate_UPIP_downlink_type; + + uint32_t length; + max_data_rate_UPIP_uplink_type max_data_rate_upip_uplink; + max_data_rate_UPIP_downlink_type max_data_rate_upip_downlink; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // integrity_protection_maximum_data_rate_t + +// IE: PDU session type +// Reference: 9.11.4.11 +class pdu_session_type_t +{ +public: + struct PDU_session_type_value_type_ { + enum options { + ipv4 = 0b001, + ipv6 = 0b010, + ipv4v6 = 0b011, + unstructured = 0b100, + ethernet = 0b101, + reserved = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated PDU_session_type_value_type; + + uint32_t length; + PDU_session_type_value_type pdu_session_type_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_type_t + +// IE: SSC mode +// Reference: 9.11.4.16 +class ssc_mode_t +{ +public: + struct SSC_mode_value_type_ { + enum options { + ssc_mode_1 = 0b001, + ssc_mode_2 = 0b010, + ssc_mode_3 = 0b011, + unused_or_ssc_mode_1 = 0b100, + unused_or_ssc_mode_2 = 0b101, + unused_or_ssc_mode_3 = 0b110, + reserved = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated SSC_mode_value_type; + + uint32_t length; + SSC_mode_value_type ssc_mode_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ssc_mode_t + +// IE: 5GSM capability +// Reference: 9.11.4.1 +class capability_5gsm_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // capability_5gsm_t + +// IE: Maximum number of supported packet filters +// Reference: 9.11.4.9 +class maximum_number_of_supported_packet_filters_t +{ +public: + uint32_t length; + uint16_t maximum_number_of_supported_packet_filters; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // maximum_number_of_supported_packet_filters_t + +// IE: Always-on PDU session requested +// Reference: 9.11.4.4 +class always_on_pdu_session_requested_t +{ +public: + uint32_t length; + bool apsi; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // always_on_pdu_session_requested_t + +// IE: SM PDU DN request container +// Reference: 9.11.4.15 +class sm_pdu_dn_request_container_t +{ +public: + uint32_t length; + std::vector dn_specific_identity; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // sm_pdu_dn_request_container_t + +// IE: Extended protocol configuration options +// Reference: 9.11.4.6 +class extended_protocol_configuration_options_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // extended_protocol_configuration_options_t + +// IE: IP header compression configuration +// Reference: 9.11.4.24 +class ip_header_compression_configuration_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ip_header_compression_configuration_t + +// IE: DS-TT Ethernet port MAC address +// Reference: 9.11.4.25 +class ds_tt__ethernet_port_mac_address_t +{ +public: + uint32_t length; + std::array ds_tt__ethernet_port_mac_address_contents; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ds_tt__ethernet_port_mac_address_t + +// IE: UE-DS-TT residence time +// Reference: 9.11.4.26 +class ue_ds_tt_residence_time_t +{ +public: + uint32_t length; + std::array ue_ds_tt_residence_time_contents; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ue_ds_tt_residence_time_t + +// IE: Port management information container +// Reference: 9.11.4.27 +class port_management_information_container_t +{ +public: + uint32_t length; + std::vector port_management_information_container; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // port_management_information_container_t + +// IE: Ethernet header compression configuration +// Reference: 9.11.4.28 +class ethernet_header_compression_configuration_t +{ +public: + struct CID_Length_type_ { + enum options { + ethernet_header_compression_not_used = 0b00, + bits_7 = 0b01, + bits_15 = 0b10, + + } value; + const char* to_string(); + }; + typedef nas_enumerated CID_Length_type; + + uint32_t length; + CID_Length_type cid__length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ethernet_header_compression_configuration_t + +// IE: PDU address +// Reference: 9.11.4.10 +class pdu_address_t +{ +public: + struct PDU_session_type_value_type_ { + enum options { + ipv4 = 0b001, + ipv6 = 0b010, + ipv4v6 = 0b011, + + } value; + const char* to_string(); + }; + typedef nas_enumerated PDU_session_type_value_type; + + uint32_t length; + bool si6_lla; + PDU_session_type_value_type pdu_session_type_value; + std::array ipv4; + std::array ipv6; + std::array smf_i_pv6_link_local_address; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_address_t + +// IE: QoS rules +// Reference: 9.11.4.13 +class qo_s_rules_t +{ +public: + struct qos_rule_t {}; + uint32_t length; + std::vector qos_rules; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // qo_s_rules_t + +// IE: Session-AMBR +// Reference: 9.11.4.14 +class session_ambr_t +{ +public: + struct unit_session_AMBR_type_ { + enum options { + not_used = 0b00000000, + inc_by_1_kbps = 0b00000001, + inc_by_4_kbps = 0b00000010, + inc_by_16_kbps = 0b00000011, + inc_by_64_kbps = 0b00000100, + inc_by_256_kbps = 0b00000101, + inc_by_1_mbps = 0b00000110, + inc_by_4_mbps = 0b00000111, + inc_by_16_mbps = 0b00001000, + inc_by_64_mbps = 0b00001001, + inc_by_256_mbps = 0b00001010, + inc_by_1_gbps = 0b00001011, + inc_by_4_gbps = 0b00001100, + inc_by_16_gbps = 0b00001101, + inc_by_64_gbps = 0b00001110, + inc_by_256_gbps = 0b00001111, + inc_by_1_tbps = 0b00010000, + inc_by_4_tbps = 0b00010001, + inc_by_16_tbps = 0b00010010, + inc_by_64_tbps = 0b00010011, + inc_by_256_tbps = 0b00010100, + inc_by_1_pbps = 0b00010101, + inc_by_4_pbps = 0b00010110, + inc_by_16_pbps = 0b00010111, + inc_by_64_pbps = 0b00011000, + inc_by_256_pbps = 0b00011001, + + } value; + const char* to_string(); + }; + typedef nas_enumerated unit_session_AMBR_type; + + uint32_t length; + unit_session_AMBR_type unit_session_ambr_for_downlink; + uint16_t session_ambr_for_downlink; + unit_session_AMBR_type unit_session_ambr_for_uplink; + uint16_t session_ambr_for_uplink; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // session_ambr_t + +// IE: 5GSM cause +// Reference: 9.11.4.2 +class cause_5gsm_t +{ +public: + struct cause_value_type_ { + enum options { + operator_determined_barring = 0b00001000, + insufficient_resources = 0b00011010, + missing_or_unknown_dnn = 0b00011011, + unknown_pdu_session_type = 0b00011100, + user_authentication_or_authorization_failed = 0b00011101, + request_rejected_unspecified = 0b00011111, + service_option_not_supported = 0b00100000, + requested_service_option_not_subscribed = 0b00100001, + pti_already_in_use = 0b00100011, + regular_deactivation = 0b00100100, + network_failure = 0b00100110, + reactivation_requested = 0b00100111, + semantic_error_in_the_tft_operation = 0b00101001, + syntactical_error_in_the_tft_operation = 0b00101010, + invalid_pdu_session_identity = 0b00101011, + semantic_errors_in_packet_filter = 0b00101100, + syntactical_error_in_packet_filter = 0b00101101, + out_of_ladn_service_area = 0b00101110, + pti_mismatch = 0b00101111, + pdu_session_type_i_pv4_only_allowed = 0b00110010, + pdu_session_type_i_pv6_only_allowed = 0b00110011, + pdu_session_does_not_exist = 0b00110110, + pdu_session_type_i_pv4v6_only_allowed = 0b00111001, + pdu_session_type_unstructured_only_allowed = 0b00111010, + unsupported_5_qi_value = 0b00111011, + pdu_session_type_ethernet_only_allowed = 0b00111101, + insufficient_resources_for_specific_slice_and_dnn = 0b01000011, + not_supported_ssc_mode = 0b01000100, + insufficient_resources_for_specific_slice = 0b01000101, + missing_or_unknown_dnn_in_a_slice = 0b01000110, + invalid_pti_value = 0b01010001, + maximum_data_rate_per_ue_for_user_plane_integrity_protection_is_too_low = 0b01010010, + semantic_error_in_the_qo_s_operation = 0b01010011, + syntactical_error_in_the_qo_s_operation = 0b01010100, + invalid_mapped_eps_bearer_identity = 0b01010101, + semantically_incorrect_message = 0b01011111, + invalid_mandatory_information = 0b01100000, + message_type_non_existent_or_not_implemented = 0b01100001, + message_type_not_compatible_with_the_protocol_state = 0b01100010, + information_element_non_existent_or_not_implemented = 0b01100011, + conditional_ie_error = 0b01100100, + message_not_compatible_with_the_protocol_state = 0b01100101, + protocol_error_unspecified = 0b01101111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated cause_value_type; + + uint32_t length; + cause_value_type cause_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // cause_5gsm_t + +// IE: GPRS timer +// Reference: 9.11.2.3 +class gprs_timer_t +{ +public: + struct Unit_type_ { + enum options { + value_is_incremented_in_multiples_of_2_seconds = 0b000, + value_is_incremented_in_multiples_of_1_minute = 0b001, + value_is_incremented_in_multiples_of_decihours = 0b010, + value_indicates_that_the_timer_is_deactivated = 0b111, + + } value; + const char* to_string(); + }; + typedef nas_enumerated Unit_type; + + uint32_t length; + Unit_type unit; + uint8_t timer_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // gprs_timer_t + +// IE: Always-on PDU session indication +// Reference: 9.11.4.3 +class always_on_pdu_session_indication_t +{ +public: + uint32_t length; + bool apsr; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // always_on_pdu_session_indication_t + +// IE: Mapped EPS bearer contexts +// Reference: 9.11.4.8 +class mapped_eps_bearer_contexts_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // mapped_eps_bearer_contexts_t + +// IE: QoS flow descriptions +// Reference: 9.11.4.12 +class qo_s_flow_descriptions_t +{ +public: + uint32_t length; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // qo_s_flow_descriptions_t + +// IE: 5GSM network feature support +// Reference: 9.11.4.18 +class network_feature_support_5gsm_t +{ +public: + struct EPT_S1_type_ { + enum options { + ethernet_pdn_type_in_s1_mode_not_supported = 0b0, + ethernet_pdn_type_in_s1_mode_supported = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated EPT_S1_type; + + uint32_t length; + EPT_S1_type ept_s1; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // network_feature_support_5gsm_t + +// IE: Serving PLMN rate control +// Reference: 9.11.4.20 +class serving_plmn_rate_control_t +{ +public: + uint32_t length; + uint16_t serving_plmn_rate_control_value; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // serving_plmn_rate_control_t + +// IE: ATSSS container +// Reference: 9.11.4.22 +class atsss_container_t +{ +public: + uint32_t length; + std::vector nas_message_container; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // atsss_container_t + +// IE: Control plane only indication +// Reference: 9.11.4.23 +class control_plane_only_indication_t +{ +public: + uint32_t length; + bool cpoi; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // control_plane_only_indication_t + +// IE: Allowed SSC mode +// Reference: 9.11.4.5 +class allowed_ssc_mode_t +{ +public: + uint32_t length; + bool ssc3; + bool ssc2; + bool ssc1; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // allowed_ssc_mode_t + +// IE: 5GSM congestion re-attempt indicator +// Reference: 9.11.4.21 +class congestion_re_attempt_indicator_5gsm_t +{ +public: + struct abo_type_ { + enum options { + the_back_off_timer_is_applied_in_the_registered_plmn = 0b0, + the_back_off_timer_is_applied_in_all_plm_ns = 0b1, + + } value; + const char* to_string(); + }; + typedef nas_enumerated abo_type; + + uint32_t length; + abo_type abo; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // congestion_re_attempt_indicator_5gsm_t + +// IE: Re-attempt indicator +// Reference: 9.11.4.17 +class re_attempt_indicator_t +{ +public: + uint32_t length; + bool eplmnc; + bool ratc; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // re_attempt_indicator_t + +} // namespace nas_5g +} // namespace srsran +#endif diff --git a/lib/include/srsran/asn1/nas_5g_msg.h b/lib/include/srsran/asn1/nas_5g_msg.h new file mode 100644 index 000000000..cdf7225fe --- /dev/null +++ b/lib/include/srsran/asn1/nas_5g_msg.h @@ -0,0 +1,2390 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ +#ifndef SRSRAN_NAS_5G_MSG_H +#define SRSRAN_NAS_5G_MSG_H +#include "nas_5g_ies.h" +#include "nas_5g_utils.h" + +#include "srsran/asn1/asn1_utils.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/common.h" +#include "srsran/config.h" + +#include +#include +#include + +namespace srsran { +namespace nas_5g { + +/* + * Message: Registration request. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class registration_request_t +{ +public: + // Mandatory fields + registration_type_5gs_t registration_type_5gs; + key_set_identifier_t ng_ksi; + mobile_identity_5gs_t mobile_identity_5gs; + + // Optional fields + bool non_current_native_nas_key_set_identifier_present = false; + bool capability_5gmm_present = false; + bool ue_security_capability_present = false; + bool requested_nssai_present = false; + bool last_visited_registered_tai_present = false; + bool s1_ue_network_capability_present = false; + bool uplink_data_status_present = false; + bool pdu_session_status_present = false; + bool mico_indication_present = false; + bool ue_status_present = false; + bool additional_guti_present = false; + bool allowed_pdu_session_status_present = false; + bool ue_usage_setting_present = false; + bool requested_drx_parameters_present = false; + bool eps_nas_message_container_present = false; + bool ladn_indication_present = false; + bool payload_container_type_present = false; + bool payload_container_present = false; + bool network_slicing_indication_present = false; + bool update_type_5gs_present = false; + bool mobile_station_classmark_2_present = false; + bool supported_codecs_present = false; + bool nas_message_container_present = false; + bool eps_bearer_context_status_present = false; + bool requested_extended_drx_parameters_present = false; + bool t3324_value_present = false; + bool ue_radio_capability_id_present = false; + bool requested_mapped_nssai_present = false; + bool additional_information_requested_present = false; + bool requested_wus_assistance_information_present = false; + bool n5gc_indication_present = false; + bool requested_nb_n1_mode_drx_parameters_present = false; + + key_set_identifier_t non_current_native_nas_key_set_identifier; + capability_5gmm_t capability_5gmm; + ue_security_capability_t ue_security_capability; + nssai_t requested_nssai; + tracking_area_identity_5gs_t last_visited_registered_tai; + s1_ue_network_capability_t s1_ue_network_capability; + uplink_data_status_t uplink_data_status; + pdu_session_status_t pdu_session_status; + mico_indication_t mico_indication; + ue_status_t ue_status; + mobile_identity_5gs_t additional_guti; + allowed_pdu_session_status_t allowed_pdu_session_status; + ue_usage_setting_t ue_usage_setting; + drx_parameters_5gs_t requested_drx_parameters; + eps_nas_message_container_t eps_nas_message_container; + ladn_indication_t ladn_indication; + payload_container_type_t payload_container_type; + payload_container_t payload_container; + network_slicing_indication_t network_slicing_indication; + update_type_5gs_t update_type_5gs; + mobile_station_classmark_2_t mobile_station_classmark_2; + supported_codec_list_t supported_codecs; + message_container_t nas_message_container; + eps_bearer_context_status_t eps_bearer_context_status; + extended_drx_parameters_t requested_extended_drx_parameters; + gprs_timer_3_t t3324_value; + ue_radio_capability_id_t ue_radio_capability_id; + mapped_nssai_t requested_mapped_nssai; + additional_information_requested_t additional_information_requested; + wus_assistance_information_t requested_wus_assistance_information; + n5gc_indication_t n5gc_indication; + nb_n1_mode_drx_parameters_t requested_nb_n1_mode_drx_parameters; + + const static uint8_t ie_iei_non_current_native_nas_key_set_identifier = 0xC; + const static uint8_t ie_iei_capability_5gmm = 0x10; + const static uint8_t ie_iei_ue_security_capability = 0x2E; + const static uint8_t ie_iei_requested_nssai = 0x2F; + const static uint8_t ie_iei_last_visited_registered_tai = 0x52; + const static uint8_t ie_iei_s1_ue_network_capability = 0x17; + const static uint8_t ie_iei_uplink_data_status = 0x40; + const static uint8_t ie_iei_pdu_session_status = 0x50; + const static uint8_t ie_iei_mico_indication = 0xB; + const static uint8_t ie_iei_ue_status = 0x2B; + const static uint8_t ie_iei_additional_guti = 0x77; + const static uint8_t ie_iei_allowed_pdu_session_status = 0x25; + const static uint8_t ie_iei_ue_usage_setting = 0x18; + const static uint8_t ie_iei_requested_drx_parameters = 0x51; + const static uint8_t ie_iei_eps_nas_message_container = 0x70; + const static uint8_t ie_iei_ladn_indication = 0x74; + const static uint8_t ie_iei_payload_container_type = 0x8; + const static uint8_t ie_iei_payload_container = 0x7B; + const static uint8_t ie_iei_network_slicing_indication = 0x9; + const static uint8_t ie_iei_update_type_5gs = 0x53; + const static uint8_t ie_iei_mobile_station_classmark_2 = 0x41; + const static uint8_t ie_iei_supported_codecs = 0x42; + const static uint8_t ie_iei_nas_message_container = 0x71; + const static uint8_t ie_iei_eps_bearer_context_status = 0x60; + const static uint8_t ie_iei_requested_extended_drx_parameters = 0x6E; + const static uint8_t ie_iei_t3324_value = 0x6A; + const static uint8_t ie_iei_ue_radio_capability_id = 0x67; + const static uint8_t ie_iei_requested_mapped_nssai = 0x35; + const static uint8_t ie_iei_additional_information_requested = 0x48; + const static uint8_t ie_iei_requested_wus_assistance_information = 0x1A; + const static uint8_t ie_iei_n5gc_indication = 0xA; + const static uint8_t ie_iei_requested_nb_n1_mode_drx_parameters = 0x30; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // registration_request_t + +/* + * Message: Registration accept. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class registration_accept_t +{ +public: + // Mandatory fields + registration_result_5gs_t registration_result_5gs; + + // Optional fields + bool guti_5g_present = false; + bool equivalent_plm_ns_present = false; + bool tai_list_present = false; + bool allowed_nssai_present = false; + bool rejected_nssai_present = false; + bool configured_nssai_present = false; + bool network_feature_support_5gs_present = false; + bool pdu_session_status_present = false; + bool pdu_session_reactivation_result_present = false; + bool pdu_session_reactivation_result_error_cause_present = false; + bool ladn_information_present = false; + bool mico_indication_present = false; + bool network_slicing_indication_present = false; + bool service_area_list_present = false; + bool t3512_value_present = false; + bool non_3_gpp_de_registration_timer_value_present = false; + bool t3502_value_present = false; + bool emergency_number_list_present = false; + bool extended_emergency_number_list_present = false; + bool sor_transparent_container_present = false; + bool eap_message_present = false; + bool nssai_inclusion_mode_present = false; + bool operator_defined_access_category_definitions_present = false; + bool negotiated_drx_parameters_present = false; + bool non_3_gpp_nw_policies_present = false; + bool eps_bearer_context_status_present = false; + bool negotiated_extended_drx_parameters_present = false; + bool t3447_value_present = false; + bool t3448_value_present = false; + bool t3324_value_present = false; + bool ue_radio_capability_id_present = false; + bool ue_radio_capability_id_deletion_indication_present = false; + bool pending_nssai_present = false; + bool ciphering_key_data_present = false; + bool cag_information_list_present = false; + bool truncated_5g_s_tmsi_configuration_present = false; + bool negotiated_wus_assistance_information_present = false; + bool negotiated_nb_n1_mode_drx_parameters_present = false; + + mobile_identity_5gs_t guti_5g; + plmn_list_t equivalent_plm_ns; + tracking_area_identity_list_5gs_t tai_list; + nssai_t allowed_nssai; + rejected_nssai_t rejected_nssai; + nssai_t configured_nssai; + network_feature_support_5gs_t network_feature_support_5gs; + pdu_session_status_t pdu_session_status; + pdu_session_reactivation_result_t pdu_session_reactivation_result; + pdu_session_reactivation_result_error_cause_t pdu_session_reactivation_result_error_cause; + ladn_information_t ladn_information; + mico_indication_t mico_indication; + network_slicing_indication_t network_slicing_indication; + service_area_list_t service_area_list; + gprs_timer_3_t t3512_value; + gprs_timer_2_t non_3_gpp_de_registration_timer_value; + gprs_timer_2_t t3502_value; + emergency_number_list_t emergency_number_list; + extended_emergency_number_list_t extended_emergency_number_list; + sor_transparent_container_t sor_transparent_container; + eap_message_t eap_message; + nssai_inclusion_mode_t nssai_inclusion_mode; + operator_defined_access_category_definitions_t operator_defined_access_category_definitions; + drx_parameters_5gs_t negotiated_drx_parameters; + non_3_gpp_nw_provided_policies_t non_3_gpp_nw_policies; + eps_bearer_context_status_t eps_bearer_context_status; + extended_drx_parameters_t negotiated_extended_drx_parameters; + gprs_timer_3_t t3447_value; + gprs_timer_2_t t3448_value; + gprs_timer_3_t t3324_value; + ue_radio_capability_id_t ue_radio_capability_id; + ue_radio_capability_id_deletion_indication_t ue_radio_capability_id_deletion_indication; + nssai_t pending_nssai; + ciphering_key_data_t ciphering_key_data; + cag_information_list_t cag_information_list; + truncated_5g_s_tmsi_configuration_t truncated_5g_s_tmsi_configuration; + wus_assistance_information_t negotiated_wus_assistance_information; + nb_n1_mode_drx_parameters_t negotiated_nb_n1_mode_drx_parameters; + + const static uint8_t ie_iei_guti_5g = 0x77; + const static uint8_t ie_iei_equivalent_plm_ns = 0x4A; + const static uint8_t ie_iei_tai_list = 0x54; + const static uint8_t ie_iei_allowed_nssai = 0x15; + const static uint8_t ie_iei_rejected_nssai = 0x11; + const static uint8_t ie_iei_configured_nssai = 0x31; + const static uint8_t ie_iei_network_feature_support_5gs = 0x21; + const static uint8_t ie_iei_pdu_session_status = 0x50; + const static uint8_t ie_iei_pdu_session_reactivation_result = 0x26; + const static uint8_t ie_iei_pdu_session_reactivation_result_error_cause = 0x72; + const static uint8_t ie_iei_ladn_information = 0x79; + const static uint8_t ie_iei_mico_indication = 0xB; + const static uint8_t ie_iei_network_slicing_indication = 0x9; + const static uint8_t ie_iei_service_area_list = 0x27; + const static uint8_t ie_iei_t3512_value = 0x5E; + const static uint8_t ie_iei_non_3_gpp_de_registration_timer_value = 0x5D; + const static uint8_t ie_iei_t3502_value = 0x16; + const static uint8_t ie_iei_emergency_number_list = 0x34; + const static uint8_t ie_iei_extended_emergency_number_list = 0x7A; + const static uint8_t ie_iei_sor_transparent_container = 0x73; + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_nssai_inclusion_mode = 0xA; + const static uint8_t ie_iei_operator_defined_access_category_definitions = 0x76; + const static uint8_t ie_iei_negotiated_drx_parameters = 0x51; + const static uint8_t ie_iei_non_3_gpp_nw_policies = 0xD; + const static uint8_t ie_iei_eps_bearer_context_status = 0x60; + const static uint8_t ie_iei_negotiated_extended_drx_parameters = 0x6E; + const static uint8_t ie_iei_t3447_value = 0x6C; + const static uint8_t ie_iei_t3448_value = 0x6B; + const static uint8_t ie_iei_t3324_value = 0x6A; + const static uint8_t ie_iei_ue_radio_capability_id = 0x67; + const static uint8_t ie_iei_ue_radio_capability_id_deletion_indication = 0xE; + const static uint8_t ie_iei_pending_nssai = 0x39; + const static uint8_t ie_iei_ciphering_key_data = 0x74; + const static uint8_t ie_iei_cag_information_list = 0x75; + const static uint8_t ie_iei_truncated_5g_s_tmsi_configuration = 0x1B; + const static uint8_t ie_iei_negotiated_wus_assistance_information = 0x1C; + const static uint8_t ie_iei_negotiated_nb_n1_mode_drx_parameters = 0x29; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // registration_accept_t + +/* + * Message: Registration complete. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class registration_complete_t +{ +public: + // Mandatory fields + + // Optional fields + bool sor_transparent_container_present = false; + + sor_transparent_container_t sor_transparent_container; + + const static uint8_t ie_iei_sor_transparent_container = 0x73; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // registration_complete_t + +/* + * Message: Registration reject. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class registration_reject_t +{ +public: + // Mandatory fields + cause_5gmm_t cause_5gmm; + + // Optional fields + bool t3346_value_present = false; + bool t3502_value_present = false; + bool eap_message_present = false; + bool rejected_nssai_present = false; + bool cag_information_list_present = false; + + gprs_timer_2_t t3346_value; + gprs_timer_2_t t3502_value; + eap_message_t eap_message; + rejected_nssai_t rejected_nssai; + cag_information_list_t cag_information_list; + + const static uint8_t ie_iei_t3346_value = 0x5F; + const static uint8_t ie_iei_t3502_value = 0x16; + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_rejected_nssai = 0x69; + const static uint8_t ie_iei_cag_information_list = 0x75; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // registration_reject_t + +/* + * Message: Deregistration request UE originating. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class deregistration_request_ue_originating_t +{ +public: + // Mandatory fields + de_registration_type_t de_registration_type; + key_set_identifier_t ng_ksi; + mobile_identity_5gs_t mobile_identity_5gs; + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // deregistration_request_ue_originating_t + +/* + * Message: Deregistration accept UE originating. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class deregistration_accept_ue_originating_t +{ +public: + // Mandatory fields + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // deregistration_accept_ue_originating_t + +/* + * Message: Deregistration request UE terminated. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class deregistration_request_ue_terminated_t +{ +public: + // Mandatory fields + de_registration_type_t de_registration_type; + spare_half_octet_t spare_half_octet; + + // Optional fields + bool cause_5gmm_present = false; + bool t3346_value_present = false; + bool rejected_nssai_present = false; + bool cag_information_list_present = false; + + cause_5gmm_t cause_5gmm; + gprs_timer_2_t t3346_value; + rejected_nssai_t rejected_nssai; + cag_information_list_t cag_information_list; + + const static uint8_t ie_iei_cause_5gmm = 0x58; + const static uint8_t ie_iei_t3346_value = 0x5F; + const static uint8_t ie_iei_rejected_nssai = 0x6D; + const static uint8_t ie_iei_cag_information_list = 0x75; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // deregistration_request_ue_terminated_t + +/* + * Message: Deregistration accept UE terminated. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class deregistration_accept_ue_terminated_t +{ +public: + // Mandatory fields + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // deregistration_accept_ue_terminated_t + +/* + * Message: Service request. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class service_request_t +{ +public: + // Mandatory fields + key_set_identifier_t ng_ksi; + service_type_t service_type; + mobile_identity_5gs_t s_tmsi_5g; + + // Optional fields + bool uplink_data_status_present = false; + bool pdu_session_status_present = false; + bool allowed_pdu_session_status_present = false; + bool nas_message_container_present = false; + + uplink_data_status_t uplink_data_status; + pdu_session_status_t pdu_session_status; + allowed_pdu_session_status_t allowed_pdu_session_status; + message_container_t nas_message_container; + + const static uint8_t ie_iei_uplink_data_status = 0x40; + const static uint8_t ie_iei_pdu_session_status = 0x50; + const static uint8_t ie_iei_allowed_pdu_session_status = 0x25; + const static uint8_t ie_iei_nas_message_container = 0x71; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // service_request_t + +/* + * Message: Service reject. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class service_reject_t +{ +public: + // Mandatory fields + + // Optional fields + bool pdu_session_status_present = false; + bool pdu_session_reactivation_result_present = false; + bool pdu_session_reactivation_result_error_cause_present = false; + bool eap_message_present = false; + bool t3448_value_present = false; + + pdu_session_status_t pdu_session_status; + pdu_session_reactivation_result_t pdu_session_reactivation_result; + pdu_session_reactivation_result_error_cause_t pdu_session_reactivation_result_error_cause; + eap_message_t eap_message; + gprs_timer_2_t t3448_value; + + const static uint8_t ie_iei_pdu_session_status = 0x50; + const static uint8_t ie_iei_pdu_session_reactivation_result = 0x26; + const static uint8_t ie_iei_pdu_session_reactivation_result_error_cause = 0x72; + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_t3448_value = 0x6B; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // service_reject_t + +/* + * Message: Service accept. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class service_accept_t +{ +public: + // Mandatory fields + cause_5gmm_t cause_5gmm; + + // Optional fields + bool pdu_session_status_present = false; + bool t3346_value_present = false; + bool eap_message_present = false; + bool t3448_value_present = false; + bool cag_information_list_present = false; + + pdu_session_status_t pdu_session_status; + gprs_timer_2_t t3346_value; + eap_message_t eap_message; + gprs_timer_2_t t3448_value; + cag_information_list_t cag_information_list; + + const static uint8_t ie_iei_pdu_session_status = 0x50; + const static uint8_t ie_iei_t3346_value = 0x5F; + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_t3448_value = 0x6B; + const static uint8_t ie_iei_cag_information_list = 0x75; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // service_accept_t + +/* + * Message: Configuration update command. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class configuration_update_command_t +{ +public: + // Mandatory fields + + // Optional fields + bool configuration_update_indication_present = false; + bool guti_5g_present = false; + bool tai_list_present = false; + bool allowed_nssai_present = false; + bool service_area_list_present = false; + bool full_name_for_network_present = false; + bool short_name_for_network_present = false; + bool local_time_zone_present = false; + bool universal_time_and_local_time_zone_present = false; + bool network_daylight_saving_time_present = false; + bool ladn_information_present = false; + bool mico_indication_present = false; + bool network_slicing_indication_present = false; + bool configured_nssai_present = false; + bool rejected_nssai_present = false; + bool operator_defined_access_category_definitions_present = false; + bool sms_indication_present = false; + bool t3447_value_present = false; + bool cag_information_list_present = false; + bool ue_radio_capability_id_present = false; + bool ue_radio_capability_id_deletion_indication_present = false; + bool registration_result_5gs_present = false; + bool truncated_5g_s_tmsi_configuration_present = false; + bool additional_configuration_indication_present = false; + + configuration_update_indication_t configuration_update_indication; + mobile_identity_5gs_t guti_5g; + tracking_area_identity_list_5gs_t tai_list; + nssai_t allowed_nssai; + service_area_list_t service_area_list; + network_name_t full_name_for_network; + network_name_t short_name_for_network; + time_zone_t local_time_zone; + time_zone_and_time_t universal_time_and_local_time_zone; + daylight_saving_time_t network_daylight_saving_time; + ladn_information_t ladn_information; + mico_indication_t mico_indication; + network_slicing_indication_t network_slicing_indication; + nssai_t configured_nssai; + rejected_nssai_t rejected_nssai; + operator_defined_access_category_definitions_t operator_defined_access_category_definitions; + sms_indication_t sms_indication; + gprs_timer_3_t t3447_value; + cag_information_list_t cag_information_list; + ue_radio_capability_id_t ue_radio_capability_id; + ue_radio_capability_id_deletion_indication_t ue_radio_capability_id_deletion_indication; + registration_result_5gs_t registration_result_5gs; + truncated_5g_s_tmsi_configuration_t truncated_5g_s_tmsi_configuration; + additional_configuration_indication_t additional_configuration_indication; + + const static uint8_t ie_iei_configuration_update_indication = 0xD; + const static uint8_t ie_iei_guti_5g = 0x77; + const static uint8_t ie_iei_tai_list = 0x54; + const static uint8_t ie_iei_allowed_nssai = 0x15; + const static uint8_t ie_iei_service_area_list = 0x27; + const static uint8_t ie_iei_full_name_for_network = 0x43; + const static uint8_t ie_iei_short_name_for_network = 0x45; + const static uint8_t ie_iei_local_time_zone = 0x46; + const static uint8_t ie_iei_universal_time_and_local_time_zone = 0x47; + const static uint8_t ie_iei_network_daylight_saving_time = 0x49; + const static uint8_t ie_iei_ladn_information = 0x79; + const static uint8_t ie_iei_mico_indication = 0xB; + const static uint8_t ie_iei_network_slicing_indication = 0x9; + const static uint8_t ie_iei_configured_nssai = 0x31; + const static uint8_t ie_iei_rejected_nssai = 0x11; + const static uint8_t ie_iei_operator_defined_access_category_definitions = 0x76; + const static uint8_t ie_iei_sms_indication = 0xF; + const static uint8_t ie_iei_t3447_value = 0x6C; + const static uint8_t ie_iei_cag_information_list = 0x75; + const static uint8_t ie_iei_ue_radio_capability_id = 0x67; + const static uint8_t ie_iei_ue_radio_capability_id_deletion_indication = 0xA; + const static uint8_t ie_iei_registration_result_5gs = 0x44; + const static uint8_t ie_iei_truncated_5g_s_tmsi_configuration = 0x1B; + const static uint8_t ie_iei_additional_configuration_indication = 0xC; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // configuration_update_command_t + +/* + * Message: Configuration update complete. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class configuration_update_complete_t +{ +public: + // Mandatory fields + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // configuration_update_complete_t + +/* + * Message: Authentication request. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class authentication_request_t +{ +public: + // Mandatory fields + key_set_identifier_t ng_ksi; + spare_half_octet_t spare_half_octet; + abba_t abba; + + // Optional fields + bool authentication_parameter_rand_present = false; + bool authentication_parameter_autn_present = false; + bool eap_message_present = false; + + authentication_parameter_rand_t authentication_parameter_rand; + authentication_parameter_autn_t authentication_parameter_autn; + eap_message_t eap_message; + + const static uint8_t ie_iei_authentication_parameter_rand = 0x21; + const static uint8_t ie_iei_authentication_parameter_autn = 0x20; + const static uint8_t ie_iei_eap_message = 0x78; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_request_t + +/* + * Message: Authentication response. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class authentication_response_t +{ +public: + // Mandatory fields + + // Optional fields + bool authentication_response_parameter_present = false; + bool eap_message_present = false; + + authentication_response_parameter_t authentication_response_parameter; + eap_message_t eap_message; + + const static uint8_t ie_iei_authentication_response_parameter = 0x2D; + const static uint8_t ie_iei_eap_message = 0x78; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_response_t + +/* + * Message: Authentication reject. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class authentication_reject_t +{ +public: + // Mandatory fields + + // Optional fields + bool eap_message_present = false; + + eap_message_t eap_message; + + const static uint8_t ie_iei_eap_message = 0x78; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_reject_t + +/* + * Message: Authentication failure. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class authentication_failure_t +{ +public: + // Mandatory fields + cause_5gmm_t cause_5gmm; + + // Optional fields + bool authentication_failure_parameter_present = false; + + authentication_failure_parameter_t authentication_failure_parameter; + + const static uint8_t ie_iei_authentication_failure_parameter = 0x30; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_failure_t + +/* + * Message: Authentication result. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class authentication_result_t +{ +public: + // Mandatory fields + key_set_identifier_t ng_ksi; + spare_half_octet_t spare_half_octet; + eap_message_t eap_message; + + // Optional fields + bool abba_present = false; + + abba_t abba; + + const static uint8_t ie_iei_abba = 0x38; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // authentication_result_t + +/* + * Message: Identity request. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class identity_request_t +{ +public: + // Mandatory fields + identity_type_5gs_t identity_type; + spare_half_octet_t spare_half_octet; + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // identity_request_t + +/* + * Message: Identity response. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class identity_response_t +{ +public: + // Mandatory fields + mobile_identity_5gs_t mobile_identity; + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // identity_response_t + +/* + * Message: Security mode command. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class security_mode_command_t +{ +public: + // Mandatory fields + security_algorithms_t selected_nas_security_algorithms; + key_set_identifier_t ng_ksi; + spare_half_octet_t spare_half_octet; + ue_security_capability_t replayed_ue_security_capabilities; + + // Optional fields + bool imeisv_request_present = false; + bool selected_eps_nas_security_algorithms_present = false; + bool additional_5g_security_information_present = false; + bool eap_message_present = false; + bool abba_present = false; + bool replayed_s1_ue_security_capabilities_present = false; + + imeisv_request_t imeisv_request; + eps_nas_security_algorithms_t selected_eps_nas_security_algorithms; + additional_5g_security_information_t additional_5g_security_information; + eap_message_t eap_message; + abba_t abba; + s1_ue_security_capability_t replayed_s1_ue_security_capabilities; + + const static uint8_t ie_iei_imeisv_request = 0xE; + const static uint8_t ie_iei_selected_eps_nas_security_algorithms = 0x57; + const static uint8_t ie_iei_additional_5g_security_information = 0x36; + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_abba = 0x38; + const static uint8_t ie_iei_replayed_s1_ue_security_capabilities = 0x19; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // security_mode_command_t + +/* + * Message: Security mode complete. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class security_mode_complete_t +{ +public: + // Mandatory fields + + // Optional fields + bool imeisv_present = false; + bool nas_message_container_present = false; + bool non_imeisv_pei_present = false; + + mobile_identity_5gs_t imeisv; + message_container_t nas_message_container; + mobile_identity_5gs_t non_imeisv_pei; + + const static uint8_t ie_iei_imeisv = 0x77; + const static uint8_t ie_iei_nas_message_container = 0x71; + const static uint8_t ie_iei_non_imeisv_pei = 0x78; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // security_mode_complete_t + +/* + * Message: Security mode reject. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class security_mode_reject_t +{ +public: + // Mandatory fields + cause_5gmm_t cause_5gmm; + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // security_mode_reject_t + +/* + * Message: Status 5GMM. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class status_5gmm_t +{ +public: + // Mandatory fields + cause_5gmm_t cause_5gmm; + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // status_5gmm_t + +/* + * Message: Notification. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class notification_t +{ +public: + // Mandatory fields + access_type_t access_type; + spare_half_octet_t spare_half_octet; + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // notification_t + +/* + * Message: Notification response. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class notification_response_t +{ +public: + // Mandatory fields + + // Optional fields + bool pdu_session_status_present = false; + + pdu_session_status_t pdu_session_status; + + const static uint8_t ie_iei_pdu_session_status = 0x50; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // notification_response_t + +/* + * Message: UL NAS transport. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class ul_nas_transport_t +{ +public: + // Mandatory fields + payload_container_type_t payload_container_type; + spare_half_octet_t spare_half_octet; + payload_container_t payload_container; + + // Optional fields + bool pdu_session_id_present = false; + bool old_pdu_session_id_present = false; + bool request_type_present = false; + bool s_nssai_present = false; + bool dnn_present = false; + bool additional_information_present = false; + bool ma_pdu_session_information_present = false; + bool release_assistance_indication_present = false; + + pdu_session_identity_2_t pdu_session_id; + pdu_session_identity_2_t old_pdu_session_id; + request_type_t request_type; + s_nssai_t s_nssai; + dnn_t dnn; + additional_information_t additional_information; + ma_pdu_session_information_t ma_pdu_session_information; + release_assistance_indication_t release_assistance_indication; + + const static uint8_t ie_iei_pdu_session_id = 0x12; + const static uint8_t ie_iei_old_pdu_session_id = 0x59; + const static uint8_t ie_iei_request_type = 0x8; + const static uint8_t ie_iei_s_nssai = 0x22; + const static uint8_t ie_iei_dnn = 0x25; + const static uint8_t ie_iei_additional_information = 0x24; + const static uint8_t ie_iei_ma_pdu_session_information = 0xA; + const static uint8_t ie_iei_release_assistance_indication = 0xF; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // ul_nas_transport_t + +/* + * Message: DL NAS transport . + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class dl_nas_transport_t +{ +public: + // Mandatory fields + payload_container_type_t payload_container_type; + spare_half_octet_t spare_half_octet; + payload_container_t payload_container; + + // Optional fields + bool pdu_session_id_present = false; + bool additional_information_present = false; + bool cause_5gmm_present = false; + bool back_off_timer_value_present = false; + + pdu_session_identity_2_t pdu_session_id; + additional_information_t additional_information; + cause_5gmm_t cause_5gmm; + gprs_timer_3_t back_off_timer_value; + + const static uint8_t ie_iei_pdu_session_id = 0x12; + const static uint8_t ie_iei_additional_information = 0x24; + const static uint8_t ie_iei_cause_5gmm = 0x58; + const static uint8_t ie_iei_back_off_timer_value = 0x37; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // dl_nas_transport_t + +/* + * Message: PDU session establishment request. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_establishment_request_t +{ +public: + // Mandatory fields + integrity_protection_maximum_data_rate_t integrity_protection_maximum_data_rate; + + // Optional fields + bool pdu_session_type_present = false; + bool ssc_mode_present = false; + bool capability_5gsm_present = false; + bool maximum_number_of_supported_packet_filters_present = false; + bool always_on_pdu_session_requested_present = false; + bool sm_pdu_dn_request_container_present = false; + bool extended_protocol_configuration_options_present = false; + bool ip_header_compression_configuration_present = false; + bool ds_tt__ethernet_port_mac_address_present = false; + bool ue_ds_tt_residence_time_present = false; + bool port_management_information_container_present = false; + bool ethernet_header_compression_configuration_present = false; + bool suggested_interface_identifier_present = false; + + pdu_session_type_t pdu_session_type; + ssc_mode_t ssc_mode; + capability_5gsm_t capability_5gsm; + maximum_number_of_supported_packet_filters_t maximum_number_of_supported_packet_filters; + always_on_pdu_session_requested_t always_on_pdu_session_requested; + sm_pdu_dn_request_container_t sm_pdu_dn_request_container; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + ip_header_compression_configuration_t ip_header_compression_configuration; + ds_tt__ethernet_port_mac_address_t ds_tt__ethernet_port_mac_address; + ue_ds_tt_residence_time_t ue_ds_tt_residence_time; + port_management_information_container_t port_management_information_container; + ethernet_header_compression_configuration_t ethernet_header_compression_configuration; + pdu_address_t suggested_interface_identifier; + + const static uint8_t ie_iei_pdu_session_type = 0x9; + const static uint8_t ie_iei_ssc_mode = 0xA; + const static uint8_t ie_iei_capability_5gsm = 0x28; + const static uint8_t ie_iei_maximum_number_of_supported_packet_filters = 0x55; + const static uint8_t ie_iei_always_on_pdu_session_requested = 0xB; + const static uint8_t ie_iei_sm_pdu_dn_request_container = 0x39; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + const static uint8_t ie_iei_ip_header_compression_configuration = 0x66; + const static uint8_t ie_iei_ds_tt__ethernet_port_mac_address = 0x6E; + const static uint8_t ie_iei_ue_ds_tt_residence_time = 0x6F; + const static uint8_t ie_iei_port_management_information_container = 0x74; + const static uint8_t ie_iei_ethernet_header_compression_configuration = 0x1F; + const static uint8_t ie_iei_suggested_interface_identifier = 0x29; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_establishment_request_t + +/* + * Message: PDU session establishment accept. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_establishment_accept_t +{ +public: + // Mandatory fields + pdu_session_type_t selected_pdu_session_type; + ssc_mode_t selected_ssc_mode; + qo_s_rules_t authorized__qo_s_rules; + session_ambr_t session_ambr; + + // Optional fields + bool cause_5gsm_present = false; + bool pdu_address_present = false; + bool rq_timer_value_present = false; + bool s_nssai_present = false; + bool always_on_pdu_session_indication_present = false; + bool mapped_eps_bearer_contexts_present = false; + bool eap_message_present = false; + bool authorized__qo_s_flow_descriptions_present = false; + bool extended_protocol_configuration_options_present = false; + bool dnn_present = false; + bool network_feature_support_5gsm_present = false; + bool serving_plmn_rate_control_present = false; + bool atsss_container_present = false; + bool control_plane_only_indication_present = false; + bool ip_header_compression_configuration_present = false; + bool ethernet_header_compression_configuration_present = false; + + cause_5gsm_t cause_5gsm; + pdu_address_t pdu_address; + gprs_timer_t rq_timer_value; + s_nssai_t s_nssai; + always_on_pdu_session_indication_t always_on_pdu_session_indication; + mapped_eps_bearer_contexts_t mapped_eps_bearer_contexts; + eap_message_t eap_message; + qo_s_flow_descriptions_t authorized__qo_s_flow_descriptions; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + dnn_t dnn; + network_feature_support_5gsm_t network_feature_support_5gsm; + serving_plmn_rate_control_t serving_plmn_rate_control; + atsss_container_t atsss_container; + control_plane_only_indication_t control_plane_only_indication; + ip_header_compression_configuration_t ip_header_compression_configuration; + ethernet_header_compression_configuration_t ethernet_header_compression_configuration; + + const static uint8_t ie_iei_cause_5gsm = 0x59; + const static uint8_t ie_iei_pdu_address = 0x29; + const static uint8_t ie_iei_rq_timer_value = 0x56; + const static uint8_t ie_iei_s_nssai = 0x22; + const static uint8_t ie_iei_always_on_pdu_session_indication = 0x8; + const static uint8_t ie_iei_mapped_eps_bearer_contexts = 0x75; + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_authorized__qo_s_flow_descriptions = 0x79; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + const static uint8_t ie_iei_dnn = 0x25; + const static uint8_t ie_iei_network_feature_support_5gsm = 0x17; + const static uint8_t ie_iei_serving_plmn_rate_control = 0x18; + const static uint8_t ie_iei_atsss_container = 0x77; + const static uint8_t ie_iei_control_plane_only_indication = 0xC; + const static uint8_t ie_iei_ip_header_compression_configuration = 0x66; + const static uint8_t ie_iei_ethernet_header_compression_configuration = 0x1F; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_establishment_accept_t + +/* + * Message: PDU session establishment reject. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_establishment_reject_t +{ +public: + // Mandatory fields + cause_5gsm_t cause_5gsm; + + // Optional fields + bool back_off_timer_value_present = false; + bool allowed_ssc_mode_present = false; + bool eap_message_present = false; + bool congestion_re_attempt_indicator_5gsm_present = false; + bool extended_protocol_configuration_options_present = false; + bool re_attempt_indicator_present = false; + + gprs_timer_3_t back_off_timer_value; + allowed_ssc_mode_t allowed_ssc_mode; + eap_message_t eap_message; + congestion_re_attempt_indicator_5gsm_t congestion_re_attempt_indicator_5gsm; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + re_attempt_indicator_t re_attempt_indicator; + + const static uint8_t ie_iei_back_off_timer_value = 0x37; + const static uint8_t ie_iei_allowed_ssc_mode = 0xF; + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_congestion_re_attempt_indicator_5gsm = 0x61; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + const static uint8_t ie_iei_re_attempt_indicator = 0x1D; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_establishment_reject_t + +/* + * Message: PDU session authentication command. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_authentication_command_t +{ +public: + // Mandatory fields + eap_message_t eap_message; + + // Optional fields + bool extended_protocol_configuration_options_present = false; + + extended_protocol_configuration_options_t extended_protocol_configuration_options; + + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_authentication_command_t + +/* + * Message: PDU session authentication complete. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_authentication_complete_t +{ +public: + // Mandatory fields + eap_message_t eap_message; + + // Optional fields + bool extended_protocol_configuration_options_present = false; + + extended_protocol_configuration_options_t extended_protocol_configuration_options; + + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_authentication_complete_t + +/* + * Message: PDU session authentication result. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_authentication_result_t +{ +public: + // Mandatory fields + + // Optional fields + bool eap_message_present = false; + bool extended_protocol_configuration_options_present = false; + + eap_message_t eap_message; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_authentication_result_t + +/* + * Message: PDU session modification request. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_modification_request_t +{ +public: + // Mandatory fields + + // Optional fields + bool capability_5gsm_present = false; + bool cause_5gsm_present = false; + bool maximum_number_of_supported_packet_filters_present = false; + bool always_on_pdu_session_requested_present = false; + bool integrity_protection_maximum_data_rate_present = false; + bool requested__qo_s_rules_present = false; + bool requested__qo_s_flow_descriptions_present = false; + bool mapped_eps_bearer_contexts_present = false; + bool extended_protocol_configuration_options_present = false; + bool port_management_information_container_present = false; + bool ip_header_compression_configuration_present = false; + bool ethernet_header_compression_configuration_present = false; + + capability_5gsm_t capability_5gsm; + cause_5gsm_t cause_5gsm; + maximum_number_of_supported_packet_filters_t maximum_number_of_supported_packet_filters; + always_on_pdu_session_requested_t always_on_pdu_session_requested; + integrity_protection_maximum_data_rate_t integrity_protection_maximum_data_rate; + qo_s_rules_t requested__qo_s_rules; + qo_s_flow_descriptions_t requested__qo_s_flow_descriptions; + mapped_eps_bearer_contexts_t mapped_eps_bearer_contexts; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + port_management_information_container_t port_management_information_container; + ip_header_compression_configuration_t ip_header_compression_configuration; + ethernet_header_compression_configuration_t ethernet_header_compression_configuration; + + const static uint8_t ie_iei_capability_5gsm = 0x28; + const static uint8_t ie_iei_cause_5gsm = 0x59; + const static uint8_t ie_iei_maximum_number_of_supported_packet_filters = 0x55; + const static uint8_t ie_iei_always_on_pdu_session_requested = 0xB; + const static uint8_t ie_iei_integrity_protection_maximum_data_rate = 0x13; + const static uint8_t ie_iei_requested__qo_s_rules = 0x7A; + const static uint8_t ie_iei_requested__qo_s_flow_descriptions = 0x79; + const static uint8_t ie_iei_mapped_eps_bearer_contexts = 0x75; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + const static uint8_t ie_iei_port_management_information_container = 0x74; + const static uint8_t ie_iei_ip_header_compression_configuration = 0x66; + const static uint8_t ie_iei_ethernet_header_compression_configuration = 0x1F; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_modification_request_t + +/* + * Message: PDU session modification reject. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_modification_reject_t +{ +public: + // Mandatory fields + cause_5gsm_t cause_5gsm; + + // Optional fields + bool back_off_timer_value_present = false; + bool congestion_re_attempt_indicator_5gsm_present = false; + bool extended_protocol_configuration_options_present = false; + bool re_attempt_indicator_present = false; + + gprs_timer_3_t back_off_timer_value; + congestion_re_attempt_indicator_5gsm_t congestion_re_attempt_indicator_5gsm; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + re_attempt_indicator_t re_attempt_indicator; + + const static uint8_t ie_iei_back_off_timer_value = 0x37; + const static uint8_t ie_iei_congestion_re_attempt_indicator_5gsm = 0x61; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + const static uint8_t ie_iei_re_attempt_indicator = 0x1D; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_modification_reject_t + +/* + * Message: PDU session modification command. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_modification_command_t +{ +public: + // Mandatory fields + + // Optional fields + bool cause_5gsm_present = false; + bool session_ambr_present = false; + bool rq_timer_value_present = false; + bool always_on_pdu_session_indication_present = false; + bool authorized__qo_s_rules_present = false; + bool mapped_eps_bearer_contexts_present = false; + bool authorized__qo_s_flow_descriptions_present = false; + bool extended_protocol_configuration_options_present = false; + bool atsss_container_present = false; + bool ip_header_compression_configuration_present = false; + bool port_management_information_container_present = false; + bool serving_plmn_rate_control_present = false; + bool ethernet_header_compression_configuration_present = false; + + cause_5gsm_t cause_5gsm; + session_ambr_t session_ambr; + gprs_timer_t rq_timer_value; + always_on_pdu_session_indication_t always_on_pdu_session_indication; + qo_s_rules_t authorized__qo_s_rules; + mapped_eps_bearer_contexts_t mapped_eps_bearer_contexts; + qo_s_flow_descriptions_t authorized__qo_s_flow_descriptions; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + atsss_container_t atsss_container; + ip_header_compression_configuration_t ip_header_compression_configuration; + port_management_information_container_t port_management_information_container; + serving_plmn_rate_control_t serving_plmn_rate_control; + ethernet_header_compression_configuration_t ethernet_header_compression_configuration; + + const static uint8_t ie_iei_cause_5gsm = 0x59; + const static uint8_t ie_iei_session_ambr = 0x2A; + const static uint8_t ie_iei_rq_timer_value = 0x56; + const static uint8_t ie_iei_always_on_pdu_session_indication = 0x8; + const static uint8_t ie_iei_authorized__qo_s_rules = 0x7A; + const static uint8_t ie_iei_mapped_eps_bearer_contexts = 0x75; + const static uint8_t ie_iei_authorized__qo_s_flow_descriptions = 0x79; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + const static uint8_t ie_iei_atsss_container = 0x77; + const static uint8_t ie_iei_ip_header_compression_configuration = 0x66; + const static uint8_t ie_iei_port_management_information_container = 0x74; + const static uint8_t ie_iei_serving_plmn_rate_control = 0x1E; + const static uint8_t ie_iei_ethernet_header_compression_configuration = 0x1F; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_modification_command_t + +/* + * Message: PDU session modification complete. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_modification_complete_t +{ +public: + // Mandatory fields + + // Optional fields + bool extended_protocol_configuration_options_present = false; + bool port_management_information_container_present = false; + + extended_protocol_configuration_options_t extended_protocol_configuration_options; + port_management_information_container_t port_management_information_container; + + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + const static uint8_t ie_iei_port_management_information_container = 0x74; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_modification_complete_t + +/* + * Message: PDU session modification command reject. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_modification_command_reject_t +{ +public: + // Mandatory fields + cause_5gsm_t cause_5gsm; + + // Optional fields + bool extended_protocol_configuration_options_present = false; + + extended_protocol_configuration_options_t extended_protocol_configuration_options; + + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_modification_command_reject_t + +/* + * Message: PDU session release request. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_release_request_t +{ +public: + // Mandatory fields + + // Optional fields + bool cause_5gsm_present = false; + bool extended_protocol_configuration_options_present = false; + + cause_5gsm_t cause_5gsm; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + + const static uint8_t ie_iei_cause_5gsm = 0x59; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_release_request_t + +/* + * Message: PDU session release reject. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_release_reject_t +{ +public: + // Mandatory fields + cause_5gsm_t cause_5gsm; + + // Optional fields + bool extended_protocol_configuration_options_present = false; + + extended_protocol_configuration_options_t extended_protocol_configuration_options; + + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_release_reject_t + +/* + * Message: PDU session release command. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_release_command_t +{ +public: + // Mandatory fields + cause_5gsm_t cause_5gsm; + + // Optional fields + bool back_off_timer_value_present = false; + bool eap_message_present = false; + bool congestion_re_attempt_indicator_5gsm_present = false; + bool extended_protocol_configuration_options_present = false; + bool access_type_present = false; + + gprs_timer_3_t back_off_timer_value; + eap_message_t eap_message; + congestion_re_attempt_indicator_5gsm_t congestion_re_attempt_indicator_5gsm; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + access_type_t access_type; + + const static uint8_t ie_iei_back_off_timer_value = 0x37; + const static uint8_t ie_iei_eap_message = 0x78; + const static uint8_t ie_iei_congestion_re_attempt_indicator_5gsm = 0x61; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + const static uint8_t ie_iei_access_type = 0xD; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_release_command_t + +/* + * Message: PDU session release complete. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class pdu_session_release_complete_t +{ +public: + // Mandatory fields + + // Optional fields + bool cause_5gsm_present = false; + bool extended_protocol_configuration_options_present = false; + + cause_5gsm_t cause_5gsm; + extended_protocol_configuration_options_t extended_protocol_configuration_options; + + const static uint8_t ie_iei_cause_5gsm = 0x59; + const static uint8_t ie_iei_extended_protocol_configuration_options = 0x7B; + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // pdu_session_release_complete_t + +/* + * Message: Status 5GSM. + * Based on 3GPP TS 24.501 v16.7.0 + */ + +class status_5gsm_t +{ +public: + // Mandatory fields + cause_5gsm_t cause_5gsm; + + // Optional fields + +public: + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + +}; // status_5gsm_t +// Include from nas5g/infiles/nas_5g_msg.h.in + +struct msg_opts { + enum options { + registration_request = 0x41, + registration_accept = 0x42, + registration_complete = 0x43, + registration_reject = 0x44, + deregistration_request_ue_originating = 0x45, + deregistration_accept_ue_originating = 0x46, + deregistration_request_ue_terminated = 0x47, + deregistration_accept_ue_terminated = 0x48, + service_request = 0x4c, + service_reject = 0x4d, + service_accept = 0x4e, + configuration_update_command = 0x54, + configuration_update_complete = 0x55, + authentication_request = 0x56, + authentication_response = 0x57, + authentication_reject = 0x58, + authentication_failure = 0x59, + authentication_result = 0x5a, + identity_request = 0x5b, + identity_response = 0x5c, + security_mode_command = 0x5d, + security_mode_complete = 0x5e, + security_mode_reject = 0x5f, + status_5gmm = 0x64, + notification = 0x65, + notification_response = 0x66, + ul_nas_transport = 0x67, + dl_nas_transport = 0x68, + pdu_session_establishment_request = 0xc1, + pdu_session_establishment_accept = 0xc2, + pdu_session_establishment_reject = 0xc3, + pdu_session_authentication_command = 0xc5, + pdu_session_authentication_complete = 0xc6, + pdu_session_authentication_result = 0xc7, + pdu_session_modification_request = 0xc9, + pdu_session_modification_reject = 0xca, + pdu_session_modification_command = 0xcb, + pdu_session_modification_complete = 0xcc, + pdu_session_modification_command_reject = 0xcd, + pdu_session_release_request = 0xd1, + pdu_session_release_reject = 0xd2, + pdu_session_release_command = 0xd3, + pdu_session_release_complete = 0xd4, + status_5gsm = 0xd6, + nulltype = 0xff, + + } value; + const char* to_string() const + { + switch (value) { + case registration_request: + return "Registration request"; + case registration_accept: + return "Registration accept"; + case registration_complete: + return "Registration complete"; + case registration_reject: + return "Registration reject"; + case deregistration_request_ue_originating: + return "Deregistration request UE originating"; + case deregistration_accept_ue_originating: + return "Deregistration accept UE originating"; + case deregistration_request_ue_terminated: + return "Deregistration request UE terminated"; + case deregistration_accept_ue_terminated: + return "Deregistration accept UE terminated"; + case service_request: + return "Service request"; + case service_reject: + return "Service reject"; + case service_accept: + return "Service accept"; + case configuration_update_command: + return "Configuration update command"; + case configuration_update_complete: + return "Configuration update complete"; + case authentication_request: + return "Authentication request"; + case authentication_response: + return "Authentication response"; + case authentication_reject: + return "Authentication reject"; + case authentication_failure: + return "Authentication failure"; + case authentication_result: + return "Authentication result"; + case identity_request: + return "Identity request"; + case identity_response: + return "Identity response"; + case security_mode_command: + return "Security mode command"; + case security_mode_complete: + return "Security mode complete"; + case security_mode_reject: + return "Security mode reject"; + case status_5gmm: + return "Status 5GMM"; + case notification: + return "Notification"; + case notification_response: + return "Notification response"; + case ul_nas_transport: + return "UL NAS transport"; + case dl_nas_transport: + return "DL NAS transport "; + case pdu_session_establishment_request: + return "PDU session establishment request"; + case pdu_session_establishment_accept: + return "PDU session establishment accept"; + case pdu_session_establishment_reject: + return "PDU session establishment reject"; + case pdu_session_authentication_command: + return "PDU session authentication command"; + case pdu_session_authentication_complete: + return "PDU session authentication complete"; + case pdu_session_authentication_result: + return "PDU session authentication result"; + case pdu_session_modification_request: + return "PDU session modification request"; + case pdu_session_modification_reject: + return "PDU session modification reject"; + case pdu_session_modification_command: + return "PDU session modification command"; + case pdu_session_modification_complete: + return "PDU session modification complete"; + case pdu_session_modification_command_reject: + return "PDU session modification command reject"; + case pdu_session_release_request: + return "PDU session release request"; + case pdu_session_release_reject: + return "PDU session release reject"; + case pdu_session_release_command: + return "PDU session release command"; + case pdu_session_release_complete: + return "PDU session release complete"; + case status_5gsm: + return "Status 5GSM"; + default: + return "Error"; + } + } +}; + +typedef asn1::enumerated msg_types; +struct nas_5gs_hdr { + enum security_header_type_opts { + plain_5gs_nas_message, + integrity_protected, + integrity_protected_and_ciphered, + integrity_protected_with_new_5G_nas_context, + integrity_protected_and_ciphered_with_new_5G_nas_context + }; + + enum extended_protocol_discriminator_opts { + extended_protocol_discriminator_5gsm = 0x2e, + extended_protocol_discriminator_5gmm = 0x7e, + }; + + // Outer + extended_protocol_discriminator_opts extended_protocol_discriminator = extended_protocol_discriminator_5gsm; + security_header_type_opts security_header_type = plain_5gs_nas_message; + // Only valid if not plain + uint8_t sequence_number = 0xff; + uint32_t message_authentication_code = 0x00000000; + // Only valid if 5gsm type + uint8_t pdu_session_identity = 0xff; + uint8_t procedure_transaction_identity = 0xff; + // Inner + extended_protocol_discriminator_opts inner_extended_protocol_discriminator = extended_protocol_discriminator_5gsm; + security_header_type_opts inner_security_header_type = plain_5gs_nas_message; + + msg_types message_type = msg_types::options::nulltype; + + SRSASN_CODE pack(asn1::bit_ref& bref); + SRSASN_CODE pack_outer(asn1::bit_ref& bref); + SRSASN_CODE unpack(asn1::cbit_ref& bref); + SRSASN_CODE unpack_outer(asn1::cbit_ref& bref); +}; + +class nas_5gs_msg +{ +public: + nas_5gs_hdr hdr; + + SRSASN_CODE pack(unique_byte_buffer_t& buf); + SRSASN_CODE pack(std::vector buf); + SRSASN_CODE unpack(const unique_byte_buffer_t& buf); + SRSASN_CODE unpack(const std::vector buf); + SRSASN_CODE unpack_outer_hdr(const unique_byte_buffer_t& buf); + SRSASN_CODE unpack_outer_hdr(const std::vector buf); + + void set(msg_types::options e = msg_types::nulltype) { hdr.message_type = e; }; + // Getters + + registration_request_t& registration_request() + { + asn1::assert_choice_type(msg_types::options::registration_request, hdr.message_type, "registration_request"); + return *srslog::detail::any_cast(&msg_container); + } + + registration_accept_t& registration_accept() + { + asn1::assert_choice_type(msg_types::options::registration_accept, hdr.message_type, "registration_accept"); + return *srslog::detail::any_cast(&msg_container); + } + + registration_complete_t& registration_complete() + { + asn1::assert_choice_type(msg_types::options::registration_complete, hdr.message_type, "registration_complete"); + return *srslog::detail::any_cast(&msg_container); + } + + registration_reject_t& registration_reject() + { + asn1::assert_choice_type(msg_types::options::registration_reject, hdr.message_type, "registration_reject"); + return *srslog::detail::any_cast(&msg_container); + } + + deregistration_request_ue_originating_t& deregistration_request_ue_originating() + { + asn1::assert_choice_type(msg_types::options::deregistration_request_ue_originating, + hdr.message_type, + "deregistration_request_ue_originating"); + return *srslog::detail::any_cast(&msg_container); + } + + deregistration_accept_ue_originating_t& deregistration_accept_ue_originating() + { + asn1::assert_choice_type(msg_types::options::deregistration_accept_ue_originating, + hdr.message_type, + "deregistration_accept_ue_originating"); + return *srslog::detail::any_cast(&msg_container); + } + + deregistration_request_ue_terminated_t& deregistration_request_ue_terminated() + { + asn1::assert_choice_type(msg_types::options::deregistration_request_ue_terminated, + hdr.message_type, + "deregistration_request_ue_terminated"); + return *srslog::detail::any_cast(&msg_container); + } + + deregistration_accept_ue_terminated_t& deregistration_accept_ue_terminated() + { + asn1::assert_choice_type(msg_types::options::deregistration_accept_ue_terminated, + hdr.message_type, + "deregistration_accept_ue_terminated"); + return *srslog::detail::any_cast(&msg_container); + } + + service_request_t& service_request() + { + asn1::assert_choice_type(msg_types::options::service_request, hdr.message_type, "service_request"); + return *srslog::detail::any_cast(&msg_container); + } + + service_reject_t& service_reject() + { + asn1::assert_choice_type(msg_types::options::service_reject, hdr.message_type, "service_reject"); + return *srslog::detail::any_cast(&msg_container); + } + + service_accept_t& service_accept() + { + asn1::assert_choice_type(msg_types::options::service_accept, hdr.message_type, "service_accept"); + return *srslog::detail::any_cast(&msg_container); + } + + configuration_update_command_t& configuration_update_command() + { + asn1::assert_choice_type( + msg_types::options::configuration_update_command, hdr.message_type, "configuration_update_command"); + return *srslog::detail::any_cast(&msg_container); + } + + configuration_update_complete_t& configuration_update_complete() + { + asn1::assert_choice_type( + msg_types::options::configuration_update_complete, hdr.message_type, "configuration_update_complete"); + return *srslog::detail::any_cast(&msg_container); + } + + authentication_request_t& authentication_request() + { + asn1::assert_choice_type(msg_types::options::authentication_request, hdr.message_type, "authentication_request"); + return *srslog::detail::any_cast(&msg_container); + } + + authentication_response_t& authentication_response() + { + asn1::assert_choice_type(msg_types::options::authentication_response, hdr.message_type, "authentication_response"); + return *srslog::detail::any_cast(&msg_container); + } + + authentication_reject_t& authentication_reject() + { + asn1::assert_choice_type(msg_types::options::authentication_reject, hdr.message_type, "authentication_reject"); + return *srslog::detail::any_cast(&msg_container); + } + + authentication_failure_t& authentication_failure() + { + asn1::assert_choice_type(msg_types::options::authentication_failure, hdr.message_type, "authentication_failure"); + return *srslog::detail::any_cast(&msg_container); + } + + authentication_result_t& authentication_result() + { + asn1::assert_choice_type(msg_types::options::authentication_result, hdr.message_type, "authentication_result"); + return *srslog::detail::any_cast(&msg_container); + } + + identity_request_t& identity_request() + { + asn1::assert_choice_type(msg_types::options::identity_request, hdr.message_type, "identity_request"); + return *srslog::detail::any_cast(&msg_container); + } + + identity_response_t& identity_response() + { + asn1::assert_choice_type(msg_types::options::identity_response, hdr.message_type, "identity_response"); + return *srslog::detail::any_cast(&msg_container); + } + + security_mode_command_t& security_mode_command() + { + asn1::assert_choice_type(msg_types::options::security_mode_command, hdr.message_type, "security_mode_command"); + return *srslog::detail::any_cast(&msg_container); + } + + security_mode_complete_t& security_mode_complete() + { + asn1::assert_choice_type(msg_types::options::security_mode_complete, hdr.message_type, "security_mode_complete"); + return *srslog::detail::any_cast(&msg_container); + } + + security_mode_reject_t& security_mode_reject() + { + asn1::assert_choice_type(msg_types::options::security_mode_reject, hdr.message_type, "security_mode_reject"); + return *srslog::detail::any_cast(&msg_container); + } + + status_5gmm_t& status_5gmm() + { + asn1::assert_choice_type(msg_types::options::status_5gmm, hdr.message_type, "status_5gmm"); + return *srslog::detail::any_cast(&msg_container); + } + + notification_t& notification() + { + asn1::assert_choice_type(msg_types::options::notification, hdr.message_type, "notification"); + return *srslog::detail::any_cast(&msg_container); + } + + notification_response_t& notification_response() + { + asn1::assert_choice_type(msg_types::options::notification_response, hdr.message_type, "notification_response"); + return *srslog::detail::any_cast(&msg_container); + } + + ul_nas_transport_t& ul_nas_transport() + { + asn1::assert_choice_type(msg_types::options::ul_nas_transport, hdr.message_type, "ul_nas_transport"); + return *srslog::detail::any_cast(&msg_container); + } + + dl_nas_transport_t& dl_nas_transport() + { + asn1::assert_choice_type(msg_types::options::dl_nas_transport, hdr.message_type, "dl_nas_transport"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_establishment_request_t& pdu_session_establishment_request() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_establishment_request, hdr.message_type, "pdu_session_establishment_request"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_establishment_accept_t& pdu_session_establishment_accept() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_establishment_accept, hdr.message_type, "pdu_session_establishment_accept"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_establishment_reject_t& pdu_session_establishment_reject() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_establishment_reject, hdr.message_type, "pdu_session_establishment_reject"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_authentication_command_t& pdu_session_authentication_command() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_authentication_command, hdr.message_type, "pdu_session_authentication_command"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_authentication_complete_t& pdu_session_authentication_complete() + { + asn1::assert_choice_type(msg_types::options::pdu_session_authentication_complete, + hdr.message_type, + "pdu_session_authentication_complete"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_authentication_result_t& pdu_session_authentication_result() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_authentication_result, hdr.message_type, "pdu_session_authentication_result"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_modification_request_t& pdu_session_modification_request() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_modification_request, hdr.message_type, "pdu_session_modification_request"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_modification_reject_t& pdu_session_modification_reject() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_modification_reject, hdr.message_type, "pdu_session_modification_reject"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_modification_command_t& pdu_session_modification_command() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_modification_command, hdr.message_type, "pdu_session_modification_command"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_modification_complete_t& pdu_session_modification_complete() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_modification_complete, hdr.message_type, "pdu_session_modification_complete"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_modification_command_reject_t& pdu_session_modification_command_reject() + { + asn1::assert_choice_type(msg_types::options::pdu_session_modification_command_reject, + hdr.message_type, + "pdu_session_modification_command_reject"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_release_request_t& pdu_session_release_request() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_release_request, hdr.message_type, "pdu_session_release_request"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_release_reject_t& pdu_session_release_reject() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_release_reject, hdr.message_type, "pdu_session_release_reject"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_release_command_t& pdu_session_release_command() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_release_command, hdr.message_type, "pdu_session_release_command"); + return *srslog::detail::any_cast(&msg_container); + } + + pdu_session_release_complete_t& pdu_session_release_complete() + { + asn1::assert_choice_type( + msg_types::options::pdu_session_release_complete, hdr.message_type, "pdu_session_release_complete"); + return *srslog::detail::any_cast(&msg_container); + } + + status_5gsm_t& status_5gsm() + { + asn1::assert_choice_type(msg_types::options::status_5gsm, hdr.message_type, "status_5gsm"); + return *srslog::detail::any_cast(&msg_container); + } + + // Setters + + registration_request_t& set_registration_request() + { + set(msg_types::options::registration_request); + msg_container = srslog::detail::any{registration_request_t()}; + return *srslog::detail::any_cast(&msg_container); + } + registration_accept_t& set_registration_accept() + { + set(msg_types::options::registration_accept); + msg_container = srslog::detail::any{registration_accept_t()}; + return *srslog::detail::any_cast(&msg_container); + } + registration_complete_t& set_registration_complete() + { + set(msg_types::options::registration_complete); + msg_container = srslog::detail::any{registration_complete_t()}; + return *srslog::detail::any_cast(&msg_container); + } + registration_reject_t& set_registration_reject() + { + set(msg_types::options::registration_reject); + msg_container = srslog::detail::any{registration_reject_t()}; + return *srslog::detail::any_cast(&msg_container); + } + deregistration_request_ue_originating_t& set_deregistration_request_ue_originating() + { + set(msg_types::options::deregistration_request_ue_originating); + msg_container = srslog::detail::any{deregistration_request_ue_originating_t()}; + return *srslog::detail::any_cast(&msg_container); + } + deregistration_accept_ue_originating_t& set_deregistration_accept_ue_originating() + { + set(msg_types::options::deregistration_accept_ue_originating); + msg_container = srslog::detail::any{deregistration_accept_ue_originating_t()}; + return *srslog::detail::any_cast(&msg_container); + } + deregistration_request_ue_terminated_t& set_deregistration_request_ue_terminated() + { + set(msg_types::options::deregistration_request_ue_terminated); + msg_container = srslog::detail::any{deregistration_request_ue_terminated_t()}; + return *srslog::detail::any_cast(&msg_container); + } + deregistration_accept_ue_terminated_t& set_deregistration_accept_ue_terminated() + { + set(msg_types::options::deregistration_accept_ue_terminated); + msg_container = srslog::detail::any{deregistration_accept_ue_terminated_t()}; + return *srslog::detail::any_cast(&msg_container); + } + service_request_t& set_service_request() + { + set(msg_types::options::service_request); + msg_container = srslog::detail::any{service_request_t()}; + return *srslog::detail::any_cast(&msg_container); + } + service_reject_t& set_service_reject() + { + set(msg_types::options::service_reject); + msg_container = srslog::detail::any{service_reject_t()}; + return *srslog::detail::any_cast(&msg_container); + } + service_accept_t& set_service_accept() + { + set(msg_types::options::service_accept); + msg_container = srslog::detail::any{service_accept_t()}; + return *srslog::detail::any_cast(&msg_container); + } + configuration_update_command_t& set_configuration_update_command() + { + set(msg_types::options::configuration_update_command); + msg_container = srslog::detail::any{configuration_update_command_t()}; + return *srslog::detail::any_cast(&msg_container); + } + configuration_update_complete_t& set_configuration_update_complete() + { + set(msg_types::options::configuration_update_complete); + msg_container = srslog::detail::any{configuration_update_complete_t()}; + return *srslog::detail::any_cast(&msg_container); + } + authentication_request_t& set_authentication_request() + { + set(msg_types::options::authentication_request); + msg_container = srslog::detail::any{authentication_request_t()}; + return *srslog::detail::any_cast(&msg_container); + } + authentication_response_t& set_authentication_response() + { + set(msg_types::options::authentication_response); + msg_container = srslog::detail::any{authentication_response_t()}; + return *srslog::detail::any_cast(&msg_container); + } + authentication_reject_t& set_authentication_reject() + { + set(msg_types::options::authentication_reject); + msg_container = srslog::detail::any{authentication_reject_t()}; + return *srslog::detail::any_cast(&msg_container); + } + authentication_failure_t& set_authentication_failure() + { + set(msg_types::options::authentication_failure); + msg_container = srslog::detail::any{authentication_failure_t()}; + return *srslog::detail::any_cast(&msg_container); + } + authentication_result_t& set_authentication_result() + { + set(msg_types::options::authentication_result); + msg_container = srslog::detail::any{authentication_result_t()}; + return *srslog::detail::any_cast(&msg_container); + } + identity_request_t& set_identity_request() + { + set(msg_types::options::identity_request); + msg_container = srslog::detail::any{identity_request_t()}; + return *srslog::detail::any_cast(&msg_container); + } + identity_response_t& set_identity_response() + { + set(msg_types::options::identity_response); + msg_container = srslog::detail::any{identity_response_t()}; + return *srslog::detail::any_cast(&msg_container); + } + security_mode_command_t& set_security_mode_command() + { + set(msg_types::options::security_mode_command); + msg_container = srslog::detail::any{security_mode_command_t()}; + return *srslog::detail::any_cast(&msg_container); + } + security_mode_complete_t& set_security_mode_complete() + { + set(msg_types::options::security_mode_complete); + msg_container = srslog::detail::any{security_mode_complete_t()}; + return *srslog::detail::any_cast(&msg_container); + } + security_mode_reject_t& set_security_mode_reject() + { + set(msg_types::options::security_mode_reject); + msg_container = srslog::detail::any{security_mode_reject_t()}; + return *srslog::detail::any_cast(&msg_container); + } + status_5gmm_t& set_status_5gmm() + { + set(msg_types::options::status_5gmm); + msg_container = srslog::detail::any{status_5gmm_t()}; + return *srslog::detail::any_cast(&msg_container); + } + notification_t& set_notification() + { + set(msg_types::options::notification); + msg_container = srslog::detail::any{notification_t()}; + return *srslog::detail::any_cast(&msg_container); + } + notification_response_t& set_notification_response() + { + set(msg_types::options::notification_response); + msg_container = srslog::detail::any{notification_response_t()}; + return *srslog::detail::any_cast(&msg_container); + } + ul_nas_transport_t& set_ul_nas_transport() + { + set(msg_types::options::ul_nas_transport); + msg_container = srslog::detail::any{ul_nas_transport_t()}; + return *srslog::detail::any_cast(&msg_container); + } + dl_nas_transport_t& set_dl_nas_transport() + { + set(msg_types::options::dl_nas_transport); + msg_container = srslog::detail::any{dl_nas_transport_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_establishment_request_t& set_pdu_session_establishment_request() + { + set(msg_types::options::pdu_session_establishment_request); + msg_container = srslog::detail::any{pdu_session_establishment_request_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_establishment_accept_t& set_pdu_session_establishment_accept() + { + set(msg_types::options::pdu_session_establishment_accept); + msg_container = srslog::detail::any{pdu_session_establishment_accept_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_establishment_reject_t& set_pdu_session_establishment_reject() + { + set(msg_types::options::pdu_session_establishment_reject); + msg_container = srslog::detail::any{pdu_session_establishment_reject_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_authentication_command_t& set_pdu_session_authentication_command() + { + set(msg_types::options::pdu_session_authentication_command); + msg_container = srslog::detail::any{pdu_session_authentication_command_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_authentication_complete_t& set_pdu_session_authentication_complete() + { + set(msg_types::options::pdu_session_authentication_complete); + msg_container = srslog::detail::any{pdu_session_authentication_complete_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_authentication_result_t& set_pdu_session_authentication_result() + { + set(msg_types::options::pdu_session_authentication_result); + msg_container = srslog::detail::any{pdu_session_authentication_result_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_modification_request_t& set_pdu_session_modification_request() + { + set(msg_types::options::pdu_session_modification_request); + msg_container = srslog::detail::any{pdu_session_modification_request_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_modification_reject_t& set_pdu_session_modification_reject() + { + set(msg_types::options::pdu_session_modification_reject); + msg_container = srslog::detail::any{pdu_session_modification_reject_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_modification_command_t& set_pdu_session_modification_command() + { + set(msg_types::options::pdu_session_modification_command); + msg_container = srslog::detail::any{pdu_session_modification_command_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_modification_complete_t& set_pdu_session_modification_complete() + { + set(msg_types::options::pdu_session_modification_complete); + msg_container = srslog::detail::any{pdu_session_modification_complete_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_modification_command_reject_t& set_pdu_session_modification_command_reject() + { + set(msg_types::options::pdu_session_modification_command_reject); + msg_container = srslog::detail::any{pdu_session_modification_command_reject_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_release_request_t& set_pdu_session_release_request() + { + set(msg_types::options::pdu_session_release_request); + msg_container = srslog::detail::any{pdu_session_release_request_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_release_reject_t& set_pdu_session_release_reject() + { + set(msg_types::options::pdu_session_release_reject); + msg_container = srslog::detail::any{pdu_session_release_reject_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_release_command_t& set_pdu_session_release_command() + { + set(msg_types::options::pdu_session_release_command); + msg_container = srslog::detail::any{pdu_session_release_command_t()}; + return *srslog::detail::any_cast(&msg_container); + } + pdu_session_release_complete_t& set_pdu_session_release_complete() + { + set(msg_types::options::pdu_session_release_complete); + msg_container = srslog::detail::any{pdu_session_release_complete_t()}; + return *srslog::detail::any_cast(&msg_container); + } + status_5gsm_t& set_status_5gsm() + { + set(msg_types::options::status_5gsm); + msg_container = srslog::detail::any{status_5gsm_t()}; + return *srslog::detail::any_cast(&msg_container); + } + +private: + SRSASN_CODE unpack(asn1::cbit_ref& bref); + SRSASN_CODE pack(asn1::bit_ref& bref); + srslog::detail::any msg_container; +}; +} // namespace nas_5g +} // namespace srsran +#endif diff --git a/lib/include/srsran/asn1/nas_5g_utils.h b/lib/include/srsran/asn1/nas_5g_utils.h new file mode 100644 index 000000000..b8ce86157 --- /dev/null +++ b/lib/include/srsran/asn1/nas_5g_utils.h @@ -0,0 +1,87 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_NAS_5G_UTILS_H +#define SRSRAN_NAS_5G_UTILS_H + +#include "srsran/asn1/asn1_utils.h" +#include "srsran/common/byte_buffer.h" +#include "srsran/config.h" + +using namespace asn1; +namespace srsran { +namespace nas_5g { + +struct ecies_scheme_profile_a_out { + uint8_t ecc_ephemeral_key[33]; + std::vector ciphertext; + uint8_t mac_tag[8]; +}; + +struct ecies_scheme_profile_b_out { + uint8_t ecc_ephemeral_key[32]; + std::vector ciphertext; + uint8_t mac_tag[8]; +}; + +template +SRSASN_CODE unpack_enum(asn1::cbit_ref& bref, Enum* e) +{ + uint32_t tmp = {}; + HANDLE_CODE(bref.unpack(tmp, bl)); + *e = static_cast(tmp); + return SRSASN_SUCCESS; +} + +template +SRSASN_CODE pack_enum(asn1::bit_ref& bref, Enum e) +{ + uint32_t tmp = static_cast(e); + HANDLE_CODE(bref.pack(tmp, bl)); + return SRSASN_SUCCESS; +} + +template +class nas_enumerated : public EnumType +{ +public: + static const uint32_t bit_length = bit_length_; + + nas_enumerated() {} + nas_enumerated(typename EnumType::options o) { EnumType::value = o; } + SRSASN_CODE pack(asn1::bit_ref& bref) const + { + uint32_t tmp = static_cast(EnumType::value); + HANDLE_CODE(bref.pack(tmp, bit_length)); + return SRSASN_SUCCESS; + } + SRSASN_CODE unpack(asn1::cbit_ref& bref) + { + uint32_t tmp = {}; + HANDLE_CODE(bref.unpack(tmp, bit_length)); + *this = static_cast(tmp); + return SRSASN_SUCCESS; + } + EnumType& operator=(EnumType v) + { + EnumType::value = v; + return *this; + } + operator typename EnumType::options() const { return EnumType::value; } +}; + +SRSASN_CODE unpack_mcc_mnc(uint8_t* mcc_bytes, uint8_t* mnc_bytes, asn1::cbit_ref& bref); +SRSASN_CODE pack_mcc_mnc(uint8_t* mcc_bytes, uint8_t* mnc_bytes, asn1::bit_ref& bref); + +} // namespace nas_5g +} // namespace srsran +#endif // MANUAL_H \ No newline at end of file diff --git a/lib/src/asn1/CMakeLists.txt b/lib/src/asn1/CMakeLists.txt index d99b61f27..ba164a56f 100644 --- a/lib/src/asn1/CMakeLists.txt +++ b/lib/src/asn1/CMakeLists.txt @@ -61,5 +61,10 @@ add_library(ngap_nr_asn1 STATIC ngap.cc) target_compile_options(ngap_nr_asn1 PRIVATE "-Os") target_link_libraries(ngap_nr_asn1 asn1_utils srsran_common) INSTALL(TARGETS ngap_nr_asn1 DESTINATION ${LIBRARY_DIR}) +# NAS 5G +add_library(nas_5g_msg STATIC nas_5g_msg.cc nas_5g_ies.cc nas_5g_utils.cc) +target_compile_options(nas_5g_msg PRIVATE "-Os") +target_link_libraries(nas_5g_msg asn1_utils srsran_common) +INSTALL(TARGETS nas_5g_msg DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/asn1/nas_5g_ies.cc b/lib/src/asn1/nas_5g_ies.cc new file mode 100644 index 000000000..b90265f61 --- /dev/null +++ b/lib/src/asn1/nas_5g_ies.cc @@ -0,0 +1,4359 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ +#include "srsran/asn1/nas_5g_ies.h" + +#include "srsran/asn1/asn1_utils.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/common.h" +#include "srsran/config.h" + +#include +#include +#include + +namespace srsran { +namespace nas_5g { + +using namespace asn1; +// IE: 5GS registration type +// Reference: 9.11.3.7 +SRSASN_CODE registration_type_5gs_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(follow_on_request_bit.pack(bref)); + HANDLE_CODE(registration_type.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GS registration type +// Reference: 9.11.3.7 +SRSASN_CODE registration_type_5gs_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(follow_on_request_bit.unpack(bref)); + HANDLE_CODE(registration_type.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: key set identifier +// Reference: 9.11.3.32 +SRSASN_CODE key_set_identifier_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(security_context_flag.pack(bref)); + HANDLE_CODE(nas_key_set_identifier.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: key set identifier +// Reference: 9.11.3.32 +SRSASN_CODE key_set_identifier_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(security_context_flag.unpack(bref)); + HANDLE_CODE(nas_key_set_identifier.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GS mobile identity +// Reference: 9.11.3.4 +SRSASN_CODE mobile_identity_5gs_t::pack(asn1::bit_ref& bref) +{ + // Length + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + asn1::bit_ref bref_tmp = bref; + switch (type_) { + case identity_types::no_identity: + HANDLE_CODE(type_.pack(bref)); + break; + case identity_types::suci: { + suci_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->pack(bref, bref_tmp)); + break; + } + case identity_types::guti_5g: { + guti_5g_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->pack(bref, bref_tmp)); + break; + } + case identity_types::imei: { + imei_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->pack(bref, bref_tmp)); + break; + } + case identity_types::s_tmsi_5g: { + s_tmsi_5g_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->pack(bref, bref_tmp)); + break; + } + case identity_types::imeisv: { + imeisv_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->pack(bref, bref_tmp)); + break; + } + case identity_types::mac_address: { + mac_address_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->pack(bref, bref_tmp)); + break; + } + case identity_types::eui_64: { + eui_64_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->pack(bref, bref_tmp)); + break; + } + default: + log_invalid_choice_id(type_, "5G NAS ID TYPE"); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + uint16_t length = (uint16_t)((bref.distance(bref_length) / 8) - 2); + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: 5GS mobile identity +// Reference: 9.11.3.4 +SRSASN_CODE mobile_identity_5gs_t::unpack(asn1::cbit_ref& bref) +{ + // Length + HANDLE_CODE(bref.unpack(length, 16)); + uint8_t tmp; + HANDLE_CODE(bref.unpack(tmp, 5)); + identity_types e = identity_types::no_identity; + HANDLE_CODE(e.unpack(bref)); + set(e); + switch (type_) { + case identity_types::no_identity: + break; + case identity_types::suci: { + choice_container = srslog::detail::any{suci_s()}; + suci_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->unpack(bref, tmp, length)); + break; + } + case identity_types::guti_5g: { + choice_container = srslog::detail::any{guti_5g_s()}; + guti_5g_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->unpack(bref, tmp, length)); + break; + } + case identity_types::imei: { + choice_container = srslog::detail::any{imei_s()}; + imei_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->unpack(bref, tmp, length)); + break; + } + case identity_types::s_tmsi_5g: { + choice_container = srslog::detail::any{s_tmsi_5g_s()}; + s_tmsi_5g_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->unpack(bref, tmp, length)); + break; + } + case identity_types::imeisv: { + choice_container = srslog::detail::any{imeisv_s()}; + imeisv_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->unpack(bref, tmp, length)); + break; + } + case identity_types::mac_address: { + choice_container = srslog::detail::any{mac_address_s()}; + mac_address_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->unpack(bref, tmp, length)); + break; + } + case identity_types::eui_64: { + choice_container = srslog::detail::any{eui_64_s()}; + eui_64_s* choice = srslog::detail::any_cast(&choice_container); + HANDLE_CODE(choice->unpack(bref, tmp, length)); + break; + } + default: + log_invalid_choice_id(type_, "5G NAS ID TYPE"); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + return SRSASN_SUCCESS; +} + +const char* mobile_identity_5gs_t::identity_types_::to_string() +{ + switch (value) { + case identity_types_::no_identity: + return "No identity"; + case identity_types_::suci: + return "SUCI"; + case identity_types_::guti_5g: + return "5G-GUTI"; + case identity_types_::imei: + return "IMEI"; + case identity_types_::s_tmsi_5g: + return "5G-S-TMSI"; + case identity_types_::imeisv: + return "IMEISV"; + case identity_types_::mac_address: + return "MAC address"; + case identity_types_::eui_64: + return "EUI-64"; + default: + return "Invalid Choice"; + } +} +SRSASN_CODE mobile_identity_5gs_t::suci_s::pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp) +{ + HANDLE_CODE(bref.advance_bits(1)); + HANDLE_CODE(supi_format.pack(bref)); + HANDLE_CODE(bref.advance_bits(1)); + + // Pack Type of identity + uint8_t type = static_cast(mobile_identity_5gs_t::identity_types_::options::suci); + HANDLE_CODE(bref.pack(type, 3)); + + HANDLE_CODE(pack_mcc_mnc(mcc.data(), mnc.data(), bref)); + HANDLE_CODE(bref.pack(routing_indicator[1], 4)); + HANDLE_CODE(bref.pack(routing_indicator[0], 4)); + HANDLE_CODE(bref.pack(routing_indicator[3], 4)); + HANDLE_CODE(bref.pack(routing_indicator[2], 4)); + // Spare + HANDLE_CODE(bref.advance_bits(4)); + HANDLE_CODE(protection_scheme_id.pack(bref)); + HANDLE_CODE(bref.pack(home_network_public_key_identifier, 8)); + HANDLE_CODE(bref.pack_bytes(scheme_output.data(), scheme_output.size())); + return SRSASN_SUCCESS; +} +SRSASN_CODE mobile_identity_5gs_t::suci_s::unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length) +{ + supi_format = static_cast(tmp >> 1 & 0b111); + HANDLE_CODE(unpack_mcc_mnc(mcc.data(), mnc.data(), bref)); + HANDLE_CODE(bref.unpack(routing_indicator[1], 4)); + HANDLE_CODE(bref.unpack(routing_indicator[0], 4)); + HANDLE_CODE(bref.unpack(routing_indicator[3], 4)); + HANDLE_CODE(bref.unpack(routing_indicator[2], 4)); + // Spare + HANDLE_CODE(bref.advance_bits(4)); + HANDLE_CODE(protection_scheme_id.unpack(bref)); + HANDLE_CODE(bref.unpack(home_network_public_key_identifier, 8)); + scheme_output.resize(length - 8); + HANDLE_CODE(bref.unpack_bytes(scheme_output.data(), length - 8)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE mobile_identity_5gs_t::guti_5g_s::pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp) +{ + HANDLE_CODE(bref.pack(0x0, 5)); + // Pack Type of identity + uint8_t type = static_cast(mobile_identity_5gs_t::identity_types_::options::guti_5g); + HANDLE_CODE(bref.pack(type, 3)); + + HANDLE_CODE(pack_mcc_mnc(mcc.data(), mnc.data(), bref)); + HANDLE_CODE(bref.pack(amf_region_id, 8)); + HANDLE_CODE(bref.pack(amf_set_id, 10)); + HANDLE_CODE(bref.pack(amf_pointer, 6)); + HANDLE_CODE(bref.pack(tmsi_5g, 4 * 8)); + return SRSASN_SUCCESS; +} +SRSASN_CODE mobile_identity_5gs_t::guti_5g_s::unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length) +{ + HANDLE_CODE(unpack_mcc_mnc(mcc.data(), mnc.data(), bref)); + HANDLE_CODE(bref.unpack(amf_region_id, 8)); + HANDLE_CODE(bref.unpack(amf_set_id, 10)); + HANDLE_CODE(bref.unpack(amf_pointer, 6)); + HANDLE_CODE(bref.unpack(tmsi_5g, 4 * 8)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE mobile_identity_5gs_t::imei_s::pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp) +{ + HANDLE_CODE(bref.pack(imei[0], 4)); + HANDLE_CODE(bref.pack(odd_even_indicator, 1)); + + // Pack Type of identity + uint8_t type = static_cast(mobile_identity_5gs_t::identity_types_::options::imei); + HANDLE_CODE(bref.pack(type, 3)); + + HANDLE_CODE(bref.pack(imei[2], 4)); + HANDLE_CODE(bref.pack(imei[1], 4)); + HANDLE_CODE(bref.pack(imei[4], 4)); + HANDLE_CODE(bref.pack(imei[3], 4)); + HANDLE_CODE(bref.pack(imei[6], 4)); + HANDLE_CODE(bref.pack(imei[5], 4)); + HANDLE_CODE(bref.pack(imei[8], 4)); + HANDLE_CODE(bref.pack(imei[7], 4)); + HANDLE_CODE(bref.pack(imei[10], 4)); + HANDLE_CODE(bref.pack(imei[9], 4)); + HANDLE_CODE(bref.pack(imei[12], 4)); + HANDLE_CODE(bref.pack(imei[11], 4)); + HANDLE_CODE(bref.pack(imei[14], 4)); + HANDLE_CODE(bref.pack(imei[13], 4)); + return SRSASN_SUCCESS; +} +SRSASN_CODE mobile_identity_5gs_t::imei_s::unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length) +{ + imei[0] = (uint8_t)(tmp >> 1) & 0x0f; + odd_even_indicator = (bool)(tmp & 0x01); // true = odd number + HANDLE_CODE(bref.unpack(imei[2], 4)); + HANDLE_CODE(bref.unpack(imei[1], 4)); + HANDLE_CODE(bref.unpack(imei[4], 4)); + HANDLE_CODE(bref.unpack(imei[3], 4)); + HANDLE_CODE(bref.unpack(imei[6], 4)); + HANDLE_CODE(bref.unpack(imei[5], 4)); + HANDLE_CODE(bref.unpack(imei[8], 4)); + HANDLE_CODE(bref.unpack(imei[7], 4)); + HANDLE_CODE(bref.unpack(imei[10], 4)); + HANDLE_CODE(bref.unpack(imei[9], 4)); + HANDLE_CODE(bref.unpack(imei[12], 4)); + HANDLE_CODE(bref.unpack(imei[11], 4)); + HANDLE_CODE(bref.unpack(imei[14], 4)); + HANDLE_CODE(bref.unpack(imei[13], 4)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE mobile_identity_5gs_t::s_tmsi_5g_s::pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp) +{ + // Pack Type of identity + uint8_t type = static_cast(mobile_identity_5gs_t::identity_types_::options::s_tmsi_5g); + HANDLE_CODE(bref.pack(type, 3)); + + HANDLE_CODE(bref.unpack(amf_set_id, 10)); + HANDLE_CODE(bref.unpack(amf_pointer, 6)); + HANDLE_CODE(bref.unpack(tmsi_5g, 4 * 8)); + return SRSASN_SUCCESS; +} +SRSASN_CODE mobile_identity_5gs_t::s_tmsi_5g_s::unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length) +{ + HANDLE_CODE(bref.unpack(amf_set_id, 10)); + HANDLE_CODE(bref.unpack(amf_pointer, 6)); + HANDLE_CODE(bref.unpack(tmsi_5g, 4 * 8)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE mobile_identity_5gs_t::imeisv_s::pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp) +{ + HANDLE_CODE(bref.pack(imeisv[0], 4)); + HANDLE_CODE(bref.pack(odd_even_indicator, 1)); + + // Pack Type of identity + uint8_t type = static_cast(mobile_identity_5gs_t::identity_types_::options::imeisv); + HANDLE_CODE(bref.pack(type, 3)); + + HANDLE_CODE(bref.pack(imeisv[2], 4)); + HANDLE_CODE(bref.pack(imeisv[1], 4)); + HANDLE_CODE(bref.pack(imeisv[4], 4)); + HANDLE_CODE(bref.pack(imeisv[3], 4)); + HANDLE_CODE(bref.pack(imeisv[6], 4)); + HANDLE_CODE(bref.pack(imeisv[5], 4)); + HANDLE_CODE(bref.pack(imeisv[8], 4)); + HANDLE_CODE(bref.pack(imeisv[7], 4)); + HANDLE_CODE(bref.pack(imeisv[10], 4)); + HANDLE_CODE(bref.pack(imeisv[9], 4)); + HANDLE_CODE(bref.pack(imeisv[12], 4)); + HANDLE_CODE(bref.pack(imeisv[11], 4)); + HANDLE_CODE(bref.pack(imeisv[14], 4)); + HANDLE_CODE(bref.pack(imeisv[13], 4)); + HANDLE_CODE(bref.pack(0xf, 4)); + HANDLE_CODE(bref.pack(imeisv[15], 4)); + + return SRSASN_SUCCESS; +} +SRSASN_CODE mobile_identity_5gs_t::imeisv_s::unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length) +{ + imeisv[0] = (uint8_t)(tmp >> 1) & 0x0f; + odd_even_indicator = (bool)(tmp & 0x01); // true = odd number + HANDLE_CODE(bref.unpack(imeisv[2], 4)); + HANDLE_CODE(bref.unpack(imeisv[1], 4)); + HANDLE_CODE(bref.unpack(imeisv[4], 4)); + HANDLE_CODE(bref.unpack(imeisv[3], 4)); + HANDLE_CODE(bref.unpack(imeisv[6], 4)); + HANDLE_CODE(bref.unpack(imeisv[5], 4)); + HANDLE_CODE(bref.unpack(imeisv[8], 4)); + HANDLE_CODE(bref.unpack(imeisv[7], 4)); + HANDLE_CODE(bref.unpack(imeisv[10], 4)); + HANDLE_CODE(bref.unpack(imeisv[9], 4)); + HANDLE_CODE(bref.unpack(imeisv[12], 4)); + HANDLE_CODE(bref.unpack(imeisv[11], 4)); + HANDLE_CODE(bref.unpack(imeisv[14], 4)); + HANDLE_CODE(bref.unpack(imeisv[13], 4)); + HANDLE_CODE(bref.advance_bits(4)); + HANDLE_CODE(bref.unpack(imeisv[15], 4)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE mobile_identity_5gs_t::mac_address_s::pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp) +{ + return SRSASN_SUCCESS; +} +SRSASN_CODE mobile_identity_5gs_t::mac_address_s::unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length) +{ + return SRSASN_SUCCESS; +} + +SRSASN_CODE mobile_identity_5gs_t::eui_64_s::pack(asn1::bit_ref& bref, asn1::bit_ref& bref_tmp) +{ + return SRSASN_SUCCESS; +} +SRSASN_CODE mobile_identity_5gs_t::eui_64_s::unpack(asn1::cbit_ref& bref, uint8_t tmp, uint32_t length) +{ + return SRSASN_SUCCESS; +} + +// IE: 5GMM capability +// Reference: 9.11.3.1 +SRSASN_CODE capability_5gmm_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(sgc, 1)); + HANDLE_CODE(bref.pack(iphc_cp_c_io_t_5g, 1)); + HANDLE_CODE(bref.pack(n3_data, 1)); + HANDLE_CODE(bref.pack(cp_c_io_t_5g, 1)); + HANDLE_CODE(bref.pack(restrict_ec, 1)); + HANDLE_CODE(bref.pack(lpp, 1)); + HANDLE_CODE(bref.pack(ho_attach, 1)); + HANDLE_CODE(bref.pack(s1_mode, 1)); + + HANDLE_CODE(bref.pack(racs, 1)); + HANDLE_CODE(bref.pack(nssaa, 1)); + HANDLE_CODE(bref.pack(lcs_5g, 1)); + HANDLE_CODE(bref.pack(v2_xcnpc5, 1)); + HANDLE_CODE(bref.pack(v2_xcepc5, 1)); + HANDLE_CODE(bref.pack(v2_x, 1)); + HANDLE_CODE(bref.pack(up_c_io_t_5g, 1)); + HANDLE_CODE(bref.pack(srvcc_5g, 1)); + + HANDLE_CODE(bref.advance_bits(4)); + HANDLE_CODE(bref.pack(ehc_cp_c_io_t_5g, 1)); + HANDLE_CODE(bref.pack(multiple_up, 1)); + HANDLE_CODE(bref.pack(wusa, 1)); + HANDLE_CODE(bref.pack(cag, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1 || length > 13) { + asn1::log_error("Encoding Failed (5GMM capability): Packed length (%d) is not in range of min: 1 and max 13 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GMM capability +// Reference: 9.11.3.1 +SRSASN_CODE capability_5gmm_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1 || length > 13) { + asn1::log_error("Decoding Failed (5GMM capability): Length (%d) is not in range of min: 1 and max 13 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(sgc, 1)); + HANDLE_CODE(bref.unpack(iphc_cp_c_io_t_5g, 1)); + HANDLE_CODE(bref.unpack(n3_data, 1)); + HANDLE_CODE(bref.unpack(cp_c_io_t_5g, 1)); + HANDLE_CODE(bref.unpack(restrict_ec, 1)); + HANDLE_CODE(bref.unpack(lpp, 1)); + HANDLE_CODE(bref.unpack(ho_attach, 1)); + HANDLE_CODE(bref.unpack(s1_mode, 1)); + + if (length < 2) { + return SRSASN_SUCCESS; + } + + HANDLE_CODE(bref.unpack(racs, 1)); + HANDLE_CODE(bref.unpack(nssaa, 1)); + HANDLE_CODE(bref.unpack(lcs_5g, 1)); + HANDLE_CODE(bref.unpack(v2_xcnpc5, 1)); + HANDLE_CODE(bref.unpack(v2_xcepc5, 1)); + HANDLE_CODE(bref.unpack(v2_x, 1)); + HANDLE_CODE(bref.unpack(up_c_io_t_5g, 1)); + HANDLE_CODE(bref.unpack(srvcc_5g, 1)); + + if (length < 3) { + return SRSASN_SUCCESS; + } + + HANDLE_CODE(bref.advance_bits(4)); + HANDLE_CODE(bref.unpack(ehc_cp_c_io_t_5g, 1)); + HANDLE_CODE(bref.unpack(multiple_up, 1)); + HANDLE_CODE(bref.unpack(wusa, 1)); + HANDLE_CODE(bref.unpack(cag, 1)); + return SRSASN_SUCCESS; +} + +// IE: UE security capability +// Reference: 9.11.3.54 +SRSASN_CODE ue_security_capability_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(ea0_5g_supported, 1)); + HANDLE_CODE(bref.pack(ea1_128_5g_supported, 1)); + HANDLE_CODE(bref.pack(ea2_128_5g_supported, 1)); + HANDLE_CODE(bref.pack(ea3_128_5g_supported, 1)); + HANDLE_CODE(bref.pack(ea4_5g_supported, 1)); + HANDLE_CODE(bref.pack(ea5_5g_supported, 1)); + HANDLE_CODE(bref.pack(ea6_5g_supported, 1)); + HANDLE_CODE(bref.pack(ea7_5g_supported, 1)); + HANDLE_CODE(bref.pack(ia0_5g_supported, 1)); + + HANDLE_CODE(bref.pack(ia1_128_5g_supported, 1)); + HANDLE_CODE(bref.pack(ia2_128_5g_supported, 1)); + HANDLE_CODE(bref.pack(ia3_128_5g_supported, 1)); + HANDLE_CODE(bref.pack(ia4_5g_supported, 1)); + HANDLE_CODE(bref.pack(ia5_5g_supported, 1)); + HANDLE_CODE(bref.pack(ia6_5g_supported, 1)); + HANDLE_CODE(bref.pack(ia7_5g_supported, 1)); + + if (eps_caps_present == true) { + HANDLE_CODE(bref.pack(eea0_supported, 1)); + HANDLE_CODE(bref.pack(eea1_128_supported, 1)); + HANDLE_CODE(bref.pack(eea2_128_supported, 1)); + HANDLE_CODE(bref.pack(eea3_128_supported, 1)); + HANDLE_CODE(bref.pack(eea4_supported, 1)); + HANDLE_CODE(bref.pack(eea5_supported, 1)); + HANDLE_CODE(bref.pack(eea6_supported, 1)); + HANDLE_CODE(bref.pack(eea7_supported, 1)); + HANDLE_CODE(bref.pack(eia0_supported, 1)); + HANDLE_CODE(bref.pack(eia1_128_supported, 1)); + HANDLE_CODE(bref.pack(eia2_128_supported, 1)); + HANDLE_CODE(bref.pack(eia3_128_supported, 1)); + HANDLE_CODE(bref.pack(eia4_supported, 1)); + HANDLE_CODE(bref.pack(eia5_supported, 1)); + HANDLE_CODE(bref.pack(eia6_supported, 1)); + HANDLE_CODE(bref.pack(eia7_supported, 1)); + } + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 8) { + asn1::log_error( + "Encoding Failed (UE security capability): Packed length (%d) is not in range of min: 2 and max 8 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: UE security capability +// Reference: 9.11.3.54 +SRSASN_CODE ue_security_capability_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 8) { + asn1::log_error("Decoding Failed (UE security capability): Length (%d) is not in range of min: 2 and max 8 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(ea0_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ea1_128_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ea2_128_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ea3_128_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ea4_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ea5_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ea6_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ea7_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ia0_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ia1_128_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ia2_128_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ia3_128_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ia4_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ia5_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ia6_5g_supported, 1)); + HANDLE_CODE(bref.unpack(ia7_5g_supported, 1)); + if (length > 2) { + eps_caps_present = true; + HANDLE_CODE(bref.unpack(eea0_supported, 1)); + HANDLE_CODE(bref.unpack(eea1_128_supported, 1)); + HANDLE_CODE(bref.unpack(eea2_128_supported, 1)); + HANDLE_CODE(bref.unpack(eea3_128_supported, 1)); + HANDLE_CODE(bref.unpack(eea4_supported, 1)); + HANDLE_CODE(bref.unpack(eea5_supported, 1)); + HANDLE_CODE(bref.unpack(eea6_supported, 1)); + HANDLE_CODE(bref.unpack(eea7_supported, 1)); + HANDLE_CODE(bref.unpack(eia0_supported, 1)); + HANDLE_CODE(bref.unpack(eia1_128_supported, 1)); + HANDLE_CODE(bref.unpack(eia2_128_supported, 1)); + HANDLE_CODE(bref.unpack(eia3_128_supported, 1)); + HANDLE_CODE(bref.unpack(eia4_supported, 1)); + HANDLE_CODE(bref.unpack(eia5_supported, 1)); + HANDLE_CODE(bref.unpack(eia6_supported, 1)); + HANDLE_CODE(bref.unpack(eia7_supported, 1)); + } + if (length > 4) { + HANDLE_CODE(bref.advance_bits((length - 4) * 8)); + } + return SRSASN_SUCCESS; +} + +// IE: NSSAI +// Reference: 9.11.3.37 +SRSASN_CODE nssai_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + for (auto& s_nssai : s_nssai_list) { + HANDLE_CODE(s_nssai.pack(bref)); + } + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 144) { + asn1::log_error("Encoding Failed (NSSAI): Packed length (%d) is not in range of min: 2 and max 144 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: NSSAI +// Reference: 9.11.3.37 +SRSASN_CODE nssai_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 144) { + asn1::log_error("Decoding Failed (NSSAI): Length (%d) is not in range of min: 2 and max 144 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + asn1::cbit_ref bref_start = bref; + while (floorl(bref.distance(bref_start) / 8) < length) { + s_nssai_t s_nssai; + HANDLE_CODE(s_nssai.unpack(bref)); + s_nssai_list.push_back(s_nssai); + } + return SRSASN_SUCCESS; +} + +// IE: 5GS tracking area identity +// Reference: 9.11.3.8 +SRSASN_CODE tracking_area_identity_5gs_t::pack(asn1::bit_ref& bref) +{ + pack_mcc_mnc(mcc.data(), mnc.data(), bref); + HANDLE_CODE(bref.pack(tac, 3 * 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GS tracking area identity +// Reference: 9.11.3.8 +SRSASN_CODE tracking_area_identity_5gs_t::unpack(asn1::cbit_ref& bref) +{ + unpack_mcc_mnc(mcc.data(), mnc.data(), bref); + HANDLE_CODE(bref.unpack(tac, 3 * 8)); + return SRSASN_SUCCESS; +} + +// IE: S1 UE network capability +// Reference: 9.11.3.48 +SRSASN_CODE s1_ue_network_capability_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(eea0_supported, 1)); + HANDLE_CODE(bref.pack(eea1_128_supported, 1)); + HANDLE_CODE(bref.pack(eea2_128_supported, 1)); + HANDLE_CODE(bref.pack(eea3_128_supported, 1)); + HANDLE_CODE(bref.pack(eea4_supported, 1)); + HANDLE_CODE(bref.pack(eea5_supported, 1)); + HANDLE_CODE(bref.pack(eea6_supported, 1)); + HANDLE_CODE(bref.pack(eea7_supported, 1)); + HANDLE_CODE(bref.pack(eia0_supported, 1)); + + HANDLE_CODE(bref.pack(eia1_128_supported, 1)); + HANDLE_CODE(bref.pack(eia2_128_supported, 1)); + HANDLE_CODE(bref.pack(eia3_128_supported, 1)); + HANDLE_CODE(bref.pack(eia4_supported, 1)); + HANDLE_CODE(bref.pack(eia5_supported, 1)); + HANDLE_CODE(bref.pack(eia6_supported, 1)); + HANDLE_CODE(bref.pack(eia7_supported, 1)); + + HANDLE_CODE(bref.pack(uea0_supported, 1)); + HANDLE_CODE(bref.pack(uea1_128_supported, 1)); + HANDLE_CODE(bref.pack(uea2_128_supported, 1)); + HANDLE_CODE(bref.pack(uea3_128_supported, 1)); + HANDLE_CODE(bref.pack(uea4_supported, 1)); + HANDLE_CODE(bref.pack(uea5_supported, 1)); + HANDLE_CODE(bref.pack(uea6_supported, 1)); + HANDLE_CODE(bref.pack(uea7_supported, 1)); + + HANDLE_CODE(bref.pack(ucs2_support, 1)); + HANDLE_CODE(bref.pack(uia1_128_supported, 1)); + HANDLE_CODE(bref.pack(uia2_128_supported, 1)); + HANDLE_CODE(bref.pack(uia3_128_supported, 1)); + HANDLE_CODE(bref.pack(uia4_supported, 1)); + HANDLE_CODE(bref.pack(uia5_supported, 1)); + HANDLE_CODE(bref.pack(uia6_supported, 1)); + HANDLE_CODE(bref.pack(uia7_supported, 1)); + + HANDLE_CODE(bref.pack(pro_se_dd_supported, 1)); + HANDLE_CODE(bref.pack(pro_se_supported, 1)); + HANDLE_CODE(bref.pack(h245_ash_supported, 1)); + HANDLE_CODE(bref.pack(acc_csfb_supported, 1)); + HANDLE_CODE(bref.pack(llp_supported, 1)); + HANDLE_CODE(bref.pack(lcs_supported, 1)); + HANDLE_CODE(bref.pack(srvcc_capability_supported, 1)); + HANDLE_CODE(bref.pack(nf_capability_supported, 1)); + + HANDLE_CODE(bref.pack(e_pco_supported, 1)); + HANDLE_CODE(bref.pack(hc_cp_c_io_t_supported, 1)); + HANDLE_CODE(bref.pack(e_rw_o_pdn_supported, 1)); + HANDLE_CODE(bref.pack(s1_u_data_supported, 1)); + HANDLE_CODE(bref.pack(up_c_io_t_supported, 1)); + HANDLE_CODE(bref.pack(cp_c_io_t_supported, 1)); + HANDLE_CODE(bref.pack(pro_se_relay_supported, 1)); + + HANDLE_CODE(bref.pack(pro_se_dc_supported, 1)); + HANDLE_CODE(bref.pack(max_15_eps_bearer_supported, 1)); + HANDLE_CODE(bref.pack(sgc_supported, 1)); + HANDLE_CODE(bref.pack(n1mode_supported, 1)); + HANDLE_CODE(bref.pack(dcnr_supported, 1)); + HANDLE_CODE(bref.pack(cp_backoff_supported, 1)); + HANDLE_CODE(bref.pack(restrict_ec_supported, 1)); + HANDLE_CODE(bref.pack(v2_x_pc5_supported, 1)); + HANDLE_CODE(bref.pack(multiple_drb_supported, 1)); + + HANDLE_CODE(bref.advance_bits(3)); + HANDLE_CODE(bref.pack(nr_pc5_supported, 1)); + HANDLE_CODE(bref.pack(up_mt_edt_supported, 1)); + HANDLE_CODE(bref.pack(cp_mt_edt_supported, 1)); + HANDLE_CODE(bref.pack(wus_supported, 1)); + HANDLE_CODE(bref.pack(racs_supported, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 13) { + asn1::log_error( + "Encoding Failed (S1 UE network capability): Packed length (%d) is not in range of min: 2 and max 13 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: S1 UE network capability +// Reference: 9.11.3.48 +SRSASN_CODE s1_ue_network_capability_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 13) { + asn1::log_error( + "Decoding Failed (S1 UE network capability): Length (%d) is not in range of min: 2 and max 13 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(eea0_supported, 1)); + HANDLE_CODE(bref.unpack(eea1_128_supported, 1)); + HANDLE_CODE(bref.unpack(eea2_128_supported, 1)); + HANDLE_CODE(bref.unpack(eea3_128_supported, 1)); + HANDLE_CODE(bref.unpack(eea4_supported, 1)); + HANDLE_CODE(bref.unpack(eea5_supported, 1)); + HANDLE_CODE(bref.unpack(eea6_supported, 1)); + HANDLE_CODE(bref.unpack(eea7_supported, 1)); + + HANDLE_CODE(bref.unpack(eia0_supported, 1)); + HANDLE_CODE(bref.unpack(eia1_128_supported, 1)); + HANDLE_CODE(bref.unpack(eia2_128_supported, 1)); + HANDLE_CODE(bref.unpack(eia3_128_supported, 1)); + HANDLE_CODE(bref.unpack(eia4_supported, 1)); + HANDLE_CODE(bref.unpack(eia5_supported, 1)); + HANDLE_CODE(bref.unpack(eia6_supported, 1)); + HANDLE_CODE(bref.unpack(eia7_supported, 1)); + + if (length < 3) { + return SRSASN_SUCCESS; + } + + HANDLE_CODE(bref.unpack(uea0_supported, 1)); + HANDLE_CODE(bref.unpack(uea1_128_supported, 1)); + HANDLE_CODE(bref.unpack(uea2_128_supported, 1)); + HANDLE_CODE(bref.unpack(uea3_128_supported, 1)); + HANDLE_CODE(bref.unpack(uea4_supported, 1)); + HANDLE_CODE(bref.unpack(uea5_supported, 1)); + HANDLE_CODE(bref.unpack(uea6_supported, 1)); + HANDLE_CODE(bref.unpack(uea7_supported, 1)); + + if (length < 4) { + return SRSASN_SUCCESS; + } + + HANDLE_CODE(bref.unpack(ucs2_support, 1)); + HANDLE_CODE(bref.unpack(uia1_128_supported, 1)); + HANDLE_CODE(bref.unpack(uia2_128_supported, 1)); + HANDLE_CODE(bref.unpack(uia3_128_supported, 1)); + HANDLE_CODE(bref.unpack(uia4_supported, 1)); + HANDLE_CODE(bref.unpack(uia5_supported, 1)); + HANDLE_CODE(bref.unpack(uia6_supported, 1)); + HANDLE_CODE(bref.unpack(uia7_supported, 1)); + + if (length < 5) { + return SRSASN_SUCCESS; + } + + HANDLE_CODE(bref.unpack(pro_se_dd_supported, 1)); + HANDLE_CODE(bref.unpack(pro_se_supported, 1)); + HANDLE_CODE(bref.unpack(h245_ash_supported, 1)); + HANDLE_CODE(bref.unpack(acc_csfb_supported, 1)); + HANDLE_CODE(bref.unpack(llp_supported, 1)); + HANDLE_CODE(bref.unpack(lcs_supported, 1)); + HANDLE_CODE(bref.unpack(srvcc_capability_supported, 1)); + HANDLE_CODE(bref.unpack(nf_capability_supported, 1)); + + if (length < 6) { + return SRSASN_SUCCESS; + } + + HANDLE_CODE(bref.unpack(e_pco_supported, 1)); + HANDLE_CODE(bref.unpack(hc_cp_c_io_t_supported, 1)); + HANDLE_CODE(bref.unpack(e_rw_o_pdn_supported, 1)); + HANDLE_CODE(bref.unpack(s1_u_data_supported, 1)); + HANDLE_CODE(bref.unpack(up_c_io_t_supported, 1)); + HANDLE_CODE(bref.unpack(cp_c_io_t_supported, 1)); + HANDLE_CODE(bref.unpack(pro_se_relay_supported, 1)); + HANDLE_CODE(bref.unpack(pro_se_dc_supported, 1)); + + if (length < 7) { + return SRSASN_SUCCESS; + } + + HANDLE_CODE(bref.unpack(max_15_eps_bearer_supported, 1)); + HANDLE_CODE(bref.unpack(sgc_supported, 1)); + HANDLE_CODE(bref.unpack(n1mode_supported, 1)); + HANDLE_CODE(bref.unpack(dcnr_supported, 1)); + HANDLE_CODE(bref.unpack(cp_backoff_supported, 1)); + HANDLE_CODE(bref.unpack(restrict_ec_supported, 1)); + HANDLE_CODE(bref.unpack(v2_x_pc5_supported, 1)); + HANDLE_CODE(bref.unpack(multiple_drb_supported, 1)); + + if (length < 8) { + return SRSASN_SUCCESS; + } + // 3 spare bits + bref.advance_bits(3); + + HANDLE_CODE(bref.unpack(nr_pc5_supported, 1)); + HANDLE_CODE(bref.unpack(up_mt_edt_supported, 1)); + HANDLE_CODE(bref.unpack(cp_mt_edt_supported, 1)); + HANDLE_CODE(bref.unpack(wus_supported, 1)); + HANDLE_CODE(bref.unpack(racs_supported, 1)); + return SRSASN_SUCCESS; +} + +// IE: Uplink data status +// Reference: 9.11.3.57 +SRSASN_CODE uplink_data_status_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(psi_7, 1)); + HANDLE_CODE(bref.pack(psi_6, 1)); + HANDLE_CODE(bref.pack(psi_5, 1)); + HANDLE_CODE(bref.pack(psi_4, 1)); + HANDLE_CODE(bref.pack(psi_3, 1)); + HANDLE_CODE(bref.pack(psi_2, 1)); + HANDLE_CODE(bref.pack(psi_1, 1)); + HANDLE_CODE(bref.pack(psi_0, 1)); + HANDLE_CODE(bref.pack(psi_15, 1)); + HANDLE_CODE(bref.pack(psi_14, 1)); + HANDLE_CODE(bref.pack(psi_13, 1)); + HANDLE_CODE(bref.pack(psi_12, 1)); + HANDLE_CODE(bref.pack(psi_11, 1)); + HANDLE_CODE(bref.pack(psi_10, 1)); + HANDLE_CODE(bref.pack(psi_9, 1)); + HANDLE_CODE(bref.pack(psi_8, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 32) { + asn1::log_error( + "Encoding Failed (Uplink data status): Packed length (%d) is not in range of min: 2 and max 32 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Uplink data status +// Reference: 9.11.3.57 +SRSASN_CODE uplink_data_status_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 32) { + asn1::log_error("Decoding Failed (Uplink data status): Length (%d) is not in range of min: 2 and max 32 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(psi_7, 1)); + HANDLE_CODE(bref.unpack(psi_6, 1)); + HANDLE_CODE(bref.unpack(psi_5, 1)); + HANDLE_CODE(bref.unpack(psi_4, 1)); + HANDLE_CODE(bref.unpack(psi_3, 1)); + HANDLE_CODE(bref.unpack(psi_2, 1)); + HANDLE_CODE(bref.unpack(psi_1, 1)); + HANDLE_CODE(bref.unpack(psi_0, 1)); + HANDLE_CODE(bref.unpack(psi_15, 1)); + HANDLE_CODE(bref.unpack(psi_14, 1)); + HANDLE_CODE(bref.unpack(psi_13, 1)); + HANDLE_CODE(bref.unpack(psi_12, 1)); + HANDLE_CODE(bref.unpack(psi_11, 1)); + HANDLE_CODE(bref.unpack(psi_10, 1)); + HANDLE_CODE(bref.unpack(psi_9, 1)); + HANDLE_CODE(bref.unpack(psi_8, 1)); + + if (length > 2) { + bref.advance_bits((length - 2) * 8); + } + return SRSASN_SUCCESS; +} + +// IE: PDU session status +// Reference: 9.11.3.44 +SRSASN_CODE pdu_session_status_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(psi_7, 1)); + HANDLE_CODE(bref.pack(psi_6, 1)); + HANDLE_CODE(bref.pack(psi_5, 1)); + HANDLE_CODE(bref.pack(psi_4, 1)); + HANDLE_CODE(bref.pack(psi_3, 1)); + HANDLE_CODE(bref.pack(psi_2, 1)); + HANDLE_CODE(bref.pack(psi_1, 1)); + HANDLE_CODE(bref.pack(psi_0, 1)); + HANDLE_CODE(bref.pack(psi_15, 1)); + HANDLE_CODE(bref.pack(psi_14, 1)); + HANDLE_CODE(bref.pack(psi_13, 1)); + HANDLE_CODE(bref.pack(psi_12, 1)); + HANDLE_CODE(bref.pack(psi_11, 1)); + HANDLE_CODE(bref.pack(psi_10, 1)); + HANDLE_CODE(bref.pack(psi_9, 1)); + HANDLE_CODE(bref.pack(psi_8, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 32) { + asn1::log_error( + "Encoding Failed (PDU session status): Packed length (%d) is not in range of min: 2 and max 32 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: PDU session status +// Reference: 9.11.3.44 +SRSASN_CODE pdu_session_status_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 32) { + asn1::log_error("Decoding Failed (PDU session status): Length (%d) is not in range of min: 2 and max 32 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(psi_7, 1)); + HANDLE_CODE(bref.unpack(psi_6, 1)); + HANDLE_CODE(bref.unpack(psi_5, 1)); + HANDLE_CODE(bref.unpack(psi_4, 1)); + HANDLE_CODE(bref.unpack(psi_3, 1)); + HANDLE_CODE(bref.unpack(psi_2, 1)); + HANDLE_CODE(bref.unpack(psi_1, 1)); + HANDLE_CODE(bref.unpack(psi_0, 1)); + HANDLE_CODE(bref.unpack(psi_15, 1)); + HANDLE_CODE(bref.unpack(psi_14, 1)); + HANDLE_CODE(bref.unpack(psi_13, 1)); + HANDLE_CODE(bref.unpack(psi_12, 1)); + HANDLE_CODE(bref.unpack(psi_11, 1)); + HANDLE_CODE(bref.unpack(psi_10, 1)); + HANDLE_CODE(bref.unpack(psi_9, 1)); + HANDLE_CODE(bref.unpack(psi_8, 1)); + + if (length > 2) { + bref.advance_bits((length - 2) * 8); + } + return SRSASN_SUCCESS; +} + +// IE: MICO indication +// Reference: 9.11.3.31 +SRSASN_CODE mico_indication_t::pack(asn1::bit_ref& bref) +{ + // 2 Spare bits + HANDLE_CODE(bref.pack(0x0, 2)); + HANDLE_CODE(bref.pack(sprti, 1)); + HANDLE_CODE(bref.pack(aai, 1)); + return SRSASN_SUCCESS; +} + +// IE: MICO indication +// Reference: 9.11.3.31 +SRSASN_CODE mico_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 2 Spare bits + bref.advance_bits(2); + HANDLE_CODE(bref.unpack(sprti, 1)); + HANDLE_CODE(bref.unpack(aai, 1)); + return SRSASN_SUCCESS; +} + +// IE: UE status +// Reference: 9.11.3.56 +SRSASN_CODE ue_status_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 6 Spare bits + HANDLE_CODE(bref.pack(0x0, 6)); + HANDLE_CODE(bref.pack(n1_mode_reg, 1)); + HANDLE_CODE(bref.pack(s1_mode_reg, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (UE status): Packed length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: UE status +// Reference: 9.11.3.56 +SRSASN_CODE ue_status_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (UE status): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 6 Spare bits + bref.advance_bits(6); + HANDLE_CODE(bref.unpack(n1_mode_reg, 1)); + HANDLE_CODE(bref.unpack(s1_mode_reg, 1)); + return SRSASN_SUCCESS; +} + +// IE: Allowed PDU session status +// Reference: 9.11.3.13 +SRSASN_CODE allowed_pdu_session_status_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(psi_7, 1)); + HANDLE_CODE(bref.pack(psi_6, 1)); + HANDLE_CODE(bref.pack(psi_5, 1)); + HANDLE_CODE(bref.pack(psi_4, 1)); + HANDLE_CODE(bref.pack(psi_3, 1)); + HANDLE_CODE(bref.pack(psi_2, 1)); + HANDLE_CODE(bref.pack(psi_1, 1)); + HANDLE_CODE(bref.pack(psi_0, 1)); + HANDLE_CODE(bref.pack(psi_15, 1)); + HANDLE_CODE(bref.pack(psi_14, 1)); + HANDLE_CODE(bref.pack(psi_13, 1)); + HANDLE_CODE(bref.pack(psi_12, 1)); + HANDLE_CODE(bref.pack(psi_11, 1)); + HANDLE_CODE(bref.pack(psi_10, 1)); + HANDLE_CODE(bref.pack(psi_9, 1)); + HANDLE_CODE(bref.pack(psi_8, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 32) { + asn1::log_error( + "Encoding Failed (Allowed PDU session status): Packed length (%d) is not in range of min: 2 and max 32 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Allowed PDU session status +// Reference: 9.11.3.13 +SRSASN_CODE allowed_pdu_session_status_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 32) { + asn1::log_error( + "Decoding Failed (Allowed PDU session status): Length (%d) is not in range of min: 2 and max 32 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(psi_7, 1)); + HANDLE_CODE(bref.unpack(psi_6, 1)); + HANDLE_CODE(bref.unpack(psi_5, 1)); + HANDLE_CODE(bref.unpack(psi_4, 1)); + HANDLE_CODE(bref.unpack(psi_3, 1)); + HANDLE_CODE(bref.unpack(psi_2, 1)); + HANDLE_CODE(bref.unpack(psi_1, 1)); + HANDLE_CODE(bref.unpack(psi_0, 1)); + HANDLE_CODE(bref.unpack(psi_15, 1)); + HANDLE_CODE(bref.unpack(psi_14, 1)); + HANDLE_CODE(bref.unpack(psi_13, 1)); + HANDLE_CODE(bref.unpack(psi_12, 1)); + HANDLE_CODE(bref.unpack(psi_11, 1)); + HANDLE_CODE(bref.unpack(psi_10, 1)); + HANDLE_CODE(bref.unpack(psi_9, 1)); + HANDLE_CODE(bref.unpack(psi_8, 1)); + + if (length > 2) { + bref.advance_bits((length - 2) * 8); + } + return SRSASN_SUCCESS; +} + +// IE: UE usage setting +// Reference: 9.11.3.55 +SRSASN_CODE ue_usage_setting_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 7 Spare bits + HANDLE_CODE(bref.pack(0x0, 7)); + HANDLE_CODE(ue_usage_setting.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (UE usage setting): Packed length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: UE usage setting +// Reference: 9.11.3.55 +SRSASN_CODE ue_usage_setting_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (UE usage setting): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 7 Spare bits + bref.advance_bits(7); + HANDLE_CODE(ue_usage_setting.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GS DRX parameters +// Reference: 9.11.3.2A +SRSASN_CODE drx_parameters_5gs_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 4 Spare bits + HANDLE_CODE(bref.pack(0x0, 4)); + HANDLE_CODE(drx_value.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (5GS DRX parameters): Packed length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GS DRX parameters +// Reference: 9.11.3.2A +SRSASN_CODE drx_parameters_5gs_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (5GS DRX parameters): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 4 Spare bits + bref.advance_bits(4); + HANDLE_CODE(drx_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: EPS NAS message container +// Reference: 9.11.3.24 +SRSASN_CODE eps_nas_message_container_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + HANDLE_CODE(bref.pack_bytes(eps_nas_message_container.data(), eps_nas_message_container.size())); + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: EPS NAS message container +// Reference: 9.11.3.24 +SRSASN_CODE eps_nas_message_container_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + eps_nas_message_container.resize(length); + HANDLE_CODE(bref.unpack_bytes(eps_nas_message_container.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: LADN indication +// Reference: 9.11.3.29 +SRSASN_CODE ladn_indication_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + for (auto& dnn : ladn_dnn_values) { + HANDLE_CODE(dnn.pack(bref)); + } + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MIN 0 not check because auf uint underflow + if (length > 808) { + asn1::log_error("Encoding Failed (LADN indication): Packed length (%d) is not in range of max 808 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: LADN indication +// Reference: 9.11.3.29 +SRSASN_CODE ladn_indication_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MIN 0 not check because auf uint underflow + if (length > 808) { + asn1::log_error("Decoding Failed (LADN indication): Length (%d) is not in range of max 808 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + asn1::cbit_ref bref_start = bref; + while (floorl(bref.distance(bref_start) / 8) < length) { + dnn_t dnn; + dnn.unpack(bref); + ladn_dnn_values.push_back(dnn); + } + return SRSASN_SUCCESS; +} + +// IE: Payload container type +// Reference: 9.11.3.40 +SRSASN_CODE payload_container_type_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(payload_container_type.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Payload container type +// Reference: 9.11.3.40 +SRSASN_CODE payload_container_type_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(payload_container_type.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Payload container +// Reference: 9.11.3.39 +SRSASN_CODE payload_container_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + HANDLE_CODE(bref.pack_bytes(payload_container_contents.data(), payload_container_contents.size())); + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MAX 65535 not check because auf uint overflow + if (length < 1) { + asn1::log_error("Encoding Failed (Payload container): Packed length (%d) is not in range of min: 1 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: Payload container +// Reference: 9.11.3.39 +SRSASN_CODE payload_container_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MAX 65535 not check because auf uint overflow + if (length < 1) { + asn1::log_error("Decoding Failed (Payload container): Length (%d) is not in range of min: 1 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + payload_container_contents.resize(length); + HANDLE_CODE(bref.unpack_bytes(payload_container_contents.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Network slicing indication +// Reference: 9.11.3.36 +SRSASN_CODE network_slicing_indication_t::pack(asn1::bit_ref& bref) +{ + // 2 Spare bits + HANDLE_CODE(bref.pack(0x0, 2)); + HANDLE_CODE(bref.pack(nssci, 1)); + HANDLE_CODE(bref.pack(dcni, 1)); + return SRSASN_SUCCESS; +} + +// IE: Network slicing indication +// Reference: 9.11.3.36 +SRSASN_CODE network_slicing_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 2 Spare bits + bref.advance_bits(2); + HANDLE_CODE(bref.unpack(nssci, 1)); + HANDLE_CODE(bref.unpack(dcni, 1)); + return SRSASN_SUCCESS; +} + +// IE: 5GS update type +// Reference: 9.11.3.9A +SRSASN_CODE update_type_5gs_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 2 Spare bits + HANDLE_CODE(bref.pack(0x0, 2)); + HANDLE_CODE(pnb_eps_c_io_t.pack(bref)); + HANDLE_CODE(pnb_5gs_c_io_t.pack(bref)); + HANDLE_CODE(ng_ran_rcu.pack(bref)); + HANDLE_CODE(sms_requested.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GS update type +// Reference: 9.11.3.9A +SRSASN_CODE update_type_5gs_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); // 2 Spare bits + bref.advance_bits(2); + HANDLE_CODE(pnb_eps_c_io_t.unpack(bref)); + HANDLE_CODE(pnb_5gs_c_io_t.unpack(bref)); + HANDLE_CODE(ng_ran_rcu.unpack(bref)); + HANDLE_CODE(sms_requested.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Mobile station classmark 2 +// Reference: 9.11.3.31C +SRSASN_CODE mobile_station_classmark_2_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 3) { + asn1::log_error("Encoding Failed (Mobile station classmark 2): Packed length (%d) does not equal expected length 3", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Mobile station classmark 2 +// Reference: 9.11.3.31C +SRSASN_CODE mobile_station_classmark_2_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 3) { + asn1::log_error("Decoding Failed (Mobile station classmark 2): Length (%d) does not equal expected length 3", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Supported codec list +// Reference: 9.11.3.51A +SRSASN_CODE supported_codec_list_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 3) { + asn1::log_error("Encoding Failed (Supported codec list): Packed length (%d) is not in range of min: 3 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Supported codec list +// Reference: 9.11.3.51A +SRSASN_CODE supported_codec_list_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 3) { + asn1::log_error("Decoding Failed (Supported codec list): Length (%d) is not in range of min: 3 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: message container +// Reference: 9.11.3.33 +SRSASN_CODE message_container_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + HANDLE_CODE(bref.pack_bytes(nas_message_container.data(), nas_message_container.size())); + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + if (length < 1 || length > 65532) { + asn1::log_error( + "Encoding Failed (message container): Packed length (%d) is not in range of min: 1 and max 65532 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: message container +// Reference: 9.11.3.33 +SRSASN_CODE message_container_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + if (length < 1 || length > 65532) { + asn1::log_error("Decoding Failed (message container): Length (%d) is not in range of min: 1 and max 65532 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + nas_message_container.resize(length); + HANDLE_CODE(bref.unpack_bytes(nas_message_container.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: EPS bearer context status +// Reference: 9.11.3.23A +SRSASN_CODE eps_bearer_context_status_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(ebi_7, 1)); + HANDLE_CODE(bref.pack(ebi_6, 1)); + HANDLE_CODE(bref.pack(ebi_5, 1)); + HANDLE_CODE(bref.pack(ebi_4, 1)); + HANDLE_CODE(bref.pack(ebi_3, 1)); + HANDLE_CODE(bref.pack(ebi_2, 1)); + HANDLE_CODE(bref.pack(ebi_1, 1)); + HANDLE_CODE(bref.pack(ebi_0, 1)); + HANDLE_CODE(bref.pack(ebi_15, 1)); + HANDLE_CODE(bref.pack(ebi_14, 1)); + HANDLE_CODE(bref.pack(ebi_13, 1)); + HANDLE_CODE(bref.pack(ebi_12, 1)); + HANDLE_CODE(bref.pack(ebi_11, 1)); + HANDLE_CODE(bref.pack(ebi_10, 1)); + HANDLE_CODE(bref.pack(ebi_9, 1)); + HANDLE_CODE(bref.pack(ebi_8, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 2) { + asn1::log_error("Encoding Failed (EPS bearer context status): Packed length (%d) does not equal expected length 2", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: EPS bearer context status +// Reference: 9.11.3.23A +SRSASN_CODE eps_bearer_context_status_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 2) { + asn1::log_error("Decoding Failed (EPS bearer context status): Length (%d) does not equal expected length 2", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(ebi_7, 1)); + HANDLE_CODE(bref.unpack(ebi_6, 1)); + HANDLE_CODE(bref.unpack(ebi_5, 1)); + HANDLE_CODE(bref.unpack(ebi_4, 1)); + HANDLE_CODE(bref.unpack(ebi_3, 1)); + HANDLE_CODE(bref.unpack(ebi_2, 1)); + HANDLE_CODE(bref.unpack(ebi_1, 1)); + HANDLE_CODE(bref.unpack(ebi_0, 1)); + HANDLE_CODE(bref.unpack(ebi_15, 1)); + HANDLE_CODE(bref.unpack(ebi_14, 1)); + HANDLE_CODE(bref.unpack(ebi_13, 1)); + HANDLE_CODE(bref.unpack(ebi_12, 1)); + HANDLE_CODE(bref.unpack(ebi_11, 1)); + HANDLE_CODE(bref.unpack(ebi_10, 1)); + HANDLE_CODE(bref.unpack(ebi_9, 1)); + HANDLE_CODE(bref.unpack(ebi_8, 1)); + return SRSASN_SUCCESS; +} + +// IE: Extended DRX parameters +// Reference: 9.11.3.26A +SRSASN_CODE extended_drx_parameters_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(paging__time__window.pack(bref)); + HANDLE_CODE(e_drx_value.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (Extended DRX parameters): Packed length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Extended DRX parameters +// Reference: 9.11.3.26A +SRSASN_CODE extended_drx_parameters_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (Extended DRX parameters): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(paging__time__window.unpack(bref)); + HANDLE_CODE(e_drx_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: GPRS timer 3 +// Reference: 9.11.2.5 +SRSASN_CODE gprs_timer_3_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(unit.pack(bref)); + HANDLE_CODE(bref.pack(timer_value, 5)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (GPRS timer 3): Packed length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: GPRS timer 3 +// Reference: 9.11.2.5 +SRSASN_CODE gprs_timer_3_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (GPRS timer 3): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(unit.unpack(bref)); + HANDLE_CODE(bref.unpack(timer_value, 5)); + return SRSASN_SUCCESS; +} + +// IE: UE radio capability ID +// Reference: 9.11.3.68 +SRSASN_CODE ue_radio_capability_id_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(ue_radio_capability_id.data(), ue_radio_capability_id.size())); + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: UE radio capability ID +// Reference: 9.11.3.68 +SRSASN_CODE ue_radio_capability_id_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + ue_radio_capability_id.resize(length); + HANDLE_CODE(bref.unpack_bytes(ue_radio_capability_id.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Mapped NSSAI +// Reference: 9.11.3.31B +SRSASN_CODE mapped_nssai_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 40) { + asn1::log_error("Encoding Failed (Mapped NSSAI): Packed length (%d) is not in range of min: 2 and max 40 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Mapped NSSAI +// Reference: 9.11.3.31B +SRSASN_CODE mapped_nssai_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 40) { + asn1::log_error("Decoding Failed (Mapped NSSAI): Length (%d) is not in range of min: 2 and max 40 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Additional information requested +// Reference: 9.11.3.12A +SRSASN_CODE additional_information_requested_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 7 Spare bits + HANDLE_CODE(bref.pack(0x0, 7)); + HANDLE_CODE(bref.pack(cipher_key, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Additional information requested +// Reference: 9.11.3.12A +SRSASN_CODE additional_information_requested_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); // 7 Spare bits + bref.advance_bits(7); + HANDLE_CODE(bref.unpack(cipher_key, 1)); + return SRSASN_SUCCESS; +} + +// IE: WUS assistance information +// Reference: 9.11.3.71 +SRSASN_CODE wus_assistance_information_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1) { + asn1::log_error("Encoding Failed (WUS assistance information): Packed length (%d) is not in range of min: 1 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: WUS assistance information +// Reference: 9.11.3.71 +SRSASN_CODE wus_assistance_information_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1) { + asn1::log_error("Decoding Failed (WUS assistance information): Length (%d) is not in range of min: 1 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: N5GC indication +// Reference: 9.11.3.72 +SRSASN_CODE n5gc_indication_t::pack(asn1::bit_ref& bref) +{ + // 3 Spare bits + HANDLE_CODE(bref.pack(0x0, 3)); + HANDLE_CODE(bref.pack(n5gcreg, 1)); + return SRSASN_SUCCESS; +} + +// IE: N5GC indication +// Reference: 9.11.3.72 +SRSASN_CODE n5gc_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 3 Spare bits + bref.advance_bits(3); + HANDLE_CODE(bref.unpack(n5gcreg, 1)); + return SRSASN_SUCCESS; +} + +// IE: NB-N1 mode DRX parameters +// Reference: 9.11.3.73 +SRSASN_CODE nb_n1_mode_drx_parameters_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 4 Spare bits + HANDLE_CODE(bref.pack(0x0, 4)); + HANDLE_CODE(nb_n1_mode_drx_value.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (NB-N1 mode DRX parameters): Packed length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: NB-N1 mode DRX parameters +// Reference: 9.11.3.73 +SRSASN_CODE nb_n1_mode_drx_parameters_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (NB-N1 mode DRX parameters): Length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 4 Spare bits + bref.advance_bits(4); + HANDLE_CODE(nb_n1_mode_drx_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GS registration result +// Reference: 9.11.3.6 +SRSASN_CODE registration_result_5gs_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 2 Spare bits + HANDLE_CODE(bref.pack(0x0, 2)); + HANDLE_CODE(emergency_registered.pack(bref)); + HANDLE_CODE(nssaa_to_be_performed.pack(bref)); + HANDLE_CODE(sms_allowed.pack(bref)); + HANDLE_CODE(registration_result.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (5GS registration result): Packed length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GS registration result +// Reference: 9.11.3.6 +SRSASN_CODE registration_result_5gs_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (5GS registration result): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 2 Spare bits + bref.advance_bits(2); + HANDLE_CODE(emergency_registered.unpack(bref)); + HANDLE_CODE(nssaa_to_be_performed.unpack(bref)); + HANDLE_CODE(sms_allowed.unpack(bref)); + HANDLE_CODE(registration_result.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: PLMN list +// Reference: 9.11.3.45 +SRSASN_CODE plmn_list_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: PLMN list +// Reference: 9.11.3.45 +SRSASN_CODE plmn_list_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: 5GS tracking area identity list +// Reference: 9.11.3.9 +SRSASN_CODE tracking_area_identity_list_5gs_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 7) { + asn1::log_error( + "Encoding Failed (5GS tracking area identity list): Packed length (%d) does not equal expected length 7", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GS tracking area identity list +// Reference: 9.11.3.9 +SRSASN_CODE tracking_area_identity_list_5gs_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 7) { + asn1::log_error("Decoding Failed (5GS tracking area identity list): Length (%d) does not equal expected length 7", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Rejected NSSAI +// Reference: 9.11.3.46 +SRSASN_CODE rejected_nssai_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Rejected NSSAI +// Reference: 9.11.3.46 +SRSASN_CODE rejected_nssai_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: 5GS network feature support +// Reference: 9.11.3.5 +SRSASN_CODE network_feature_support_5gs_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1 || length > 3) { + asn1::log_error( + "Encoding Failed (5GS network feature support): Packed length (%d) is not in range of min: 1 and max 3 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GS network feature support +// Reference: 9.11.3.5 +SRSASN_CODE network_feature_support_5gs_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1 || length > 3) { + asn1::log_error( + "Decoding Failed (5GS network feature support): Length (%d) is not in range of min: 1 and max 3 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: PDU session reactivation result +// Reference: 9.11.3.42 +SRSASN_CODE pdu_session_reactivation_result_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(psi_7, 1)); + HANDLE_CODE(bref.pack(psi_6, 1)); + HANDLE_CODE(bref.pack(psi_5, 1)); + HANDLE_CODE(bref.pack(psi_4, 1)); + HANDLE_CODE(bref.pack(psi_3, 1)); + HANDLE_CODE(bref.pack(psi_2, 1)); + HANDLE_CODE(bref.pack(psi_1, 1)); + HANDLE_CODE(bref.pack(psi_0, 1)); + HANDLE_CODE(bref.pack(psi_15, 1)); + HANDLE_CODE(bref.pack(psi_14, 1)); + HANDLE_CODE(bref.pack(psi_13, 1)); + HANDLE_CODE(bref.pack(psi_12, 1)); + HANDLE_CODE(bref.pack(psi_11, 1)); + HANDLE_CODE(bref.pack(psi_10, 1)); + HANDLE_CODE(bref.pack(psi_9, 1)); + HANDLE_CODE(bref.pack(psi_8, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 32) { + asn1::log_error("Encoding Failed (PDU session reactivation result): Packed length (%d) is not in range of min: 2 " + "and max 32 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: PDU session reactivation result +// Reference: 9.11.3.42 +SRSASN_CODE pdu_session_reactivation_result_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 32) { + asn1::log_error( + "Decoding Failed (PDU session reactivation result): Length (%d) is not in range of min: 2 and max 32 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + HANDLE_CODE(bref.unpack(psi_7, 1)); + HANDLE_CODE(bref.unpack(psi_6, 1)); + HANDLE_CODE(bref.unpack(psi_5, 1)); + HANDLE_CODE(bref.unpack(psi_4, 1)); + HANDLE_CODE(bref.unpack(psi_3, 1)); + HANDLE_CODE(bref.unpack(psi_2, 1)); + HANDLE_CODE(bref.unpack(psi_1, 1)); + HANDLE_CODE(bref.unpack(psi_0, 1)); + + HANDLE_CODE(bref.unpack(psi_15, 1)); + HANDLE_CODE(bref.unpack(psi_14, 1)); + HANDLE_CODE(bref.unpack(psi_13, 1)); + HANDLE_CODE(bref.unpack(psi_12, 1)); + HANDLE_CODE(bref.unpack(psi_11, 1)); + HANDLE_CODE(bref.unpack(psi_10, 1)); + HANDLE_CODE(bref.unpack(psi_9, 1)); + HANDLE_CODE(bref.unpack(psi_8, 1)); + + if (length > 2) { + HANDLE_CODE(bref.advance_bits((length - 2) * 8)); + } + return SRSASN_SUCCESS; +} + +// IE: PDU session reactivation result error cause +// Reference: 9.11.3.43 +SRSASN_CODE pdu_session_reactivation_result_error_cause_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + if (length < 2 || length > 512) { + asn1::log_error("Encoding Failed (PDU session reactivation result error cause): Packed length (%d) is not in range " + "of min: 2 and max 512 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: PDU session reactivation result error cause +// Reference: 9.11.3.43 +SRSASN_CODE pdu_session_reactivation_result_error_cause_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + if (length < 2 || length > 512) { + asn1::log_error("Decoding Failed (PDU session reactivation result error cause): Length (%d) is not in range of " + "min: 2 and max 512 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: LADN information +// Reference: 9.11.3.30 +SRSASN_CODE ladn_information_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MIN 0 not check because auf uint underflow + if (length > 1712) { + asn1::log_error("Encoding Failed (LADN information): Packed length (%d) is not in range of max 1712 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: LADN information +// Reference: 9.11.3.30 +SRSASN_CODE ladn_information_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MIN 0 not check because auf uint underflow + if (length > 1712) { + asn1::log_error("Decoding Failed (LADN information): Length (%d) is not in range of max 1712 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Service area list +// Reference: 9.11.3.49 +SRSASN_CODE service_area_list_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Service area list +// Reference: 9.11.3.49 +SRSASN_CODE service_area_list_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: GPRS timer 2 +// Reference: 9.11.2.4 +SRSASN_CODE gprs_timer_2_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(timer_value, 8)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (GPRS timer 2): Packed length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: GPRS timer 2 +// Reference: 9.11.2.4 +SRSASN_CODE gprs_timer_2_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (GPRS timer 2): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(timer_value, 8)); + return SRSASN_SUCCESS; +} + +// IE: Emergency number list +// Reference: 9.11.3.23 +SRSASN_CODE emergency_number_list_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 3 || length > 48) { + asn1::log_error( + "Encoding Failed (Emergency number list): Packed length (%d) is not in range of min: 3 and max 48 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Emergency number list +// Reference: 9.11.3.23 +SRSASN_CODE emergency_number_list_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 3 || length > 48) { + asn1::log_error("Decoding Failed (Emergency number list): Length (%d) is not in range of min: 3 and max 48 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Extended emergency number list +// Reference: 9.11.3.26 +SRSASN_CODE extended_emergency_number_list_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MAX 65535 not check because auf uint overflow + if (length < 4) { + asn1::log_error( + "Encoding Failed (Extended emergency number list): Packed length (%d) is not in range of min: 4 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: Extended emergency number list +// Reference: 9.11.3.26 +SRSASN_CODE extended_emergency_number_list_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MAX 65535 not check because auf uint overflow + if (length < 4) { + asn1::log_error("Decoding Failed (Extended emergency number list): Length (%d) is not in range of min: 4 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: SOR transparent container +// Reference: 9.11.3.51 +SRSASN_CODE sor_transparent_container_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + if (length < 17) { + asn1::log_error("Encoding Failed (SOR transparent container): Packed length (%d) is not in range of min: 17 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: SOR transparent container +// Reference: 9.11.3.51 +SRSASN_CODE sor_transparent_container_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + if (length < 17) { + asn1::log_error("Decoding Failed (SOR transparent container): Length (%d) is not in range of min: 17 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: EAP message +// Reference: 9.11.2.2 +SRSASN_CODE eap_message_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + HANDLE_CODE(bref.pack_bytes(eap_message.data(), eap_message.size())); + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + if (length < 4 || length > 1500) { + asn1::log_error("Encoding Failed (EAP message): Packed length (%d) is not in range of min: 4 and max 1500 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: EAP message +// Reference: 9.11.2.2 +SRSASN_CODE eap_message_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + if (length < 4 || length > 1500) { + asn1::log_error("Decoding Failed (EAP message): Length (%d) is not in range of min: 4 and max 1500 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + eap_message.resize(length); + HANDLE_CODE(bref.unpack_bytes(eap_message.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: NSSAI inclusion mode +// Reference: 9.11.3.37A +SRSASN_CODE nssai_inclusion_mode_t::pack(asn1::bit_ref& bref) +{ + // 2 Spare bits + HANDLE_CODE(bref.pack(0x0, 2)); + HANDLE_CODE(nssai_inclusion_mode.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: NSSAI inclusion mode +// Reference: 9.11.3.37A +SRSASN_CODE nssai_inclusion_mode_t::unpack(asn1::cbit_ref& bref) +{ + // 2 Spare bits + bref.advance_bits(2); + HANDLE_CODE(nssai_inclusion_mode.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Operator-defined access category definitions +// Reference: 9.11.3.38 +SRSASN_CODE operator_defined_access_category_definitions_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: Operator-defined access category definitions +// Reference: 9.11.3.38 +SRSASN_CODE operator_defined_access_category_definitions_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Non-3GPP NW provided policies +// Reference: 9.11.3.36A +SRSASN_CODE non_3_gpp_nw_provided_policies_t::pack(asn1::bit_ref& bref) +{ + // 3 Spare bits + HANDLE_CODE(bref.pack(0x0, 3)); + HANDLE_CODE(bref.pack(n3_en, 1)); + return SRSASN_SUCCESS; +} + +// IE: Non-3GPP NW provided policies +// Reference: 9.11.3.36A +SRSASN_CODE non_3_gpp_nw_provided_policies_t::unpack(asn1::cbit_ref& bref) +{ + // 3 Spare bits + bref.advance_bits(3); + HANDLE_CODE(bref.unpack(n3_en, 1)); + return SRSASN_SUCCESS; +} + +// IE: UE radio capability ID deletion indication +// Reference: 9.11.3.69 +SRSASN_CODE ue_radio_capability_id_deletion_indication_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(deletion_request.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: UE radio capability ID deletion indication +// Reference: 9.11.3.69 +SRSASN_CODE ue_radio_capability_id_deletion_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(deletion_request.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Ciphering key data +// Reference: 9.11.3.18C +SRSASN_CODE ciphering_key_data_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + if (length < 31 || length > 2672) { + asn1::log_error( + "Encoding Failed (Ciphering key data): Packed length (%d) is not in range of min: 31 and max 2672 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: Ciphering key data +// Reference: 9.11.3.18C +SRSASN_CODE ciphering_key_data_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + if (length < 31 || length > 2672) { + asn1::log_error("Decoding Failed (Ciphering key data): Length (%d) is not in range of min: 31 and max 2672 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: CAG information list +// Reference: 9.11.3.18A +SRSASN_CODE cag_information_list_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: CAG information list +// Reference: 9.11.3.18A +SRSASN_CODE cag_information_list_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Truncated 5G-S-TMSI configuration +// Reference: 9.11.3.70 +SRSASN_CODE truncated_5g_s_tmsi_configuration_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(truncated_amf__set_id_value, 4)); + HANDLE_CODE(bref.pack(truncated_amf__pointer_value, 4)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error( + "Encoding Failed (Truncated 5G-S-TMSI configuration): Packed length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Truncated 5G-S-TMSI configuration +// Reference: 9.11.3.70 +SRSASN_CODE truncated_5g_s_tmsi_configuration_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (Truncated 5G-S-TMSI configuration): Length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(truncated_amf__set_id_value, 4)); + HANDLE_CODE(bref.unpack(truncated_amf__pointer_value, 4)); + return SRSASN_SUCCESS; +} + +// IE: 5GMM cause +// Reference: 9.11.3.2 +SRSASN_CODE cause_5gmm_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(cause_5gmm.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GMM cause +// Reference: 9.11.3.2 +SRSASN_CODE cause_5gmm_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(cause_5gmm.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: De-registration type +// Reference: 9.11.3.20 +SRSASN_CODE de_registration_type_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(switch_off.pack(bref)); + HANDLE_CODE(re_registration_required.pack(bref)); + HANDLE_CODE(access_type.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: De-registration type +// Reference: 9.11.3.20 +SRSASN_CODE de_registration_type_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(switch_off.unpack(bref)); + HANDLE_CODE(re_registration_required.unpack(bref)); + HANDLE_CODE(access_type.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Spare half octet +// Reference: 9.5 +SRSASN_CODE spare_half_octet_t::pack(asn1::bit_ref& bref) +{ + // 4 Spare bits + HANDLE_CODE(bref.pack(0x0, 4)); + return SRSASN_SUCCESS; +} + +// IE: Spare half octet +// Reference: 9.5 +SRSASN_CODE spare_half_octet_t::unpack(asn1::cbit_ref& bref) +{ + // 4 Spare bits + bref.advance_bits(4); + return SRSASN_SUCCESS; +} + +// IE: Service type +// Reference: 9.11.3.50 +SRSASN_CODE service_type_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(service_type_value.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Service type +// Reference: 9.11.3.50 +SRSASN_CODE service_type_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(service_type_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Configuration update indication +// Reference: 9.11.3.18 +SRSASN_CODE configuration_update_indication_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(control_plane_service_type_value.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Configuration update indication +// Reference: 9.11.3.18 +SRSASN_CODE configuration_update_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(control_plane_service_type_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Network name +// Reference: 9.11.3.35 +SRSASN_CODE network_name_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Network name +// Reference: 9.11.3.35 +SRSASN_CODE network_name_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Time zone +// Reference: 9.11.3.52 +SRSASN_CODE time_zone_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(bref.pack(year, 8)); + HANDLE_CODE(bref.pack(month, 8)); + HANDLE_CODE(bref.pack(day, 8)); + HANDLE_CODE(bref.pack(hour, 8)); + HANDLE_CODE(bref.pack(second, 8)); + HANDLE_CODE(bref.pack(time_zone, 8)); + return SRSASN_SUCCESS; +} + +// IE: Time zone +// Reference: 9.11.3.52 +SRSASN_CODE time_zone_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(year, 8)); + HANDLE_CODE(bref.unpack(month, 8)); + HANDLE_CODE(bref.unpack(day, 8)); + HANDLE_CODE(bref.unpack(hour, 8)); + HANDLE_CODE(bref.unpack(second, 8)); + HANDLE_CODE(bref.unpack(time_zone, 8)); + return SRSASN_SUCCESS; +} + +// IE: Time zone and time +// Reference: 9.11.3.53 +SRSASN_CODE time_zone_and_time_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(bref.pack(time_zone, 8)); + return SRSASN_SUCCESS; +} + +// IE: Time zone and time +// Reference: 9.11.3.53 +SRSASN_CODE time_zone_and_time_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(time_zone, 8)); + return SRSASN_SUCCESS; +} + +// IE: Daylight saving time +// Reference: 9.11.3.19 +SRSASN_CODE daylight_saving_time_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(value.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (Daylight saving time): Packed length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Daylight saving time +// Reference: 9.11.3.19 +SRSASN_CODE daylight_saving_time_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (Daylight saving time): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: SMS indication +// Reference: 9.11.3.50A +SRSASN_CODE sms_indication_t::pack(asn1::bit_ref& bref) +{ + // 3 Spare bits + HANDLE_CODE(bref.pack(0x0, 3)); + HANDLE_CODE(bref.pack(sms_availability_indication, 1)); + return SRSASN_SUCCESS; +} + +// IE: SMS indication +// Reference: 9.11.3.50A +SRSASN_CODE sms_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 3 Spare bits + bref.advance_bits(3); + HANDLE_CODE(bref.unpack(sms_availability_indication, 1)); + return SRSASN_SUCCESS; +} + +// IE: Additional configuration indication +// Reference: 9.11.3.74 +SRSASN_CODE additional_configuration_indication_t::pack(asn1::bit_ref& bref) +{ + // 3 Spare bits + HANDLE_CODE(bref.pack(0x0, 3)); + HANDLE_CODE(scmr.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Additional configuration indication +// Reference: 9.11.3.74 +SRSASN_CODE additional_configuration_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 3 Spare bits + bref.advance_bits(3); + HANDLE_CODE(scmr.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: ABBA +// Reference: 9.11.3.10 +SRSASN_CODE abba_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(abba_contents.data(), abba_contents.size())); + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2) { + asn1::log_error("Encoding Failed (ABBA): Packed length (%d) is not in range of min: 2 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: ABBA +// Reference: 9.11.3.10 +SRSASN_CODE abba_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2) { + asn1::log_error("Decoding Failed (ABBA): Length (%d) is not in range of min: 2 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + abba_contents.resize(length); + HANDLE_CODE(bref.unpack_bytes(abba_contents.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Authentication parameter RAND +// Reference: 9.11.3.16 +SRSASN_CODE authentication_parameter_rand_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(bref.pack_bytes(rand.data(), 16)); + return SRSASN_SUCCESS; +} + +// IE: Authentication parameter RAND +// Reference: 9.11.3.16 +SRSASN_CODE authentication_parameter_rand_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack_bytes(rand.data(), 16)); + return SRSASN_SUCCESS; +} + +// IE: Authentication parameter AUTN +// Reference: 9.11.3.15 +SRSASN_CODE authentication_parameter_autn_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(autn.data(), autn.size())); + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 16) { + asn1::log_error( + "Encoding Failed (Authentication parameter AUTN): Packed length (%d) does not equal expected length 16", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Authentication parameter AUTN +// Reference: 9.11.3.15 +SRSASN_CODE authentication_parameter_autn_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 16) { + asn1::log_error("Decoding Failed (Authentication parameter AUTN): Length (%d) does not equal expected length 16", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + autn.resize(length); + HANDLE_CODE(bref.unpack_bytes(autn.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Authentication response parameter +// Reference: 9.11.3.17 +SRSASN_CODE authentication_response_parameter_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(res.data(), res.size())); + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 16) { + asn1::log_error( + "Encoding Failed (Authentication response parameter): Packed length (%d) does not equal expected length 16", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Authentication response parameter +// Reference: 9.11.3.17 +SRSASN_CODE authentication_response_parameter_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 16) { + asn1::log_error( + "Decoding Failed (Authentication response parameter): Length (%d) does not equal expected length 16", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + res.resize(length); + HANDLE_CODE(bref.unpack_bytes(res.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Authentication failure parameter +// Reference: 9.11.3.14 +SRSASN_CODE authentication_failure_parameter_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(auth_failure.data(), auth_failure.size())); + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 14) { + asn1::log_error( + "Encoding Failed (Authentication failure parameter): Packed length (%d) does not equal expected length 14", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Authentication failure parameter +// Reference: 9.11.3.14 +SRSASN_CODE authentication_failure_parameter_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 14) { + asn1::log_error("Decoding Failed (Authentication failure parameter): Length (%d) does not equal expected length 14", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + auth_failure.resize(length); + HANDLE_CODE(bref.unpack_bytes(auth_failure.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: 5GS identity type +// Reference: 9.11.3.3 +SRSASN_CODE identity_type_5gs_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(type_of_identity.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GS identity type +// Reference: 9.11.3.3 +SRSASN_CODE identity_type_5gs_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(type_of_identity.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: security algorithms +// Reference: 9.11.3.34 +SRSASN_CODE security_algorithms_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(ciphering_algorithm.pack(bref)); + HANDLE_CODE(integrity_protection_algorithm.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: security algorithms +// Reference: 9.11.3.34 +SRSASN_CODE security_algorithms_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(ciphering_algorithm.unpack(bref)); + HANDLE_CODE(integrity_protection_algorithm.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: IMEISV request +// Reference: 9.11.3.28 +SRSASN_CODE imeisv_request_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(imeisv_request.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: IMEISV request +// Reference: 9.11.3.28 +SRSASN_CODE imeisv_request_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(imeisv_request.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: EPS NAS security algorithms +// Reference: 9.11.3.25 +SRSASN_CODE eps_nas_security_algorithms_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(ciphering_algorithm.pack(bref)); + + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(integrity_protection_algorithm.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: EPS NAS security algorithms +// Reference: 9.11.3.25 +SRSASN_CODE eps_nas_security_algorithms_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(ciphering_algorithm.unpack(bref)); + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(integrity_protection_algorithm.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Additional 5G security information +// Reference: 9.11.3.12 +SRSASN_CODE additional_5g_security_information_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 6 Spare bits + HANDLE_CODE(bref.pack(0x0, 6)); + HANDLE_CODE(bref.pack(rinmr, 1)); + HANDLE_CODE(bref.pack(hdp, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error( + "Encoding Failed (Additional 5G security information): Packed length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Additional 5G security information +// Reference: 9.11.3.12 +SRSASN_CODE additional_5g_security_information_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error( + "Decoding Failed (Additional 5G security information): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 6 Spare bits + bref.advance_bits(6); + HANDLE_CODE(bref.unpack(rinmr, 1)); + HANDLE_CODE(bref.unpack(hdp, 1)); + return SRSASN_SUCCESS; +} + +// IE: S1 UE security capability +// Reference: 9.11.3.48A +SRSASN_CODE s1_ue_security_capability_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(eea0, 1)); + HANDLE_CODE(bref.pack(eea1_128, 1)); + HANDLE_CODE(bref.pack(eea2_128, 1)); + HANDLE_CODE(bref.pack(eea3_128, 1)); + HANDLE_CODE(bref.pack(eea4, 1)); + HANDLE_CODE(bref.pack(eea5, 1)); + HANDLE_CODE(bref.pack(eea6, 1)); + HANDLE_CODE(bref.pack(eea7, 1)); + HANDLE_CODE(bref.pack(eia0, 1)); + HANDLE_CODE(bref.pack(eia1_128, 1)); + HANDLE_CODE(bref.pack(eia2_128, 1)); + HANDLE_CODE(bref.pack(eia3_128, 1)); + HANDLE_CODE(bref.pack(eia4, 1)); + HANDLE_CODE(bref.pack(eia5, 1)); + HANDLE_CODE(bref.pack(eia6, 1)); + HANDLE_CODE(bref.pack(eia7, 1)); + HANDLE_CODE(bref.pack(uea0, 1)); + HANDLE_CODE(bref.pack(uea1, 1)); + HANDLE_CODE(bref.pack(uea2, 1)); + HANDLE_CODE(bref.pack(uea3, 1)); + HANDLE_CODE(bref.pack(uea4, 1)); + HANDLE_CODE(bref.pack(uea5, 1)); + HANDLE_CODE(bref.pack(uea6, 1)); + HANDLE_CODE(bref.pack(uea7, 1)); + + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(bref.pack(uia1, 1)); + HANDLE_CODE(bref.pack(uia2, 1)); + HANDLE_CODE(bref.pack(uia3, 1)); + HANDLE_CODE(bref.pack(uia4, 1)); + HANDLE_CODE(bref.pack(uia5, 1)); + HANDLE_CODE(bref.pack(uia6, 1)); + HANDLE_CODE(bref.pack(uia7, 1)); + + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(bref.pack(gea1, 1)); + HANDLE_CODE(bref.pack(gea2, 1)); + HANDLE_CODE(bref.pack(gea3, 1)); + HANDLE_CODE(bref.pack(gea4, 1)); + HANDLE_CODE(bref.pack(gea5, 1)); + HANDLE_CODE(bref.pack(gea6, 1)); + HANDLE_CODE(bref.pack(gea7, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 2 || length > 5) { + asn1::log_error( + "Encoding Failed (S1 UE security capability): Packed length (%d) is not in range of min: 2 and max 5 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: S1 UE security capability +// Reference: 9.11.3.48A +SRSASN_CODE s1_ue_security_capability_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 2 || length > 5) { + asn1::log_error( + "Decoding Failed (S1 UE security capability): Length (%d) is not in range of min: 2 and max 5 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(eea0, 1)); + HANDLE_CODE(bref.unpack(eea1_128, 1)); + HANDLE_CODE(bref.unpack(eea2_128, 1)); + HANDLE_CODE(bref.unpack(eea3_128, 1)); + HANDLE_CODE(bref.unpack(eea4, 1)); + HANDLE_CODE(bref.unpack(eea5, 1)); + HANDLE_CODE(bref.unpack(eea6, 1)); + HANDLE_CODE(bref.unpack(eea7, 1)); + + HANDLE_CODE(bref.unpack(eia0, 1)); + HANDLE_CODE(bref.unpack(eia1_128, 1)); + HANDLE_CODE(bref.unpack(eia2_128, 1)); + HANDLE_CODE(bref.unpack(eia3_128, 1)); + HANDLE_CODE(bref.unpack(eia4, 1)); + HANDLE_CODE(bref.unpack(eia5, 1)); + HANDLE_CODE(bref.unpack(eia6, 1)); + HANDLE_CODE(bref.unpack(eia7, 1)); + + if (length < 3) { + return SRSASN_SUCCESS; + } + + HANDLE_CODE(bref.unpack(uea0, 1)); + HANDLE_CODE(bref.unpack(uea1, 1)); + HANDLE_CODE(bref.unpack(uea2, 1)); + HANDLE_CODE(bref.unpack(uea3, 1)); + HANDLE_CODE(bref.unpack(uea4, 1)); + HANDLE_CODE(bref.unpack(uea5, 1)); + HANDLE_CODE(bref.unpack(uea6, 1)); + HANDLE_CODE(bref.unpack(uea7, 1)); + + if (length < 4) { + return SRSASN_SUCCESS; + } + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(bref.unpack(uia1, 1)); + HANDLE_CODE(bref.unpack(uia2, 1)); + HANDLE_CODE(bref.unpack(uia3, 1)); + HANDLE_CODE(bref.unpack(uia4, 1)); + HANDLE_CODE(bref.unpack(uia5, 1)); + HANDLE_CODE(bref.unpack(uia6, 1)); + HANDLE_CODE(bref.unpack(uia7, 1)); + + if (length < 5) { + return SRSASN_SUCCESS; + } + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(bref.unpack(gea1, 1)); + HANDLE_CODE(bref.unpack(gea2, 1)); + HANDLE_CODE(bref.unpack(gea3, 1)); + HANDLE_CODE(bref.unpack(gea4, 1)); + HANDLE_CODE(bref.unpack(gea5, 1)); + HANDLE_CODE(bref.unpack(gea6, 1)); + HANDLE_CODE(bref.unpack(gea7, 1)); + return SRSASN_SUCCESS; +} + +// IE: Access type +// Reference: 9.11.2.1A +SRSASN_CODE access_type_t::pack(asn1::bit_ref& bref) +{ + // 2 Spare bits + HANDLE_CODE(bref.pack(0x0, 2)); + HANDLE_CODE(access_type_value.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Access type +// Reference: 9.11.2.1A +SRSASN_CODE access_type_t::unpack(asn1::cbit_ref& bref) +{ + // 2 Spare bits + bref.advance_bits(2); + HANDLE_CODE(access_type_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: PDU session identity 2 +// Reference: 9.11.3.41 +SRSASN_CODE pdu_session_identity_2_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(bref.pack(pdu_session_identity_2_value, 8)); + return SRSASN_SUCCESS; +} + +// IE: PDU session identity 2 +// Reference: 9.11.3.41 +SRSASN_CODE pdu_session_identity_2_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(pdu_session_identity_2_value, 8)); + return SRSASN_SUCCESS; +} + +// IE: Request type +// Reference: 9.11.3.47 +SRSASN_CODE request_type_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(request_type_value.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Request type +// Reference: 9.11.3.47 +SRSASN_CODE request_type_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(request_type_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: S-NSSAI +// Reference: 9.11.2.8 +SRSASN_CODE s_nssai_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + if (length == s_nssai_t::SST_type_::options::sst) { + HANDLE_CODE(bref.pack(sst, 8)); + } else if (length == s_nssai_t::SST_type_::options::sst_and_mapped_hplmn_sst) { + HANDLE_CODE(bref.pack(sst, 8)); + HANDLE_CODE(bref.pack(mapped_hplmn_sst, 8)); + } else if (length == s_nssai_t::SST_type_::options::sst_and_sd) { + HANDLE_CODE(bref.pack(sst, 8)); + HANDLE_CODE(bref.pack(sd, 24)); + } else if (length == s_nssai_t::SST_type_::options::sst_sd_mapped_hplmn_sst_and_mapped_hplmn_sd) { + HANDLE_CODE(bref.pack(sst, 8)); + HANDLE_CODE(bref.pack(sd, 24)); + HANDLE_CODE(bref.pack(mapped_hplmn_sst, 8)); + HANDLE_CODE(bref.pack(mapped_hplmn_sd, 24)); + } else { + asn1::log_error("Not such a length type for s_nssai"); + return SRSASN_ERROR_ENCODE_FAIL; + } + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1 || length > 8) { + asn1::log_error("Encoding Failed (S-NSSAI): Packed length (%d) is not in range of min: 1 and max 8 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: S-NSSAI +// Reference: 9.11.2.8 +SRSASN_CODE s_nssai_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1 || length > 8) { + asn1::log_error("Decoding Failed (S-NSSAI): Length (%d) is not in range of min: 1 and max 8 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + if (length == s_nssai_t::SST_type_::options::sst) { + HANDLE_CODE(bref.unpack(sst, 8)); + } else if (length == s_nssai_t::SST_type_::options::sst_and_mapped_hplmn_sst) { + HANDLE_CODE(bref.unpack(sst, 8)); + HANDLE_CODE(bref.unpack(mapped_hplmn_sst, 8)); + } else if (length == s_nssai_t::SST_type_::options::sst_and_sd) { + HANDLE_CODE(bref.unpack(sst, 8)); + HANDLE_CODE(bref.unpack(sd, 24)); + } else if (length == s_nssai_t::SST_type_::options::sst_sd_mapped_hplmn_sst_and_mapped_hplmn_sd) { + HANDLE_CODE(bref.unpack(sst, 8)); + HANDLE_CODE(bref.unpack(sd, 24)); + HANDLE_CODE(bref.unpack(mapped_hplmn_sst, 8)); + HANDLE_CODE(bref.unpack(mapped_hplmn_sd, 24)); + } else { + asn1::log_error("Not such a length type for s_nssai"); + return SRSASN_ERROR_DECODE_FAIL; + } + return SRSASN_SUCCESS; +} + +// IE: DNN +// Reference: 9.11.2.1B +SRSASN_CODE dnn_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(dnn_value.data(), dnn_value.size())); + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1 || length > 100) { + asn1::log_error("Encoding Failed (DNN): Packed length (%d) is not in range of min: 1 and max 100 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: DNN +// Reference: 9.11.2.1B +SRSASN_CODE dnn_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1 || length > 100) { + asn1::log_error("Decoding Failed (DNN): Length (%d) is not in range of min: 1 and max 100 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + dnn_value.resize(length); + HANDLE_CODE(bref.unpack_bytes(dnn_value.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Additional information +// Reference: 9.11.2.1 +SRSASN_CODE additional_information_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(additional_information_value.data(), additional_information_value.size())); + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1) { + asn1::log_error("Encoding Failed (Additional information): Packed length (%d) is not in range of min: 1 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Additional information +// Reference: 9.11.2.1 +SRSASN_CODE additional_information_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1) { + asn1::log_error("Decoding Failed (Additional information): Length (%d) is not in range of min: 1 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + additional_information_value.resize(length); + HANDLE_CODE(bref.unpack_bytes(additional_information_value.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: MA PDU session information +// Reference: 9.11.3.31A +SRSASN_CODE ma_pdu_session_information_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(ma_pdu_session_information_value.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: MA PDU session information +// Reference: 9.11.3.31A +SRSASN_CODE ma_pdu_session_information_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(ma_pdu_session_information_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Release assistance indication +// Reference: 9.11.3.46A +SRSASN_CODE release_assistance_indication_t::pack(asn1::bit_ref& bref) +{ + // 2 Spare bits + HANDLE_CODE(bref.pack(0x0, 2)); + HANDLE_CODE(downlink_data_expected.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Release assistance indication +// Reference: 9.11.3.46A +SRSASN_CODE release_assistance_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 2 Spare bits + bref.advance_bits(2); + HANDLE_CODE(downlink_data_expected.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Integrity protection maximum data rate +// Reference: 9.11.4.7 +SRSASN_CODE integrity_protection_maximum_data_rate_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(max_data_rate_upip_uplink.pack(bref)); + HANDLE_CODE(max_data_rate_upip_downlink.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Integrity protection maximum data rate +// Reference: 9.11.4.7 +SRSASN_CODE integrity_protection_maximum_data_rate_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(max_data_rate_upip_uplink.unpack(bref)); + HANDLE_CODE(max_data_rate_upip_downlink.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: PDU session type +// Reference: 9.11.4.11 +SRSASN_CODE pdu_session_type_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(pdu_session_type_value.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: PDU session type +// Reference: 9.11.4.11 +SRSASN_CODE pdu_session_type_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(pdu_session_type_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: SSC mode +// Reference: 9.11.4.16 +SRSASN_CODE ssc_mode_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(ssc_mode_value.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: SSC mode +// Reference: 9.11.4.16 +SRSASN_CODE ssc_mode_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(ssc_mode_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GSM capability +// Reference: 9.11.4.1 +SRSASN_CODE capability_5gsm_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1 || length > 13) { + asn1::log_error("Encoding Failed (5GSM capability): Packed length (%d) is not in range of min: 1 and max 13 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GSM capability +// Reference: 9.11.4.1 +SRSASN_CODE capability_5gsm_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1 || length > 13) { + asn1::log_error("Decoding Failed (5GSM capability): Length (%d) is not in range of min: 1 and max 13 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: Maximum number of supported packet filters +// Reference: 9.11.4.9 +SRSASN_CODE maximum_number_of_supported_packet_filters_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(bref.pack(maximum_number_of_supported_packet_filters, 11)); + + // 5 Spare bits + HANDLE_CODE(bref.pack(0x0, 5)); + return SRSASN_SUCCESS; +} + +// IE: Maximum number of supported packet filters +// Reference: 9.11.4.9 +SRSASN_CODE maximum_number_of_supported_packet_filters_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(maximum_number_of_supported_packet_filters, 11)); + // 5 Spare bits + bref.advance_bits(5); + return SRSASN_SUCCESS; +} + +// IE: Always-on PDU session requested +// Reference: 9.11.4.4 +SRSASN_CODE always_on_pdu_session_requested_t::pack(asn1::bit_ref& bref) +{ + // 3 Spare bits + HANDLE_CODE(bref.pack(0x0, 3)); + HANDLE_CODE(bref.pack(apsi, 1)); + return SRSASN_SUCCESS; +} + +// IE: Always-on PDU session requested +// Reference: 9.11.4.4 +SRSASN_CODE always_on_pdu_session_requested_t::unpack(asn1::cbit_ref& bref) +{ + // 3 Spare bits + bref.advance_bits(3); + HANDLE_CODE(bref.unpack(apsi, 1)); + return SRSASN_SUCCESS; +} + +// IE: SM PDU DN request container +// Reference: 9.11.4.15 +SRSASN_CODE sm_pdu_dn_request_container_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(dn_specific_identity.data(), dn_specific_identity.size())); + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1 || length > 253) { + asn1::log_error( + "Encoding Failed (SM PDU DN request container): Packed length (%d) is not in range of min: 1 and max 253 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: SM PDU DN request container +// Reference: 9.11.4.15 +SRSASN_CODE sm_pdu_dn_request_container_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1 || length > 253) { + asn1::log_error( + "Decoding Failed (SM PDU DN request container): Length (%d) is not in range of min: 1 and max 253 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + dn_specific_identity.resize(length); + HANDLE_CODE(bref.unpack_bytes(dn_specific_identity.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Extended protocol configuration options +// Reference: 9.11.4.6 +SRSASN_CODE extended_protocol_configuration_options_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MAX 65535 not check because auf uint overflow + if (length < 1) { + asn1::log_error( + "Encoding Failed (Extended protocol configuration options): Packed length (%d) is not in range of min: 1 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: Extended protocol configuration options +// Reference: 9.11.4.6 +SRSASN_CODE extended_protocol_configuration_options_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MAX 65535 not check because auf uint overflow + if (length < 1) { + asn1::log_error( + "Decoding Failed (Extended protocol configuration options): Length (%d) is not in range of min: 1 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: IP header compression configuration +// Reference: 9.11.4.24 +SRSASN_CODE ip_header_compression_configuration_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + // MAX 255 not check because auf uint overflow + if (length < 3) { + asn1::log_error( + "Encoding Failed (IP header compression configuration): Packed length (%d) is not in range of min: 3 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: IP header compression configuration +// Reference: 9.11.4.24 +SRSASN_CODE ip_header_compression_configuration_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + // MAX 255 not check because auf uint overflow + if (length < 3) { + asn1::log_error( + "Decoding Failed (IP header compression configuration): Length (%d) is not in range of min: 3 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: DS-TT Ethernet port MAC address +// Reference: 9.11.4.25 +SRSASN_CODE ds_tt__ethernet_port_mac_address_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(ds_tt__ethernet_port_mac_address_contents.data(), 6)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 6) { + asn1::log_error( + "Encoding Failed (DS-TT Ethernet port MAC address): Packed length (%d) does not equal expected length 6", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: DS-TT Ethernet port MAC address +// Reference: 9.11.4.25 +SRSASN_CODE ds_tt__ethernet_port_mac_address_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 6) { + asn1::log_error("Decoding Failed (DS-TT Ethernet port MAC address): Length (%d) does not equal expected length 6", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack_bytes(ds_tt__ethernet_port_mac_address_contents.data(), 6)); + return SRSASN_SUCCESS; +} + +// IE: UE-DS-TT residence time +// Reference: 9.11.4.26 +SRSASN_CODE ue_ds_tt_residence_time_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack_bytes(ue_ds_tt_residence_time_contents.data(), 8)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 8) { + asn1::log_error("Encoding Failed (UE-DS-TT residence time): Packed length (%d) does not equal expected length 8", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: UE-DS-TT residence time +// Reference: 9.11.4.26 +SRSASN_CODE ue_ds_tt_residence_time_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 8) { + asn1::log_error("Decoding Failed (UE-DS-TT residence time): Length (%d) does not equal expected length 8", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack_bytes(ue_ds_tt_residence_time_contents.data(), 8)); + return SRSASN_SUCCESS; +} + +// IE: Port management information container +// Reference: 9.11.4.27 +SRSASN_CODE port_management_information_container_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + HANDLE_CODE( + bref.pack_bytes(port_management_information_container.data(), port_management_information_container.size())); + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MAX 65535 not check because auf uint overflow + if (length < 1) { + asn1::log_error( + "Encoding Failed (Port management information container): Packed length (%d) is not in range of min: 1 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: Port management information container +// Reference: 9.11.4.27 +SRSASN_CODE port_management_information_container_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MAX 65535 not check because auf uint overflow + if (length < 1) { + asn1::log_error( + "Decoding Failed (Port management information container): Length (%d) is not in range of min: 1 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + port_management_information_container.resize(length); + HANDLE_CODE(bref.unpack_bytes(port_management_information_container.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Ethernet header compression configuration +// Reference: 9.11.4.28 +SRSASN_CODE ethernet_header_compression_configuration_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 6 Spare bits + HANDLE_CODE(bref.pack(0x0, 6)); + HANDLE_CODE(cid__length.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (Ethernet header compression configuration): Packed length (%d) does not equal " + "expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Ethernet header compression configuration +// Reference: 9.11.4.28 +SRSASN_CODE ethernet_header_compression_configuration_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error( + "Decoding Failed (Ethernet header compression configuration): Length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 6 Spare bits + bref.advance_bits(6); + HANDLE_CODE(cid__length.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: PDU address +// Reference: 9.11.4.10 +SRSASN_CODE pdu_address_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 4 Spare bits + HANDLE_CODE(bref.pack(0x0, 4)); + HANDLE_CODE(bref.pack(si6_lla, 1)); + HANDLE_CODE(pdu_session_type_value.pack(bref)); + + if (pdu_session_type_value == pdu_address_t::PDU_session_type_value_type_::options::ipv4) { + HANDLE_CODE(bref.pack_bytes(ipv4.data(), 4)); + } else if (pdu_session_type_value == pdu_address_t::PDU_session_type_value_type_::options::ipv6) { + HANDLE_CODE(bref.pack_bytes(ipv6.data(), 16)); + } else if (pdu_session_type_value == pdu_address_t::PDU_session_type_value_type_::options::ipv4v6) { + HANDLE_CODE(bref.pack_bytes(ipv6.data(), 16)); + HANDLE_CODE(bref.pack_bytes(ipv4.data(), 4)); + } + + if (si6_lla == true) { + HANDLE_CODE(bref.pack_bytes(smf_i_pv6_link_local_address.data(), 16)); + } + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 5 || length > 29) { + asn1::log_error("Encoding Failed (PDU address): Packed length (%d) is not in range of min: 5 and max 29 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: PDU address +// Reference: 9.11.4.10 +SRSASN_CODE pdu_address_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 5 || length > 29) { + asn1::log_error("Decoding Failed (PDU address): Length (%d) is not in range of min: 5 and max 29 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 4 Spare bits + bref.advance_bits(4); + HANDLE_CODE(bref.unpack(si6_lla, 1)); + HANDLE_CODE(pdu_session_type_value.unpack(bref)); + if (length == 5 && pdu_session_type_value == pdu_address_t::PDU_session_type_value_type_::options::ipv4 && + si6_lla == false) { + HANDLE_CODE(bref.unpack_bytes(ipv4.data(), 4)); + } else if (length == 9 && pdu_session_type_value == pdu_address_t::PDU_session_type_value_type_::options::ipv6 && + si6_lla == false) { + HANDLE_CODE(bref.unpack_bytes(ipv6.data(), 16)); + } else if (length == 13 && pdu_session_type_value == pdu_address_t::PDU_session_type_value_type_::options::ipv4v6 && + si6_lla == false) { + HANDLE_CODE(bref.unpack_bytes(ipv6.data(), 16)); + HANDLE_CODE(bref.unpack_bytes(ipv4.data(), 4)); + } else if (length == 25 && pdu_session_type_value == pdu_address_t::PDU_session_type_value_type_::options::ipv6 && + si6_lla == true) { + HANDLE_CODE(bref.unpack_bytes(ipv6.data(), 16)); + HANDLE_CODE(bref.unpack_bytes(smf_i_pv6_link_local_address.data(), 16)); + } else if (length == 29 && pdu_session_type_value == pdu_address_t::PDU_session_type_value_type_::options::ipv4v6 && + si6_lla == true) { + HANDLE_CODE(bref.unpack_bytes(ipv6.data(), 16)); + HANDLE_CODE(bref.unpack_bytes(ipv4.data(), 4)); + HANDLE_CODE(bref.unpack_bytes(smf_i_pv6_link_local_address.data(), 16)); + } else { + asn1::log_error("Not expected combination of length and type field"); + return SRSASN_ERROR_DECODE_FAIL; + } + return SRSASN_SUCCESS; +} + +// IE: QoS rules +// Reference: 9.11.4.13 +SRSASN_CODE qo_s_rules_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MAX 65535 not check because auf uint overflow + if (length < 4) { + asn1::log_error("Encoding Failed (QoS rules): Packed length (%d) is not in range of min: 4 bytes", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: QoS rules +// Reference: 9.11.4.13 +SRSASN_CODE qo_s_rules_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MAX 65535 not check because auf uint overflow + if (length < 4) { + asn1::log_error("Decoding Failed (QoS rules): Length (%d) is not in range of min: 4 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.advance_bits(length * 8)); + return SRSASN_SUCCESS; +} + +// IE: Session-AMBR +// Reference: 9.11.4.14 +SRSASN_CODE session_ambr_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(unit_session_ambr_for_downlink.pack(bref)); + HANDLE_CODE(bref.pack(session_ambr_for_downlink, 16)); + HANDLE_CODE(unit_session_ambr_for_uplink.pack(bref)); + HANDLE_CODE(bref.pack(session_ambr_for_uplink, 16)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 6) { + asn1::log_error("Encoding Failed (Session-AMBR): Packed length (%d) does not equal expected length 6", length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Session-AMBR +// Reference: 9.11.4.14 +SRSASN_CODE session_ambr_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 6) { + asn1::log_error("Decoding Failed (Session-AMBR): Length (%d) does not equal expected length 6", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(unit_session_ambr_for_downlink.unpack(bref)); + HANDLE_CODE(bref.unpack(session_ambr_for_downlink, 16)); + HANDLE_CODE(unit_session_ambr_for_uplink.unpack(bref)); + HANDLE_CODE(bref.unpack(session_ambr_for_uplink, 16)); + return SRSASN_SUCCESS; +} + +// IE: 5GSM cause +// Reference: 9.11.4.2 +SRSASN_CODE cause_5gsm_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(cause_value.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GSM cause +// Reference: 9.11.4.2 +SRSASN_CODE cause_5gsm_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(cause_value.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: GPRS timer +// Reference: 9.11.2.3 +SRSASN_CODE gprs_timer_t::pack(asn1::bit_ref& bref) +{ + HANDLE_CODE(unit.pack(bref)); + HANDLE_CODE(bref.pack(timer_value, 5)); + return SRSASN_SUCCESS; +} + +// IE: GPRS timer +// Reference: 9.11.2.3 +SRSASN_CODE gprs_timer_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(unit.unpack(bref)); + HANDLE_CODE(bref.unpack(timer_value, 5)); + return SRSASN_SUCCESS; +} + +// IE: Always-on PDU session indication +// Reference: 9.11.4.3 +SRSASN_CODE always_on_pdu_session_indication_t::pack(asn1::bit_ref& bref) +{ + // 3 Spare bits + HANDLE_CODE(bref.pack(0x0, 3)); + HANDLE_CODE(bref.pack(apsr, 1)); + return SRSASN_SUCCESS; +} + +// IE: Always-on PDU session indication +// Reference: 9.11.4.3 +SRSASN_CODE always_on_pdu_session_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 3 Spare bits + bref.advance_bits(3); + HANDLE_CODE(bref.unpack(apsr, 1)); + return SRSASN_SUCCESS; +} + +// IE: Mapped EPS bearer contexts +// Reference: 9.11.4.8 +SRSASN_CODE mapped_eps_bearer_contexts_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MAX 65535 not check because auf uint overflow + if (length < 4) { + asn1::log_error("Encoding Failed (Mapped EPS bearer contexts): Packed length (%d) is not in range of min: 4 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: Mapped EPS bearer contexts +// Reference: 9.11.4.8 +SRSASN_CODE mapped_eps_bearer_contexts_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MAX 65535 not check because auf uint overflow + if (length < 4) { + asn1::log_error("Decoding Failed (Mapped EPS bearer contexts): Length (%d) is not in range of min: 4 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: QoS flow descriptions +// Reference: 9.11.4.12 +SRSASN_CODE qo_s_flow_descriptions_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + // TODO proper packing + + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MAX 65535 not check because auf uint overflow + if (length < 3) { + asn1::log_error("Encoding Failed (QoS flow descriptions): Packed length (%d) is not in range of min: 3 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: QoS flow descriptions +// Reference: 9.11.4.12 +SRSASN_CODE qo_s_flow_descriptions_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MAX 65535 not check because auf uint overflow + if (length < 3) { + asn1::log_error("Decoding Failed (QoS flow descriptions): Length (%d) is not in range of min: 3 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + + // TODO proper unpacking + bref.advance_bits(length * 8); + return SRSASN_SUCCESS; +} + +// IE: 5GSM network feature support +// Reference: 9.11.4.18 +SRSASN_CODE network_feature_support_5gsm_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 7 Spare bits + HANDLE_CODE(bref.pack(0x0, 7)); + HANDLE_CODE(ept_s1.pack(bref)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length < 1 || length > 13) { + asn1::log_error( + "Encoding Failed (5GSM network feature support): Packed length (%d) is not in range of min: 1 and max 13 bytes", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: 5GSM network feature support +// Reference: 9.11.4.18 +SRSASN_CODE network_feature_support_5gsm_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length < 1 || length > 13) { + asn1::log_error( + "Decoding Failed (5GSM network feature support): Length (%d) is not in range of min: 1 and max 13 bytes", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 7 Spare bits + bref.advance_bits(7); + HANDLE_CODE(ept_s1.unpack(bref)); + if (length > 1) { + HANDLE_CODE(bref.advance_bits((length - 1) * 8)); + } + return SRSASN_SUCCESS; +} + +// IE: Serving PLMN rate control +// Reference: 9.11.4.20 +SRSASN_CODE serving_plmn_rate_control_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + HANDLE_CODE(bref.pack(serving_plmn_rate_control_value, 16)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 2) { + asn1::log_error("Encoding Failed (Serving PLMN rate control): Packed length (%d) does not equal expected length 2", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Serving PLMN rate control +// Reference: 9.11.4.20 +SRSASN_CODE serving_plmn_rate_control_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 2) { + asn1::log_error("Decoding Failed (Serving PLMN rate control): Length (%d) does not equal expected length 2", + length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + HANDLE_CODE(bref.unpack(serving_plmn_rate_control_value, 16)); + return SRSASN_SUCCESS; +} + +// IE: ATSSS container +// Reference: 9.11.4.22 +SRSASN_CODE atsss_container_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(16)); + + HANDLE_CODE(bref.pack_bytes(nas_message_container.data(), nas_message_container.size())); + bref.align_bytes_zero(); + uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + + // MIN 0 not check because auf uint underflow + // MAX 65535 not check because auf uint overflow + HANDLE_CODE(bref_length.pack(length, 16)); + return SRSASN_SUCCESS; +} + +// IE: ATSSS container +// Reference: 9.11.4.22 +SRSASN_CODE atsss_container_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 16)); + // MIN 0 not check because auf uint underflow + if (length > 65535) { + asn1::log_error("Decoding Failed (ATSSS container): Length (%d) is not in range of max 65535 bytes", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + nas_message_container.resize(length); + HANDLE_CODE(bref.unpack_bytes(nas_message_container.data(), length)); + return SRSASN_SUCCESS; +} + +// IE: Control plane only indication +// Reference: 9.11.4.23 +SRSASN_CODE control_plane_only_indication_t::pack(asn1::bit_ref& bref) +{ + // 3 Spare bits + HANDLE_CODE(bref.pack(0x0, 3)); + HANDLE_CODE(bref.pack(cpoi, 1)); + return SRSASN_SUCCESS; +} + +// IE: Control plane only indication +// Reference: 9.11.4.23 +SRSASN_CODE control_plane_only_indication_t::unpack(asn1::cbit_ref& bref) +{ + // 3 Spare bits + bref.advance_bits(3); + HANDLE_CODE(bref.unpack(cpoi, 1)); + return SRSASN_SUCCESS; +} + +// IE: Allowed SSC mode +// Reference: 9.11.4.5 +SRSASN_CODE allowed_ssc_mode_t::pack(asn1::bit_ref& bref) +{ + // 1 Spare bits + HANDLE_CODE(bref.pack(0x0, 1)); + HANDLE_CODE(bref.pack(ssc3, 1)); + HANDLE_CODE(bref.pack(ssc2, 1)); + HANDLE_CODE(bref.pack(ssc1, 1)); + return SRSASN_SUCCESS; +} + +// IE: Allowed SSC mode +// Reference: 9.11.4.5 +SRSASN_CODE allowed_ssc_mode_t::unpack(asn1::cbit_ref& bref) +{ + // 1 Spare bits + bref.advance_bits(1); + HANDLE_CODE(bref.unpack(ssc3, 1)); + HANDLE_CODE(bref.unpack(ssc2, 1)); + HANDLE_CODE(bref.unpack(ssc1, 1)); + return SRSASN_SUCCESS; +} + +// IE: 5GSM congestion re-attempt indicator +// Reference: 9.11.4.21 +SRSASN_CODE congestion_re_attempt_indicator_5gsm_t::pack(asn1::bit_ref& bref) +{ + // 7 Spare bits + HANDLE_CODE(bref.pack(0x0, 7)); + HANDLE_CODE(abo.pack(bref)); + return SRSASN_SUCCESS; +} + +// IE: 5GSM congestion re-attempt indicator +// Reference: 9.11.4.21 +SRSASN_CODE congestion_re_attempt_indicator_5gsm_t::unpack(asn1::cbit_ref& bref) +{ + // 7 Spare bits + bref.advance_bits(7); + HANDLE_CODE(abo.unpack(bref)); + return SRSASN_SUCCESS; +} + +// IE: Re-attempt indicator +// Reference: 9.11.4.17 +SRSASN_CODE re_attempt_indicator_t::pack(asn1::bit_ref& bref) +{ + // Save length bref pointer + asn1::bit_ref bref_length = bref; + HANDLE_CODE(bref.advance_bits(8)); + + // 6 Spare bits + HANDLE_CODE(bref.pack(0x0, 6)); + HANDLE_CODE(bref.pack(eplmnc, 1)); + HANDLE_CODE(bref.pack(ratc, 1)); + + bref.align_bytes_zero(); + uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + + if (length != 1) { + asn1::log_error("Encoding Failed (Re-attempt indicator): Packed length (%d) does not equal expected length 1", + length); + return asn1::SRSASN_ERROR_ENCODE_FAIL; + } + HANDLE_CODE(bref_length.pack(length, 8)); + return SRSASN_SUCCESS; +} + +// IE: Re-attempt indicator +// Reference: 9.11.4.17 +SRSASN_CODE re_attempt_indicator_t::unpack(asn1::cbit_ref& bref) +{ + HANDLE_CODE(bref.unpack(length, 8)); + if (length != 1) { + asn1::log_error("Decoding Failed (Re-attempt indicator): Length (%d) does not equal expected length 1", length); + return asn1::SRSASN_ERROR_DECODE_FAIL; + } + // 6 Spare bits + bref.advance_bits(6); + HANDLE_CODE(bref.unpack(eplmnc, 1)); + HANDLE_CODE(bref.unpack(ratc, 1)); + return SRSASN_SUCCESS; +} + +} // namespace nas_5g +} // namespace srsran diff --git a/lib/src/asn1/nas_5g_msg.cc b/lib/src/asn1/nas_5g_msg.cc new file mode 100644 index 000000000..91af1bca4 --- /dev/null +++ b/lib/src/asn1/nas_5g_msg.cc @@ -0,0 +1,4198 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ +#include "srsran/asn1/nas_5g_msg.h" +#include "srsran/asn1/nas_5g_ies.h" +#include "srsran/asn1/nas_5g_utils.h" + +#include "srsran/asn1/asn1_utils.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/common.h" +#include "srsran/config.h" + +#include +#include +#include + +namespace srsran { +namespace nas_5g { + +SRSASN_CODE registration_request_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(ng_ksi.pack(bref)); + HANDLE_CODE(registration_type_5gs.pack(bref)); + HANDLE_CODE(mobile_identity_5gs.pack(bref)); + + // Optional fields + if (non_current_native_nas_key_set_identifier_present == true) { + HANDLE_CODE(bref.pack(ie_iei_non_current_native_nas_key_set_identifier, 4)); + HANDLE_CODE(non_current_native_nas_key_set_identifier.pack(bref)); + } + if (capability_5gmm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_capability_5gmm, 8)); + HANDLE_CODE(capability_5gmm.pack(bref)); + } + if (ue_security_capability_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_security_capability, 8)); + HANDLE_CODE(ue_security_capability.pack(bref)); + } + if (requested_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_requested_nssai, 8)); + HANDLE_CODE(requested_nssai.pack(bref)); + } + if (last_visited_registered_tai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_last_visited_registered_tai, 8)); + HANDLE_CODE(last_visited_registered_tai.pack(bref)); + } + if (s1_ue_network_capability_present == true) { + HANDLE_CODE(bref.pack(ie_iei_s1_ue_network_capability, 8)); + HANDLE_CODE(s1_ue_network_capability.pack(bref)); + } + if (uplink_data_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_uplink_data_status, 8)); + HANDLE_CODE(uplink_data_status.pack(bref)); + } + if (pdu_session_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_status, 8)); + HANDLE_CODE(pdu_session_status.pack(bref)); + } + if (mico_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_mico_indication, 4)); + HANDLE_CODE(mico_indication.pack(bref)); + } + if (ue_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_status, 8)); + HANDLE_CODE(ue_status.pack(bref)); + } + if (additional_guti_present == true) { + HANDLE_CODE(bref.pack(ie_iei_additional_guti, 8)); + HANDLE_CODE(additional_guti.pack(bref)); + } + if (allowed_pdu_session_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_allowed_pdu_session_status, 8)); + HANDLE_CODE(allowed_pdu_session_status.pack(bref)); + } + if (ue_usage_setting_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_usage_setting, 8)); + HANDLE_CODE(ue_usage_setting.pack(bref)); + } + if (requested_drx_parameters_present == true) { + HANDLE_CODE(bref.pack(ie_iei_requested_drx_parameters, 8)); + HANDLE_CODE(requested_drx_parameters.pack(bref)); + } + if (eps_nas_message_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eps_nas_message_container, 8)); + HANDLE_CODE(eps_nas_message_container.pack(bref)); + } + if (ladn_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ladn_indication, 8)); + HANDLE_CODE(ladn_indication.pack(bref)); + } + if (payload_container_type_present == true) { + HANDLE_CODE(bref.pack(ie_iei_payload_container_type, 4)); + HANDLE_CODE(payload_container_type.pack(bref)); + } + if (payload_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_payload_container, 8)); + HANDLE_CODE(payload_container.pack(bref)); + } + if (network_slicing_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_network_slicing_indication, 4)); + HANDLE_CODE(network_slicing_indication.pack(bref)); + } + if (update_type_5gs_present == true) { + HANDLE_CODE(bref.pack(ie_iei_update_type_5gs, 8)); + HANDLE_CODE(update_type_5gs.pack(bref)); + } + if (mobile_station_classmark_2_present == true) { + HANDLE_CODE(bref.pack(ie_iei_mobile_station_classmark_2, 8)); + HANDLE_CODE(mobile_station_classmark_2.pack(bref)); + } + if (supported_codecs_present == true) { + HANDLE_CODE(bref.pack(ie_iei_supported_codecs, 8)); + HANDLE_CODE(supported_codecs.pack(bref)); + } + if (nas_message_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_nas_message_container, 8)); + HANDLE_CODE(nas_message_container.pack(bref)); + } + if (eps_bearer_context_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eps_bearer_context_status, 8)); + HANDLE_CODE(eps_bearer_context_status.pack(bref)); + } + if (requested_extended_drx_parameters_present == true) { + HANDLE_CODE(bref.pack(ie_iei_requested_extended_drx_parameters, 8)); + HANDLE_CODE(requested_extended_drx_parameters.pack(bref)); + } + if (t3324_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3324_value, 8)); + HANDLE_CODE(t3324_value.pack(bref)); + } + if (ue_radio_capability_id_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_radio_capability_id, 8)); + HANDLE_CODE(ue_radio_capability_id.pack(bref)); + } + if (requested_mapped_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_requested_mapped_nssai, 8)); + HANDLE_CODE(requested_mapped_nssai.pack(bref)); + } + if (additional_information_requested_present == true) { + HANDLE_CODE(bref.pack(ie_iei_additional_information_requested, 8)); + HANDLE_CODE(additional_information_requested.pack(bref)); + } + if (requested_wus_assistance_information_present == true) { + HANDLE_CODE(bref.pack(ie_iei_requested_wus_assistance_information, 8)); + HANDLE_CODE(requested_wus_assistance_information.pack(bref)); + } + if (n5gc_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_n5gc_indication, 4)); + HANDLE_CODE(n5gc_indication.pack(bref)); + } + if (requested_nb_n1_mode_drx_parameters_present == true) { + HANDLE_CODE(bref.pack(ie_iei_requested_nb_n1_mode_drx_parameters, 8)); + HANDLE_CODE(requested_nb_n1_mode_drx_parameters.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE registration_request_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(ng_ksi.unpack(bref)); + HANDLE_CODE(registration_type_5gs.unpack(bref)); + HANDLE_CODE(mobile_identity_5gs.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_non_current_native_nas_key_set_identifier: + non_current_native_nas_key_set_identifier_present = true; + HANDLE_CODE(non_current_native_nas_key_set_identifier.unpack(bref)); + break; + case ie_iei_capability_5gmm: + capability_5gmm_present = true; + HANDLE_CODE(capability_5gmm.unpack(bref)); + break; + case ie_iei_ue_security_capability: + ue_security_capability_present = true; + HANDLE_CODE(ue_security_capability.unpack(bref)); + break; + case ie_iei_requested_nssai: + requested_nssai_present = true; + HANDLE_CODE(requested_nssai.unpack(bref)); + break; + case ie_iei_last_visited_registered_tai: + last_visited_registered_tai_present = true; + HANDLE_CODE(last_visited_registered_tai.unpack(bref)); + break; + case ie_iei_s1_ue_network_capability: + s1_ue_network_capability_present = true; + HANDLE_CODE(s1_ue_network_capability.unpack(bref)); + break; + case ie_iei_uplink_data_status: + uplink_data_status_present = true; + HANDLE_CODE(uplink_data_status.unpack(bref)); + break; + case ie_iei_pdu_session_status: + pdu_session_status_present = true; + HANDLE_CODE(pdu_session_status.unpack(bref)); + break; + case ie_iei_mico_indication: + mico_indication_present = true; + HANDLE_CODE(mico_indication.unpack(bref)); + break; + case ie_iei_ue_status: + ue_status_present = true; + HANDLE_CODE(ue_status.unpack(bref)); + break; + case ie_iei_additional_guti: + additional_guti_present = true; + HANDLE_CODE(additional_guti.unpack(bref)); + break; + case ie_iei_allowed_pdu_session_status: + allowed_pdu_session_status_present = true; + HANDLE_CODE(allowed_pdu_session_status.unpack(bref)); + break; + case ie_iei_ue_usage_setting: + ue_usage_setting_present = true; + HANDLE_CODE(ue_usage_setting.unpack(bref)); + break; + case ie_iei_requested_drx_parameters: + requested_drx_parameters_present = true; + HANDLE_CODE(requested_drx_parameters.unpack(bref)); + break; + case ie_iei_eps_nas_message_container: + eps_nas_message_container_present = true; + HANDLE_CODE(eps_nas_message_container.unpack(bref)); + break; + case ie_iei_ladn_indication: + ladn_indication_present = true; + HANDLE_CODE(ladn_indication.unpack(bref)); + break; + case ie_iei_payload_container_type: + payload_container_type_present = true; + HANDLE_CODE(payload_container_type.unpack(bref)); + break; + case ie_iei_payload_container: + payload_container_present = true; + HANDLE_CODE(payload_container.unpack(bref)); + break; + case ie_iei_network_slicing_indication: + network_slicing_indication_present = true; + HANDLE_CODE(network_slicing_indication.unpack(bref)); + break; + case ie_iei_update_type_5gs: + update_type_5gs_present = true; + HANDLE_CODE(update_type_5gs.unpack(bref)); + break; + case ie_iei_mobile_station_classmark_2: + mobile_station_classmark_2_present = true; + HANDLE_CODE(mobile_station_classmark_2.unpack(bref)); + break; + case ie_iei_supported_codecs: + supported_codecs_present = true; + HANDLE_CODE(supported_codecs.unpack(bref)); + break; + case ie_iei_nas_message_container: + nas_message_container_present = true; + HANDLE_CODE(nas_message_container.unpack(bref)); + break; + case ie_iei_eps_bearer_context_status: + eps_bearer_context_status_present = true; + HANDLE_CODE(eps_bearer_context_status.unpack(bref)); + break; + case ie_iei_requested_extended_drx_parameters: + requested_extended_drx_parameters_present = true; + HANDLE_CODE(requested_extended_drx_parameters.unpack(bref)); + break; + case ie_iei_t3324_value: + t3324_value_present = true; + HANDLE_CODE(t3324_value.unpack(bref)); + break; + case ie_iei_ue_radio_capability_id: + ue_radio_capability_id_present = true; + HANDLE_CODE(ue_radio_capability_id.unpack(bref)); + break; + case ie_iei_requested_mapped_nssai: + requested_mapped_nssai_present = true; + HANDLE_CODE(requested_mapped_nssai.unpack(bref)); + break; + case ie_iei_additional_information_requested: + additional_information_requested_present = true; + HANDLE_CODE(additional_information_requested.unpack(bref)); + break; + case ie_iei_requested_wus_assistance_information: + requested_wus_assistance_information_present = true; + HANDLE_CODE(requested_wus_assistance_information.unpack(bref)); + break; + case ie_iei_n5gc_indication: + n5gc_indication_present = true; + HANDLE_CODE(n5gc_indication.unpack(bref)); + break; + case ie_iei_requested_nb_n1_mode_drx_parameters: + requested_nb_n1_mode_drx_parameters_present = true; + HANDLE_CODE(requested_nb_n1_mode_drx_parameters.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE registration_accept_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(registration_result_5gs.pack(bref)); + + // Optional fields + if (guti_5g_present == true) { + HANDLE_CODE(bref.pack(ie_iei_guti_5g, 8)); + HANDLE_CODE(guti_5g.pack(bref)); + } + if (equivalent_plm_ns_present == true) { + HANDLE_CODE(bref.pack(ie_iei_equivalent_plm_ns, 8)); + HANDLE_CODE(equivalent_plm_ns.pack(bref)); + } + if (tai_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_tai_list, 8)); + HANDLE_CODE(tai_list.pack(bref)); + } + if (allowed_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_allowed_nssai, 8)); + HANDLE_CODE(allowed_nssai.pack(bref)); + } + if (rejected_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_rejected_nssai, 8)); + HANDLE_CODE(rejected_nssai.pack(bref)); + } + if (configured_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_configured_nssai, 8)); + HANDLE_CODE(configured_nssai.pack(bref)); + } + if (network_feature_support_5gs_present == true) { + HANDLE_CODE(bref.pack(ie_iei_network_feature_support_5gs, 8)); + HANDLE_CODE(network_feature_support_5gs.pack(bref)); + } + if (pdu_session_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_status, 8)); + HANDLE_CODE(pdu_session_status.pack(bref)); + } + if (pdu_session_reactivation_result_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_reactivation_result, 8)); + HANDLE_CODE(pdu_session_reactivation_result.pack(bref)); + } + if (pdu_session_reactivation_result_error_cause_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_reactivation_result_error_cause, 8)); + HANDLE_CODE(pdu_session_reactivation_result_error_cause.pack(bref)); + } + if (ladn_information_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ladn_information, 8)); + HANDLE_CODE(ladn_information.pack(bref)); + } + if (mico_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_mico_indication, 4)); + HANDLE_CODE(mico_indication.pack(bref)); + } + if (network_slicing_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_network_slicing_indication, 4)); + HANDLE_CODE(network_slicing_indication.pack(bref)); + } + if (service_area_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_service_area_list, 8)); + HANDLE_CODE(service_area_list.pack(bref)); + } + if (t3512_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3512_value, 8)); + HANDLE_CODE(t3512_value.pack(bref)); + } + if (non_3_gpp_de_registration_timer_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_non_3_gpp_de_registration_timer_value, 8)); + HANDLE_CODE(non_3_gpp_de_registration_timer_value.pack(bref)); + } + if (t3502_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3502_value, 8)); + HANDLE_CODE(t3502_value.pack(bref)); + } + if (emergency_number_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_emergency_number_list, 8)); + HANDLE_CODE(emergency_number_list.pack(bref)); + } + if (extended_emergency_number_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_emergency_number_list, 8)); + HANDLE_CODE(extended_emergency_number_list.pack(bref)); + } + if (sor_transparent_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_sor_transparent_container, 8)); + HANDLE_CODE(sor_transparent_container.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (nssai_inclusion_mode_present == true) { + HANDLE_CODE(bref.pack(ie_iei_nssai_inclusion_mode, 4)); + HANDLE_CODE(nssai_inclusion_mode.pack(bref)); + } + if (operator_defined_access_category_definitions_present == true) { + HANDLE_CODE(bref.pack(ie_iei_operator_defined_access_category_definitions, 8)); + HANDLE_CODE(operator_defined_access_category_definitions.pack(bref)); + } + if (negotiated_drx_parameters_present == true) { + HANDLE_CODE(bref.pack(ie_iei_negotiated_drx_parameters, 8)); + HANDLE_CODE(negotiated_drx_parameters.pack(bref)); + } + if (non_3_gpp_nw_policies_present == true) { + HANDLE_CODE(bref.pack(ie_iei_non_3_gpp_nw_policies, 4)); + HANDLE_CODE(non_3_gpp_nw_policies.pack(bref)); + } + if (eps_bearer_context_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eps_bearer_context_status, 8)); + HANDLE_CODE(eps_bearer_context_status.pack(bref)); + } + if (negotiated_extended_drx_parameters_present == true) { + HANDLE_CODE(bref.pack(ie_iei_negotiated_extended_drx_parameters, 8)); + HANDLE_CODE(negotiated_extended_drx_parameters.pack(bref)); + } + if (t3447_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3447_value, 8)); + HANDLE_CODE(t3447_value.pack(bref)); + } + if (t3448_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3448_value, 8)); + HANDLE_CODE(t3448_value.pack(bref)); + } + if (t3324_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3324_value, 8)); + HANDLE_CODE(t3324_value.pack(bref)); + } + if (ue_radio_capability_id_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_radio_capability_id, 8)); + HANDLE_CODE(ue_radio_capability_id.pack(bref)); + } + if (ue_radio_capability_id_deletion_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_radio_capability_id_deletion_indication, 4)); + HANDLE_CODE(ue_radio_capability_id_deletion_indication.pack(bref)); + } + if (pending_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pending_nssai, 8)); + HANDLE_CODE(pending_nssai.pack(bref)); + } + if (ciphering_key_data_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ciphering_key_data, 8)); + HANDLE_CODE(ciphering_key_data.pack(bref)); + } + if (cag_information_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cag_information_list, 8)); + HANDLE_CODE(cag_information_list.pack(bref)); + } + if (truncated_5g_s_tmsi_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_truncated_5g_s_tmsi_configuration, 8)); + HANDLE_CODE(truncated_5g_s_tmsi_configuration.pack(bref)); + } + if (negotiated_wus_assistance_information_present == true) { + HANDLE_CODE(bref.pack(ie_iei_negotiated_wus_assistance_information, 8)); + HANDLE_CODE(negotiated_wus_assistance_information.pack(bref)); + } + if (negotiated_nb_n1_mode_drx_parameters_present == true) { + HANDLE_CODE(bref.pack(ie_iei_negotiated_nb_n1_mode_drx_parameters, 8)); + HANDLE_CODE(negotiated_nb_n1_mode_drx_parameters.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE registration_accept_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(registration_result_5gs.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_guti_5g: + guti_5g_present = true; + HANDLE_CODE(guti_5g.unpack(bref)); + break; + case ie_iei_equivalent_plm_ns: + equivalent_plm_ns_present = true; + HANDLE_CODE(equivalent_plm_ns.unpack(bref)); + break; + case ie_iei_tai_list: + tai_list_present = true; + HANDLE_CODE(tai_list.unpack(bref)); + break; + case ie_iei_allowed_nssai: + allowed_nssai_present = true; + HANDLE_CODE(allowed_nssai.unpack(bref)); + break; + case ie_iei_rejected_nssai: + rejected_nssai_present = true; + HANDLE_CODE(rejected_nssai.unpack(bref)); + break; + case ie_iei_configured_nssai: + configured_nssai_present = true; + HANDLE_CODE(configured_nssai.unpack(bref)); + break; + case ie_iei_network_feature_support_5gs: + network_feature_support_5gs_present = true; + HANDLE_CODE(network_feature_support_5gs.unpack(bref)); + break; + case ie_iei_pdu_session_status: + pdu_session_status_present = true; + HANDLE_CODE(pdu_session_status.unpack(bref)); + break; + case ie_iei_pdu_session_reactivation_result: + pdu_session_reactivation_result_present = true; + HANDLE_CODE(pdu_session_reactivation_result.unpack(bref)); + break; + case ie_iei_pdu_session_reactivation_result_error_cause: + pdu_session_reactivation_result_error_cause_present = true; + HANDLE_CODE(pdu_session_reactivation_result_error_cause.unpack(bref)); + break; + case ie_iei_ladn_information: + ladn_information_present = true; + HANDLE_CODE(ladn_information.unpack(bref)); + break; + case ie_iei_mico_indication: + mico_indication_present = true; + HANDLE_CODE(mico_indication.unpack(bref)); + break; + case ie_iei_network_slicing_indication: + network_slicing_indication_present = true; + HANDLE_CODE(network_slicing_indication.unpack(bref)); + break; + case ie_iei_service_area_list: + service_area_list_present = true; + HANDLE_CODE(service_area_list.unpack(bref)); + break; + case ie_iei_t3512_value: + t3512_value_present = true; + HANDLE_CODE(t3512_value.unpack(bref)); + break; + case ie_iei_non_3_gpp_de_registration_timer_value: + non_3_gpp_de_registration_timer_value_present = true; + HANDLE_CODE(non_3_gpp_de_registration_timer_value.unpack(bref)); + break; + case ie_iei_t3502_value: + t3502_value_present = true; + HANDLE_CODE(t3502_value.unpack(bref)); + break; + case ie_iei_emergency_number_list: + emergency_number_list_present = true; + HANDLE_CODE(emergency_number_list.unpack(bref)); + break; + case ie_iei_extended_emergency_number_list: + extended_emergency_number_list_present = true; + HANDLE_CODE(extended_emergency_number_list.unpack(bref)); + break; + case ie_iei_sor_transparent_container: + sor_transparent_container_present = true; + HANDLE_CODE(sor_transparent_container.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_nssai_inclusion_mode: + nssai_inclusion_mode_present = true; + HANDLE_CODE(nssai_inclusion_mode.unpack(bref)); + break; + case ie_iei_operator_defined_access_category_definitions: + operator_defined_access_category_definitions_present = true; + HANDLE_CODE(operator_defined_access_category_definitions.unpack(bref)); + break; + case ie_iei_negotiated_drx_parameters: + negotiated_drx_parameters_present = true; + HANDLE_CODE(negotiated_drx_parameters.unpack(bref)); + break; + case ie_iei_non_3_gpp_nw_policies: + non_3_gpp_nw_policies_present = true; + HANDLE_CODE(non_3_gpp_nw_policies.unpack(bref)); + break; + case ie_iei_eps_bearer_context_status: + eps_bearer_context_status_present = true; + HANDLE_CODE(eps_bearer_context_status.unpack(bref)); + break; + case ie_iei_negotiated_extended_drx_parameters: + negotiated_extended_drx_parameters_present = true; + HANDLE_CODE(negotiated_extended_drx_parameters.unpack(bref)); + break; + case ie_iei_t3447_value: + t3447_value_present = true; + HANDLE_CODE(t3447_value.unpack(bref)); + break; + case ie_iei_t3448_value: + t3448_value_present = true; + HANDLE_CODE(t3448_value.unpack(bref)); + break; + case ie_iei_t3324_value: + t3324_value_present = true; + HANDLE_CODE(t3324_value.unpack(bref)); + break; + case ie_iei_ue_radio_capability_id: + ue_radio_capability_id_present = true; + HANDLE_CODE(ue_radio_capability_id.unpack(bref)); + break; + case ie_iei_ue_radio_capability_id_deletion_indication: + ue_radio_capability_id_deletion_indication_present = true; + HANDLE_CODE(ue_radio_capability_id_deletion_indication.unpack(bref)); + break; + case ie_iei_pending_nssai: + pending_nssai_present = true; + HANDLE_CODE(pending_nssai.unpack(bref)); + break; + case ie_iei_ciphering_key_data: + ciphering_key_data_present = true; + HANDLE_CODE(ciphering_key_data.unpack(bref)); + break; + case ie_iei_cag_information_list: + cag_information_list_present = true; + HANDLE_CODE(cag_information_list.unpack(bref)); + break; + case ie_iei_truncated_5g_s_tmsi_configuration: + truncated_5g_s_tmsi_configuration_present = true; + HANDLE_CODE(truncated_5g_s_tmsi_configuration.unpack(bref)); + break; + case ie_iei_negotiated_wus_assistance_information: + negotiated_wus_assistance_information_present = true; + HANDLE_CODE(negotiated_wus_assistance_information.unpack(bref)); + break; + case ie_iei_negotiated_nb_n1_mode_drx_parameters: + negotiated_nb_n1_mode_drx_parameters_present = true; + HANDLE_CODE(negotiated_nb_n1_mode_drx_parameters.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE registration_complete_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (sor_transparent_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_sor_transparent_container, 8)); + HANDLE_CODE(sor_transparent_container.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE registration_complete_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_sor_transparent_container: + sor_transparent_container_present = true; + HANDLE_CODE(sor_transparent_container.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE registration_reject_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.pack(bref)); + + // Optional fields + if (t3346_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3346_value, 8)); + HANDLE_CODE(t3346_value.pack(bref)); + } + if (t3502_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3502_value, 8)); + HANDLE_CODE(t3502_value.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (rejected_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_rejected_nssai, 8)); + HANDLE_CODE(rejected_nssai.pack(bref)); + } + if (cag_information_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cag_information_list, 8)); + HANDLE_CODE(cag_information_list.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE registration_reject_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_t3346_value: + t3346_value_present = true; + HANDLE_CODE(t3346_value.unpack(bref)); + break; + case ie_iei_t3502_value: + t3502_value_present = true; + HANDLE_CODE(t3502_value.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_rejected_nssai: + rejected_nssai_present = true; + HANDLE_CODE(rejected_nssai.unpack(bref)); + break; + case ie_iei_cag_information_list: + cag_information_list_present = true; + HANDLE_CODE(cag_information_list.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE deregistration_request_ue_originating_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(ng_ksi.pack(bref)); + HANDLE_CODE(de_registration_type.pack(bref)); + HANDLE_CODE(mobile_identity_5gs.pack(bref)); + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE deregistration_request_ue_originating_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(ng_ksi.unpack(bref)); + HANDLE_CODE(de_registration_type.unpack(bref)); + HANDLE_CODE(mobile_identity_5gs.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE deregistration_accept_ue_originating_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE deregistration_accept_ue_originating_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE deregistration_request_ue_terminated_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.pack(bref)); + HANDLE_CODE(de_registration_type.pack(bref)); + + // Optional fields + if (cause_5gmm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cause_5gmm, 8)); + HANDLE_CODE(cause_5gmm.pack(bref)); + } + if (t3346_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3346_value, 8)); + HANDLE_CODE(t3346_value.pack(bref)); + } + if (rejected_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_rejected_nssai, 8)); + HANDLE_CODE(rejected_nssai.pack(bref)); + } + if (cag_information_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cag_information_list, 8)); + HANDLE_CODE(cag_information_list.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE deregistration_request_ue_terminated_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.unpack(bref)); + HANDLE_CODE(de_registration_type.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_cause_5gmm: + cause_5gmm_present = true; + HANDLE_CODE(cause_5gmm.unpack(bref)); + break; + case ie_iei_t3346_value: + t3346_value_present = true; + HANDLE_CODE(t3346_value.unpack(bref)); + break; + case ie_iei_rejected_nssai: + rejected_nssai_present = true; + HANDLE_CODE(rejected_nssai.unpack(bref)); + break; + case ie_iei_cag_information_list: + cag_information_list_present = true; + HANDLE_CODE(cag_information_list.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE deregistration_accept_ue_terminated_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE deregistration_accept_ue_terminated_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE service_request_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(service_type.pack(bref)); + HANDLE_CODE(ng_ksi.pack(bref)); + HANDLE_CODE(s_tmsi_5g.pack(bref)); + + // Optional fields + if (uplink_data_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_uplink_data_status, 8)); + HANDLE_CODE(uplink_data_status.pack(bref)); + } + if (pdu_session_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_status, 8)); + HANDLE_CODE(pdu_session_status.pack(bref)); + } + if (allowed_pdu_session_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_allowed_pdu_session_status, 8)); + HANDLE_CODE(allowed_pdu_session_status.pack(bref)); + } + if (nas_message_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_nas_message_container, 8)); + HANDLE_CODE(nas_message_container.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE service_request_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(service_type.unpack(bref)); + HANDLE_CODE(ng_ksi.unpack(bref)); + HANDLE_CODE(s_tmsi_5g.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_uplink_data_status: + uplink_data_status_present = true; + HANDLE_CODE(uplink_data_status.unpack(bref)); + break; + case ie_iei_pdu_session_status: + pdu_session_status_present = true; + HANDLE_CODE(pdu_session_status.unpack(bref)); + break; + case ie_iei_allowed_pdu_session_status: + allowed_pdu_session_status_present = true; + HANDLE_CODE(allowed_pdu_session_status.unpack(bref)); + break; + case ie_iei_nas_message_container: + nas_message_container_present = true; + HANDLE_CODE(nas_message_container.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE service_reject_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (pdu_session_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_status, 8)); + HANDLE_CODE(pdu_session_status.pack(bref)); + } + if (pdu_session_reactivation_result_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_reactivation_result, 8)); + HANDLE_CODE(pdu_session_reactivation_result.pack(bref)); + } + if (pdu_session_reactivation_result_error_cause_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_reactivation_result_error_cause, 8)); + HANDLE_CODE(pdu_session_reactivation_result_error_cause.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (t3448_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3448_value, 8)); + HANDLE_CODE(t3448_value.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE service_reject_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_pdu_session_status: + pdu_session_status_present = true; + HANDLE_CODE(pdu_session_status.unpack(bref)); + break; + case ie_iei_pdu_session_reactivation_result: + pdu_session_reactivation_result_present = true; + HANDLE_CODE(pdu_session_reactivation_result.unpack(bref)); + break; + case ie_iei_pdu_session_reactivation_result_error_cause: + pdu_session_reactivation_result_error_cause_present = true; + HANDLE_CODE(pdu_session_reactivation_result_error_cause.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_t3448_value: + t3448_value_present = true; + HANDLE_CODE(t3448_value.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE service_accept_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.pack(bref)); + + // Optional fields + if (pdu_session_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_status, 8)); + HANDLE_CODE(pdu_session_status.pack(bref)); + } + if (t3346_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3346_value, 8)); + HANDLE_CODE(t3346_value.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (t3448_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3448_value, 8)); + HANDLE_CODE(t3448_value.pack(bref)); + } + if (cag_information_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cag_information_list, 8)); + HANDLE_CODE(cag_information_list.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE service_accept_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_pdu_session_status: + pdu_session_status_present = true; + HANDLE_CODE(pdu_session_status.unpack(bref)); + break; + case ie_iei_t3346_value: + t3346_value_present = true; + HANDLE_CODE(t3346_value.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_t3448_value: + t3448_value_present = true; + HANDLE_CODE(t3448_value.unpack(bref)); + break; + case ie_iei_cag_information_list: + cag_information_list_present = true; + HANDLE_CODE(cag_information_list.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE configuration_update_command_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (configuration_update_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_configuration_update_indication, 4)); + HANDLE_CODE(configuration_update_indication.pack(bref)); + } + if (guti_5g_present == true) { + HANDLE_CODE(bref.pack(ie_iei_guti_5g, 8)); + HANDLE_CODE(guti_5g.pack(bref)); + } + if (tai_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_tai_list, 8)); + HANDLE_CODE(tai_list.pack(bref)); + } + if (allowed_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_allowed_nssai, 8)); + HANDLE_CODE(allowed_nssai.pack(bref)); + } + if (service_area_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_service_area_list, 8)); + HANDLE_CODE(service_area_list.pack(bref)); + } + if (full_name_for_network_present == true) { + HANDLE_CODE(bref.pack(ie_iei_full_name_for_network, 8)); + HANDLE_CODE(full_name_for_network.pack(bref)); + } + if (short_name_for_network_present == true) { + HANDLE_CODE(bref.pack(ie_iei_short_name_for_network, 8)); + HANDLE_CODE(short_name_for_network.pack(bref)); + } + if (local_time_zone_present == true) { + HANDLE_CODE(bref.pack(ie_iei_local_time_zone, 8)); + HANDLE_CODE(local_time_zone.pack(bref)); + } + if (universal_time_and_local_time_zone_present == true) { + HANDLE_CODE(bref.pack(ie_iei_universal_time_and_local_time_zone, 8)); + HANDLE_CODE(universal_time_and_local_time_zone.pack(bref)); + } + if (network_daylight_saving_time_present == true) { + HANDLE_CODE(bref.pack(ie_iei_network_daylight_saving_time, 8)); + HANDLE_CODE(network_daylight_saving_time.pack(bref)); + } + if (ladn_information_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ladn_information, 8)); + HANDLE_CODE(ladn_information.pack(bref)); + } + if (mico_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_mico_indication, 4)); + HANDLE_CODE(mico_indication.pack(bref)); + } + if (network_slicing_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_network_slicing_indication, 4)); + HANDLE_CODE(network_slicing_indication.pack(bref)); + } + if (configured_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_configured_nssai, 8)); + HANDLE_CODE(configured_nssai.pack(bref)); + } + if (rejected_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_rejected_nssai, 8)); + HANDLE_CODE(rejected_nssai.pack(bref)); + } + if (operator_defined_access_category_definitions_present == true) { + HANDLE_CODE(bref.pack(ie_iei_operator_defined_access_category_definitions, 8)); + HANDLE_CODE(operator_defined_access_category_definitions.pack(bref)); + } + if (sms_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_sms_indication, 4)); + HANDLE_CODE(sms_indication.pack(bref)); + } + if (t3447_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_t3447_value, 8)); + HANDLE_CODE(t3447_value.pack(bref)); + } + if (cag_information_list_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cag_information_list, 8)); + HANDLE_CODE(cag_information_list.pack(bref)); + } + if (ue_radio_capability_id_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_radio_capability_id, 8)); + HANDLE_CODE(ue_radio_capability_id.pack(bref)); + } + if (ue_radio_capability_id_deletion_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_radio_capability_id_deletion_indication, 4)); + HANDLE_CODE(ue_radio_capability_id_deletion_indication.pack(bref)); + } + if (registration_result_5gs_present == true) { + HANDLE_CODE(bref.pack(ie_iei_registration_result_5gs, 8)); + HANDLE_CODE(registration_result_5gs.pack(bref)); + } + if (truncated_5g_s_tmsi_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_truncated_5g_s_tmsi_configuration, 8)); + HANDLE_CODE(truncated_5g_s_tmsi_configuration.pack(bref)); + } + if (additional_configuration_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_additional_configuration_indication, 4)); + HANDLE_CODE(additional_configuration_indication.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE configuration_update_command_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_configuration_update_indication: + configuration_update_indication_present = true; + HANDLE_CODE(configuration_update_indication.unpack(bref)); + break; + case ie_iei_guti_5g: + guti_5g_present = true; + HANDLE_CODE(guti_5g.unpack(bref)); + break; + case ie_iei_tai_list: + tai_list_present = true; + HANDLE_CODE(tai_list.unpack(bref)); + break; + case ie_iei_allowed_nssai: + allowed_nssai_present = true; + HANDLE_CODE(allowed_nssai.unpack(bref)); + break; + case ie_iei_service_area_list: + service_area_list_present = true; + HANDLE_CODE(service_area_list.unpack(bref)); + break; + case ie_iei_full_name_for_network: + full_name_for_network_present = true; + HANDLE_CODE(full_name_for_network.unpack(bref)); + break; + case ie_iei_short_name_for_network: + short_name_for_network_present = true; + HANDLE_CODE(short_name_for_network.unpack(bref)); + break; + case ie_iei_local_time_zone: + local_time_zone_present = true; + HANDLE_CODE(local_time_zone.unpack(bref)); + break; + case ie_iei_universal_time_and_local_time_zone: + universal_time_and_local_time_zone_present = true; + HANDLE_CODE(universal_time_and_local_time_zone.unpack(bref)); + break; + case ie_iei_network_daylight_saving_time: + network_daylight_saving_time_present = true; + HANDLE_CODE(network_daylight_saving_time.unpack(bref)); + break; + case ie_iei_ladn_information: + ladn_information_present = true; + HANDLE_CODE(ladn_information.unpack(bref)); + break; + case ie_iei_mico_indication: + mico_indication_present = true; + HANDLE_CODE(mico_indication.unpack(bref)); + break; + case ie_iei_network_slicing_indication: + network_slicing_indication_present = true; + HANDLE_CODE(network_slicing_indication.unpack(bref)); + break; + case ie_iei_configured_nssai: + configured_nssai_present = true; + HANDLE_CODE(configured_nssai.unpack(bref)); + break; + case ie_iei_rejected_nssai: + rejected_nssai_present = true; + HANDLE_CODE(rejected_nssai.unpack(bref)); + break; + case ie_iei_operator_defined_access_category_definitions: + operator_defined_access_category_definitions_present = true; + HANDLE_CODE(operator_defined_access_category_definitions.unpack(bref)); + break; + case ie_iei_sms_indication: + sms_indication_present = true; + HANDLE_CODE(sms_indication.unpack(bref)); + break; + case ie_iei_t3447_value: + t3447_value_present = true; + HANDLE_CODE(t3447_value.unpack(bref)); + break; + case ie_iei_cag_information_list: + cag_information_list_present = true; + HANDLE_CODE(cag_information_list.unpack(bref)); + break; + case ie_iei_ue_radio_capability_id: + ue_radio_capability_id_present = true; + HANDLE_CODE(ue_radio_capability_id.unpack(bref)); + break; + case ie_iei_ue_radio_capability_id_deletion_indication: + ue_radio_capability_id_deletion_indication_present = true; + HANDLE_CODE(ue_radio_capability_id_deletion_indication.unpack(bref)); + break; + case ie_iei_registration_result_5gs: + registration_result_5gs_present = true; + HANDLE_CODE(registration_result_5gs.unpack(bref)); + break; + case ie_iei_truncated_5g_s_tmsi_configuration: + truncated_5g_s_tmsi_configuration_present = true; + HANDLE_CODE(truncated_5g_s_tmsi_configuration.unpack(bref)); + break; + case ie_iei_additional_configuration_indication: + additional_configuration_indication_present = true; + HANDLE_CODE(additional_configuration_indication.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE configuration_update_complete_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE configuration_update_complete_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE authentication_request_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.pack(bref)); + HANDLE_CODE(ng_ksi.pack(bref)); + HANDLE_CODE(abba.pack(bref)); + + // Optional fields + if (authentication_parameter_rand_present == true) { + HANDLE_CODE(bref.pack(ie_iei_authentication_parameter_rand, 8)); + HANDLE_CODE(authentication_parameter_rand.pack(bref)); + } + if (authentication_parameter_autn_present == true) { + HANDLE_CODE(bref.pack(ie_iei_authentication_parameter_autn, 8)); + HANDLE_CODE(authentication_parameter_autn.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE authentication_request_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.unpack(bref)); + HANDLE_CODE(ng_ksi.unpack(bref)); + HANDLE_CODE(abba.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_authentication_parameter_rand: + authentication_parameter_rand_present = true; + HANDLE_CODE(authentication_parameter_rand.unpack(bref)); + break; + case ie_iei_authentication_parameter_autn: + authentication_parameter_autn_present = true; + HANDLE_CODE(authentication_parameter_autn.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE authentication_response_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (authentication_response_parameter_present == true) { + HANDLE_CODE(bref.pack(ie_iei_authentication_response_parameter, 8)); + HANDLE_CODE(authentication_response_parameter.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE authentication_response_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_authentication_response_parameter: + authentication_response_parameter_present = true; + HANDLE_CODE(authentication_response_parameter.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE authentication_reject_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE authentication_reject_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE authentication_failure_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.pack(bref)); + + // Optional fields + if (authentication_failure_parameter_present == true) { + HANDLE_CODE(bref.pack(ie_iei_authentication_failure_parameter, 8)); + HANDLE_CODE(authentication_failure_parameter.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE authentication_failure_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_authentication_failure_parameter: + authentication_failure_parameter_present = true; + HANDLE_CODE(authentication_failure_parameter.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE authentication_result_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.pack(bref)); + HANDLE_CODE(ng_ksi.pack(bref)); + HANDLE_CODE(eap_message.pack(bref)); + + // Optional fields + if (abba_present == true) { + HANDLE_CODE(bref.pack(ie_iei_abba, 8)); + HANDLE_CODE(abba.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE authentication_result_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.unpack(bref)); + HANDLE_CODE(ng_ksi.unpack(bref)); + HANDLE_CODE(eap_message.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_abba: + abba_present = true; + HANDLE_CODE(abba.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE identity_request_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.pack(bref)); + HANDLE_CODE(identity_type.pack(bref)); + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE identity_request_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.unpack(bref)); + HANDLE_CODE(identity_type.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE identity_response_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(mobile_identity.pack(bref)); + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE identity_response_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(mobile_identity.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE security_mode_command_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(selected_nas_security_algorithms.pack(bref)); + HANDLE_CODE(spare_half_octet.pack(bref)); + HANDLE_CODE(ng_ksi.pack(bref)); + HANDLE_CODE(replayed_ue_security_capabilities.pack(bref)); + + // Optional fields + if (imeisv_request_present == true) { + HANDLE_CODE(bref.pack(ie_iei_imeisv_request, 4)); + HANDLE_CODE(imeisv_request.pack(bref)); + } + if (selected_eps_nas_security_algorithms_present == true) { + HANDLE_CODE(bref.pack(ie_iei_selected_eps_nas_security_algorithms, 8)); + HANDLE_CODE(selected_eps_nas_security_algorithms.pack(bref)); + } + if (additional_5g_security_information_present == true) { + HANDLE_CODE(bref.pack(ie_iei_additional_5g_security_information, 8)); + HANDLE_CODE(additional_5g_security_information.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (abba_present == true) { + HANDLE_CODE(bref.pack(ie_iei_abba, 8)); + HANDLE_CODE(abba.pack(bref)); + } + if (replayed_s1_ue_security_capabilities_present == true) { + HANDLE_CODE(bref.pack(ie_iei_replayed_s1_ue_security_capabilities, 8)); + HANDLE_CODE(replayed_s1_ue_security_capabilities.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE security_mode_command_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(selected_nas_security_algorithms.unpack(bref)); + HANDLE_CODE(spare_half_octet.unpack(bref)); + HANDLE_CODE(ng_ksi.unpack(bref)); + HANDLE_CODE(replayed_ue_security_capabilities.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_imeisv_request: + imeisv_request_present = true; + HANDLE_CODE(imeisv_request.unpack(bref)); + break; + case ie_iei_selected_eps_nas_security_algorithms: + selected_eps_nas_security_algorithms_present = true; + HANDLE_CODE(selected_eps_nas_security_algorithms.unpack(bref)); + break; + case ie_iei_additional_5g_security_information: + additional_5g_security_information_present = true; + HANDLE_CODE(additional_5g_security_information.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_abba: + abba_present = true; + HANDLE_CODE(abba.unpack(bref)); + break; + case ie_iei_replayed_s1_ue_security_capabilities: + replayed_s1_ue_security_capabilities_present = true; + HANDLE_CODE(replayed_s1_ue_security_capabilities.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE security_mode_complete_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (imeisv_present == true) { + HANDLE_CODE(bref.pack(ie_iei_imeisv, 8)); + HANDLE_CODE(imeisv.pack(bref)); + } + if (nas_message_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_nas_message_container, 8)); + HANDLE_CODE(nas_message_container.pack(bref)); + } + if (non_imeisv_pei_present == true) { + HANDLE_CODE(bref.pack(ie_iei_non_imeisv_pei, 8)); + HANDLE_CODE(non_imeisv_pei.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE security_mode_complete_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_imeisv: + imeisv_present = true; + HANDLE_CODE(imeisv.unpack(bref)); + break; + case ie_iei_nas_message_container: + nas_message_container_present = true; + HANDLE_CODE(nas_message_container.unpack(bref)); + break; + case ie_iei_non_imeisv_pei: + non_imeisv_pei_present = true; + HANDLE_CODE(non_imeisv_pei.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE security_mode_reject_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.pack(bref)); + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE security_mode_reject_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE status_5gmm_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.pack(bref)); + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE status_5gmm_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gmm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE notification_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.pack(bref)); + HANDLE_CODE(access_type.pack(bref)); + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE notification_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.unpack(bref)); + HANDLE_CODE(access_type.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE notification_response_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (pdu_session_status_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_status, 8)); + HANDLE_CODE(pdu_session_status.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE notification_response_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_pdu_session_status: + pdu_session_status_present = true; + HANDLE_CODE(pdu_session_status.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE ul_nas_transport_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.pack(bref)); + HANDLE_CODE(payload_container_type.pack(bref)); + HANDLE_CODE(payload_container.pack(bref)); + + // Optional fields + if (pdu_session_id_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_id, 8)); + HANDLE_CODE(pdu_session_id.pack(bref)); + } + if (old_pdu_session_id_present == true) { + HANDLE_CODE(bref.pack(ie_iei_old_pdu_session_id, 8)); + HANDLE_CODE(old_pdu_session_id.pack(bref)); + } + if (request_type_present == true) { + HANDLE_CODE(bref.pack(ie_iei_request_type, 4)); + HANDLE_CODE(request_type.pack(bref)); + } + if (s_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_s_nssai, 8)); + HANDLE_CODE(s_nssai.pack(bref)); + } + if (dnn_present == true) { + HANDLE_CODE(bref.pack(ie_iei_dnn, 8)); + HANDLE_CODE(dnn.pack(bref)); + } + if (additional_information_present == true) { + HANDLE_CODE(bref.pack(ie_iei_additional_information, 8)); + HANDLE_CODE(additional_information.pack(bref)); + } + if (ma_pdu_session_information_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ma_pdu_session_information, 4)); + HANDLE_CODE(ma_pdu_session_information.pack(bref)); + } + if (release_assistance_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_release_assistance_indication, 4)); + HANDLE_CODE(release_assistance_indication.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE ul_nas_transport_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.unpack(bref)); + HANDLE_CODE(payload_container_type.unpack(bref)); + HANDLE_CODE(payload_container.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_pdu_session_id: + pdu_session_id_present = true; + HANDLE_CODE(pdu_session_id.unpack(bref)); + break; + case ie_iei_old_pdu_session_id: + old_pdu_session_id_present = true; + HANDLE_CODE(old_pdu_session_id.unpack(bref)); + break; + case ie_iei_request_type: + request_type_present = true; + HANDLE_CODE(request_type.unpack(bref)); + break; + case ie_iei_s_nssai: + s_nssai_present = true; + HANDLE_CODE(s_nssai.unpack(bref)); + break; + case ie_iei_dnn: + dnn_present = true; + HANDLE_CODE(dnn.unpack(bref)); + break; + case ie_iei_additional_information: + additional_information_present = true; + HANDLE_CODE(additional_information.unpack(bref)); + break; + case ie_iei_ma_pdu_session_information: + ma_pdu_session_information_present = true; + HANDLE_CODE(ma_pdu_session_information.unpack(bref)); + break; + case ie_iei_release_assistance_indication: + release_assistance_indication_present = true; + HANDLE_CODE(release_assistance_indication.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE dl_nas_transport_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.pack(bref)); + HANDLE_CODE(payload_container_type.pack(bref)); + HANDLE_CODE(payload_container.pack(bref)); + + // Optional fields + if (pdu_session_id_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_id, 8)); + HANDLE_CODE(pdu_session_id.pack(bref)); + } + if (additional_information_present == true) { + HANDLE_CODE(bref.pack(ie_iei_additional_information, 8)); + HANDLE_CODE(additional_information.pack(bref)); + } + if (cause_5gmm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cause_5gmm, 8)); + HANDLE_CODE(cause_5gmm.pack(bref)); + } + if (back_off_timer_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_back_off_timer_value, 8)); + HANDLE_CODE(back_off_timer_value.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE dl_nas_transport_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(spare_half_octet.unpack(bref)); + HANDLE_CODE(payload_container_type.unpack(bref)); + HANDLE_CODE(payload_container.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_pdu_session_id: + pdu_session_id_present = true; + HANDLE_CODE(pdu_session_id.unpack(bref)); + break; + case ie_iei_additional_information: + additional_information_present = true; + HANDLE_CODE(additional_information.unpack(bref)); + break; + case ie_iei_cause_5gmm: + cause_5gmm_present = true; + HANDLE_CODE(cause_5gmm.unpack(bref)); + break; + case ie_iei_back_off_timer_value: + back_off_timer_value_present = true; + HANDLE_CODE(back_off_timer_value.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_establishment_request_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(integrity_protection_maximum_data_rate.pack(bref)); + + // Optional fields + if (pdu_session_type_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_session_type, 4)); + HANDLE_CODE(pdu_session_type.pack(bref)); + } + if (ssc_mode_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ssc_mode, 4)); + HANDLE_CODE(ssc_mode.pack(bref)); + } + if (capability_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_capability_5gsm, 8)); + HANDLE_CODE(capability_5gsm.pack(bref)); + } + if (maximum_number_of_supported_packet_filters_present == true) { + HANDLE_CODE(bref.pack(ie_iei_maximum_number_of_supported_packet_filters, 8)); + HANDLE_CODE(maximum_number_of_supported_packet_filters.pack(bref)); + } + if (always_on_pdu_session_requested_present == true) { + HANDLE_CODE(bref.pack(ie_iei_always_on_pdu_session_requested, 4)); + HANDLE_CODE(always_on_pdu_session_requested.pack(bref)); + } + if (sm_pdu_dn_request_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_sm_pdu_dn_request_container, 8)); + HANDLE_CODE(sm_pdu_dn_request_container.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + if (ip_header_compression_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ip_header_compression_configuration, 8)); + HANDLE_CODE(ip_header_compression_configuration.pack(bref)); + } + if (ds_tt__ethernet_port_mac_address_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ds_tt__ethernet_port_mac_address, 8)); + HANDLE_CODE(ds_tt__ethernet_port_mac_address.pack(bref)); + } + if (ue_ds_tt_residence_time_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ue_ds_tt_residence_time, 8)); + HANDLE_CODE(ue_ds_tt_residence_time.pack(bref)); + } + if (port_management_information_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_port_management_information_container, 8)); + HANDLE_CODE(port_management_information_container.pack(bref)); + } + if (ethernet_header_compression_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ethernet_header_compression_configuration, 8)); + HANDLE_CODE(ethernet_header_compression_configuration.pack(bref)); + } + if (suggested_interface_identifier_present == true) { + HANDLE_CODE(bref.pack(ie_iei_suggested_interface_identifier, 8)); + HANDLE_CODE(suggested_interface_identifier.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_establishment_request_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(integrity_protection_maximum_data_rate.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_pdu_session_type: + pdu_session_type_present = true; + HANDLE_CODE(pdu_session_type.unpack(bref)); + break; + case ie_iei_ssc_mode: + ssc_mode_present = true; + HANDLE_CODE(ssc_mode.unpack(bref)); + break; + case ie_iei_capability_5gsm: + capability_5gsm_present = true; + HANDLE_CODE(capability_5gsm.unpack(bref)); + break; + case ie_iei_maximum_number_of_supported_packet_filters: + maximum_number_of_supported_packet_filters_present = true; + HANDLE_CODE(maximum_number_of_supported_packet_filters.unpack(bref)); + break; + case ie_iei_always_on_pdu_session_requested: + always_on_pdu_session_requested_present = true; + HANDLE_CODE(always_on_pdu_session_requested.unpack(bref)); + break; + case ie_iei_sm_pdu_dn_request_container: + sm_pdu_dn_request_container_present = true; + HANDLE_CODE(sm_pdu_dn_request_container.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + case ie_iei_ip_header_compression_configuration: + ip_header_compression_configuration_present = true; + HANDLE_CODE(ip_header_compression_configuration.unpack(bref)); + break; + case ie_iei_ds_tt__ethernet_port_mac_address: + ds_tt__ethernet_port_mac_address_present = true; + HANDLE_CODE(ds_tt__ethernet_port_mac_address.unpack(bref)); + break; + case ie_iei_ue_ds_tt_residence_time: + ue_ds_tt_residence_time_present = true; + HANDLE_CODE(ue_ds_tt_residence_time.unpack(bref)); + break; + case ie_iei_port_management_information_container: + port_management_information_container_present = true; + HANDLE_CODE(port_management_information_container.unpack(bref)); + break; + case ie_iei_ethernet_header_compression_configuration: + ethernet_header_compression_configuration_present = true; + HANDLE_CODE(ethernet_header_compression_configuration.unpack(bref)); + break; + case ie_iei_suggested_interface_identifier: + suggested_interface_identifier_present = true; + HANDLE_CODE(suggested_interface_identifier.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_establishment_accept_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(selected_ssc_mode.pack(bref)); + HANDLE_CODE(selected_pdu_session_type.pack(bref)); + HANDLE_CODE(authorized__qo_s_rules.pack(bref)); + HANDLE_CODE(session_ambr.pack(bref)); + + // Optional fields + if (cause_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cause_5gsm, 8)); + HANDLE_CODE(cause_5gsm.pack(bref)); + } + if (pdu_address_present == true) { + HANDLE_CODE(bref.pack(ie_iei_pdu_address, 8)); + HANDLE_CODE(pdu_address.pack(bref)); + } + if (rq_timer_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_rq_timer_value, 8)); + HANDLE_CODE(rq_timer_value.pack(bref)); + } + if (s_nssai_present == true) { + HANDLE_CODE(bref.pack(ie_iei_s_nssai, 8)); + HANDLE_CODE(s_nssai.pack(bref)); + } + if (always_on_pdu_session_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_always_on_pdu_session_indication, 4)); + HANDLE_CODE(always_on_pdu_session_indication.pack(bref)); + } + if (mapped_eps_bearer_contexts_present == true) { + HANDLE_CODE(bref.pack(ie_iei_mapped_eps_bearer_contexts, 8)); + HANDLE_CODE(mapped_eps_bearer_contexts.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (authorized__qo_s_flow_descriptions_present == true) { + HANDLE_CODE(bref.pack(ie_iei_authorized__qo_s_flow_descriptions, 8)); + HANDLE_CODE(authorized__qo_s_flow_descriptions.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + if (dnn_present == true) { + HANDLE_CODE(bref.pack(ie_iei_dnn, 8)); + HANDLE_CODE(dnn.pack(bref)); + } + if (network_feature_support_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_network_feature_support_5gsm, 8)); + HANDLE_CODE(network_feature_support_5gsm.pack(bref)); + } + if (serving_plmn_rate_control_present == true) { + HANDLE_CODE(bref.pack(ie_iei_serving_plmn_rate_control, 8)); + HANDLE_CODE(serving_plmn_rate_control.pack(bref)); + } + if (atsss_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_atsss_container, 8)); + HANDLE_CODE(atsss_container.pack(bref)); + } + if (control_plane_only_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_control_plane_only_indication, 4)); + HANDLE_CODE(control_plane_only_indication.pack(bref)); + } + if (ip_header_compression_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ip_header_compression_configuration, 8)); + HANDLE_CODE(ip_header_compression_configuration.pack(bref)); + } + if (ethernet_header_compression_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ethernet_header_compression_configuration, 8)); + HANDLE_CODE(ethernet_header_compression_configuration.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_establishment_accept_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(selected_ssc_mode.unpack(bref)); + HANDLE_CODE(selected_pdu_session_type.unpack(bref)); + HANDLE_CODE(authorized__qo_s_rules.unpack(bref)); + HANDLE_CODE(session_ambr.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_cause_5gsm: + cause_5gsm_present = true; + HANDLE_CODE(cause_5gsm.unpack(bref)); + break; + case ie_iei_pdu_address: + pdu_address_present = true; + HANDLE_CODE(pdu_address.unpack(bref)); + break; + case ie_iei_rq_timer_value: + rq_timer_value_present = true; + HANDLE_CODE(rq_timer_value.unpack(bref)); + break; + case ie_iei_s_nssai: + s_nssai_present = true; + HANDLE_CODE(s_nssai.unpack(bref)); + break; + case ie_iei_always_on_pdu_session_indication: + always_on_pdu_session_indication_present = true; + HANDLE_CODE(always_on_pdu_session_indication.unpack(bref)); + break; + case ie_iei_mapped_eps_bearer_contexts: + mapped_eps_bearer_contexts_present = true; + HANDLE_CODE(mapped_eps_bearer_contexts.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_authorized__qo_s_flow_descriptions: + authorized__qo_s_flow_descriptions_present = true; + HANDLE_CODE(authorized__qo_s_flow_descriptions.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + case ie_iei_dnn: + dnn_present = true; + HANDLE_CODE(dnn.unpack(bref)); + break; + case ie_iei_network_feature_support_5gsm: + network_feature_support_5gsm_present = true; + HANDLE_CODE(network_feature_support_5gsm.unpack(bref)); + break; + case ie_iei_serving_plmn_rate_control: + serving_plmn_rate_control_present = true; + HANDLE_CODE(serving_plmn_rate_control.unpack(bref)); + break; + case ie_iei_atsss_container: + atsss_container_present = true; + HANDLE_CODE(atsss_container.unpack(bref)); + break; + case ie_iei_control_plane_only_indication: + control_plane_only_indication_present = true; + HANDLE_CODE(control_plane_only_indication.unpack(bref)); + break; + case ie_iei_ip_header_compression_configuration: + ip_header_compression_configuration_present = true; + HANDLE_CODE(ip_header_compression_configuration.unpack(bref)); + break; + case ie_iei_ethernet_header_compression_configuration: + ethernet_header_compression_configuration_present = true; + HANDLE_CODE(ethernet_header_compression_configuration.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_establishment_reject_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.pack(bref)); + + // Optional fields + if (back_off_timer_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_back_off_timer_value, 8)); + HANDLE_CODE(back_off_timer_value.pack(bref)); + } + if (allowed_ssc_mode_present == true) { + HANDLE_CODE(bref.pack(ie_iei_allowed_ssc_mode, 4)); + HANDLE_CODE(allowed_ssc_mode.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (congestion_re_attempt_indicator_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_congestion_re_attempt_indicator_5gsm, 8)); + HANDLE_CODE(congestion_re_attempt_indicator_5gsm.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + if (re_attempt_indicator_present == true) { + HANDLE_CODE(bref.pack(ie_iei_re_attempt_indicator, 8)); + HANDLE_CODE(re_attempt_indicator.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_establishment_reject_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_back_off_timer_value: + back_off_timer_value_present = true; + HANDLE_CODE(back_off_timer_value.unpack(bref)); + break; + case ie_iei_allowed_ssc_mode: + allowed_ssc_mode_present = true; + HANDLE_CODE(allowed_ssc_mode.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_congestion_re_attempt_indicator_5gsm: + congestion_re_attempt_indicator_5gsm_present = true; + HANDLE_CODE(congestion_re_attempt_indicator_5gsm.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + case ie_iei_re_attempt_indicator: + re_attempt_indicator_present = true; + HANDLE_CODE(re_attempt_indicator.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_authentication_command_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(eap_message.pack(bref)); + + // Optional fields + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_authentication_command_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(eap_message.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_authentication_complete_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(eap_message.pack(bref)); + + // Optional fields + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_authentication_complete_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(eap_message.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_authentication_result_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_authentication_result_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_modification_request_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (capability_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_capability_5gsm, 8)); + HANDLE_CODE(capability_5gsm.pack(bref)); + } + if (cause_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cause_5gsm, 8)); + HANDLE_CODE(cause_5gsm.pack(bref)); + } + if (maximum_number_of_supported_packet_filters_present == true) { + HANDLE_CODE(bref.pack(ie_iei_maximum_number_of_supported_packet_filters, 8)); + HANDLE_CODE(maximum_number_of_supported_packet_filters.pack(bref)); + } + if (always_on_pdu_session_requested_present == true) { + HANDLE_CODE(bref.pack(ie_iei_always_on_pdu_session_requested, 4)); + HANDLE_CODE(always_on_pdu_session_requested.pack(bref)); + } + if (integrity_protection_maximum_data_rate_present == true) { + HANDLE_CODE(bref.pack(ie_iei_integrity_protection_maximum_data_rate, 8)); + HANDLE_CODE(integrity_protection_maximum_data_rate.pack(bref)); + } + if (requested__qo_s_rules_present == true) { + HANDLE_CODE(bref.pack(ie_iei_requested__qo_s_rules, 8)); + HANDLE_CODE(requested__qo_s_rules.pack(bref)); + } + if (requested__qo_s_flow_descriptions_present == true) { + HANDLE_CODE(bref.pack(ie_iei_requested__qo_s_flow_descriptions, 8)); + HANDLE_CODE(requested__qo_s_flow_descriptions.pack(bref)); + } + if (mapped_eps_bearer_contexts_present == true) { + HANDLE_CODE(bref.pack(ie_iei_mapped_eps_bearer_contexts, 8)); + HANDLE_CODE(mapped_eps_bearer_contexts.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + if (port_management_information_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_port_management_information_container, 8)); + HANDLE_CODE(port_management_information_container.pack(bref)); + } + if (ip_header_compression_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ip_header_compression_configuration, 8)); + HANDLE_CODE(ip_header_compression_configuration.pack(bref)); + } + if (ethernet_header_compression_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ethernet_header_compression_configuration, 8)); + HANDLE_CODE(ethernet_header_compression_configuration.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_modification_request_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_capability_5gsm: + capability_5gsm_present = true; + HANDLE_CODE(capability_5gsm.unpack(bref)); + break; + case ie_iei_cause_5gsm: + cause_5gsm_present = true; + HANDLE_CODE(cause_5gsm.unpack(bref)); + break; + case ie_iei_maximum_number_of_supported_packet_filters: + maximum_number_of_supported_packet_filters_present = true; + HANDLE_CODE(maximum_number_of_supported_packet_filters.unpack(bref)); + break; + case ie_iei_always_on_pdu_session_requested: + always_on_pdu_session_requested_present = true; + HANDLE_CODE(always_on_pdu_session_requested.unpack(bref)); + break; + case ie_iei_integrity_protection_maximum_data_rate: + integrity_protection_maximum_data_rate_present = true; + HANDLE_CODE(integrity_protection_maximum_data_rate.unpack(bref)); + break; + case ie_iei_requested__qo_s_rules: + requested__qo_s_rules_present = true; + HANDLE_CODE(requested__qo_s_rules.unpack(bref)); + break; + case ie_iei_requested__qo_s_flow_descriptions: + requested__qo_s_flow_descriptions_present = true; + HANDLE_CODE(requested__qo_s_flow_descriptions.unpack(bref)); + break; + case ie_iei_mapped_eps_bearer_contexts: + mapped_eps_bearer_contexts_present = true; + HANDLE_CODE(mapped_eps_bearer_contexts.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + case ie_iei_port_management_information_container: + port_management_information_container_present = true; + HANDLE_CODE(port_management_information_container.unpack(bref)); + break; + case ie_iei_ip_header_compression_configuration: + ip_header_compression_configuration_present = true; + HANDLE_CODE(ip_header_compression_configuration.unpack(bref)); + break; + case ie_iei_ethernet_header_compression_configuration: + ethernet_header_compression_configuration_present = true; + HANDLE_CODE(ethernet_header_compression_configuration.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_modification_reject_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.pack(bref)); + + // Optional fields + if (back_off_timer_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_back_off_timer_value, 8)); + HANDLE_CODE(back_off_timer_value.pack(bref)); + } + if (congestion_re_attempt_indicator_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_congestion_re_attempt_indicator_5gsm, 8)); + HANDLE_CODE(congestion_re_attempt_indicator_5gsm.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + if (re_attempt_indicator_present == true) { + HANDLE_CODE(bref.pack(ie_iei_re_attempt_indicator, 8)); + HANDLE_CODE(re_attempt_indicator.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_modification_reject_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_back_off_timer_value: + back_off_timer_value_present = true; + HANDLE_CODE(back_off_timer_value.unpack(bref)); + break; + case ie_iei_congestion_re_attempt_indicator_5gsm: + congestion_re_attempt_indicator_5gsm_present = true; + HANDLE_CODE(congestion_re_attempt_indicator_5gsm.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + case ie_iei_re_attempt_indicator: + re_attempt_indicator_present = true; + HANDLE_CODE(re_attempt_indicator.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_modification_command_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (cause_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cause_5gsm, 8)); + HANDLE_CODE(cause_5gsm.pack(bref)); + } + if (session_ambr_present == true) { + HANDLE_CODE(bref.pack(ie_iei_session_ambr, 8)); + HANDLE_CODE(session_ambr.pack(bref)); + } + if (rq_timer_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_rq_timer_value, 8)); + HANDLE_CODE(rq_timer_value.pack(bref)); + } + if (always_on_pdu_session_indication_present == true) { + HANDLE_CODE(bref.pack(ie_iei_always_on_pdu_session_indication, 4)); + HANDLE_CODE(always_on_pdu_session_indication.pack(bref)); + } + if (authorized__qo_s_rules_present == true) { + HANDLE_CODE(bref.pack(ie_iei_authorized__qo_s_rules, 8)); + HANDLE_CODE(authorized__qo_s_rules.pack(bref)); + } + if (mapped_eps_bearer_contexts_present == true) { + HANDLE_CODE(bref.pack(ie_iei_mapped_eps_bearer_contexts, 8)); + HANDLE_CODE(mapped_eps_bearer_contexts.pack(bref)); + } + if (authorized__qo_s_flow_descriptions_present == true) { + HANDLE_CODE(bref.pack(ie_iei_authorized__qo_s_flow_descriptions, 8)); + HANDLE_CODE(authorized__qo_s_flow_descriptions.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + if (atsss_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_atsss_container, 8)); + HANDLE_CODE(atsss_container.pack(bref)); + } + if (ip_header_compression_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ip_header_compression_configuration, 8)); + HANDLE_CODE(ip_header_compression_configuration.pack(bref)); + } + if (port_management_information_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_port_management_information_container, 8)); + HANDLE_CODE(port_management_information_container.pack(bref)); + } + if (serving_plmn_rate_control_present == true) { + HANDLE_CODE(bref.pack(ie_iei_serving_plmn_rate_control, 8)); + HANDLE_CODE(serving_plmn_rate_control.pack(bref)); + } + if (ethernet_header_compression_configuration_present == true) { + HANDLE_CODE(bref.pack(ie_iei_ethernet_header_compression_configuration, 8)); + HANDLE_CODE(ethernet_header_compression_configuration.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_modification_command_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_cause_5gsm: + cause_5gsm_present = true; + HANDLE_CODE(cause_5gsm.unpack(bref)); + break; + case ie_iei_session_ambr: + session_ambr_present = true; + HANDLE_CODE(session_ambr.unpack(bref)); + break; + case ie_iei_rq_timer_value: + rq_timer_value_present = true; + HANDLE_CODE(rq_timer_value.unpack(bref)); + break; + case ie_iei_always_on_pdu_session_indication: + always_on_pdu_session_indication_present = true; + HANDLE_CODE(always_on_pdu_session_indication.unpack(bref)); + break; + case ie_iei_authorized__qo_s_rules: + authorized__qo_s_rules_present = true; + HANDLE_CODE(authorized__qo_s_rules.unpack(bref)); + break; + case ie_iei_mapped_eps_bearer_contexts: + mapped_eps_bearer_contexts_present = true; + HANDLE_CODE(mapped_eps_bearer_contexts.unpack(bref)); + break; + case ie_iei_authorized__qo_s_flow_descriptions: + authorized__qo_s_flow_descriptions_present = true; + HANDLE_CODE(authorized__qo_s_flow_descriptions.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + case ie_iei_atsss_container: + atsss_container_present = true; + HANDLE_CODE(atsss_container.unpack(bref)); + break; + case ie_iei_ip_header_compression_configuration: + ip_header_compression_configuration_present = true; + HANDLE_CODE(ip_header_compression_configuration.unpack(bref)); + break; + case ie_iei_port_management_information_container: + port_management_information_container_present = true; + HANDLE_CODE(port_management_information_container.unpack(bref)); + break; + case ie_iei_serving_plmn_rate_control: + serving_plmn_rate_control_present = true; + HANDLE_CODE(serving_plmn_rate_control.unpack(bref)); + break; + case ie_iei_ethernet_header_compression_configuration: + ethernet_header_compression_configuration_present = true; + HANDLE_CODE(ethernet_header_compression_configuration.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_modification_complete_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + if (port_management_information_container_present == true) { + HANDLE_CODE(bref.pack(ie_iei_port_management_information_container, 8)); + HANDLE_CODE(port_management_information_container.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_modification_complete_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + case ie_iei_port_management_information_container: + port_management_information_container_present = true; + HANDLE_CODE(port_management_information_container.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_modification_command_reject_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.pack(bref)); + + // Optional fields + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_modification_command_reject_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_release_request_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (cause_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cause_5gsm, 8)); + HANDLE_CODE(cause_5gsm.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_release_request_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_cause_5gsm: + cause_5gsm_present = true; + HANDLE_CODE(cause_5gsm.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_release_reject_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.pack(bref)); + + // Optional fields + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_release_reject_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_release_command_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.pack(bref)); + + // Optional fields + if (back_off_timer_value_present == true) { + HANDLE_CODE(bref.pack(ie_iei_back_off_timer_value, 8)); + HANDLE_CODE(back_off_timer_value.pack(bref)); + } + if (eap_message_present == true) { + HANDLE_CODE(bref.pack(ie_iei_eap_message, 8)); + HANDLE_CODE(eap_message.pack(bref)); + } + if (congestion_re_attempt_indicator_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_congestion_re_attempt_indicator_5gsm, 8)); + HANDLE_CODE(congestion_re_attempt_indicator_5gsm.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + if (access_type_present == true) { + HANDLE_CODE(bref.pack(ie_iei_access_type, 4)); + HANDLE_CODE(access_type.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_release_command_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_back_off_timer_value: + back_off_timer_value_present = true; + HANDLE_CODE(back_off_timer_value.unpack(bref)); + break; + case ie_iei_eap_message: + eap_message_present = true; + HANDLE_CODE(eap_message.unpack(bref)); + break; + case ie_iei_congestion_re_attempt_indicator_5gsm: + congestion_re_attempt_indicator_5gsm_present = true; + HANDLE_CODE(congestion_re_attempt_indicator_5gsm.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + case ie_iei_access_type: + access_type_present = true; + HANDLE_CODE(access_type.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE pdu_session_release_complete_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + + // Optional fields + if (cause_5gsm_present == true) { + HANDLE_CODE(bref.pack(ie_iei_cause_5gsm, 8)); + HANDLE_CODE(cause_5gsm.pack(bref)); + } + if (extended_protocol_configuration_options_present == true) { + HANDLE_CODE(bref.pack(ie_iei_extended_protocol_configuration_options, 8)); + HANDLE_CODE(extended_protocol_configuration_options.pack(bref)); + } + + return SRSASN_SUCCESS; +} +SRSASN_CODE pdu_session_release_complete_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + case ie_iei_cause_5gsm: + cause_5gsm_present = true; + HANDLE_CODE(cause_5gsm.unpack(bref)); + break; + case ie_iei_extended_protocol_configuration_options: + extended_protocol_configuration_options_present = true; + HANDLE_CODE(extended_protocol_configuration_options.unpack(bref)); + break; + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +SRSASN_CODE status_5gsm_t::pack(asn1::bit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.pack(bref)); + + // Optional fields + + return SRSASN_SUCCESS; +} +SRSASN_CODE status_5gsm_t::unpack(asn1::cbit_ref& bref) +{ + // Mandatory fields + HANDLE_CODE(cause_5gsm.unpack(bref)); + + // Optional fields + + while (bref.distance_bytes_end() > 0) { + // some iei are only 1/2 byte long which are > 8 + // otherwise a complete byte + uint8_t iei; + HANDLE_CODE(bref.unpack(iei, 4)); + if (iei < 8) { + uint8_t iei_tmp; + HANDLE_CODE(bref.unpack(iei_tmp, 4)); + iei = iei << 4 | iei_tmp; + } + + switch (iei) { + default: + asn1::log_error("Invalid IE %x", iei); + break; + } + } + + return SRSASN_SUCCESS; +} + +// Include from nas5g/infiles/nas_5g_msg.cc.in + +SRSASN_CODE nas_5gs_hdr::unpack_outer(asn1::cbit_ref& bref) +{ + unpack_enum(bref, &extended_protocol_discriminator); + // Security header type associated with a spare half octet; or PDU session identity + switch (extended_protocol_discriminator) { + case extended_protocol_discriminator_5gmm: + HANDLE_CODE(bref.advance_bits(4)); // spare + unpack_enum(bref, &security_header_type); + if (security_header_type == plain_5gs_nas_message) { + HANDLE_CODE(message_type.unpack(bref)); + } else { + HANDLE_CODE(bref.unpack(message_authentication_code, 32)); + HANDLE_CODE(bref.unpack(sequence_number, 8)); + } + break; + case extended_protocol_discriminator_5gsm: + // The PDU session identity and the procedure transaction identity are only used in messages with extended + // protocol discriminator 5GS session management. Octet 2a with the procedure transaction identity shall only be + // included in these messages. + HANDLE_CODE(bref.unpack(pdu_session_identity, 8)); + HANDLE_CODE(bref.unpack(procedure_transaction_identity, 8)); + HANDLE_CODE(message_type.unpack(bref)); + break; + default: + asn1::log_error("Unsupported extended protocol discriminator %x\n", extended_protocol_discriminator); + return SRSASN_ERROR_DECODE_FAIL; + } + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_hdr::unpack(asn1::cbit_ref& bref) +{ + unpack_outer(bref); + if (security_header_type != plain_5gs_nas_message) { + unpack_enum(bref, &inner_extended_protocol_discriminator); + // Security header type associated with a spare half octet; or PDU session identity + switch (inner_extended_protocol_discriminator) { + case extended_protocol_discriminator_5gmm: + HANDLE_CODE(bref.advance_bits(4)); // spare + unpack_enum(bref, &inner_security_header_type); + if (inner_security_header_type == plain_5gs_nas_message) { + HANDLE_CODE(message_type.unpack(bref)); + } else { + asn1::log_error("Expected inner security type to be plain\n"); + return SRSASN_ERROR_DECODE_FAIL; + } + break; + case extended_protocol_discriminator_5gsm: + // The PDU session identity and the procedure transaction identity are only used in messages with extended + // protocol discriminator 5GS session management. Octet 2a with the procedure transaction identity shall only be + // included in these messages. + HANDLE_CODE(bref.unpack(pdu_session_identity, 8)); + HANDLE_CODE(bref.unpack(procedure_transaction_identity, 8)); + HANDLE_CODE(message_type.unpack(bref)); + break; + default: + asn1::log_error("Unsupported extended protocol discriminator %x\n", inner_extended_protocol_discriminator); + return SRSASN_ERROR_DECODE_FAIL; + } + } + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_hdr::pack_outer(asn1::bit_ref& bref) +{ + pack_enum(bref, extended_protocol_discriminator); + // Security header type associated with a spare half octet; or PDU session identity + switch (extended_protocol_discriminator) { + case extended_protocol_discriminator_5gmm: + HANDLE_CODE(bref.pack(0x0, 4)); // spare + pack_enum(bref, security_header_type); + if (security_header_type == plain_5gs_nas_message) { + HANDLE_CODE(message_type.pack(bref)); + } else { + HANDLE_CODE(bref.pack(message_authentication_code, 32)); + HANDLE_CODE(bref.pack(sequence_number, 8)); + } + break; + case extended_protocol_discriminator_5gsm: + // The PDU session identity and the procedure transaction identity are only used in messages with extended + // protocol discriminator 5GS session management. Octet 2a with the procedure transaction identity shall only be + // included in these messages. + HANDLE_CODE(bref.pack(pdu_session_identity, 8)); + HANDLE_CODE(bref.pack(procedure_transaction_identity, 8)); + HANDLE_CODE(message_type.pack(bref)); + break; + default: + asn1::log_error("Unsupported extended protocol discriminator %x\n", extended_protocol_discriminator); + return SRSASN_ERROR_DECODE_FAIL; + } + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_hdr::pack(asn1::bit_ref& bref) +{ + pack_outer(bref); + if (security_header_type != plain_5gs_nas_message) { + pack_enum(bref, inner_extended_protocol_discriminator); + if (inner_extended_protocol_discriminator == extended_protocol_discriminator_5gsm) { + HANDLE_CODE(bref.pack(pdu_session_identity, 4)); + } else { + HANDLE_CODE(bref.pack(0x0, 4)); + } + pack_enum(bref, inner_security_header_type); + if (inner_extended_protocol_discriminator == extended_protocol_discriminator_5gsm) { + HANDLE_CODE(bref.pack(procedure_transaction_identity, 8)); + } + HANDLE_CODE(message_type.pack(bref)); + } + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_msg::pack(unique_byte_buffer_t& buf) +{ + asn1::bit_ref msg_bref(buf->msg, buf->get_tailroom()); + HANDLE_CODE(pack(msg_bref)); + buf->N_bytes = msg_bref.distance_bytes(); + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_msg::pack(std::vector buf) +{ + buf.resize(SRSRAN_MAX_BUFFER_SIZE_BYTES); + asn1::bit_ref msg_bref(buf.data(), buf.size()); + HANDLE_CODE(pack(msg_bref)); + buf.resize(msg_bref.distance_bytes()); + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_msg::pack(asn1::bit_ref& msg_bref) +{ + HANDLE_CODE(hdr.pack(msg_bref)); + switch (hdr.message_type) { + case msg_types::options::registration_request: { + registration_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::registration_accept: { + registration_accept_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::registration_complete: { + registration_complete_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::registration_reject: { + registration_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::deregistration_request_ue_originating: { + deregistration_request_ue_originating_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::deregistration_accept_ue_originating: { + deregistration_accept_ue_originating_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::deregistration_request_ue_terminated: { + deregistration_request_ue_terminated_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::deregistration_accept_ue_terminated: { + deregistration_accept_ue_terminated_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::service_request: { + service_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::service_reject: { + service_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::service_accept: { + service_accept_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::configuration_update_command: { + configuration_update_command_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::configuration_update_complete: { + configuration_update_complete_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::authentication_request: { + authentication_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::authentication_response: { + authentication_response_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::authentication_reject: { + authentication_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::authentication_failure: { + authentication_failure_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::authentication_result: { + authentication_result_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::identity_request: { + identity_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::identity_response: { + identity_response_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::security_mode_command: { + security_mode_command_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::security_mode_complete: { + security_mode_complete_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::security_mode_reject: { + security_mode_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::status_5gmm: { + status_5gmm_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::notification: { + notification_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::notification_response: { + notification_response_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::ul_nas_transport: { + ul_nas_transport_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::dl_nas_transport: { + dl_nas_transport_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_establishment_request: { + pdu_session_establishment_request_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_establishment_accept: { + pdu_session_establishment_accept_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_establishment_reject: { + pdu_session_establishment_reject_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_authentication_command: { + pdu_session_authentication_command_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_authentication_complete: { + pdu_session_authentication_complete_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_authentication_result: { + pdu_session_authentication_result_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_request: { + pdu_session_modification_request_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_reject: { + pdu_session_modification_reject_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_command: { + pdu_session_modification_command_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_complete: { + pdu_session_modification_complete_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_command_reject: { + pdu_session_modification_command_reject_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_release_request: { + pdu_session_release_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_release_reject: { + pdu_session_release_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_release_command: { + pdu_session_release_command_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::pdu_session_release_complete: { + pdu_session_release_complete_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + case msg_types::options::status_5gsm: { + status_5gsm_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->pack(msg_bref)); + break; + } + + default: + break; + } + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_msg::unpack_outer_hdr(const unique_byte_buffer_t& buf) +{ + asn1::cbit_ref msg_bref(buf->msg, buf->N_bytes); + HANDLE_CODE(hdr.unpack_outer(msg_bref)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_msg::unpack_outer_hdr(const std::vector buf) +{ + asn1::cbit_ref msg_bref(buf.data(), buf.size()); + HANDLE_CODE(hdr.unpack_outer(msg_bref)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_msg::unpack(const unique_byte_buffer_t& buf) +{ + asn1::cbit_ref msg_bref(buf->msg, buf->N_bytes); + HANDLE_CODE(unpack(msg_bref)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_msg::unpack(const std::vector buf) +{ + asn1::cbit_ref msg_bref(buf.data(), buf.size()); + HANDLE_CODE(unpack(msg_bref)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE nas_5gs_msg::unpack(asn1::cbit_ref& msg_bref) +{ + HANDLE_CODE(hdr.unpack(msg_bref)); + switch (hdr.message_type) { + case msg_types::options::registration_request: { + msg_container = srslog::detail::any{registration_request_t()}; + registration_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::registration_accept: { + msg_container = srslog::detail::any{registration_accept_t()}; + registration_accept_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::registration_complete: { + msg_container = srslog::detail::any{registration_complete_t()}; + registration_complete_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::registration_reject: { + msg_container = srslog::detail::any{registration_reject_t()}; + registration_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::deregistration_request_ue_originating: { + msg_container = srslog::detail::any{deregistration_request_ue_originating_t()}; + deregistration_request_ue_originating_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::deregistration_accept_ue_originating: { + msg_container = srslog::detail::any{deregistration_accept_ue_originating_t()}; + deregistration_accept_ue_originating_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::deregistration_request_ue_terminated: { + msg_container = srslog::detail::any{deregistration_request_ue_terminated_t()}; + deregistration_request_ue_terminated_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::deregistration_accept_ue_terminated: { + msg_container = srslog::detail::any{deregistration_accept_ue_terminated_t()}; + deregistration_accept_ue_terminated_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::service_request: { + msg_container = srslog::detail::any{service_request_t()}; + service_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::service_reject: { + msg_container = srslog::detail::any{service_reject_t()}; + service_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::service_accept: { + msg_container = srslog::detail::any{service_accept_t()}; + service_accept_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::configuration_update_command: { + msg_container = srslog::detail::any{configuration_update_command_t()}; + configuration_update_command_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::configuration_update_complete: { + msg_container = srslog::detail::any{configuration_update_complete_t()}; + configuration_update_complete_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::authentication_request: { + msg_container = srslog::detail::any{authentication_request_t()}; + authentication_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::authentication_response: { + msg_container = srslog::detail::any{authentication_response_t()}; + authentication_response_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::authentication_reject: { + msg_container = srslog::detail::any{authentication_reject_t()}; + authentication_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::authentication_failure: { + msg_container = srslog::detail::any{authentication_failure_t()}; + authentication_failure_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::authentication_result: { + msg_container = srslog::detail::any{authentication_result_t()}; + authentication_result_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::identity_request: { + msg_container = srslog::detail::any{identity_request_t()}; + identity_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::identity_response: { + msg_container = srslog::detail::any{identity_response_t()}; + identity_response_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::security_mode_command: { + msg_container = srslog::detail::any{security_mode_command_t()}; + security_mode_command_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::security_mode_complete: { + msg_container = srslog::detail::any{security_mode_complete_t()}; + security_mode_complete_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::security_mode_reject: { + msg_container = srslog::detail::any{security_mode_reject_t()}; + security_mode_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::status_5gmm: { + msg_container = srslog::detail::any{status_5gmm_t()}; + status_5gmm_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::notification: { + msg_container = srslog::detail::any{notification_t()}; + notification_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::notification_response: { + msg_container = srslog::detail::any{notification_response_t()}; + notification_response_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::ul_nas_transport: { + msg_container = srslog::detail::any{ul_nas_transport_t()}; + ul_nas_transport_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::dl_nas_transport: { + msg_container = srslog::detail::any{dl_nas_transport_t()}; + dl_nas_transport_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_establishment_request: { + msg_container = srslog::detail::any{pdu_session_establishment_request_t()}; + pdu_session_establishment_request_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_establishment_accept: { + msg_container = srslog::detail::any{pdu_session_establishment_accept_t()}; + pdu_session_establishment_accept_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_establishment_reject: { + msg_container = srslog::detail::any{pdu_session_establishment_reject_t()}; + pdu_session_establishment_reject_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_authentication_command: { + msg_container = srslog::detail::any{pdu_session_authentication_command_t()}; + pdu_session_authentication_command_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_authentication_complete: { + msg_container = srslog::detail::any{pdu_session_authentication_complete_t()}; + pdu_session_authentication_complete_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_authentication_result: { + msg_container = srslog::detail::any{pdu_session_authentication_result_t()}; + pdu_session_authentication_result_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_request: { + msg_container = srslog::detail::any{pdu_session_modification_request_t()}; + pdu_session_modification_request_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_reject: { + msg_container = srslog::detail::any{pdu_session_modification_reject_t()}; + pdu_session_modification_reject_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_command: { + msg_container = srslog::detail::any{pdu_session_modification_command_t()}; + pdu_session_modification_command_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_complete: { + msg_container = srslog::detail::any{pdu_session_modification_complete_t()}; + pdu_session_modification_complete_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_modification_command_reject: { + msg_container = srslog::detail::any{pdu_session_modification_command_reject_t()}; + pdu_session_modification_command_reject_t* msg = + srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_release_request: { + msg_container = srslog::detail::any{pdu_session_release_request_t()}; + pdu_session_release_request_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_release_reject: { + msg_container = srslog::detail::any{pdu_session_release_reject_t()}; + pdu_session_release_reject_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_release_command: { + msg_container = srslog::detail::any{pdu_session_release_command_t()}; + pdu_session_release_command_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::pdu_session_release_complete: { + msg_container = srslog::detail::any{pdu_session_release_complete_t()}; + pdu_session_release_complete_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + case msg_types::options::status_5gsm: { + msg_container = srslog::detail::any{status_5gsm_t()}; + status_5gsm_t* msg = srslog::detail::any_cast(&msg_container); + HANDLE_CODE(msg->unpack(msg_bref)); + break; + } + + default: + break; + } + return SRSASN_SUCCESS; +} + +} // namespace nas_5g +} // namespace srsran diff --git a/lib/src/asn1/nas_5g_utils.cc b/lib/src/asn1/nas_5g_utils.cc new file mode 100644 index 000000000..24915c8c8 --- /dev/null +++ b/lib/src/asn1/nas_5g_utils.cc @@ -0,0 +1,56 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/asn1/nas_5g_utils.h" + +#include "srsran/asn1/asn1_utils.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/common.h" +#include "srsran/config.h" + +#include +#include +#include + +namespace srsran { +namespace nas_5g { + +SRSASN_CODE unpack_mcc_mnc(uint8_t* mcc_bytes, uint8_t* mnc_bytes, asn1::cbit_ref& bref) +{ + // MCC digit 2 | MCC digit 1 | octet 5 + // MNC digit 3 | MCC digit 3 | octet 6 + // MNC digit 2 | MNC digit 1 | octet 7 + HANDLE_CODE(bref.unpack(mcc_bytes[1], 4)); + HANDLE_CODE(bref.unpack(mcc_bytes[0], 4)); + HANDLE_CODE(bref.unpack(mnc_bytes[2], 4)); + HANDLE_CODE(bref.unpack(mcc_bytes[2], 4)); + HANDLE_CODE(bref.unpack(mnc_bytes[1], 4)); + HANDLE_CODE(bref.unpack(mnc_bytes[0], 4)); + return SRSASN_SUCCESS; +} + +SRSASN_CODE pack_mcc_mnc(uint8_t* mcc_bytes, uint8_t* mnc_bytes, asn1::bit_ref& bref) +{ + // MCC digit 2 | MCC digit 1 | octet 5 + // MNC digit 3 | MCC digit 3 | octet 6 + // MNC digit 2 | MNC digit 1 | octet 7 + HANDLE_CODE(bref.pack(mcc_bytes[1], 4)); + HANDLE_CODE(bref.pack(mcc_bytes[0], 4)); + HANDLE_CODE(bref.pack(mnc_bytes[2], 4)); + HANDLE_CODE(bref.pack(mcc_bytes[2], 4)); + HANDLE_CODE(bref.pack(mnc_bytes[1], 4)); + HANDLE_CODE(bref.pack(mnc_bytes[0], 4)); + return SRSASN_SUCCESS; +} + +} // namespace nas_5g +} // namespace srsran \ No newline at end of file diff --git a/lib/test/asn1/CMakeLists.txt b/lib/test/asn1/CMakeLists.txt index 5ee4ff156..1c7054213 100644 --- a/lib/test/asn1/CMakeLists.txt +++ b/lib/test/asn1/CMakeLists.txt @@ -59,3 +59,6 @@ target_link_libraries(rrc_asn1_decoder rrc_asn1) add_executable(nas_decoder nas_decoder.cc) target_link_libraries(nas_decoder srsran_asn1) + +add_executable(nas_5g_msg_test nas_5g_msg_test.cc) +target_link_libraries(nas_5g_msg_test nas_5g_msg) \ No newline at end of file diff --git a/lib/test/asn1/nas_5g_msg_test.cc b/lib/test/asn1/nas_5g_msg_test.cc new file mode 100644 index 000000000..440602b9f --- /dev/null +++ b/lib/test/asn1/nas_5g_msg_test.cc @@ -0,0 +1,1610 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include +#include + +#include "srsran/asn1/nas_5g_msg.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/nas_pcap.h" +#include "srsran/common/test_common.h" +#include "srsran/srslog/srslog.h" + +using namespace srsran::nas_5g; + +#define HAVE_PCAP 0 + +inline void print_msg(const srsran::unique_byte_buffer_t& msg) +{ + printf("\t"); + for (uint32_t i = 0; i < msg->N_bytes; i++) { + printf("0x%02x ", msg->msg[i]); + if ((i + 1) % 16 == 0) { + printf("\n\t"); + } + } + printf("\n"); +} + +inline void hex_dump(uint8_t* buf, uint32_t buf_length) +{ + printf("\t"); + for (uint32_t i = 0; i < buf_length; i++) { + printf("0x%02x ", buf[i]); + if ((i + 1) % 16 == 0) { + printf("\n\t"); + } + } + printf("\n"); +} + +void copy_msg_to_buffer(srsran::unique_byte_buffer_t& pdu, srsran::const_byte_span msg) +{ + pdu = srsran::make_byte_buffer(); + memcpy(pdu->msg, msg.data(), msg.size()); + pdu->N_bytes = msg.size(); +} + +int registration_request_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + uint8_t reg_request[] = {0x7e, 0x00, 0x41, 0x79, 0x00, 0x0b, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x2e, 0x02, 0xf0, 0xf0, 0x17, 0x07, 0xf0, 0xf0, 0xc0, 0xc0, 0x01, 0x80, 0x30}; + // Non-Access-Stratum 5GS (NAS)PDU + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Registration request (0x41) + // 5GS registration type + // .... 1... = Follow-On Request bit (FOR): Follow-on request pending + // .... .001 = 5GS registration type: initial registration (1) + // NAS key set identifier + // 0... .... = Type of security context flag (TSC): Native security context (for KSIAMF) + // .111 .... = NAS key set identifier: 7 + // 5GS mobile identity + // Length: 11 + // .... 0... = Odd/even indication: Even number of identity digits + // .... .010 = Type of identity: 5G-GUTI (2) + // Mobile Country Code (MCC): Unknown (0) + // Mobile Network Code (MNC): Unknown (000) + // AMF Region ID: 0 + // 0000 0000 00.. .... = AMF Set ID: 0 + // ..00 0000 = AMF Pointer: 0 + // 5G-TMSI: 0 (0x00000000) + // + // UE security capability + // Element ID: 0x2e + // Length: 2 + // 1... .... = 5G-EA0: Supported + // .1.. .... = 128-5G-EA1: Supported + // ..1. .... = 128-5G-EA2: Supported + // ...1 .... = 128-5G-EA3: Supported + // .... 0... = 5G-EA4: Not supported + // .... .0.. = 5G-EA5: Not supported + // .... ..0. = 5G-EA6: Not supported + // .... ...0 = 5G-EA7: Not supported + // 1... .... = 5G-IA0: Supported + // .1.. .... = 128-5G-IA1: Supported + // ..1. .... = 128-5G-IA2: Supported + // ...1 .... = 128-5G-IA3: Supported + // .... 0... = 5G-IA4: Not supported + // .... .0.. = 5G-IA5: Not supported + // .... ..0. = 5G-IA6: Not supported + // .... ...0 = 5G-IA7: Not supported + // UE network capability + // Element ID: 0x17 + // Length: 7 + // 1... .... = EEA0: Supported + // .1.. .... = 128-EEA1: Supported + // ..1. .... = 128-EEA2: Supported + // ...1 .... = 128-EEA3: Supported + // .... 0... = EEA4: Not supported + // .... .0.. = EEA5: Not supported + // .... ..0. = EEA6: Not supported + // .... ...0 = EEA7: Not supported + // 1... .... = EIA0: Supported + // .1.. .... = 128-EIA1: Supported + // ..1. .... = 128-EIA2: Supported + // ...1 .... = 128-EIA3: Supported + // .... 0... = EIA4: Not supported + // .... .0.. = EIA5: Not supported + // .... ..0. = EIA6: Not supported + // .... ...0 = EIA7: Not supported + // 1... .... = UEA0: Supported + // .1.. .... = UEA1: Supported + // ..0. .... = UEA2: Not supported + // ...0 .... = UEA3: Not supported + // .... 0... = UEA4: Not supported + // .... .0.. = UEA5: Not supported + // .... ..0. = UEA6: Not supported + // .... ...0 = UEA7: Not supported + // 1... .... = UCS2 support (UCS2): The UE has no preference between the use of the default alphabet and + // the use of UCS2 .1.. .... = UMTS integrity algorithm UIA1: Supported + // ..0. .... = UMTS integrity algorithm UIA2: Not supported + // ...0 .... = UMTS integrity algorithm UIA3: Not supported + // .... 0... = UMTS integrity algorithm UIA4: Not supported + // .... .0.. = UMTS integrity algorithm UIA5: Not supported + // .... ..0. = UMTS integrity algorithm UIA6: Not supported + // .... ...0 = UMTS integrity algorithm UIA7: Not supported + // 0... .... = ProSe direct discovery: Not supported + // .0.. .... = ProSe: Not supported + // ..0. .... = H.245 After SRVCC Handover: Not supported + // ...0 .... = Access class control for CSFB: Not supported + // .... 0... = LTE Positioning Protocol: Not supported + // .... .0.. = Location services (LCS) notification mechanisms: Not supported + // .... ..0. = SRVCC from E-UTRAN to cdma2000 1xCS: Not supported + // .... ...1 = Notification procedure: Supported + // 1... .... = Extended protocol configuration options: Supported + // .0.. .... = Header compression for control plane CIoT EPS optimization: Not supported + // ..0. .... = EMM-REGISTERED w/o PDN connectivity: Not supported + // ...0 .... = S1-U data transfer: Not supported + // .... 0... = User plane CIoT EPS optimization: Not supported + // .... .0.. = Control plane CIoT EPS optimization: Not supported + // .... ..0. = ProSe UE-to-network relay: Not supported + // .... ...0 = ProSe direct communication: Not supported + // 0... .... = Signalling for a maximum number of 15 EPS bearer contexts: Not supported + // .0.. .... = Service gap control: Not supported + // ..1. .... = N1 mode: Supported + // ...1 .... = Dual connectivity with NR: Supported + // .... 0... = Control plane data backoff: Not supported + // .... .0.. = Restriction on use of enhanced coverage: Not supported + // .... ..0. = V2X communication over PC5: Not supported + // .... ...0 = Multiple DRB: Not supported + + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, reg_request); +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + nas_5gs_msg nas_msg; + + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::registration_request); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::registration_request); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + registration_request_t& reg_request_msg = nas_msg.registration_request(); + TESTASSERT(reg_request_msg.registration_type_5gs.registration_type == + registration_type_5gs_t::registration_type_type_::options::initial_registration); + TESTASSERT(reg_request_msg.registration_type_5gs.follow_on_request_bit == + registration_type_5gs_t::follow_on_request_bit_type_::options::follow_on_request_pending); + TESTASSERT(reg_request_msg.ng_ksi.security_context_flag == + key_set_identifier_t::security_context_flag_type_::options::native_security_context); + TESTASSERT(reg_request_msg.ng_ksi.nas_key_set_identifier == + key_set_identifier_t::nas_key_set_identifier_type_::options::no_key_is_available_or_reserved); + TESTASSERT(reg_request_msg.mobile_identity_5gs.length == 11); + TESTASSERT(reg_request_msg.mobile_identity_5gs.type() == mobile_identity_5gs_t::identity_types_::options::guti_5g); + mobile_identity_5gs_t::guti_5g_s guti_5g_ = reg_request_msg.mobile_identity_5gs.guti_5g(); + TESTASSERT(guti_5g_.amf_pointer == 0x0); + TESTASSERT(guti_5g_.amf_region_id == 0x0); + TESTASSERT(guti_5g_.amf_set_id == 0); + TESTASSERT(guti_5g_.mcc[0] == 0); + TESTASSERT(guti_5g_.mcc[1] == 0); + TESTASSERT(guti_5g_.mcc[2] == 0); + TESTASSERT(guti_5g_.mnc[0] == 0); + TESTASSERT(guti_5g_.mnc[1] == 0); + TESTASSERT(guti_5g_.mnc[2] == 0); + TESTASSERT(reg_request_msg.ue_security_capability_present == true); + TESTASSERT(reg_request_msg.ue_security_capability.ea0_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ea1_128_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ea2_128_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ea3_128_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ea3_128_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ea4_5g_supported == false); + TESTASSERT(reg_request_msg.ue_security_capability.ea5_5g_supported == false); + TESTASSERT(reg_request_msg.ue_security_capability.ea6_5g_supported == false); + TESTASSERT(reg_request_msg.ue_security_capability.ea7_5g_supported == false); + TESTASSERT(reg_request_msg.ue_security_capability.ia0_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ia1_128_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ia2_128_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ia3_128_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ia3_128_5g_supported == true); + TESTASSERT(reg_request_msg.ue_security_capability.ia4_5g_supported == false); + TESTASSERT(reg_request_msg.ue_security_capability.ia5_5g_supported == false); + TESTASSERT(reg_request_msg.ue_security_capability.ia6_5g_supported == false); + TESTASSERT(reg_request_msg.ue_security_capability.ia7_5g_supported == false); + TESTASSERT(reg_request_msg.ue_security_capability.eps_caps_present == false); + + TESTASSERT(reg_request_msg.s1_ue_network_capability_present == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.length == 7); + + TESTASSERT(reg_request_msg.s1_ue_network_capability.eea0_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eea1_128_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eea2_128_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eea3_128_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eea4_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eea5_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eea6_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eea7_supported == false); + + TESTASSERT(reg_request_msg.s1_ue_network_capability.eia0_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eia1_128_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eia2_128_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eia3_128_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eia4_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eia5_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eia6_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.eia7_supported == false); + + TESTASSERT(reg_request_msg.s1_ue_network_capability.uea0_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uea1_128_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uea2_128_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uea3_128_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uea4_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uea5_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uea6_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uea7_supported == false); + + TESTASSERT(reg_request_msg.s1_ue_network_capability.ucs2_support == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uia1_128_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uia2_128_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uia3_128_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uia4_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uia5_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uia6_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.uia7_supported == false); + + TESTASSERT(reg_request_msg.s1_ue_network_capability.pro_se_dd_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.pro_se_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.h245_ash_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.acc_csfb_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.llp_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.lcs_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.srvcc_capability_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.nf_capability_supported == true); + + TESTASSERT(reg_request_msg.s1_ue_network_capability.e_pco_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.hc_cp_c_io_t_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.e_rw_o_pdn_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.s1_u_data_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.up_c_io_t_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.cp_c_io_t_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.pro_se_relay_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.pro_se_dc_supported == false); + + TESTASSERT(reg_request_msg.s1_ue_network_capability.max_15_eps_bearer_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.sgc_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.n1mode_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.dcnr_supported == true); + TESTASSERT(reg_request_msg.s1_ue_network_capability.cp_backoff_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.restrict_ec_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.v2_x_pc5_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.multiple_drb_supported == false); + + TESTASSERT(reg_request_msg.s1_ue_network_capability.nr_pc5_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.up_mt_edt_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.cp_mt_edt_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.wus_supported == false); + TESTASSERT(reg_request_msg.s1_ue_network_capability.racs_supported == false); + + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); + + printf("buf_cmp->N_bytes %d buf->N_bytes %d\n", buf_cmp->N_bytes, buf->N_bytes); + printf("\n"); + print_msg(buf); + printf("\n"); + print_msg(buf_cmp); + printf("\n"); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + return SRSRAN_SUCCESS; +} + +int registration_request_unpacking_packing_test_2(srsran::nas_pcap* pcap) +{ + // Non-Access-Stratum 5GS (NAS)PDU + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Registration request (0x41) + // 5GS registration type + // .... 1... = Follow-On Request bit (FOR): Follow-on request pending + // .... .001 = 5GS registration type: initial registration (1) + // NAS key set identifier + // 0... .... = Type of security context flag (TSC): Native security context (for KSIAMF) + // .111 .... = NAS key set identifier: 7 + // 5GS mobile identity + // Length: 54 + // 0... .... = Spare: 0 + // .000 .... = SUPI format: IMSI (0) + // .... 0... = Spare: 0 + // .... .001 = Type of identity: SUCI (1) + // Mobile Country Code (MCC): Unknown (1) + // Mobile Network Code (MNC): Unknown (01) + // Routing indicator: 17 + // .... 0010 = Protection scheme Id: ECIES scheme profile B (2) + // Home network public key identifier: 27 + // Scheme output: 03 99 7e e4 01 2d e3 6c 86 e2 29 97 c8 99 70 4b 0f 61 3a bd 6c 3b 1c 9c … + // ECC ephemeral public key: 03 99 7e e4 01 2d e3 6c 86 e2 29 97 c8 99 70 4b 0f 61 3a bd 6c 3b 1c 9c … + // Ciphertext: cb bd 5d 27 34 + // MAC tag: 0x1e8b9e3328184bec + // UE security capability + // Element ID: 0x2e + // Length: 2 + // 1... .... = 5G-EA0: Supported + // .0.. .... = 128-5G-EA1: Not supported + // ..0. .... = 128-5G-EA2: Not supported + // ...0 .... = 128-5G-EA3: Not supported + // .... 0... = 5G-EA4: Not supported + // .... .0.. = 5G-EA5: Not supported + // .... ..0. = 5G-EA6: Not supported + // .... ...0 = 5G-EA7: Not supported + // 0... .... = 5G-IA0: Not supported + // .0.. .... = 128-5G-IA1: Not supported + // ..1. .... = 128-5G-IA2: Supported + // ...0 .... = 128-5G-IA3: Not supported + // .... 0... = 5G-IA4: Not supported + // .... .0.. = 5G-IA5: Not supported + // .... ..0. = 5G-IA6: Not supported + // .... ...0 = 5G-IA7: Not supported + + uint8_t reg_request[] = {0x7e, 0x00, 0x41, 0x79, 0x00, 0x36, 0x01, 0x00, 0xf1, 0x10, 0x71, 0xff, 0x02, + 0x1b, 0x03, 0x99, 0x7e, 0xe4, 0x01, 0x2d, 0xe3, 0x6c, 0x86, 0xe2, 0x29, 0x97, + 0xc8, 0x99, 0x70, 0x4b, 0x0f, 0x61, 0x3a, 0xbd, 0x6c, 0x3b, 0x1c, 0x9c, 0xa7, + 0x8a, 0x4b, 0x14, 0x7e, 0x22, 0xaf, 0xb0, 0x64, 0xcb, 0xbd, 0x5d, 0x27, 0x34, + 0x1e, 0x8b, 0x9e, 0x33, 0x28, 0x18, 0x4b, 0xec, 0x2e, 0x02, 0x80, 0x20}; + + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, reg_request); +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + nas_5gs_msg nas_msg; + + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::registration_request); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::registration_request); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + registration_request_t& reg_request_msg = nas_msg.registration_request(); + TESTASSERT(reg_request_msg.registration_type_5gs.registration_type == + registration_type_5gs_t::registration_type_type_::options::initial_registration); + TESTASSERT(reg_request_msg.registration_type_5gs.follow_on_request_bit == + registration_type_5gs_t::follow_on_request_bit_type_::options::follow_on_request_pending); + TESTASSERT(reg_request_msg.ng_ksi.security_context_flag == + key_set_identifier_t::security_context_flag_type_::options::native_security_context); + TESTASSERT(reg_request_msg.ng_ksi.nas_key_set_identifier == + key_set_identifier_t::nas_key_set_identifier_type_::options::no_key_is_available_or_reserved); + TESTASSERT(reg_request_msg.mobile_identity_5gs.length == 54); + TESTASSERT(reg_request_msg.mobile_identity_5gs.type() == mobile_identity_5gs_t::identity_types_::options::suci); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().supi_format.value == + mobile_identity_5gs_t::suci_s::supi_format_type_::options::imsi); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().mcc[0] == 0); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().mcc[1] == 0); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().mcc[2] == 1); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().mnc[0] == 0); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().mnc[1] == 1); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().mnc[2] == 0xf); + + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().routing_indicator[0] == 1); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().routing_indicator[1] == 7); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().routing_indicator[2] == 0xf); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().routing_indicator[3] == 0xf); + + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().protection_scheme_id == + mobile_identity_5gs_t::suci_s::protection_scheme_id_type_::options::ecies_scheme_profile_b); + TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().home_network_public_key_identifier == 27); + + hex_dump(reg_request_msg.mobile_identity_5gs.suci().scheme_output.data(), + reg_request_msg.mobile_identity_5gs.suci().scheme_output.size()); + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); + + printf("buf_cmp->N_bytes %d buf->N_bytes %d\n", buf_cmp->N_bytes, buf->N_bytes); + printf("\n"); + print_msg(buf); + printf("\n"); + print_msg(buf_cmp); + printf("\n"); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + return SRSRAN_SUCCESS; +} + +int deregistration_request_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + // Non-Access-Stratum 5GS (NAS)PDU + // Security protected NAS 5GS message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0001 = Security header type: Integrity protected (1) + // Message authentication code: 0x6f0325f5 + // Sequence number: 2 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Deregistration request (UE originating) (0x45) + // De-registration type + // .... 1... = Switch off: Switch off + // .... .0.. = Re-registration required: re-registration not required + // .... ..01 = Access type: 3GPP access (1) + // NAS key set identifier + // 0... .... = Type of security context flag (TSC): Native security context (for KSIAMF) + // .000 .... = NAS key set identifier: 0 + // 5GS mobile identity + // Length: 11 + // .... 0... = Odd/even indication: Even number of identity digits + // .... .010 = Type of identity: 5G-GUTI (2) + // Mobile Country Code (MCC): Unknown (1) + // Mobile Network Code (MNC): Unknown (01) + // AMF Region ID: 202 + // 1111 1110 00.. .... = AMF Set ID: 1016 + // ..00 0000 = AMF Pointer: 0 + // 5G-TMSI: 1 (0x00000001) + // + uint8_t dereg_request[] = {0x7e, 0x01, 0x6f, 0x03, 0x25, 0xf5, 0x02, 0x7e, 0x00, 0x45, 0x09, 0x00, + 0x0b, 0x02, 0x00, 0xf1, 0x10, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x01}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, dereg_request); +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + + nas_5gs_msg nas_msg; + + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::integrity_protected); + TESTASSERT(nas_msg.hdr.message_authentication_code == 0x6f0325f5); + TESTASSERT(nas_msg.hdr.sequence_number == 2); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::deregistration_request_ue_originating); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + deregistration_request_ue_originating_t& dereg_request_msg = nas_msg.deregistration_request_ue_originating(); + TESTASSERT(dereg_request_msg.de_registration_type.switch_off == + de_registration_type_t::switch_off_type_::options::switch_off); + TESTASSERT(dereg_request_msg.de_registration_type.re_registration_required == + de_registration_type_t::re_registration_required_type_::options::re_registration_not_required); + TESTASSERT(dereg_request_msg.de_registration_type.access_type == + de_registration_type_t::access_type_type_::options::access_3_gpp); + TESTASSERT(dereg_request_msg.ng_ksi.security_context_flag == + key_set_identifier_t::security_context_flag_type_::options::native_security_context); + TESTASSERT(dereg_request_msg.ng_ksi.nas_key_set_identifier == 0); + TESTASSERT(dereg_request_msg.mobile_identity_5gs.length == 11); + TESTASSERT(dereg_request_msg.mobile_identity_5gs.type() == mobile_identity_5gs_t::identity_types_::options::guti_5g); + mobile_identity_5gs_t::guti_5g_s guti_5g_ = dereg_request_msg.mobile_identity_5gs.guti_5g(); + TESTASSERT(guti_5g_.amf_pointer == 0x0); + TESTASSERT(guti_5g_.amf_region_id == 202); + TESTASSERT(guti_5g_.amf_set_id == 1016); + TESTASSERT(guti_5g_.mcc[0] == 0); + TESTASSERT(guti_5g_.mcc[1] == 0); + TESTASSERT(guti_5g_.mcc[2] == 1); + TESTASSERT(guti_5g_.mnc[0] == 0); + TESTASSERT(guti_5g_.mnc[1] == 1); + TESTASSERT(guti_5g_.mnc[2] == 0xf); + TESTASSERT(guti_5g_.tmsi_5g == 0x00000001); + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + return SRSRAN_SUCCESS; +} + +int authentication_request_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + // Non-Access-Stratum 5GS (NAS)PDU + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Authentication request (0x56) + // 0000 .... = Spare Half Octet: 0 + // NAS key set identifier - ngKSI + // .... 0... = Type of security context flag (TSC): Native security context (for KSIAMF) + // .... .000 = NAS key set identifier: 0 + // ABBA + // Length: 2 + // ABBA Contents: 0x0000 + // Authentication Parameter RAND - 5G authentication challenge + // Element ID: 0x21 + // RAND value: 16 46 24 32 75 b8 b9 c7 18 b6 05 c6 ff 03 96 71 + // Authentication Parameter AUTN (UMTS and EPS authentication challenge) - 5G authentication challenge + // Element ID: 0x20 + // Length: 16 + // AUTN value: a3 09 26 e4 2e ea 80 00 f6 87 d5 ba a2 d9 56 ed + // SQN xor AK: a3 09 26 e4 2e ea + // AMF: 80 00 + // MAC: f6 87 d5 ba a2 d9 56 ed + + uint8_t auth_request[] = {0x7e, 0x00, 0x56, 0x00, 0x02, 0x00, 0x00, 0x21, 0x16, 0x46, 0x24, 0x32, 0x75, 0xb8, + 0xb9, 0xc7, 0x18, 0xb6, 0x05, 0xc6, 0xff, 0x03, 0x96, 0x71, 0x20, 0x10, 0xa3, 0x09, + 0x26, 0xe4, 0x2e, 0xea, 0x80, 0x00, 0xf6, 0x87, 0xd5, 0xba, 0xa2, 0xd9, 0x56, 0xed}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, auth_request); + +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + + nas_5gs_msg nas_msg; + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::authentication_request); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + authentication_request_t& auth_request_msg = nas_msg.authentication_request(); + TESTASSERT(auth_request_msg.ng_ksi.security_context_flag == + key_set_identifier_t::security_context_flag_type_::options::native_security_context); + TESTASSERT(auth_request_msg.ng_ksi.nas_key_set_identifier == 0); + TESTASSERT(auth_request_msg.abba.length == 2); + TESTASSERT(auth_request_msg.abba.abba_contents[0] == 0x00); + TESTASSERT(auth_request_msg.abba.abba_contents[1] == 0x00); + TESTASSERT(auth_request_msg.authentication_parameter_rand_present == true); + TESTASSERT(auth_request_msg.authentication_parameter_rand.rand[0] == 0x16); + TESTASSERT(auth_request_msg.authentication_parameter_rand.rand[15] == 0x71); + TESTASSERT(auth_request_msg.authentication_parameter_autn_present == true); + TESTASSERT(auth_request_msg.authentication_parameter_autn.length == 16); + TESTASSERT(auth_request_msg.authentication_parameter_autn.autn[0] == 0xa3); + TESTASSERT(auth_request_msg.authentication_parameter_autn.autn[15] == 0xed); + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + return SRSRAN_SUCCESS; +} + +int authentication_resp_request_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + // Non-Access-Stratum 5GS (NAS)PDU + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Authentication response (0x57) + // Authentication response parameter + // Element ID: 0x2d + // Length: 16 + // RES: a1 1f 51 a4 1d a9 b5 29 b3 3b 04 3a e1 e2 02 08 + + uint8_t auth_resp_buf[] = {0x7e, 0x00, 0x57, 0x2d, 0x10, 0xa1, 0x1f, 0x51, 0xa4, 0x1d, 0xa9, + 0xb5, 0x29, 0xb3, 0x3b, 0x04, 0x3a, 0xe1, 0xe2, 0x02, 0x08}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, auth_resp_buf); + +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + nas_5gs_msg nas_msg; + + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::authentication_response); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::authentication_response); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + authentication_response_t& auth_resp = nas_msg.authentication_response(); + + TESTASSERT(auth_resp.authentication_response_parameter_present == true); + TESTASSERT(auth_resp.authentication_response_parameter.length == 16); + TESTASSERT(auth_resp.authentication_response_parameter.res.size() == 16); + TESTASSERT(auth_resp.authentication_response_parameter.res[0] == 0xa1); + TESTASSERT(auth_resp.authentication_response_parameter.res[15] == 0x08); + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + return SRSRAN_SUCCESS; +} + +int security_command_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + // Non-Access-Stratum 5GS (NAS)PDU + // Security protected NAS 5GS message + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Security mode command (0x5d) + // NAS security algorithms + // 0000 .... = Type of ciphering algorithm: 5G-EA0 (null ciphering algorithm) (0) + // .... 0010 = Type of integrity protection algorithm: 128-5G-IA2 (2) + // 0000 .... = Spare Half Octet: 0 + // NAS key set identifier - ngKSI + // .... 0... = Type of security context flag (TSC): Native security context (for KSIAMF) + // .... .000 = NAS key set identifier: 0 + // UE security capability - Replayed UE security capabilities + // Length: 4 + // 1... .... = 5G-EA0: Supported + // .1.. .... = 128-5G-EA1: Supported + // ..1. .... = 128-5G-EA2: Supported + // ...1 .... = 128-5G-EA3: Supported + // .... 0... = 5G-EA4: Not supported + // .... .0.. = 5G-EA5: Not supported + // .... ..0. = 5G-EA6: Not supported + // .... ...0 = 5G-EA7: Not supported + // 0... .... = 5G-IA0: Not supported + // .1.. .... = 128-5G-IA1: Supported + // ..1. .... = 128-5G-IA2: Supported + // ...1 .... = 128-5G-IA3: Supported + // .... 0... = 5G-IA4: Not supported + // .... .0.. = 5G-IA5: Not supported + // .... ..0. = 5G-IA6: Not supported + // .... ...0 = 5G-IA7: Not supported + // 1... .... = EEA0: Supported + // .1.. .... = 128-EEA1: Supported + // ..1. .... = 128-EEA2: Supported + // ...1 .... = 128-EEA3: Supported + // .... 0... = EEA4: Not supported + // .... .0.. = EEA5: Not supported + // .... ..0. = EEA6: Not supported + // .... ...0 = EEA7: Not supported + // 0... .... = EIA0: Not supported + // .1.. .... = 128-EIA1: Supported + // ..1. .... = 128-EIA2: Supported + // ...1 .... = 128-EIA3: Supported + // .... 0... = EIA4: Not supported + // .... .0.. = EIA5: Not supported + // .... ..0. = EIA6: Not supported + // .... ...0 = EIA7: Not supported + // IMEISV request + // 1110 .... = Element ID: 0xe- + // .... 0... = Spare bit(s): 0x00 + // .... .001 = IMEISV request: IMEISV requested (1) + // Additional 5G security information + // Element ID: 0x36 + // Length: 1 + // .... 0... = Spare: 0 + // .... .0.. = Spare: 0 + // .... ..0. = Retransmission of initial NAS message request(RINMR): Not Requested + // .... ...0 = Horizontal derivation parameter (HDP): Not required + + uint8_t sec_command[] = {0x7e, 0x03, 0x53, 0x3f, 0xcb, 0x29, 0x00, 0x7e, 0x00, 0x5d, 0x02, + 0x00, 0x04, 0xf0, 0x70, 0xf0, 0x70, 0xe1, 0x36, 0x01, 0x00}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, sec_command); + +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + nas_5gs_msg nas_msg; + + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::integrity_protected_with_new_5G_nas_context); + TESTASSERT(nas_msg.hdr.message_authentication_code == 0x533fcb29); + TESTASSERT(nas_msg.hdr.sequence_number == 0); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.inner_extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.inner_security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::security_mode_command); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + security_mode_command_t& sec_command_msg = nas_msg.security_mode_command(); + TESTASSERT(sec_command_msg.ng_ksi.security_context_flag == + key_set_identifier_t::security_context_flag_type_::options::native_security_context); + TESTASSERT(sec_command_msg.ng_ksi.nas_key_set_identifier == 0); + + TESTASSERT(sec_command_msg.selected_nas_security_algorithms.ciphering_algorithm == + security_algorithms_t::ciphering_algorithm_type_::options::ea0_5g); + TESTASSERT(sec_command_msg.selected_nas_security_algorithms.integrity_protection_algorithm == + security_algorithms_t::integrity_protection_algorithm_type_::options::ia2_128_5g); + + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ea0_5g_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ea1_128_5g_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ea2_128_5g_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ea3_128_5g_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ea4_5g_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ea5_5g_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ea6_5g_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ea7_5g_supported == false); + + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ia0_5g_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ia1_128_5g_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ia2_128_5g_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ia3_128_5g_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ia4_5g_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ia5_5g_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ia6_5g_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.ia7_5g_supported == false); + + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eps_caps_present == true); + + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eea0_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eea1_128_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eea2_128_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eea3_128_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eea4_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eea5_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eea6_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eea7_supported == false); + + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eia0_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eia1_128_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eia2_128_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eia3_128_supported == true); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eia4_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eia5_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eia6_supported == false); + TESTASSERT(sec_command_msg.replayed_ue_security_capabilities.eia7_supported == false); + + TESTASSERT(sec_command_msg.imeisv_request_present == true); + TESTASSERT(sec_command_msg.imeisv_request.imeisv_request == true); + + TESTASSERT(sec_command_msg.additional_5g_security_information_present == true); + TESTASSERT(sec_command_msg.additional_5g_security_information.length == 1); + TESTASSERT(sec_command_msg.additional_5g_security_information.rinmr == false); + TESTASSERT(sec_command_msg.additional_5g_security_information.hdp == false); + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); + + printf("buf_cmp->N_bytes %d buf->N_bytes %d\n", buf_cmp->N_bytes, buf->N_bytes); + printf("\n"); + print_msg(buf); + printf("\n"); + print_msg(buf_cmp); + printf("\n"); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + return SRSRAN_SUCCESS; +} + +int security_complete_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + // Non-Access-Stratum 5GS (NAS)PDU + // Security protected NAS 5GS message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0100 = Security header type: Integrity protected and ciphered with new 5GS security context (4) + // Message authentication code: 0x4088e4e4 + // Sequence number: 0 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Security mode complete (0x5e) + // 5GS mobile identity + // Element ID: 0x77 + // Length: 9 + // .... 0... = Odd/even indication: Even number of identity digits + // .... .101 = Type of identity: IMEISV (5) + // IMEISV: 8651160458202125 + // NAS message container + // Element ID: 0x71 + // Length: 87 + // Non-Access-Stratum 5GS (NAS)PDU + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Registration request (0x41) + // 5GS registration type + // .... 1... = Follow-On Request bit (FOR): Follow-on request pending + // .... .001 = 5GS registration type: initial registration (1) + // NAS key set identifier + // 0... .... = Type of security context flag (TSC): Native security context (for KSIAMF) + // .111 .... = NAS key set identifier: 7 + // 5GS mobile identity + // Length: 54 + // 0... .... = Spare: 0 + // .000 .... = SUPI format: IMSI (0) + // .... 0... = Spare: 0 + // .... .001 = Type of identity: SUCI (1) + // Mobile Country Code (MCC): Unknown (1) + // Mobile Network Code (MNC): Unknown (01) + // Routing indicator: 17 + // .... 0010 = Protection scheme Id: ECIES scheme profile B (2) + // Home network public key identifier: 27 + // Scheme output: 03 e3 42 42 99 67 4b 24 bc 8c 8a 54 e2 f9 06 5b f6 92 09 63 b0 9e 37 26 … + // ECC ephemeral public key: 03 e3 42 42 99 67 4b 24 bc 8c 8a 54 e2 f9 06 5b f6 92 09 63 b0 + // 9e 37 26 … Ciphertext: 00 f9 6d 57 82 MAC tag: 0xbf257ecba4d6ce2d + // 5GMM capability + // Element ID: 0x10 + // Length: 1 + // 0... .... = Spare: 0 + // .0.. .... = Spare: 0 + // ..0. .... = Spare: 0 + // ...0 .... = Spare: 0 + // .... 0... = Spare: 0 + // .... .0.. = LTE Positioning Protocol (LPP) capability: Not Requested + // .... ..1. = HO attach: Supported + // .... ...1 = S1 mode: Requested + // UE security capability + // Element ID: 0x2e + // Length: 4 + // 1... .... = 5G-EA0: Supported + // .1.. .... = 128-5G-EA1: Supported + // ..1. .... = 128-5G-EA2: Supported + // ...1 .... = 128-5G-EA3: Supported + // .... 0... = 5G-EA4: Not supported + // .... .0.. = 5G-EA5: Not supported + // .... ..0. = 5G-EA6: Not supported + // .... ...0 = 5G-EA7: Not supported + // 0... .... = 5G-IA0: Not supported + // .1.. .... = 128-5G-IA1: Supported + // ..1. .... = 128-5G-IA2: Supported + // ...1 .... = 128-5G-IA3: Supported + // .... 0... = 5G-IA4: Not supported + // .... .0.. = 5G-IA5: Not supported + // .... ..0. = 5G-IA6: Not supported + // .... ...0 = 5G-IA7: Not supported + // 1... .... = EEA0: Supported + // .1.. .... = 128-EEA1: Supported + // ..1. .... = 128-EEA2: Supported + // ...1 .... = 128-EEA3: Supported + // .... 0... = EEA4: Not supported + // .... .0.. = EEA5: Not supported + // .... ..0. = EEA6: Not supported + // .... ...0 = EEA7: Not supported + // 0... .... = EIA0: Not supported + // .1.. .... = 128-EIA1: Supported + // ..1. .... = 128-EIA2: Supported + // ...1 .... = 128-EIA3: Supported + // .... 0... = EIA4: Not supported + // .... .0.. = EIA5: Not supported + // .... ..0. = EIA6: Not supported + // .... ...0 = EIA7: Not supported + // UE network capability + // Element ID: 0x17 + // Length: 7 + // 1... .... = EEA0: Supported + // .1.. .... = 128-EEA1: Supported + // ..1. .... = 128-EEA2: Supported + // ...1 .... = 128-EEA3: Supported + // .... 0... = EEA4: Not supported + // .... .0.. = EEA5: Not supported + // .... ..0. = EEA6: Not supported + // .... ...0 = EEA7: Not supported + // 0... .... = EIA0: Not supported + // .1.. .... = 128-EIA1: Supported + // ..1. .... = 128-EIA2: Supported + // ...1 .... = 128-EIA3: Supported + // .... 0... = EIA4: Not supported + // .... .0.. = EIA5: Not supported + // .... ..0. = EIA6: Not supported + // .... ...0 = EIA7: Not supported + // 1... .... = UEA0: Supported + // .1.. .... = UEA1: Supported + // ..0. .... = UEA2: Not supported + // ...0 .... = UEA3: Not supported + // .... 0... = UEA4: Not supported + // .... .0.. = UEA5: Not supported + // .... ..0. = UEA6: Not supported + // .... ...0 = UEA7: Not supported + // 0... .... = UCS2 support (UCS2): The UE has a preference for the default alphabet + // .1.. .... = UMTS integrity algorithm UIA1: Supported + // ..0. .... = UMTS integrity algorithm UIA2: Not supported + // ...0 .... = UMTS integrity algorithm UIA3: Not supported + // .... 0... = UMTS integrity algorithm UIA4: Not supported + // .... .0.. = UMTS integrity algorithm UIA5: Not supported + // .... ..0. = UMTS integrity algorithm UIA6: Not supported + // .... ...0 = UMTS integrity algorithm UIA7: Not supported + // 0... .... = ProSe direct discovery: Not supported + // .0.. .... = ProSe: Not supported + // ..0. .... = H.245 After SRVCC Handover: Not supported + // ...1 .... = Access class control for CSFB: Supported + // .... 0... = LTE Positioning Protocol: Not supported + // .... .0.. = Location services (LCS) notification mechanisms: Not supported + // .... ..0. = SRVCC from E-UTRAN to cdma2000 1xCS: Not supported + // .... ...1 = Notification procedure: Supported + // 1... .... = Extended protocol configuration options: Supported + // .0.. .... = Header compression for control plane CIoT EPS optimization: Not supported + // ..0. .... = EMM-REGISTERED w/o PDN connectivity: Not supported + // ...0 .... = S1-U data transfer: Not supported + // .... 0... = User plane CIoT EPS optimization: Not supported + // .... .0.. = Control plane CIoT EPS optimization: Not supported + // .... ..0. = ProSe UE-to-network relay: Not supported + // .... ...0 = ProSe direct communication: Not supported + // 1... .... = Signalling for a maximum number of 15 EPS bearer contexts: Supported + // .0.. .... = Service gap control: Not supported + // ..1. .... = N1 mode: Supported + // ...1 .... = Dual connectivity with NR: Supported + // .... 0... = Control plane data backoff: Not supported + // .... .0.. = Restriction on use of enhanced coverage: Not supported + // .... ..0. = V2X communication over PC5: Not supported + // .... ...0 = Multiple DRB: Not supported + // UE's usage setting + // Element ID: 0x18 + // Length: 1 + // .... 0... = Spare: 0 + // .... .0.. = Spare: 0 + // .... ..0. = Spare: 0 + // .... ...1 = UE's usage setting: Data centric + // LADN indication + // Element ID: 0x74 + // Length: 0 + // 5GS update type + // Element ID: 0x53 + // Length: 1 + // .... 0... = Spare: 0 + // .... .0.. = Spare: 0 + // .... ..0. = NG-RAN Radio Capability Update (NG-RAN-RCU): Not Needed + // .... ...1 = SMS requested: SMS over NAS supported + + uint8_t sec_complete[] = { + 0x7e, 0x04, 0x40, 0x88, 0xe4, 0xe4, 0x00, 0x7e, 0x00, 0x5e, 0x77, 0x00, 0x09, 0x85, 0x56, 0x11, 0x06, 0x54, 0x28, + 0x20, 0x21, 0xf5, 0x71, 0x00, 0x57, 0x7e, 0x00, 0x41, 0x79, 0x00, 0x36, 0x01, 0x00, 0xf1, 0x10, 0x71, 0xff, 0x02, + 0x1b, 0x03, 0xe3, 0x42, 0x42, 0x99, 0x67, 0x4b, 0x24, 0xbc, 0x8c, 0x8a, 0x54, 0xe2, 0xf9, 0x06, 0x5b, 0xf6, 0x92, + 0x09, 0x63, 0xb0, 0x9e, 0x37, 0x26, 0x13, 0x48, 0xf5, 0xfe, 0xdc, 0xa2, 0x42, 0x07, 0x91, 0x00, 0xf9, 0x6d, 0x57, + 0x82, 0xbf, 0x25, 0x7e, 0xcb, 0xa4, 0xd6, 0xce, 0x2d, 0x10, 0x01, 0x03, 0x2e, 0x04, 0xf0, 0x70, 0xf0, 0x70, 0x17, + 0x07, 0xf0, 0x70, 0xc0, 0x40, 0x11, 0x80, 0xb0, 0x18, 0x01, 0x01, 0x74, 0x00, 0x00, 0x53, 0x01, 0x01}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, sec_complete); + +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + nas_5gs_msg nas_msg; + + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::integrity_protected_and_ciphered_with_new_5G_nas_context); + TESTASSERT(nas_msg.hdr.message_authentication_code == 0x4088e4e4); + TESTASSERT(nas_msg.hdr.sequence_number == 0); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.inner_extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.inner_security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::security_mode_complete); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + security_mode_complete_t& sec_complete_msg = nas_msg.security_mode_complete(); + + TESTASSERT(sec_complete_msg.imeisv_present == true); + TESTASSERT(sec_complete_msg.imeisv.type() == mobile_identity_5gs_t::identity_types_::options::imeisv); + mobile_identity_5gs_t::imeisv_s imeisv = sec_complete_msg.imeisv.imeisv(); + + TESTASSERT(imeisv.odd_even_indicator == false); + TESTASSERT(imeisv.imeisv[0] == 8); + TESTASSERT(imeisv.imeisv[1] == 6); + TESTASSERT(imeisv.imeisv[2] == 5); + TESTASSERT(imeisv.imeisv[3] == 1); + TESTASSERT(imeisv.imeisv[4] == 1); + TESTASSERT(imeisv.imeisv[5] == 6); + TESTASSERT(imeisv.imeisv[6] == 0); + TESTASSERT(imeisv.imeisv[7] == 4); + TESTASSERT(imeisv.imeisv[8] == 5); + TESTASSERT(imeisv.imeisv[9] == 8); + TESTASSERT(imeisv.imeisv[10] == 2); + TESTASSERT(imeisv.imeisv[11] == 0); + TESTASSERT(imeisv.imeisv[12] == 2); + TESTASSERT(imeisv.imeisv[13] == 1); + TESTASSERT(imeisv.imeisv[14] == 2); + TESTASSERT(imeisv.imeisv[15] == 5); + + TESTASSERT(sec_complete_msg.nas_message_container_present == true); + TESTASSERT(sec_complete_msg.nas_message_container.length == 87); + TESTASSERT(sec_complete_msg.nas_message_container.nas_message_container.size() == 87); + nas_5gs_msg inner_message; + TESTASSERT(inner_message.unpack(sec_complete_msg.nas_message_container.nas_message_container) == SRSRAN_SUCCESS); + // TODO check content of inner message + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + return SRSRAN_SUCCESS; +} + +int registration_accept_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + // Non-Access-Stratum 5GS (NAS)PDU + // Security protected NAS 5GS message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0010 = Security header type: Integrity protected and ciphered (2) + // Message authentication code: 0xd2b078f7 + // Sequence number: 1 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Registration accept (0x42) + // 5GS registration result + // Length: 1 + // ...0 .... = NSSAA Performed: False + // .... 0... = SMS over NAS: Not Allowed + // .... .001 = 5GS registration result: 3GPP access (1) + // 5GS mobile identity - 5G-GUTI + // Element ID: 0x77 + // Length: 11 + // .... 0... = Odd/even indication: Even number of identity digits + // .... .010 = Type of identity: 5G-GUTI (2) + // Mobile Country Code (MCC): Unknown (1) + // Mobile Network Code (MNC): Unknown (01) + // AMF Region ID: 202 + // 1111 1110 00.. .... = AMF Set ID: 1016 + // ..00 0000 = AMF Pointer: 0 + // 5G-TMSI: 3 (0x00000003) + // + // 5GS tracking area identity list + // Element ID: 0x54 + // Length: 7 + // Partial tracking area list 1 + // .00. .... = Type of list: list of TACs belonging to one PLMN, with non-consecutive TAC values (0) + // ...0 0000 = Number of elements: 1 element (0) + // Mobile Country Code (MCC): Unknown (1) + // Mobile Network Code (MNC): Unknown (01) + // TAC: 1 + // NSSAI - Allowed NSSAI + // Element ID: 0x15 + // Length: 10 + // S-NSSAI 1 + // Length: 4 + // Slice/service type (SST): 1 + // Slice differentiator (SD): 66051 + // S-NSSAI 2 + // Length: 4 + // Slice/service type (SST): 1 + // Slice differentiator (SD): 1122867 + // GPRS Timer 3 - T3512 value + // Element ID: 0x5e + // Length: 1 + // GPRS Timer: 60 min + // 000. .... = Unit: value is incremented in multiples of 10 minutes (0) + // ...0 0110 = Timer value: 6 + // GPRS Timer 2 - T3502 value + // Element ID: 0x16 + // Length: 1 + // GPRS Timer: 12 min + // 001. .... = Unit: value is incremented in multiples of 1 minute (1) + // ...0 1100 = Timer value: 12 + + uint8_t reg_accept[] = {0x7e, 0x02, 0xd2, 0xb0, 0x78, 0xf7, 0x01, 0x7e, 0x00, 0x42, 0x01, 0x01, 0x77, 0x00, + 0x0b, 0xf2, 0x00, 0xf1, 0x10, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0x54, 0x07, + 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x01, 0x15, 0x0a, 0x04, 0x01, 0x01, 0x02, 0x03, + 0x04, 0x01, 0x11, 0x22, 0x33, 0x5e, 0x01, 0x06, 0x16, 0x01, 0x2c}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, reg_accept); + +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + nas_5gs_msg nas_msg; + + // Unpacking + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::integrity_protected_and_ciphered); + TESTASSERT(nas_msg.hdr.message_authentication_code == 0xd2b078f7); + TESTASSERT(nas_msg.hdr.sequence_number == 1); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.inner_extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.inner_security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::registration_accept); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + return SRSRAN_SUCCESS; +} + +int registration_complete_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + // Non-Access-Stratum 5GS (NAS)PDU + // Security protected NAS 5GS message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0010 = Security header type: Integrity protected and ciphered (2) + // Message authentication code: 0xa0b88817 + // Sequence number: 1 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Registration complete (0x43) + + uint8_t reg_complete[] = {0x7e, 0x02, 0xa0, 0xb8, 0x88, 0x17, 0x01, 0x7e, 0x00, 0x43}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, reg_complete); + +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + nas_5gs_msg nas_msg; + + // Unpacking + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::integrity_protected_and_ciphered); + TESTASSERT(nas_msg.hdr.message_authentication_code == 0xa0b88817); + TESTASSERT(nas_msg.hdr.sequence_number == 1); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.inner_extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.inner_security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::registration_complete); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + + return SRSRAN_SUCCESS; +} + +int deregistration_request_unpacking_packing_test_2(srsran::nas_pcap* pcap) +{ + // NAS-PDU: 7e 02 b1 b8 76 98 02 7e 00 45 09 00 0b f2 00 f1 10 ca fe 00 00 00 00 03 + // Non-Access-Stratum 5GS (NAS)PDU + // Security protected NAS 5GS message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0010 = Security header type: Integrity protected and ciphered (2) + // Message authentication code: 0xb1b87698 + // Sequence number: 2 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: Deregistration request (UE originating) (0x45) + // De-registration type + // .... 1... = Switch off: Switch off + // .... .0.. = Re-registration required: re-registration not required + // .... ..01 = Access type: 3GPP access (1) + // NAS key set identifier + // 0... .... = Type of security context flag (TSC): Native security context (for KSIAMF) + // .000 .... = NAS key set identifier: 0 + // 5GS mobile identity + // Length: 11 + // .... 0... = Odd/even indication: Even number of identity digits + // .... .010 = Type of identity: 5G-GUTI (2) + // Mobile Country Code (MCC): Unknown (1) + // Mobile Network Code (MNC): Unknown (01) + // AMF Region ID: 202 + // 1111 1110 00.. .... = AMF Set ID: 1016 + // ..00 0000 = AMF Pointer: 0 + // 5G-TMSI: 3 (0x00000003) + // + + uint8_t deregistration_req[] = {0x7e, 0x02, 0xb1, 0xb8, 0x76, 0x98, 0x02, 0x7e, 0x00, 0x45, 0x09, 0x00, + 0x0b, 0x02, 0x00, 0xf1, 0x10, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x03}; + + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, deregistration_req); +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + + nas_5gs_msg nas_msg; + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::integrity_protected_and_ciphered); + TESTASSERT(nas_msg.hdr.message_authentication_code == 0xb1b87698); + TESTASSERT(nas_msg.hdr.sequence_number == 2); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.inner_extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.inner_security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::deregistration_request_ue_originating); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + deregistration_request_ue_originating_t& dereg_req_ue_o = nas_msg.deregistration_request_ue_originating(); + + TESTASSERT(dereg_req_ue_o.de_registration_type.switch_off == + de_registration_type_t::switch_off_type_::options::switch_off); + TESTASSERT(dereg_req_ue_o.de_registration_type.access_type == + de_registration_type_t::access_type_type_::options::access_3_gpp); + TESTASSERT(dereg_req_ue_o.ng_ksi.security_context_flag == + key_set_identifier_t::security_context_flag_type_::options::native_security_context); + TESTASSERT(dereg_req_ue_o.ng_ksi.nas_key_set_identifier == 0); + TESTASSERT(dereg_req_ue_o.mobile_identity_5gs.type() == mobile_identity_5gs_t::identity_types_::options::guti_5g); + TESTASSERT(dereg_req_ue_o.mobile_identity_5gs.length == 11); + mobile_identity_5gs_t::guti_5g_s guti_5g = dereg_req_ue_o.mobile_identity_5gs.guti_5g(); + + TESTASSERT(guti_5g.mcc[0] == 0); + TESTASSERT(guti_5g.mcc[1] == 0); + TESTASSERT(guti_5g.mcc[2] == 1); + TESTASSERT(guti_5g.mnc[0] == 0); + TESTASSERT(guti_5g.mnc[1] == 1); + TESTASSERT(guti_5g.mnc[2] == 0xf); + TESTASSERT(guti_5g.amf_region_id == 202); + TESTASSERT(guti_5g.amf_set_id == 1016); + TESTASSERT(guti_5g.amf_pointer == 0); + TESTASSERT(guti_5g.tmsi_5g == 0x00000003); + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); + +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + return SRSRAN_SUCCESS; +} + +int pdu_session_establishment_request_unpacking_packing_test(srsran::nas_pcap* pcap) +{ + // NAS-PDU: 7e 02 dc f9 1d 1b 02 7e 00 67 01 00 06 2e 0a 00 c1 ff ff 12 0a 81 22 04 … + // Non-Access-Stratum 5GS (NAS)PDU + // Security protected NAS 5GS message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0010 = Security header type: Integrity protected and ciphered (2) + // Message authentication code: 0xdcf91d1b + // Sequence number: 2 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: UL NAS transport (0x67) + // 0000 .... = Spare Half Octet: 0 + // Payload container type + // .... 0001 = Payload container type: N1 SM information (1) + // Payload container + // Length: 6 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G session management messages (46) + // PDU session identity: PDU session identity value 10 (10) + // Procedure transaction identity: 0 + // Message type: PDU session establishment request (0xc1) + // Integrity protection maximum data rate + // Integrity protection maximum data rate for uplink: Full data rate (255) + // Integrity protection maximum data rate for downlink: Full data rate (255) + // PDU session identity 2 - PDU session ID + // Element ID: 0x12 + // PDU session identity: PDU session identity value 10 (10) + // Request type + // 1000 .... = Element ID: 0x8- + // .... .001 = Request type: Initial request (1) + // S-NSSAI + // Element ID: 0x22 + // Length: 4 + // Slice/service type (SST): 1 + // Slice differentiator (SD): 66051 + // DNN + // Element ID: 0x25 + // Length: 9 + // DNN: internet + + uint8_t pdu_session_bytes[] = {0x7e, 0x02, 0xdc, 0xf9, 0x1d, 0x1b, 0x02, 0x7e, 0x00, 0x67, 0x01, 0x00, 0x06, + 0x2e, 0x0a, 0x00, 0xc1, 0xff, 0xff, 0x12, 0x0a, 0x81, 0x22, 0x04, 0x01, 0x01, + 0x02, 0x03, 0x25, 0x09, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, pdu_session_bytes); +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + + nas_5gs_msg nas_msg; + + // Unpacking + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::integrity_protected_and_ciphered); + TESTASSERT(nas_msg.hdr.message_authentication_code == 0xdcf91d1b); + TESTASSERT(nas_msg.hdr.sequence_number == 2); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.inner_extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.inner_security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::ul_nas_transport); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + ul_nas_transport_t& ul_nas = nas_msg.ul_nas_transport(); + TESTASSERT(ul_nas.payload_container_type.payload_container_type == + payload_container_type_t::Payload_container_type_type_::options::n1_sm_information); + TESTASSERT(ul_nas.payload_container.length == 6); + TESTASSERT(ul_nas.payload_container.payload_container_contents.size() == 6); + TESTASSERT(ul_nas.payload_container.payload_container_contents[0] == 0x2e); + TESTASSERT(ul_nas.payload_container.payload_container_contents[5] == 0xff); + + // Unpack inner nas + nas_5gs_msg inner_nas; + TESTASSERT(inner_nas.unpack_outer_hdr(ul_nas.payload_container.payload_container_contents) == SRSRAN_SUCCESS); + TESTASSERT(inner_nas.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gsm); + TESTASSERT(inner_nas.hdr.pdu_session_identity == 10); + TESTASSERT(inner_nas.hdr.procedure_transaction_identity == 0); + TESTASSERT(inner_nas.hdr.message_type == msg_types::options::pdu_session_establishment_request); + + TESTASSERT(inner_nas.unpack(ul_nas.payload_container.payload_container_contents) == SRSRAN_SUCCESS); + pdu_session_establishment_request_t pdu_sess_est_req = inner_nas.pdu_session_establishment_request(); + TESTASSERT(pdu_sess_est_req.integrity_protection_maximum_data_rate.max_data_rate_upip_uplink == + integrity_protection_maximum_data_rate_t::max_data_rate_UPIP_uplink_type_::options::full_data_rate); + TESTASSERT(pdu_sess_est_req.integrity_protection_maximum_data_rate.max_data_rate_upip_downlink == + integrity_protection_maximum_data_rate_t::max_data_rate_UPIP_downlink_type_::options::full_data_rate); + + // Packing inner nas buffer + srsran::unique_byte_buffer_t buf_cmp_inner = srsran::make_byte_buffer(); + inner_nas.pack(buf_cmp_inner); + + // Compare inner nas buffer + TESTASSERT(ul_nas.payload_container.payload_container_contents.size() == buf_cmp_inner.get()->N_bytes); + TESTASSERT(memcmp(ul_nas.payload_container.payload_container_contents.data(), + buf_cmp_inner.get()->msg, + buf_cmp_inner.get()->N_bytes) == 0); + + // Outer again + TESTASSERT(ul_nas.pdu_session_id_present == true); + TESTASSERT(ul_nas.pdu_session_id.pdu_session_identity_2_value == 10); + TESTASSERT(ul_nas.request_type_present == true); + TESTASSERT(ul_nas.request_type.request_type_value == + request_type_t::Request_type_value_type_::options::initial_request); + TESTASSERT(ul_nas.s_nssai_present == true); + TESTASSERT(ul_nas.s_nssai.length == 4); + TESTASSERT(ul_nas.s_nssai.sst == 1); + TESTASSERT(ul_nas.s_nssai.sd == 66051); + TESTASSERT(ul_nas.dnn_present == true); + TESTASSERT(ul_nas.dnn.length == 9); + TESTASSERT(ul_nas.dnn.dnn_value.size() == 9); + TESTASSERT(ul_nas.dnn.dnn_value[0] == 0x08); + TESTASSERT(ul_nas.dnn.dnn_value[1] == 0x69); + TESTASSERT(ul_nas.dnn.dnn_value[8] == 0x74); + + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); + +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + return SRSRAN_SUCCESS; +} + +int pdu_session_est_req_accecpt(srsran::nas_pcap* pcap) +{ + // pDUSessionNAS-PDU: 7e 02 1a ca a2 92 02 7e 00 68 01 00 1d 2e 0a 00 c2 11 00 08 01 06 31 31 … + // Non-Access-Stratum 5GS (NAS)PDU + // Security protected NAS 5GS message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0010 = Security header type: Integrity protected and ciphered (2) + // Message authentication code: 0x1acaa292 + // Sequence number: 2 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G mobility management messages (126) + // 0000 .... = Spare Half Octet: 0 + // .... 0000 = Security header type: Plain NAS message, not security protected (0) + // Message type: DL NAS transport (0x68) + // 0000 .... = Spare Half Octet: 0 + // Payload container type + // .... 0001 = Payload container type: N1 SM information (1) + // Payload container + // Length: 29 + // Plain NAS 5GS Message + // Extended protocol discriminator: 5G session management messages (46) + // PDU session identity: PDU session identity value 10 (10) + // Procedure transaction identity: 0 + // Message type: PDU session establishment accept (0xc2) + // .001 .... = Selected SSC mode: SSC mode 1 (1) + // PDU session type - Selected PDU session type + // .... .001 = PDU session type: IPv4 (1) + // QoS rules - Authorized QoS rules + // Length: 8 + // QoS rule 1 + // QoS rule identifier: 1 + // Length: 1585 + // 001. .... = Rule operation code: Create new QoS rule (1) + // ...1 .... = DQR: The QoS rule is the default QoS rule + // .... 0001 = Number of packet filters: 1 + // Packet filter 1 + // ..00 .... = Packet filter direction: Reserved (0) + // .... 0001 = Packet filter identifier: 1 + // Length: 1 + // Packet filter component 1 + // Packet filter component type: Unknown (0) + // Not dissected yet + // [Expert Info (Note/Protocol): Not dissected yet] + // [Not dissected yet] + // + // [Severity level: Note] + // [Group: Protocol] + // QoS rule precedence: 9 + // 0... .... = Spare: 0 + // .0.. .... = Spare: 0 + // ..00 0110 = Qos flow identifier: 6 + // Session-AMBR + // Length: 6 + // Unit for Session-AMBR for downlink: value is incremented in multiples of 1 Kbps (1) + // Session-AMBR for downlink: 59395 Kbps (59395) + // Unit for Session-AMBR for uplink: value is incremented in multiples of 1 Kbps (1) + // Session-AMBR for uplink: 59395 Kbps (59395) + // PDU address + // Element ID: 0x29 + // Length: 5 + // .... .001 = PDU session type: IPv4 (1) + // PDU address information: 60.60.0.1 + // PDU session identity 2 - PDU session ID + // Element ID: 0x12 + // PDU session identity: PDU session identity value 10 (10) + + uint8_t pdu_session_bytes[] = {0x7e, 0x02, 0x1a, 0xca, 0xa2, 0x92, 0x02, 0x7e, 0x00, 0x68, 0x01, + 0x00, 0x1d, 0x2e, 0x0a, 0x00, 0xc2, 0x11, 0x00, 0x08, 0x01, 0x06, + 0x31, 0x31, 0x01, 0x01, 0x00, 0x09, 0x06, 0x01, 0xe8, 0x03, 0x01, + 0xe8, 0x03, 0x29, 0x05, 0x01, 0x3c, 0x3c, 0x00, 0x01, 0x12, 0x0a}; + srsran::unique_byte_buffer_t buf; + copy_msg_to_buffer(buf, pdu_session_bytes); +#if HAVE_PCAP + pcap->write_nas(buf.get()->msg, buf.get()->N_bytes); +#endif + + nas_5gs_msg nas_msg; + + // Unpacking + TESTASSERT(nas_msg.unpack_outer_hdr(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.security_header_type == nas_5gs_hdr::integrity_protected_and_ciphered); + TESTASSERT(nas_msg.hdr.message_authentication_code == 0x1acaa292); + TESTASSERT(nas_msg.hdr.sequence_number == 2); + + TESTASSERT(nas_msg.unpack(buf) == SRSRAN_SUCCESS); + TESTASSERT(nas_msg.hdr.inner_extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gmm); + TESTASSERT(nas_msg.hdr.inner_security_header_type == nas_5gs_hdr::plain_5gs_nas_message); + TESTASSERT(nas_msg.hdr.message_type == msg_types::options::dl_nas_transport); + printf("%s\n", nas_msg.hdr.message_type.to_string()); + + dl_nas_transport_t& dl_nas = nas_msg.dl_nas_transport(); + TESTASSERT(dl_nas.payload_container_type.payload_container_type == + payload_container_type_t::Payload_container_type_type_::options::n1_sm_information); + TESTASSERT(dl_nas.payload_container.length == 29); + TESTASSERT(dl_nas.payload_container.payload_container_contents.size() == 29); + TESTASSERT(dl_nas.payload_container.payload_container_contents[0] == 0x2e); + TESTASSERT(dl_nas.payload_container.payload_container_contents[28] == 0x01); + + // Unpack inner nas + nas_5gs_msg inner_nas; + TESTASSERT(inner_nas.unpack_outer_hdr(dl_nas.payload_container.payload_container_contents) == SRSRAN_SUCCESS); + TESTASSERT(inner_nas.hdr.extended_protocol_discriminator == nas_5gs_hdr::extended_protocol_discriminator_5gsm); + TESTASSERT(inner_nas.hdr.pdu_session_identity == 10); + TESTASSERT(inner_nas.hdr.procedure_transaction_identity == 0); + TESTASSERT(inner_nas.hdr.message_type == msg_types::options::pdu_session_establishment_accept); + + TESTASSERT(inner_nas.unpack(dl_nas.payload_container.payload_container_contents) == SRSRAN_SUCCESS); + pdu_session_establishment_accept_t pdu_sess_est_acc = inner_nas.pdu_session_establishment_accept(); + TESTASSERT(pdu_sess_est_acc.selected_ssc_mode.ssc_mode_value == + ssc_mode_t::SSC_mode_value_type_::options::ssc_mode_1); + TESTASSERT(pdu_sess_est_acc.selected_pdu_session_type.pdu_session_type_value == + pdu_session_type_t::PDU_session_type_value_type_::options::ipv4); + + TESTASSERT(pdu_sess_est_acc.authorized__qo_s_rules.length == 8); + TESTASSERT(pdu_sess_est_acc.session_ambr.length == 6); + TESTASSERT(pdu_sess_est_acc.session_ambr.unit_session_ambr_for_downlink == + session_ambr_t::unit_session_AMBR_type_::options::inc_by_1_kbps); + TESTASSERT(pdu_sess_est_acc.session_ambr.session_ambr_for_downlink == 59395); + TESTASSERT(pdu_sess_est_acc.session_ambr.unit_session_ambr_for_uplink == + session_ambr_t::unit_session_AMBR_type_::options::inc_by_1_kbps); + TESTASSERT(pdu_sess_est_acc.session_ambr.session_ambr_for_uplink == 59395); + TESTASSERT(pdu_sess_est_acc.pdu_address_present == true); + TESTASSERT(pdu_sess_est_acc.pdu_address.si6_lla == false); + TESTASSERT(pdu_sess_est_acc.pdu_address.pdu_session_type_value == + pdu_address_t::PDU_session_type_value_type_::options::ipv4); + TESTASSERT(pdu_sess_est_acc.pdu_address.ipv4[0] == 0x3c); + TESTASSERT(pdu_sess_est_acc.pdu_address.ipv4[1] == 0x3c); + TESTASSERT(pdu_sess_est_acc.pdu_address.ipv4[2] == 0x00); + TESTASSERT(pdu_sess_est_acc.pdu_address.ipv4[3] == 0x01); + + // Packing inner nas buffer + srsran::unique_byte_buffer_t buf_cmp_inner = srsran::make_byte_buffer(); + inner_nas.pack(buf_cmp_inner); + + // Compare inner nas buffer + // TESTASSERT(dl_nas.payload_container.payload_container_contents.size() == buf_cmp_inner.get()->N_bytes); + // TESTASSERT(memcmp(dl_nas.payload_container.payload_container_contents.data(), + // buf_cmp_inner.get()->msg, + // buf_cmp_inner.get()->N_bytes) == 0); + + // outer nas again + TESTASSERT(dl_nas.pdu_session_id_present == true); + TESTASSERT(dl_nas.pdu_session_id.pdu_session_identity_2_value == 10); + // Packing + srsran::unique_byte_buffer_t buf_cmp = srsran::make_byte_buffer(); + nas_msg.pack(buf_cmp); + +#if HAVE_PCAP + pcap->write_nas(buf_cmp.get()->msg, buf_cmp.get()->N_bytes); +#endif + + // Compare buffer + TESTASSERT(buf.get()->N_bytes == buf_cmp.get()->N_bytes); + TESTASSERT(memcmp(buf.get()->msg, buf_cmp.get()->msg, buf.get()->N_bytes) == 0); + return SRSRAN_SUCCESS; +} + +int main() +{ + srslog::init(); + srsran::console("Testing 5G NAS packing and unpacking\n"); +#if HAVE_PCAP + srsran::nas_pcap pcap; + pcap.open("nas_5g_msg_test.pcap", 0, srsran::srsran_rat_t::nr); + TESTASSERT(registration_request_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(registration_request_unpacking_packing_test_2(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(deregistration_request_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(authentication_request_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(authentication_resp_request_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(security_command_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(security_complete_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(registration_accept_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(registration_complete_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(deregistration_request_unpacking_packing_test_2(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(pdu_session_establishment_request_unpacking_packing_test(&pcap) == SRSRAN_SUCCESS); + TESTASSERT(pdu_session_est_req_accecpt(&pcap) == SRSRAN_SUCCESS); + pcap.close(); +#else + TESTASSERT(registration_request_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(registration_request_unpacking_packing_test_2(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(deregistration_request_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(authentication_request_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(authentication_resp_request_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(security_command_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(security_complete_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(registration_accept_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(registration_complete_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(deregistration_request_unpacking_packing_test_2(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(pdu_session_establishment_request_unpacking_packing_test(nullptr) == SRSRAN_SUCCESS); + TESTASSERT(pdu_session_est_req_accecpt(nullptr) == SRSRAN_SUCCESS); +#endif + return SRSRAN_SUCCESS; +} From 654afac9c76c1ff64df5f1e7ef60c77bcb011ef8 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 8 Jul 2021 14:06:10 +0200 Subject: [PATCH 46/50] nas_5g_msg_test: remove copy_msg_to_buffer() that is now in test_common.h --- lib/test/asn1/nas_5g_msg_test.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/test/asn1/nas_5g_msg_test.cc b/lib/test/asn1/nas_5g_msg_test.cc index 440602b9f..7926964a4 100644 --- a/lib/test/asn1/nas_5g_msg_test.cc +++ b/lib/test/asn1/nas_5g_msg_test.cc @@ -47,13 +47,6 @@ inline void hex_dump(uint8_t* buf, uint32_t buf_length) printf("\n"); } -void copy_msg_to_buffer(srsran::unique_byte_buffer_t& pdu, srsran::const_byte_span msg) -{ - pdu = srsran::make_byte_buffer(); - memcpy(pdu->msg, msg.data(), msg.size()); - pdu->N_bytes = msg.size(); -} - int registration_request_unpacking_packing_test(srsran::nas_pcap* pcap) { uint8_t reg_request[] = {0x7e, 0x00, 0x41, 0x79, 0x00, 0x0b, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, From 068267992d9862bcb0c34e59561c4a767ddb0f82 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 8 Jul 2021 09:08:30 +0200 Subject: [PATCH 47/50] rnti_pool: add rrc_endc class and extra 1024B to UE memblock size this should fix #3045 however, this hard-coded size seems pretty unflexible anyway so we might have to increase/add to it, or find an alternative way to calculate the size? --- srsenb/src/common/rnti_pool.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/srsenb/src/common/rnti_pool.cc b/srsenb/src/common/rnti_pool.cc index 6b2804876..44b8cff3a 100644 --- a/srsenb/src/common/rnti_pool.cc +++ b/srsenb/src/common/rnti_pool.cc @@ -13,6 +13,7 @@ #include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/common/common_enb.h" #include "srsenb/hdr/stack/mac/ue.h" +#include "srsenb/hdr/stack/rrc/rrc_endc.h" #include "srsenb/hdr/stack/rrc/rrc_mobility.h" #include "srsenb/hdr/stack/rrc/rrc_ue.h" #include "srsran/adt/pool/circular_stack_pool.h" @@ -21,8 +22,8 @@ namespace srsenb { -const static size_t UE_MEM_BLOCK_SIZE = - sizeof(ue) + sizeof(rrc::ue) + sizeof(rrc::ue::rrc_mobility) + sizeof(srsran::rlc) + sizeof(srsran::pdcp); +const static size_t UE_MEM_BLOCK_SIZE = 1024 + sizeof(ue) + sizeof(rrc::ue) + sizeof(rrc::ue::rrc_mobility) + + sizeof(rrc::ue::rrc_endc) + sizeof(srsran::rlc) + sizeof(srsran::pdcp); srsran::circular_stack_pool* get_rnti_pool() { From e3ea5d3d25f40685d0ec9f9af88450c3c0ad0ee8 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 5 Jul 2021 17:09:34 +0200 Subject: [PATCH 48/50] Renamed PHY NR test --- test/phy/CMakeLists.txt | 2 +- test/phy/{nr_dl_flood.cc => nr_phy_test.cc} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/phy/{nr_dl_flood.cc => nr_phy_test.cc} (100%) diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 959bd21bb..ea235b828 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -7,7 +7,7 @@ # if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) - add_executable(nr_phy_test nr_dl_flood.cc) + add_executable(nr_phy_test nr_phy_test.cc) target_link_libraries(nr_phy_test srsue_phy_nr srsue_phy diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_phy_test.cc similarity index 100% rename from test/phy/nr_dl_flood.cc rename to test/phy/nr_phy_test.cc From f07d925be17beac0cff67fc9595179699580f5cd Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 5 Jul 2021 18:51:02 +0200 Subject: [PATCH 49/50] Initial NR PHY test scheduling for PUSCH --- lib/include/srsran/common/phy_cfg_nr.h | 25 +- lib/src/common/phy_cfg_nr.cc | 36 ++- lib/src/common/phy_cfg_nr_default.cc | 5 + test/phy/dummy_gnb_stack.h | 305 +++++++++++++++++-------- test/phy/dummy_rx_harq_proc.h | 41 ++++ test/phy/dummy_tx_harq_proc.h | 41 ++++ test/phy/nr_phy_test.cc | 29 +-- 7 files changed, 356 insertions(+), 126 deletions(-) create mode 100644 test/phy/dummy_rx_harq_proc.h create mode 100644 test/phy/dummy_tx_harq_proc.h diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index b37e6291d..e3985ce21 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -127,11 +127,26 @@ struct phy_cfg_nr_t { * @brief Compute UCI configuration for the given slot from the pending PDSCH ACK resources, periodic CSI, * periodic SR resources and so on. */ - bool get_pucch(const srsran_slot_cfg_t& slot_cfg, - const srsran_pdsch_ack_nr_t& pdsch_ack, - srsran_pucch_nr_common_cfg_t& cfg, - srsran_uci_cfg_nr_t& uci_cfg, - srsran_pucch_nr_resource_t& resource) const; + bool get_uci_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_pdsch_ack_nr_t& pdsch_ack, + srsran_uci_cfg_nr_t& uci_cfg) const; + + /** + * @brief Compute UCI configuration for PUCCH for the given slot from the pending PDSCH ACK resources, periodic CSI, + * periodic SR resources and so on. + */ + bool get_pucch_uci_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_uci_cfg_nr_t& uci_cfg, + srsran_pucch_nr_common_cfg_t& cfg, + srsran_pucch_nr_resource_t& resource) const; + + /** + * @brief Compute UCI configuration for PUSCH for the given slot from the pending PDSCH ACK resources, periodic CSI, + * periodic SR resources and so on. + */ + bool get_pusch_uci_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_uci_cfg_nr_t& uci_cfg, + srsran_sch_cfg_nr_t& pusch_cfg) const; }; } // namespace srsran diff --git a/lib/src/common/phy_cfg_nr.cc b/lib/src/common/phy_cfg_nr.cc index 729839084..1ab321feb 100644 --- a/lib/src/common/phy_cfg_nr.cc +++ b/lib/src/common/phy_cfg_nr.cc @@ -280,17 +280,29 @@ bool phy_cfg_nr_t::get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl, return srsran_harq_ack_resource(&harq_ack, &dci_dl, &ack_resource) == SRSRAN_SUCCESS; } -bool phy_cfg_nr_t::get_pucch(const srsran_slot_cfg_t& slot_cfg, - const srsran_pdsch_ack_nr_t& ack_info, - srsran_pucch_nr_common_cfg_t& cfg, - srsran_uci_cfg_nr_t& uci_cfg, - srsran_pucch_nr_resource_t& resource) const +bool phy_cfg_nr_t::get_uci_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_pdsch_ack_nr_t& pdsch_ack, + srsran_uci_cfg_nr_t& uci_cfg) const { // Generate configuration for HARQ feedback - if (srsran_harq_ack_gen_uci_cfg(&harq_ack, &ack_info, &uci_cfg) < SRSRAN_SUCCESS) { + if (srsran_harq_ack_gen_uci_cfg(&harq_ack, &pdsch_ack, &uci_cfg) < SRSRAN_SUCCESS) { return false; } + // Generate configuration for SR + // ... + + // Generate configuration for CSI reports + // ... + + return true; +} + +bool phy_cfg_nr_t::get_pucch_uci_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_uci_cfg_nr_t& uci_cfg, + srsran_pucch_nr_common_cfg_t& cfg, + srsran_pucch_nr_resource_t& resource) const +{ // Select PUCCH resource if (srsran_ra_ul_nr_pucch_resource(&pucch, &uci_cfg, &resource) < SRSRAN_SUCCESS) { ERROR("Selecting PUCCH resource"); @@ -300,4 +312,16 @@ bool phy_cfg_nr_t::get_pucch(const srsran_slot_cfg_t& slot_cfg, return true; } +bool phy_cfg_nr_t::get_pusch_uci_cfg(const srsran_slot_cfg_t& slot_cfg, + const srsran_uci_cfg_nr_t& uci_cfg, + srsran_sch_cfg_nr_t& pusch_cfg) const +{ + // Generate configuration for PUSCH + if (srsran_ra_ul_set_grant_uci_nr(&carrier, &pusch, &uci_cfg, &pusch_cfg) < SRSRAN_SUCCESS) { + return false; + } + + return true; +} + } // namespace srsran \ No newline at end of file diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index b674ea8d8..ae4226685 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -91,6 +91,11 @@ void phy_cfg_nr_default_t::make_pusch_default(srsran_sch_hl_cfg_nr_t& pusch) // Setup PUSCH DMRS type A position pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; + + pusch.scaling = 1.0f; + pusch.beta_offsets.fix_ack = 12.625f; + pusch.beta_offsets.fix_csi1 = 2.25f; + pusch.beta_offsets.fix_csi2 = 2.25f; } void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch) diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 42c2d9c5d..afc56563c 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -13,6 +13,8 @@ #ifndef SRSRAN_DUMMY_GNB_STACK_H #define SRSRAN_DUMMY_GNB_STACK_H +#include "dummy_rx_harq_proc.h" +#include "dummy_tx_harq_proc.h" #include #include #include @@ -29,14 +31,14 @@ private: srsran::circular_array dci_dl_location; srsran::circular_array dci_ul_location; srsran::circular_array dl_data_to_ul_ack; - uint32_t ss_id = 0; - srsran_dci_format_nr_t dci_format_ul = SRSRAN_DCI_FORMAT_NR_COUNT; - srsran_dci_format_nr_t dci_format_dl = SRSRAN_DCI_FORMAT_NR_COUNT; - uint32_t dl_freq_res = 0; - uint32_t dl_time_res = 0; - srsran_random_t random_gen = nullptr; - srsran::phy_cfg_nr_t phy_cfg = {}; - bool valid = false; + uint32_t ss_id = 0; + uint32_t dl_freq_res = 0; + uint32_t dl_time_res = 0; + uint32_t ul_freq_res = 0; + uint32_t ul_time_res = 0; + srsran_random_t random_gen = nullptr; + srsran::phy_cfg_nr_t phy_cfg = {}; + bool valid = false; std::mutex mac_metrics_mutex; srsenb::mac_ue_metrics_t mac_metrics = {}; @@ -79,26 +81,164 @@ private: }; std::array pending_ack = {}; - struct dummy_harq_proc { - static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; - std::vector data; - srsran_softbuffer_tx_t softbuffer = {}; + // PUSCH state + class pending_pusch_t + { + private: + std::mutex mutex; + srsran_sch_cfg_nr_t pusch = {}; + bool valid = false; - dummy_harq_proc() + public: + pending_pusch_t() = default; + void push(const srsran_sch_cfg_nr_t& pusch_) { - // Allocate data - data.resize(MAX_TB_SZ); - - // Initialise softbuffer - if (srsran_softbuffer_tx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < - SRSRAN_SUCCESS) { - ERROR("Error Tx buffer"); - } + std::unique_lock lock(mutex); + pusch = pusch_; + valid = true; } - ~dummy_harq_proc() { srsran_softbuffer_tx_free(&softbuffer); } + bool pop(srsran_sch_cfg_nr_t& pusch_) + { + std::unique_lock lock(mutex); + bool ret = valid; + pusch_ = pusch; + valid = false; + return ret; + } }; - srsran::circular_array tx_harq_proc; + std::array pending_pusch = {}; + + srsran::circular_array tx_harq_proc; + + srsran::circular_array rx_harq_proc; + +private: + bool schedule_pdsch(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) + { + // Instantiate PDCCH and PDSCH + pdcch_dl_t pdcch = {}; + pdsch_t pdsch = {}; + + // Select grant and set data + pdsch.data[0] = tx_harq_proc[slot_cfg.idx].data.data(); + + // Second TB is not used + pdsch.data[1] = nullptr; + + // Fill DCI configuration + pdcch.dci_cfg = phy_cfg.get_dci_cfg(); + + // Fill DCI context + if (not phy_cfg.get_dci_ctx_pdsch_rnti_c(ss_id, dci_dl_location[slot_cfg.idx], rnti, pdcch.dci.ctx)) { + logger.error("Error filling PDSCH DCI context"); + return false; + } + + uint32_t harq_feedback = dl_data_to_ul_ack[slot_cfg.idx]; + uint32_t harq_ack_slot_idx = TTI_ADD(slot_cfg.idx, harq_feedback); + + // Fill DCI fields + srsran_dci_dl_nr_t& dci = pdcch.dci; + dci.freq_domain_assigment = dl_freq_res; + dci.time_domain_assigment = dl_time_res; + dci.mcs = mcs; + dci.rv = 0; + dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; + dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; + dci.dai = pending_ack[harq_ack_slot_idx % pending_ack.size()].get_dai(); + dci.tpc = 1; + dci.pucch_resource = 0; + if (dci.ctx.format == srsran_dci_format_nr_1_0) { + dci.harq_feedback = dl_data_to_ul_ack[slot_cfg.idx] - 1; + } else { + dci.harq_feedback = slot_cfg.idx; + } + + // Create PDSCH configuration + if (not phy_cfg.get_pdsch_cfg(slot_cfg, dci, pdsch.sch)) { + logger.error("Error converting DCI to grant"); + return false; + } + + // Generate random data + srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); + + // Set TBS + tx_harq_proc[slot_cfg.idx].tbs = pdsch.sch.grant.tb[0].tbs; + + // Set softbuffer + pdsch.sch.grant.tb[0].softbuffer.tx = &tx_harq_proc[slot_cfg.idx].softbuffer; + + // Reset Tx softbuffer always + srsran_softbuffer_tx_reset(pdsch.sch.grant.tb[0].softbuffer.tx); + + // Push scheduling results + dl_sched.pdcch_dl.push_back(pdcch); + dl_sched.pdsch.push_back(pdsch); + + // Generate PDSCH HARQ Feedback + srsran_harq_ack_resource_t ack_resource = {}; + if (not phy_cfg.get_pdsch_ack_resource(dci, ack_resource)) { + logger.error("Error getting ack resource"); + return false; + } + + // Calculate PUCCH slot and push resource + pending_ack[harq_ack_slot_idx % pending_ack.size()].push_ack(ack_resource); + + return true; + } + + bool schedule_pusch(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) + { + // Instantiate PDCCH + pdcch_ul_t pdcch = {}; + + // Fill DCI configuration + pdcch.dci_cfg = phy_cfg.get_dci_cfg(); + + // Fill DCI context + if (not phy_cfg.get_dci_ctx_pusch_rnti_c(ss_id, dci_ul_location[slot_cfg.idx], rnti, pdcch.dci.ctx)) { + logger.error("Error filling PDSCH DCI context"); + return false; + } + + // Fill DCI fields + srsran_dci_ul_nr_t& dci = pdcch.dci; + dci.freq_domain_assigment = ul_freq_res; + dci.time_domain_assigment = ul_time_res; + dci.freq_hopping_flag = 0; + dci.mcs = mcs; + dci.rv = 0; + dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; + dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; + dci.tpc = 1; + + // Create PDSCH configuration + srsran_sch_cfg_nr_t pusch_cfg = {}; + if (not phy_cfg.get_pusch_cfg(slot_cfg, dci, pusch_cfg)) { + logger.error("Error converting DCI to grant"); + return false; + } + + // Set TBS + rx_harq_proc[slot_cfg.idx].tbs = pusch_cfg.grant.tb[0].tbs; + + // Set softbuffer + pusch_cfg.grant.tb[0].softbuffer.rx = &rx_harq_proc[slot_cfg.idx].softbuffer; + + // Reset Tx softbuffer always + srsran_softbuffer_rx_reset(pusch_cfg.grant.tb[0].softbuffer.rx); + + // Push scheduling results + dl_sched.pdcch_ul.push_back(pdcch); + + // Set pending PUSCH + pending_pusch[TTI_TX(slot_cfg.idx) % pending_pusch.size()].push(pusch_cfg); + + return true; + } public: struct args_t { @@ -110,13 +250,19 @@ public: uint32_t pdcch_dl_candidate_index = 0; ///< PDCCH DL DCI candidate index uint32_t pdcch_ul_candidate_index = 0; ///< PDCCH UL DCI candidate index uint32_t dl_start_rb = 0; ///< Start resource block - uint32_t dl_length_rb = 0l; ///< Number of resource blocks + uint32_t dl_length_rb = 0; ///< Number of resource blocks + uint32_t ul_start_rb = 0; ///< Start resource block + uint32_t ul_length_rb = 0; ///< Number of resource blocks uint32_t dl_time_res = 0; ///< PDSCH time resource std::string log_level = "debug"; }; gnb_dummy_stack(args_t args) : - mcs(args.mcs), rnti(args.rnti), dl_time_res(args.dl_time_res), phy_cfg(args.phy_cfg), ss_id(args.ss_id) + mcs(args.mcs), + rnti(args.rnti), + dl_time_res(args.dl_time_res), + phy_cfg(args.phy_cfg), + ss_id(args.ss_id) { random_gen = srsran_random_init(0x1234); logger.set_level(srslog::str_to_basic_level(args.log_level)); @@ -152,17 +298,12 @@ public: dci_ul_location[slot] = locations[args.pdcch_ul_candidate_index]; } - // Select DCI formats - dci_format_dl = phy_cfg.get_dci_format_pdsch(args.ss_id); - dci_format_ul = phy_cfg.get_dci_format_pusch(args.ss_id); - if (dci_format_dl == SRSRAN_DCI_FORMAT_NR_COUNT or dci_format_ul == SRSRAN_DCI_FORMAT_NR_COUNT) { - logger.error("Missing valid DL or UL DCI format in search space"); - return; - } - // Select DL frequency domain resources dl_freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.dl_start_rb, args.dl_length_rb); + // Select DL frequency domain resources + ul_freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.ul_start_rb, args.ul_length_rb); + // Setup DL Data to ACK timing for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % SRSRAN_MAX_NOF_DL_DATA_TO_UL]; @@ -188,74 +329,21 @@ public: return SRSRAN_SUCCESS; } - // Instantiate PDCCH and PDSCH - pdcch_dl_t pdcch = {}; - pdsch_t pdsch = {}; - - // Select grant and set data - pdsch.data[0] = tx_harq_proc[slot_cfg.idx].data.data(); - - // Second TB is not used - pdsch.data[1] = nullptr; - - // Fill DCI configuration - pdcch.dci_cfg = phy_cfg.get_dci_cfg(); - - // Fill DCI context - if (not phy_cfg.get_dci_ctx_pdsch_rnti_c(ss_id, dci_dl_location[slot_cfg.idx], rnti, pdcch.dci.ctx)) { - logger.error("Error filling PDSCH DCI context"); + if (not schedule_pdsch(slot_cfg, dl_sched)) { + logger.error("Error scheduling PDSCH"); return SRSRAN_ERROR; } - uint32_t harq_feedback = dl_data_to_ul_ack[slot_cfg.idx]; - uint32_t harq_ack_slot_idx = TTI_ADD(slot_cfg.idx, harq_feedback); - - // Fill DCI fields - srsran_dci_dl_nr_t& dci = pdcch.dci; - dci.freq_domain_assigment = dl_freq_res; - dci.time_domain_assigment = dl_time_res; - dci.mcs = mcs; - dci.rv = 0; - dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; - dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; - dci.dai = pending_ack[harq_ack_slot_idx % pending_ack.size()].get_dai(); - dci.tpc = 1; - dci.pucch_resource = 0; - if (dci.ctx.format == srsran_dci_format_nr_1_0) { - dci.harq_feedback = dl_data_to_ul_ack[slot_cfg.idx] - 1; - } else { - dci.harq_feedback = slot_cfg.idx; - } - - // Create PDSCH configuration - if (not phy_cfg.get_pdsch_cfg(slot_cfg, dci, pdsch.sch)) { - logger.error("Error converting DCI to grant"); - return SRSRAN_ERROR; + // Check if the UL slot is valid, if not skip UL scheduling + if (not srsran_tdd_nr_is_ul(&phy_cfg.tdd, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) { + return SRSRAN_SUCCESS; } - // Generate random data - srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); - - // Set softbuffer - pdsch.sch.grant.tb[0].softbuffer.tx = &tx_harq_proc[slot_cfg.idx].softbuffer; - - // Reset Tx softbuffer always - srsran_softbuffer_tx_reset(pdsch.sch.grant.tb[0].softbuffer.tx); - - // Push scheduling results - dl_sched.pdcch_dl.push_back(pdcch); - dl_sched.pdsch.push_back(pdsch); - - // Generate PDSCH HARQ Feedback - srsran_harq_ack_resource_t ack_resource = {}; - if (not phy_cfg.get_pdsch_ack_resource(dci, ack_resource)) { - logger.error("Error getting ack resource"); + if (not schedule_pusch(slot_cfg, dl_sched)) { + logger.error("Error scheduling PUSCH"); return SRSRAN_ERROR; } - // Calculate PUCCH slot and push resource - pending_ack[harq_ack_slot_idx % pending_ack.size()].push_ack(ack_resource); - return SRSRAN_SUCCESS; } @@ -263,19 +351,39 @@ public: { logger.set_context(slot_cfg.idx); - srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx % pending_ack.size()].get_ack(); - - if (ack.nof_cc > 0) { - mac_interface_phy_nr::pucch_t pucch = {}; + // Get ACK information + srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx % pending_ack.size()].get_ack(); + bool has_ack = ack.nof_cc > 0; + if (has_ack) { if (logger.debug.enabled()) { std::array str = {}; if (srsran_harq_ack_info(&ack, str.data(), (uint32_t)str.size()) > 0) { logger.debug("HARQ feedback:\n%s", str.data()); } } + } + mac_interface_phy_nr::pusch_t pusch = {}; + bool has_pusch = pending_pusch[slot_cfg.idx % pending_pusch.size()].pop(pusch.sch); + + srsran_uci_cfg_nr_t uci_cfg = {}; + if (not phy_cfg.get_uci_cfg(slot_cfg, ack, uci_cfg)) { + logger.error("Error getting UCI configuration"); + return SRSRAN_ERROR; + } - if (not phy_cfg.get_pucch(slot_cfg, ack, pucch.pucch_cfg, pucch.uci_cfg, pucch.resource)) { + if (has_pusch) { + if (not phy_cfg.get_pusch_uci_cfg(slot_cfg, uci_cfg, pusch.sch)) { + logger.error("Error setting UCI configuration in PUSCH"); + return SRSRAN_ERROR; + } + + ul_sched.pusch.push_back(pusch); + return SRSRAN_SUCCESS; + } else if (has_ack) { + mac_interface_phy_nr::pucch_t pucch = {}; + pucch.uci_cfg = uci_cfg; + if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.resource)) { logger.error("Error getting UCI CFG"); return SRSRAN_ERROR; } @@ -294,6 +402,7 @@ public: const srsran_harq_ack_bit_t* ack_bit = &pucch_info.uci_data.cfg.ack.bits[i]; bool is_ok = (pucch_info.uci_data.value.ack[i] == 1) and pucch_info.uci_data.value.valid; uint32_t tb_count = (ack_bit->tb0 ? 1 : 0) + (ack_bit->tb1 ? 1 : 0); + mac_metrics.tx_brate += tx_harq_proc[ack_bit->pid].tbs; mac_metrics.tx_pkts += tb_count; if (not is_ok) { mac_metrics.tx_errors += tb_count; diff --git a/test/phy/dummy_rx_harq_proc.h b/test/phy/dummy_rx_harq_proc.h new file mode 100644 index 000000000..9a5fe85a3 --- /dev/null +++ b/test/phy/dummy_rx_harq_proc.h @@ -0,0 +1,41 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_DUMMY_RX_HARQ_PROC_H +#define SRSRAN_DUMMY_RX_HARQ_PROC_H + +#include +#include +#include +#include +#include +#include + +struct dummy_rx_harq_proc { + static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; + srsran::byte_buffer_t data; + srsran_softbuffer_rx_t softbuffer = {}; + std::atomic tbs = {0}; + + dummy_rx_harq_proc() : data(0) + { + // Initialise softbuffer + if (srsran_softbuffer_rx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < + SRSRAN_SUCCESS) { + ERROR("Error Tx buffer"); + } + } + + ~dummy_rx_harq_proc() { srsran_softbuffer_rx_free(&softbuffer); } +}; + +#endif // SRSRAN_DUMMY_RX_HARQ_PROC_H diff --git a/test/phy/dummy_tx_harq_proc.h b/test/phy/dummy_tx_harq_proc.h new file mode 100644 index 000000000..cbaddc8b5 --- /dev/null +++ b/test/phy/dummy_tx_harq_proc.h @@ -0,0 +1,41 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_TX_DUMMY_HARQ_PROC_H +#define SRSRAN_TX_DUMMY_HARQ_PROC_H + +#include +#include +#include +#include +#include +#include + +struct dummy_tx_harq_proc { + static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; + srsran::byte_buffer_t data; + srsran_softbuffer_tx_t softbuffer = {}; + std::atomic tbs = {0}; + + dummy_tx_harq_proc() + { + // Initialise softbuffer + if (srsran_softbuffer_tx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < + SRSRAN_SUCCESS) { + ERROR("Error Tx buffer"); + } + } + + ~dummy_tx_harq_proc() { srsran_softbuffer_tx_free(&softbuffer); } +}; + +#endif // SRSRAN_TX_DUMMY_HARQ_PROC_H diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 270e74894..d1115f7cf 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -37,22 +37,8 @@ private: uint16_t rnti = 0; bool valid = false; - struct dummy_harq_proc { - static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; - srsran_softbuffer_rx_t softbuffer = {}; - - dummy_harq_proc() - { - // Initialise softbuffer - if (srsran_softbuffer_rx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < - SRSRAN_SUCCESS) { - ERROR("Error Tx buffer"); - } - } - - ~dummy_harq_proc() { srsran_softbuffer_rx_free(&softbuffer); } - }; - srsran::circular_array rx_harq_proc; + srsran::circular_array tx_harq_proc; + srsran::circular_array rx_harq_proc; public: struct args_t { @@ -71,7 +57,14 @@ public: action->tb.softbuffer = &rx_harq_proc[grant.pid].softbuffer; } void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) override {} - void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) override {} + void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) override + { + if (action == nullptr) { + return; + } + action->tb.enabled = true; + action->tb.payload = &rx_harq_proc[grant.pid].data; + } void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override { return false; } bool is_valid() const { return valid; } @@ -109,6 +102,8 @@ int main(int argc, char** argv) gnb_stack_args.phy_cfg = args.phy_cfg; gnb_stack_args.dl_start_rb = 0; gnb_stack_args.dl_length_rb = args.phy_cfg.carrier.nof_prb; + gnb_stack_args.ul_start_rb = 0; + gnb_stack_args.ul_length_rb = args.phy_cfg.carrier.nof_prb; // Create GNB stack gnb_dummy_stack gnb_stack(gnb_stack_args); From ecc0b921425217108391327115c34abf309676be Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 6 Jul 2021 15:26:00 +0200 Subject: [PATCH 50/50] Integrated PUSCH decoder in gNb --- .../srsran/common/phy_cfg_nr_default.h | 2 +- .../srsran/interfaces/gnb_interfaces.h | 8 +- lib/include/srsran/phy/gnb/gnb_ul.h | 6 + lib/src/common/phy_cfg_nr_default.cc | 2 +- lib/src/phy/gnb/gnb_ul.c | 19 +++ srsenb/src/phy/nr/slot_worker.cc | 28 ++++- test/phy/dummy_gnb_stack.h | 112 +++++++++++------- test/phy/dummy_rx_harq_proc.h | 29 ++++- test/phy/dummy_tx_harq_proc.h | 27 ++++- test/phy/dummy_ue_stack.h | 61 ++++++++++ test/phy/nr_phy_test.cc | 71 ++++------- 11 files changed, 267 insertions(+), 98 deletions(-) create mode 100644 test/phy/dummy_ue_stack.h diff --git a/lib/include/srsran/common/phy_cfg_nr_default.h b/lib/include/srsran/common/phy_cfg_nr_default.h index 56854f821..379558513 100644 --- a/lib/include/srsran/common/phy_cfg_nr_default.h +++ b/lib/include/srsran/common/phy_cfg_nr_default.h @@ -44,7 +44,7 @@ public: * @brief Carrier reference configuration for 10MHz serving cell bandwidth * - CORESET: all channel, 1 symbol * - Single common Search Space - * - 1 possible candidate per aggregation level + * - 2 possible candidate per aggregation level to allow DL and UL grants simultaneously */ R_PDCCH_CUSTOM_COMMON_SS = 0, } pdcch = R_PDCCH_CUSTOM_COMMON_SS; diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 4dc8af583..0ed3595ba 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -242,9 +242,9 @@ public: }; struct pusch_t { - srsran_sch_cfg_nr_t sch = {}; ///< PUSCH configuration - std::array data = {}; ///< Data pointer - std::array softbuffer_tx = {}; ///< Tx Softbuffer + uint32_t pid = 0; ///< HARQ process ID + srsran_sch_cfg_nr_t sch = {}; ///< PUSCH configuration + std::array data = {}; ///< Data pointer }; struct pucch_t { @@ -265,7 +265,9 @@ public: struct pusch_info_t { uint16_t rnti; + uint32_t pid = 0; ///< HARQ process ID srsran_pusch_res_nr_t pusch_data; + srsran_uci_cfg_nr_t uci_cfg; ///< Provides UCI configuration, so stack does not need to keep the pending state // ... add signal measurements here }; diff --git a/lib/include/srsran/phy/gnb/gnb_ul.h b/lib/include/srsran/phy/gnb/gnb_ul.h index 856cd539f..c0fbcfa13 100644 --- a/lib/include/srsran/phy/gnb/gnb_ul.h +++ b/lib/include/srsran/phy/gnb/gnb_ul.h @@ -65,4 +65,10 @@ SRSRAN_API uint32_t srsran_gnb_ul_pucch_info(srsran_gnb_ul_t* q char* str, uint32_t str_len); +SRSRAN_API uint32_t srsran_gnb_ul_pusch_info(srsran_gnb_ul_t* q, + const srsran_sch_cfg_nr_t* cfg, + const srsran_pusch_res_nr_t* res, + char* str, + uint32_t str_len); + #endif // SRSRAN_GNB_UL_H diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index ae4226685..abb3fd39a 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -65,7 +65,7 @@ void phy_cfg_nr_default_t::make_pdcch_custom_common_ss(srsran_pdcch_cfg_nr_t& pd // Generate 1 candidate for each aggregation level if possible for (uint32_t L = 0; L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) { pdcch.search_space[1].nof_candidates[L] = - SRSRAN_MIN(1, srsran_pdcch_nr_max_candidates_coreset(&pdcch.coreset[1], L)); + SRSRAN_MIN(2, srsran_pdcch_nr_max_candidates_coreset(&pdcch.coreset[1], L)); } } diff --git a/lib/src/phy/gnb/gnb_ul.c b/lib/src/phy/gnb/gnb_ul.c index b8961c682..22bc57ee5 100644 --- a/lib/src/phy/gnb/gnb_ul.c +++ b/lib/src/phy/gnb/gnb_ul.c @@ -287,5 +287,24 @@ uint32_t srsran_gnb_ul_pucch_info(srsran_gnb_ul_t* q, len = srsran_print_check( str, str_len, len, "snr=%+.1f valid=%c", q->chest_pucch.snr_db, uci_data->value.valid ? 'y' : 'n'); + return len; +} + +uint32_t srsran_gnb_ul_pusch_info(srsran_gnb_ul_t* q, + const srsran_sch_cfg_nr_t* cfg, + const srsran_pusch_res_nr_t* res, + char* str, + uint32_t str_len) +{ + if (q == NULL || cfg == NULL || res == NULL) { + return 0; + } + + uint32_t len = 0; + + len += srsran_pusch_nr_rx_info(&q->pusch, cfg, &cfg->grant, res, str, str_len - len); + + len = srsran_print_check(str, str_len, len, "snr=%+.1f", q->chest_pusch.snr_db); + return len; } \ No newline at end of file diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index b355f8b55..4ff00a180 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -190,7 +190,33 @@ bool slot_worker::work_ul() // Decode PUSCH for (stack_interface_phy_nr::pusch_t& pusch : ul_sched.pusch) { - // ... + // Get payload PDU + stack_interface_phy_nr::pusch_info_t pusch_info = {}; + pusch_info.uci_cfg = pusch.sch.uci; + pusch_info.pid = pusch.pid; + pusch_info.pusch_data.tb[0].payload = pusch.data[0]; + pusch_info.pusch_data.tb[1].payload = pusch.data[1]; + + // Decode PUCCH + if (srsran_gnb_ul_get_pusch(&gnb_ul, &ul_slot_cfg, &pusch.sch, &pusch.sch.grant, &pusch_info.pusch_data) < + SRSRAN_SUCCESS) { + logger.error("Error getting PUSCH"); + return false; + } + + // Inform stack + if (stack.pusch_info(ul_slot_cfg, pusch_info) < SRSRAN_SUCCESS) { + logger.error("Error pushing PUSCH information to stack"); + return false; + } + + // Log PUSCH decoding + if (logger.info.enabled()) { + std::array str; + srsran_gnb_ul_pusch_info(&gnb_ul, &pusch.sch, &pusch_info.pusch_data, str.data(), (uint32_t)str.size()); + + logger.info("PUSCH: %s", str.data()); + } } return true; diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index afc56563c..d1069dd1d 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -88,21 +88,24 @@ private: std::mutex mutex; srsran_sch_cfg_nr_t pusch = {}; bool valid = false; + uint32_t pid = 0; public: pending_pusch_t() = default; - void push(const srsran_sch_cfg_nr_t& pusch_) + void push(const uint32_t& pid_, const srsran_sch_cfg_nr_t& pusch_) { std::unique_lock lock(mutex); pusch = pusch_; + pid = pid_; valid = true; } - bool pop(srsran_sch_cfg_nr_t& pusch_) + bool pop(uint32_t& pid_, srsran_sch_cfg_nr_t& pusch_) { std::unique_lock lock(mutex); bool ret = valid; pusch_ = pusch; + pid_ = pid; valid = false; return ret; } @@ -113,16 +116,12 @@ private: srsran::circular_array rx_harq_proc; -private: bool schedule_pdsch(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { // Instantiate PDCCH and PDSCH pdcch_dl_t pdcch = {}; pdsch_t pdsch = {}; - // Select grant and set data - pdsch.data[0] = tx_harq_proc[slot_cfg.idx].data.data(); - // Second TB is not used pdsch.data[1] = nullptr; @@ -161,14 +160,15 @@ private: return false; } + // Set TBS + // Select grant and set data + pdsch.data[0] = tx_harq_proc[slot_cfg.idx].get_tb(pdsch.sch.grant.tb[0].tbs).data(); + // Generate random data srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); - // Set TBS - tx_harq_proc[slot_cfg.idx].tbs = pdsch.sch.grant.tb[0].tbs; - // Set softbuffer - pdsch.sch.grant.tb[0].softbuffer.tx = &tx_harq_proc[slot_cfg.idx].softbuffer; + pdsch.sch.grant.tb[0].softbuffer.tx = &tx_harq_proc[slot_cfg.idx].get_softbuffer(dci.ndi); // Reset Tx softbuffer always srsran_softbuffer_tx_reset(pdsch.sch.grant.tb[0].softbuffer.tx); @@ -222,20 +222,33 @@ private: return false; } - // Set TBS - rx_harq_proc[slot_cfg.idx].tbs = pusch_cfg.grant.tb[0].tbs; - // Set softbuffer - pusch_cfg.grant.tb[0].softbuffer.rx = &rx_harq_proc[slot_cfg.idx].softbuffer; - - // Reset Tx softbuffer always - srsran_softbuffer_rx_reset(pusch_cfg.grant.tb[0].softbuffer.rx); + pusch_cfg.grant.tb[0].softbuffer.rx = &rx_harq_proc[slot_cfg.idx].get_softbuffer(dci.ndi); // Push scheduling results dl_sched.pdcch_ul.push_back(pdcch); // Set pending PUSCH - pending_pusch[TTI_TX(slot_cfg.idx) % pending_pusch.size()].push(pusch_cfg); + pending_pusch[TTI_TX(slot_cfg.idx) % pending_pusch.size()].push(dci.pid, pusch_cfg); + + return true; + } + + bool handle_uci_data(const srsran_uci_cfg_nr_t& cfg, const srsran_uci_value_nr_t& value) + { + std::unique_lock lock(mac_metrics_mutex); + + for (uint32_t i = 0; i < cfg.ack.count; i++) { + const srsran_harq_ack_bit_t* ack_bit = &cfg.ack.bits[i]; + bool is_ok = (value.ack[i] == 1) and value.valid; + uint32_t tb_count = (ack_bit->tb0 ? 1 : 0) + (ack_bit->tb1 ? 1 : 0); + mac_metrics.tx_brate += tx_harq_proc[ack_bit->pid].get_tbs(); + mac_metrics.tx_pkts += tb_count; + if (not is_ok) { + mac_metrics.tx_errors += tb_count; + logger.debug("NACK received!"); + } + } return true; } @@ -248,7 +261,7 @@ public: uint32_t ss_id = 1; ///< Search Space identifier uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level uint32_t pdcch_dl_candidate_index = 0; ///< PDCCH DL DCI candidate index - uint32_t pdcch_ul_candidate_index = 0; ///< PDCCH UL DCI candidate index + uint32_t pdcch_ul_candidate_index = 1; ///< PDCCH UL DCI candidate index uint32_t dl_start_rb = 0; ///< Start resource block uint32_t dl_length_rb = 0; ///< Number of resource blocks uint32_t ul_start_rb = 0; ///< Start resource block @@ -258,11 +271,7 @@ public: }; gnb_dummy_stack(args_t args) : - mcs(args.mcs), - rnti(args.rnti), - dl_time_res(args.dl_time_res), - phy_cfg(args.phy_cfg), - ss_id(args.ss_id) + mcs(args.mcs), rnti(args.rnti), dl_time_res(args.dl_time_res), phy_cfg(args.phy_cfg), ss_id(args.ss_id) { random_gen = srsran_random_init(0x1234); logger.set_level(srslog::str_to_basic_level(args.log_level)); @@ -363,8 +372,8 @@ public: } } } - mac_interface_phy_nr::pusch_t pusch = {}; - bool has_pusch = pending_pusch[slot_cfg.idx % pending_pusch.size()].pop(pusch.sch); + mac_interface_phy_nr::pusch_t pusch = {}; + bool has_pusch = pending_pusch[slot_cfg.idx % pending_pusch.size()].pop(pusch.pid, pusch.sch); srsran_uci_cfg_nr_t uci_cfg = {}; if (not phy_cfg.get_uci_cfg(slot_cfg, ack, uci_cfg)) { @@ -372,7 +381,14 @@ public: return SRSRAN_ERROR; } + // Schedule PUSCH if (has_pusch) { + // Generate data + pusch.data[0] = rx_harq_proc[pusch.pid].get_tb(pusch.sch.grant.tb[0].tbs).data(); + pusch.data[1] = nullptr; + srsran_random_byte_vector(random_gen, pusch.data[0], pusch.sch.grant.tb[0].tbs / 8); + + // Put UCI configuration in PUSCH config if (not phy_cfg.get_pusch_uci_cfg(slot_cfg, uci_cfg, pusch.sch)) { logger.error("Error setting UCI configuration in PUSCH"); return SRSRAN_ERROR; @@ -380,7 +396,10 @@ public: ul_sched.pusch.push_back(pusch); return SRSRAN_SUCCESS; - } else if (has_ack) { + } + + // If any UCI information is triggered, schedule PUCCH + if (uci_cfg.ack.count > 0 || uci_cfg.nof_csi > 0 || uci_cfg.o_sr > 0) { mac_interface_phy_nr::pucch_t pucch = {}; pucch.uci_cfg = uci_cfg; if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.resource)) { @@ -389,33 +408,42 @@ public: } ul_sched.pucch.push_back(pucch); + return SRSRAN_SUCCESS; } - return 0; + // Otherwise no UL scheduling + return SRSRAN_SUCCESS; } int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override { - std::unique_lock lock(mac_metrics_mutex); - - for (uint32_t i = 0; i < pucch_info.uci_data.cfg.ack.count; i++) { - const srsran_harq_ack_bit_t* ack_bit = &pucch_info.uci_data.cfg.ack.bits[i]; - bool is_ok = (pucch_info.uci_data.value.ack[i] == 1) and pucch_info.uci_data.value.valid; - uint32_t tb_count = (ack_bit->tb0 ? 1 : 0) + (ack_bit->tb1 ? 1 : 0); - mac_metrics.tx_brate += tx_harq_proc[ack_bit->pid].tbs; - mac_metrics.tx_pkts += tb_count; - if (not is_ok) { - mac_metrics.tx_errors += tb_count; - logger.debug("NACK received!"); - } + // Handle UCI data + if (not handle_uci_data(pucch_info.uci_data.cfg, pucch_info.uci_data.value)) { + logger.error("Error handling UCI data from PUCCH reception"); + return SRSRAN_ERROR; } + + // Handle PHY metrics + // ... + return SRSRAN_SUCCESS; } int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override { - // ... Not implemented - return SRSRAN_ERROR; + // Handle UCI data + if (not handle_uci_data(pusch_info.uci_cfg, pusch_info.pusch_data.uci)) { + logger.error("Error handling UCI data from PUCCH reception"); + return SRSRAN_ERROR; + } + + if (not pusch_info.pusch_data.tb[0].crc) { + mac_metrics.rx_errors++; + } + mac_metrics.rx_brate += rx_harq_proc[pusch_info.pid].get_tbs(); + mac_metrics.rx_pkts++; + + return SRSRAN_SUCCESS; } srsenb::mac_ue_metrics_t get_metrics() diff --git a/test/phy/dummy_rx_harq_proc.h b/test/phy/dummy_rx_harq_proc.h index 9a5fe85a3..146213e70 100644 --- a/test/phy/dummy_rx_harq_proc.h +++ b/test/phy/dummy_rx_harq_proc.h @@ -20,12 +20,16 @@ #include #include -struct dummy_rx_harq_proc { - static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; +class dummy_rx_harq_proc +{ +private: srsran::byte_buffer_t data; srsran_softbuffer_rx_t softbuffer = {}; - std::atomic tbs = {0}; + uint32_t tbs = {0}; + bool first = true; + uint32_t ndi = 0; +public: dummy_rx_harq_proc() : data(0) { // Initialise softbuffer @@ -36,6 +40,25 @@ struct dummy_rx_harq_proc { } ~dummy_rx_harq_proc() { srsran_softbuffer_rx_free(&softbuffer); } + + srsran::byte_buffer_t& get_tb(uint32_t tbs_) + { + tbs = tbs_; + return data; + } + + srsran_softbuffer_rx_t& get_softbuffer(uint32_t ndi_) + { + if (ndi != ndi_ || first) { + srsran_softbuffer_rx_reset(&softbuffer); + ndi = ndi_; + first = false; + } + + return softbuffer; + } + + uint32_t get_tbs() const { return tbs; } }; #endif // SRSRAN_DUMMY_RX_HARQ_PROC_H diff --git a/test/phy/dummy_tx_harq_proc.h b/test/phy/dummy_tx_harq_proc.h index cbaddc8b5..19c0138dc 100644 --- a/test/phy/dummy_tx_harq_proc.h +++ b/test/phy/dummy_tx_harq_proc.h @@ -20,12 +20,16 @@ #include #include -struct dummy_tx_harq_proc { - static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC; +class dummy_tx_harq_proc +{ +private: srsran::byte_buffer_t data; srsran_softbuffer_tx_t softbuffer = {}; std::atomic tbs = {0}; + bool first = true; + uint32_t ndi = 0; +public: dummy_tx_harq_proc() { // Initialise softbuffer @@ -36,6 +40,25 @@ struct dummy_tx_harq_proc { } ~dummy_tx_harq_proc() { srsran_softbuffer_tx_free(&softbuffer); } + + srsran::byte_buffer_t& get_tb(uint32_t tbs_) + { + tbs = tbs_; + return data; + } + + srsran_softbuffer_tx_t& get_softbuffer(uint32_t ndi_) + { + if (ndi_ != ndi || first) { + srsran_softbuffer_tx_reset(&softbuffer); + ndi = ndi_; + first = false; + } + + return softbuffer; + } + + uint32_t get_tbs() const { return tbs; } }; #endif // SRSRAN_TX_DUMMY_HARQ_PROC_H diff --git a/test/phy/dummy_ue_stack.h b/test/phy/dummy_ue_stack.h new file mode 100644 index 000000000..0a3c51a3c --- /dev/null +++ b/test/phy/dummy_ue_stack.h @@ -0,0 +1,61 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_DUMMY_UE_STACK_H +#define SRSRAN_DUMMY_UE_STACK_H + +#include + +class ue_dummy_stack : public srsue::stack_interface_phy_nr +{ +private: + srsran_random_t random_gen = srsran_random_init(0x4567); + uint16_t rnti = 0; + bool valid = false; + + srsran::circular_array tx_harq_proc; + srsran::circular_array rx_harq_proc; + +public: + struct args_t { + uint16_t rnti = 0x1234; + }; + ue_dummy_stack(const args_t& args) : rnti(args.rnti) { valid = true; } + ~ue_dummy_stack() { srsran_random_free(random_gen); } + void in_sync() override {} + void out_of_sync() override {} + void run_tti(const uint32_t tti) override {} + int sf_indication(const uint32_t tti) override { return 0; } + sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; } + sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; } + void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) override + { + action->tb.enabled = true; + action->tb.softbuffer = &rx_harq_proc[grant.pid].get_softbuffer(grant.ndi); + } + void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) override {} + void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) override + { + if (action == nullptr) { + return; + } + action->tb.enabled = true; + action->tb.payload = &tx_harq_proc[grant.pid].get_tb(grant.tbs); + action->tb.softbuffer = &tx_harq_proc[grant.pid].get_softbuffer(grant.ndi); + srsran_random_byte_vector(random_gen, action->tb.payload->msg, grant.tbs / 8); + } + void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} + bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override { return false; } + bool is_valid() const { return valid; } +}; + +#endif // SRSRAN_DUMMY_UE_STACK_H diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index d1115f7cf..151105178 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -11,6 +11,7 @@ */ #include "dummy_gnb_stack.h" +#include "dummy_ue_stack.h" #include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/test_common.h" #include "test_bench.h" @@ -31,45 +32,6 @@ test_bench::args_t::args_t(int argc, char** argv) cell_list[0].pdcch = phy_cfg.pdcch; } -class ue_dummy_stack : public srsue::stack_interface_phy_nr -{ -private: - uint16_t rnti = 0; - bool valid = false; - - srsran::circular_array tx_harq_proc; - srsran::circular_array rx_harq_proc; - -public: - struct args_t { - uint16_t rnti = 0x1234; - }; - ue_dummy_stack(const args_t& args) : rnti(args.rnti) { valid = true; } - void in_sync() override {} - void out_of_sync() override {} - void run_tti(const uint32_t tti) override {} - int sf_indication(const uint32_t tti) override { return 0; } - sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; } - sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; } - void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) override - { - action->tb.enabled = true; - action->tb.softbuffer = &rx_harq_proc[grant.pid].softbuffer; - } - void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) override {} - void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) override - { - if (action == nullptr) { - return; - } - action->tb.enabled = true; - action->tb.payload = &rx_harq_proc[grant.pid].data; - } - void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} - bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override { return false; } - bool is_valid() const { return valid; } -}; - int main(int argc, char** argv) { srslog::init(); @@ -81,7 +43,7 @@ int main(int argc, char** argv) args.gnb_args.nof_phy_threads = 1; args.ue_args.log.id_preamble = " UE/"; args.ue_args.log.phy_level = "info"; - args.ue_args.log.phy_hex_limit = 0; + args.ue_args.log.phy_hex_limit = 1; args.ue_args.nof_phy_threads = 1; // Parse arguments @@ -134,18 +96,37 @@ int main(int argc, char** argv) if (mac_metrics.tx_pkts != 0) { pdsch_bler = (float)mac_metrics.tx_errors / (float)mac_metrics.tx_pkts; } - float pdsch_rate = 0.0f; + float pusch_bler = 0.0f; + if (mac_metrics.rx_pkts != 0) { + pusch_bler = (float)mac_metrics.rx_errors / (float)mac_metrics.rx_pkts; + } + float pdsch_shed_rate = 0.0f; if (mac_metrics.tx_pkts != 0) { - pdsch_rate = (float)mac_metrics.tx_brate / (float)mac_metrics.tx_pkts / 1000.0f; + pdsch_shed_rate = (float)mac_metrics.tx_brate / (float)mac_metrics.tx_pkts / 1000.0f; + } + float pusch_shed_rate = 0.0f; + if (mac_metrics.rx_pkts != 0) { + pusch_shed_rate = (float)mac_metrics.rx_brate / (float)mac_metrics.rx_pkts / 1000.0f; } srsran::console("PDSCH:\n"); - srsran::console(" Count: %d\n", mac_metrics.tx_pkts); - srsran::console(" BLER: %f\n", pdsch_bler); - srsran::console(" Rate: %f Mbps\n", pdsch_rate); + srsran::console(" Count: %d\n", mac_metrics.tx_pkts); + srsran::console(" BLER: %f\n", pdsch_bler); + srsran::console(" Sched Rate: %f Mbps\n", pdsch_shed_rate); + srsran::console(" Net Rate: %f Mbps\n", (1.0f - pdsch_bler) * pdsch_shed_rate); + srsran::console(" Retx Rate: %f Mbps\n", pdsch_bler * pdsch_shed_rate); + + srsran::console("\n"); + srsran::console("PUSCH:\n"); + srsran::console(" Count: %d\n", mac_metrics.rx_pkts); + srsran::console(" BLER: %f\n", pusch_bler); + srsran::console(" Sched Rate: %f Mbps\n", pusch_shed_rate); + srsran::console(" Net Rate: %f Mbps\n", (1.0f - pusch_bler) * pusch_shed_rate); + srsran::console(" Retx Rate: %f Mbps\n", pusch_bler * pusch_shed_rate); // Assert metrics TESTASSERT(mac_metrics.tx_errors == 0); + TESTASSERT(mac_metrics.rx_errors == 0); // If reached here, the test is successful return SRSRAN_SUCCESS;