From ee24b59924891b8fd4fa36e2654cff6db3a1cc21 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 20 Jan 2020 00:33:02 +0000 Subject: [PATCH] converted s1ap to new s1ap asn1 lib. Cleaned up bitstring packing/unpacking and bitstring types --- lib/include/srslte/asn1/asn1_utils.h | 240 +++++----------- lib/include/srslte/common/int_helpers.h | 2 +- .../srslte/interfaces/enb_interfaces.h | 8 +- lib/src/asn1/asn1_utils.cc | 227 +++++---------- srsenb/hdr/stack/rrc/rrc.h | 64 ++--- srsenb/hdr/stack/upper/s1ap.h | 34 +-- srsenb/src/stack/rrc/rrc.cc | 259 +++++++++-------- srsenb/src/stack/upper/s1ap.cc | 269 +++++++++--------- srsenb/test/upper/erab_setup_test.cc | 9 +- srsenb/test/upper/rrc_mobility_test.cc | 8 - srsenb/test/upper/test_helpers.h | 9 +- 11 files changed, 479 insertions(+), 650 deletions(-) diff --git a/lib/include/srslte/asn1/asn1_utils.h b/lib/include/srslte/asn1/asn1_utils.h index f2d461941..6a55ae376 100644 --- a/lib/include/srslte/asn1/asn1_utils.h +++ b/lib/include/srslte/asn1/asn1_utils.h @@ -224,7 +224,7 @@ public: using iterator = T*; using const_iterator = const T*; - bounded_array(uint32_t size_ = 0) : current_size(size_) {} + explicit bounded_array(uint32_t size_ = 0) : current_size(size_) {} static uint32_t capacity() { return MAX_N; } uint32_t size() const { return current_size; } T& operator[](uint32_t idx) { return data_[idx]; } @@ -691,227 +691,139 @@ private: using dyn_octstring = unbounded_octstring; /********************* - common bitstring + bitstring *********************/ -// helper functions common to all bitstring implementations -uint64_t bitstring_to_number(const uint8_t* ptr, uint32_t nbits); -void number_to_bitstring(uint8_t* ptr, uint64_t number, uint32_t nbits); -std::string bitstring_to_string(const uint8_t* ptr, uint32_t nbits); -inline bool bitstring_get(const uint8_t* ptr, uint32_t idx) +namespace bitstring_utils { +inline bool get(const uint8_t* ptr, uint32_t idx) { uint32_t byte_idx = idx / 8; uint32_t offset = idx % 8; return (ptr[byte_idx] & (1u << offset)) > 0; } -inline void bitstring_set(uint8_t* ptr, uint32_t idx, bool value) +inline void set(uint8_t* ptr, uint32_t idx, bool value) { uint32_t byte_idx = idx / 8; uint32_t offset = idx % 8; if (value) { ptr[byte_idx] |= (1u << offset); } else { - ptr[byte_idx] &= ((uint16_t)(1u << 8) - 1) - (1 << offset); + ptr[byte_idx] &= ((uint16_t)(1u << 8u) - 1u) - (1u << offset); } } +SRSASN_CODE +pack(bit_ref& bref, const uint8_t* data, uint32_t size, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned); +SRSASN_CODE unpack_length_prefix(uint32_t& len, bit_ref& bref, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned); +SRSASN_CODE unpack_bitfield(uint8_t* buf, bit_ref& bref, uint32_t n, uint32_t lb, uint32_t ub, bool is_aligned); -/********************* - fixed_bitstring -*********************/ +uint64_t to_number(const uint8_t* ptr, uint32_t nbits); +void from_number(uint8_t* ptr, uint64_t number, uint32_t nbits); +std::string to_string(const uint8_t* ptr, uint32_t nbits); -// fixed bitstring pack/unpack helpers -SRSASN_CODE pack_fixed_bitstring(bit_ref& bref, const uint8_t* buf, uint32_t nbits); -SRSASN_CODE pack_fixed_bitstring(bit_ref& bref, const uint8_t* buf, uint32_t nbits, bool ext); -SRSASN_CODE unpack_fixed_bitstring(uint8_t* buf, bit_ref& bref, uint32_t nbits); -SRSASN_CODE unpack_fixed_bitstring(uint8_t* buf, bool& ext, bit_ref& bref, uint32_t nbits); +} // namespace bitstring_utils -template -class fixed_bitstring +template +class bitstring { + using this_type = bitstring; + public: - using type_t = fixed_bitstring; - static const bool has_ext = Ext, is_aligned = Al; + static const uint32_t lb = LB, ub = UB; + static const bool has_ext = ext, is_aligned = aligned; - fixed_bitstring() { memset(&octets_[0], 0, nof_octets()); } - fixed_bitstring(const std::string& s) + explicit bitstring(uint32_t siz_ = lb) { resize(siz_); } + explicit bitstring(const std::string& s) { - if (s.size() != N) { - srsasn_log_print( - srslte::LOG_LEVEL_ERROR, "The provided string size=%zd does not match the bit string size=%d\n", s.size(), N); - } + resize(s.size()); memset(&octets_[0], 0, nof_octets()); - for (uint32_t i = 0; i < N; ++i) - this->set(N - i - 1, s[i] == '1'); - } - bool get(uint32_t idx) const { return bitstring_get(&octets_[0], idx); } - void set(uint32_t idx, bool value) { bitstring_set(&octets_[0], idx, value); } - bool operator==(const type_t& other) const { return octets_ == other.octets_; } - bool operator==(const char* other_str) const { return strlen(other_str) == N and (*this) == type_t(other_str); } - uint32_t nof_octets() const { return (uint32_t)ceilf(N / 8.0f); } - uint32_t length() const { return N; } - std::string to_string() const { return bitstring_to_string(&octets_[0], length()); } - uint64_t to_number() const { return bitstring_to_number(&octets_[0], length()); } - type_t& from_number(uint64_t val) - { - number_to_bitstring(&octets_[0], val, length()); - return *this; + for (uint32_t i = 0; i < s.size(); ++i) + set(s.size() - i - 1, s[i] == '1'); } - uint8_t* data() { return &octets_[0]; } - const uint8_t* data() const { return &octets_[0]; } - - SRSASN_CODE pack(bit_ref& bref) const { return pack_fixed_bitstring(bref, data(), N); } - SRSASN_CODE unpack(bit_ref& bref) { return unpack_fixed_bitstring(data(), bref, N); } - -private: - std::array octets_; // ceil(N/8.0) -}; -/********************* - bounded_bitstring -*********************/ - -namespace bitstring_utils { -SRSASN_CODE -pack(bit_ref& bref, const uint8_t* data, uint32_t size, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned); -SRSASN_CODE unpack_length_prefix(uint32_t& len, bit_ref& bref, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned); -SRSASN_CODE unpack_bitfield(uint8_t* buf, bit_ref& bref, uint32_t n, uint32_t lb, uint32_t ub, bool is_aligned); -SRSASN_CODE -unpack_fixed_bitstring(uint8_t* buf, bit_ref& bref, uint32_t nof_bits, bool has_ext = false, bool is_aligned = false); -} // namespace bitstring_utils + bool get(uint32_t idx) const { return bitstring_utils::get(data(), idx); } + void set(uint32_t idx, bool value) { bitstring_utils::set(data(), idx, value); } + uint32_t nof_octets() const { return ceil_frac(length(), 8u); } -template -class base_bitstring -{ -protected: - using derived_t = BitStringType; + const uint8_t* data() const { return &octets_[0]; } + uint8_t* data() { return &octets_[0]; } + uint32_t length() const { return nof_bits; } + void resize(uint32_t new_size) + { + nof_bits = new_size; + octets_.resize(nof_octets()); + memset(data(), 0, nof_octets()); // resize always resets content + } -public: - bool get(uint32_t idx) const { return bitstring_get(derived()->data(), idx); } - void set(uint32_t idx, bool value) { bitstring_set(derived()->data(), idx, value); } - uint32_t nof_octets() const { return ceil_frac(derived()->length(), 8u); } + // comparison + bool operator==(const this_type& other) const + { + return length() == other.length() and std::equal(data(), data() + nof_octets(), other.data()); + } + bool operator==(const char* other_str) const + { + return strlen(other_str) == length() and (*this) == this_type{}.from_string(other_str); + } - std::string to_string() const { return bitstring_to_string(derived()->data(), derived()->length()); } - derived_t& from_string(const std::string& s) + // string conversion + std::string to_string() const { return bitstring_utils::to_string(data(), length()); } + this_type& from_string(const std::string& s) { - if (s.size() < derived_t::lb or s.size() > derived_t::ub) { + if (s.size() < lb or s.size() > ub) { srsasn_log_print(srslte::LOG_LEVEL_ERROR, "The provided string size=%zd is not withing the bounds [%d, %d]\n", s.size(), - derived_t::lb, - derived_t::ub); + lb, + ub); } else { - derived()->resize(s.size()); + resize(s.size()); for (uint32_t i = 0; i < s.size(); ++i) { set(s.size() - i - 1, s[i] == '1'); } } - return *derived(); - } - uint64_t to_number() const { return bitstring_to_number(derived()->data(), derived()->length()); } - derived_t& from_number(uint64_t val) - { - uint32_t nof_bits = (uint32_t)ceilf(log2(val)); - if (nof_bits > derived()->length()) { - derived()->resize(nof_bits); - } - number_to_bitstring(derived()->data(), val, derived()->length()); - return *derived(); + return *this; } - bool operator==(const base_bitstring& other) const - { - return derived()->length() == other.derived()->length() and - std::equal(derived()->data(), derived()->data() + derived()->nof_octets(), other.derived()->data()); - } - bool operator==(const char* other_str) const + // number conversion + uint64_t to_number() const { return bitstring_utils::to_number(data(), length()); } + this_type& from_number(uint64_t val) { - return strlen(other_str) == derived()->length() and (*this) == derived_t{}.from_string(other_str); + auto nof_bits_ = (uint32_t)ceilf(log2(val)); + resize(std::max(nof_bits_, LB)); + bitstring_utils::from_number(data(), val, length()); + return *this; } + // packers / unpackers SRSASN_CODE pack(bit_ref& bref) const { - return bitstring_utils::pack(bref, - derived()->data(), - derived()->length(), - derived_t::lb, - derived_t::ub, - derived_t::has_ext, - derived_t::is_aligned); + return bitstring_utils::pack(bref, data(), length(), lb, ub, has_ext, is_aligned); } SRSASN_CODE unpack(bit_ref& bref) { // X.691, subclause 15.11 uint32_t nbits; - HANDLE_CODE(bitstring_utils::unpack_length_prefix( - nbits, bref, derived_t::lb, derived_t::ub, derived_t::has_ext, derived_t::is_aligned)); - derived()->resize(nbits); - return bitstring_utils::unpack_bitfield( - derived()->data(), bref, nbits, derived_t::lb, derived_t::ub, derived_t::is_aligned); + HANDLE_CODE(bitstring_utils::unpack_length_prefix(nbits, bref, lb, ub, has_ext, is_aligned)); + resize(nbits); + return bitstring_utils::unpack_bitfield(data(), bref, nbits, lb, ub, is_aligned); } private: - derived_t* derived() { return static_cast(this); } - const derived_t* derived() const { return static_cast(this); } + const static uint32_t stack_size = (UB == std::numeric_limits::max()) ? 4 : ceil_frac(ub, 8u); + ext_array octets_; + uint32_t nof_bits = 0; }; template -class bounded_bitstring : public base_bitstring > -{ - using base_t = base_bitstring >; - -public: - static const uint32_t lb = LB, ub = UB; - static const bool has_ext = ext, is_aligned = aligned; - - explicit bounded_bitstring(uint32_t siz_ = 0) { resize(siz_); } - - const uint8_t* data() const { return &octets_[0]; } - uint8_t* data() { return &octets_[0]; } - uint32_t length() const { return nof_bits; } - void resize(uint32_t new_size) - { - nof_bits = new_size; - octets_.resize(this->nof_octets()); - memset(data(), 0, this->nof_octets()); - } - -private: - bounded_array octets_; - uint32_t nof_bits = 0; -}; - -/********************* - dyn_bitstring -*********************/ +using bounded_bitstring = bitstring; template -class unbounded_bitstring : public base_bitstring > -{ - using base_t = base_bitstring >; - -public: - static const uint32_t lb = 0, ub = std::numeric_limits::max(); - static const bool has_ext = Ext, is_aligned = Al; - - explicit unbounded_bitstring(uint32_t siz_ = 0) { resize(siz_); } - - const uint8_t* data() const { return &octets_[0]; } - uint8_t* data() { return &octets_[0]; } - uint32_t length() const { return n_bits; } - void resize(uint32_t new_size) - { - n_bits = new_size; - octets_.resize(this->nof_octets()); - memset(data(), 0, this->nof_octets()); // resize always resets content - } - -private: - dyn_array octets_; - uint32_t n_bits; -}; +using unbounded_bitstring = bitstring<0, std::numeric_limits::max(), Ext, Al>; using dyn_bitstring = unbounded_bitstring; +template +using fixed_bitstring = bitstring; + /********************* fixed sequence of *********************/ @@ -953,7 +865,7 @@ SRSASN_CODE unpack_fixed_seq_of(T* item_array, bit_ref& bref, uint32_t nof_items template struct FixedSeqOfPacker { FixedSeqOfPacker(uint32_t nof_items_, ItemPacker packer_) : nof_items(nof_items_), packer(packer_) {} - FixedSeqOfPacker(uint32_t nof_items_) : nof_items(nof_items_), packer(Packer()) {} + explicit FixedSeqOfPacker(uint32_t nof_items_) : nof_items(nof_items_), packer(Packer()) {} template SRSASN_CODE pack(bit_ref& bref, const T* topack) { @@ -1080,7 +992,7 @@ public: void resize(std::size_t newsize) { str.resize(newsize); } std::size_t size() const { return str.size(); } std::string to_string() const { return str; } - void from_string(std::string s) { str = std::move(s); } + void from_string(const std::string& s) { str = s; } private: std::string str; diff --git a/lib/include/srslte/common/int_helpers.h b/lib/include/srslte/common/int_helpers.h index ea7e180ac..8b3329c6e 100644 --- a/lib/include/srslte/common/int_helpers.h +++ b/lib/include/srslte/common/int_helpers.h @@ -28,7 +28,7 @@ namespace srslte { * Safe conversions between byte buffers and integer types. * Note: these don't perform endian conversion - use e.g. htonl/ntohl if required *****************************************************************************/ -inline void uint8_to_uint32(uint8_t* buf, uint32_t* i) +inline void uint8_to_uint32(const uint8_t* buf, uint32_t* i) { *i = (uint32_t)buf[0] << 24 | (uint32_t)buf[1] << 16 | (uint32_t)buf[2] << 8 | (uint32_t)buf[3]; } diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 81626c6be..abf164119 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -268,11 +268,11 @@ class rrc_interface_s1ap public: virtual void write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu) = 0; virtual void release_complete(uint16_t rnti) = 0; - virtual bool setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT* msg) = 0; - virtual bool modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT* msg) = 0; - virtual bool setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT* msg) = 0; + virtual bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) = 0; + virtual bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) = 0; + virtual bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::e_rab_setup_request_s& msg) = 0; virtual bool release_erabs(uint32_t rnti) = 0; - virtual void add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID) = 0; + virtual void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& ue_paging_id) = 0; virtual void ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique_byte_buffer_t container) = 0; }; diff --git a/lib/src/asn1/asn1_utils.cc b/lib/src/asn1/asn1_utils.cc index fa50c16d2..d006a18e6 100644 --- a/lib/src/asn1/asn1_utils.cc +++ b/lib/src/asn1/asn1_utils.cc @@ -991,130 +991,20 @@ template class unbounded_octstring; template class unbounded_octstring; /********************* - bitstring -*********************/ - -SRSASN_CODE pack_common_bitstring(bit_ref& bref, const uint8_t* buf, uint32_t nbits) -{ - if (nbits == 0) { - srsasn_log_print(LOG_LEVEL_ERROR, "Invalid bitstring size=%d\n", nbits); - return SRSASN_ERROR_ENCODE_FAIL; - } - uint32_t n_octs = (uint32_t)ceilf(nbits / 8.0f); - uint32_t offset = ((nbits - 1) % 8) + 1; - HANDLE_CODE(bref.pack(buf[n_octs - 1], offset)); - for (uint32_t i = 1; i < n_octs; ++i) { - HANDLE_CODE(bref.pack(buf[n_octs - 1 - i], 8)); - } - return SRSASN_SUCCESS; -} - -SRSASN_CODE unpack_common_bitstring(uint8_t* buf, bit_ref& bref, uint32_t nbits) -{ - if (nbits == 0) { - srsasn_log_print(LOG_LEVEL_ERROR, "Invalid bitstring size=%d\n", nbits); - return SRSASN_ERROR_DECODE_FAIL; - } - uint32_t n_octs = (uint32_t)ceilf(nbits / 8.0f); - uint32_t offset = ((nbits - 1) % 8) + 1; - HANDLE_CODE(bref.unpack(buf[n_octs - 1], offset)); - for (uint32_t i = 1; i < n_octs; ++i) { - HANDLE_CODE(bref.unpack(buf[n_octs - 1 - i], 8)); - } - return SRSASN_SUCCESS; -} - -uint64_t bitstring_to_number(const uint8_t* ptr, uint32_t nbits) -{ - if (nbits > 64) { - srsasn_log_print(LOG_LEVEL_ERROR, "bitstring of size=%d does not fit in an uint64_t\n", nbits); - return 0; - } - uint64_t val = 0; - uint32_t nof_bytes = (uint32_t)ceilf(nbits / 8.0f); - for (uint32_t i = 0; i < nof_bytes; ++i) { - val += ptr[i] << (i * 8); - } - return val; -} -void number_to_bitstring(uint8_t* ptr, uint64_t number, uint32_t nbits) -{ - if (nbits > 64) { - srsasn_log_print(LOG_LEVEL_ERROR, "bitstring of size=%d does not fit in an uint64_t\n", nbits); - return; - } - uint32_t nof_bytes = (uint32_t)ceilf(nbits / 8.0f); - for (uint32_t i = 0; i < nof_bytes; ++i) { - ptr[i] = (number >> (i * 8)) & 0xFF; - } - uint32_t offset = nbits % 8; // clean up any extra set bit - if (offset > 0) { - ptr[nof_bytes - 1] &= (uint8_t)((1 << offset) - 1); - } -} - -std::string bitstring_to_string(const uint8_t* ptr, uint32_t nbits) -{ - std::string str(nbits, '\0'); - for (uint32_t i = 0; i < nbits; ++i) { - str[i] = bitstring_get(ptr, nbits - 1 - i) ? '1' : '0'; - } - return str; -} - -/********************* - fixed_bitstring -*********************/ - -SRSASN_CODE pack_fixed_bitstring(bit_ref& bref, const uint8_t* buf, uint32_t nbits) -{ - // if(nbits > 16) { // X.691 Section 15 - // bref.align_bytes_zero(); - // } - return pack_common_bitstring(bref, buf, nbits); - // if(nbits > 16) { // X.691 Section 15 - // bref.align_bytes_zero(); - // } -} - -SRSASN_CODE pack_fixed_bitstring(bit_ref& bref, const uint8_t* buf, uint32_t nbits, bool ext) -{ - HANDLE_CODE(pack_unsupported_ext_flag(bref, ext)); - HANDLE_CODE(pack_fixed_bitstring(bref, buf, nbits)); - return SRSASN_SUCCESS; -} - -SRSASN_CODE unpack_fixed_bitstring(uint8_t* buf, bit_ref& bref, uint32_t nbits) -{ - // if(nbits > 16) { // X.691 Section 15 - // bref.align_bytes_zero(); - // } - return unpack_common_bitstring(buf, bref, nbits); - // if(nbits > 16) { // X.691 Section 15 - // bref.align_bytes_zero(); - // } -} - -SRSASN_CODE unpack_fixed_bitstring(uint8_t* buf, bool& ext, bit_ref& bref, uint32_t nbits) -{ - HANDLE_CODE(unpack_unsupported_ext_flag(ext, bref)); - HANDLE_CODE(unpack_fixed_bitstring(buf, bref, nbits)); - return SRSASN_SUCCESS; -} - -/********************* - common bitstring + bitstring *********************/ namespace bitstring_utils { -SRSASN_CODE pack_length_prefix(bit_ref& bref, - const uint8_t* data, - uint32_t len, - uint32_t lb, - uint32_t ub, - bool has_ext, - bool is_aligned) +/** + * Pack ASN1 bitstring length prefix. Accommodates for cases: fixed/unbounded/bounded, aligned/unaligned, with/out ext + */ +SRSASN_CODE pack_length_prefix(bit_ref& bref, + uint32_t len, + uint32_t lb = 0, + uint32_t ub = std::numeric_limits::max(), + bool has_ext = false, + bool is_aligned = false) { if (has_ext and ub == std::numeric_limits::max()) { srsasn_log_print(LOG_LEVEL_ERROR, "has extension marker but it is an unbounded prefix size\n"); @@ -1126,21 +1016,22 @@ SRSASN_CODE pack_length_prefix(bit_ref& bref, return SRSASN_ERROR_ENCODE_FAIL; } + // encode ext bit if (has_ext) { HANDLE_CODE(bref.pack(not within_bounds, 1)); } + // do not encode prefix if fixed size if (lb == ub and within_bounds) { - // do not encode prefix if fixed size return SRSASN_SUCCESS; } + // pack as unbounded if unbounded bitstring or ext is active if (ub == std::numeric_limits::max() or not within_bounds) { - // pack as unbounded return pack_length(bref, len); } - // pack as bounded + // pack as bounded bitstring uint32_t len_bits = (uint32_t)ceilf(log2(ub - lb)); HANDLE_CODE(bref.pack(len - lb, len_bits)); if (is_aligned) { @@ -1149,23 +1040,36 @@ SRSASN_CODE pack_length_prefix(bit_ref& bref, return SRSASN_SUCCESS; } -SRSASN_CODE -pack(bit_ref& bref, const uint8_t* data, uint32_t len, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned) +SRSASN_CODE pack_bitfield(bit_ref& bref, const uint8_t* buf, uint32_t nbits) { - if ((len < lb or len > ub) and not has_ext) { - srsasn_log_print(LOG_LEVEL_ERROR, "bitstring length=%d is not within bounds [%d, %d]\n", len, lb, ub); + if (nbits == 0) { + srsasn_log_print(LOG_LEVEL_ERROR, "Invalid bitstring size=%d\n", nbits); return SRSASN_ERROR_ENCODE_FAIL; } + uint32_t n_octs = ceil_frac(nbits, 8u); + uint32_t offset = ((nbits - 1) % 8) + 1; + HANDLE_CODE(bref.pack(buf[n_octs - 1], offset)); + for (uint32_t i = 1; i < n_octs; ++i) { + HANDLE_CODE(bref.pack(buf[n_octs - 1 - i], 8)); + } + return SRSASN_SUCCESS; +} - // encode prefix - HANDLE_CODE(bitstring_utils::pack_length_prefix(bref, data, len, lb, ub, has_ext, is_aligned)); - - // encode bitstring - return pack_common_bitstring(bref, data, len); +/** + * Pack ASN1 bitstring. Accommodates for cases: fixed/unbounded/bounded, aligned/unaligned, with/out ext + */ +SRSASN_CODE +pack(bit_ref& bref, const uint8_t* data, uint32_t len, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned) +{ + HANDLE_CODE(bitstring_utils::pack_length_prefix(bref, len, lb, ub, has_ext, is_aligned)); + return pack_bitfield(bref, data, len); } // Unpack prefix, excluding ext bit +/** + * Unpack ASN1 bitstring length prefix. Accommodates for cases: fixed/unbounded/bounded, aligned/unaligned, with/out ext + */ SRSASN_CODE unpack_length_prefix(uint32_t& len, bit_ref& bref, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned) { bool ext = false; @@ -1198,6 +1102,14 @@ SRSASN_CODE unpack_length_prefix(uint32_t& len, bit_ref& bref, uint32_t lb, uint // for both fixed, constrained and unconstrained scenarios SRSASN_CODE unpack_bitfield(uint8_t* buf, bit_ref& bref, uint32_t n, uint32_t lb, uint32_t ub, bool is_aligned) { + if (n > ASN_64K) { + srsasn_log_print(LOG_LEVEL_ERROR, "bitstrings longer than 64K not supported\n"); + return SRSASN_ERROR_DECODE_FAIL; + } + if (n == 0) { + // empty bit string + return SRSASN_SUCCESS; + } if (is_aligned and (lb != ub or ub > 16)) { bref.align_bytes(); } @@ -1211,28 +1123,43 @@ SRSASN_CODE unpack_bitfield(uint8_t* buf, bit_ref& bref, uint32_t n, uint32_t lb return SRSASN_SUCCESS; } -// fixed length case -SRSASN_CODE unpack_fixed_bitstring(uint8_t* buf, bit_ref& bref, uint32_t nof_bits, bool has_ext, bool is_aligned) +void from_number(uint8_t* ptr, uint64_t number, uint32_t nbits) { - if (has_ext) { - bool ext; - HANDLE_CODE(bref.unpack(ext, 1)); - if (ext) { - srsasn_log_print(LOG_LEVEL_ERROR, "bitstrings longer than 64K not supported\n"); - // TODO: fixed bitstrings have to become resizeable - // return unpack_default_bitstring(buf, bref, nof_bits, nof_bits, is_aligned); - } + if (nbits > 64) { + srsasn_log_print(LOG_LEVEL_ERROR, "bitstring of size=%d does not fit in an uint64_t\n", nbits); + return; } - if (nof_bits == 0) { - // empty bit string - return SRSASN_SUCCESS; + uint32_t nof_bytes = (uint32_t)ceilf(nbits / 8.0f); + for (uint32_t i = 0; i < nof_bytes; ++i) { + ptr[i] = (number >> (i * 8u)) & 0xFFu; } - if (nof_bits <= ASN_64K) { - return unpack_bitfield(buf, bref, nof_bits, nof_bits, nof_bits, is_aligned); - } else { - srsasn_log_print(LOG_LEVEL_ERROR, "bitstrings longer than 64K not supported\n"); - return SRSASN_ERROR_DECODE_FAIL; + uint32_t offset = nbits % 8; // clean up any extra set bit + if (offset > 0) { + ptr[nof_bytes - 1] &= (uint8_t)((1 << offset) - 1); + } +} + +std::string to_string(const uint8_t* ptr, uint32_t nbits) +{ + std::string str(nbits, '\0'); + for (uint32_t i = 0; i < nbits; ++i) { + str[i] = bitstring_utils::get(ptr, nbits - 1 - i) ? '1' : '0'; + } + return str; +} + +uint64_t to_number(const uint8_t* ptr, uint32_t nbits) +{ + if (nbits > 64) { + srsasn_log_print(LOG_LEVEL_ERROR, "bitstring of size=%d does not fit in an uint64_t\n", nbits); + return 0; } + uint64_t val = 0; + uint32_t nof_bytes = (uint32_t)ceilf(nbits / 8.0f); + for (uint32_t i = 0; i < nof_bytes; ++i) { + val += ptr[i] << (i * 8); + } + return val; } } // namespace bitstring_utils diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 30d1db23f..5cb3ba7d7 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -175,11 +175,11 @@ public: // rrc_interface_s1ap void write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu) override; void release_complete(uint16_t rnti) override; - bool setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT* msg) override; - bool modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT* msg) override; - bool setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT* msg) override; + bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) override; + bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) override; + bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::e_rab_setup_request_s& msg) override; bool release_erabs(uint32_t rnti) override; - void add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID) override; + void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& UEPagingID) override; void ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique_byte_buffer_t rrc_container) override; // rrc_interface_pdcp @@ -212,9 +212,9 @@ public: nulltype } activity_timeout_type_t; std::string to_string(const activity_timeout_type_t& type); - void set_activity_timeout(const activity_timeout_type_t type); - void set_activity(); - void activity_timer_expired(); + void set_activity_timeout(const activity_timeout_type_t type); + void set_activity(); + void activity_timer_expired(); uint32_t rl_failure(); @@ -226,7 +226,7 @@ public: void send_connection_release(); void send_connection_reest_rej(); void send_connection_reconf(srslte::unique_byte_buffer_t sdu); - void send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e); + void send_connection_reconf_new_bearer(const asn1::s1ap::e_rab_to_be_setup_list_bearer_su_req_l& e); void send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu); void send_security_mode_command(); void send_ue_cap_enquiry(); @@ -240,24 +240,24 @@ public: void handle_security_mode_failure(asn1::rrc::security_mode_fail_s* msg); bool handle_ue_cap_info(asn1::rrc::ue_cap_info_s* msg); - void set_bitrates(LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT* rates); - void set_security_capabilities(LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT* caps); - void set_security_key(uint8_t* key, uint32_t length); - - bool setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT* e); - bool setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e); - void setup_erab(uint8_t id, - LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT* qos, - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT* addr, - uint32_t teid_out, - LIBLTE_S1AP_NAS_PDU_STRUCT* nas_pdu); + void set_bitrates(const asn1::s1ap::ue_aggregate_maximum_bitrate_s& rates); + void set_security_capabilities(const asn1::s1ap::ue_security_cap_s& caps); + void set_security_key(const asn1::fixed_bitstring<256, false, true>& key); + + bool setup_erabs(const asn1::s1ap::e_rab_to_be_setup_list_ctxt_su_req_l& e); + bool setup_erabs(const asn1::s1ap::e_rab_to_be_setup_list_bearer_su_req_l& e); + void setup_erab(uint8_t id, + const asn1::s1ap::e_rab_level_qo_sparams_s& qos, + const asn1::bounded_bitstring<1, 160, true, true>& addr, + uint32_t teid_out, + const asn1::unbounded_octstring* nas_pdu); bool release_erabs(); // handover void handle_ho_preparation_complete(bool is_success, srslte::unique_byte_buffer_t container); void notify_s1ap_ue_ctxt_setup_complete(); - void notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e); + void notify_s1ap_ue_erab_setup_response(const asn1::s1ap::e_rab_to_be_setup_list_bearer_su_req_l& e); int sr_allocate(uint32_t period, uint8_t* I_sr, uint16_t* N_pucch_sr); void sr_get(uint8_t* I_sr, uint16_t* N_pucch_sr); @@ -283,7 +283,7 @@ public: private: // args - srslte::byte_buffer_pool* pool = nullptr; + srslte::byte_buffer_pool* pool = nullptr; srslte::timer_handler::unique_timer activity_timer; // cached for ease of context transfer @@ -314,17 +314,17 @@ public: srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; - LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT bitrates; - LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT security_capabilities; - bool eutra_capabilities_unpacked = false; - asn1::rrc::ue_eutra_cap_s eutra_capabilities; + asn1::s1ap::ue_aggregate_maximum_bitrate_s bitrates; + asn1::s1ap::ue_security_cap_s security_capabilities; + bool eutra_capabilities_unpacked = false; + asn1::rrc::ue_eutra_cap_s eutra_capabilities; typedef struct { - uint8_t id; - LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT qos_params; - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT address; - uint32_t teid_out; - uint32_t teid_in; + uint8_t id; + asn1::s1ap::e_rab_level_qo_sparams_s qos_params; + asn1::bounded_bitstring<1, 160, true, true> address; + uint32_t teid_out; + uint32_t teid_in; } erab_t; std::map erabs; int sr_sched_sf_idx = 0; @@ -355,8 +355,8 @@ private: srslte::log* rrc_log = nullptr; // state - std::map > users; // NOTE: has to have fixed addr - std::map pending_paging; + std::map > users; // NOTE: has to have fixed addr + std::map pending_paging; std::vector sib_buffer; diff --git a/srsenb/hdr/stack/upper/s1ap.h b/srsenb/hdr/stack/upper/s1ap.h index 64901a101..680c9ca06 100644 --- a/srsenb/hdr/stack/upper/s1ap.h +++ b/srsenb/hdr/stack/upper/s1ap.h @@ -109,7 +109,7 @@ private: LIBLTE_S1AP_TAI_STRUCT tai; LIBLTE_S1AP_EUTRAN_CGI_STRUCT eutran_cgi; - LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT s1setupresponse; + asn1::s1ap::s1_setup_resp_s s1setupresponse; void build_tai_cgi(); bool connect_mme(); @@ -117,19 +117,19 @@ private: bool sctp_send_s1ap_pdu(const asn1::s1ap::s1ap_pdu_c& tx_pdu, uint32_t rnti, const char* procedure_name); bool handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu); - bool handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* msg); - bool handle_successfuloutcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* msg); - bool handle_unsuccessfuloutcome(LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT* msg); - bool handle_paging(LIBLTE_S1AP_MESSAGE_PAGING_STRUCT* msg); + bool handle_initiatingmessage(const asn1::s1ap::init_msg_s& msg); + bool handle_successfuloutcome(const asn1::s1ap::successful_outcome_s& msg); + bool handle_unsuccessfuloutcome(const asn1::s1ap::unsuccessful_outcome_s& msg); + bool handle_paging(const asn1::s1ap::paging_s& msg); - bool handle_s1setupresponse(LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* msg); + bool handle_s1setupresponse(const asn1::s1ap::s1_setup_resp_s& msg); - bool handle_dlnastransport(LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT* msg); - bool handle_initialctxtsetuprequest(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT* msg); - bool handle_uectxtreleasecommand(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMAND_STRUCT* msg); - bool handle_s1setupfailure(LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT* msg); - bool handle_erabsetuprequest(LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT* msg); - bool handle_uecontextmodifyrequest(LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT* msg); + bool handle_dlnastransport(const asn1::s1ap::dl_nas_transport_s& msg); + bool handle_initialctxtsetuprequest(const asn1::s1ap::init_context_setup_request_s& msg); + bool handle_uectxtreleasecommand(const asn1::s1ap::ue_context_release_cmd_s& msg); + bool handle_s1setupfailure(const asn1::s1ap::s1_setup_fail_s& msg); + bool handle_erabsetuprequest(const asn1::s1ap::e_rab_setup_request_s& msg); + bool handle_uecontextmodifyrequest(const asn1::s1ap::ue_context_mod_request_s& msg); bool send_initialuemessage(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, @@ -151,12 +151,12 @@ private: uint32_t target_eci, srslte::plmn_id_t target_plmn, srslte::unique_byte_buffer_t rrc_container) override; - bool handle_hopreparationfailure(LIBLTE_S1AP_MESSAGE_HANDOVERPREPARATIONFAILURE_STRUCT* msg); - bool handle_s1hocommand(LIBLTE_S1AP_MESSAGE_HANDOVERCOMMAND_STRUCT& msg); + bool handle_hopreparationfailure(const asn1::s1ap::ho_prep_fail_s& msg); + bool handle_s1hocommand(const asn1::s1ap::ho_cmd_s& msg); bool send_enb_status_transfer_proc(uint16_t rnti, std::vector& bearer_status_list) override; bool find_mme_ue_id(uint32_t mme_ue_id, uint16_t* rnti, uint32_t* enb_ue_id); - std::string get_cause(const LIBLTE_S1AP_CAUSE_STRUCT* c); + std::string get_cause(const asn1::s1ap::cause_c& c); // UE-specific data and procedures struct ue { @@ -171,8 +171,8 @@ private: init(uint32_t target_eci_, srslte::plmn_id_t target_plmn_, srslte::unique_byte_buffer_t rrc_container); srslte::proc_outcome_t step() { return srslte::proc_outcome_t::yield; } srslte::proc_outcome_t react(ts1_reloc_prep_expired e); - srslte::proc_outcome_t react(const LIBLTE_S1AP_MESSAGE_HANDOVERPREPARATIONFAILURE_STRUCT& msg); - srslte::proc_outcome_t react(LIBLTE_S1AP_MESSAGE_HANDOVERCOMMAND_STRUCT& msg); + srslte::proc_outcome_t react(const asn1::s1ap::ho_prep_fail_s& msg); + srslte::proc_outcome_t react(const asn1::s1ap::ho_cmd_s& msg); void then(const srslte::proc_state_t& result); const char* name() { return "HandoverPreparation"; } diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 06e0c8254..f7364694f 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -55,14 +55,14 @@ void rrc::init(rrc_cfg_t* cfg_, srslte::timer_handler* timers_, srslte::log* log_rrc) { - phy = phy_; - mac = mac_; - rlc = rlc_; - pdcp = pdcp_; - gtpu = gtpu_; - s1ap = s1ap_; - rrc_log = log_rrc; - timers = timers_; + phy = phy_; + mac = mac_; + rlc = rlc_; + pdcp = pdcp_; + gtpu = gtpu_; + s1ap = s1ap_; + rrc_log = log_rrc; + timers = timers_; pool = srslte::byte_buffer_pool::get_instance(); @@ -111,7 +111,7 @@ void rrc::get_metrics(rrc_metrics_t& m) pthread_mutex_lock(&user_mutex); m.n_ues = 0; for (auto iter = users.begin(); m.n_ues < ENB_METRICS_MAX_USERS && iter != users.end(); ++iter) { - ue* u = iter->second.get(); + ue* u = iter->second.get(); m.ues[m.n_ues++].state = u->get_state(); } pthread_mutex_unlock(&user_mutex); @@ -279,7 +279,7 @@ void rrc::release_complete(uint16_t rnti) rx_pdu_queue.push(std::move(p)); } -bool rrc::setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT* msg) +bool rrc::setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) { pthread_mutex_lock(&user_mutex); @@ -292,58 +292,56 @@ bool rrc::setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRE return false; } - if (msg->AdditionalCSFallbackIndicator_present) { + if (msg.protocol_ies.add_cs_fallback_ind_present) { rrc_log->warning("Not handling AdditionalCSFallbackIndicator\n"); } - if (msg->CSGMembershipStatus_present) { + if (msg.protocol_ies.csg_membership_status_present) { rrc_log->warning("Not handling CSGMembershipStatus\n"); } - if (msg->GUMMEI_ID_present) { + if (msg.protocol_ies.gummei_id_present) { rrc_log->warning("Not handling GUMMEI_ID\n"); } - if (msg->HandoverRestrictionList_present) { + if (msg.protocol_ies.ho_restrict_list_present) { rrc_log->warning("Not handling HandoverRestrictionList\n"); } - if (msg->ManagementBasedMDTAllowed_present) { + if (msg.protocol_ies.management_based_mdt_allowed_present) { rrc_log->warning("Not handling ManagementBasedMDTAllowed\n"); } - if (msg->ManagementBasedMDTPLMNList_present) { + if (msg.protocol_ies.management_based_mdtplmn_list_present) { rrc_log->warning("Not handling ManagementBasedMDTPLMNList\n"); } - if (msg->MME_UE_S1AP_ID_2_present) { + if (msg.protocol_ies.mme_ue_s1ap_id_minus2_present) { rrc_log->warning("Not handling MME_UE_S1AP_ID_2\n"); } - if (msg->RegisteredLAI_present) { + if (msg.protocol_ies.registered_lai_present) { rrc_log->warning("Not handling RegisteredLAI\n"); } - if (msg->SRVCCOperationPossible_present) { + if (msg.protocol_ies.srvcc_operation_possible_present) { rrc_log->warning("Not handling SRVCCOperationPossible\n"); } - if (msg->SubscriberProfileIDforRFP_present) { + if (msg.protocol_ies.subscriber_profile_idfor_rfp_present) { rrc_log->warning("Not handling SubscriberProfileIDforRFP\n"); } - if (msg->TraceActivation_present) { + if (msg.protocol_ies.trace_activation_present) { rrc_log->warning("Not handling TraceActivation\n"); } - if (msg->UERadioCapability_present) { + if (msg.protocol_ies.ue_radio_cap_present) { rrc_log->warning("Not handling UERadioCapability\n"); } // UEAggregateMaximumBitrate - user_it->second->set_bitrates(&msg->uEaggregateMaximumBitrate); + user_it->second->set_bitrates(msg.protocol_ies.ueaggregate_maximum_bitrate.value); // UESecurityCapabilities - user_it->second->set_security_capabilities(&msg->UESecurityCapabilities); + user_it->second->set_security_capabilities(msg.protocol_ies.ue_security_cap.value); // SecurityKey - uint8_t key[32]; - liblte_pack(msg->SecurityKey.buffer, LIBLTE_S1AP_SECURITYKEY_BIT_STRING_LEN, key); - user_it->second->set_security_key(key, LIBLTE_S1AP_SECURITYKEY_BIT_STRING_LEN / 8); + user_it->second->set_security_key(msg.protocol_ies.security_key.value); // CSFB - if (msg->CSFallbackIndicator_present) { - if (msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_REQUIRED || - msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_HIGH_PRIORITY) { + if (msg.protocol_ies.cs_fallback_ind_present) { + if (msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_required or + msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_high_prio) { user_it->second->is_csfb = true; } } @@ -352,14 +350,14 @@ bool rrc::setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRE user_it->second->send_security_mode_command(); // Setup E-RABs - user_it->second->setup_erabs(&msg->E_RABToBeSetupListCtxtSUReq); + user_it->second->setup_erabs(msg.protocol_ies.e_rab_to_be_setup_list_ctxt_su_req.value); pthread_mutex_unlock(&user_mutex); return true; } -bool rrc::modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT* msg) +bool rrc::modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) { bool err = false; pthread_mutex_lock(&user_mutex); @@ -373,27 +371,27 @@ bool rrc::modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIO return false; } - if (msg->CSFallbackIndicator_present) { - if (msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_REQUIRED || - msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_HIGH_PRIORITY) { + if (msg.protocol_ies.cs_fallback_ind_present) { + if (msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_required || + msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_high_prio) { /* Remember that we are in a CSFB right now */ user_it->second->is_csfb = true; } } - if (msg->AdditionalCSFallbackIndicator_present) { + if (msg.protocol_ies.add_cs_fallback_ind_present) { rrc_log->warning("Not handling AdditionalCSFallbackIndicator\n"); err = true; } - if (msg->CSGMembershipStatus_present) { + if (msg.protocol_ies.csg_membership_status_present) { rrc_log->warning("Not handling CSGMembershipStatus\n"); err = true; } - if (msg->RegisteredLAI_present) { + if (msg.protocol_ies.registered_lai_present) { rrc_log->warning("Not handling RegisteredLAI\n"); err = true; } - if (msg->SubscriberProfileIDforRFP_present) { + if (msg.protocol_ies.subscriber_profile_idfor_rfp_present) { rrc_log->warning("Not handling SubscriberProfileIDforRFP\n"); err = true; } @@ -405,20 +403,18 @@ bool rrc::modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIO } // UEAggregateMaximumBitrate - if (msg->uEaggregateMaximumBitrate_present) { - user_it->second->set_bitrates(&msg->uEaggregateMaximumBitrate); + if (msg.protocol_ies.ueaggregate_maximum_bitrate_present) { + user_it->second->set_bitrates(msg.protocol_ies.ueaggregate_maximum_bitrate.value); } // UESecurityCapabilities - if (msg->UESecurityCapabilities_present) { - user_it->second->set_security_capabilities(&msg->UESecurityCapabilities); + if (msg.protocol_ies.ue_security_cap_present) { + user_it->second->set_security_capabilities(msg.protocol_ies.ue_security_cap.value); } // SecurityKey - if (msg->SecurityKey_present) { - uint8_t key[32]; - liblte_pack(msg->SecurityKey.buffer, LIBLTE_S1AP_SECURITYKEY_BIT_STRING_LEN, key); - user_it->second->set_security_key(key, LIBLTE_S1AP_SECURITYKEY_BIT_STRING_LEN / 8); + if (msg.protocol_ies.security_key_present) { + user_it->second->set_security_key(msg.protocol_ies.security_key.value); // Send RRC security mode command ?? user_it->second->send_security_mode_command(); @@ -429,7 +425,7 @@ bool rrc::modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIO return true; } -bool rrc::setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT* msg) +bool rrc::setup_ue_erabs(uint16_t rnti, const asn1::s1ap::e_rab_setup_request_s& msg) { pthread_mutex_lock(&user_mutex); @@ -442,13 +438,13 @@ bool rrc::setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_ST return false; } - if (msg->uEaggregateMaximumBitrate_present) { + if (msg.protocol_ies.ueaggregate_maximum_bitrate_present) { // UEAggregateMaximumBitrate - user_it->second->set_bitrates(&msg->uEaggregateMaximumBitrate); + user_it->second->set_bitrates(msg.protocol_ies.ueaggregate_maximum_bitrate.value); } // Setup E-RABs - user_it->second->setup_erabs(&msg->E_RABToBeSetupListBearerSUReq); + user_it->second->setup_erabs(msg.protocol_ies.e_rab_to_be_setup_list_bearer_su_req.value); pthread_mutex_unlock(&user_mutex); @@ -478,7 +474,7 @@ bool rrc::release_erabs(uint32_t rnti) than user map *******************************************************************************/ -void rrc::add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID) +void rrc::add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& UEPagingID) { pthread_mutex_lock(&paging_mutex); if (pending_paging.count(ueid) == 0) { @@ -519,9 +515,9 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t* payload_len) if (n >= ASN1_RRC_MAX_PAGE_REC) { break; } - LIBLTE_S1AP_UEPAGINGID_STRUCT u = (LIBLTE_S1AP_UEPAGINGID_STRUCT)item.second; - uint32_t ueid = ((uint32_t)item.first) % 1024; - uint32_t i_s = (ueid / N) % Ns; + asn1::s1ap::ue_paging_id_c& u = item.second; + uint32_t ueid = ((uint32_t)item.first) % 1024; + uint32_t i_s = (ueid / N) % Ns; if ((sfn % T) != (T / N) * (ueid % N)) { continue; @@ -536,17 +532,18 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t* payload_len) if ((uint32_t)sf_idx == (tti % 10)) { paging_rec->paging_record_list_present = true; paging_record_s paging_elem; - if (u.choice_type == LIBLTE_S1AP_UEPAGINGID_CHOICE_IMSI) { + if (u.type().value == asn1::s1ap::ue_paging_id_c::types_opts::imsi) { paging_elem.ue_id.set_imsi(); - paging_elem.ue_id.imsi().resize(u.choice.iMSI.n_octets); - memcpy(paging_elem.ue_id.imsi().data(), u.choice.iMSI.buffer, u.choice.iMSI.n_octets); + paging_elem.ue_id.imsi().resize(u.imsi().size()); + memcpy(paging_elem.ue_id.imsi().data(), u.imsi().data(), u.imsi().size()); rrc_log->console("Warning IMSI paging not tested\n"); } else { paging_elem.ue_id.set_s_tmsi(); - paging_elem.ue_id.s_tmsi().mmec.from_number(u.choice.s_TMSI.mMEC.buffer[0]); - uint32_t m_tmsi = 0; - for (int i = 0; i < LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN; i++) { - m_tmsi |= u.choice.s_TMSI.m_TMSI.buffer[i] << (8u * (LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN - i - 1)); + paging_elem.ue_id.s_tmsi().mmec.from_number(u.s_tmsi().mmec[0]); + uint32_t m_tmsi = 0; + uint32_t nof_octets = u.s_tmsi().m_tmsi.size(); + for (uint32_t i = 0; i < nof_octets; i++) { + m_tmsi |= u.s_tmsi().m_tmsi[i] << (8u * (nof_octets - i - 1u)); } paging_elem.ue_id.s_tmsi().m_tmsi.from_number(m_tmsi); } @@ -1046,12 +1043,12 @@ void rrc::ue::set_activity_timeout(const activity_timeout_type_t type) break; case UE_RESPONSE_RX_TIMEOUT: // Arbitrarily chosen value to complete each UE config step, i.e. security, bearer setup, etc. - deadline_s = 1; - deadline_ms = 0; + deadline_s = 1; + deadline_ms = 0; break; case UE_INACTIVITY_TIMEOUT: - deadline_s = parent->cfg.inactivity_timeout_ms / 1000; - deadline_ms = parent->cfg.inactivity_timeout_ms % 1000; + deadline_s = parent->cfg.inactivity_timeout_ms / 1000; + deadline_ms = parent->cfg.inactivity_timeout_ms % 1000; break; default: parent->rrc_log->error("Unknown timeout type %d", type); @@ -1258,19 +1255,19 @@ bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) // parent->s1ap->ue_capabilities(rnti, &eutra_capabilities); } -void rrc::ue::set_bitrates(LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT* rates) +void rrc::ue::set_bitrates(const asn1::s1ap::ue_aggregate_maximum_bitrate_s& rates) { - memcpy(&bitrates, rates, sizeof(LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT)); + bitrates = rates; } -void rrc::ue::set_security_capabilities(LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT* caps) +void rrc::ue::set_security_capabilities(const asn1::s1ap::ue_security_cap_s& caps) { - memcpy(&security_capabilities, caps, sizeof(LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT)); + security_capabilities = caps; } -void rrc::ue::set_security_key(uint8_t* key, uint32_t length) +void rrc::ue::set_security_key(const asn1::fixed_bitstring<256, false, true>& key) { - memcpy(k_enb, key, length); + memcpy(k_enb, key.data(), key.nof_octets()); parent->rrc_log->info_hex(k_enb, 32, "Key eNodeB (k_enb)"); // Selects security algorithms (cipher_algo and integ_algo) based on capabilities and config preferences select_security_algorithms(); @@ -1292,52 +1289,47 @@ void rrc::ue::set_security_key(uint8_t* key, uint32_t length) parent->rrc_log->info_hex(k_up_enc, 32, "UP Encryption Key (k_up_enc)"); } -bool rrc::ue::setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT* e) +bool rrc::ue::setup_erabs(const asn1::s1ap::e_rab_to_be_setup_list_ctxt_su_req_l& e) { - for (uint32_t i = 0; i < e->len; i++) { - LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT* erab = &e->buffer[i]; - if (erab->ext) { - parent->rrc_log->warning("Not handling LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT extensions\n"); + for (const auto& item : e) { + auto& erab = item.value.e_rab_to_be_setup_item_ctxt_su_req(); + if (erab.ext) { + parent->rrc_log->warning("Not handling E-RABToBeSetupListCtxtSURequest extensions\n"); } - if (erab->iE_Extensions_present) { - parent->rrc_log->warning("Not handling LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT extensions\n"); + if (erab.ie_exts_present) { + parent->rrc_log->warning("Not handling E-RABToBeSetupListCtxtSURequest extensions\n"); } - if (erab->transportLayerAddress.n_bits > 32) { + if (erab.transport_layer_address.length() > 32) { parent->rrc_log->error("IPv6 addresses not currently supported\n"); return false; } uint32_t teid_out; - uint8_to_uint32(erab->gTP_TEID.buffer, &teid_out); - LIBLTE_S1AP_NAS_PDU_STRUCT* nas_pdu = erab->nAS_PDU_present ? &erab->nAS_PDU : nullptr; - setup_erab( - erab->e_RAB_ID.E_RAB_ID, &erab->e_RABlevelQoSParameters, &erab->transportLayerAddress, teid_out, nas_pdu); + uint8_to_uint32(erab.gtp_teid.data(), &teid_out); + const asn1::unbounded_octstring* nas_pdu = erab.nas_pdu_present ? &erab.nas_pdu : nullptr; + setup_erab(erab.e_rab_id, erab.e_ra_blevel_qo_sparams, erab.transport_layer_address, teid_out, nas_pdu); } return true; } -bool rrc::ue::setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e) +bool rrc::ue::setup_erabs(const asn1::s1ap::e_rab_to_be_setup_list_bearer_su_req_l& e) { - for (uint32_t i = 0; i < e->len; i++) { - LIBLTE_S1AP_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT* erab = &e->buffer[i]; - if (erab->ext) { - parent->rrc_log->warning("Not handling LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT extensions\n"); + for (const auto& item : e) { + auto& erab = item.value.e_rab_to_be_setup_item_bearer_su_req(); + if (erab.ext) { + parent->rrc_log->warning("Not handling E-RABToBeSetupListBearerSUReq extensions\n"); } - if (erab->iE_Extensions_present) { - parent->rrc_log->warning("Not handling LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT extensions\n"); + if (erab.ie_exts_present) { + parent->rrc_log->warning("Not handling E-RABToBeSetupListBearerSUReq extensions\n"); } - if (erab->transportLayerAddress.n_bits > 32) { + if (erab.transport_layer_address.length() > 32) { parent->rrc_log->error("IPv6 addresses not currently supported\n"); return false; } uint32_t teid_out; - uint8_to_uint32(erab->gTP_TEID.buffer, &teid_out); - setup_erab(erab->e_RAB_ID.E_RAB_ID, - &erab->e_RABlevelQoSParameters, - &erab->transportLayerAddress, - teid_out, - &erab->nAS_PDU); + uint8_to_uint32(erab.gtp_teid.data(), &teid_out); + setup_erab(erab.e_rab_id, erab.e_ra_blevel_qo_sparams, erab.transport_layer_address, teid_out, &erab.nas_pdu); } // Work in progress @@ -1346,26 +1338,29 @@ bool rrc::ue::setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e) return true; } -void rrc::ue::setup_erab(uint8_t id, - LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT* qos, - LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT* addr, - uint32_t teid_out, - LIBLTE_S1AP_NAS_PDU_STRUCT* nas_pdu) +void rrc::ue::setup_erab(uint8_t id, + const asn1::s1ap::e_rab_level_qo_sparams_s& qos, + const asn1::bounded_bitstring<1, 160, true, true>& addr, + uint32_t teid_out, + const asn1::unbounded_octstring* nas_pdu) { - erabs[id].id = id; - memcpy(&erabs[id].qos_params, qos, sizeof(LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT)); - memcpy(&erabs[id].address, addr, sizeof(LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT)); - erabs[id].teid_out = teid_out; + erabs[id].id = id; + erabs[id].qos_params = qos; + erabs[id].address = addr; + erabs[id].teid_out = teid_out; - uint8_t* bit_ptr = addr->buffer; - uint32_t addr_ = liblte_bits_2_value(&bit_ptr, addr->n_bits); - uint8_t lcid = id - 2; // Map e.g. E-RAB 5 to LCID 3 (==DRB1) + if (addr.length() > 32) { + parent->rrc_log->error("Only addresses with length <= 32 are supported\n"); + return; + } + uint32_t addr_ = addr.to_number(); + uint8_t lcid = id - 2; // Map e.g. E-RAB 5 to LCID 3 (==DRB1) parent->gtpu->add_bearer(rnti, lcid, addr_, erabs[id].teid_out, &(erabs[id].teid_in)); - if (nas_pdu) { + if (nas_pdu != nullptr) { nas_pending = true; - memcpy(erab_info.msg, nas_pdu->buffer, nas_pdu->n_octets); - erab_info.N_bytes = nas_pdu->n_octets; + memcpy(erab_info.msg, nas_pdu->data(), nas_pdu->size()); + erab_info.N_bytes = nas_pdu->size(); parent->rrc_log->info_hex(erab_info.msg, erab_info.N_bytes, "setup_erab nas_pdu -> erab_info rnti 0x%x", rnti); } else { nas_pending = false; @@ -1396,16 +1391,16 @@ void rrc::ue::notify_s1ap_ue_ctxt_setup_complete() parent->s1ap->ue_ctxt_setup_complete(rnti, res); } -void rrc::ue::notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e) +void rrc::ue::notify_s1ap_ue_erab_setup_response(const asn1::s1ap::e_rab_to_be_setup_list_bearer_su_req_l& e) { asn1::s1ap::e_rab_setup_resp_s res; - res.protocol_ies.e_rab_setup_list_bearer_su_res.value.resize(e->len); - for (uint32_t i = 0; i < e->len; ++i) { + res.protocol_ies.e_rab_setup_list_bearer_su_res.value.resize(e.size()); + for (uint32_t i = 0; i < e.size(); ++i) { res.protocol_ies.e_rab_setup_list_bearer_su_res_present = true; auto& item = res.protocol_ies.e_rab_setup_list_bearer_su_res.value[i]; item.load_info_obj(ASN1_S1AP_ID_E_RAB_SETUP_ITEM_BEARER_SU_RES); - uint8_t id = e->buffer[i].e_RAB_ID.E_RAB_ID; + uint8_t id = e[i].value.e_rab_to_be_setup_item_bearer_su_req().e_rab_id; item.value.e_rab_setup_item_bearer_su_res().e_rab_id = id; uint32_to_uint8(erabs[id].teid_in, &item.value.e_rab_setup_item_bearer_su_res().gtp_teid[0]); } @@ -1610,7 +1605,7 @@ int rrc::ue::get_drbid_config(drb_to_add_mod_s* drb, int drb_id) { uint32_t lc_id = (uint32_t)(drb_id + 2); uint32_t erab_id = lc_id + 2; - uint32_t qci = erabs[erab_id].qos_params.qCI.QCI; + uint32_t qci = erabs[erab_id].qos_params.qci; if (qci >= MAX_NOF_QCI) { parent->rrc_log->error("Invalid QCI=%d for ERAB_id=%d, DRB_id=%d\n", qci, erab_id, drb_id); @@ -1762,7 +1757,7 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) conn_reconf->rr_cfg_ded.drb_to_add_mod_list.resize(1); if (get_drbid_config(&conn_reconf->rr_cfg_ded.drb_to_add_mod_list[0], 1)) { parent->rrc_log->error("Getting DRB1 configuration\n"); - parent->rrc_log->console("The QCI %d for DRB1 is invalid or not configured.\n", erabs[5].qos_params.qCI.QCI); + parent->rrc_log->console("The QCI %d for DRB1 is invalid or not configured.\n", erabs[5].qos_params.qci); return; } @@ -1826,7 +1821,7 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE; } -void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e) +void rrc::ue::send_connection_reconf_new_bearer(const asn1::s1ap::e_rab_to_be_setup_list_bearer_su_req_l& e) { srslte::unique_byte_buffer_t pdu = srslte::allocate_unique_buffer(*pool); @@ -1835,16 +1830,16 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE dl_dcch_msg.msg.c1().rrc_conn_recfg().rrc_transaction_id = (uint8_t)((transaction_id++) % 4); rrc_conn_recfg_r8_ies_s* conn_reconf = &dl_dcch_msg.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); - for (uint32_t i = 0; i < e->len; i++) { - LIBLTE_S1AP_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT* erab = &e->buffer[i]; - uint8_t id = erab->e_RAB_ID.E_RAB_ID; - uint8_t lcid = id - 2; // Map e.g. E-RAB 5 to LCID 3 (==DRB1) + for (const auto& item : e) { + auto& erab = item.value.e_rab_to_be_setup_item_bearer_su_req(); + uint8_t id = erab.e_rab_id; + uint8_t lcid = id - 2; // Map e.g. E-RAB 5 to LCID 3 (==DRB1) // Get DRB configuration drb_to_add_mod_s drb_item; if (get_drbid_config(&drb_item, lcid - 2)) { parent->rrc_log->error("Getting DRB configuration\n"); - parent->rrc_log->console("ERROR: The QCI %d is invalid or not configured.\n", erabs[id].qos_params.qCI.QCI); + parent->rrc_log->console("ERROR: The QCI %d is invalid or not configured.\n", erabs[id].qos_params.qci); // TODO: send S1AP response indicating error? return; } @@ -1943,6 +1938,7 @@ bool rrc::ue::select_security_algorithms() bool integ_algo_found = false; for (auto& cipher_item : parent->cfg.eea_preference_list) { + auto& v = security_capabilities.encryption_algorithms; switch (cipher_item) { case srslte::CIPHERING_ALGORITHM_ID_EEA0: // “all bits equal to 0” – UE supports no other algorithm than EEA0, @@ -1954,7 +1950,7 @@ bool rrc::ue::select_security_algorithms() break; case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: // “first bit” – 128-EEA1, - if (security_capabilities.encryptionAlgorithms.buffer[srslte::CIPHERING_ALGORITHM_ID_128_EEA1 - 1]) { + if (v.get(v.length() - 1 - srslte::CIPHERING_ALGORITHM_ID_128_EEA1)) { cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1; enc_algo_found = true; parent->rrc_log->info("Selected EEA1 as RRC encryption algorithm\n"); @@ -1965,7 +1961,7 @@ bool rrc::ue::select_security_algorithms() break; case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: // “second bit” – 128-EEA2, - if (security_capabilities.encryptionAlgorithms.buffer[srslte::CIPHERING_ALGORITHM_ID_128_EEA2 - 1]) { + if (v.get(v.length() - 1 - srslte::CIPHERING_ALGORITHM_ID_128_EEA2)) { cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2; enc_algo_found = true; parent->rrc_log->info("Selected EEA2 as RRC encryption algorithm\n"); @@ -1976,7 +1972,7 @@ bool rrc::ue::select_security_algorithms() break; case srslte::CIPHERING_ALGORITHM_ID_128_EEA3: // “third bit” – 128-EEA3, - if (security_capabilities.encryptionAlgorithms.buffer[srslte::CIPHERING_ALGORITHM_ID_128_EEA3 - 1]) { + if (v.get(v.length() - 1 - srslte::CIPHERING_ALGORITHM_ID_128_EEA3)) { cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA3; enc_algo_found = true; parent->rrc_log->info("Selected EEA3 as RRC encryption algorithm\n"); @@ -1995,6 +1991,7 @@ bool rrc::ue::select_security_algorithms() } for (auto& eia_enum : parent->cfg.eia_preference_list) { + auto& v = security_capabilities.integrity_protection_algorithms; switch (eia_enum) { case srslte::INTEGRITY_ALGORITHM_ID_EIA0: // Null integrity is not supported @@ -2002,7 +1999,7 @@ bool rrc::ue::select_security_algorithms() break; case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: // “first bit” – 128-EIA1, - if (security_capabilities.integrityProtectionAlgorithms.buffer[srslte::INTEGRITY_ALGORITHM_ID_128_EIA1 - 1]) { + if (v.get(v.length() - 1 - srslte::INTEGRITY_ALGORITHM_ID_128_EIA1)) { integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; integ_algo_found = true; parent->rrc_log->info("Selected EIA1 as RRC integrity algorithm.\n"); @@ -2012,7 +2009,7 @@ bool rrc::ue::select_security_algorithms() break; case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: // “second bit” – 128-EIA2, - if (security_capabilities.integrityProtectionAlgorithms.buffer[srslte::INTEGRITY_ALGORITHM_ID_128_EIA2 - 1]) { + if (v.get(v.length() - 1 - srslte::INTEGRITY_ALGORITHM_ID_128_EIA2)) { integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2; integ_algo_found = true; parent->rrc_log->info("Selected EIA2 as RRC integrity algorithm.\n"); @@ -2022,7 +2019,7 @@ bool rrc::ue::select_security_algorithms() break; case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: // “third bit” – 128-EIA3, - if (security_capabilities.integrityProtectionAlgorithms.buffer[srslte::INTEGRITY_ALGORITHM_ID_128_EIA3 - 1]) { + if (v.get(v.length() - 1 - srslte::INTEGRITY_ALGORITHM_ID_128_EIA3)) { integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA3; integ_algo_found = true; parent->rrc_log->info("Selected EIA3 as RRC integrity algorithm.\n"); diff --git a/srsenb/src/stack/upper/s1ap.cc b/srsenb/src/stack/upper/s1ap.cc index 435722fa6..9bd02fed7 100644 --- a/srsenb/src/stack/upper/s1ap.cc +++ b/srsenb/src/stack/upper/s1ap.cc @@ -25,6 +25,7 @@ #include "srslte/common/int_helpers.h" #include //for inet_ntop() +#include #include #include #include @@ -73,11 +74,11 @@ srslte::proc_outcome_t s1ap::ue::ho_prep_proc_t::react(ts1_reloc_prep_expired e) procError("timer TS1Relocprep has expired.\n"); return srslte::proc_outcome_t::error; } -srslte::proc_outcome_t s1ap::ue::ho_prep_proc_t::react(const LIBLTE_S1AP_MESSAGE_HANDOVERPREPARATIONFAILURE_STRUCT& msg) +srslte::proc_outcome_t s1ap::ue::ho_prep_proc_t::react(const ho_prep_fail_s& msg) { ue_ptr->ts1_reloc_prep.stop(); - std::string cause = s1ap_ptr->get_cause(&msg.Cause); + std::string cause = s1ap_ptr->get_cause(msg.protocol_ies.cause.value); procError("HO preparation Failure. Cause: %s\n", cause.c_str()); s1ap_ptr->s1ap_log->console("HO preparation Failure. Cause: %s\n", cause.c_str()); @@ -88,41 +89,41 @@ srslte::proc_outcome_t s1ap::ue::ho_prep_proc_t::react(const LIBLTE_S1AP_MESSAGE * TS 36.413 - Section 8.4.1.2 - HandoverPreparation Successful Operation * Description: MME returns back an HandoverCommand to the SeNB */ -srslte::proc_outcome_t s1ap::ue::ho_prep_proc_t::react(LIBLTE_S1AP_MESSAGE_HANDOVERCOMMAND_STRUCT& msg) +srslte::proc_outcome_t s1ap::ue::ho_prep_proc_t::react(const asn1::s1ap::ho_cmd_s& msg) { // update timers ue_ptr->ts1_reloc_prep.stop(); ue_ptr->ts1_reloc_overall.run(); // Check for unsupported S1AP fields - if (msg.ext or msg.Target_ToSource_TransparentContainer_Secondary_present or msg.HandoverType.ext or - msg.HandoverType.e != LIBLTE_S1AP_HANDOVERTYPE_INTRALTE or msg.CriticalityDiagnostics_present or - msg.NASSecurityParametersfromE_UTRAN_present) { + if (msg.ext or msg.protocol_ies.target_to_source_transparent_container_secondary_present or + msg.protocol_ies.handov_type.value.value != handov_type_opts::intralte or + msg.protocol_ies.crit_diagnostics_present or msg.protocol_ies.nas_security_paramsfrom_e_utran_present) { procWarning("Not handling HandoverCommand extensions and non-intraLTE params\n"); } // Check for E-RABs that could not be admitted in the target - if (msg.E_RABtoReleaseListHOCmd_present) { + if (msg.protocol_ies.e_ra_bto_release_list_ho_cmd_present) { procWarning("Not handling E-RABtoReleaseList\n"); // TODO } // Check for E-RABs subject to being forwarded - if (msg.E_RABSubjecttoDataForwardingList_present) { + if (msg.protocol_ies.e_rab_subjectto_data_forwarding_list_present) { procWarning("Not handling E-RABSubjecttoDataForwardingList\n"); // TODO } // In case of intra-system Handover, Target to Source Transparent Container IE shall be encoded as // Target eNB to Source eNB Transparent Container IE - LIBLTE_BIT_MSG_STRUCT bit_msg; - uint8_t* bit_ptr = &bit_msg.msg[0]; - LIBLTE_S1AP_TARGETENB_TOSOURCEENB_TRANSPARENTCONTAINER_STRUCT container; - liblte_unpack( - &msg.Target_ToSource_TransparentContainer.buffer[0], msg.Target_ToSource_TransparentContainer.n_octets, bit_ptr); - bit_msg.N_bits = bit_ptr - &bit_msg.msg[0]; - liblte_s1ap_unpack_targetenb_tosourceenb_transparentcontainer(&bit_ptr, &container); - if (container.iE_Extensions_present or container.ext) { + uint8_t* buf = const_cast(msg.protocol_ies.target_to_source_transparent_container.value.data()); + asn1::bit_ref bref(buf, msg.protocol_ies.target_to_source_transparent_container.value.size()); + asn1::s1ap::targete_nb_to_sourcee_nb_transparent_container_s container; + if (container.unpack(bref) != asn1::SRSASN_SUCCESS) { + procError("Failed to decode TargeteNBToSourceeNBTransparentContainer\n"); + return srslte::proc_outcome_t::error; + } + if (container.ie_exts_present or container.ext) { procWarning("Not handling extensions\n"); } @@ -132,8 +133,8 @@ srslte::proc_outcome_t s1ap::ue::ho_prep_proc_t::react(LIBLTE_S1AP_MESSAGE_HANDO procError("Fatal Error: Couldn't allocate buffer.\n"); return srslte::proc_outcome_t::error; } - memcpy(rrc_container->msg, container.rRC_Container.buffer, container.rRC_Container.n_octets); - rrc_container->N_bytes = container.rRC_Container.n_octets; + memcpy(rrc_container->msg, container.rrc_container.data(), container.rrc_container.size()); + rrc_container->N_bytes = container.rrc_container.size(); return srslte::proc_outcome_t::success; } @@ -500,81 +501,80 @@ bool s1ap::handle_mme_rx_msg(srslte::unique_byte_buffer_t pdu, bool s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu) { - LIBLTE_S1AP_S1AP_PDU_STRUCT rx_pdu; + s1ap_pdu_c rx_pdu; + asn1::bit_ref bref(pdu->msg, pdu->N_bytes); - if (liblte_s1ap_unpack_s1ap_pdu((LIBLTE_BYTE_MSG_STRUCT*)pdu, &rx_pdu) != LIBLTE_SUCCESS) { + if (rx_pdu.unpack(bref) != asn1::SRSASN_SUCCESS) { s1ap_log->error("Failed to unpack received PDU\n"); return false; } - switch (rx_pdu.choice_type) { - case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: - return handle_initiatingmessage(&rx_pdu.choice.initiatingMessage); - case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: - return handle_successfuloutcome(&rx_pdu.choice.successfulOutcome); - case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: - return handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); + switch (rx_pdu.type().value) { + case s1ap_pdu_c::types_opts::init_msg: + return handle_initiatingmessage(rx_pdu.init_msg()); + case s1ap_pdu_c::types_opts::successful_outcome: + return handle_successfuloutcome(rx_pdu.successful_outcome()); + case s1ap_pdu_c::types_opts::unsuccessful_outcome: + return handle_unsuccessfuloutcome(rx_pdu.unsuccessful_outcome()); default: - s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.choice_type); + s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.type().value); return false; } return true; } -bool s1ap::handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* msg) +bool s1ap::handle_initiatingmessage(const init_msg_s& msg) { - switch (msg->choice_type) { - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT: - return handle_dlnastransport(&msg->choice.DownlinkNASTransport); - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST: - return handle_initialctxtsetuprequest(&msg->choice.InitialContextSetupRequest); - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASECOMMAND: - return handle_uectxtreleasecommand(&msg->choice.UEContextReleaseCommand); - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PAGING: - return handle_paging(&msg->choice.Paging); - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_E_RABSETUPREQUEST: - return handle_erabsetuprequest(&msg->choice.E_RABSetupRequest); - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTMODIFICATIONREQUEST: - return handle_uecontextmodifyrequest(&msg->choice.UEContextModificationRequest); + switch (msg.value.type().value) { + case s1ap_elem_procs_o::init_msg_c::types_opts::dl_nas_transport: + return handle_dlnastransport(msg.value.dl_nas_transport()); + case s1ap_elem_procs_o::init_msg_c::types_opts::init_context_setup_request: + return handle_initialctxtsetuprequest(msg.value.init_context_setup_request()); + case s1ap_elem_procs_o::init_msg_c::types_opts::ue_context_release_cmd: + return handle_uectxtreleasecommand(msg.value.ue_context_release_cmd()); + case s1ap_elem_procs_o::init_msg_c::types_opts::paging: + return handle_paging(msg.value.paging()); + case s1ap_elem_procs_o::init_msg_c::types_opts::e_rab_setup_request: + return handle_erabsetuprequest(msg.value.e_rab_setup_request()); + case s1ap_elem_procs_o::init_msg_c::types_opts::ue_context_mod_request: + return handle_uecontextmodifyrequest(msg.value.ue_context_mod_request()); default: - s1ap_log->error("Unhandled intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); + s1ap_log->error("Unhandled intiating message: %s\n", msg.value.type().to_string().c_str()); } return true; } -bool s1ap::handle_successfuloutcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* msg) +bool s1ap::handle_successfuloutcome(const successful_outcome_s& msg) { - switch (msg->choice_type) { - case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE: - return handle_s1setupresponse(&msg->choice.S1SetupResponse); - case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_HANDOVERCOMMAND: - return handle_s1hocommand(msg->choice.HandoverCommand); + switch (msg.value.type().value) { + case s1ap_elem_procs_o::successful_outcome_c::types_opts::s1_setup_request: + return handle_s1setupresponse(msg.value.s1_setup_request()); + case s1ap_elem_procs_o::successful_outcome_c::types_opts::ho_required: + return handle_s1hocommand(msg.value.ho_required()); default: - s1ap_log->error("Unhandled successful outcome message: %s\n", - liblte_s1ap_successfuloutcome_choice_text[msg->choice_type]); + s1ap_log->error("Unhandled successful outcome message: %s\n", msg.value.type().to_string().c_str()); } return true; } -bool s1ap::handle_unsuccessfuloutcome(LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT* msg) +bool s1ap::handle_unsuccessfuloutcome(const unsuccessful_outcome_s& msg) { - switch (msg->choice_type) { - case LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE: - return handle_s1setupfailure(&msg->choice.S1SetupFailure); - case LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_HANDOVERPREPARATIONFAILURE: - return handle_hopreparationfailure(&msg->choice.HandoverPreparationFailure); + switch (msg.value.type().value) { + case s1ap_elem_procs_o::unsuccessful_outcome_c::types_opts::s1_setup_request: + return handle_s1setupfailure(msg.value.s1_setup_request()); + case s1ap_elem_procs_o::unsuccessful_outcome_c::types_opts::ho_required: + return handle_hopreparationfailure(msg.value.ho_required()); default: - s1ap_log->error("Unhandled unsuccessful outcome message: %s\n", - liblte_s1ap_unsuccessfuloutcome_choice_text[msg->choice_type]); + s1ap_log->error("Unhandled unsuccessful outcome message: %s\n", msg.value.type().to_string().c_str()); } return true; } -bool s1ap::handle_s1setupresponse(LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* msg) +bool s1ap::handle_s1setupresponse(const asn1::s1ap::s1_setup_resp_s& msg) { s1ap_log->info("Received S1SetupResponse\n"); - s1setupresponse = *msg; + s1setupresponse = msg; mme_connected = true; s1_setup_proc_t::s1setupresult res; res.success = true; @@ -582,24 +582,24 @@ bool s1ap::handle_s1setupresponse(LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* ms return true; } -bool s1ap::handle_dlnastransport(LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT* msg) +bool s1ap::handle_dlnastransport(const dl_nas_transport_s& msg) { s1ap_log->info("Received DownlinkNASTransport\n"); - if (msg->ext) { + if (msg.ext) { s1ap_log->warning("Not handling S1AP message extension\n"); } - if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID)) { + if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg.protocol_ies.enb_ue_s1ap_id.value.value)) { s1ap_log->warning("eNB_UE_S1AP_ID not found - discarding message\n"); return false; } - uint16_t rnti = enbid_to_rnti_map[msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID]; + uint16_t rnti = enbid_to_rnti_map[msg.protocol_ies.enb_ue_s1ap_id.value.value]; ue_ctxt_t* ctxt = get_user_ctxt(rnti); - ctxt->MME_UE_S1AP_ID = msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + ctxt->MME_UE_S1AP_ID = msg.protocol_ies.mme_ue_s1ap_id.value.value; - if (msg->HandoverRestrictionList_present) { + if (msg.protocol_ies.ho_restrict_list_present) { s1ap_log->warning("Not handling HandoverRestrictionList\n"); } - if (msg->SubscriberProfileIDforRFP_present) { + if (msg.protocol_ies.subscriber_profile_idfor_rfp_present) { s1ap_log->warning("Not handling SubscriberProfileIDforRFP\n"); } @@ -608,28 +608,29 @@ bool s1ap::handle_dlnastransport(LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT s1ap_log->error("Fatal Error: Couldn't allocate buffer in s1ap::run_thread().\n"); return false; } - memcpy(pdu->msg, msg->NAS_PDU.buffer, msg->NAS_PDU.n_octets); - pdu->N_bytes = msg->NAS_PDU.n_octets; + memcpy(pdu->msg, msg.protocol_ies.nas_pdu.value.data(), msg.protocol_ies.nas_pdu.value.size()); + pdu->N_bytes = msg.protocol_ies.nas_pdu.value.size(); rrc->write_dl_info(rnti, std::move(pdu)); return true; } -bool s1ap::handle_initialctxtsetuprequest(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT* msg) +bool s1ap::handle_initialctxtsetuprequest(const init_context_setup_request_s& msg) { s1ap_log->info("Received InitialContextSetupRequest\n"); - if (msg->ext) { + if (msg.ext) { s1ap_log->warning("Not handling S1AP message extension\n"); } - if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID)) { + if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg.protocol_ies.enb_ue_s1ap_id.value.value)) { s1ap_log->warning("eNB_UE_S1AP_ID not found - discarding message\n"); return false; } - uint16_t rnti = enbid_to_rnti_map[msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID]; + uint16_t rnti = enbid_to_rnti_map[msg.protocol_ies.enb_ue_s1ap_id.value.value]; ue_ctxt_t* ctxt = get_user_ctxt(rnti); - if (msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID != ctxt->MME_UE_S1AP_ID) { - s1ap_log->warning( - "MME_UE_S1AP_ID has changed - old:%d, new:%d\n", ctxt->MME_UE_S1AP_ID, msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID); - ctxt->MME_UE_S1AP_ID = msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + if (msg.protocol_ies.mme_ue_s1ap_id.value.value != ctxt->MME_UE_S1AP_ID) { + s1ap_log->warning("MME_UE_S1AP_ID has changed - old:%d, new: %" PRIu64 "\n", + ctxt->MME_UE_S1AP_ID, + msg.protocol_ies.mme_ue_s1ap_id.value.value); + ctxt->MME_UE_S1AP_ID = msg.protocol_ies.mme_ue_s1ap_id.value.value; } // Setup UE ctxt in RRC @@ -638,9 +639,9 @@ bool s1ap::handle_initialctxtsetuprequest(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETU } /* Ideally the check below would be "if (users[rnti].is_csfb)" */ - if (msg->CSFallbackIndicator_present) { - if (msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_REQUIRED || - msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_HIGH_PRIORITY) { + if (msg.protocol_ies.cs_fallback_ind_present) { + if (msg.protocol_ies.cs_fallback_ind.value.value == cs_fallback_ind_opts::cs_fallback_required || + msg.protocol_ies.cs_fallback_ind.value.value == cs_fallback_ind_opts::cs_fallback_high_prio) { // Send RRC Release (cs-fallback-triggered) to MME cause_c cause; cause.set_radio_network().value = cause_radio_network_opts::cs_fallback_triggered; @@ -654,54 +655,54 @@ bool s1ap::handle_initialctxtsetuprequest(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETU return true; } -bool s1ap::handle_paging(LIBLTE_S1AP_MESSAGE_PAGING_STRUCT* msg) +bool s1ap::handle_paging(const asn1::s1ap::paging_s& msg) { - if (msg->ext) { + if (msg.ext) { s1ap_log->warning("Not handling S1AP message extension\n"); } - uint8_t* ptr = msg->UEIdentityIndexValue.buffer; - uint32_t ueid = srslte_bit_pack(&ptr, 10); - - rrc->add_paging_id(ueid, msg->UEPagingID); + uint32_t ueid = msg.protocol_ies.ue_id_idx_value.value.to_number(); + rrc->add_paging_id(ueid, msg.protocol_ies.ue_paging_id.value); return true; } -bool s1ap::handle_erabsetuprequest(LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT* msg) +bool s1ap::handle_erabsetuprequest(const e_rab_setup_request_s& msg) { s1ap_log->info("Received ERABSetupRequest\n"); - if (msg->ext) { + if (msg.ext) { s1ap_log->warning("Not handling S1AP message extension\n"); } - if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID)) { + if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg.protocol_ies.enb_ue_s1ap_id.value.value)) { s1ap_log->warning("eNB_UE_S1AP_ID not found - discarding message\n"); return false; } - uint16_t rnti = enbid_to_rnti_map[msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID]; + uint16_t rnti = enbid_to_rnti_map[msg.protocol_ies.enb_ue_s1ap_id.value.value]; ue_ctxt_t* ctxt = get_user_ctxt(rnti); - if (msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID != ctxt->MME_UE_S1AP_ID) { - s1ap_log->warning( - "MME_UE_S1AP_ID has changed - old:%d, new:%d\n", ctxt->MME_UE_S1AP_ID, msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID); - ctxt->MME_UE_S1AP_ID = msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + if (msg.protocol_ies.mme_ue_s1ap_id.value.value != ctxt->MME_UE_S1AP_ID) { + s1ap_log->warning("MME_UE_S1AP_ID has changed - old:%d, new:%" PRIu64 "\n", + ctxt->MME_UE_S1AP_ID, + msg.protocol_ies.mme_ue_s1ap_id.value.value); + ctxt->MME_UE_S1AP_ID = msg.protocol_ies.mme_ue_s1ap_id.value.value; } // Setup UE ctxt in RRC return rrc->setup_ue_erabs(rnti, msg); } -bool s1ap::handle_uecontextmodifyrequest(LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT* msg) +bool s1ap::handle_uecontextmodifyrequest(const ue_context_mod_request_s& msg) { s1ap_log->info("Received UeContextModificationRequest\n"); - if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID)) { + if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(msg.protocol_ies.enb_ue_s1ap_id.value.value)) { s1ap_log->warning("eNB_UE_S1AP_ID not found - discarding message\n"); return false; } - uint16_t rnti = enbid_to_rnti_map[msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID]; + uint16_t rnti = enbid_to_rnti_map[msg.protocol_ies.enb_ue_s1ap_id.value.value]; ue_ctxt_t* ctxt = get_user_ctxt(rnti); - if (msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID != ctxt->MME_UE_S1AP_ID) { - s1ap_log->warning( - "MME_UE_S1AP_ID has changed - old:%d, new:%d\n", ctxt->MME_UE_S1AP_ID, msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID); - ctxt->MME_UE_S1AP_ID = msg->MME_UE_S1AP_ID.MME_UE_S1AP_ID; + if (msg.protocol_ies.mme_ue_s1ap_id.value.value != ctxt->MME_UE_S1AP_ID) { + s1ap_log->warning("MME_UE_S1AP_ID has changed - old:%d, new:%" PRIu64 "\n", + ctxt->MME_UE_S1AP_ID, + msg.protocol_ies.mme_ue_s1ap_id.value.value); + ctxt->MME_UE_S1AP_ID = msg.protocol_ies.mme_ue_s1ap_id.value.value; } if (!rrc->modify_ue_ctxt(rnti, msg)) { @@ -715,9 +716,9 @@ bool s1ap::handle_uecontextmodifyrequest(LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATI send_uectxmodifyresp(rnti); /* Ideally the check below would be "if (users[rnti].is_csfb)" */ - if (msg->CSFallbackIndicator_present) { - if (msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_REQUIRED || - msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_HIGH_PRIORITY) { + if (msg.protocol_ies.cs_fallback_ind_present) { + if (msg.protocol_ies.cs_fallback_ind.value.value == cs_fallback_ind_opts::cs_fallback_required || + msg.protocol_ies.cs_fallback_ind.value.value == cs_fallback_ind_opts::cs_fallback_high_prio) { // Send RRC Release (cs-fallback-triggered) to MME cause_c cause; cause.set_radio_network().value = cause_radio_network_opts::cs_fallback_triggered; @@ -730,26 +731,24 @@ bool s1ap::handle_uecontextmodifyrequest(LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATI return true; } -bool s1ap::handle_uectxtreleasecommand(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMAND_STRUCT* msg) +bool s1ap::handle_uectxtreleasecommand(const ue_context_release_cmd_s& msg) { s1ap_log->info("Received UEContextReleaseCommand\n"); - if (msg->ext) { - s1ap_log->warning("Not handling S1AP message extension\n"); - } - if (msg->UE_S1AP_IDs.ext) { + if (msg.ext) { s1ap_log->warning("Not handling S1AP message extension\n"); } uint16_t rnti = 0; - if (msg->UE_S1AP_IDs.choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR) { + if (msg.protocol_ies.ue_s1ap_ids.value.type().value == ue_s1ap_ids_c::types_opts::ue_s1ap_id_pair) { + auto& idpair = msg.protocol_ies.ue_s1ap_ids.value.ue_s1ap_id_pair(); - if (msg->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.ext) { + if (idpair.ext) { s1ap_log->warning("Not handling S1AP message extension\n"); } - if (msg->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.iE_Extensions_present) { + if (idpair.ie_exts_present) { s1ap_log->warning("Not handling S1AP message iE_Extensions\n"); } - uint32_t enb_ue_id = msg->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; + uint32_t enb_ue_id = idpair.enb_ue_s1ap_id; if (enbid_to_rnti_map.end() == enbid_to_rnti_map.find(enb_ue_id)) { s1ap_log->warning("eNB_UE_S1AP_ID:%d not found - discarding message\n", enb_ue_id); return false; @@ -759,7 +758,7 @@ bool s1ap::handle_uectxtreleasecommand(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMA } else { // LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_MME_UE_S1AP_ID - uint32_t mme_ue_id = msg->UE_S1AP_IDs.choice.mME_UE_S1AP_ID.MME_UE_S1AP_ID; + uint32_t mme_ue_id = msg.protocol_ies.ue_s1ap_ids.value.mme_ue_s1ap_id(); uint32_t enb_ue_id; if (!find_mme_ue_id(mme_ue_id, &rnti, &enb_ue_id)) { s1ap_log->warning("UE for MME_UE_S1AP_ID:%d not found - discarding message\n", mme_ue_id); @@ -781,27 +780,27 @@ bool s1ap::handle_uectxtreleasecommand(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMA return true; } -bool s1ap::handle_s1setupfailure(LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT* msg) +bool s1ap::handle_s1setupfailure(const asn1::s1ap::s1_setup_fail_s& msg) { - std::string cause = get_cause(&msg->Cause); + std::string cause = get_cause(msg.protocol_ies.cause.value); s1ap_log->error("S1 Setup Failure. Cause: %s\n", cause.c_str()); s1ap_log->console("S1 Setup Failure. Cause: %s\n", cause.c_str()); return true; } -bool s1ap::handle_hopreparationfailure(LIBLTE_S1AP_MESSAGE_HANDOVERPREPARATIONFAILURE_STRUCT* msg) +bool s1ap::handle_hopreparationfailure(const ho_prep_fail_s& msg) { - auto user_it = users.find(enbid_to_rnti_map[msg->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID]); + auto user_it = users.find(enbid_to_rnti_map[msg.protocol_ies.enb_ue_s1ap_id.value.value]); if (user_it == users.end()) { s1ap_log->error("user rnti=0x%x no longer exists\n", user_it->first); } - user_it->second->get_ho_prep_proc().trigger(*msg); + user_it->second->get_ho_prep_proc().trigger(msg); return true; } -bool s1ap::handle_s1hocommand(LIBLTE_S1AP_MESSAGE_HANDOVERCOMMAND_STRUCT& msg) +bool s1ap::handle_s1hocommand(const asn1::s1ap::ho_cmd_s& msg) { - auto user_it = users.find(enbid_to_rnti_map[msg.eNB_UE_S1AP_ID.ENB_UE_S1AP_ID]); + auto user_it = users.find(enbid_to_rnti_map[msg.protocol_ies.enb_ue_s1ap_id.value.value]); if (user_it == users.end()) { s1ap_log->error("user rnti=0x%x no longer exists\n", user_it->first); return false; @@ -1174,25 +1173,25 @@ bool s1ap::find_mme_ue_id(uint32_t mme_ue_id, uint16_t* rnti, uint32_t* enb_ue_i return false; } -std::string s1ap::get_cause(const LIBLTE_S1AP_CAUSE_STRUCT* c) +std::string s1ap::get_cause(const cause_c& c) { - std::string cause = liblte_s1ap_cause_choice_text[c->choice_type]; + std::string cause = c.type().to_string(); cause += " - "; - switch (c->choice_type) { - case LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK: - cause += liblte_s1ap_causeradionetwork_text[c->choice.radioNetwork.e]; + switch (c.type().value) { + case cause_c::types_opts::radio_network: + cause += c.radio_network().to_string(); break; - case LIBLTE_S1AP_CAUSE_CHOICE_TRANSPORT: - cause += liblte_s1ap_causetransport_text[c->choice.transport.e]; + case cause_c::types_opts::transport: + cause += c.transport().to_string(); break; - case LIBLTE_S1AP_CAUSE_CHOICE_NAS: - cause += liblte_s1ap_causenas_text[c->choice.nas.e]; + case cause_c::types_opts::nas: + cause += c.nas().to_string(); break; - case LIBLTE_S1AP_CAUSE_CHOICE_PROTOCOL: - cause += liblte_s1ap_causeprotocol_text[c->choice.protocol.e]; + case cause_c::types_opts::protocol: + cause += c.protocol().to_string(); break; - case LIBLTE_S1AP_CAUSE_CHOICE_MISC: - cause += liblte_s1ap_causemisc_text[c->choice.misc.e]; + case cause_c::types_opts::misc: + cause += c.misc().to_string(); break; default: cause += "unknown"; diff --git a/srsenb/test/upper/erab_setup_test.cc b/srsenb/test/upper/erab_setup_test.cc index 2749a8a81..c87379aa1 100644 --- a/srsenb/test/upper/erab_setup_test.cc +++ b/srsenb/test/upper/erab_setup_test.cc @@ -83,8 +83,8 @@ int test_erab_setup(bool qci_exists) 0x72, 0x73, 0x05, 0x01, 0xc0, 0xa8, 0x04, 0x02, 0x27, 0x15, 0x80, 0x80, 0x21, 0x0a, 0x03, 0x00, 0x00, 0x0a, 0x81, 0x06, 0x08, 0x08, 0x08, 0x08, 0x00, 0x0d, 0x04, 0x08, 0x08, 0x08, 0x08}; - LIBLTE_S1AP_S1AP_PDU_STRUCT s1ap_pdu; - LIBLTE_BYTE_MSG_STRUCT byte_buf; + asn1::s1ap::s1ap_pdu_c s1ap_pdu; + srslte::byte_buffer_t byte_buf; if (qci_exists) { byte_buf.N_bytes = sizeof(drb2_erab_setup_request_ok); memcpy(byte_buf.msg, drb2_erab_setup_request_ok, byte_buf.N_bytes); @@ -92,9 +92,10 @@ int test_erab_setup(bool qci_exists) byte_buf.N_bytes = sizeof(drb2_erab_setup_request_fail); memcpy(byte_buf.msg, drb2_erab_setup_request_fail, byte_buf.N_bytes); } + asn1::bit_ref bref(byte_buf.msg, byte_buf.N_bytes); - liblte_s1ap_unpack_s1ap_pdu(&byte_buf, &s1ap_pdu); - rrc.setup_ue_erabs(rnti, &s1ap_pdu.choice.initiatingMessage.choice.E_RABSetupRequest); + TESTASSERT(s1ap_pdu.unpack(bref) == asn1::SRSASN_SUCCESS); + rrc.setup_ue_erabs(rnti, s1ap_pdu.init_msg().value.e_rab_setup_request()); if (qci_exists) { TESTASSERT(rrc_log.error_counter == 0); diff --git a/srsenb/test/upper/rrc_mobility_test.cc b/srsenb/test/upper/rrc_mobility_test.cc index 7508098da..361680f68 100644 --- a/srsenb/test/upper/rrc_mobility_test.cc +++ b/srsenb/test/upper/rrc_mobility_test.cc @@ -237,14 +237,6 @@ int test_correct_meascfg_calculation() return SRSLTE_SUCCESS; } -namespace test_helpers { - -int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args); -void copy_msg_to_buffer(srslte::unique_byte_buffer_t& pdu, uint8_t* msg, size_t nof_bytes); -int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, uint16_t rnti); - -} // namespace test_helpers - struct mobility_test_params { enum class test_fail_at { success, wrong_measreport, concurrent_ho, ho_prep_failure } fail_at; const char* to_string() diff --git a/srsenb/test/upper/test_helpers.h b/srsenb/test/upper/test_helpers.h index aae4ab794..bc29a99f7 100644 --- a/srsenb/test/upper/test_helpers.h +++ b/srsenb/test/upper/test_helpers.h @@ -173,12 +173,13 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u 0x05, 0xf4, 0xf6, 0x7e, 0x72, 0x69, 0x00, 0x6b, 0x00, 0x05, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x49, 0x00, 0x20, 0x45, 0x25, 0xe4, 0x9a, 0x77, 0xc8, 0xd5, 0xcf, 0x26, 0x33, 0x63, 0xeb, 0x5b, 0xb9, 0xc3, 0x43, 0x9b, 0x9e, 0xb3, 0x86, 0x1f, 0xa8, 0xa7, 0xcf, 0x43, 0x54, 0x07, 0xae, 0x42, 0x2b, 0x63, 0xb9}; - LIBLTE_S1AP_S1AP_PDU_STRUCT s1ap_pdu; - LIBLTE_BYTE_MSG_STRUCT byte_buf; + asn1::s1ap::s1ap_pdu_c s1ap_pdu; + srslte::byte_buffer_t byte_buf; byte_buf.N_bytes = sizeof(s1ap_init_ctxt_setup_req); memcpy(byte_buf.msg, s1ap_init_ctxt_setup_req, byte_buf.N_bytes); - liblte_s1ap_unpack_s1ap_pdu(&byte_buf, &s1ap_pdu); - rrc.setup_ue_ctxt(rnti, &s1ap_pdu.choice.initiatingMessage.choice.InitialContextSetupRequest); + asn1::bit_ref bref(byte_buf.msg, byte_buf.N_bytes); + TESTASSERT(s1ap_pdu.unpack(bref) == asn1::SRSASN_SUCCESS); + rrc.setup_ue_ctxt(rnti, s1ap_pdu.init_msg().value.init_context_setup_request()); timers.step_all(); rrc.tti_clock();