converted s1ap to new s1ap asn1 lib. Cleaned up bitstring packing/unpacking and bitstring types

master
Francisco Paisana 5 years ago
parent 25bb36cdc3
commit ee24b59924

@ -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<false>;
/*********************
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 <uint32_t N, bool Ext = false, bool Al = false>
class fixed_bitstring
template <uint32_t LB, uint32_t UB, bool ext = false, bool aligned = false>
class bitstring
{
using this_type = bitstring<LB, UB, ext, aligned>;
public:
using type_t = fixed_bitstring<N, Ext, Al>;
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<uint8_t, (uint32_t)((N + 7) / 8)> 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 <typename BitStringType>
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<BitStringType>& 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);
}
private:
derived_t* derived() { return static_cast<derived_t*>(this); }
const derived_t* derived() const { return static_cast<const derived_t*>(this); }
};
template <uint32_t LB, uint32_t UB, bool ext = false, bool aligned = false>
class bounded_bitstring : public base_bitstring<bounded_bitstring<LB, UB, ext, aligned> >
{
using base_t = base_bitstring<bounded_bitstring<LB, UB> >;
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());
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:
bounded_array<uint8_t, ceil_frac(ub, 8u)> octets_;
const static uint32_t stack_size = (UB == std::numeric_limits<uint32_t>::max()) ? 4 : ceil_frac(ub, 8u);
ext_array<uint8_t, stack_size> octets_;
uint32_t nof_bits = 0;
};
/*********************
dyn_bitstring
*********************/
template <uint32_t LB, uint32_t UB, bool ext = false, bool aligned = false>
using bounded_bitstring = bitstring<LB, UB, ext, aligned>;
template <bool Ext = false, bool Al = false>
class unbounded_bitstring : public base_bitstring<unbounded_bitstring<Ext, Al> >
{
using base_t = base_bitstring<unbounded_bitstring<Ext, Al> >;
public:
static const uint32_t lb = 0, ub = std::numeric_limits<uint32_t>::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<uint8_t> octets_;
uint32_t n_bits;
};
using unbounded_bitstring = bitstring<0, std::numeric_limits<uint32_t>::max(), Ext, Al>;
using dyn_bitstring = unbounded_bitstring<false, false>;
template <uint32_t N, bool Ext = false, bool Al = false>
using fixed_bitstring = bitstring<N, N, Ext, Al>;
/*********************
fixed sequence of
*********************/
@ -953,7 +865,7 @@ SRSASN_CODE unpack_fixed_seq_of(T* item_array, bit_ref& bref, uint32_t nof_items
template <class ItemPacker>
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 <typename T>
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;

@ -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];
}

@ -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;
};

@ -994,127 +994,17 @@ template class unbounded_octstring<false>;
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
*********************/
namespace bitstring_utils {
/**
* Pack ASN1 bitstring length prefix. Accommodates for cases: fixed/unbounded/bounded, aligned/unaligned, with/out ext
*/
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)
uint32_t lb = 0,
uint32_t ub = std::numeric_limits<uint32_t>::max(),
bool has_ext = false,
bool is_aligned = false)
{
if (has_ext and ub == std::numeric_limits<uint32_t>::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));
}
if (lb == ub and within_bounds) {
// do not encode prefix if fixed size
if (lb == ub and within_bounds) {
return SRSASN_SUCCESS;
}
// pack as unbounded if unbounded bitstring or ext is active
if (ub == std::numeric_limits<uint32_t>::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;
}
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 == 0) {
// empty bit string
return SRSASN_SUCCESS;
uint32_t offset = nbits % 8; // clean up any extra set bit
if (offset > 0) {
ptr[nof_bytes - 1] &= (uint8_t)((1 << offset) - 1);
}
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;
}
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

@ -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
@ -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);
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(LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT* e);
bool setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e);
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,
LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT* qos,
LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT* addr,
const asn1::s1ap::e_rab_level_qo_sparams_s& qos,
const asn1::bounded_bitstring<1, 160, true, true>& addr,
uint32_t teid_out,
LIBLTE_S1AP_NAS_PDU_STRUCT* nas_pdu);
const asn1::unbounded_octstring<true>* 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);
@ -314,15 +314,15 @@ 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;
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;
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;
@ -356,7 +356,7 @@ private:
// state
std::map<uint16_t, std::unique_ptr<ue> > users; // NOTE: has to have fixed addr
std::map<uint32_t, LIBLTE_S1AP_UEPAGINGID_STRUCT> pending_paging;
std::map<uint32_t, asn1::s1ap::ue_paging_id_c> pending_paging;
std::vector<srslte::unique_byte_buffer_t> sib_buffer;

@ -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_info>& 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"; }

@ -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,7 +515,7 @@ 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;
asn1::s1ap::ue_paging_id_c& u = item.second;
uint32_t ueid = ((uint32_t)item.first) % 1024;
uint32_t i_s = (ueid / N) % Ns;
@ -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]);
paging_elem.ue_id.s_tmsi().mmec.from_number(u.s_tmsi().mmec[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));
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);
}
@ -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<true>* 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
@ -1347,25 +1339,28 @@ bool rrc::ue::setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e)
}
void rrc::ue::setup_erab(uint8_t id,
LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT* qos,
LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT* addr,
const asn1::s1ap::e_rab_level_qo_sparams_s& qos,
const asn1::bounded_bitstring<1, 160, true, true>& addr,
uint32_t teid_out,
LIBLTE_S1AP_NAS_PDU_STRUCT* nas_pdu)
const asn1::unbounded_octstring<true>* 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].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);
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;
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");

@ -25,6 +25,7 @@
#include "srslte/common/int_helpers.h"
#include <arpa/inet.h> //for inet_ntop()
#include <inttypes.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <stdio.h>
@ -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<uint8_t*>(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";

@ -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);

@ -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()

@ -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();

Loading…
Cancel
Save