new asn1 rrc library

master
Francisco Paisana 6 years ago committed by Andre Puschmann
parent 6bea1814c9
commit 0204db2e12

@ -0,0 +1,975 @@
/*
Copyright 2013-2017 Software Radio Systems Limited
This file is part of srsLTE
srsLTE is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
srsLTE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
A copy of the GNU Affero General Public License can be found in
the LICENSE file in the top-level directory of this distribution
and at http://www.gnu.org/licenses/.
*/
#ifndef SRSASN_COMMON_UTILS_H
#define SRSASN_COMMON_UTILS_H
#include <algorithm>
#include <cmath>
#include <cstring>
#include <sstream>
#include <stdarg.h> /* va_list, va_start, va_arg, va_end */
#include <stdint.h>
#include <string>
// TODOS/FIXME:
// - ext flag as an template arg?
// - custom allocators?
namespace asn1 {
#define ASN_16K 16383
/************************
logging
************************/
typedef enum { LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_WARN, LOG_LEVEL_ERROR } srsasn_logger_level_t;
typedef void (*log_handler_t)(srsasn_logger_level_t log_level, void* ctx, const char* str);
void vlog_print(log_handler_t handler, void* ctx, srsasn_logger_level_t log_level, const char* format, va_list args);
void srsasn_log_register_handler(void* ctx, log_handler_t handler);
void srsasn_log_print(srsasn_logger_level_t log_level, const char* format, ...);
/************************
error handling
************************/
enum SRSASN_CODE { SRSASN_SUCCESS, SRSASN_ERROR_ENCODE_FAIL, SRSASN_ERROR_DECODE_FAIL };
void log_error_code(SRSASN_CODE code, const char* filename, int line);
#define HANDLE_CODE(ret) \
{ \
SRSASN_CODE macrocode = (ret); \
if (macrocode != SRSASN_SUCCESS) { \
log_error_code(macrocode, __FILE__, __LINE__); \
return macrocode; \
} \
}
/************************
bit_ref
************************/
struct ValOrError {
uint32_t val;
SRSASN_CODE code;
ValOrError() : val(0), code(SRSASN_SUCCESS) {}
ValOrError(uint32_t val_, SRSASN_CODE code_) : val(val_), code(code_) {}
};
ValOrError unpack_bits(uint8_t*& ptr, uint8_t& offset, uint8_t* max_ptr, uint32_t n_bits);
class bit_ref
{
public:
bit_ref();
bit_ref(uint8_t* start_ptr_, uint32_t max_size_);
int distance(const bit_ref& other) const;
int distance(uint8_t* ref_ptr) const;
int distance() const;
int distance_bytes(uint8_t* ref_ptr) const;
int distance_bytes() const;
SRSASN_CODE pack(uint32_t val, uint32_t n_bits);
template <class T>
SRSASN_CODE unpack(T& val, uint32_t n_bits)
{
ValOrError ret = unpack_bits(ptr, offset, max_ptr, n_bits);
val = ret.val;
return ret.code;
}
SRSASN_CODE align_bytes();
SRSASN_CODE align_bytes_zero();
void set(uint8_t* start_ptr_, uint32_t max_size_);
private:
uint8_t* ptr;
uint8_t offset;
uint8_t* start_ptr;
uint8_t* max_ptr;
};
/*********************
function helpers
*********************/
template <class T>
class dyn_array
{
public:
typedef T item_type;
dyn_array() : data_(NULL), size_(0), cap_(0) {}
dyn_array(uint32_t new_size) : size_(new_size), cap_(new_size) { data_ = new T[size_]; }
dyn_array(const dyn_array<T>& other)
{
size_ = other.size_;
cap_ = other.cap_;
data_ = new T[cap_];
std::copy(&other[0], &other[size_], data_);
}
~dyn_array()
{
if (data_ != NULL) {
delete[] data_;
}
}
uint32_t size() const { return size_; }
uint32_t capacity() const { return cap_; }
T& operator[](uint32_t idx) { return data_[idx]; }
const T& operator[](uint32_t idx) const { return data_[idx]; }
dyn_array<T>& operator=(const dyn_array<T>& other)
{
if (this == &other) {
return *this;
}
resize(other.size());
std::copy(&other[0], &other[size_], data_);
return *this;
}
void resize(uint32_t new_size, uint32_t new_cap = 0)
{
if (new_size == size_) {
return;
}
if (cap_ >= new_size) {
size_ = new_size;
return;
}
T* old_data = data_;
cap_ = new_size > new_cap ? new_size : new_cap;
if (cap_ > 0) {
data_ = new T[cap_];
if (old_data != NULL) {
std::copy(&old_data[0], &old_data[size_], data_);
}
} else {
data_ = NULL;
}
size_ = new_size;
if (old_data != NULL) {
delete[] old_data;
}
}
bool operator==(const dyn_array<T>& other) const
{
return size() == other.size() and std::equal(data_, data_ + size(), other.data_);
}
void push_back(const T& elem)
{
resize(size() + 1, size() * 2);
data_[size() - 1] = elem;
}
T& back() { return data_[size() - 1]; }
const T& back() const { return data_[size() - 1]; }
T* data() { return &data_[0]; }
const T* data() const { return &data_[0]; }
private:
T* data_;
uint32_t size_, cap_;
};
template <class T, uint32_t MAX_N>
class bounded_array
{
public:
typedef T item_type;
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]; }
const T& operator[](uint32_t idx) const { return data_[idx]; }
bool operator==(const bounded_array<T, MAX_N>& other) const
{
return size() == other.size() and std::equal(data_, data_ + size(), other.data_);
}
void resize(uint32_t new_size) { current_size = new_size; }
void push_back(const T& elem)
{
if (current_size >= MAX_N) {
srsasn_log_print(LOG_LEVEL_ERROR, "Maximum size %d achieved for bounded_array.\n", MAX_N);
}
data_[current_size++] = elem;
}
T& back() { return data_[current_size - 1]; }
const T& back() const { return data_[current_size - 1]; }
T* data() { return &data_[0]; }
const T* data() const { return &data_[0]; }
private:
T data_[MAX_N];
uint32_t current_size;
};
template <class T, uint32_t N>
class fixed_array
{
public:
typedef T item_type;
static uint32_t size() { return N; }
T& operator[](uint32_t idx) { return data_[idx]; }
const T& operator[](uint32_t idx) const { return data_[idx]; }
bool operator==(const fixed_array<T, N>& other) const { return std::equal(data_, data_ + size(), other.data_); }
T& back() { return data_[size() - 1]; }
const T& back() const { return data_[size() - 1]; }
T* data() { return &data_[0]; }
const T* data() const { return &data_[0]; }
private:
T data_[N];
};
/*********************
ext packing
*********************/
SRSASN_CODE pack_unsupported_ext_flag(bit_ref& bref, bool ext);
SRSASN_CODE unpack_unsupported_ext_flag(bool& ext, bit_ref& bref);
/************************
enum packing
************************/
SRSASN_CODE pack_enum(bit_ref& bref, uint32_t enum_val, uint32_t nbits);
SRSASN_CODE pack_enum(bit_ref& bref, uint32_t enum_val, uint32_t nbits, uint32_t nof_noext);
SRSASN_CODE pack_enum(bit_ref& bref, uint32_t e, uint32_t nof_types, uint32_t nof_exts, bool has_ext);
ValOrError unpack_enum(uint32_t nof_types, uint32_t nof_exts, bool has_ext, bit_ref& bref);
template <typename EnumType>
SRSASN_CODE pack_enum(bit_ref& bref, EnumType e)
{
return pack_enum(bref, e, EnumType::nof_types, EnumType::nof_exts, EnumType::has_ext);
}
template <typename EnumType>
SRSASN_CODE unpack_enum(EnumType& e, bit_ref& bref)
{
ValOrError ret = unpack_enum(EnumType::nof_types, EnumType::nof_exts, EnumType::has_ext, bref);
e = (typename EnumType::options)ret.val;
return ret.code;
}
struct EnumPacker {
template <class EnumType>
SRSASN_CODE pack(bit_ref& bref, EnumType e)
{
return pack_enum(bref, e);
}
template <class EnumType>
SRSASN_CODE unpack(EnumType& e, bit_ref& bref)
{
return unpack_enum(e, bref);
}
};
template <class EnumType>
bool string_to_enum(EnumType& e, const std::string& s)
{
for (uint32_t i = 0; i < EnumType::nof_types; ++i) {
e = (typename EnumType::options)i;
if (e.to_string() == s) {
return true;
}
}
return false;
}
template <class EnumType, class NumberType>
bool number_to_enum(EnumType& e, NumberType val)
{
for (uint32_t i = 0; i < e.nof_types; ++i) {
e = (typename EnumType::options)i;
if (e.to_number() == val) {
return true;
}
}
return false;
}
template <class EnumType>
bool number_string_to_enum(EnumType& e, const std::string& val)
{
for (uint32_t i = 0; i < e.nof_types; ++i) {
e = (typename EnumType::options)i;
if (e.to_number_string() == val) {
return true;
}
}
return false;
}
/************************
integer packing
************************/
// Constrained Whole Number
template <class IntType>
SRSASN_CODE pack_unalign_integer(bit_ref& bref, IntType n, IntType lb, IntType ub);
template <class IntType>
SRSASN_CODE unpack_unalign_integer(IntType& n, bit_ref& bref, IntType lb, IntType ub);
template <class IntType>
struct UnalignedIntegerPacker {
UnalignedIntegerPacker(IntType, IntType);
IntType lb;
IntType ub;
SRSASN_CODE pack(bit_ref& bref, IntType n);
SRSASN_CODE unpack(IntType& n, bit_ref& bref);
};
template <class IntType>
SRSASN_CODE pack_align_integer(bit_ref& bref, IntType n, IntType lb, IntType ub);
template <typename IntType>
SRSASN_CODE unpack_align_integer(IntType& intval, bit_ref& bref, IntType lb, IntType ub);
template <class IntType>
struct AlignedIntegerPacker {
AlignedIntegerPacker(IntType lb_, IntType ub_);
IntType lb;
IntType ub;
SRSASN_CODE pack(bit_ref& bref, IntType n);
SRSASN_CODE unpack(IntType& n, bit_ref& bref);
};
// Normally Small non-negative whole number
template <typename UintType>
SRSASN_CODE pack_norm_small_integer(bit_ref& bref, UintType n);
template <typename UintType>
SRSASN_CODE unpack_norm_small_integer(UintType& n, bit_ref& bref);
// Unconstrained Whole Number
// FIXME: Implement
inline SRSASN_CODE pack_unconstrained_integer(bit_ref& bref, int64_t n)
{
// TODO
srsasn_log_print(LOG_LEVEL_ERROR, "Not implemented\n");
return SRSASN_SUCCESS;
}
inline SRSASN_CODE unpack_unconstrained_integer(int64_t& n, bit_ref& bref)
{
// TODO
srsasn_log_print(LOG_LEVEL_ERROR, "Not implemented\n");
return SRSASN_SUCCESS;
}
/************************
length determinant
************************/
// Pack as whole constrained number
template <typename IntType>
SRSASN_CODE pack_length(bit_ref& bref, IntType n, IntType lb, IntType ub);
template <typename IntType>
SRSASN_CODE unpack_length(IntType& n, bit_ref& bref, IntType lb, IntType ub);
// Pack as a small non-negative whole number
SRSASN_CODE pack_length(bit_ref& ref, uint32_t val);
SRSASN_CODE unpack_length(uint32_t& val, bit_ref& ref);
/************************
General Packer/Unpacker
************************/
struct BitPacker {
BitPacker(uint32_t nof_bits_) : nof_bits(nof_bits_) {}
template <typename T>
SRSASN_CODE pack(bit_ref& bref, const T& topack)
{
bref.pack(topack, nof_bits);
return SRSASN_SUCCESS;
}
template <typename T>
SRSASN_CODE unpack(T& tounpack, bit_ref& bref)
{
return bref.unpack(tounpack, nof_bits);
}
uint32_t nof_bits;
};
struct Packer {
template <typename T>
SRSASN_CODE pack(bit_ref& bref, const T& topack)
{
return topack.pack(bref);
}
template <typename T>
SRSASN_CODE unpack(T& tounpack, bit_ref& bref)
{
return tounpack.unpack(bref);
}
};
/*********************
common octstring
*********************/
// helper functions common to all octstring implementations
uint64_t octstring_to_number(const uint8_t* ptr, uint32_t nbytes);
void number_to_octstring(uint8_t* ptr, uint64_t number, uint32_t nbytes);
std::string octstring_to_string(const uint8_t* ptr, uint32_t N);
void string_to_octstring(uint8_t* ptr, const std::string& str);
/************************
fixed_octstring
************************/
template <uint32_t N>
class fixed_octstring
{
public:
const uint8_t& operator[](uint32_t idx) const { return octets_[idx]; }
uint8_t& operator[](uint32_t idx) { return octets_[idx]; }
bool operator==(const fixed_octstring<N>& other) const { return octets_ == other.octets_; }
uint8_t* data() { return &octets_[0]; }
const uint8_t* data() const { return &octets_[0]; }
static uint32_t size() { return N; }
std::string to_string() const { return octstring_to_string(&octets_[0], N); }
fixed_octstring<N>& from_string(const std::string& hexstr)
{
if (hexstr.size() != 2 * N) {
srsasn_log_print(LOG_LEVEL_ERROR, "The provided hex string size is not valid (%d!=2*%d).\n", hexstr.size(), N);
} else {
string_to_octstring(&octets_[0], hexstr);
}
return *this;
}
uint64_t to_number() const { return octstring_to_number(&octets_[0], size()); }
fixed_octstring<N>& from_number(uint64_t val)
{
number_to_octstring(&octets_[0], val, size());
return *this;
}
SRSASN_CODE pack(bit_ref& bref) const;
SRSASN_CODE unpack(bit_ref& bref);
private:
fixed_array<uint8_t, N> octets_;
};
template <uint32_t N>
SRSASN_CODE fixed_octstring<N>::pack(bit_ref& bref) const
{
// if(N > 2) { // X.691 Sec.16
// bref.align_bytes_zero();
// }
for (uint32_t i = 0; i < size(); ++i) {
bref.pack(octets_[i], 8);
}
return SRSASN_SUCCESS;
}
template <uint32_t N>
SRSASN_CODE fixed_octstring<N>::unpack(bit_ref& bref)
{
// if(N > 2) { // X.691 Sec.16
// bref.align_bytes_zero();
// }
for (uint32_t i = 0; i < size(); ++i) {
HANDLE_CODE(bref.unpack(octets_[i], 8));
}
return SRSASN_SUCCESS;
}
/************************
dyn_octstring
************************/
class dyn_octstring
{
public:
dyn_octstring() {}
dyn_octstring(uint32_t new_size) : octets_(new_size) {}
const uint8_t& operator[](uint32_t idx) const { return octets_[idx]; }
uint8_t& operator[](uint32_t idx) { return octets_[idx]; }
bool operator==(const dyn_octstring& other) const { return octets_ == other.octets_; }
void resize(uint32_t new_size) { octets_.resize(new_size); }
uint32_t size() const { return octets_.size(); }
uint8_t* data() { return &octets_[0]; }
const uint8_t* data() const { return &octets_[0]; }
SRSASN_CODE pack(bit_ref& ie_ref) const;
SRSASN_CODE unpack(bit_ref& ie_ref);
std::string to_string() const;
dyn_octstring& from_string(const std::string& hexstr);
uint64_t to_number() const { return octstring_to_number(&octets_[0], size()); }
dyn_octstring& from_number(uint64_t val)
{
number_to_octstring(&octets_[0], val, size());
return *this;
}
private:
dyn_array<uint8_t> octets_;
};
/*********************
common 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)
{
uint32_t byte_idx = idx / 8;
uint32_t offset = idx % 8;
return (ptr[byte_idx] & (1 << offset)) > 0;
}
inline void bitstring_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] |= (1 << offset);
} else {
ptr[byte_idx] &= ((uint16_t)(1 << 8) - 1) - (1 << offset);
}
}
/*********************
fixed_bitstring
*********************/
// 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);
template <uint32_t N>
class fixed_bitstring
{
public:
fixed_bitstring() { memset(&octets_[0], 0, nof_octets()); }
fixed_bitstring(const std::string& s)
{
if (s.size() != N) {
srsasn_log_print(LOG_LEVEL_ERROR, "The provided string size=%d does not match the bit string size=%d\n", s.size(),
N);
}
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 fixed_bitstring<N>& other) const { return octets_ == other.octets_; }
bool operator==(const char* other_str) const
{
return strlen(other_str) == N and (*this) == fixed_bitstring<N>(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()); }
fixed_bitstring<N>& from_number(uint64_t val)
{
number_to_bitstring(&octets_[0], val, length());
return *this;
}
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 pack(bit_ref& bref, bool ext) const { return pack_fixed_bitstring(bref, data(), N, ext); }
SRSASN_CODE unpack(bit_ref& bref) { return unpack_fixed_bitstring(data(), bref, N); }
SRSASN_CODE unpack(bit_ref& bref, bool& ext) { return unpack_fixed_bitstring(data(), ext, bref, N); }
private:
fixed_array<uint8_t, (uint32_t)((N + 7) / 8)> octets_; // ceil(N/8.0)
};
/*********************
dyn_bitstring
*********************/
class dyn_bitstring
{
public:
dyn_bitstring() : n_bits(0) {}
dyn_bitstring(uint32_t n_bits_);
dyn_bitstring(const char* s);
bool operator==(const dyn_bitstring& other) const { return octets_ == other.octets_; }
bool operator==(const char* other_str) const;
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); }
void resize(uint32_t new_size);
uint32_t length() const { return n_bits; }
uint32_t nof_octets() const { return (uint32_t)ceilf(length() / 8.0f); }
std::string to_string() const { return bitstring_to_string(&octets_[0], length()); }
uint64_t to_number() const { return bitstring_to_number(&octets_[0], length()); }
dyn_bitstring& from_number(uint64_t val)
{
number_to_bitstring(&octets_[0], val, length());
return *this;
}
const uint8_t* data() const { return &octets_[0]; }
uint8_t* data() { return &octets_[0]; }
SRSASN_CODE pack(bit_ref& bref, uint32_t lb = 0, uint32_t ub = 0) const;
SRSASN_CODE pack(bit_ref& bref, bool ext, uint32_t lb = 0, uint32_t ub = 0) const;
SRSASN_CODE unpack(bit_ref& bref, uint32_t lb = 0, uint32_t ub = 0);
SRSASN_CODE unpack(bit_ref& bref, bool& ext, uint32_t lb = 0, uint32_t ub = 0);
private:
dyn_array<uint8_t> octets_;
uint32_t n_bits;
};
/*********************
fixed sequence of
*********************/
// packers/unpackers for fixed_length sequence-of
template <class T, class ItemPacker>
SRSASN_CODE pack_fixed_seq_of(bit_ref& bref, const T* item_array, uint32_t nof_items, ItemPacker packer)
{
for (uint32_t i = 0; i < nof_items; ++i) {
HANDLE_CODE(packer.pack(bref, item_array[i]));
}
return SRSASN_SUCCESS;
}
template <class T>
SRSASN_CODE pack_fixed_seq_of(bit_ref& bref, const T* item_array, uint32_t nof_items)
{
for (uint32_t i = 0; i < nof_items; ++i) {
HANDLE_CODE(item_array[i].pack(bref));
}
return SRSASN_SUCCESS;
}
template <class T, class ItemUnpacker>
SRSASN_CODE unpack_fixed_seq_of(T* item_array, bit_ref& bref, uint32_t nof_items, ItemUnpacker unpacker)
{
for (uint32_t i = 0; i < nof_items; ++i) {
HANDLE_CODE(unpacker.unpack(item_array[i], bref));
}
return SRSASN_SUCCESS;
}
template <class T>
SRSASN_CODE unpack_fixed_seq_of(T* item_array, bit_ref& bref, uint32_t nof_items)
{
for (uint32_t i = 0; i < nof_items; ++i) {
HANDLE_CODE(item_array[i].unpack(bref));
}
return SRSASN_SUCCESS;
}
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()) {}
template <typename T>
SRSASN_CODE pack(bit_ref& bref, const T* topack)
{
return pack_fixed_seq_of(bref, topack, nof_items, packer);
}
template <typename T>
SRSASN_CODE unpack(T* tounpack, bit_ref& bref)
{
return unpack_fixed_seq_of(tounpack, bref, nof_items, packer);
}
uint32_t nof_items;
ItemPacker packer;
};
/*********************
dyn sequence of
*********************/
template <class ArrayType, class ItemPacker>
SRSASN_CODE pack_dyn_seq_of(bit_ref& bref, const ArrayType& seqof, uint32_t lb, uint32_t ub, ItemPacker packer)
{
HANDLE_CODE(pack_length(bref, seqof.size(), lb, ub));
for (uint32_t i = 0; i < seqof.size(); ++i) {
HANDLE_CODE(packer.pack(bref, seqof[i]));
}
return SRSASN_SUCCESS;
}
template <class ArrayType>
SRSASN_CODE pack_dyn_seq_of(bit_ref& bref, const ArrayType& seqof, uint32_t lb, uint32_t ub)
{
HANDLE_CODE(pack_length(bref, seqof.size(), lb, ub));
for (uint32_t i = 0; i < seqof.size(); ++i) {
HANDLE_CODE(seqof[i].pack(bref));
}
return SRSASN_SUCCESS;
}
template <class ArrayType, class ItemUnpacker>
SRSASN_CODE unpack_dyn_seq_of(ArrayType& seqof, bit_ref& bref, uint32_t lb, uint32_t ub, ItemUnpacker unpacker)
{
uint32_t nof_items;
HANDLE_CODE(unpack_length(nof_items, bref, lb, ub));
seqof.resize(nof_items);
for (uint32_t i = 0; i < nof_items; ++i) {
HANDLE_CODE(unpacker.unpack(seqof[i], bref));
}
return SRSASN_SUCCESS;
}
template <class ArrayType>
SRSASN_CODE unpack_dyn_seq_of(ArrayType& seqof, bit_ref& bref, uint32_t lb, uint32_t ub)
{
uint32_t nof_items;
HANDLE_CODE(unpack_length(nof_items, bref, lb, ub));
seqof.resize(nof_items);
for (uint32_t i = 0; i < nof_items; ++i) {
HANDLE_CODE(seqof[i].unpack(bref));
}
return SRSASN_SUCCESS;
}
template <class InnerPacker>
struct SeqOfPacker {
SeqOfPacker(uint32_t lb_, uint32_t ub_, InnerPacker packer_) : lb(lb_), ub(ub_), packer(packer_) {}
template <typename T>
SRSASN_CODE pack(bit_ref& bref, const T& topack)
{
return pack_dyn_seq_of(bref, topack, lb, ub, packer);
}
template <typename T>
SRSASN_CODE unpack(T& tounpack, bit_ref& bref)
{
return unpack_dyn_seq_of(tounpack, bref, lb, ub, packer);
}
InnerPacker packer;
uint32_t lb;
uint32_t ub;
};
/*********************
choice utils
*********************/
union alignment_t {
char c;
float f;
uint32_t i;
uint64_t i2;
double d;
long double d2;
uint32_t* ptr;
};
#define MAX2(a, b) ((a) > (b)) ? (a) : (b)
#define MAX4(a, b, c, d) MAX2((MAX2(a, b)), MAX2(c, d))
#define MAX8(a, b, c, d, e, f, g, h) MAX2((MAX4(a, b, c, d)), (MAX4(e, f, g, h)))
#define MAX12(a, b, c, d, e, f, g, h, i, j, k, l) MAX2((MAX8(a, b, c, d, e, f, g, h)), (MAX4(i, j, k, l)))
#define MAX16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
MAX2((MAX8(a, b, c, d, e, f, g, h)), (MAX8(i, j, k, l, m, n, o, p)))
#define MAX32(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, \
o1, p1) \
MAX2((MAX16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)), \
(MAX16(a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1)))
template <size_t SIZE>
class choice_buffer_t
{
public:
struct __attribute__((__may_alias__)) bytes {
uint8_t buf_[MAX2(SIZE, 8)];
uint8_t* data() { return &buf_[0]; }
const uint8_t* data() const { return &buf_[0]; }
};
template <typename T>
T& get()
{
return *((T*)buffer.buf_.data());
}
template <typename T>
const T& get() const
{
return *((T*)buffer.buf_.data());
}
template <typename T>
void destroy()
{
((T*)buffer.buf_.data())->~T();
}
template <typename T>
void init()
{
new (buffer.buf_.data()) T();
}
template <typename T>
void init(const T& other)
{
new (buffer.buf_.data()) T(other);
}
template <typename T>
void set(const T& other)
{
get<T>() = other;
}
private:
union {
alignment_t a_;
bytes buf_;
} buffer;
};
/*********************
copy_ptr
*********************/
template <class T>
class copy_ptr
{
public:
copy_ptr() : ptr(NULL) {}
explicit copy_ptr(T* ptr_) :
ptr(ptr_) {} // it takes hold of the pointer (including destruction). You should use make_copy_ptr() in most cases
// instead of this ctor
copy_ptr(const copy_ptr<T>& other) { ptr = other.make_obj_(); } // it allocates new memory for the new object
~copy_ptr() { destroy_(); }
inline copy_ptr<T>& operator=(const copy_ptr<T>& other)
{
if (this != &other) {
acquire(other.make_obj_());
}
return *this;
}
inline bool operator==(const copy_ptr<T>& other) const { return *ptr == *other; }
inline T* operator->() { return ptr; }
inline const T* operator->() const { return ptr; }
inline T& operator*() { return *ptr; } // like pointers, don't call this if ptr==NULL
inline const T& operator*() const { return *ptr; } // like pointers, don't call this if ptr==NULL
inline T* get() { return ptr; }
inline const T* get() const { return ptr; }
inline T* release()
{
T* ret = ptr;
ptr = NULL;
return ret;
}
inline void acquire(T* ptr_)
{
destroy_();
ptr = ptr_;
}
inline void reset() { acquire(NULL); }
private:
inline void destroy_()
{
if (ptr != NULL) {
delete ptr;
}
}
inline T* make_obj_() const { return (ptr == NULL) ? NULL : new T(*ptr); }
T* ptr;
};
template <class T>
copy_ptr<T> make_copy_ptr(const T& t)
{
return copy_ptr<T>(new T(t));
}
/*********************
ext group
*********************/
class ext_groups_header
{
public:
ext_groups_header(uint32_t max_nof_groups, uint32_t nof_nogroups_ = 0);
bool& operator[](uint32_t idx);
SRSASN_CODE pack_nof_groups(bit_ref& bref) const;
SRSASN_CODE pack_group_flags(bit_ref& bref) const;
SRSASN_CODE pack(bit_ref& bref) const;
SRSASN_CODE unpack_nof_groups(bit_ref& bref);
SRSASN_CODE unpack_group_flags(bit_ref& bref);
SRSASN_CODE unpack(bit_ref& bref);
private:
mutable uint32_t nof_groups;
const uint32_t nof_nogroups;
bounded_array<bool, 20> groups;
};
/*********************
Var Length Field
*********************/
class varlength_field_pack_guard
{
public:
varlength_field_pack_guard(bit_ref& bref);
~varlength_field_pack_guard();
private:
bit_ref brefstart;
// bit_ref bref0;
bit_ref* bref_tracker;
uint8_t buffer[1024];
};
class varlength_field_unpack_guard
{
public:
varlength_field_unpack_guard(bit_ref& bref);
~varlength_field_unpack_guard();
private:
bit_ref bref0;
bit_ref* bref_tracker;
uint32_t len;
};
/*******************
JsonWriter
*******************/
class json_writer
{
public:
json_writer();
void write_fieldname(const std::string& fieldname);
void write_str(const std::string& fieldname, const std::string& value);
void write_str(const std::string& value);
void write_int(const std::string& fieldname, int64_t value);
void write_int(int64_t value);
void write_bool(const std::string& fieldname, bool value);
void write_bool(bool value);
void write_null(const std::string& fieldname);
void write_null();
void start_obj(const std::string& fieldname = "");
void end_obj();
void start_array(const std::string& fieldname = "");
void end_array();
std::string to_string() const;
private:
std::stringstream ss;
std::string ident;
enum separator_t { COMMA, NEWLINE, NONE };
separator_t sep;
};
} // namespace asn1
#endif // SRSASN_COMMON_UTILS_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -28,9 +28,9 @@
#define SRSLTE_BCD_HELPERS_H #define SRSLTE_BCD_HELPERS_H
#include <ctype.h> #include <ctype.h>
#include <srslte/asn1/rrc_asn1.h>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <srslte/asn1/liblte_rrc.h>
namespace srslte { namespace srslte {
@ -41,7 +41,7 @@ namespace srslte {
*****************************************************************************/ *****************************************************************************/
inline bool string_to_mcc(std::string str, uint16_t *mcc) inline bool string_to_mcc(std::string str, uint16_t *mcc)
{ {
uint32_t len = str.size(); uint32_t len = (uint32_t)str.size();
if(len != 3) { if(len != 3) {
return false; return false;
} }
@ -67,6 +67,43 @@ inline bool mcc_to_string(uint16_t mcc, std::string *str)
return true; return true;
} }
/******************************************************************************
* Convert between array of bytes and BCD-coded MCC.
* Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF.
* MCC 001 results in 0xF001
*****************************************************************************/
inline bool bytes_to_mcc(uint8_t* bytes, uint16_t* mcc)
{
*mcc = 0xF000;
*mcc |= (((uint16_t)bytes[0]) << 8u);
*mcc |= (((uint16_t)bytes[1]) << 4u);
*mcc |= (uint16_t)bytes[2];
return true;
}
inline bool mcc_to_bytes(uint16_t mcc, uint8_t* bytes)
{
if ((mcc & 0xF000) != 0xF000) {
return false;
}
bytes[0] = (uint8_t)((mcc & 0xF00) >> 8);
bytes[1] = (uint8_t)((mcc & 0x0F0) >> 4);
bytes[2] = (uint8_t)(mcc & 0x00F);
return true;
}
inline std::string mcc_bytes_to_string(asn1::rrc::mcc_l mcc_bytes)
{
std::string mcc_str;
uint16_t mcc;
bytes_to_mcc(&mcc_bytes[0], &mcc);
if (!mcc_to_string(mcc, &mcc_str)) {
mcc_str = "000";
}
return mcc_str;
}
/****************************************************************************** /******************************************************************************
* Convert between string and BCD-coded MNC. * Convert between string and BCD-coded MNC.
* Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF. * Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF.
@ -113,13 +150,101 @@ inline bool mnc_to_string(uint16_t mnc, std::string *str)
*str += (mnc & 0x000F) + '0'; *str += (mnc & 0x000F) + '0';
return true; return true;
} }
inline std::string plmn_id_to_string(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
/******************************************************************************
* Convert between array of bytes and BCD-coded MNC.
* Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF.
* MNC 001 results in 0xF001
* MNC 01 results in 0xFF01
*****************************************************************************/
inline bool bytes_to_mnc(uint8_t* bytes, uint16_t* mnc, uint8_t len)
{
if (len != 3 && len != 2) {
*mnc = 0;
return false;
}
if (len == 3) {
*mnc = 0xF000;
*mnc |= ((uint16_t)bytes[0]) << 8u;
*mnc |= ((uint16_t)bytes[1]) << 4u;
*mnc |= ((uint16_t)bytes[2]) << 0u;
}
if (len == 2) {
*mnc = 0xFF00;
*mnc |= ((uint16_t)bytes[0]) << 4u;
*mnc |= ((uint16_t)bytes[1]) << 0u;
}
return true;
}
inline bool mnc_to_bytes(uint16_t mnc, uint8_t* bytes, uint8_t* len)
{
if ((mnc & 0xF000) != 0xF000) {
*len = 0;
return false;
}
uint8_t count = 0;
if ((mnc & 0xFF00) != 0xFF00) {
bytes[count++] = (mnc & 0xF00) >> 8u;
}
bytes[count++] = (mnc & 0x00F0) >> 4u;
bytes[count++] = (mnc & 0x000F);
*len = count;
return true;
}
template <class Vec>
bool mnc_to_bytes(uint16_t mnc, Vec& vec)
{
uint8_t len;
uint8_t v[3];
bool ret = mnc_to_bytes(mnc, &v[0], &len);
vec.resize(len);
memcpy(&vec[0], &v[0], len);
return ret;
}
inline std::string mnc_bytes_to_string(asn1::rrc::mnc_l mnc_bytes)
{
std::string mnc_str;
uint16_t mnc;
bytes_to_mnc(&mnc_bytes[0], &mnc, mnc_bytes.size());
if (!mnc_to_string(mnc, &mnc_str)) {
mnc_str = "000";
}
return mnc_str;
}
inline std::string plmn_id_to_string(asn1::rrc::plmn_id_s plmn_id)
{
std::string mcc_str, mnc_str; std::string mcc_str, mnc_str;
mnc_to_string(plmn_id.mnc, &mnc_str); uint16_t mnc, mcc;
mcc_to_string(plmn_id.mcc, &mcc_str); bytes_to_mnc(&plmn_id.mnc[0], &mnc, plmn_id.mnc.size());
bytes_to_mcc(&plmn_id.mcc[0], &mcc);
mnc_to_string(mnc, &mnc_str);
mcc_to_string(mcc, &mcc_str);
return mcc_str + mnc_str; return mcc_str + mnc_str;
} }
inline bool string_to_plmn_id(asn1::rrc::plmn_id_s& plmn, std::string mccmnc_str)
{
if (mccmnc_str.size() < 5 or mccmnc_str.size() > 6) {
return false;
}
uint16_t mnc, mcc;
if (not string_to_mcc(std::string(mccmnc_str.begin(), mccmnc_str.begin() + 3), &mcc)) {
return false;
}
if (not string_to_mnc(std::string(mccmnc_str.begin() + 3, mccmnc_str.end()), &mnc)) {
return false;
}
plmn.mcc_present = true;
if (not mcc_to_bytes(mcc, &plmn.mcc[0])) {
return false;
}
return mnc_to_bytes(mnc, plmn.mnc);
}
/****************************************************************************** /******************************************************************************
* Convert PLMN to BCD-coded MCC and MNC. * Convert PLMN to BCD-coded MCC and MNC.
* Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF. * Digits are represented by 4-bit nibbles. Unused nibbles are filled with 0xF.

@ -205,15 +205,15 @@ public:
if (!pool->deallocate(b)) { if (!pool->deallocate(b)) {
if (log) { if (log) {
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
log->error("Deallocating PDU: Addr=0x%lx, name=%s not found in pool\n", (uint64_t) b, b->debug_name); log->error("Deallocating PDU: Addr=0x%p, name=%s not found in pool\n", b, b->debug_name);
#else #else
log->error("Deallocating PDU: Addr=0x%lx\n", (uint64_t) b); log->error("Deallocating PDU: Addr=0x%p\n", b);
#endif #endif
} else { } else {
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
printf("Error deallocating PDU: Addr=0x%lx, name=%s not found in pool\n", (uint64_t) b, b->debug_name); printf("Error deallocating PDU: Addr=0x%p, name=%s not found in pool\n", b, b->debug_name);
#else #else
printf("Error deallocating PDU: Addr=0x%lx\n", (uint64_t) b); printf("Error deallocating PDU: Addr=0x%p\n", b);
#endif #endif
} }
} }

@ -191,8 +191,7 @@ public:
#endif #endif
} }
private: private:
#ifdef ENABLE_TIMESTAMP #ifdef ENABLE_TIMESTAMP
struct timeval timestamp[3]; struct timeval timestamp[3];
bool timestamp_is_set; bool timestamp_is_set;

@ -29,7 +29,6 @@
#include "srslte/common/timers.h" #include "srslte/common/timers.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/asn1/liblte_rrc.h"
#include <string> #include <string>

@ -52,9 +52,11 @@ public:
void write_dl_pch(uint8_t *pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti); void write_dl_pch(uint8_t *pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti);
void write_dl_mch(uint8_t *pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti); void write_dl_mch(uint8_t *pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti);
void write_ul_rrc_pdu(const uint8_t* input, const int32_t input_len);
private: private:
bool enable_write; bool enable_write;
FILE *pcap_file; FILE* pcap_file;
uint32_t ue_id; uint32_t ue_id;
void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti, void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti,
uint16_t crnti_, uint8_t direction, uint8_t rnti_type); uint16_t crnti_, uint8_t direction, uint8_t rnti_type);

@ -26,13 +26,13 @@
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srslte/asn1/liblte_s1ap.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/security.h"
#include "srslte/common/interfaces_common.h" #include "srslte/common/interfaces_common.h"
#include "srslte/common/security.h"
#include "srslte/interfaces/sched_interface.h" #include "srslte/interfaces/sched_interface.h"
#include "srslte/upper/rlc_interface.h" #include "srslte/upper/rlc_interface.h"
#include "srslte/asn1/liblte_rrc.h"
#include "srslte/asn1/liblte_s1ap.h"
#include <vector> #include <vector>
@ -96,23 +96,21 @@ public:
class phy_interface_rrc class phy_interface_rrc
{ {
public: public:
struct phy_cfg_mbsfn_t {
typedef struct { asn1::rrc::mbsfn_sf_cfg_s mbsfn_subfr_cnfg;
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT mbsfn_subfr_cnfg; asn1::rrc::mbms_notif_cfg_r9_s mbsfn_notification_cnfg;
LIBLTE_RRC_MBSFN_NOTIFICATION_CONFIG_STRUCT mbsfn_notification_cnfg; asn1::rrc::mbsfn_area_info_r9_s mbsfn_area_info;
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT mbsfn_area_info; asn1::rrc::mcch_msg_s mcch;
LIBLTE_RRC_MCCH_MSG_STRUCT mcch; };
} phy_cfg_mbsfn_t;
typedef struct { typedef struct {
phy_cfg_mbsfn_t mbsfn; phy_cfg_mbsfn_t mbsfn;
} phy_rrc_cfg_t; } phy_rrc_cfg_t;
virtual void configure_mbsfn(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13,
virtual void configure_mbsfn(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, LIBLTE_RRC_MCCH_MSG_STRUCT mcch) = 0; asn1::rrc::mcch_msg_s mcch) = 0;
virtual void set_conf_dedicated_ack(uint16_t rnti, bool rrc_completed) = 0; virtual void set_conf_dedicated_ack(uint16_t rnti, bool rrc_completed) = 0;
virtual void set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) = 0; virtual void set_config_dedicated(uint16_t rnti, asn1::rrc::phys_cfg_ded_s* dedicated) = 0;
}; };
class mac_interface_rrc class mac_interface_rrc
@ -129,9 +127,10 @@ public:
/* Manages UE bearers and associated configuration */ /* Manages UE bearers and associated configuration */
virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t *cfg) = 0; virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t *cfg) = 0;
virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0; virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0;
virtual int set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) = 0; virtual int set_dl_ant_info(uint16_t rnti, asn1::rrc::phys_cfg_ded_s::ant_info_c_* dl_ant_info) = 0;
virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0; virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0;
virtual void write_mcch(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, LIBLTE_RRC_MCCH_MSG_STRUCT *mcch) = 0; virtual void write_mcch(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13,
asn1::rrc::mcch_msg_s* mcch) = 0;
}; };
class mac_interface_rlc class mac_interface_rlc
@ -281,7 +280,6 @@ public:
virtual void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *res) = 0; virtual void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *res) = 0;
virtual void ue_erab_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT *res) = 0; virtual void ue_erab_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT *res) = 0;
virtual bool is_mme_connected() = 0; virtual bool is_mme_connected() = 0;
// virtual void ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps) = 0;
}; };
} }

@ -35,10 +35,10 @@
#include <string> #include <string>
#include "srslte/asn1/liblte_rrc.h"
#include "srslte/asn1/liblte_mme.h" #include "srslte/asn1/liblte_mme.h"
#include "srslte/common/interfaces_common.h" #include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/interfaces_common.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/upper/rlc_interface.h" #include "srslte/upper/rlc_interface.h"
@ -63,7 +63,7 @@ public:
virtual std::string get_imei_str() = 0; virtual std::string get_imei_str() = 0;
virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0; virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0;
virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0; virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0;
virtual bool get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 0; virtual bool get_home_plmn_id(asn1::rrc::plmn_id_s* home_plmn_id) = 0;
virtual auth_result_t generate_authentication_response(uint8_t *rand, virtual auth_result_t generate_authentication_response(uint8_t *rand,
uint8_t *autn_enb, uint8_t *autn_enb,
uint16_t mcc, uint16_t mcc,
@ -135,7 +135,7 @@ public:
BARRING_ALL BARRING_ALL
} barring_t; } barring_t;
virtual void set_barring(barring_t barring) = 0; virtual void set_barring(barring_t barring) = 0;
virtual void paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy) = 0; virtual void paging(asn1::rrc::s_tmsi_s* ue_identiy) = 0;
virtual bool is_attached() = 0; virtual bool is_attached() = 0;
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_k_enb_count() = 0; virtual uint32_t get_k_enb_count() = 0;
@ -188,7 +188,7 @@ class rrc_interface_nas
{ {
public: public:
typedef struct { typedef struct {
LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id; asn1::rrc::plmn_id_s plmn_id;
uint16_t tac; uint16_t tac;
} found_plmn_t; } found_plmn_t;
@ -199,10 +199,9 @@ public:
virtual uint16_t get_mnc() = 0; virtual uint16_t get_mnc() = 0;
virtual void enable_capabilities() = 0; virtual void enable_capabilities() = 0;
virtual int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]) = 0; virtual int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]) = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0; virtual void plmn_select(asn1::rrc::plmn_id_s plmn_id) = 0;
virtual bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, virtual bool connection_request(asn1::rrc::establishment_cause_e cause, srslte::byte_buffer_t* dedicatedInfoNAS) = 0;
srslte::byte_buffer_t *dedicatedInfoNAS) = 0; virtual void set_ue_idenity(asn1::rrc::s_tmsi_s s_tmsi) = 0;
virtual void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) = 0;
virtual bool is_connected() = 0; virtual bool is_connected() = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0; virtual std::string get_rb_name(uint32_t lcid) = 0;
}; };
@ -284,6 +283,7 @@ public:
virtual void del_bearer(uint32_t lcid) = 0; virtual void del_bearer(uint32_t lcid) = 0;
virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0; virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0;
virtual bool has_bearer(uint32_t lcid) = 0; virtual bool has_bearer(uint32_t lcid) = 0;
virtual bool has_data(const uint32_t lcid) = 0;
}; };
// RLC interface for PDCP // RLC interface for PDCP
@ -469,9 +469,9 @@ class mac_interface_rrc : public mac_interface_rrc_common
public: public:
typedef struct { typedef struct {
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT main; asn1::rrc::mac_main_cfg_s main;
LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach; asn1::rrc::rach_cfg_common_s rach;
LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT sr; asn1::rrc::sched_request_cfg_c sr;
ul_harq_params_t ul_harq_params; ul_harq_params_t ul_harq_params;
uint32_t prach_config_index; uint32_t prach_config_index;
} mac_cfg_t; } mac_cfg_t;
@ -493,9 +493,9 @@ public:
virtual uint32_t get_current_tti() = 0; virtual uint32_t get_current_tti() = 0;
virtual void set_config(mac_cfg_t *mac_cfg) = 0; virtual void set_config(mac_cfg_t *mac_cfg) = 0;
virtual void set_config_main(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *main_cfg) = 0; virtual void set_config_main(asn1::rrc::mac_main_cfg_s* main_cfg) = 0;
virtual void set_config_rach(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cfg, uint32_t prach_config_index) = 0; virtual void set_config_rach(asn1::rrc::rach_cfg_common_s* rach_cfg, uint32_t prach_config_index) = 0;
virtual void set_config_sr(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT *sr_cfg) = 0; virtual void set_config_sr(asn1::rrc::sched_request_cfg_c* sr_cfg) = 0;
virtual void get_config(mac_cfg_t *mac_cfg) = 0; virtual void get_config(mac_cfg_t *mac_cfg) = 0;
virtual void get_rntis(ue_rnti_t *rntis) = 0; virtual void get_rntis(ue_rnti_t *rntis) = 0;
@ -607,29 +607,27 @@ public:
class phy_interface_rrc class phy_interface_rrc
{ {
public: public:
struct phy_cfg_common_t {
asn1::rrc::prach_cfg_sib_s prach_cnfg;
asn1::rrc::pdsch_cfg_common_s pdsch_cnfg;
asn1::rrc::pusch_cfg_common_s pusch_cnfg;
asn1::rrc::phich_cfg_s phich_cnfg;
asn1::rrc::pucch_cfg_common_s pucch_cnfg;
asn1::rrc::srs_ul_cfg_common_c srs_ul_cnfg;
asn1::rrc::ul_pwr_ctrl_common_s ul_pwr_ctrl;
asn1::rrc::tdd_cfg_s tdd_cnfg;
asn1::rrc::srs_ant_port_e ant_info;
};
struct phy_cfg_mbsfn_t {
asn1::rrc::mbsfn_sf_cfg_s mbsfn_subfr_cnfg;
asn1::rrc::mbms_notif_cfg_r9_s mbsfn_notification_cnfg;
asn1::rrc::mbsfn_area_info_r9_s mbsfn_area_info;
asn1::rrc::mcch_msg_s mcch;
};
typedef struct { typedef struct {
LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT prach_cnfg; asn1::rrc::phys_cfg_ded_s dedicated;
LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT pdsch_cnfg;
LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT pusch_cnfg;
LIBLTE_RRC_PHICH_CONFIG_STRUCT phich_cnfg;
LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT pucch_cnfg;
LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT srs_ul_cnfg;
LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT ul_pwr_ctrl;
LIBLTE_RRC_TDD_CONFIG_STRUCT tdd_cnfg;
LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM ant_info;
} phy_cfg_common_t;
typedef struct {
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT mbsfn_subfr_cnfg;
LIBLTE_RRC_MBSFN_NOTIFICATION_CONFIG_STRUCT mbsfn_notification_cnfg;
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT mbsfn_area_info;
LIBLTE_RRC_MCCH_MSG_STRUCT mcch;
} phy_cfg_mbsfn_t;
typedef struct {
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT dedicated;
phy_cfg_common_t common; phy_cfg_common_t common;
phy_cfg_mbsfn_t mbsfn; phy_cfg_mbsfn_t mbsfn;
bool enable_64qam; bool enable_64qam;
@ -641,13 +639,13 @@ public:
virtual void get_config(phy_cfg_t *phy_cfg) = 0; virtual void get_config(phy_cfg_t *phy_cfg) = 0;
virtual void set_config(phy_cfg_t *phy_cfg) = 0; virtual void set_config(phy_cfg_t *phy_cfg) = 0;
virtual void set_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated) = 0; virtual void set_config_dedicated(asn1::rrc::phys_cfg_ded_s* dedicated) = 0;
virtual void set_config_common(phy_cfg_common_t *common) = 0; virtual void set_config_common(phy_cfg_common_t *common) = 0;
virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0; virtual void set_config_tdd(asn1::rrc::tdd_cfg_s* tdd) = 0;
virtual void set_config_64qam_en(bool enable) = 0; virtual void set_config_64qam_en(bool enable) = 0;
virtual void set_config_mbsfn_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) = 0; virtual void set_config_mbsfn_sib2(asn1::rrc::sib_type2_s* sib2) = 0;
virtual void set_config_mbsfn_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) = 0; virtual void set_config_mbsfn_sib13(asn1::rrc::sib_type13_r9_s* sib13) = 0;
virtual void set_config_mbsfn_mcch(LIBLTE_RRC_MCCH_MSG_STRUCT *mcch) = 0; virtual void set_config_mbsfn_mcch(asn1::rrc::mcch_msg_s* mcch) = 0;
/* Measurements interface */ /* Measurements interface */
virtual void meas_reset() = 0; virtual void meas_reset() = 0;

@ -244,11 +244,17 @@ SRSLTE_API int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API int srslte_ra_tbs_idx_from_mcs(uint32_t mcs); SRSLTE_API int srslte_ra_dl_tbs_idx_from_mcs(uint32_t mcs);
SRSLTE_API srslte_mod_t srslte_ra_mod_from_mcs(uint32_t mcs); SRSLTE_API int srslte_ra_ul_tbs_idx_from_mcs(uint32_t mcs);
SRSLTE_API int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx); SRSLTE_API srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs);
SRSLTE_API srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs);
SRSLTE_API int srslte_ra_dl_mcs_from_tbs_idx(uint32_t tbs_idx);
SRSLTE_API int srslte_ra_ul_mcs_from_tbs_idx(uint32_t tbs_idx);
SRSLTE_API int srslte_ra_tbs_from_idx(uint32_t tbs_idx, SRSLTE_API int srslte_ra_tbs_from_idx(uint32_t tbs_idx,
uint32_t n_prb); uint32_t n_prb);

@ -28,7 +28,7 @@
#define SRSLTE_RLC_INTERFACE_H #define SRSLTE_RLC_INTERFACE_H
// for custom constructors // for custom constructors
#include <srslte/asn1/liblte_rrc.h> #include "srslte/asn1/rrc_asn1.h"
namespace srslte { namespace srslte {
@ -42,15 +42,14 @@ static const char rlc_mode_text[RLC_MODE_N_ITEMS][20] = {"Transparent Mode",
"Unacknowledged Mode", "Unacknowledged Mode",
"Acknowledged Mode"}; "Acknowledged Mode"};
typedef enum{ typedef enum {
RLC_UMD_SN_SIZE_5_BITS = 0, RLC_UMD_SN_SIZE_5_BITS = 0,
RLC_UMD_SN_SIZE_10_BITS, RLC_UMD_SN_SIZE_10_BITS,
RLC_UMD_SN_SIZE_N_ITEMS, RLC_UMD_SN_SIZE_N_ITEMS,
}rlc_umd_sn_size_t; } rlc_umd_sn_size_t;
static const char rlc_umd_sn_size_text[RLC_UMD_SN_SIZE_N_ITEMS][20] = {"5 bits", "10 bits"}; static const char rlc_umd_sn_size_text[RLC_UMD_SN_SIZE_N_ITEMS][20] = {"5 bits", "10 bits"};
static const uint16_t rlc_umd_sn_size_num[RLC_UMD_SN_SIZE_N_ITEMS] = {5, 10}; static const uint16_t rlc_umd_sn_size_num[RLC_UMD_SN_SIZE_N_ITEMS] = {5, 10};
typedef struct { typedef struct {
/**************************************************************************** /****************************************************************************
* Configurable parameters * Configurable parameters
@ -68,7 +67,6 @@ typedef struct {
int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms) int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms)
} srslte_rlc_am_config_t; } srslte_rlc_am_config_t;
typedef struct { typedef struct {
/**************************************************************************** /****************************************************************************
* Configurable parameters * Configurable parameters
@ -85,7 +83,6 @@ typedef struct {
bool is_mrb; // Whether this is a multicast bearer bool is_mrb; // Whether this is a multicast bearer
} srslte_rlc_um_config_t; } srslte_rlc_um_config_t;
class srslte_rlc_config_t class srslte_rlc_config_t
{ {
public: public:
@ -96,30 +93,40 @@ public:
// Default ctor // Default ctor
srslte_rlc_config_t(): rlc_mode(RLC_MODE_TM), am(), um() {}; srslte_rlc_config_t(): rlc_mode(RLC_MODE_TM), am(), um() {};
// Constructor based on liblte's RLC config // Constructor based on rrc_asn1's RLC config
srslte_rlc_config_t(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) : rlc_mode(RLC_MODE_AM), am(), um() srslte_rlc_config_t(asn1::rrc::rlc_cfg_c* cnfg) : rlc_mode(RLC_MODE_AM), am(), um()
{ {
// update RLC mode to internal mode struct // update RLC mode to internal mode struct
rlc_mode = (cnfg->rlc_mode == LIBLTE_RRC_RLC_MODE_AM) ? RLC_MODE_AM : RLC_MODE_UM; rlc_mode = (cnfg->type() == asn1::rrc::rlc_cfg_c::types::am) ? RLC_MODE_AM : RLC_MODE_UM;
switch(rlc_mode) switch(rlc_mode)
{ {
case RLC_MODE_AM: case RLC_MODE_AM:
am.t_poll_retx = liblte_rrc_t_poll_retransmit_num[cnfg->ul_am_rlc.t_poll_retx]; am.t_poll_retx = cnfg->am().ul_am_rlc.t_poll_retx.to_number();
am.poll_pdu = liblte_rrc_poll_pdu_num[cnfg->ul_am_rlc.poll_pdu]; am.poll_pdu = cnfg->am().ul_am_rlc.poll_pdu.to_number();
am.poll_byte = liblte_rrc_poll_byte_num[cnfg->ul_am_rlc.poll_byte]*1000; // KB am.poll_byte = cnfg->am().ul_am_rlc.poll_byte.to_number() * 1000; // KB
am.max_retx_thresh = liblte_rrc_max_retx_threshold_num[cnfg->ul_am_rlc.max_retx_thresh]; am.max_retx_thresh = cnfg->am().ul_am_rlc.max_retx_thres.to_number();
am.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_am_rlc.t_reordering]; am.t_reordering = cnfg->am().dl_am_rlc.t_reordering.to_number();
am.t_status_prohibit = liblte_rrc_t_status_prohibit_num[cnfg->dl_am_rlc.t_status_prohibit]; am.t_status_prohibit = cnfg->am().dl_am_rlc.t_status_prohibit.to_number();
break; break;
case RLC_MODE_UM: case RLC_MODE_UM:
um.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_bi_rlc.t_reordering]; um.t_reordering = cnfg->um_bi_dir().dl_um_rlc.t_reordering.to_number();
um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_bi_rlc.sn_field_len; um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->um_bi_dir().dl_um_rlc.sn_field_len.value;
um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512; um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512;
um.rx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 32 : 1024; um.rx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 32 : 1024;
um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_bi_rlc.sn_field_len; um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->um_bi_dir().ul_um_rlc.sn_field_len.value;
um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024; um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024;
break; break;
// case asn1::rrc::rlc_cfg_c::types::um_uni_dir_ul:
// um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->um_uni_dir_ul().ul_um_rlc.sn_field_len.value;
// um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024;
// break;
// case asn1::rrc::rlc_cfg_c::types::um_uni_dir_dl:
// um.t_reordering = cnfg->um_uni_dir_dl().dl_um_rlc.t_reordering.to_number();
// um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->um_uni_dir_dl().dl_um_rlc.sn_field_len.value;
// um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512;
// um.rx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 32 : 1024;
// break;
default: default:
// Handle default case // Handle default case
break; break;

@ -21,10 +21,16 @@
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch -Wno-unused-but-set-variable -Wno-unused-variable -Wno-return-type -Wno-sign-compare -Wno-reorder -Wno-parantheses") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch -Wno-unused-but-set-variable -Wno-unused-variable -Wno-return-type -Wno-sign-compare -Wno-reorder -Wno-parantheses")
add_library(srslte_asn1 STATIC add_library(srslte_asn1 STATIC
liblte_common.cc liblte_common.cc
liblte_rrc.cc
liblte_mme.cc liblte_mme.cc
liblte_s1ap.cc liblte_s1ap.cc
liblte_m2ap.cc liblte_m2ap.cc
gtpc.cc gtpc.cc
) )
install(TARGETS srslte_asn1 DESTINATION ${LIBRARY_DIR}) install(TARGETS srslte_asn1 DESTINATION ${LIBRARY_DIR})
add_library(rrc_asn1 STATIC
rrc_asn1.cc
rrc_asn1_enum.cc
asn1_utils.cc
)
install(TARGETS rrc_asn1 DESTINATION ${LIBRARY_DIR})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -103,5 +103,76 @@ void mac_pcap::write_dl_sirnti(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok
pack_and_write(pdu, pdu_len_bytes, 0, crc_ok, tti, SRSLTE_SIRNTI, DIRECTION_DOWNLINK, SI_RNTI); pack_and_write(pdu, pdu_len_bytes, 0, crc_ok, tti, SRSLTE_SIRNTI, DIRECTION_DOWNLINK, SI_RNTI);
} }
void mac_pcap::write_ul_rrc_pdu(const uint8_t* input, const int32_t input_len)
{
uint8_t pdu[1024];
bzero(pdu, sizeof(pdu));
// Size is limited by PDU buffer and MAC subheader (format 1 < 128 B)
if (input_len > 128 - 7) {
printf("PDU too large.\n");
return;
}
// MAC PDU Header (Short BSR) (1:54) (Padding:remainder) [3 subheaders]
// Sub-header (lcid=Short BSR)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..1. .... = Extension: 0x1
// ...1 1101 = LCID: Short BSR (0x1d)
// Sub-header (lcid=1, length=54)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..1. .... = Extension: 0x1
// ...0 0001 = LCID: 1 (0x01)
// 0... .... = Format: Data length is < 128 bytes
// .011 0110 = Length: 54 (Will be dynamically updated)
// Sub-header (lcid=Padding, length is remainder)
// 0... .... = SCH reserved bit: 0x0
// .0.. .... = Format2: Data length is < 32768 bytes
// ..0. .... = Extension: 0x0
// ...1 1111 = LCID: Padding (0x1f)
uint8_t mac_hdr[] = {0x3D, 0x21, 0x36, 0x1F, 0x0C};
// Update MAC length
mac_hdr[2] = input_len + 7; // rlc_hdr (2) + pdcp_hdr (1) + MAC (4)
// AM Header (P) sn=4
// 1... .... = Frame type: Data PDU (0x1)
// .0.. .... = Re-segmentation Flag: AMD PDU (0x0)
// ..1. .... = Polling Bit: Status report is requested (0x1)
// ...0 0... = Framing Info: First byte begins a RLC SDU and last byte ends a RLC SDU (0x0)
// .... .0.. = Extension: Data field follows from the octet following the fixed part of the header (0x0)
// .... ..00 0000 0100 = Sequence Number: 4
uint8_t rlc_hdr[] = {0xA0, 0x04};
// PDCP-LTE sn=3
// 000. .... = Reserved: 0
// ...0 0011 = Seq Num: 3
uint8_t pdcp_hdr[] = {0x03};
uint8_t* pdu_ptr = pdu;
memcpy(pdu_ptr, mac_hdr, sizeof(mac_hdr));
pdu_ptr += sizeof(mac_hdr);
memcpy(pdu_ptr, rlc_hdr, sizeof(rlc_hdr));
pdu_ptr += sizeof(rlc_hdr);
memcpy(pdu_ptr, pdcp_hdr, sizeof(pdcp_hdr));
pdu_ptr += sizeof(pdcp_hdr);
memcpy(pdu_ptr, input, input_len);
pdu_ptr += input_len;
// MAC
uint8_t pad = 0x00;
for (uint32_t i = 0; i < 4; i++) {
memcpy(pdu_ptr, &pad, 1);
pdu_ptr += 1;
}
// Pad
memcpy(pdu_ptr, &pad, 1);
pdu_ptr += 1;
write_ul_crnti(pdu, pdu_ptr - pdu, 14931, true, 0);
}
} }

@ -189,17 +189,9 @@ int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_
static void ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant) { static void ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant) {
// 8.6.2 First paragraph // 8.6.2 First paragraph
if (dci->mcs_idx <= 28) { if (dci->mcs_idx <= 28) {
/* Table 8.6.1-1 on 36.213 */ grant->mcs.mod = srslte_ra_ul_mod_from_mcs(dci->mcs_idx);
if (dci->mcs_idx < 11) { grant->mcs.tbs = srslte_ra_tbs_from_idx(srslte_ra_ul_tbs_idx_from_mcs(dci->mcs_idx), grant->L_prb);
grant->mcs.mod = SRSLTE_MOD_QPSK; if (grant->mcs.mod >= SRSLTE_MOD_LAST || grant->mcs.tbs < 0) {
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb);
} else if (dci->mcs_idx < 21) {
grant->mcs.mod = SRSLTE_MOD_16QAM;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb);
} else if (dci->mcs_idx < 29) {
grant->mcs.mod = SRSLTE_MOD_64QAM;
grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb);
} else {
fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx); fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx);
} }
} else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) { } else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) {
@ -694,15 +686,26 @@ uint32_t srslte_ra_type2_n_vrb_dl(uint32_t nof_prb, bool ngap_is_1) {
} }
/* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v10.3.0 table 7.1.7.1-1 */ /* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v10.3.0 table 7.1.7.1-1 */
int srslte_ra_tbs_idx_from_mcs(uint32_t mcs) { int srslte_ra_dl_tbs_idx_from_mcs(uint32_t mcs)
{
if(mcs < 29) { if(mcs < 29) {
return mcs_tbs_idx_table[mcs]; return dl_mcs_tbs_idx_table[mcs];
} else {
return SRSLTE_ERROR;
}
}
int srslte_ra_ul_tbs_idx_from_mcs(uint32_t mcs)
{
if (mcs < 29) {
return ul_mcs_tbs_idx_table[mcs];
} else { } else {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }
srslte_mod_t srslte_ra_mod_from_mcs(uint32_t mcs) { srslte_mod_t srslte_ra_dl_mod_from_mcs(uint32_t mcs)
{
if (mcs <= 10 || mcs == 29) { if (mcs <= 10 || mcs == 29) {
return SRSLTE_MOD_QPSK; return SRSLTE_MOD_QPSK;
} else if (mcs <= 17 || mcs == 30) { } else if (mcs <= 17 || mcs == 30) {
@ -712,9 +715,34 @@ srslte_mod_t srslte_ra_mod_from_mcs(uint32_t mcs) {
} }
} }
int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx) { srslte_mod_t srslte_ra_ul_mod_from_mcs(uint32_t mcs)
for (int i=0;i<29;i++) { {
if (tbs_idx == mcs_tbs_idx_table[i]) { /* Table 8.6.1-1 on 36.213 */
if (mcs <= 10) {
return SRSLTE_MOD_QPSK;
} else if (mcs <= 20) {
return SRSLTE_MOD_16QAM;
} else if (mcs <= 28) {
return SRSLTE_MOD_64QAM;
} else {
return SRSLTE_MOD_LAST;
}
}
int srslte_ra_dl_mcs_from_tbs_idx(uint32_t tbs_idx)
{
for (int i = 0; i < 29; i++) {
if (tbs_idx == dl_mcs_tbs_idx_table[i]) {
return i;
}
}
return SRSLTE_ERROR;
}
int srslte_ra_ul_mcs_from_tbs_idx(uint32_t tbs_idx)
{
for (int i = 0; i < 29; i++) {
if (tbs_idx == ul_mcs_tbs_idx_table[i]) {
return i; return i;
} }
} }

@ -30,10 +30,12 @@ const int tbs_format1c_table[32] = {
}; };
/* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v10.3.0 table 7.1.7.1-1 */ /* Modulation and TBS index table for PDSCH from 3GPP TS 36.213 v10.3.0 table 7.1.7.1-1 */
const int mcs_tbs_idx_table[29] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, const int dl_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13,
9, 10, 11, 12, 13, 14, 15, 15, 16, 17, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26};
18, 19, 20, 21, 22, 23, 24, 25, 26};
/* Modulation and TBS index table for PUSCH from 3GPP TS 36.213 v10.3.0 table 8.6.1-1 */
const int ul_mcs_tbs_idx_table[29] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26};
/* Transport Block Size from 3GPP TS 36.213 v10.3.0 table 7.1.7.2.1-1 */ /* Transport Block Size from 3GPP TS 36.213 v10.3.0 table 7.1.7.2.1-1 */
const int tbs_table[27][110] = {{ 16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288, const int tbs_table[27][110] = {{ 16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288,

@ -25,12 +25,13 @@
*/ */
#include <srslte/asn1/liblte_rrc.h>
#include "srslte/upper/rlc.h" #include "srslte/upper/rlc.h"
#include "srslte/upper/rlc_tm.h" #include "srslte/upper/rlc_tm.h"
#include "srslte/upper/rlc_um.h" #include "srslte/upper/rlc_um.h"
#include "srslte/upper/rlc_am.h" #include "srslte/upper/rlc_am.h"
using namespace asn1::rrc;
namespace srslte { namespace srslte {
rlc::rlc() rlc::rlc()
@ -402,14 +403,15 @@ void rlc::add_bearer(uint32_t lcid)
add_bearer(lcid, srslte_rlc_config_t()); add_bearer(lcid, srslte_rlc_config_t());
} else { } else {
// SRB1 and SRB2 are AM // SRB1 and SRB2 are AM
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg = {}; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS45; rlc_cfg_c::am_s_* amcfg = &cnfg.am();
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_INFINITY; amcfg->ul_am_rlc.t_poll_retx = t_poll_retx_e::ms45;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_INFINITY; amcfg->ul_am_rlc.poll_pdu = poll_pdu_e::p_infinity;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; amcfg->ul_am_rlc.poll_byte = poll_byte_e::kbinfinity;
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS35; amcfg->ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS0; amcfg->dl_am_rlc.t_reordering = t_reordering_e::ms35;
amcfg->dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms0;
add_bearer(lcid, srslte_rlc_config_t(&cnfg)); add_bearer(lcid, srslte_rlc_config_t(&cnfg));
} }
} }

@ -32,6 +32,8 @@
#define RX_MOD_BASE(x) (((x)-vr_uh-cfg.rx_window_size)%cfg.rx_mod) #define RX_MOD_BASE(x) (((x)-vr_uh-cfg.rx_window_size)%cfg.rx_mod)
using namespace asn1::rrc;
namespace srslte { namespace srslte {
rlc_um::rlc_um(uint32_t queue_len) rlc_um::rlc_um(uint32_t queue_len)
@ -80,9 +82,9 @@ bool rlc_um::configure(srslte_rlc_config_t cnfg_)
// store config // store config
cfg = cnfg_.um; cfg = cnfg_.um;
log->warning("%s configured in %s mode: ft_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", log->warning("%s configured in %s: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n",
rb_name.c_str(), rlc_mode_text[cnfg_.rlc_mode], rb_name.c_str(), rlc_mode_text[cnfg_.rlc_mode], cfg.t_reordering,
cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length], rlc_umd_sn_size_num[cfg.rx_sn_field_length]); rlc_umd_sn_size_num[cfg.rx_sn_field_length], rlc_umd_sn_size_num[cfg.rx_sn_field_length]);
return true; return true;
} }

@ -19,13 +19,25 @@
# #
add_executable(srslte_asn1_rrc_mcch_test srslte_asn1_rrc_mcch_test.cc) add_executable(srslte_asn1_rrc_mcch_test srslte_asn1_rrc_mcch_test.cc)
target_link_libraries(srslte_asn1_rrc_mcch_test srslte_asn1 srslte_common) target_link_libraries(srslte_asn1_rrc_mcch_test rrc_asn1 srslte_common)
add_test(srslte_asn1_rrc_mcch_test srslte_asn1_rrc_mcch_test) add_test(srslte_asn1_rrc_mcch_test srslte_asn1_rrc_mcch_test)
add_executable(srslte_asn1_rrc_meas_test srslte_asn1_rrc_meas_test.cc) add_executable(srslte_asn1_rrc_meas_test srslte_asn1_rrc_meas_test.cc)
target_link_libraries(srslte_asn1_rrc_meas_test srslte_common srslte_phy srslte_asn1) target_link_libraries(srslte_asn1_rrc_meas_test rrc_asn1 srslte_common)
add_test(srslte_asn1_rrc_meas_test srslte_asn1_rrc_meas_test) add_test(srslte_asn1_rrc_meas_test srslte_asn1_rrc_meas_test)
add_executable(srslte_asn1_rrc_ul_dcch_test srslte_asn1_rrc_ul_dcch_test.cc)
target_link_libraries(srslte_asn1_rrc_ul_dcch_test rrc_asn1 srslte_common)
add_test(srslte_asn1_rrc_ul_dcch_test srslte_asn1_rrc_ul_dcch_test)
add_executable(srslte_asn1_rrc_dl_ccch_test srslte_asn1_rrc_dl_ccch_test.cc)
target_link_libraries(srslte_asn1_rrc_dl_ccch_test rrc_asn1 srslte_common)
add_test(srslte_asn1_rrc_dl_ccch_test srslte_asn1_rrc_dl_ccch_test)
add_executable(srslte_asn1_rrc_dl_dcch_test srslte_asn1_rrc_dl_dcch_test.cc)
target_link_libraries(srslte_asn1_rrc_dl_dcch_test rrc_asn1 srslte_common)
add_test(srslte_asn1_rrc_dl_dcch_test srslte_asn1_rrc_dl_dcch_test)
add_executable(srslte_asn1_m2ap_test srslte_asn1_m2ap_test.cc) add_executable(srslte_asn1_m2ap_test srslte_asn1_m2ap_test.cc)
target_link_libraries(srslte_asn1_m2ap_test srslte_common srslte_phy srslte_asn1) target_link_libraries(srslte_asn1_m2ap_test srslte_common srslte_phy srslte_asn1)
add_test(srslte_asn1_m2ap_test srslte_asn1_m2ap_test) add_test(srslte_asn1_m2ap_test srslte_asn1_m2ap_test)

@ -1,91 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <assert.h>
#include <iostream>
#include <srslte/srslte.h>
#include "srslte/common/log_filter.h"
#include "srslte/asn1/liblte_rrc.h"
void basic_test() {
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
LIBLTE_BIT_MSG_STRUCT bit_buf;
LIBLTE_BIT_MSG_STRUCT bit_buf2;
LIBLTE_BYTE_MSG_STRUCT byte_buf;
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
uint32_t rrc_message_len = 18;
uint8_t rrc_message[] = {0x08, 0x10, 0x49, 0x3C, 0x0D, 0x97, 0x89, 0x83,
0xC0, 0x84, 0x20, 0x82, 0x08, 0x21, 0x00, 0x01,
0xBC, 0x48};
srslte_bit_unpack_vector(rrc_message, bit_buf.msg, rrc_message_len*8);
bit_buf.N_bits = rrc_message_len*8;
liblte_rrc_unpack_ul_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &ul_dcch_msg);
assert(ul_dcch_msg.msg_type == LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT);
LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *rep = &ul_dcch_msg.msg.measurement_report;
assert(rep->meas_id == 1);
assert(rep->pcell_rsrp_result == 73);
assert(rep->pcell_rsrq_result == 15);
assert(rep->have_meas_result_neigh_cells);
assert(rep->meas_result_neigh_cells_choice == LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA);
LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT *eutra = &rep->meas_result_neigh_cells.eutra;
assert(eutra->n_result == 1);
assert(eutra->result_eutra_list[0].phys_cell_id == 357);
assert(eutra->result_eutra_list[0].have_cgi_info);
assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mcc == 0xF898);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mnc == 0xFF78);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.cell_id == 0x1084104);
assert(eutra->result_eutra_list[0].cgi_info.tracking_area_code == 0x1042);
assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list);
assert(eutra->result_eutra_list[0].cgi_info.n_plmn_identity_list == 1);
assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mcc == 0xFFFF);
assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mnc == 0xFF00);
assert(eutra->result_eutra_list[0].meas_result.have_rsrp);
assert(eutra->result_eutra_list[0].meas_result.rsrp_result == 60);
assert(eutra->result_eutra_list[0].meas_result.have_rsrp);
assert(eutra->result_eutra_list[0].meas_result.rsrq_result == 18);
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT*)&bit_buf2);
srslte_bit_pack_vector(bit_buf2.msg, byte_buf.msg, bit_buf2.N_bits);
byte_buf.N_bytes = (bit_buf2.N_bits+7)/8;
log1.info_hex(byte_buf.msg, byte_buf.N_bytes, "UL_DCCH Packed message\n");
for(uint32_t i=0; i<rrc_message_len; i++) {
assert(byte_buf.msg[i] == rrc_message[i]);
}
}
int main(int argc, char **argv) {
basic_test();
}

@ -0,0 +1,129 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2019 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "../../../srsue/hdr/upper/rrc.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/bcd_helpers.h"
#include "srslte/common/log_filter.h"
#include <iostream>
using namespace asn1;
using namespace asn1::rrc;
#define TESTASSERT(cond) \
{ \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
}
int rrc_conn_setup_test1()
{
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
uint8_t rrc_msg[] = {0x60, 0x12, 0x98, 0x0b, 0xfd, 0xd2, 0x04, 0xfa, 0x18, 0x3e, 0xd5, 0xe6, 0xc2,
0x59, 0x90, 0xc1, 0xa6, 0x00, 0x01, 0x31, 0x40, 0x42, 0x50, 0x80, 0x00, 0xf8};
uint32_t rrc_msg_len = sizeof(rrc_msg);
// 6012980bfdd204fa183ed5e6c25990c1a60001314042508000f8
bit_ref bref(&rrc_msg[0], sizeof(rrc_msg));
bit_ref bref0(&rrc_msg[0], sizeof(rrc_msg));
dl_ccch_msg_s dl_ccch_msg;
dl_ccch_msg.unpack(bref);
TESTASSERT(dl_ccch_msg.msg.type() == dl_ccch_msg_type_c::types::c1);
TESTASSERT(dl_ccch_msg.msg.c1().type() == dl_ccch_msg_type_c::c1_c_::types::rrc_conn_setup);
rrc_conn_setup_s* setup = &dl_ccch_msg.msg.c1().rrc_conn_setup();
// FIXME: add test for setup
rr_cfg_ded_s* cnfg = &setup->crit_exts.c1().rrc_conn_setup_r8().rr_cfg_ded;
TESTASSERT(cnfg->phys_cfg_ded_present);
// FIXME: add tests for RR config dedicated
phys_cfg_ded_s* phy_cnfg = &cnfg->phys_cfg_ded;
TESTASSERT(phy_cnfg->cqi_report_cfg_present);
// Test CQI config
cqi_report_cfg_s* cqi_cfg = &phy_cnfg->cqi_report_cfg;
TESTASSERT(cqi_cfg->cqi_report_periodic_present);
TESTASSERT(cqi_cfg->nom_pdsch_rs_epre_offset == 0);
TESTASSERT(cqi_cfg->cqi_report_periodic.type() == setup_e::setup);
TESTASSERT(cqi_cfg->cqi_report_periodic.setup().cqi_pucch_res_idx == 0);
TESTASSERT(cqi_cfg->cqi_report_periodic.setup().cqi_pmi_cfg_idx == 38);
// test repacking
uint8_t rrc_msg2[rrc_msg_len];
bit_ref bref2(&rrc_msg2[0], sizeof(rrc_msg2));
if (dl_ccch_msg.pack(bref2) != SRSASN_SUCCESS) {
return -1;
}
TESTASSERT(bref.distance(bref0) == bref2.distance(&rrc_msg2[0]));
TESTASSERT(memcmp(rrc_msg2, rrc_msg, rrc_msg_len) == 0);
return 0;
}
// Only packing implemented
int rrc_reestablishment_reject_test()
{
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
dl_ccch_msg_s dl_ccch_msg;
dl_ccch_msg.msg.set(dl_ccch_msg_type_c::types::c1);
dl_ccch_msg.msg.c1().set(dl_ccch_msg_type_c::c1_c_::types::rrc_conn_reest_reject);
dl_ccch_msg.msg.c1().rrc_conn_reest_reject().crit_exts.set(
rrc_conn_reest_reject_s::crit_exts_c_::types::rrc_conn_reest_reject_r8);
dl_ccch_msg.msg.c1().rrc_conn_reest_reject().crit_exts.rrc_conn_reest_reject_r8();
// test repacking
uint8_t rrc_msg[32];
bit_ref bref(rrc_msg, sizeof(rrc_msg));
if (dl_ccch_msg.pack(bref) != SRSASN_SUCCESS) {
return -1;
}
int actual_len = bref.distance_bytes(rrc_msg);
log1.info_hex(rrc_msg, actual_len, "DL-CCCH message (%d/%zd B)\n", actual_len, sizeof(rrc_msg));
return 0;
}
int main(int argc, char** argv)
{
TESTASSERT(rrc_conn_setup_test1() == 0);
TESTASSERT(rrc_reestablishment_reject_test() == 0);
return 0;
}

@ -0,0 +1,84 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2019 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "../../../srsue/hdr/upper/rrc.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/bcd_helpers.h"
#include "srslte/common/log_filter.h"
#include <iostream>
using namespace asn1;
using namespace asn1::rrc;
#define TESTASSERT(cond) \
{ \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
}
int rrc_conn_reconfig_ho_test1()
{
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
uint8_t rrc_msg[] = {0x20, 0x1b, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xa9, 0x08, 0x80, 0x00, 0x00, 0x29, 0x00,
0x97, 0x80, 0x00, 0x00, 0x00, 0x01, 0x04, 0x22, 0x14, 0x00, 0xf8, 0x02, 0x0a, 0xc0, 0x60,
0x00, 0xa0, 0x0c, 0x80, 0x42, 0x02, 0x9f, 0x43, 0x07, 0xda, 0xbc, 0xf8, 0x4b, 0x32, 0x18,
0x34, 0xc0, 0x00, 0x2d, 0x68, 0x08, 0x5e, 0x18, 0x00, 0x16, 0x80, 0x00};
// 20 1b 3f 80 00 00 00 01 a9 08 80 00 00 29 00 97 80 00 00 00 01 04 22 14 00 f8 02 0a c0 60 00 a0 0c 80 42 02 9f 43
// 07 da bc f8 4b 32 18 34 c0 00 2d 68 08 5e 18 00 16 80 00
bit_ref bref(rrc_msg, sizeof(rrc_msg));
dl_dcch_msg_s dl_dcch_msg;
dl_dcch_msg.unpack(bref);
TESTASSERT(dl_dcch_msg.msg.type() == dl_dcch_msg_type_c::types::c1);
TESTASSERT(dl_dcch_msg.msg.c1().type() == dl_dcch_msg_type_c::c1_c_::types::rrc_conn_recfg);
// assign to stack-allocated variable
asn1::rrc::rrc_conn_recfg_s mob_reconf;
mob_reconf = dl_dcch_msg.msg.c1().rrc_conn_recfg();
// decode same message and assign again
bit_ref bref2(rrc_msg, sizeof(rrc_msg));
dl_dcch_msg_s dl_dcch_msg2;
dl_dcch_msg2.unpack(bref2);
TESTASSERT(dl_dcch_msg2.msg.type() == dl_dcch_msg_type_c::types::c1);
TESTASSERT(dl_dcch_msg2.msg.c1().type() == dl_dcch_msg_type_c::c1_c_::types::rrc_conn_recfg);
mob_reconf = dl_dcch_msg2.msg.c1().rrc_conn_recfg();
return 0;
}
int main(int argc, char** argv)
{
TESTASSERT(rrc_conn_reconfig_ho_test1() == 0);
return 0;
}

@ -24,137 +24,116 @@
* *
*/ */
#include <assert.h> #include "srslte/asn1/rrc_asn1.h"
#include "srslte/asn1/liblte_rrc.h" #include "srslte/common/bcd_helpers.h"
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"
#include "srslte/phy/utils/bit.h" #include <iostream>
void pack_test() using namespace asn1::rrc;
#define TESTASSERT(cond) \
{ \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
}
int basic_test()
{ {
srslte::log_filter log1("RRC"); srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(1024); log1.set_hex_limit(1024);
uint32_t known_reference_len = 30; uint8_t known_reference[] = {0x0d, 0x8f, 0xdf, 0xff, 0xff, 0xff, 0xe2, 0x2f, 0xfc, 0x38,
uint8_t known_reference[256] = {0x0d, 0x8f, 0xdf, 0xff, 0xff, 0xff, 0xe2, 0x2f, 0x5e, 0x61, 0xec, 0xa8, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
0xfc, 0x38, 0x5e, 0x61, 0xec, 0xa8, 0x00, 0x00, 0x20, 0x05, 0xe6, 0x1e, 0xca, 0x80, 0x00, 0x00, 0x40, 0x42};
0x02, 0x02, 0x10, 0x00, 0x20, 0x05, 0xe6, 0x1e, uint32_t known_reference_len = sizeof(known_reference);
0xca, 0x80, 0x00, 0x00, 0x40, 0x42}; // 0d8fdfffffffe22ffc385e61eca80000020210002005e61eca8000004042
LIBLTE_BYTE_MSG_STRUCT byte_buf; asn1::bit_ref bref(&known_reference[0], sizeof(known_reference));
LIBLTE_BIT_MSG_STRUCT bit_buf; asn1::bit_ref bref0(&known_reference[0], sizeof(known_reference));
LIBLTE_RRC_MCCH_MSG_STRUCT mcch_msg; asn1::rrc::mcch_msg_s mcch_msg;
mcch_msg.commonsf_allocpatternlist_r9_size = 2; mcch_msg.unpack(bref);
mcch_msg.commonsf_allocpatternlist_r9[0].radio_fr_alloc_offset = 4;
mcch_msg.commonsf_allocpatternlist_r9[0].radio_fr_alloc_period = LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N32; TESTASSERT(mcch_msg.msg.type() == mcch_msg_type_c::types::c1);
mcch_msg.commonsf_allocpatternlist_r9[0].subfr_alloc_num_frames = LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE; TESTASSERT(mcch_msg.msg.c1().type() == mcch_msg_type_c::c1_c_::types::mbsfn_area_cfg_r9);
mcch_msg.commonsf_allocpatternlist_r9[0].subfr_alloc = 0x3F; mbsfn_area_cfg_r9_s* area_cfg_r9 = &mcch_msg.msg.c1().mbsfn_area_cfg_r9();
mcch_msg.commonsf_allocpatternlist_r9[1].radio_fr_alloc_offset = 7; TESTASSERT(not area_cfg_r9->non_crit_ext_present);
mcch_msg.commonsf_allocpatternlist_r9[1].radio_fr_alloc_period = LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N8; TESTASSERT(area_cfg_r9->common_sf_alloc_r9.size() == 2);
mcch_msg.commonsf_allocpatternlist_r9[1].subfr_alloc_num_frames = LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_FOUR; TESTASSERT(area_cfg_r9->common_sf_alloc_r9[0].radioframe_alloc_period ==
mcch_msg.commonsf_allocpatternlist_r9[1].subfr_alloc = 0xFFFFFF; mbsfn_sf_cfg_s::radioframe_alloc_period_e_::n32);
TESTASSERT(area_cfg_r9->common_sf_alloc_r9[0].radioframe_alloc_offset == 4);
mcch_msg.commonsf_allocperiod_r9 = LIBLTE_RRC_MBSFN_COMMON_SF_ALLOC_PERIOD_R9_RF256; TESTASSERT(area_cfg_r9->common_sf_alloc_r9[0].sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::one_frame);
TESTASSERT(area_cfg_r9->common_sf_alloc_r9[0].sf_alloc.one_frame().to_string() == "111111");
mcch_msg.pmch_infolist_r9_size = 2; TESTASSERT(area_cfg_r9->common_sf_alloc_r9[1].radioframe_alloc_period ==
mbsfn_sf_cfg_s::radioframe_alloc_period_e_::n8);
mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size = 1; TESTASSERT(area_cfg_r9->common_sf_alloc_r9[1].radioframe_alloc_offset == 7);
mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].logicalchannelid_r9 = 1; TESTASSERT(area_cfg_r9->common_sf_alloc_r9[1].sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::four_frames);
mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].sessionid_r9_present = true; TESTASSERT(area_cfg_r9->common_sf_alloc_r9[1].sf_alloc.four_frames().to_string() == "111111111111111111111111");
mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].sessionid_r9 = 1; TESTASSERT(area_cfg_r9->common_sf_alloc_period_r9 == mbsfn_area_cfg_r9_s::common_sf_alloc_period_r9_e_::rf256);
mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_explicit = true; TESTASSERT(area_cfg_r9->pmch_info_list_r9.size() == 2);
mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mcc = 0xF987; TESTASSERT(not area_cfg_r9->pmch_info_list_r9[0].ext);
mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mnc = 0xF654; TESTASSERT(not area_cfg_r9->pmch_info_list_r9[0].pmch_cfg_r9.ext);
mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.serviceid_r9 = 1; TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].pmch_cfg_r9.sf_alloc_end_r9 == 1535);
mcch_msg.pmch_infolist_r9[0].pmch_config_r9.datamcs_r9 = 16; TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].pmch_cfg_r9.data_mcs_r9 == 16);
mcch_msg.pmch_infolist_r9[0].pmch_config_r9.mch_schedulingperiod_r9 = LIBLTE_RRC_MCH_SCHEDULING_PERIOD_R9_RF1024; TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].pmch_cfg_r9.mch_sched_period_r9 ==
mcch_msg.pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9 = 1535; pmch_cfg_r9_s::mch_sched_period_r9_e_::rf1024);
TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9.size() == 1);
mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9_size = 1; TESTASSERT(not area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9[0].ext);
mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].logicalchannelid_r9 = 2; TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9[0].session_id_r9_present);
mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].sessionid_r9_present = true; TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9[0].tmgi_r9.plmn_id_r9.type() ==
mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].sessionid_r9 = 2; tmgi_r9_s::plmn_id_r9_c_::types::explicit_value_r9);
mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_explicit = true; TESTASSERT(area_cfg_r9->pmch_info_list_r9[0]
mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mcc = 0xF987; .mbms_session_info_list_r9[0]
mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mnc = 0xF654; .tmgi_r9.plmn_id_r9.explicit_value_r9()
mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].tmgi_r9.serviceid_r9 = 2; .mcc_present);
mcch_msg.pmch_infolist_r9[1].pmch_config_r9.datamcs_r9 = 8; std::string mccmnc_str = srslte::plmn_id_to_string(
mcch_msg.pmch_infolist_r9[1].pmch_config_r9.mch_schedulingperiod_r9 = LIBLTE_RRC_MCH_SCHEDULING_PERIOD_R9_RF8; area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9[0].tmgi_r9.plmn_id_r9.explicit_value_r9());
mcch_msg.pmch_infolist_r9[1].pmch_config_r9.sf_alloc_end_r9 = 0; TESTASSERT(mccmnc_str == "987654");
TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9[0].tmgi_r9.service_id_r9.to_string() ==
liblte_rrc_pack_mcch_msg(&mcch_msg, &bit_buf); "000001");
liblte_pack(bit_buf.msg, bit_buf.N_bits, byte_buf.msg); TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9[0].session_id_r9.to_string() == "01");
byte_buf.N_bytes = (bit_buf.N_bits+7)/8; TESTASSERT(area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9[0].lc_ch_id_r9 == 1);
TESTASSERT(not area_cfg_r9->pmch_info_list_r9[1].ext);
TESTASSERT(not area_cfg_r9->pmch_info_list_r9[1].pmch_cfg_r9.ext);
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].pmch_cfg_r9.sf_alloc_end_r9 == 0);
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].pmch_cfg_r9.data_mcs_r9 == 8);
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].pmch_cfg_r9.mch_sched_period_r9 ==
pmch_cfg_r9_s::mch_sched_period_r9_e_::rf8);
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].mbms_session_info_list_r9.size() == 1);
TESTASSERT(not area_cfg_r9->pmch_info_list_r9[1].mbms_session_info_list_r9[0].ext);
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].mbms_session_info_list_r9[0].session_id_r9_present);
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].mbms_session_info_list_r9[0].tmgi_r9.plmn_id_r9.type() ==
tmgi_r9_s::plmn_id_r9_c_::types::explicit_value_r9);
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1]
.mbms_session_info_list_r9[0]
.tmgi_r9.plmn_id_r9.explicit_value_r9()
.mcc_present);
mccmnc_str = srslte::plmn_id_to_string(
area_cfg_r9->pmch_info_list_r9[0].mbms_session_info_list_r9[0].tmgi_r9.plmn_id_r9.explicit_value_r9());
TESTASSERT(mccmnc_str == "987654");
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].mbms_session_info_list_r9[0].tmgi_r9.service_id_r9.to_string() ==
"000002");
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].mbms_session_info_list_r9[0].session_id_r9.to_string() == "02");
TESTASSERT(area_cfg_r9->pmch_info_list_r9[1].mbms_session_info_list_r9[0].lc_ch_id_r9 == 2);
//log1.info_hex(byte_buf.msg, byte_buf.N_bytes, "MCCH packed message:"); //log1.info_hex(byte_buf.msg, byte_buf.N_bytes, "MCCH packed message:");
assert(byte_buf.N_bytes == known_reference_len); uint8_t rrc_msg2[known_reference_len];
for(uint32 i=0; i<known_reference_len; i++) { asn1::bit_ref bref2(&rrc_msg2[0], sizeof(rrc_msg2));
assert(byte_buf.msg[i] == known_reference[i]); mcch_msg.pack(bref2);
} TESTASSERT(bref.distance(bref0) == bref2.distance(&rrc_msg2[0]));
TESTASSERT(memcmp(rrc_msg2, known_reference, known_reference_len) == 0);
}
void unpack_test()
{
uint32_t known_reference_len = 30;
uint8_t known_reference[256] = {0x0d, 0x8f, 0xdf, 0xff, 0xff, 0xff, 0xe2, 0x2f,
0xfc, 0x38, 0x5e, 0x61, 0xec, 0xa8, 0x00, 0x00,
0x02, 0x02, 0x10, 0x00, 0x20, 0x05, 0xe6, 0x1e,
0xca, 0x80, 0x00, 0x00, 0x40, 0x42};
LIBLTE_BYTE_MSG_STRUCT byte_buf;
LIBLTE_BIT_MSG_STRUCT bit_buf;
LIBLTE_RRC_MCCH_MSG_STRUCT mcch_msg;
liblte_unpack(known_reference, known_reference_len, bit_buf.msg);
bit_buf.N_bits = known_reference_len*8;
liblte_rrc_unpack_mcch_msg(&bit_buf, &mcch_msg);
assert(mcch_msg.commonsf_allocpatternlist_r9_size == 2);
assert(mcch_msg.commonsf_allocpatternlist_r9[0].radio_fr_alloc_offset == 4);
assert(mcch_msg.commonsf_allocpatternlist_r9[0].radio_fr_alloc_period == LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N32);
assert(mcch_msg.commonsf_allocpatternlist_r9[0].subfr_alloc_num_frames == LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE);
assert(mcch_msg.commonsf_allocpatternlist_r9[0].subfr_alloc == 0x3F);
assert(mcch_msg.commonsf_allocpatternlist_r9[1].radio_fr_alloc_offset == 7);
assert(mcch_msg.commonsf_allocpatternlist_r9[1].radio_fr_alloc_period == LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N8);
assert(mcch_msg.commonsf_allocpatternlist_r9[1].subfr_alloc_num_frames == LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_FOUR);
assert(mcch_msg.commonsf_allocpatternlist_r9[1].subfr_alloc == 0xFFFFFF);
assert(mcch_msg.commonsf_allocperiod_r9 == LIBLTE_RRC_MBSFN_COMMON_SF_ALLOC_PERIOD_R9_RF256);
assert(mcch_msg.pmch_infolist_r9_size == 2);
assert(mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size == 1);
assert(mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].logicalchannelid_r9 == 1);
assert(mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].sessionid_r9_present == true);
assert(mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].sessionid_r9 == 1);
assert(mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_explicit == true);
assert(mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mcc == 0xF987);
assert(mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mnc == 0xF654);
assert(mcch_msg.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.serviceid_r9 == 1);
assert(mcch_msg.pmch_infolist_r9[0].pmch_config_r9.datamcs_r9 == 16);
assert(mcch_msg.pmch_infolist_r9[0].pmch_config_r9.mch_schedulingperiod_r9 == LIBLTE_RRC_MCH_SCHEDULING_PERIOD_R9_RF1024);
assert(mcch_msg.pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9 == 1535);
assert(mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9_size == 1);
assert(mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].logicalchannelid_r9 == 2);
assert(mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].sessionid_r9_present == true);
assert(mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].sessionid_r9 == 2);
assert(mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_explicit == true);
assert(mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mcc == 0xF987);
assert(mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mnc == 0xF654);
assert(mcch_msg.pmch_infolist_r9[1].mbms_sessioninfolist_r9[0].tmgi_r9.serviceid_r9 == 2);
assert(mcch_msg.pmch_infolist_r9[1].pmch_config_r9.datamcs_r9 == 8);
assert(mcch_msg.pmch_infolist_r9[1].pmch_config_r9.mch_schedulingperiod_r9 == LIBLTE_RRC_MCH_SCHEDULING_PERIOD_R9_RF8);
assert(mcch_msg.pmch_infolist_r9[1].pmch_config_r9.sf_alloc_end_r9 == 0);
return 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
pack_test(); TESTASSERT(basic_test() == 0);
unpack_test(); return 0;
} }

@ -24,68 +24,85 @@
* *
*/ */
#include <assert.h> #include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/bcd_helpers.h"
#include "srslte/common/log_filter.h"
#include <iostream> #include <iostream>
#include <srslte/srslte.h> #include <srslte/srslte.h>
#include "srslte/common/log_filter.h"
#include "srslte/asn1/liblte_rrc.h"
#define TESTASSERT(cond) \
{ \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
}
using namespace asn1;
using namespace asn1::rrc;
void basic_test() { int basic_test()
{
srslte::log_filter log1("RRC"); srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128); log1.set_hex_limit(128);
LIBLTE_BIT_MSG_STRUCT bit_buf; uint8_t rrc_msg[] = {0x08, 0x10, 0x49, 0x3C, 0x0D, 0x97, 0x89, 0x83, 0xC0,
LIBLTE_BIT_MSG_STRUCT bit_buf2; 0x84, 0x20, 0x82, 0x08, 0x21, 0x00, 0x01, 0xBC, 0x48};
LIBLTE_BYTE_MSG_STRUCT byte_buf; uint32_t rrc_msg_len = sizeof(rrc_msg);
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; // 0810493C0D978983C084208208210001BC48
uint32_t rrc_message_len = 18; bit_ref bref(&rrc_msg[0], sizeof(rrc_msg));
uint8_t rrc_message[] = {0x08, 0x10, 0x49, 0x3C, 0x0D, 0x97, 0x89, 0x83, bit_ref bref0(&rrc_msg[0], sizeof(rrc_msg));
0xC0, 0x84, 0x20, 0x82, 0x08, 0x21, 0x00, 0x01,
0xBC, 0x48};
srslte_bit_unpack_vector(rrc_message, bit_buf.msg, rrc_message_len*8); ul_dcch_msg_s ul_dcch_msg;
bit_buf.N_bits = rrc_message_len*8; ul_dcch_msg.unpack(bref);
liblte_rrc_unpack_ul_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &ul_dcch_msg);
assert(ul_dcch_msg.msg_type == LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT); TESTASSERT(ul_dcch_msg.msg.type() == ul_dcch_msg_type_c::types::c1);
LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *rep = &ul_dcch_msg.msg.measurement_report; TESTASSERT(ul_dcch_msg.msg.c1().type() == ul_dcch_msg_type_c::c1_c_::types::meas_report);
assert(rep->meas_id == 1);
assert(rep->pcell_rsrp_result == 73);
assert(rep->pcell_rsrq_result == 15);
assert(rep->have_meas_result_neigh_cells);
assert(rep->meas_result_neigh_cells_choice == LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA);
LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT *eutra = &rep->meas_result_neigh_cells.eutra;
assert(eutra->n_result == 1);
assert(eutra->result_eutra_list[0].phys_cell_id == 357);
assert(eutra->result_eutra_list[0].have_cgi_info);
assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mcc == 0xF898);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mnc == 0xFF78);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.cell_id == 0x1084104);
assert(eutra->result_eutra_list[0].cgi_info.tracking_area_code == 0x1042);
assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list);
assert(eutra->result_eutra_list[0].cgi_info.n_plmn_identity_list == 1);
assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mcc == 0xFFFF);
assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mnc == 0xFF00);
assert(eutra->result_eutra_list[0].meas_result.have_rsrp);
assert(eutra->result_eutra_list[0].meas_result.rsrp_result == 60);
assert(eutra->result_eutra_list[0].meas_result.have_rsrp);
assert(eutra->result_eutra_list[0].meas_result.rsrq_result == 18);
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT*)&bit_buf2); meas_report_s* rep = &ul_dcch_msg.msg.c1().meas_report();
srslte_bit_pack_vector(bit_buf2.msg, byte_buf.msg, bit_buf2.N_bits); TESTASSERT(rep->crit_exts.type() == meas_report_s::crit_exts_c_::types::c1);
byte_buf.N_bytes = (bit_buf2.N_bits+7)/8; TESTASSERT(rep->crit_exts.c1().type() == meas_report_s::crit_exts_c_::c1_c_::types::meas_report_r8);
log1.info_hex(byte_buf.msg, byte_buf.N_bytes, "UL_DCCH Packed message\n"); TESTASSERT(not rep->crit_exts.c1().meas_report_r8().non_crit_ext_present);
meas_results_s* meas = &rep->crit_exts.c1().meas_report_r8().meas_results;
for(uint32_t i=0; i<rrc_message_len; i++) { TESTASSERT(not meas->ext);
assert(byte_buf.msg[i] == rrc_message[i]); TESTASSERT(meas->meas_id == 1);
} TESTASSERT(meas->meas_result_pcell.rsrp_result == 73);
} TESTASSERT(meas->meas_result_pcell.rsrq_result == 15);
TESTASSERT(meas->meas_result_neigh_cells_present);
TESTASSERT(meas->meas_result_neigh_cells.type() ==
meas_results_s::meas_result_neigh_cells_c_::types::meas_result_list_eutra);
meas_result_list_eutra_l& meas_list = meas->meas_result_neigh_cells.meas_result_list_eutra();
TESTASSERT(meas_list.size() == 1);
TESTASSERT(meas_list[0].pci == 357);
TESTASSERT(meas_list[0].cgi_info_present);
TESTASSERT(meas_list[0].cgi_info.plmn_id_list_present);
TESTASSERT(meas_list[0].cgi_info.cell_global_id.plmn_id.mcc_present);
std::string mccmnc_str = srslte::plmn_id_to_string(meas_list[0].cgi_info.cell_global_id.plmn_id);
TESTASSERT(mccmnc_str == "89878");
TESTASSERT(meas_list[0].cgi_info.cell_global_id.cell_id.to_number() == 0x1084104);
TESTASSERT(meas_list[0].cgi_info.tac.to_number() == 0x1042);
TESTASSERT(meas_list[0].cgi_info.plmn_id_list.size() == 1);
TESTASSERT(not meas_list[0].cgi_info.plmn_id_list[0].mcc_present);
TESTASSERT(not meas_list[0].meas_result.ext);
TESTASSERT(meas_list[0].meas_result.rsrp_result_present);
TESTASSERT(meas_list[0].meas_result.rsrp_result == 60);
TESTASSERT(meas_list[0].meas_result.rsrq_result_present);
TESTASSERT(meas_list[0].meas_result.rsrq_result == 18);
uint8_t rrc_msg2[rrc_msg_len];
bit_ref bref2(&rrc_msg2[0], sizeof(rrc_msg2));
ul_dcch_msg.pack(bref2);
TESTASSERT(bref.distance(bref0) == bref2.distance(&rrc_msg2[0]));
TESTASSERT(memcmp(rrc_msg2, rrc_msg, rrc_msg_len) == 0);
return 0;
}
int main(int argc, char **argv) { int main(int argc, char** argv)
basic_test(); {
TESTASSERT(basic_test() == 0);
return 0;
} }

@ -0,0 +1,174 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "../../../srsue/hdr/upper/rrc.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/bcd_helpers.h"
#include "srslte/common/log_filter.h"
#include "srslte/common/mac_pcap.h"
#include <iostream>
using namespace asn1::rrc;
#define TESTASSERT(cond) \
{ \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
}
int rrc_ue_cap_info_test(srslte::mac_pcap& pcap)
{
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
rrc_args_t args = {};
args.feature_group = 0xe6041c00;
args.nof_supported_bands = 1;
args.supported_bands[0] = 8;
args.ue_category = 4;
asn1::rrc::ul_dcch_msg_s ul_dcch_msg;
ul_dcch_msg.msg.set(ul_dcch_msg_type_c::types::c1);
ul_dcch_msg.msg.c1().set(ul_dcch_msg_type_c::c1_c_::types::ue_cap_info);
ul_dcch_msg.msg.c1().ue_cap_info().rrc_transaction_id = 0;
ul_dcch_msg.msg.c1().ue_cap_info().crit_exts.set(ue_cap_info_s::crit_exts_c_::types::c1);
ul_dcch_msg.msg.c1().ue_cap_info().crit_exts.c1().set(ue_cap_info_s::crit_exts_c_::c1_c_::types::ue_cap_info_r8);
ue_cap_info_r8_ies_s* info = &ul_dcch_msg.msg.c1().ue_cap_info().crit_exts.c1().ue_cap_info_r8();
info->ue_cap_rat_container_list.resize(1);
info->ue_cap_rat_container_list[0].rat_type = rat_type_e::eutra;
ue_eutra_cap_s cap;
cap.access_stratum_release = access_stratum_release_e::rel8;
cap.ue_category = (uint8_t)args.ue_category;
cap.pdcp_params.max_num_rohc_context_sessions_present = false;
cap.phy_layer_params.ue_specific_ref_sigs_supported = false;
cap.phy_layer_params.ue_tx_ant_sel_supported = false;
cap.rf_params.supported_band_list_eutra.resize(args.nof_supported_bands);
cap.meas_params.band_list_eutra.resize(args.nof_supported_bands);
for (uint32_t i = 0; i < args.nof_supported_bands; i++) {
cap.rf_params.supported_band_list_eutra[i].band_eutra = args.supported_bands[i];
cap.rf_params.supported_band_list_eutra[i].half_duplex = false;
cap.meas_params.band_list_eutra[i].inter_freq_band_list.resize(1);
cap.meas_params.band_list_eutra[i].inter_freq_band_list[0].inter_freq_need_for_gaps = true;
}
cap.feature_group_inds_present = true;
cap.feature_group_inds.from_number(args.feature_group);
uint8_t buf[64];
asn1::bit_ref bref(buf, sizeof(buf));
cap.pack(bref);
bref.align_bytes_zero();
uint32_t cap_len = (uint32_t)bref.distance_bytes(buf);
info->ue_cap_rat_container_list[0].ue_cap_rat_container.resize(cap_len);
memcpy(info->ue_cap_rat_container_list[0].ue_cap_rat_container.data(), buf, cap_len);
log1.debug_hex(buf, cap_len, "UE-Cap (%d/%zd B)\n", cap_len, sizeof(buf));
// pack the message
uint8_t byte_buf[16];
ZERO_OBJECT(byte_buf);
asn1::bit_ref bref3(byte_buf, sizeof(byte_buf));
ul_dcch_msg.pack(bref3);
bref3.align_bytes_zero();
uint32_t len = (uint32_t)bref3.distance_bytes(byte_buf);
log1.debug_hex(byte_buf, len, "UL-DCCH (%d/%zd B)\n", len, sizeof(byte_buf));
pcap.write_ul_rrc_pdu(byte_buf, len);
return 0;
}
int pack_fail_test()
{
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
rrc_args_t args = {};
args.feature_group = 0xe6041c00;
args.nof_supported_bands = 1;
args.supported_bands[0] = 8;
args.ue_category = 4;
asn1::rrc::ul_dcch_msg_s ul_dcch_msg;
ul_dcch_msg.msg.set(ul_dcch_msg_type_c::types::c1);
ul_dcch_msg.msg.c1().set(ul_dcch_msg_type_c::c1_c_::types::ue_cap_info);
ul_dcch_msg.msg.c1().ue_cap_info().rrc_transaction_id = 0;
ul_dcch_msg.msg.c1().ue_cap_info().crit_exts.set(ue_cap_info_s::crit_exts_c_::types::c1);
ul_dcch_msg.msg.c1().ue_cap_info().crit_exts.c1().set(ue_cap_info_s::crit_exts_c_::c1_c_::types::ue_cap_info_r8);
ue_cap_info_r8_ies_s* info = &ul_dcch_msg.msg.c1().ue_cap_info().crit_exts.c1().ue_cap_info_r8();
info->ue_cap_rat_container_list.resize(1);
info->ue_cap_rat_container_list[0].rat_type = rat_type_e::eutra;
ue_eutra_cap_s cap;
cap.access_stratum_release = access_stratum_release_e::rel8;
cap.ue_category = (uint8_t)args.ue_category;
cap.pdcp_params.max_num_rohc_context_sessions_present = false;
cap.phy_layer_params.ue_specific_ref_sigs_supported = false;
cap.phy_layer_params.ue_tx_ant_sel_supported = false;
cap.rf_params.supported_band_list_eutra.resize(args.nof_supported_bands);
cap.meas_params.band_list_eutra.resize(args.nof_supported_bands);
for (uint32_t i = 0; i < args.nof_supported_bands; i++) {
cap.rf_params.supported_band_list_eutra[i].band_eutra = args.supported_bands[i];
cap.rf_params.supported_band_list_eutra[i].half_duplex = false;
cap.meas_params.band_list_eutra[i].inter_freq_band_list.resize(1);
cap.meas_params.band_list_eutra[i].inter_freq_band_list[0].inter_freq_need_for_gaps = true;
}
cap.feature_group_inds_present = true;
cap.feature_group_inds.from_number(args.feature_group);
uint8_t buff[3];
asn1::bit_ref bref(buff, sizeof(buff));
if (ul_dcch_msg.pack(bref) != asn1::SRSASN_SUCCESS) {
fprintf(stderr, "Error while packing message.\n");
return -1;
}
return 0;
}
int main(int argc, char** argv)
{
srslte::mac_pcap pcap;
pcap.open("ul_dcch.pcap");
TESTASSERT(rrc_ue_cap_info_test(pcap) == 0);
TESTASSERT(pack_fail_test() == -1);
pcap.close();
return 0;
}

@ -398,7 +398,7 @@ int main(int argc, char **argv) {
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }
printf("%ld were transmitted, %ld bits were received.\n", tx_nof_bits, rx_nof_bits); printf("%zd were transmitted, %zd bits were received.\n", tx_nof_bits, rx_nof_bits);
printf("[Rates in Mbps] Granted Processed\n"); printf("[Rates in Mbps] Granted Processed\n");
printf(" eNb: %5.1f %5.1f\n", printf(" eNb: %5.1f %5.1f\n",
(float) tx_nof_bits / (float) nof_subframes / 1000.0f, (float) tx_nof_bits / (float) nof_subframes / 1000.0f,

@ -27,11 +27,11 @@ target_link_libraries(rlc_am_control_test srslte_upper srslte_phy)
add_test(rlc_am_control_test rlc_am_control_test) add_test(rlc_am_control_test rlc_am_control_test)
add_executable(rlc_am_test rlc_am_test.cc) add_executable(rlc_am_test rlc_am_test.cc)
target_link_libraries(rlc_am_test srslte_upper srslte_phy srslte_common) target_link_libraries(rlc_am_test srslte_upper srslte_phy srslte_common rrc_asn1)
add_test(rlc_am_test rlc_am_test) add_test(rlc_am_test rlc_am_test)
add_executable(rlc_stress_test rlc_stress_test.cc) add_executable(rlc_stress_test rlc_stress_test.cc)
target_link_libraries(rlc_stress_test srslte_upper srslte_phy srslte_common ${Boost_LIBRARIES}) target_link_libraries(rlc_stress_test srslte_upper srslte_phy srslte_common rrc_asn1 ${Boost_LIBRARIES})
add_test(rlc_am_stress_test rlc_stress_test --mode=AM --loglevel 1 --sdu_gen_delay 250) add_test(rlc_am_stress_test rlc_stress_test --mode=AM --loglevel 1 --sdu_gen_delay 250)
add_test(rlc_um_stress_test rlc_stress_test --mode=UM --loglevel 1) add_test(rlc_um_stress_test rlc_stress_test --mode=UM --loglevel 1)
add_test(rlc_tm_stress_test rlc_stress_test --mode=TM --loglevel 1 --random_opp=false) add_test(rlc_tm_stress_test rlc_stress_test --mode=TM --loglevel 1 --random_opp=false)
@ -41,7 +41,7 @@ target_link_libraries(rlc_um_data_test srslte_upper srslte_phy srslte_common)
add_test(rlc_um_data_test rlc_um_data_test) add_test(rlc_um_data_test rlc_um_data_test)
add_executable(rlc_um_test rlc_um_test.cc) add_executable(rlc_um_test rlc_um_test.cc)
target_link_libraries(rlc_um_test srslte_upper srslte_phy) target_link_libraries(rlc_um_test srslte_upper srslte_phy rrc_asn1)
add_test(rlc_um_test rlc_um_test) add_test(rlc_um_test rlc_um_test)

@ -37,6 +37,7 @@
using namespace srsue; using namespace srsue;
using namespace srslte; using namespace srslte;
using namespace asn1::rrc;
class mac_dummy_timers class mac_dummy_timers
:public srslte::mac_interface_timers :public srslte::mac_interface_timers
@ -163,14 +164,14 @@ bool basic_test()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -258,14 +259,14 @@ bool concat_test()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -338,14 +339,14 @@ bool segment_test(bool in_seq_rx)
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -446,14 +447,14 @@ bool retx_test()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -553,14 +554,14 @@ bool resegment_test_1()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -673,14 +674,14 @@ bool resegment_test_2()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -790,14 +791,14 @@ bool resegment_test_3()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -902,14 +903,14 @@ bool resegment_test_4()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -1014,14 +1015,14 @@ bool resegment_test_5()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -1128,14 +1129,14 @@ bool resegment_test_6()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -1276,14 +1277,14 @@ bool resegment_test_7()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -1463,14 +1464,14 @@ bool resegment_test_8()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc2.init(&log2, 1, &tester, &tester, &timers); rlc2.init(&log2, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -1621,14 +1622,14 @@ bool reset_test()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;
@ -1677,14 +1678,14 @@ bool stop_test()
rlc1.init(&log1, 1, &tester, &tester, &timers); rlc1.init(&log1, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.set(rlc_cfg_c::types::am);
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5; cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) { if (not rlc1.configure(&cnfg)) {
return -1; return -1;

@ -34,6 +34,7 @@
using namespace srslte; using namespace srslte;
using namespace srsue; using namespace srsue;
using namespace asn1::rrc;
class mac_dummy_timers class mac_dummy_timers
:public srslte::mac_interface_timers :public srslte::mac_interface_timers
@ -124,11 +125,11 @@ void basic_test()
rlc1.init(&log1, 3, &tester, &tester, &timers); rlc1.init(&log1, 3, &tester, &tester, &timers);
rlc2.init(&log2, 3, &tester, &tester, &timers); rlc2.init(&log2, 3, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_UM_BI; cnfg.set(rlc_cfg_c::types::um_bi_dir);
cnfg.dl_um_bi_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.um_bi_dir().dl_um_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE10; cnfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_e::size10;
cnfg.ul_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE10; cnfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_e::size10;
assert(rlc1.configure(&cnfg) == true); assert(rlc1.configure(&cnfg) == true);
assert(rlc2.configure(&cnfg) == true); assert(rlc2.configure(&cnfg) == true);
@ -194,11 +195,11 @@ void loss_test()
rlc1.init(&log1, 3, &tester, &tester, &timers); rlc1.init(&log1, 3, &tester, &tester, &timers);
rlc2.init(&log2, 3, &tester, &tester, &timers); rlc2.init(&log2, 3, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_UM_BI; cnfg.set(rlc_cfg_c::types::um_bi_dir);
cnfg.dl_um_bi_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.um_bi_dir().dl_um_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE10; cnfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_e::size10;
cnfg.ul_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE10; cnfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_e::size10;
rlc1.configure(&cnfg); rlc1.configure(&cnfg);
rlc2.configure(&cnfg); rlc2.configure(&cnfg);
@ -338,11 +339,11 @@ void reassmble_test()
rlc1.init(&log1, 3, &tester, &tester, &timers); rlc1.init(&log1, 3, &tester, &tester, &timers);
rlc2.init(&log2, 3, &tester, &tester, &timers); rlc2.init(&log2, 3, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_UM_BI; cnfg.set(rlc_cfg_c::types::um_bi_dir);
cnfg.dl_um_bi_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.um_bi_dir().dl_um_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE5; cnfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_e::size5;
cnfg.ul_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE5; cnfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_e::size5;
rlc1.configure(&cnfg); rlc1.configure(&cnfg);
rlc2.configure(&cnfg); rlc2.configure(&cnfg);
@ -451,11 +452,11 @@ void reassmble_test2()
rlc1.init(&log1, 3, &tester, &tester, &timers); rlc1.init(&log1, 3, &tester, &tester, &timers);
rlc2.init(&log2, 3, &tester, &tester, &timers); rlc2.init(&log2, 3, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; rlc_cfg_c cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_UM_BI; cnfg.set(rlc_cfg_c::types::um_bi_dir);
cnfg.dl_um_bi_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5; cnfg.um_bi_dir().dl_um_rlc.t_reordering = t_reordering_e::ms5;
cnfg.dl_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE5; cnfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_e::size5;
cnfg.ul_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE5; cnfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_e::size5;
rlc1.configure(&cnfg); rlc1.configure(&cnfg);
rlc2.configure(&cnfg); rlc2.configure(&cnfg);

@ -214,18 +214,18 @@ private:
srslte::LOG_LEVEL_ENUM level(std::string l); srslte::LOG_LEVEL_ENUM level(std::string l);
bool check_srslte_version(); // bool check_srslte_version();
int parse_sib1(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *data); int parse_sib1(std::string filename, asn1::rrc::sib_type1_s* data);
int parse_sib2(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *data, bool *mbsfn_section_present); int parse_sib2(std::string filename, asn1::rrc::sib_type2_s* data);
int parse_sib3(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *data); int parse_sib3(std::string filename, asn1::rrc::sib_type3_s* data);
int parse_sib4(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *data); int parse_sib4(std::string filename, asn1::rrc::sib_type4_s* data);
int parse_sib9(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *data); int parse_sib9(std::string filename, asn1::rrc::sib_type9_s* data);
int parse_sib13(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *data); int parse_sib13(std::string filename, asn1::rrc::sib_type13_r9_s* data);
int parse_sibs(all_args_t *args, rrc_cfg_t *rrc_cfg, phy_cfg_t *phy_config_common); int parse_sibs(all_args_t* args, rrc_cfg_t* rrc_cfg, phy_cfg_t* phy_config_common);
int parse_rr(all_args_t *args, rrc_cfg_t *rrc_cfg); int parse_rr(all_args_t *args, rrc_cfg_t *rrc_cfg);
int parse_drb(all_args_t *args, rrc_cfg_t *rrc_cfg); int parse_drb(all_args_t *args, rrc_cfg_t *rrc_cfg);
bool sib_is_present(LIBLTE_RRC_SCHEDULING_INFO_STRUCT *sched_info, uint32_t nof_sched_info, LIBLTE_RRC_SIB_TYPE_ENUM sib_num); bool sib_is_present(const asn1::rrc::sched_info_list_l& l, asn1::rrc::sib_type_e sib_num);
int parse_cell_cfg(all_args_t *args, srslte_cell_t *cell); int parse_cell_cfg(all_args_t* args, srslte_cell_t* cell);
std::string get_build_mode(); std::string get_build_mode();
std::string get_build_info(); std::string get_build_info();

@ -72,7 +72,7 @@ public:
int sr_detected(uint32_t tti, uint16_t rnti); int sr_detected(uint32_t tti, uint16_t rnti);
int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv); int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv);
int set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info); int set_dl_ant_info(uint16_t rnti, asn1::rrc::phys_cfg_ded_s::ant_info_c_* dl_ant_info);
int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value);
int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value); int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value);
@ -115,7 +115,8 @@ public:
uint32_t get_current_tti(); uint32_t get_current_tti();
void get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS]); void get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS]);
void write_mcch(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, LIBLTE_RRC_MCCH_MSG_STRUCT *mcch); void write_mcch(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13, asn1::rrc::mcch_msg_s* mcch);
private: private:
static const int MAX_LOCATIONS = 20; static const int MAX_LOCATIONS = 20;
@ -181,9 +182,9 @@ private:
const static int mcch_payload_len = 3000; //TODO FIND OUT MAX LENGTH const static int mcch_payload_len = 3000; //TODO FIND OUT MAX LENGTH
int current_mcch_length; int current_mcch_length;
uint8_t mcch_payload_buffer[mcch_payload_len]; uint8_t mcch_payload_buffer[mcch_payload_len];
LIBLTE_RRC_MCCH_MSG_STRUCT mcch; asn1::rrc::mcch_msg_s mcch;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; asn1::rrc::sib_type2_s sib2;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13; asn1::rrc::sib_type13_r9_s sib13;
const static int mtch_payload_len = 10000; const static int mtch_payload_len = 10000;
uint8_t mtch_payload_buffer[mtch_payload_len]; uint8_t mtch_payload_buffer[mtch_payload_len];

@ -111,7 +111,7 @@ public:
int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue); int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue);
int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code); int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code);
int dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated); int dl_ant_info(uint16_t rnti, asn1::rrc::phys_cfg_ded_s::ant_info_c_* dedicated);
int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack); int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack);
int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size); int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size);
int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value);

@ -32,6 +32,7 @@
#include "srslte/interfaces/sched_interface.h" #include "srslte/interfaces/sched_interface.h"
#include "scheduler_harq.h" #include "scheduler_harq.h"
#include "srslte/asn1/rrc_asn1.h"
namespace srsenb { namespace srsenb {
@ -76,7 +77,7 @@ public:
void ul_phr(int phr); void ul_phr(int phr);
void mac_buffer_state(uint32_t ce_code); void mac_buffer_state(uint32_t ce_code);
void ul_recv_len(uint32_t lcid, uint32_t len); void ul_recv_len(uint32_t lcid, uint32_t len);
void set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated); void set_dl_ant_info(asn1::rrc::phys_cfg_ded_s::ant_info_c_* dedicated);
void set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code); void set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code);
void set_dl_ri(uint32_t tti, uint32_t ri); void set_dl_ri(uint32_t tti, uint32_t ri);
void set_dl_pmi(uint32_t tti, uint32_t ri); void set_dl_pmi(uint32_t tti, uint32_t ri);
@ -151,7 +152,8 @@ private:
int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu); int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu);
static uint32_t format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb); static uint32_t format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb);
static int cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t max_Qm, uint32_t *mcs); static int cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t max_Qm, bool is_ul,
uint32_t* mcs);
int alloc_tbs_dl(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int *mcs); int alloc_tbs_dl(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int *mcs);
int alloc_tbs_ul(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int *mcs); int alloc_tbs_ul(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int *mcs);
int alloc_tbs(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, bool is_ul, int *mcs); int alloc_tbs(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, bool is_ul, int *mcs);
@ -209,8 +211,7 @@ private:
ul_harq_proc ul_harq[SCHED_MAX_HARQ_PROC]; ul_harq_proc ul_harq[SCHED_MAX_HARQ_PROC];
bool phy_config_dedicated_enabled; bool phy_config_dedicated_enabled;
LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT dl_ant_info; asn1::rrc::phys_cfg_ded_s::ant_info_c_ dl_ant_info;
}; };
} }

@ -294,6 +294,13 @@ public:
*val = t; *val = t;
return r; return r;
} }
static bool lookupValue(Setting& root, const char* name, float* val)
{
double t;
bool r = root.lookupValue(name, t);
*val = t;
return r;
}
static bool lookupValue(Setting &root, const char *name, bool *val) { static bool lookupValue(Setting &root, const char *name, bool *val) {
bool t; bool t;
bool r = root.lookupValue(name, t); bool r = root.lookupValue(name, t);

@ -62,9 +62,7 @@ public:
void set_conf_dedicated_ack(uint16_t rnti, void set_conf_dedicated_ack(uint16_t rnti,
bool rrc_completed); bool rrc_completed);
void set_config_dedicated(uint16_t rnti, void set_config_dedicated(uint16_t rnti, srslte_refsignal_srs_cfg_t* srs_cfg, asn1::rrc::phys_cfg_ded_s* dedicated);
srslte_refsignal_srs_cfg_t *srs_cfg,
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated);
uint32_t get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]); uint32_t get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]);
@ -106,9 +104,12 @@ private:
public: public:
ue() : I_sr(0), I_sr_en(false), cqi_en(false), pucch_cqi_ack(false), pmi_idx(0), has_grant_tti(0), ue() : I_sr(0), I_sr_en(false), cqi_en(false), pucch_cqi_ack(false), pmi_idx(0), has_grant_tti(0),
dedicated_ack(false), ri_idx(0), ri_en(false), rnti(0) { dedicated_ack(false), ri_idx(0), ri_en(false), rnti(0) {
bzero(&dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT));
bzero(&phich_info, sizeof(srslte_enb_ul_phich_info_t)); bzero(&phich_info, sizeof(srslte_enb_ul_phich_info_t));
bzero(&metrics, sizeof(phy_metrics_t)); bzero(&metrics, sizeof(phy_metrics_t));
dedicated.ant_info_present = true;
dedicated.ant_info.set(asn1::rrc::phys_cfg_ded_s::ant_info_c_::types::explicit_value);
dedicated.ant_info.explicit_value().tx_mode.value = asn1::rrc::ant_info_ded_s::tx_mode_e_::tm1;
dedicated.ant_info.explicit_value().ue_tx_ant_sel.set(asn1::rrc::setup_e::release);
} }
uint32_t I_sr; uint32_t I_sr;
uint32_t pmi_idx; uint32_t pmi_idx;
@ -118,7 +119,7 @@ private:
bool ri_en; bool ri_en;
bool pucch_cqi_ack; bool pucch_cqi_ack;
int has_grant_tti; int has_grant_tti;
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT dedicated; asn1::rrc::phys_cfg_ded_s dedicated;
bool dedicated_ack; bool dedicated_ack;
uint32_t rnti; uint32_t rnti;
srslte_enb_ul_phich_info_t phich_info; srslte_enb_ul_phich_info_t phich_info;

@ -27,29 +27,29 @@
#ifndef SRSENB_PHY_H #ifndef SRSENB_PHY_H
#define SRSENB_PHY_H #define SRSENB_PHY_H
#include "phch_common.h"
#include "phch_worker.h"
#include "srslte/common/log.h" #include "srslte/common/log.h"
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"
#include "txrx.h"
#include "phch_worker.h"
#include "phch_common.h"
#include "srslte/radio/radio.h"
#include "srslte/interfaces/enb_interfaces.h"
#include "srslte/common/task_dispatcher.h" #include "srslte/common/task_dispatcher.h"
#include "srslte/common/trace.h" #include "srslte/common/trace.h"
#include "srslte/interfaces/enb_interfaces.h"
#include "srslte/interfaces/enb_metrics_interface.h" #include "srslte/interfaces/enb_metrics_interface.h"
#include "srslte/radio/radio.h"
#include "txrx.h"
#include <srslte/asn1/rrc_asn1.h>
namespace srsenb { namespace srsenb {
typedef struct { typedef struct {
srslte_cell_t cell; srslte_cell_t cell;
LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT prach_cnfg; asn1::rrc::prach_cfg_sib_s prach_cnfg;
LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT pdsch_cnfg; asn1::rrc::pdsch_cfg_common_s pdsch_cnfg;
LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT pusch_cnfg; asn1::rrc::pusch_cfg_common_s pusch_cnfg;
LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT pucch_cnfg; asn1::rrc::pucch_cfg_common_s pucch_cnfg;
LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT srs_ul_cnfg; asn1::rrc::srs_ul_cfg_common_c srs_ul_cnfg;
} phy_cfg_t; } phy_cfg_t;
class phy : public phy_interface_mac, class phy : public phy_interface_mac,
public phy_interface_rrc public phy_interface_rrc
{ {
@ -65,14 +65,14 @@ public:
void rem_rnti(uint16_t rnti); void rem_rnti(uint16_t rnti);
/*RRC-PHY interface*/ /*RRC-PHY interface*/
void configure_mbsfn(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, LIBLTE_RRC_MCCH_MSG_STRUCT mcch); void configure_mbsfn(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13, asn1::rrc::mcch_msg_s mcch);
static uint32_t tti_to_SFN(uint32_t tti); static uint32_t tti_to_SFN(uint32_t tti);
static uint32_t tti_to_subf(uint32_t tti); static uint32_t tti_to_subf(uint32_t tti);
void start_plot(); void start_plot();
void set_conf_dedicated_ack(uint16_t rnti, bool dedicated_ack); void set_conf_dedicated_ack(uint16_t rnti, bool dedicated_ack);
void set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated); void set_config_dedicated(uint16_t rnti, asn1::rrc::phys_cfg_ded_s* dedicated);
void get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]); void get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]);

@ -27,27 +27,28 @@
#ifndef SRSENB_RRC_H #ifndef SRSENB_RRC_H
#define SRSENB_RRC_H #define SRSENB_RRC_H
#include <map> #include "common_enb.h"
#include <queue> #include "rrc_metrics.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/block_queue.h"
#include "srslte/common/buffer_pool.h" #include "srslte/common/buffer_pool.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/block_queue.h" #include "srslte/common/log.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include "srslte/common/timeout.h" #include "srslte/common/timeout.h"
#include "srslte/common/log.h"
#include "srslte/interfaces/enb_interfaces.h" #include "srslte/interfaces/enb_interfaces.h"
#include "common_enb.h" #include <map>
#include "rrc_metrics.h" #include <queue>
namespace srsenb { namespace srsenb {
typedef struct { struct rrc_cfg_sr_t {
uint32_t period; uint32_t period;
LIBLTE_RRC_DSR_TRANS_MAX_ENUM dsr_max; asn1::rrc::sched_request_cfg_c::setup_s_::dsr_trans_max_e_ dsr_max;
uint32_t nof_prb; uint32_t nof_prb;
uint32_t sf_mapping[80]; uint32_t sf_mapping[80];
uint32_t nof_subframes; uint32_t nof_subframes;
} rrc_cfg_sr_t; };
typedef enum { typedef enum {
RRC_CFG_CQI_MODE_PERIODIC = 0, RRC_CFG_CQI_MODE_PERIODIC = 0,
@ -68,20 +69,21 @@ typedef struct {
typedef struct { typedef struct {
bool configured; bool configured;
LIBLTE_RRC_UL_SPECIFIC_PARAMETERS_STRUCT lc_cfg; asn1::rrc::lc_ch_cfg_s::ul_specific_params_s_ lc_cfg;
LIBLTE_RRC_PDCP_CONFIG_STRUCT pdcp_cfg; asn1::rrc::pdcp_cfg_s pdcp_cfg;
LIBLTE_RRC_RLC_CONFIG_STRUCT rlc_cfg; asn1::rrc::rlc_cfg_c rlc_cfg;
} rrc_cfg_qci_t; } rrc_cfg_qci_t;
#define MAX_NOF_QCI 10 #define MAX_NOF_QCI 10
typedef struct { typedef struct {
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT sibs[LIBLTE_RRC_MAX_SIB]; asn1::rrc::sib_type1_s sib1;
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT mac_cnfg; asn1::rrc::sib_info_item_c sibs[ASN1_RRC_MAX_SIB];
asn1::rrc::mac_main_cfg_s mac_cnfg;
LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT pusch_cfg; asn1::rrc::pusch_cfg_ded_s pusch_cfg;
LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT antenna_info; asn1::rrc::ant_info_ded_s antenna_info;
LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM pdsch_cfg; asn1::rrc::pdsch_cfg_ded_s::p_a_e_ pdsch_cfg;
rrc_cfg_sr_t sr_cfg; rrc_cfg_sr_t sr_cfg;
rrc_cfg_cqi_t cqi_cfg; rrc_cfg_cqi_t cqi_cfg;
rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI]; rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI];
@ -121,10 +123,10 @@ public:
bzero(&sr_sched, sizeof(sr_sched)); bzero(&sr_sched, sizeof(sr_sched));
bzero(&cqi_sched, sizeof(cqi_sched)); bzero(&cqi_sched, sizeof(cqi_sched));
bzero(&cfg, sizeof(cfg)); bzero(&cfg.sr_cfg, sizeof(cfg.sr_cfg));
bzero(&sib2, sizeof(sib2)); bzero(&cfg.cqi_cfg, sizeof(cfg.cqi_cfg));
bzero(&paging_mutex, sizeof(paging_mutex)); bzero(&cfg.qci_cfg, sizeof(cfg.qci_cfg));
bzero(&cfg.cell, sizeof(cfg.cell));
} }
void init(rrc_cfg_t *cfg, void init(rrc_cfg_t *cfg,
@ -165,6 +167,11 @@ public:
void parse_sibs(); void parse_sibs();
uint32_t get_nof_users(); uint32_t get_nof_users();
// logging
typedef enum { Rx = 0, Tx } direction_t;
template <class T>
void log_rrc_message(const std::string& source, direction_t dir, const srslte::byte_buffer_t* pdu, const T& msg);
// Notifier for user connect // Notifier for user connect
class connect_notifier { class connect_notifier {
public: public:
@ -208,13 +215,13 @@ public:
void send_ue_cap_enquiry(); void send_ue_cap_enquiry();
void parse_ul_dcch(uint32_t lcid, srslte::byte_buffer_t* pdu); void parse_ul_dcch(uint32_t lcid, srslte::byte_buffer_t* pdu);
void handle_rrc_con_req(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *msg); void handle_rrc_con_req(asn1::rrc::rrc_conn_request_s* msg);
void handle_rrc_con_reest_req(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *msg); void handle_rrc_con_reest_req(asn1::rrc::rrc_conn_reest_request_r8_ies_s* msg);
void handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT *msg, srslte::byte_buffer_t *pdu); void handle_rrc_con_setup_complete(asn1::rrc::rrc_conn_setup_complete_s* msg, srslte::byte_buffer_t* pdu);
void handle_rrc_reconf_complete(LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *msg, srslte::byte_buffer_t *pdu); void handle_rrc_reconf_complete(asn1::rrc::rrc_conn_recfg_complete_s* msg, srslte::byte_buffer_t* pdu);
void handle_security_mode_complete(LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *msg); void handle_security_mode_complete(asn1::rrc::security_mode_complete_s* msg);
void handle_security_mode_failure(LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *msg); void handle_security_mode_failure(asn1::rrc::security_mode_fail_s* msg);
void handle_ue_cap_info(LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *msg); void handle_ue_cap_info(asn1::rrc::ue_cap_info_s* msg);
void set_bitrates(LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT *rates); void set_bitrates(LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT *rates);
void set_security_capabilities(LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT *caps); void set_security_capabilities(LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT *caps);
@ -230,19 +237,19 @@ public:
void notify_s1ap_ue_ctxt_setup_complete(); 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(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e);
int sr_allocate(uint32_t period, uint32_t *I_sr, uint32_t *N_pucch_sr); int sr_allocate(uint32_t period, uint8_t* I_sr, uint16_t* N_pucch_sr);
void sr_get(uint32_t *I_sr, uint32_t *N_pucch_sr); void sr_get(uint8_t* I_sr, uint16_t* N_pucch_sr);
int sr_free(); int sr_free();
int cqi_allocate(uint32_t period, uint32_t *pmi_idx, uint32_t *n_pucch); int cqi_allocate(uint32_t period, uint16_t* pmi_idx, uint16_t* n_pucch);
void cqi_get(uint32_t *pmi_idx, uint32_t *n_pucch); void cqi_get(uint16_t* pmi_idx, uint16_t* n_pucch);
int cqi_free(); int cqi_free();
void send_dl_ccch(LIBLTE_RRC_DL_CCCH_MSG_STRUCT *dl_ccch_msg); void send_dl_ccch(asn1::rrc::dl_ccch_msg_s* dl_ccch_msg);
void send_dl_dcch(LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg, srslte::byte_buffer_t *pdu = NULL); void send_dl_dcch(asn1::rrc::dl_dcch_msg_s* dl_dcch_msg, srslte::byte_buffer_t* pdu = NULL);
uint16_t rnti; uint16_t rnti;
rrc *parent; rrc* parent;
bool connect_notified; bool connect_notified;
@ -251,7 +258,7 @@ public:
struct timeval t_last_activity; struct timeval t_last_activity;
LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM establishment_cause; asn1::rrc::establishment_cause_e establishment_cause;
// S-TMSI for this UE // S-TMSI for this UE
bool has_tmsi; bool has_tmsi;
@ -262,8 +269,8 @@ public:
uint8_t transaction_id; uint8_t transaction_id;
rrc_state_t state; rrc_state_t state;
std::map<uint32_t, LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT> srbs; std::map<uint32_t, asn1::rrc::srb_to_add_mod_s> srbs;
std::map<uint32_t, LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT> drbs; std::map<uint32_t, asn1::rrc::drb_to_add_mod_s> drbs;
uint8_t k_enb[32]; // Provided by MME uint8_t k_enb[32]; // Provided by MME
uint8_t k_rrc_enc[32]; uint8_t k_rrc_enc[32];
@ -276,7 +283,7 @@ public:
LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT bitrates; LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT bitrates;
LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT security_capabilities; LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT security_capabilities;
LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT eutra_capabilities; asn1::rrc::ue_eutra_cap_s eutra_capabilities;
typedef struct { typedef struct {
uint8_t id; uint8_t id;
@ -296,21 +303,19 @@ public:
bool cqi_allocated; bool cqi_allocated;
int cqi_sched_sf_idx; int cqi_sched_sf_idx;
int cqi_sched_prb_idx; int cqi_sched_prb_idx;
int get_drbid_config(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb, int drbid); int get_drbid_config(asn1::rrc::drb_to_add_mod_s* drb, int drbid);
bool nas_pending; bool nas_pending;
srslte::byte_buffer_t erab_info; srslte::byte_buffer_t erab_info;
}; };
private: private:
std::map<uint16_t,ue> users; std::map<uint16_t,ue> users;
std::map<uint32_t, LIBLTE_S1AP_UEPAGINGID_STRUCT > pending_paging; std::map<uint32_t, LIBLTE_S1AP_UEPAGINGID_STRUCT > pending_paging;
activity_monitor act_monitor; activity_monitor act_monitor;
LIBLTE_BYTE_MSG_STRUCT sib_buffer[LIBLTE_RRC_MAX_SIB]; std::vector<srslte::byte_buffer_t*> sib_buffer;
// user connect notifier // user connect notifier
connect_notifier *cnotifier; connect_notifier *cnotifier;
@ -319,7 +324,7 @@ private:
void process_rl_failure(uint16_t rnti); void process_rl_failure(uint16_t rnti);
void rem_user(uint16_t rnti); void rem_user(uint16_t rnti);
uint32_t generate_sibs(); uint32_t generate_sibs();
void configure_mbsfn_sibs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13); void configure_mbsfn_sibs(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13);
void config_mac(); void config_mac();
void parse_ul_dcch(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *pdu); void parse_ul_dcch(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *pdu);
@ -333,17 +338,16 @@ private:
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo); srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
srslte::byte_buffer_pool *pool; srslte::byte_buffer_pool* pool;
srslte::bit_buffer_t bit_buf; srslte::byte_buffer_t byte_buf_paging;
srslte::bit_buffer_t bit_buf_paging;
phy_interface_rrc *phy; phy_interface_rrc* phy;
mac_interface_rrc *mac; mac_interface_rrc* mac;
rlc_interface_rrc *rlc; rlc_interface_rrc* rlc;
pdcp_interface_rrc *pdcp; pdcp_interface_rrc* pdcp;
gtpu_interface_rrc *gtpu; gtpu_interface_rrc* gtpu;
s1ap_interface_rrc *s1ap; s1ap_interface_rrc* s1ap;
srslte::log *rrc_log; srslte::log* rrc_log;
typedef struct{ typedef struct{
uint16_t rnti; uint16_t rnti;
@ -361,18 +365,17 @@ private:
static const int RRC_THREAD_PRIO = 65; static const int RRC_THREAD_PRIO = 65;
srslte::block_queue<rrc_pdu> rx_pdu_queue; srslte::block_queue<rrc_pdu> rx_pdu_queue;
typedef struct { struct sr_sched_t {
uint32_t nof_users[100][80]; uint32_t nof_users[100][80];
} sr_sched_t; };
sr_sched_t sr_sched; sr_sched_t sr_sched;
sr_sched_t cqi_sched; sr_sched_t cqi_sched;
LIBLTE_RRC_MCCH_MSG_STRUCT mcch; asn1::rrc::mcch_msg_s mcch;
bool enable_mbms; bool enable_mbms;
rrc_cfg_t cfg; rrc_cfg_t cfg;
uint32_t nof_si_messages; uint32_t nof_si_messages;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; asn1::rrc::sib_type2_s sib2;
void run_thread(); void run_thread();
void rem_user_thread(uint16_t rnti); void rem_user_thread(uint16_t rnti);

@ -2,7 +2,7 @@ mac_cnfg =
{ {
phr_cnfg = phr_cnfg =
{ {
dl_pathloss_change = "3dB"; // Valid: 1, 3, 6 or INFINITY dl_pathloss_change = "dB3"; // Valid: 1, 3, 6 or INFINITY
periodic_phr_timer = 50; periodic_phr_timer = 50;
prohibit_phr_timer = 0; prohibit_phr_timer = 0;
}; };

@ -1,9 +1,9 @@
sib1 = sib1 =
{ {
intra_freq_reselection = "Allowed"; intra_freq_reselection = "Allowed";
q_rx_lev_min = -130; q_rx_lev_min = -65;
//p_max = 3; //p_max = 3;
cell_barred = "Not Barred" cell_barred = "NotBarred"
si_window_length = 20; si_window_length = 20;
sched_info = sched_info =
( (
@ -89,9 +89,9 @@ sib2 =
format_2a = 2; format_2a = 2;
format_2b = 2; format_2b = 2;
}; };
delta_preamble_msg3 = 8; delta_preamble_msg3 = 6;
}; };
ul_cp_length = "Normal"; ul_cp_length = "len1";
}; };
ue_timers_and_constants = ue_timers_and_constants =

@ -3,7 +3,7 @@ sib1 =
intra_freq_reselection = "Allowed"; intra_freq_reselection = "Allowed";
q_rx_lev_min = -130; q_rx_lev_min = -130;
//p_max = 3; //p_max = 3;
cell_barred = "Not Barred" cell_barred = "NotBarred"
si_window_length = 20; si_window_length = 20;
sched_info = sched_info =
( (
@ -23,9 +23,9 @@ sib2 =
rach_cnfg = rach_cnfg =
{ {
num_ra_preambles = 52; num_ra_preambles = 52;
preamble_init_rx_target_pwr = -108; preamble_init_rx_target_pwr = -104;
pwr_ramping_step = 6; // in dB pwr_ramping_step = 6; // in dB
preamble_trans_max = 7; preamble_trans_max = 10;
ra_resp_win_size = 10; // in ms ra_resp_win_size = 10; // in ms
mac_con_res_timer = 64; // in ms mac_con_res_timer = 64; // in ms
max_harq_msg3_tx = 4; max_harq_msg3_tx = 4;
@ -53,14 +53,14 @@ sib2 =
pdsch_cnfg = pdsch_cnfg =
{ {
p_b = 0; p_b = 0;
rs_power = -4; rs_power = 0;
}; };
pusch_cnfg = pusch_cnfg =
{ {
n_sb = 1; n_sb = 1;
hopping_mode = "inter-subframe"; hopping_mode = "inter-subframe";
pusch_hopping_offset = 2; pusch_hopping_offset = 2;
enable_64_qam = false; enable_64_qam = false; // 64QAM PUSCH is not currently enabled
ul_rs = ul_rs =
{ {
cyclic_shift = 0; cyclic_shift = 0;
@ -71,27 +71,27 @@ sib2 =
}; };
pucch_cnfg = pucch_cnfg =
{ {
delta_pucch_shift = 1; delta_pucch_shift = 2;
n_rb_cqi = 1; n_rb_cqi = 2;
n_cs_an = 0; n_cs_an = 0;
n1_pucch_an = 2; n1_pucch_an = 12;
}; };
ul_pwr_ctrl = ul_pwr_ctrl =
{ {
p0_nominal_pusch = -108; p0_nominal_pusch = -85;
alpha = 1.0; alpha = 0.7;
p0_nominal_pucch = -88; p0_nominal_pucch = -107;
delta_flist_pucch = delta_flist_pucch =
{ {
format_1 = 2; format_1 = 0;
format_1b = 3; format_1b = 3;
format_2 = 0; format_2 = 1;
format_2a = 0; format_2a = 2;
format_2b = 0; format_2b = 2;
}; };
delta_preamble_msg3 = 4; delta_preamble_msg3 = 6;
}; };
ul_cp_length = "Normal"; ul_cp_length = "len1";
}; };
ue_timers_and_constants = ue_timers_and_constants =
@ -113,11 +113,10 @@ sib2 =
mbsfnSubframeConfigList = mbsfnSubframeConfigList =
{ {
radioframeAllocationPeriod = "1"; radioframeAllocationPeriod = 1;
subframeAllocationNumFrames = "1"; subframeAllocationNumFrames = 1;
radioframeAllocationOffset = 0; radioframeAllocationOffset = 0;
subframeAllocation = 63; subframeAllocation = 63;
}; };
time_alignment_timer = "INFINITY"; // use "sf500", "sf750", etc. time_alignment_timer = "INFINITY"; // use "sf500", "sf750", etc.
@ -127,23 +126,20 @@ sib13 =
{ {
mbsfn_notification_config = mbsfn_notification_config =
{ {
mbsfn_notification_repetition_coeff = "2"; mbsfn_notification_repetition_coeff = "n2";
mbsfn_notification_offset = 0; mbsfn_notification_offset = 0;
mbsfn_notification_sf_index = 1; mbsfn_notification_sf_index = 1;
}; };
mbsfn_area_info_list_size = 1; mbsfn_area_info_list_size = 1;
mbsfn_area_info_list = mbsfn_area_info_list =
{ {
non_mbsfn_region_length = "2"; non_mbsfn_region_length = "s2";
mcch_repetition_period = "64"; mcch_repetition_period = "rf64";
mcch_modification_period = "512"; mcch_modification_period = "rf512";
signalling_mcs = "2"; signalling_mcs = "n2";
mbsfn_area_id = 1; mbsfn_area_id = 1;
notification_indicator = 0; notification_indicator = 0;
mcch_offset = 0; mcch_offset = 0;
sf_alloc_info = 32; sf_alloc_info = 32;
}; };
}; };

@ -23,6 +23,7 @@ target_link_libraries(srsenb srsenb_upper
srslte_phy srslte_phy
srslte_upper srslte_upper
srslte_radio srslte_radio
rrc_asn1
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${SEC_LIBRARIES} ${SEC_LIBRARIES}

@ -154,9 +154,9 @@ bool enb::init(all_args_t *args_)
return false; return false;
} }
uint32_t prach_freq_offset = rrc_cfg.sibs[1].sib.sib2.rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset; uint32_t prach_freq_offset = rrc_cfg.sibs[1].sib2().rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset;
if(cell_cfg.nof_prb>10) { if (cell_cfg.nof_prb > 10) {
if (prach_freq_offset + 6 > cell_cfg.nof_prb - SRSLTE_MAX(rrc_cfg.cqi_cfg.nof_prb, rrc_cfg.sr_cfg.nof_prb)) { if (prach_freq_offset + 6 > cell_cfg.nof_prb - SRSLTE_MAX(rrc_cfg.cqi_cfg.nof_prb, rrc_cfg.sr_cfg.nof_prb)) {
fprintf(stderr, "Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", prach_freq_offset); fprintf(stderr, "Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", prach_freq_offset);
return false; return false;
@ -168,9 +168,10 @@ bool enb::init(all_args_t *args_)
return false; return false;
} }
} else { // 6 PRB case } else { // 6 PRB case
if (prach_freq_offset+6 > cell_cfg.nof_prb) { if (prach_freq_offset + 6 > cell_cfg.nof_prb) {
fprintf(stderr, "Invalid PRACH configuration: frequency interval=(%d, %d) does not fit into the eNB PRBs=(0,%d)\n", fprintf(stderr,
prach_freq_offset, prach_freq_offset+6, cell_cfg.nof_prb); "Invalid PRACH configuration: frequency interval=(%d, %d) does not fit into the eNB PRBs=(0,%d)\n",
prach_freq_offset, prach_freq_offset + 6, cell_cfg.nof_prb);
return false; return false;
} }
} }

File diff suppressed because it is too large Load Diff

@ -36,7 +36,7 @@
#include "srsenb/hdr/parser.h" #include "srsenb/hdr/parser.h"
#include "srsenb/hdr/upper/rrc.h" #include "srsenb/hdr/upper/rrc.h"
#include "srslte/asn1/liblte_rrc.h" #include "srslte/asn1/asn1_utils.h"
namespace srsenb { namespace srsenb {
@ -45,7 +45,7 @@ using namespace libconfig;
class field_sched_info : public parser::field_itf class field_sched_info : public parser::field_itf
{ {
public: public:
field_sched_info(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *data_) { data = data_; } field_sched_info(asn1::rrc::sib_type1_s* data_) { data = data_; }
~field_sched_info() {} ~field_sched_info() {}
int parse(Setting &root); int parse(Setting &root);
const char* get_name() { const char* get_name() {
@ -53,27 +53,27 @@ public:
} }
private: private:
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *data; asn1::rrc::sib_type1_s* data;
}; };
class field_intra_neigh_cell_list : public parser::field_itf class field_intra_neigh_cell_list : public parser::field_itf
{ {
public: public:
field_intra_neigh_cell_list(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *data_) { data = data_; } field_intra_neigh_cell_list(asn1::rrc::sib_type4_s* data_) { data = data_; }
~field_intra_neigh_cell_list(){} ~field_intra_neigh_cell_list(){}
int parse(Setting &root); int parse(Setting& root);
const char* get_name() { const char* get_name() {
return "intra_neigh_cell_list"; return "intra_neigh_cell_list";
} }
private: private:
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *data; asn1::rrc::sib_type4_s* data;
}; };
class field_intra_black_cell_list : public parser::field_itf class field_intra_black_cell_list : public parser::field_itf
{ {
public: public:
field_intra_black_cell_list(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *data_) { data = data_; } field_intra_black_cell_list(asn1::rrc::sib_type4_s* data_) { data = data_; }
~field_intra_black_cell_list(){} ~field_intra_black_cell_list(){}
int parse(Setting &root); int parse(Setting &root);
const char* get_name() { const char* get_name() {
@ -81,7 +81,7 @@ public:
} }
private: private:
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *data; asn1::rrc::sib_type4_s* data;
}; };
class field_sf_mapping : public parser::field_itf class field_sf_mapping : public parser::field_itf
@ -113,7 +113,432 @@ private:
rrc_cfg_qci_t *cfg; rrc_cfg_qci_t *cfg;
}; };
// ASN1 parsers
class field_asn1 : public parser::field_itf
{
public:
field_asn1(const char* name_, bool* enabled_value_ = NULL)
{
name = name_;
enabled_value = enabled_value_;
}
const char* get_name() { return name; }
int parse(Setting& root)
{
if (root.exists(name)) {
if (enabled_value) {
*enabled_value = true;
}
return parse_value(root);
} else {
if (enabled_value) {
*enabled_value = false;
return 0;
} else {
return -1;
}
}
}
virtual int parse_value(Setting& root) = 0;
protected:
const char* name;
bool* enabled_value;
};
template <class ListType>
class field_asn1_seqof_size : public field_asn1
{
ListType* store_ptr;
public:
field_asn1_seqof_size(const char* name_, ListType* store_ptr_, bool* enabled_value_ = NULL) :
field_asn1(name_, enabled_value_),
store_ptr(store_ptr_)
{
}
int parse_value(Setting& root)
{
uint32_t size_val;
if (root.lookupValue(name, size_val)) {
store_ptr->resize(size_val);
return 0;
}
return -1;
}
};
template <class ListType>
field_asn1_seqof_size<ListType>* make_asn1_seqof_size_parser(const char* name, ListType* store_ptr,
bool* enabled = NULL)
{
return new field_asn1_seqof_size<ListType>(name, store_ptr, enabled);
}
template <class ChoiceType, class NumberType>
class field_asn1_choice_type_number : public field_asn1
{
ChoiceType* store_ptr;
public:
field_asn1_choice_type_number(const char* name_, ChoiceType* store_ptr_, bool* enabled_value_ = NULL) :
field_asn1(name_, enabled_value_),
store_ptr(store_ptr_)
{
}
int parse_value(Setting& root)
{
NumberType val;
if (root.lookupValue(name, val)) {
typename ChoiceType::types type;
bool found = asn1::number_to_enum(type, val);
if (not found) {
fprintf(stderr, "Invalid option: %s for field \"%s\"\n", val.c_str(), name);
fprintf(stderr, "Valid options: %d", ChoiceType::types(0).to_number());
for (uint32_t i = 1; i < ChoiceType::types::nof_types; i++) {
fprintf(stderr, ", %s", ChoiceType::types(i).to_number());
}
fprintf(stderr, "\n");
return -1;
}
store_ptr->set(type);
return 0;
}
return -1;
}
};
template <class EnumType>
bool parse_enum_by_number(EnumType& enum_val, const char* name, Setting& root)
{
typename EnumType::number_type val;
if (parser::lookupValue(root, name, &val)) {
bool found = asn1::number_to_enum(enum_val, val);
if (not found) {
std::ostringstream ss;
ss << val;
fprintf(stderr, "Invalid option: %s for field \"%s\"\n", ss.str().c_str(), name);
ss.str("");
ss << EnumType((typename EnumType::options)0).to_number();
fprintf(stderr, "Valid options: %s", ss.str().c_str());
for (uint32_t i = 1; i < EnumType::nof_types; i++) {
ss.str("");
ss << EnumType((typename EnumType::options)i).to_number();
fprintf(stderr, ", %s", ss.str().c_str());
}
fprintf(stderr, "\n");
return false;
}
return true;
} else {
std::string str_val;
if (parser::lookupValue(root, name, &str_val)) {
fprintf(stderr, "Expected a number for field %s but received a string %s\n", name, str_val.c_str());
}
}
return false;
}
template <class EnumType>
bool parse_enum_by_number_str(EnumType& enum_val, const char* name, Setting& root)
{
std::string val;
if (parser::lookupValue(root, name, &val)) {
bool found = asn1::number_string_to_enum(enum_val, val);
if (not found) {
fprintf(stderr, "PARSER ERROR: Invalid option: \"%s\" for field \"%s\"\n", val.c_str(), name);
fprintf(stderr, "Valid options: \"%s\"", EnumType((typename EnumType::options)0).to_number_string().c_str());
for (uint32_t i = 1; i < EnumType::nof_types; i++) {
fprintf(stderr, ", \"%s\"", EnumType((typename EnumType::options)i).to_number_string().c_str());
}
fprintf(stderr, "\n");
return false;
}
return true;
}
return false;
}
template <class EnumType>
bool nowhitespace_string_to_enum(EnumType& e, const std::string& s)
{
std::string s_nows = s;
std::transform(s_nows.begin(), s_nows.end(), s_nows.begin(), ::tolower);
s_nows.erase(std::remove(s_nows.begin(), s_nows.end(), ' '), s_nows.end());
s_nows.erase(std::remove(s_nows.begin(), s_nows.end(), '-'), s_nows.end());
for (uint32_t i = 0; i < EnumType::nof_types; ++i) {
e = (typename EnumType::options)i;
std::string s_nows2 = e.to_string();
std::transform(s_nows2.begin(), s_nows2.end(), s_nows2.begin(), ::tolower);
s_nows2.erase(std::remove(s_nows2.begin(), s_nows2.end(), ' '), s_nows2.end());
s_nows2.erase(std::remove(s_nows2.begin(), s_nows2.end(), '-'), s_nows2.end());
if (s_nows2 == s_nows) {
return true;
}
}
return false;
}
template <class EnumType>
bool parse_enum_by_str(EnumType& enum_val, const char* name, Setting& root)
{
std::string val;
if (root.lookupValue(name, val)) {
bool found = nowhitespace_string_to_enum(enum_val, val);
if (not found) {
fprintf(stderr, "PARSER ERROR: Invalid option: \"%s\" for field \"%s\"\n", val.c_str(), name);
fprintf(stderr, "Valid options: \"%s\"", EnumType((typename EnumType::options)0).to_string().c_str());
for (uint32_t i = 1; i < EnumType::nof_types; i++) {
fprintf(stderr, ", \"%s\"", EnumType((typename EnumType::options)i).to_string().c_str());
}
fprintf(stderr, "\n");
return false;
}
return true;
}
return false;
}
template <class EnumType>
class field_asn1_enum_number : public field_asn1
{
EnumType* store_ptr;
public:
field_asn1_enum_number(const char* name_, EnumType* store_ptr_, bool* enabled_value_ = NULL) :
field_asn1(name_, enabled_value_),
store_ptr(store_ptr_)
{
}
int parse_value(Setting& root)
{
bool found = parse_enum_by_number(*store_ptr, name, root);
return found ? 0 : -1;
}
};
template <class EnumType>
field_asn1_enum_number<EnumType>* make_asn1_enum_number_parser(const char* name, EnumType* store_ptr,
bool* enabled = NULL)
{
return new field_asn1_enum_number<EnumType>(name, store_ptr, enabled);
}
template <class EnumType>
class field_asn1_enum_str : public field_asn1
{
EnumType* store_ptr;
public:
field_asn1_enum_str(const char* name_, EnumType* store_ptr_, bool* enabled_value_ = NULL) :
field_asn1(name_, enabled_value_),
store_ptr(store_ptr_)
{
}
int parse_value(Setting& root)
{
bool found = parse_enum_by_str(*store_ptr, name, root);
return found ? 0 : -1;
}
};
template <class EnumType>
field_asn1_enum_str<EnumType>* make_asn1_enum_str_parser(const char* name, EnumType* store_ptr, bool* enabled = NULL)
{
return new field_asn1_enum_str<EnumType>(name, store_ptr, enabled);
}
template <class EnumType>
class field_asn1_enum_number_str : public field_asn1
{
EnumType* store_ptr;
public:
field_asn1_enum_number_str(const char* name_, EnumType* store_ptr_, bool* enabled_value_ = NULL) :
field_asn1(name_, enabled_value_),
store_ptr(store_ptr_)
{
}
int parse_value(Setting& root)
{
bool found = parse_enum_by_number_str(*store_ptr, name, root);
return found ? 0 : -1;
}
};
template <class EnumType>
field_asn1_enum_number_str<EnumType>* make_asn1_enum_number_str_parser(const char* name, EnumType* store_ptr,
bool* enabled = NULL)
{
return new field_asn1_enum_number_str<EnumType>(name, store_ptr, enabled);
}
template <class ChoiceType>
class field_asn1_choice_str : public field_asn1
{
public:
typedef bool (*func_ptr)(ChoiceType*, const char*, Setting&);
field_asn1_choice_str(const char* name_, const char* choicetypename_, func_ptr f_, ChoiceType* store_ptr_,
bool* enabled_value_ = NULL) :
field_asn1(name_, enabled_value_),
store_ptr(store_ptr_),
choicetypename(choicetypename_),
f(f_)
{
}
int parse_value(Setting& root)
{
typename ChoiceType::types type;
bool found = parse_enum_by_str(type, choicetypename, root);
if (not found) {
return -1;
}
store_ptr->set(type);
if (f(store_ptr, name, root)) {
return 0;
}
return -1;
}
private:
ChoiceType* store_ptr;
const char* choicetypename;
func_ptr f;
};
template <class ChoiceType, class FuncOper>
field_asn1_choice_str<ChoiceType>* make_asn1_choice_str_parser(const char* name, const char* choicetypename,
ChoiceType* store_ptr, FuncOper f, bool* enabled = NULL)
{
return new field_asn1_choice_str<ChoiceType>(name, choicetypename, f, store_ptr, enabled);
}
template <class ChoiceType>
class field_asn1_choice_number : public field_asn1
{
public:
typedef bool (*func_ptr)(ChoiceType*, const char*, Setting&);
field_asn1_choice_number(const char* name_, const char* choicetypename_, func_ptr f_, ChoiceType* store_ptr_,
bool* enabled_value_ = NULL) :
field_asn1(name_, enabled_value_),
store_ptr(store_ptr_),
choicetypename(choicetypename_),
f(f_)
{
}
int parse_value(Setting& root)
{
typename ChoiceType::types type;
bool found = parse_enum_by_number(type, choicetypename, root);
if (not found) {
return -1;
}
store_ptr->set(type);
if (f(store_ptr, name, root)) {
return 0;
}
return -1;
}
private:
ChoiceType* store_ptr;
const char* choicetypename;
func_ptr f;
};
template <class BitString, class NumType>
class field_asn1_bitstring_number : public field_asn1
{
BitString* store_ptr;
public:
field_asn1_bitstring_number(const char* name_, BitString* store_ptr_, bool* enabled_value_ = NULL) :
field_asn1(name_, enabled_value_),
store_ptr(store_ptr_)
{
}
int parse_value(Setting& root)
{
NumType val;
if (parser::lookupValue(root, name, &val)) {
store_ptr->from_number(val);
return true;
} else {
std::string str_val;
if (parser::lookupValue(root, name, &str_val)) {
fprintf(stderr, "PARSER ERROR: Expected number for field %s but got the string \"%s\"\n", name,
str_val.c_str());
}
}
return false;
}
};
template <class BitString>
field_asn1_bitstring_number<BitString, uint32_t>* make_asn1_bitstring_number_parser(const char* name,
BitString* store_ptr)
{
return new field_asn1_bitstring_number<BitString, uint32_t>(name, store_ptr);
}
class phr_cnfg_parser : public parser::field_itf
{
public:
phr_cnfg_parser(asn1::rrc::mac_main_cfg_s::phr_cfg_c_* phr_cfg_) { phr_cfg = phr_cfg_; }
~phr_cnfg_parser() {}
int parse(Setting& root);
const char* get_name() { return "phr_cnfg"; }
private:
asn1::rrc::mac_main_cfg_s::phr_cfg_c_* phr_cfg;
};
class mbsfn_sf_cfg_list_parser : public parser::field_itf
{
public:
mbsfn_sf_cfg_list_parser(asn1::rrc::mbsfn_sf_cfg_list_l* mbsfn_list_, bool* enabled_) :
mbsfn_list(mbsfn_list_),
enabled(enabled_)
{
}
~mbsfn_sf_cfg_list_parser() {}
int parse(Setting& root);
const char* get_name() { return "mbsfnSubframeConfigList"; }
private:
asn1::rrc::mbsfn_sf_cfg_list_l* mbsfn_list;
bool* enabled;
};
class mbsfn_area_info_list_parser : public parser::field_itf
{
public:
mbsfn_area_info_list_parser(asn1::rrc::mbsfn_area_info_list_r9_l* mbsfn_list_, bool* enabled_) :
mbsfn_list(mbsfn_list_),
enabled(enabled_)
{
}
~mbsfn_area_info_list_parser() {}
int parse(Setting& root);
const char* get_name() { return "mbsfn_area_info_list"; }
private:
asn1::rrc::mbsfn_area_info_list_r9_l* mbsfn_list;
bool* enabled;
};
} }
#endif #endif

@ -39,6 +39,7 @@
#include "srsenb/hdr/mac/mac.h" #include "srsenb/hdr/mac/mac.h"
//#define WRITE_SIB_PCAP //#define WRITE_SIB_PCAP
using namespace asn1::rrc;
namespace srsenb { namespace srsenb {
@ -365,7 +366,8 @@ int mac::crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc)
return ret; return ret;
} }
int mac::set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { int mac::set_dl_ant_info(uint16_t rnti, phys_cfg_ded_s::ant_info_c_* dl_ant_info)
{
log_h->step(tti); log_h->step(tti);
int ret = -1; int ret = -1;
@ -654,7 +656,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res)
void mac::build_mch_sched(uint32_t tbs) void mac::build_mch_sched(uint32_t tbs)
{ {
int sfs_per_sched_period = mcch.pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9; int sfs_per_sched_period = mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].pmch_cfg_r9.sf_alloc_end_r9;
int bytes_per_sf = tbs/8 - 6;// leave 6 bytes for header int bytes_per_sf = tbs/8 - 6;// leave 6 bytes for header
int total_space_avail_bytes = sfs_per_sched_period*bytes_per_sf; int total_space_avail_bytes = sfs_per_sched_period*bytes_per_sf;
@ -691,8 +693,8 @@ int mac::get_mch_sched(bool is_mcch, dl_sched_t *dl_sched_res)
srslte_ra_mcs_t mcs; srslte_ra_mcs_t mcs;
srslte_ra_mcs_t mcs_data; srslte_ra_mcs_t mcs_data;
mcs.idx = this->sib13.mbsfn_area_info_list_r9[0].signalling_mcs_r9; mcs.idx = this->sib13.mbsfn_area_info_list_r9[0].mcch_cfg_r9.sig_mcs_r9;
mcs_data.idx = this->mcch.pmch_infolist_r9[0].pmch_config_r9.datamcs_r9; mcs_data.idx = this->mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].pmch_cfg_r9.data_mcs_r9;
srslte_dl_fill_ra_mcs(&mcs, this->cell_config.cell.nof_prb); srslte_dl_fill_ra_mcs(&mcs, this->cell_config.cell.nof_prb);
srslte_dl_fill_ra_mcs(&mcs_data, this->cell_config.cell.nof_prb); srslte_dl_fill_ra_mcs(&mcs_data, this->cell_config.cell.nof_prb);
if(is_mcch){ if(is_mcch){
@ -961,29 +963,22 @@ bool mac::process_pdus()
return ret; return ret;
} }
void mac::write_mcch(sib_type2_s* sib2, sib_type13_r9_s* sib13, mcch_msg_s* mcch)
void mac::write_mcch(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, LIBLTE_RRC_MCCH_MSG_STRUCT *mcch)
{ {
bzero(&mcch_payload_buffer[0],sizeof(uint8_t)*3000); this->mcch = *mcch;
mch.num_mtch_sched = this->mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9.size();
for (uint32_t i = 0; i < mch.num_mtch_sched; ++i) {
LIBLTE_BIT_MSG_STRUCT bitbuffer; mch.mtch_sched[i].lcid =
liblte_rrc_pack_mcch_msg(mcch, &bitbuffer); this->mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9[i].lc_ch_id_r9;
memcpy(&this->mcch ,mcch, sizeof(LIBLTE_RRC_MCCH_MSG_STRUCT));
mch.num_mtch_sched = this->mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size;
for(uint32_t i = 0; i < mch.num_mtch_sched; i++){
mch.mtch_sched[i].lcid = this->mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[i].logicalchannelid_r9;
} }
this->sib2 = *sib2;
this->sib13 = *sib13;
memcpy(&this->sib2,sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); const int rlc_header_len = 1;
memcpy(&this->sib2,sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT)); // TODO: consolidate relevant parts into 1 struct asn1::bit_ref bref(&mcch_payload_buffer[rlc_header_len], sizeof(mcch_payload_buffer) - rlc_header_len);
current_mcch_length = floor(bitbuffer.N_bits/8); mcch->pack(bref);
if(bitbuffer.N_bits%8 != 0) { current_mcch_length = bref.distance_bytes(&mcch_payload_buffer[1]);
current_mcch_length++;
}
int rlc_header_len = 1;
current_mcch_length = current_mcch_length + rlc_header_len; current_mcch_length = current_mcch_length + rlc_header_len;
srslte_bit_pack_vector(&bitbuffer.msg[0], &mcch_payload_buffer[rlc_header_len], bitbuffer.N_bits);
ue_db[SRSLTE_MRNTI] = new ue; ue_db[SRSLTE_MRNTI] = new ue;
ue_db[SRSLTE_MRNTI]->config(SRSLTE_MRNTI, cell.nof_prb, &scheduler, rrc_h, rlc_h, log_h); ue_db[SRSLTE_MRNTI]->config(SRSLTE_MRNTI, cell.nof_prb, &scheduler, rrc_h, rlc_h, log_h);

@ -285,7 +285,8 @@ int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code)
return ret; return ret;
} }
int sched::dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { int sched::dl_ant_info(uint16_t rnti, asn1::rrc::phys_cfg_ded_s::ant_info_c_* dl_ant_info)
{
int ret = 0; int ret = 0;
pthread_rwlock_rdlock(&rwlock); pthread_rwlock_rdlock(&rwlock);
if (ue_db.count(rnti)) { if (ue_db.count(rnti)) {

@ -59,7 +59,6 @@ sched_ue::sched_ue() : dl_next_alloc(NULL), ul_next_alloc(NULL), has_pucch(false
bzero(&dci_locations, sizeof(dci_locations)); bzero(&dci_locations, sizeof(dci_locations));
bzero(&dl_harq, sizeof(dl_harq)); bzero(&dl_harq, sizeof(dl_harq));
bzero(&ul_harq, sizeof(ul_harq)); bzero(&ul_harq, sizeof(ul_harq));
bzero(&dl_ant_info, sizeof(dl_ant_info));
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
reset(); reset();
@ -425,10 +424,10 @@ void sched_ue::set_dl_cqi(uint32_t tti, uint32_t cqi)
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
void sched_ue::set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *d) void sched_ue::set_dl_ant_info(asn1::rrc::phys_cfg_ded_s::ant_info_c_* d)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
memcpy(&dl_ant_info, d, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); dl_ant_info = *d;
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
@ -500,12 +499,12 @@ int sched_ue::generate_format1(dl_harq_proc *h,
uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0); uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0);
uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols);
if(need_conres_ce and cell.nof_prb<10) { // SRB0 Tx. Use a higher MCS for the PRACH to fit in 6 PRBs if(need_conres_ce and cell.nof_prb<10) { // SRB0 Tx. Use a higher MCS for the PRACH to fit in 6 PRBs
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(4), nof_prb)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_dl_tbs_idx_from_mcs(4), nof_prb) / 8;
mcs = 4; mcs = 4;
} else if (fixed_mcs_dl < 0) { } else if (fixed_mcs_dl < 0) {
tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_dl_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb) / 8;
mcs = fixed_mcs_dl; mcs = fixed_mcs_dl;
} }
@ -622,7 +621,7 @@ int sched_ue::generate_format2a_unlocked(dl_harq_proc *h,
if (fixed_mcs_dl < 0) { if (fixed_mcs_dl < 0) {
tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx((uint32_t) srslte_ra_tbs_idx_from_mcs((uint32_t) fixed_mcs_dl), nof_prb) / 8; tbs = srslte_ra_tbs_from_idx((uint32_t)srslte_ra_dl_tbs_idx_from_mcs((uint32_t)fixed_mcs_dl), nof_prb) / 8;
mcs = fixed_mcs_dl; mcs = fixed_mcs_dl;
} }
h->new_tx(tb, tti, mcs, tbs, data->dci_location.ncce); h->new_tx(tb, tti, mcs, tbs, data->dci_location.ncce);
@ -712,7 +711,7 @@ int sched_ue::generate_format0(ul_harq_proc *h,
bool is_newtx = true; bool is_newtx = true;
if (h->get_rar_mcs(&mcs)) { if (h->get_rar_mcs(&mcs)) {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_ul_tbs_idx_from_mcs(mcs), allocation.L) / 8;
h->new_tx(tti, mcs, tbs); h->new_tx(tti, mcs, tbs);
} else if (h->is_empty(0)) { } else if (h->is_empty(0)) {
@ -723,7 +722,7 @@ int sched_ue::generate_format0(ul_harq_proc *h,
if (fixed_mcs_ul < 0) { if (fixed_mcs_ul < 0) {
tbs = alloc_tbs_ul(allocation.L, nof_re, req_bytes, &mcs); tbs = alloc_tbs_ul(allocation.L, nof_re, req_bytes, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul), allocation.L)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_ul_tbs_idx_from_mcs(fixed_mcs_ul), allocation.L) / 8;
mcs = fixed_mcs_ul; mcs = fixed_mcs_ul;
} }
@ -732,7 +731,7 @@ int sched_ue::generate_format0(ul_harq_proc *h,
} else { } else {
h->new_retx(0, tti, &mcs, NULL); h->new_retx(0, tti, &mcs, NULL);
is_newtx = false; is_newtx = false;
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_ul_tbs_idx_from_mcs(mcs), allocation.L) / 8;
} }
data->rnti = rnti; data->rnti = rnti;
@ -936,7 +935,7 @@ uint32_t sched_ue::get_required_prb_dl(uint32_t req_bytes, uint32_t nof_ctrl_sym
if(fixed_mcs_dl < 0) { if(fixed_mcs_dl < 0) {
tbs = alloc_tbs_dl(n+1, nof_re, 0, &mcs); tbs = alloc_tbs_dl(n+1, nof_re, 0, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), n+1)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_dl_tbs_idx_from_mcs(fixed_mcs_dl), n + 1) / 8;
} }
if (tbs > 0) { if (tbs > 0) {
nbytes = tbs; nbytes = tbs;
@ -970,7 +969,7 @@ uint32_t sched_ue::get_required_prb_ul(uint32_t req_bytes)
if (fixed_mcs_ul < 0) { if (fixed_mcs_ul < 0) {
tbs = alloc_tbs_ul(n, nof_re, 0, &mcs); tbs = alloc_tbs_ul(n, nof_re, 0, &mcs);
} else { } else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul), n)/8; tbs = srslte_ra_tbs_from_idx(srslte_ra_ul_tbs_idx_from_mcs(fixed_mcs_ul), n) / 8;
} }
if (tbs > 0) { if (tbs > 0) {
nbytes = tbs; nbytes = tbs;
@ -1059,22 +1058,21 @@ srslte_dci_format_t sched_ue::get_dci_format() {
if (phy_config_dedicated_enabled) { if (phy_config_dedicated_enabled) {
/* FIXME: Assumes UE-Specific Search Space (Not common) */ /* FIXME: Assumes UE-Specific Search Space (Not common) */
switch (dl_ant_info.tx_mode) { switch (dl_ant_info.explicit_value().tx_mode) {
case LIBLTE_RRC_TRANSMISSION_MODE_1: case asn1::rrc::ant_info_ded_s::tx_mode_e_::tm1:
case LIBLTE_RRC_TRANSMISSION_MODE_2: case asn1::rrc::ant_info_ded_s::tx_mode_e_::tm2:
ret = SRSLTE_DCI_FORMAT1; ret = SRSLTE_DCI_FORMAT1;
break; break;
case LIBLTE_RRC_TRANSMISSION_MODE_3: case asn1::rrc::ant_info_ded_s::tx_mode_e_::tm3:
ret = SRSLTE_DCI_FORMAT2A; ret = SRSLTE_DCI_FORMAT2A;
break; break;
case LIBLTE_RRC_TRANSMISSION_MODE_4: case asn1::rrc::ant_info_ded_s::tx_mode_e_::tm4:
ret = SRSLTE_DCI_FORMAT2; ret = SRSLTE_DCI_FORMAT2;
break; break;
case LIBLTE_RRC_TRANSMISSION_MODE_5: case asn1::rrc::ant_info_ded_s::tx_mode_e_::tm5:
case LIBLTE_RRC_TRANSMISSION_MODE_6: case asn1::rrc::ant_info_ded_s::tx_mode_e_::tm6:
case LIBLTE_RRC_TRANSMISSION_MODE_7: case asn1::rrc::ant_info_ded_s::tx_mode_e_::tm7:
case LIBLTE_RRC_TRANSMISSION_MODE_8: case asn1::rrc::ant_info_ded_s::tx_mode_e_::tm8_v920:
case LIBLTE_RRC_TRANSMISSION_MODE_N_ITEMS:
default: default:
Warning("Incorrect transmission mode (rnti=%04x)\n", rnti); Warning("Incorrect transmission mode (rnti=%04x)\n", rnti);
} }
@ -1156,7 +1154,9 @@ uint32_t sched_ue::format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb) {
return nof_prb; return nof_prb;
} }
int sched_ue::cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t max_Qm, uint32_t *mcs) { int sched_ue::cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t max_Qm, bool is_ul,
uint32_t* mcs)
{
float max_coderate = srslte_cqi_to_coderate(cqi); float max_coderate = srslte_cqi_to_coderate(cqi);
int sel_mcs = max_mcs+1; int sel_mcs = max_mcs+1;
float coderate = 99; float coderate = 99;
@ -1166,10 +1166,11 @@ int sched_ue::cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32
do { do {
sel_mcs--; sel_mcs--;
uint32_t tbs_idx = srslte_ra_tbs_idx_from_mcs(sel_mcs); uint32_t tbs_idx = (is_ul) ? srslte_ra_ul_tbs_idx_from_mcs(sel_mcs) : srslte_ra_dl_tbs_idx_from_mcs(sel_mcs);
tbs = srslte_ra_tbs_from_idx(tbs_idx, nof_prb); tbs = srslte_ra_tbs_from_idx(tbs_idx, nof_prb);
coderate = srslte_coderate(tbs, nof_re); coderate = srslte_coderate(tbs, nof_re);
Qm = SRSLTE_MIN(max_Qm, srslte_mod_bits_x_symbol(srslte_ra_mod_from_mcs(sel_mcs))); srslte_mod_t mod = (is_ul) ? srslte_ra_ul_mod_from_mcs(sel_mcs) : srslte_ra_dl_mod_from_mcs(sel_mcs);
Qm = SRSLTE_MIN(max_Qm, srslte_mod_bits_x_symbol(mod));
eff_coderate = coderate/Qm; eff_coderate = coderate/Qm;
} while((sel_mcs > 0 && coderate > max_coderate) || eff_coderate > 0.930); } while((sel_mcs > 0 && coderate > max_coderate) || eff_coderate > 0.930);
if (mcs) { if (mcs) {
@ -1210,12 +1211,13 @@ int sched_ue::alloc_tbs(uint32_t nof_prb,
uint32_t max_Qm = is_ul?4:6; // Allow 16-QAM in PUSCH Only uint32_t max_Qm = is_ul?4:6; // Allow 16-QAM in PUSCH Only
// TODO: Compute real spectral efficiency based on PUSCH-UCI configuration // TODO: Compute real spectral efficiency based on PUSCH-UCI configuration
int tbs = cqi_to_tbs(cqi, nof_prb, nof_re, max_mcs, max_Qm, &sel_mcs)/8; int tbs = cqi_to_tbs(cqi, nof_prb, nof_re, max_mcs, max_Qm, is_ul, &sel_mcs) / 8;
/* If less bytes are requested, lower the MCS */ /* If less bytes are requested, lower the MCS */
if (tbs > (int) req_bytes && req_bytes > 0) { if (tbs > (int) req_bytes && req_bytes > 0) {
uint32_t req_tbs_idx = srslte_ra_tbs_to_table_idx(req_bytes*8, nof_prb); int req_tbs_idx = srslte_ra_tbs_to_table_idx(req_bytes * 8, nof_prb);
uint32_t req_mcs = srslte_ra_mcs_from_tbs_idx(req_tbs_idx); int req_mcs = (is_ul) ? srslte_ra_ul_mcs_from_tbs_idx(req_tbs_idx) : srslte_ra_dl_mcs_from_tbs_idx(req_tbs_idx);
if (req_mcs < sel_mcs) { if (req_mcs < sel_mcs) {
sel_mcs = req_mcs; sel_mcs = req_mcs;
tbs = srslte_ra_tbs_from_idx(req_tbs_idx, nof_prb)/8; tbs = srslte_ra_tbs_from_idx(req_tbs_idx, nof_prb)/8;
@ -1224,7 +1226,8 @@ int sched_ue::alloc_tbs(uint32_t nof_prb,
// Avoid the unusual case n_prb=1, mcs=6 tbs=328 (used in voip) // Avoid the unusual case n_prb=1, mcs=6 tbs=328 (used in voip)
if (nof_prb == 1 && sel_mcs == 6) { if (nof_prb == 1 && sel_mcs == 6) {
sel_mcs--; sel_mcs--;
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(sel_mcs), nof_prb)/8; uint32_t tbs_idx = (is_ul) ? srslte_ra_ul_tbs_idx_from_mcs(sel_mcs) : srslte_ra_dl_tbs_idx_from_mcs(sel_mcs);
tbs = srslte_ra_tbs_from_idx(tbs_idx, nof_prb) / 8;
} }
if (mcs && tbs >= 0) { if (mcs && tbs >= 0) {

@ -62,6 +62,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
// Command line only options // Command line only options
bpo::options_description general("General options"); bpo::options_description general("General options");
// clang-format off
general.add_options() general.add_options()
("help,h", "Produce help message") ("help,h", "Produce help message")
("version,v", "Print version information and exit") ("version,v", "Print version information and exit")
@ -130,90 +131,30 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
("log.file_max_size", bpo::value<int>(&args->log.file_max_size)->default_value(-1), "Maximum file size (in kilobytes). When passed, multiple files are created. Default -1 (single file)") ("log.file_max_size", bpo::value<int>(&args->log.file_max_size)->default_value(-1), "Maximum file size (in kilobytes). When passed, multiple files are created. Default -1 (single file)")
/* MCS section */ /* MCS section */
("scheduler.pdsch_mcs", ("scheduler.pdsch_mcs", bpo::value<int>(&args->expert.mac.sched.pdsch_mcs)->default_value(-1), "Optional fixed PDSCH MCS (ignores reported CQIs if specified)")
bpo::value<int>(&args->expert.mac.sched.pdsch_mcs)->default_value(-1), ("scheduler.pdsch_max_mcs", bpo::value<int>(&args->expert.mac.sched.pdsch_max_mcs)->default_value(-1), "Optional PDSCH MCS limit")
"Optional fixed PDSCH MCS (ignores reported CQIs if specified)") ("scheduler.pusch_mcs", bpo::value<int>(&args->expert.mac.sched.pusch_mcs)->default_value(-1), "Optional fixed PUSCH MCS (ignores reported CQIs if specified)")
("scheduler.pdsch_max_mcs", ("scheduler.pusch_max_mcs", bpo::value<int>(&args->expert.mac.sched.pusch_max_mcs)->default_value(-1), "Optional PUSCH MCS limit")
bpo::value<int>(&args->expert.mac.sched.pdsch_max_mcs)->default_value(-1), ("scheduler.nof_ctrl_symbols", bpo::value<int>(&args->expert.mac.sched.nof_ctrl_symbols)->default_value(3), "Number of control symbols")
"Optional PDSCH MCS limit")
("scheduler.pusch_mcs",
bpo::value<int>(&args->expert.mac.sched.pusch_mcs)->default_value(-1),
"Optional fixed PUSCH MCS (ignores reported CQIs if specified)")
("scheduler.pusch_max_mcs",
bpo::value<int>(&args->expert.mac.sched.pusch_max_mcs)->default_value(-1),
"Optional PUSCH MCS limit")
("scheduler.nof_ctrl_symbols",
bpo::value<int>(&args->expert.mac.sched.nof_ctrl_symbols)->default_value(3),
"Number of control symbols")
/* Expert section */ /* Expert section */
("expert.metrics_period_secs", ("expert.metrics_period_secs", bpo::value<float>(&args->expert.metrics_period_secs)->default_value(1.0), "Periodicity for metrics in seconds")
bpo::value<float>(&args->expert.metrics_period_secs)->default_value(1.0), ("expert.metrics_csv_enable", bpo::value<bool>(&args->expert.metrics_csv_enable)->default_value(false), "Write metrics to CSV file")
"Periodicity for metrics in seconds") ("expert.metrics_csv_filename", bpo::value<string>(&args->expert.metrics_csv_filename)->default_value("/tmp/enb_metrics.csv"), "Metrics CSV filename")
("expert.pregenerate_signals", bpo::value<bool>(&args->expert.phy.pregenerate_signals)->default_value(false), "Pregenerate uplink signals after attach. Improves CPU performance.")
("expert.metrics_csv_enable", ("expert.pusch_max_its", bpo::value<int>(&args->expert.phy.pusch_max_its)->default_value(8), "Maximum number of turbo decoder iterations")
bpo::value<bool>(&args->expert.metrics_csv_enable)->default_value(false), ("expert.pusch_8bit_decoder", bpo::value<bool>(&args->expert.phy.pusch_8bit_decoder)->default_value(false), "Use 8-bit for LLR representation and turbo decoder trellis computation (Experimental)")
"Write metrics to CSV file") ("expert.tx_amplitude", bpo::value<float>(&args->expert.phy.tx_amplitude)->default_value(0.6), "Transmit amplitude factor")
("expert.nof_phy_threads", bpo::value<int>(&args->expert.phy.nof_phy_threads)->default_value(2), "Number of PHY threads")
("expert.metrics_csv_filename", ("expert.link_failure_nof_err", bpo::value<int>(&args->expert.mac.link_failure_nof_err)->default_value(100), "Number of PUSCH failures after which a radio-link failure is triggered")
bpo::value<string>(&args->expert.metrics_csv_filename)->default_value("/tmp/enb_metrics.csv"), ("expert.max_prach_offset_us", bpo::value<float>(&args->expert.phy.max_prach_offset_us)->default_value(30), "Maximum allowed RACH offset (in us)")
"Metrics CSV filename") ("expert.equalizer_mode", bpo::value<string>(&args->expert.phy.equalizer_mode)->default_value("mmse"), "Equalizer mode")
("expert.estimator_fil_w", bpo::value<float>(&args->expert.phy.estimator_fil_w)->default_value(0.1), "Chooses the coefficients for the 3-tap channel estimator centered filter.")
("expert.pregenerate_signals", ("expert.rrc_inactivity_timer", bpo::value<uint32_t>(&args->expert.rrc_inactivity_timer)->default_value(60000), "Inactivity timer in ms")
bpo::value<bool>(&args->expert.phy.pregenerate_signals)->default_value(false), ("expert.enable_mbsfn", bpo::value<bool>(&args->expert.enable_mbsfn)->default_value(false), "Enables MBMS in the eNB")
"Pregenerate uplink signals after attach. Improves CPU performance.") ("expert.print_buffer_state", bpo::value<bool>(&args->expert.print_buffer_state)->default_value(false), "Prints on the console the buffer state every 10 seconds")
("expert.m1u_multiaddr", bpo::value<string>(&args->expert.m1u_multiaddr)->default_value("239.255.0.1"), "M1-U Multicast address the eNB joins.")
("expert.pusch_max_its", ("expert.m1u_if_addr", bpo::value<string>(&args->expert.m1u_if_addr)->default_value("127.0.1.201"), "IP address of the interface the eNB will listen for M1-U traffic.")
bpo::value<int>(&args->expert.phy.pusch_max_its)->default_value(8),
"Maximum number of turbo decoder iterations")
("expert.pusch_8bit_decoder",
bpo::value<bool>(&args->expert.phy.pusch_8bit_decoder)->default_value(false),
"Use 8-bit for LLR representation and turbo decoder trellis computation (Experimental)")
("expert.tx_amplitude",
bpo::value<float>(&args->expert.phy.tx_amplitude)->default_value(0.6),
"Transmit amplitude factor")
("expert.nof_phy_threads",
bpo::value<int>(&args->expert.phy.nof_phy_threads)->default_value(2),
"Number of PHY threads")
("expert.link_failure_nof_err",
bpo::value<int>(&args->expert.mac.link_failure_nof_err)->default_value(100),
"Number of PUSCH failures after which a radio-link failure is triggered")
("expert.max_prach_offset_us",
bpo::value<float>(&args->expert.phy.max_prach_offset_us)->default_value(30),
"Maximum allowed RACH offset (in us)")
("expert.equalizer_mode",
bpo::value<string>(&args->expert.phy.equalizer_mode)->default_value("mmse"),
"Equalizer mode")
("expert.estimator_fil_w",
bpo::value<float>(&args->expert.phy.estimator_fil_w)->default_value(0.1),
"Chooses the coefficients for the 3-tap channel estimator centered filter.")
("expert.rrc_inactivity_timer",
bpo::value<uint32_t>(&args->expert.rrc_inactivity_timer)->default_value(60000),
"Inactivity timer in ms")
("expert.enable_mbsfn",
bpo::value<bool>(&args->expert.enable_mbsfn)->default_value(false),
"Enables MBMS in the eNB")
("expert.print_buffer_state",
bpo::value<bool>(&args->expert.print_buffer_state)->default_value(false),
"Prints on the console the buffer state every 10 seconds")
("expert.m1u_multiaddr",
bpo::value<string>(&args->expert.m1u_multiaddr)->default_value("239.255.0.1"),
"M1-U Multicast address the eNB joins.")
("expert.m1u_if_addr",
bpo::value<string>(&args->expert.m1u_if_addr)->default_value("127.0.1.201"),
"IP address of the interface the eNB will listen for M1-U traffic.")
; ;
// Positional options - config file location // Positional options - config file location
@ -221,6 +162,8 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
position.add_options() position.add_options()
("config_file", bpo::value< string >(&config_file), "eNodeB configuration file") ("config_file", bpo::value< string >(&config_file), "eNodeB configuration file")
; ;
// clang-format on
bpo::positional_options_description p; bpo::positional_options_description p;
p.add("config_file", -1); p.add("config_file", -1);

@ -24,10 +24,11 @@
* *
*/ */
#include "srslte/common/threads.h" #include "srsenb/hdr/phy/txrx.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/log.h" #include "srslte/common/log.h"
#include "srslte/common/threads.h"
#include <sstream> #include <sstream>
#include "srsenb/hdr/phy/txrx.h"
#include <assert.h> #include <assert.h>
@ -37,7 +38,7 @@
#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) #define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__)
using namespace std; using namespace std;
using namespace asn1::rrc;
namespace srsenb { namespace srsenb {
@ -81,7 +82,7 @@ bool phch_common::init(srslte_cell_t *cell_, srslte::radio* radio_h_, mac_interf
{ {
radio = radio_h_; radio = radio_h_;
mac = mac_; mac = mac_;
memcpy(&cell, cell_, sizeof(srslte_cell_t)); cell = *cell_;
pthread_mutex_init(&user_mutex, NULL); pthread_mutex_init(&user_mutex, NULL);
@ -250,7 +251,7 @@ int phch_common::ue_db_get_last_ul_tbs(uint16_t rnti, uint32_t tti) {
void phch_common::configure_mbsfn(phy_interface_rrc::phy_cfg_mbsfn_t *cfg) void phch_common::configure_mbsfn(phy_interface_rrc::phy_cfg_mbsfn_t *cfg)
{ {
memcpy(&mbsfn, cfg, sizeof(phy_interface_rrc::phy_cfg_mbsfn_t)); mbsfn = *cfg;
build_mch_table(); build_mch_table();
build_mcch_table(); build_mcch_table();
@ -261,9 +262,14 @@ void phch_common::configure_mbsfn(phy_interface_rrc::phy_cfg_mbsfn_t *cfg)
void phch_common::build_mch_table() void phch_common::build_mch_table()
{ {
// First reset tables // First reset tables
bzero(&mch_table[0], sizeof(uint8_t)*40); ZERO_OBJECT(mcch_table);
// 40 element table represents 4 frames (40 subframes) // 40 element table represents 4 frames (40 subframes)
generate_mch_table(&mch_table[0], mbsfn.mbsfn_subfr_cnfg.subfr_alloc,(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == mbsfn.mbsfn_subfr_cnfg.subfr_alloc_num_frames)?1:4); if (mbsfn.mbsfn_subfr_cnfg.sf_alloc.type().value == mbsfn_sf_cfg_s::sf_alloc_c_::types::one_frame) {
generate_mch_table(&mch_table[0], (uint32_t)mbsfn.mbsfn_subfr_cnfg.sf_alloc.one_frame().to_number(), 1);
} else {
generate_mch_table(&mch_table[0], (uint32_t)mbsfn.mbsfn_subfr_cnfg.sf_alloc.four_frames().to_number(), 4);
}
// Debug // Debug
std::stringstream ss; std::stringstream ss;
ss << "|"; ss << "|";
@ -274,9 +280,9 @@ void phch_common::build_mch_table()
void phch_common::build_mcch_table() void phch_common::build_mcch_table()
{ {
bzero(&mcch_table[0], sizeof(uint8_t)*10); ZERO_OBJECT(mcch_table);
generate_mcch_table(&mcch_table[0], mbsfn.mbsfn_area_info.sf_alloc_info_r9); generate_mcch_table(mcch_table, static_cast<uint32>(mbsfn.mbsfn_area_info.mcch_cfg_r9.sf_alloc_info_r9.to_number()));
std::stringstream ss; std::stringstream ss;
ss << "|"; ss << "|";
@ -296,16 +302,15 @@ bool phch_common::is_mcch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti)
sf = phy_tti%10; sf = phy_tti%10;
if(sib13_configured) { if(sib13_configured) {
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT *subfr_cnfg = &mbsfn.mbsfn_subfr_cnfg; mbsfn_area_info_r9_s* area_info = &mbsfn.mbsfn_area_info;
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *area_info = &mbsfn.mbsfn_area_info;
offset = area_info->mcch_offset_r9; offset = area_info->mcch_cfg_r9.mcch_offset_r9;
period = liblte_rrc_mcch_repetition_period_r9_num[area_info->mcch_repetition_period_r9]; period = area_info->mcch_cfg_r9.mcch_repeat_period_r9.to_number();
if((sfn%period == offset) && mcch_table[sf] > 0) { if((sfn%period == offset) && mcch_table[sf] > 0) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length]; cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number();
cfg->mbsfn_mcs = liblte_rrc_mcch_signalling_mcs_r9_num[area_info->signalling_mcs_r9]; cfg->mbsfn_mcs = area_info->mcch_cfg_r9.sig_mcs_r9.to_number();
cfg->mbsfn_encode = true; cfg->mbsfn_encode = true;
cfg->is_mcch = true; cfg->is_mcch = true;
return true; return true;
@ -336,24 +341,24 @@ bool phch_common::is_mch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti)
} }
// Not MCCH, check for MCH // Not MCCH, check for MCH
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT *subfr_cnfg = &mbsfn.mbsfn_subfr_cnfg; mbsfn_sf_cfg_s* subfr_cnfg = &mbsfn.mbsfn_subfr_cnfg;
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *area_info = &mbsfn.mbsfn_area_info; mbsfn_area_info_r9_s* area_info = &mbsfn.mbsfn_area_info;
offset = subfr_cnfg->radio_fr_alloc_offset; offset = subfr_cnfg->radioframe_alloc_offset;
period = liblte_rrc_radio_frame_allocation_period_num[subfr_cnfg->radio_fr_alloc_period]; period = subfr_cnfg->radioframe_alloc_period.to_number();
if (LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == subfr_cnfg->subfr_alloc_num_frames) { if (subfr_cnfg->sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::one_frame) {
if ((sfn%period == offset) && (mch_table[sf] > 0)) { if ((sfn%period == offset) && (mch_table[sf] > 0)) {
if (sib13_configured) { if (sib13_configured) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length]; cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number();
if (mcch_configured) { if (mcch_configured) {
// Iterate through PMCH configs to see which one applies in the current frame // Iterate through PMCH configs to see which one applies in the current frame
LIBLTE_RRC_MCCH_MSG_STRUCT *mcch = &mbsfn.mcch; mbsfn_area_cfg_r9_s* area_r9 = &mbsfn.mcch.msg.c1().mbsfn_area_cfg_r9();
uint32_t sf_alloc_idx = sfn%liblte_rrc_mbsfn_common_sf_alloc_period_r9_num[mcch->commonsf_allocperiod_r9]; uint32_t sf_alloc_idx = sfn % area_r9->common_sf_alloc_period_r9.to_number();
for (uint32_t i=0; i<mcch->pmch_infolist_r9_size; i++) { for (uint32_t i = 0; i < area_r9->pmch_info_list_r9.size(); i++) {
//if(sf_alloc_idx < mch_period_stop) { //if(sf_alloc_idx < mch_period_stop) {
cfg->mbsfn_mcs = mcch->pmch_infolist_r9[i].pmch_config_r9.datamcs_r9; cfg->mbsfn_mcs = area_r9->pmch_info_list_r9[i].pmch_cfg_r9.data_mcs_r9;
cfg->mbsfn_encode = true; cfg->mbsfn_encode = true;
//} //}
} }
@ -362,13 +367,13 @@ bool phch_common::is_mch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti)
} }
return true; return true;
} }
} else if (LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_FOUR == subfr_cnfg->subfr_alloc_num_frames) { } else if (subfr_cnfg->sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::four_frames) {
uint8_t idx = sfn%period; uint8_t idx = sfn%period;
if ((idx >= offset) && (idx < offset+4)) { if ((idx >= offset) && (idx < offset+4)) {
if (mch_table[(idx*10)+sf] > 0){ if (mch_table[(idx*10)+sf] > 0){
if (sib13_configured) { if (sib13_configured) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length]; cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number();
// TODO: check for MCCH configuration, set MCS and decode // TODO: check for MCCH configuration, set MCS and decode
} }

@ -37,6 +37,7 @@
#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) #define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__)
using namespace std; using namespace std;
using namespace asn1::rrc;
// Enable this to log SI // Enable this to log SI
//#define LOG_THIS(a) 1 //#define LOG_THIS(a) 1
@ -225,7 +226,6 @@ void phch_worker::set_time(uint32_t tti_, uint32_t tx_worker_cnt_, srslte_timest
int phch_worker::add_rnti(uint16_t rnti) int phch_worker::add_rnti(uint16_t rnti)
{ {
if (srslte_enb_dl_add_rnti(&enb_dl, rnti)) { if (srslte_enb_dl_add_rnti(&enb_dl, rnti)) {
return -1; return -1;
} }
@ -254,12 +254,10 @@ void phch_worker::set_conf_dedicated_ack(uint16_t rnti, bool ack){
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
void phch_worker::set_config_dedicated(uint16_t rnti, void phch_worker::set_config_dedicated(uint16_t rnti, srslte_refsignal_srs_cfg_t* srs_cfg, phys_cfg_ded_s* dedicated)
srslte_refsignal_srs_cfg_t *srs_cfg,
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated)
{ {
bool pucch_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; bool pucch_cqi_ack = dedicated->cqi_report_cfg.cqi_report_periodic.setup().simul_ack_nack_and_cqi;
bool pucch_ri = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present; bool pucch_ri = dedicated->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present;
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (ue_db.count(rnti)) { if (ue_db.count(rnti)) {
@ -267,26 +265,27 @@ void phch_worker::set_config_dedicated(uint16_t rnti,
srslte_uci_cfg_t uci_cfg; srslte_uci_cfg_t uci_cfg;
ZERO_OBJECT(uci_cfg); ZERO_OBJECT(uci_cfg);
if (dedicated->pusch_cnfg_ded_present && dedicated->sched_request_cnfg_present) { if (dedicated->pusch_cfg_ded_present && dedicated->sched_request_cfg_present) {
uci_cfg.I_offset_ack = dedicated->pusch_cnfg_ded.beta_offset_ack_idx; uci_cfg.I_offset_ack = dedicated->pusch_cfg_ded.beta_offset_ack_idx;
uci_cfg.I_offset_cqi = dedicated->pusch_cnfg_ded.beta_offset_cqi_idx; uci_cfg.I_offset_cqi = dedicated->pusch_cfg_ded.beta_offset_cqi_idx;
uci_cfg.I_offset_ri = dedicated->pusch_cnfg_ded.beta_offset_ri_idx; uci_cfg.I_offset_ri = dedicated->pusch_cfg_ded.beta_offset_ri_idx;
srslte_pucch_sched_t pucch_sched; srslte_pucch_sched_t pucch_sched;
ZERO_OBJECT(pucch_sched); ZERO_OBJECT(pucch_sched);
pucch_sched.N_pucch_1 = phy->pucch_cfg.n1_pucch_an; pucch_sched.N_pucch_1 = phy->pucch_cfg.n1_pucch_an;
pucch_sched.n_pucch_2 = dedicated->cqi_report_cnfg.report_periodic.pucch_resource_idx; pucch_sched.n_pucch_2 = dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx;
pucch_sched.n_pucch_sr = dedicated->sched_request_cnfg.sr_pucch_resource_idx; pucch_sched.n_pucch_sr = dedicated->sched_request_cfg.setup().sr_pucch_res_idx;
srslte_enb_ul_cfg_ue(&enb_ul, rnti, &uci_cfg, &pucch_sched, srs_cfg); srslte_enb_ul_cfg_ue(&enb_ul, rnti, &uci_cfg, &pucch_sched, srs_cfg);
ue_db[rnti].I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx; ue_db[rnti].I_sr = dedicated->sched_request_cfg.setup().sr_cfg_idx;
ue_db[rnti].I_sr_en = true; ue_db[rnti].I_sr_en = true;
} }
/* CQI Reporting */ /* CQI Reporting */
if (dedicated->cqi_report_cnfg.report_periodic_setup_present) { if (dedicated->cqi_report_cfg.cqi_report_periodic_present and
ue_db[rnti].pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; dedicated->cqi_report_cfg.cqi_report_periodic.type() == setup_e::setup) {
ue_db[rnti].pmi_idx = dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx;
ue_db[rnti].cqi_en = true; ue_db[rnti].cqi_en = true;
ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack; ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack;
} else { } else {
@ -295,34 +294,31 @@ void phch_worker::set_config_dedicated(uint16_t rnti,
} }
/* RI reporting */ /* RI reporting */
if (pucch_ri) { if (pucch_ri and dedicated->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present) {
ue_db[rnti].ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; ue_db[rnti].ri_idx = dedicated->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx;
ue_db[rnti].ri_en = true; ue_db[rnti].ri_en = true;
} else { } else {
ue_db[rnti].ri_idx = 0; ue_db[rnti].ri_idx = 0;
ue_db[rnti].ri_en = false; ue_db[rnti].ri_en = false;
} }
if (dedicated->antenna_info_present) { if (dedicated->ant_info_present) {
/* If default antenna info then follow 3GPP 36.331 clause 9.2.4 Default physical channel configuration */ /* If default antenna info then follow 3GPP 36.331 clause 9.2.4 Default physical channel configuration */
if (dedicated->antenna_info_default_value) { if (dedicated->ant_info.type() == phys_cfg_ded_s::ant_info_c_::types::default_value) {
ue_db[rnti].dedicated.ant_info.set(phys_cfg_ded_s::ant_info_c_::types::explicit_value);
if (enb_dl.cell.nof_ports == 1) { if (enb_dl.cell.nof_ports == 1) {
ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode = LIBLTE_RRC_TRANSMISSION_MODE_1; ue_db[rnti].dedicated.ant_info.explicit_value().tx_mode = ant_info_ded_s::tx_mode_e_::tm1;
} else { } else {
ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode = LIBLTE_RRC_TRANSMISSION_MODE_2; ue_db[rnti].dedicated.ant_info.explicit_value().tx_mode = ant_info_ded_s::tx_mode_e_::tm2;
} }
ue_db[rnti].dedicated.antenna_info_explicit_value.codebook_subset_restriction_present = false; ue_db[rnti].dedicated.ant_info.explicit_value().ue_tx_ant_sel.set(setup_e::release);
ue_db[rnti].dedicated.antenna_info_explicit_value.ue_tx_antenna_selection_setup_present = false;
ue_db[rnti].ri_idx = 0; ue_db[rnti].ri_idx = 0;
ue_db[rnti].ri_en = false; ue_db[rnti].ri_en = false;
} else { } else {
/* Physical channel reconfiguration according to 3GPP 36.331 clause 5.3.10.6 */ /* Physical channel reconfiguration according to 3GPP 36.331 clause 5.3.10.6 */
memcpy(&ue_db[rnti].dedicated.antenna_info_explicit_value, ue_db[rnti].dedicated.ant_info.explicit_value() = dedicated->ant_info.explicit_value();
&dedicated->antenna_info_explicit_value, if (dedicated->ant_info.explicit_value().tx_mode != ant_info_ded_s::tx_mode_e_::tm3 &&
sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); dedicated->ant_info.explicit_value().tx_mode != ant_info_ded_s::tx_mode_e_::tm4 && ue_db[rnti].ri_en) {
if (dedicated->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_3 &&
dedicated->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_4 &&
ue_db[rnti].ri_en) {
ue_db[rnti].ri_idx = 0; ue_db[rnti].ri_idx = 0;
ue_db[rnti].ri_en = false; ue_db[rnti].ri_en = false;
} }
@ -330,9 +326,9 @@ void phch_worker::set_config_dedicated(uint16_t rnti,
} }
/* Set PDSCH power allocation */ /* Set PDSCH power allocation */
if (dedicated->pdsch_cnfg_ded_present) { if (dedicated->pdsch_cfg_ded_present) {
ue_db[rnti].dedicated.pdsch_cnfg_ded_present = true; ue_db[rnti].dedicated.pdsch_cfg_ded_present = true;
ue_db[rnti].dedicated.pdsch_cnfg_ded = dedicated->pdsch_cnfg_ded; ue_db[rnti].dedicated.pdsch_cfg_ded = dedicated->pdsch_cfg_ded;
} }
} else { } else {
Error("Setting config dedicated: rnti=0x%x does not exist\n", rnti); Error("Setting config dedicated: rnti=0x%x does not exist\n", rnti);
@ -554,21 +550,23 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
} else if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { } else if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
cqi_enabled = true; cqi_enabled = true;
if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { if (ue_db[rnti].dedicated.ant_info_present and
ue_db[rnti].dedicated.ant_info.type() == phys_cfg_ded_s::ant_info_c_::types::explicit_value and
ue_db[rnti].dedicated.ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm4) {
cqi_value.wideband.pmi_present = true; cqi_value.wideband.pmi_present = true;
cqi_value.wideband.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0; cqi_value.wideband.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0;
} }
} else if (grants[i].grant.cqi_request) { } else if (grants[i].grant.cqi_request) {
cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
if (ue_db[rnti].dedicated.antenna_info_present && ( if (ue_db[rnti].dedicated.ant_info_present &&
ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 || (ue_db[rnti].dedicated.ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm3 ||
ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4 ue_db[rnti].dedicated.ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm4)) {
)) {
cqi_value.subband_hl.ri_present = true; cqi_value.subband_hl.ri_present = true;
} }
cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0; cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0;
cqi_value.subband_hl.four_antenna_ports = (phy->cell.nof_ports == 4); cqi_value.subband_hl.four_antenna_ports = (phy->cell.nof_ports == 4);
cqi_value.subband_hl.pmi_present = (ue_db[rnti].dedicated.cqi_report_cnfg.report_mode_aperiodic == LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31); cqi_value.subband_hl.pmi_present =
(ue_db[rnti].dedicated.cqi_report_cfg.cqi_report_mode_aperiodic == cqi_report_mode_aperiodic_e::rm31);
cqi_value.subband_hl.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0; cqi_value.subband_hl.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0;
cqi_enabled = true; cqi_enabled = true;
} }
@ -756,8 +754,14 @@ int phch_worker::decode_pucch()
srslte_cqi_value_t cqi_value; srslte_cqi_value_t cqi_value;
ZERO_OBJECT(cqi_value); ZERO_OBJECT(cqi_value);
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated; phys_cfg_ded_s* dedicated = &ue_db[rnti].dedicated;
LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = dedicated->antenna_info_explicit_value.tx_mode; ant_info_ded_s::tx_mode_e_ tx_mode;
if (dedicated->ant_info.type() == phys_cfg_ded_s::ant_info_c_::types::explicit_value) {
tx_mode = dedicated->ant_info.explicit_value().tx_mode;
} else {
tx_mode.value = ant_info_ded_s::tx_mode_e_::tm2;
Warning("Tx mode not yet set\n");
}
if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack[0] || !needs_ack[1])) { if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack[0] || !needs_ack[1])) {
if (ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx)) { if (ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx)) {
@ -768,7 +772,7 @@ int phch_worker::decode_pucch()
needs_pucch = true; needs_pucch = true;
needs_cqi = true; needs_cqi = true;
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { if (tx_mode == ant_info_ded_s::tx_mode_e_::tm4) {
cqi_value.wideband.pmi_present = true; cqi_value.wideband.pmi_present = true;
cqi_value.wideband.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0; cqi_value.wideband.rank_is_not_one = phy->ue_db_get_ri(rnti) > 0;
} }
@ -1013,9 +1017,9 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
/* Set power allocation */ /* Set power allocation */
float rho_a = ((enb_dl.cell.nof_ports == 1) ? 1.0f : sqrtf(2.0f)), rho_b = 1.0f; float rho_a = ((enb_dl.cell.nof_ports == 1) ? 1.0f : sqrtf(2.0f)), rho_b = 1.0f;
uint32_t pdsch_cnfg_ded = ue_db[rnti].dedicated.pdsch_cnfg_ded; pdsch_cfg_ded_s::p_a_e_ pdsch_cnfg_ded = ue_db[rnti].dedicated.pdsch_cfg_ded.p_a;
if (pdsch_cnfg_ded < (uint32_t) LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS) { if (pdsch_cnfg_ded < (uint32_t)pdsch_cfg_ded_s::p_a_e_::nof_types) {
float rho_a_db = liblte_rrc_pdsch_config_p_a_num[pdsch_cnfg_ded]; float rho_a_db = pdsch_cnfg_ded.to_number();
rho_a *= powf(10.0f, rho_a_db / 20.0f); rho_a *= powf(10.0f, rho_a_db / 20.0f);
} }
if (phy->pdsch_p_b < 4) { if (phy->pdsch_p_b < 4) {

@ -42,7 +42,7 @@
#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) #define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__)
using namespace std; using namespace std;
using namespace asn1::rrc;
namespace srsenb { namespace srsenb {
@ -59,27 +59,31 @@ void phy::parse_config(phy_cfg_t* cfg)
{ {
// PRACH configuration // PRACH configuration
prach_cfg.config_idx = cfg->prach_cnfg.prach_cnfg_info.prach_config_index; prach_cfg.config_idx = cfg->prach_cnfg.prach_cfg_info.prach_cfg_idx;
prach_cfg.hs_flag = cfg->prach_cnfg.prach_cnfg_info.high_speed_flag; prach_cfg.hs_flag = cfg->prach_cnfg.prach_cfg_info.high_speed_flag;
prach_cfg.root_seq_idx = cfg->prach_cnfg.root_sequence_index; prach_cfg.root_seq_idx = cfg->prach_cnfg.root_seq_idx;
prach_cfg.zero_corr_zone = cfg->prach_cnfg.prach_cnfg_info.zero_correlation_zone_config; prach_cfg.zero_corr_zone = cfg->prach_cnfg.prach_cfg_info.zero_correlation_zone_cfg;
prach_cfg.freq_offset = cfg->prach_cnfg.prach_cnfg_info.prach_freq_offset; prach_cfg.freq_offset = cfg->prach_cnfg.prach_cfg_info.prach_freq_offset;
// PUSCH DMRS configuration // PUSCH DMRS configuration
workers_common.pusch_cfg.cyclic_shift = cfg->pusch_cnfg.ul_rs.cyclic_shift; workers_common.pusch_cfg.cyclic_shift = cfg->pusch_cnfg.ul_ref_sigs_pusch.cyclic_shift;
workers_common.pusch_cfg.delta_ss = cfg->pusch_cnfg.ul_rs.group_assignment_pusch; workers_common.pusch_cfg.delta_ss = cfg->pusch_cnfg.ul_ref_sigs_pusch.group_assign_pusch;
workers_common.pusch_cfg.group_hopping_en = cfg->pusch_cnfg.ul_rs.group_hopping_enabled; workers_common.pusch_cfg.group_hopping_en = cfg->pusch_cnfg.ul_ref_sigs_pusch.group_hop_enabled;
workers_common.pusch_cfg.sequence_hopping_en = cfg->pusch_cnfg.ul_rs.sequence_hopping_enabled; workers_common.pusch_cfg.sequence_hopping_en = cfg->pusch_cnfg.ul_ref_sigs_pusch.seq_hop_enabled;
// PUSCH hopping configuration // PUSCH hopping configuration
workers_common.hopping_cfg.hop_mode = cfg->pusch_cnfg.hopping_mode == LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME ? workers_common.hopping_cfg.hop_mode =
srslte_pusch_hopping_cfg_t::SRSLTE_PUSCH_HOP_MODE_INTRA_SF : cfg->pusch_cnfg.pusch_cfg_basic.hop_mode ==
srslte_pusch_hopping_cfg_t::SRSLTE_PUSCH_HOP_MODE_INTER_SF; ; asn1::rrc::pusch_cfg_common_s::pusch_cfg_basic_s_::hop_mode_e_::intra_and_inter_sub_frame
workers_common.hopping_cfg.n_sb = cfg->pusch_cnfg.n_sb; ? srslte_pusch_hopping_cfg_t::SRSLTE_PUSCH_HOP_MODE_INTRA_SF
workers_common.hopping_cfg.hopping_offset = cfg->pusch_cnfg.pusch_hopping_offset; : srslte_pusch_hopping_cfg_t::SRSLTE_PUSCH_HOP_MODE_INTER_SF;
;
workers_common.hopping_cfg.n_sb = cfg->pusch_cnfg.pusch_cfg_basic.n_sb;
workers_common.hopping_cfg.hopping_offset = cfg->pusch_cnfg.pusch_cfg_basic.pusch_hop_offset;
// PUCCH configuration // PUCCH configuration
workers_common.pucch_cfg.delta_pucch_shift = liblte_rrc_delta_pucch_shift_num[cfg->pucch_cnfg.delta_pucch_shift%LIBLTE_RRC_DELTA_PUCCH_SHIFT_N_ITEMS]; workers_common.pucch_cfg.delta_pucch_shift =
cfg->pucch_cnfg.delta_pucch_shift.to_number(); // FIXME: Why was it a % operator before?
workers_common.pucch_cfg.N_cs = cfg->pucch_cnfg.n_cs_an; workers_common.pucch_cfg.N_cs = cfg->pucch_cnfg.n_cs_an;
workers_common.pucch_cfg.n_rb_2 = cfg->pucch_cnfg.n_rb_cqi; workers_common.pucch_cfg.n_rb_2 = cfg->pucch_cnfg.n_rb_cqi;
workers_common.pucch_cfg.srs_configured = false; workers_common.pucch_cfg.srs_configured = false;
@ -222,31 +226,35 @@ void phy::set_conf_dedicated_ack(uint16_t rnti, bool ack)
} }
} }
void phy::set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) void phy::set_config_dedicated(uint16_t rnti, phys_cfg_ded_s* dedicated)
{ {
for (uint32_t i=0;i<nof_workers;i++) { for (uint32_t i=0;i<nof_workers;i++) {
workers[i].set_config_dedicated(rnti, NULL, dedicated); workers[i].set_config_dedicated(rnti, NULL, dedicated);
} }
} }
void phy::configure_mbsfn(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13, LIBLTE_RRC_MCCH_MSG_STRUCT mcch) void phy::configure_mbsfn(sib_type2_s* sib2, sib_type13_r9_s* sib13, mcch_msg_s mcch)
{ {
if(sib2->mbsfn_subfr_cnfg_list_size > 1) { if (sib2->mbsfn_sf_cfg_list_present) {
Warning("SIB2 has %d MBSFN subframe configs - only 1 supported\n", sib2->mbsfn_subfr_cnfg_list_size); if (sib2->mbsfn_sf_cfg_list.size() == 0) {
Warning("SIB2 does not have any MBSFN config although it was set as present\n");
} else {
if (sib2->mbsfn_sf_cfg_list.size() > 1) {
Warning("SIB2 has %d MBSFN subframe configs - only 1 supported\n", sib2->mbsfn_sf_cfg_list.size());
}
phy_rrc_config.mbsfn.mbsfn_subfr_cnfg = sib2->mbsfn_sf_cfg_list[0];
} }
if(sib2->mbsfn_subfr_cnfg_list_size > 0) {
memcpy(&phy_rrc_config.mbsfn.mbsfn_subfr_cnfg, &sib2->mbsfn_subfr_cnfg_list[0], sizeof(LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT));
} }
memcpy(&phy_rrc_config.mbsfn.mbsfn_notification_cnfg, &sib13->mbsfn_notification_config, sizeof(LIBLTE_RRC_MBSFN_NOTIFICATION_CONFIG_STRUCT)); phy_rrc_config.mbsfn.mbsfn_notification_cnfg = sib13->notif_cfg_r9;
if(sib13->mbsfn_area_info_list_r9_size > 1) { if (sib13->mbsfn_area_info_list_r9.size() > 0) {
Warning("SIB13 has %d MBSFN area info elements - only 1 supported\n", sib13->mbsfn_area_info_list_r9_size); if (sib13->mbsfn_area_info_list_r9.size() > 1) {
Warning("SIB13 has %d MBSFN area info elements - only 1 supported\n", sib13->mbsfn_area_info_list_r9.size());
} }
if(sib13->mbsfn_area_info_list_r9_size > 0) { phy_rrc_config.mbsfn.mbsfn_area_info = sib13->mbsfn_area_info_list_r9[0];
memcpy(&phy_rrc_config.mbsfn.mbsfn_area_info, &sib13->mbsfn_area_info_list_r9[0], sizeof(LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT));
} }
memcpy(&phy_rrc_config.mbsfn.mcch, &mcch, sizeof(LIBLTE_RRC_MCCH_MSG_STRUCT)); phy_rrc_config.mbsfn.mcch = mcch;
workers_common.configure_mbsfn(&phy_rrc_config.mbsfn); workers_common.configure_mbsfn(&phy_rrc_config.mbsfn);
} }

File diff suppressed because it is too large Load Diff

@ -5,5 +5,6 @@ target_link_libraries(scheduler_test srsenb_mac
srsenb_phy srsenb_phy
srslte_common srslte_common
srslte_phy srslte_phy
rrc_asn1
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}) ${Boost_LIBRARIES})

@ -1,17 +1,4 @@
# IP tx/rx program test
add_executable(ip_test_enb ip_test.cc)
target_link_libraries(ip_test_enb srsenb_upper
srsenb_mac
srsenb_phy
srslte_common
srslte_phy
srslte_upper
srslte_radio
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}
${SEC_LIBRARIES})
# Simple PLMN -> MCC/MNC test # Simple PLMN -> MCC/MNC test
add_executable(plmn_test plmn_test.cc) add_executable(plmn_test plmn_test.cc)
target_link_libraries(plmn_test srsenb_upper srslte_asn1 ) target_link_libraries(plmn_test rrc_asn1)

@ -1,684 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2017 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of srsLTE.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <linux/ip.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include "srsenb/hdr/mac/mac.h"
#include "srsenb/hdr/phy/phy.h"
#include "srslte/common/threads.h"
#include "srslte/interfaces/enb_interfaces.h"
#include "srslte/common/common.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/logger_file.h"
#include "srslte/common/log_filter.h"
#include "srslte/upper/rlc.h"
#include "srslte/radio/radio.h"
#include "srslte/phy/utils/debug.h"
#define START_TUNTAP
#define USE_RADIO
/**********************************************************************
* Program arguments processing
***********************************************************************/
#define LCID 3
typedef struct {
float rx_freq;
float tx_freq;
float rx_gain;
float tx_gain;
bool enable_gui;
int time_adv;
std::string ip_address;
}prog_args_t;
uint32_t srsapps_verbose = 1;
prog_args_t prog_args;
void args_default(prog_args_t *args) {
args->rx_freq = 2.505e9;
args->tx_freq = 2.625e9;
args->rx_gain = 50.0;
args->tx_gain = 70.0;
args->enable_gui = false;
args->time_adv = -1; // calibrated for b210
args->ip_address = "192.168.3.1";
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [gGIrfFdv] \n", prog);
printf("\t-f RX frequency [Default %.1f MHz]\n", args->rx_freq/1e6);
printf("\t-F TX frequency [Default %.1f MHz]\n", args->tx_freq/1e6);
printf("\t-g RX gain [Default %.1f]\n", args->rx_gain);
printf("\t-G TX gain [Default %.1f]\n", args->tx_gain);
printf("\t-I IP address [Default %s]\n", args->ip_address.c_str());
printf("\t-t time advance (in samples) [Default %d]\n", args->time_adv);
printf("\t-d Enable gui [Default disabled]\n");
printf("\t-v [increase verbosity, default none]\n");
}
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "gGfFItdv")) != -1) {
switch (opt) {
case 'd':
args->enable_gui = true;
break;
case 'g':
args->rx_gain = atof(argv[optind]);
break;
case 'G':
args->tx_gain = atof(argv[optind]);
break;
case 'f':
args->rx_freq = atof(argv[optind]);
break;
case 'F':
args->tx_freq = atof(argv[optind]);
break;
case 'I':
args->ip_address = argv[optind];
break;
case 't':
args->time_adv = atoi(argv[optind]);
break;
case 'v':
srsapps_verbose++;
break;
default:
usage(args, argv[0]);
exit(-1);
}
}
if (args->rx_freq < 0 || args->tx_freq < 0) {
usage(args, argv[0]);
exit(-1);
}
}
LIBLTE_BYTE_MSG_STRUCT sib_buffer[2];
int setup_if_addr(char *ip_addr);
class tester : public srsue::pdcp_interface_rlc,
public srsue::rrc_interface_rlc,
public srsue::ue_interface,
public srsenb::rlc_interface_mac,
public srsenb::rrc_interface_mac,
public thread
{
public:
tester() {
rnti = 0;
}
void init(srslte::rlc *rlc_, srsenb::mac *mac_, srsenb::phy *phy_, srslte::log *log_h_, std::string ip_address) {
log_h = log_h_;
rlc = rlc_;
mac = mac_;
phy = phy_;
tun_fd = 0;
#ifdef START_TUNTAP
if (init_tuntap((char*) ip_address.c_str())) {
log_h->error("Initiating IP address\n");
}
#endif
pool = srslte::byte_buffer_pool::get_instance();
// Start reader thread
running=true;
start();
}
void write_pdu_bcch_bch(srslte::byte_buffer_t *sdu) {}
void write_pdu_bcch_dlsch(srslte::byte_buffer_t *sdu) {}
void write_pdu_pcch(srslte::byte_buffer_t *sdu) {}
void write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *pdu){}
void max_retx_attempted(){}
void add_user(uint16_t rnti) {}
void release_user(uint16_t rnti) {}
void upd_user(uint16_t rnti, uint16_t old_rnti) {}
void set_activity_user(uint16_t rnti) {}
bool is_paging_opportunity(uint32_t tti, uint32_t *payload_len) {return false;}
void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) {}
std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); }
void write_pdu(uint32_t lcid, srslte::byte_buffer_t *sdu)
{
int n = write(tun_fd, sdu->msg, sdu->N_bytes);
if (n != (int) sdu->N_bytes) {
log_h->error("TUN/TAP write failure n=%d, nof_bytes=%d\n", n, sdu->N_bytes);
return;
}
log_h->debug_hex(sdu->msg, sdu->N_bytes,
"Wrote %d bytes to TUN/TAP\n",
sdu->N_bytes);
pool->deallocate(sdu);
}
int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t *payload, uint32_t nof_bytes)
{
return rlc->read_pdu(lcid, payload, nof_bytes);
}
void read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t payload[srsenb::sched_interface::MAX_SIB_PAYLOAD_LEN])
{
if (sib_index < 2) {
memcpy(payload, sib_buffer[sib_index].msg, sib_buffer[sib_index].N_bytes);
}
}
void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t *payload, uint32_t nof_bytes)
{
srslte::byte_buffer_t *sdu = NULL;
log_h->info("Received PDU rnti=0x%x, lcid=%d, nof_bytes=%d\n", rnti, lcid, nof_bytes);
switch(lcid) {
case LCID:
rlc->write_pdu(lcid, payload, nof_bytes);
break;
case 0:
log_h->info("Received ConnectionRequest from rnti=0x%x\n", rnti);
// Configure User in MAC
srsenb::sched_interface::ue_cfg_t uecfg;
bzero(&uecfg, sizeof(srsenb::sched_interface::ue_cfg_t));
uecfg.maxharq_tx = 5;
uecfg.continuous_pusch = false;
uecfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
uecfg.ue_bearers[LCID].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
mac->ue_cfg(rnti, &uecfg);
// configure DRB1 as UM
LIBLTE_RRC_RLC_CONFIG_STRUCT cfg;
bzero(&cfg, sizeof(LIBLTE_RRC_RLC_CONFIG_STRUCT));
cfg.rlc_mode = LIBLTE_RRC_RLC_MODE_UM_BI;
cfg.dl_um_bi_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS100;
cfg.dl_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE10;
cfg.ul_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE10;
rlc->add_bearer(LCID, &cfg);
// Send dummy ConnectionSetup. MAC will send contention resolution ID automatically.
log_h->info("Sending ConnectionSetup\n");
sdu = pool_allocate;
sdu->msg[0] = 0xab;
sdu->N_bytes = 1;
rlc->write_sdu(0, sdu);
// Indicate RLC status to mac
mac->rlc_buffer_state(rnti, 0, 1, 0);
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT dedicated;
bzero(&dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT));
dedicated.pusch_cnfg_ded.beta_offset_ack_idx = 5;
dedicated.pusch_cnfg_ded.beta_offset_ri_idx = 12;
dedicated.pusch_cnfg_ded.beta_offset_cqi_idx = 15;
dedicated.pusch_cnfg_ded_present = true;
dedicated.sched_request_cnfg.dsr_trans_max = LIBLTE_RRC_DSR_TRANS_MAX_N4;
dedicated.sched_request_cnfg.sr_pucch_resource_idx = 0;
dedicated.sched_request_cnfg.sr_cnfg_idx = 35;
dedicated.sched_request_cnfg_present = true;
phy->set_config_dedicated(rnti, &dedicated);
usleep(500);
break;
default:
log_h->error("Received message for lcid=%d\n", lcid);
break;
}
}
void rl_failure(uint16_t rnti)
{
log_h->console("Disconnecting rnti=0x%x.\n", rnti);
mac->ue_rem(rnti);
rlc->reset();
}
private:
int tun_fd;
bool running;
srslte::log *log_h;
srslte::byte_buffer_pool *pool;
srslte::rlc *rlc;
srsenb::mac *mac;
srsenb::phy *phy;
uint16_t rnti;
bool read_enable;
int init_tuntap(char *ip_address) {
read_enable = true;
tun_fd = setup_if_addr(ip_address);
if (tun_fd<0) {
fprintf(stderr, "Error setting up IP %s\n", ip_address);
return -1;
}
printf("Created tun/tap interface at IP %s\n", ip_address);
return 0;
}
void run_thread() {
struct iphdr *ip_pkt;
uint32_t idx = 0;
int32_t N_bytes = 0;
srslte::byte_buffer_t *pdu = pool_allocate;
log_h->info("TUN/TAP reader thread running\n");
int first=1;
while(running) {
if (tun_fd > 0) {
pdu->msg[0] = 0x0;
N_bytes = read(tun_fd, &pdu->msg[idx], SRSLTE_MAX_BUFFER_SIZE_BYTES-SRSLTE_BUFFER_HEADER_OFFSET - idx);
}
if(N_bytes > 0)
{
if (read_enable && pdu->msg[0] != 0x60) {
pdu->N_bytes = idx + N_bytes;
ip_pkt = (struct iphdr*)pdu->msg;
log_h->debug_hex(pdu->msg, pdu->N_bytes,
"Read %d bytes from TUN/TAP\n",
N_bytes);
// Check if entire packet was received
if(ntohs(ip_pkt->tot_len) == pdu->N_bytes)
{
// Send PDU directly to RLC
pdu->set_timestamp();
rlc->write_sdu(LCID, pdu);
// Indicate RLC status to mac
mac->rlc_buffer_state(rnti, LCID, rlc->get_buffer_state(LCID), 0);
pdu = pool_allocate;
idx = 0;
} else{
idx += N_bytes;
}
}
}else{
log_h->error("Failed to read from TUN interface - gw receive thread exiting.\n");
break;
}
}
}
};
// Create classes
srslte::logger_file logger;
srslte::log_filter log_phy;
srslte::log_filter log_mac;
srslte::log_filter log_rlc;
srslte::log_filter log_tester;
srsenb::phy my_phy;
srsenb::mac my_mac;
srslte::rlc my_rlc;
srslte::radio my_radio;
// Local classes for testing
tester my_tester;
void generate_cell_configuration(srsenb::sched_interface::cell_cfg_t *mac_cfg, srsenb::phy_cfg_t *phy_cfg)
{
// Main cell configuration
srslte_cell_t cell;
cell.id = 0;
cell.cp = SRSLTE_CP_NORM;
cell.nof_ports = 1;
cell.nof_prb = 25;
cell.phich_length = SRSLTE_PHICH_NORM;
cell.phich_resources = SRSLTE_PHICH_R_1;
// Generate SIB1
LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT msg[2];
bzero(&msg[0], sizeof(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT));
bzero(&msg[1], sizeof(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT));
msg[0].N_sibs = 1;
msg[0].sibs[0].sib_type = LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1 = &msg[0].sibs[0].sib.sib1;
sib1->cell_id = 0x1234;
sib1->tracking_area_code = 0x1234;
sib1->freq_band_indicator = 2;
sib1->N_plmn_ids = 1;
sib1->plmn_id[0].id.mcc = 1;
sib1->plmn_id[0].id.mnc = 1;
sib1->plmn_id[0].resv_for_oper = LIBLTE_RRC_NOT_RESV_FOR_OPER;
sib1->cell_barred = LIBLTE_RRC_CELL_NOT_BARRED;
sib1->intra_freq_reselection = LIBLTE_RRC_INTRA_FREQ_RESELECTION_ALLOWED;
sib1->q_rx_lev_min = -140;
sib1->q_rx_lev_min_offset = 1;
sib1->p_max = 10;
sib1->p_max_present = true;
sib1->si_window_length = LIBLTE_RRC_SI_WINDOW_LENGTH_MS40;
sib1->N_sched_info = 1;
sib1->sched_info[0].si_periodicity = LIBLTE_RRC_SI_PERIODICITY_RF16;
sib1->sched_info[0].N_sib_mapping_info = 0;
sib1->system_info_value_tag = 8;
// Generate SIB2
msg[1].N_sibs = 2;
msg[1].sibs[0].sib_type = LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2;
msg[1].sibs[1].sib_type = LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2 = &msg[1].sibs[0].sib.sib2;
// RACH configuration
sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles = LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_N64;
sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.present = false;
sib2->rr_config_common_sib.rach_cnfg.preamble_init_rx_target_pwr = LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_DBM_N90;
sib2->rr_config_common_sib.rach_cnfg.pwr_ramping_step = LIBLTE_RRC_POWER_RAMPING_STEP_DB6;
sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max = LIBLTE_RRC_PREAMBLE_TRANS_MAX_N10;
sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size = LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_SF10;
sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer = LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_SF40;
sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx = 4;
// BCCH
sib2->rr_config_common_sib.bcch_cnfg.modification_period_coeff = LIBLTE_RRC_MODIFICATION_PERIOD_COEFF_N16;
// PCCH
sib2->rr_config_common_sib.pcch_cnfg.default_paging_cycle = LIBLTE_RRC_DEFAULT_PAGING_CYCLE_RF128;
sib2->rr_config_common_sib.pcch_cnfg.nB = LIBLTE_RRC_NB_ONE_THIRTY_SECOND_T;
// PRACH Configuration
sib2->rr_config_common_sib.prach_cnfg.root_sequence_index = 41;
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag = false;
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index = 4;
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset = 2;
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config = 11;
// PDSCH configuration
sib2->rr_config_common_sib.pdsch_cnfg.p_b = 0;
sib2->rr_config_common_sib.pdsch_cnfg.rs_power = -5;
// PUSCH configuration
sib2->rr_config_common_sib.pusch_cnfg.n_sb = 1;
sib2->rr_config_common_sib.pusch_cnfg.hopping_mode = LIBLTE_RRC_HOPPING_MODE_INTER_SUBFRAME;
sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset = 4;
sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam = false;
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift = 0;
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch = 0;
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled = false;
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.sequence_hopping_enabled = false;
// PUCCH configuration
sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift = LIBLTE_RRC_DELTA_PUCCH_SHIFT_DS2;
sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi = 2;
sib2->rr_config_common_sib.pucch_cnfg.n_cs_an = 0;
sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an = 12;
// SRS configuration
sib2->rr_config_common_sib.srs_ul_cnfg.present = false;
// UL power control
sib2->rr_config_common_sib.ul_pwr_ctrl.p0_nominal_pusch = -80;
sib2->rr_config_common_sib.ul_pwr_ctrl.alpha = LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_1;
sib2->rr_config_common_sib.ul_pwr_ctrl.p0_nominal_pucch = -80;
sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_1 = LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_0;
sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_1b = LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_5;
sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2 = LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_2;
sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2a = LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_2;
sib2->rr_config_common_sib.ul_pwr_ctrl.delta_flist_pucch.format_2b = LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_2;
sib2->rr_config_common_sib.ul_pwr_ctrl.delta_preamble_msg3 = 4;
sib2->rr_config_common_sib.ul_cp_length = LIBLTE_RRC_UL_CP_LENGTH_1;
sib2->ue_timers_and_constants.t300 = LIBLTE_RRC_T300_MS1000;
sib2->ue_timers_and_constants.t301 = LIBLTE_RRC_T301_MS1000;
sib2->ue_timers_and_constants.n310 = LIBLTE_RRC_N310_N10;
sib2->ue_timers_and_constants.t311 = LIBLTE_RRC_T311_MS1000;
sib2->ue_timers_and_constants.n311 = LIBLTE_RRC_N311_N1;
sib2->time_alignment_timer = LIBLTE_RRC_TIME_ALIGNMENT_TIMER_INFINITY;
sib2->additional_spectrum_emission = 1;
sib2->arfcn_value_eutra.present = false;
sib2->ul_bw.present = false;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = &msg[1].sibs[1].sib.sib3;
bzero(sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT));
sib3->q_hyst = LIBLTE_RRC_Q_HYST_DB_2;
sib3->s_non_intra_search = 6;
sib3->s_non_intra_search_present = true;
sib3->thresh_serving_low = 4;
sib3->cell_resel_prio = 6;
sib3->q_rx_lev_min = -122;
sib3->p_max = 23;
sib3->p_max_present = true;
sib3->s_intra_search = 10;
sib3->s_intra_search_present = true;
sib3->presence_ant_port_1 = true;
sib3->neigh_cell_cnfg = 1;
sib3->t_resel_eutra = 1;
// Genreate payload
LIBLTE_BIT_MSG_STRUCT bitbuffer[2];
for (int i=0;i<2;i++) {
liblte_rrc_pack_bcch_dlsch_msg(&msg[i], &bitbuffer[i]);
srslte_bit_pack_vector(bitbuffer[i].msg, sib_buffer[i].msg, bitbuffer[i].N_bits);
sib_buffer[i].N_bytes = (bitbuffer[i].N_bits-1)/8+1;
}
// Fill MAC scheduler configuration
bzero(mac_cfg, sizeof(srsenb::sched_interface::cell_cfg_t));
memcpy(&mac_cfg->cell, &cell, sizeof(srslte_cell_t));
mac_cfg->sibs[0].len = sib_buffer[0].N_bytes;
mac_cfg->sibs[0].period_rf = 8; // Fixed to 8 rf
mac_cfg->sibs[1].len = sib_buffer[1].N_bytes;
mac_cfg->sibs[1].period_rf = liblte_rrc_si_periodicity_num[sib1->sched_info[0].si_periodicity];
mac_cfg->si_window_ms = liblte_rrc_si_window_length_num[sib1->si_window_length];
mac_cfg->prach_rar_window = liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size];
// Copy PHY common configuration
bzero(phy_cfg, sizeof(srsenb::phy_cfg_t));
memcpy(&phy_cfg->cell, &cell, sizeof(srslte_cell_t));
memcpy(&phy_cfg->prach_cnfg, &sib2->rr_config_common_sib.prach_cnfg, sizeof(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT));
memcpy(&phy_cfg->pdsch_cnfg, &sib2->rr_config_common_sib.pdsch_cnfg, sizeof(LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT));
memcpy(&phy_cfg->pusch_cnfg, &sib2->rr_config_common_sib.pusch_cnfg, sizeof(LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT));
memcpy(&phy_cfg->pucch_cnfg, &sib2->rr_config_common_sib.pucch_cnfg, sizeof(LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT));
memcpy(&phy_cfg->srs_ul_cnfg, &sib2->rr_config_common_sib.srs_ul_cnfg, sizeof(LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT));
}
int main(int argc, char *argv[])
{
parse_args(&prog_args, argc, argv);
logger.init("/tmp/ip_test.log");
log_phy.init("PHY ", &logger, true);
log_mac.init("MAC ", &logger, true);
log_rlc.init("RLC ", &logger);
log_tester.init("TEST", &logger);
logger.log("\n\n");
if (srsapps_verbose == 1) {
log_phy.set_level(srslte::LOG_LEVEL_INFO);
log_phy.set_hex_limit(100);
log_mac.set_level(srslte::LOG_LEVEL_DEBUG);
log_mac.set_hex_limit(100);
log_rlc.set_level(srslte::LOG_LEVEL_DEBUG);
log_rlc.set_hex_limit(1000);
log_tester.set_level(srslte::LOG_LEVEL_DEBUG);
log_tester.set_hex_limit(100);
printf("Log level info\n");
}
if (srsapps_verbose == 2) {
log_phy.set_level(srslte::LOG_LEVEL_DEBUG);
log_phy.set_hex_limit(100);
log_mac.set_level(srslte::LOG_LEVEL_DEBUG);
log_mac.set_hex_limit(100);
log_rlc.set_level(srslte::LOG_LEVEL_DEBUG);
log_rlc.set_hex_limit(100);
log_tester.set_level(srslte::LOG_LEVEL_DEBUG);
log_tester.set_hex_limit(100);
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
printf("Log level debug\n");
}
// Init Radio and PHY
#ifdef USE_RADIO
my_radio.init();
#else
my_radio.init(NULL, (char*) "dummy");
#endif
my_radio.set_tx_freq(prog_args.tx_freq);
my_radio.set_tx_gain(prog_args.tx_gain);
my_radio.set_rx_freq(prog_args.rx_freq);
my_radio.set_rx_gain(prog_args.rx_gain);
//my_radio.set_tx_adv_neg(true);
if (prog_args.time_adv >= 0) {
printf("Setting TA=%d samples\n", prog_args.time_adv);
my_radio.set_tx_adv(prog_args.time_adv);
}
// Configuure cell
srsenb::phy_cfg_t phy_cfg;
srsenb::sched_interface::cell_cfg_t mac_cfg;
srsenb::mac_args_t mac_args;
srsenb::phy_args_t phy_args;
mac_args.link_failure_nof_err = 10;
phy_args.equalizer_mode = "mmse";
phy_args.estimator_fil_w = 0.2;
phy_args.max_prach_offset_us = 50;
phy_args.nof_phy_threads = 1;
phy_args.pusch_max_its = 5;
generate_cell_configuration(&mac_cfg, &phy_cfg);
my_phy.init(&phy_args, &phy_cfg, &my_radio, &my_mac, &log_phy);
my_mac.init(&mac_args, &mac_cfg.cell, &my_phy, &my_tester, &my_tester, &log_mac);
my_rlc.init(&my_tester, &my_tester, &my_tester, &log_rlc, &my_mac, 0 /* SRB0 */);
my_tester.init(&my_rlc, &my_mac, &my_phy, &log_tester, prog_args.ip_address);
if (prog_args.enable_gui) {
sleep(1);
my_phy.start_plot();
}
bool running = true;
while(running) {
printf("Main running\n");
sleep(1);
}
my_phy.stop();
my_mac.stop();
}
/******************* This is copied from srsue gw **********************/
int setup_if_addr(char *ip_addr)
{
char *dev = (char*) "tun_srsenb";
int sock = -1;
// Construct the TUN device
int tun_fd = open("/dev/net/tun", O_RDWR);
if(0 > tun_fd)
{
perror("open");
return SRSLTE_ERROR;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ);
if(0 > ioctl(tun_fd, TUNSETIFF, &ifr))
{
perror("ioctl1");
goto clean_exit;
}
// Bring up the interface
sock = socket(AF_INET, SOCK_DGRAM, 0);
if(0 > ioctl(sock, SIOCGIFFLAGS, &ifr))
{
perror("socket");
goto clean_exit;
}
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
if(0 > ioctl(sock, SIOCSIFFLAGS, &ifr))
{
perror("ioctl2");
goto clean_exit;
}
// Setup the IP address
sock = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = inet_addr(ip_addr);
if(0 > ioctl(sock, SIOCSIFADDR, &ifr))
{
perror("ioctl");
goto clean_exit;
}
ifr.ifr_netmask.sa_family = AF_INET;
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0");
if(0 > ioctl(sock, SIOCSIFNETMASK, &ifr))
{
perror("ioctl");
goto clean_exit;
}
shutdown(sock, SHUT_RDWR);
return(tun_fd);
clean_exit:
if (sock != -1) {
shutdown(sock, SHUT_RDWR);
}
if (tun_fd != -1) {
close(tun_fd);
}
return SRSLTE_ERROR;
}

@ -7,49 +7,77 @@
* *
*/ */
#include <assert.h>
#include "srsenb/hdr/upper/common_enb.h" #include "srsenb/hdr/upper/common_enb.h"
#include "srslte/asn1/liblte_rrc.h" #include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/bcd_helpers.h" #include "srslte/common/bcd_helpers.h"
#include <iostream>
void rrc_plmn_test() using namespace asn1::rrc;
#define TESTASSERT(cond) \
{ \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
}
int rrc_plmn_test()
{ {
LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_in, plmn_out; plmn_id_s plmn_in, plmn_out;
plmn_in.mcc = 0xF123; uint8_t ref[3] = {0x89, 0x19, 0x14};
plmn_in.mnc = 0xFF45; uint8_t byte_buf[4];
// 2-digit MNC test // 2-digit MNC test
uint8_t bit_buf[32]; asn1::bit_ref bref_out(&ref[0], sizeof(ref));
uint8_t *ie_ptr = bit_buf; asn1::bit_ref bref_out0(&ref[0], sizeof(ref));
liblte_rrc_pack_plmn_identity_ie(&plmn_in, &ie_ptr); plmn_out.unpack(bref_out);
uint8_t byte_buf[4];
liblte_pack(bit_buf, 22, byte_buf); TESTASSERT(plmn_out.mcc_present);
uint8_t ref[3] = {0x89, 0x19, 0x05}; uint16_t mcc, mnc;
for(int i=0;i<3;i++) { srslte::bytes_to_mcc(&plmn_out.mcc[0], &mcc);
assert(ref[i] == byte_buf[i]); srslte::bytes_to_mnc(&plmn_out.mnc[0], &mnc, plmn_out.mnc.size());
} TESTASSERT(mcc == 0xF123);
ie_ptr = bit_buf; TESTASSERT(mnc == 0xFF45);
liblte_rrc_unpack_plmn_identity_ie(&ie_ptr, &plmn_out);
assert(plmn_in.mcc == plmn_out.mcc); // Test MCC/MNC --> vector
assert(plmn_in.mnc == plmn_out.mnc); plmn_in.mcc_present = plmn_out.mcc_present;
TESTASSERT(srslte::mcc_to_bytes(mcc, &plmn_in.mcc[0]));
TESTASSERT(srslte::mnc_to_bytes(mnc, plmn_in.mnc));
TESTASSERT(plmn_in.mcc_present == plmn_out.mcc_present);
TESTASSERT(plmn_in.mcc == plmn_out.mcc);
TESTASSERT(plmn_in.mnc == plmn_out.mnc);
// Test plmn --> string
std::string mccmnc_str = srslte::plmn_id_to_string(plmn_in);
TESTASSERT(mccmnc_str == "12345");
asn1::bit_ref bref_in(&byte_buf[0], sizeof(byte_buf));
asn1::bit_ref bref_in0(&byte_buf[0], sizeof(byte_buf));
plmn_out.pack(bref_in);
TESTASSERT(bref_in.distance(&byte_buf[0]) == bref_out.distance(bref_out0));
TESTASSERT(memcmp(&ref[0], &byte_buf[0], sizeof(ref)) == 0);
// 3-digit MNC test // 3-digit MNC test
plmn_in.mnc = 0xF456; TESTASSERT(srslte::mnc_to_bytes(0xF456, plmn_in.mnc));
ie_ptr = bit_buf; bref_in = asn1::bit_ref(&byte_buf[0], sizeof(byte_buf));
liblte_rrc_pack_plmn_identity_ie(&plmn_in, &ie_ptr); plmn_in.pack(bref_in);
liblte_pack(bit_buf, 26, byte_buf); uint8_t ref2[4] = {0x89, 0x1D, 0x15, 0x80};
uint8_t ref2[4] = {0x89, 0x1D, 0x15, 0x02}; TESTASSERT(bref_in.distance(bref_in0) == (1 + 3 * 4 + 1 + 3 * 4));
for(int i=0;i<3;i++) { TESTASSERT(memcmp(&byte_buf[0], &ref2[0], sizeof(ref)) == 0);
assert(ref2[i] == byte_buf[i]);
} bref_out = asn1::bit_ref(&ref2[0], sizeof(ref2));
ie_ptr = bit_buf; plmn_out.unpack(bref_out);
liblte_rrc_unpack_plmn_identity_ie(&ie_ptr, &plmn_out); TESTASSERT(plmn_in.mcc_present == plmn_out.mcc_present);
assert(plmn_in.mcc == plmn_out.mcc); TESTASSERT(plmn_in.mcc == plmn_out.mcc);
assert(plmn_in.mnc == plmn_out.mnc); TESTASSERT(plmn_in.mnc == plmn_out.mnc);
return 0;
} }
void s1ap_plmn_test() int s1ap_plmn_test()
{ {
uint16_t mcc = 0xF123; uint16_t mcc = 0xF123;
uint16_t mnc = 0xFF45; uint16_t mnc = 0xFF45;
@ -57,22 +85,24 @@ void s1ap_plmn_test()
// 2-digit MNC test // 2-digit MNC test
srslte::s1ap_mccmnc_to_plmn(mcc, mnc, &plmn); srslte::s1ap_mccmnc_to_plmn(mcc, mnc, &plmn);
assert(plmn == 0x21F354); TESTASSERT(plmn == 0x21F354);
srslte::s1ap_plmn_to_mccmnc(plmn, &mcc, &mnc); srslte::s1ap_plmn_to_mccmnc(plmn, &mcc, &mnc);
assert(mcc == 0xF123); TESTASSERT(mcc == 0xF123);
assert(mnc == 0xFF45); TESTASSERT(mnc == 0xFF45);
// 3-digit MNC test // 3-digit MNC test
mnc = 0xF456; mnc = 0xF456;
srslte::s1ap_mccmnc_to_plmn(mcc, mnc, &plmn); srslte::s1ap_mccmnc_to_plmn(mcc, mnc, &plmn);
assert(plmn == 0x214365); TESTASSERT(plmn == 0x216354);
srslte::s1ap_plmn_to_mccmnc(plmn, &mcc, &mnc); srslte::s1ap_plmn_to_mccmnc(plmn, &mcc, &mnc);
assert(mcc == 0xF123); TESTASSERT(mcc == 0xF123);
assert(mnc == 0xF456); TESTASSERT(mnc == 0xF456);
return 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
rrc_plmn_test(); TESTASSERT(rrc_plmn_test() == 0);
s1ap_plmn_test(); TESTASSERT(s1ap_plmn_test() == 0);
return 0;
} }

@ -158,7 +158,7 @@ hss::read_db_file(std::string db_filename)
if(split.size() != column_size) if(split.size() != column_size)
{ {
m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n"); m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n");
m_hss_log->error("Columns: %lu, Expected %d.\n",split.size(),column_size); m_hss_log->error("Columns: %zd, Expected %d.\n", split.size(), column_size);
return false; return false;
} }
hss_ue_ctx_t *ue_ctx = new hss_ue_ctx_t; hss_ue_ctx_t *ue_ctx = new hss_ue_ctx_t;

@ -27,21 +27,22 @@
#ifndef SRSUE_MAC_H #ifndef SRSUE_MAC_H
#define SRSUE_MAC_H #define SRSUE_MAC_H
#include "srslte/common/log.h" #include "demux.h"
#include "dl_harq.h" #include "dl_harq.h"
#include "ul_harq.h"
#include "srslte/common/timers.h"
#include "mac_metrics.h" #include "mac_metrics.h"
#include "proc_ra.h" #include "mux.h"
#include "proc_sr.h"
#include "proc_bsr.h" #include "proc_bsr.h"
#include "proc_phr.h" #include "proc_phr.h"
#include "mux.h" #include "proc_ra.h"
#include "demux.h" #include "proc_sr.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/log.h"
#include "srslte/common/mac_pcap.h" #include "srslte/common/mac_pcap.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srslte/common/tti_sync_cv.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include "srslte/common/timers.h"
#include "srslte/common/tti_sync_cv.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "ul_harq.h"
namespace srsue { namespace srsue {
@ -89,9 +90,9 @@ public:
/******** set/get MAC configuration ****************/ /******** set/get MAC configuration ****************/
void set_config(mac_cfg_t *mac_cfg); void set_config(mac_cfg_t *mac_cfg);
void get_config(mac_cfg_t *mac_cfg); void get_config(mac_cfg_t *mac_cfg);
void set_config_main(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *main_cfg); void set_config_main(asn1::rrc::mac_main_cfg_s* main_cfg);
void set_config_rach(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cfg, uint32_t prach_config_index); void set_config_rach(asn1::rrc::rach_cfg_common_s* rach_cfg, uint32_t prach_config_index);
void set_config_sr(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT *sr_cfg); void set_config_sr(asn1::rrc::sched_request_cfg_c* sr_cfg);
void set_contention_id(uint64_t uecri); void set_contention_id(uint64_t uecri);
void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask); void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask);

@ -133,12 +133,12 @@ private:
uint32_t nof_preambles; uint32_t nof_preambles;
uint32_t nof_groupA_preambles; uint32_t nof_groupA_preambles;
uint32_t nof_groupB_preambles; uint32_t nof_groupB_preambles;
uint32_t messagePowerOffsetGroupB; int32_t messagePowerOffsetGroupB;
uint32_t messageSizeGroupA; uint32_t messageSizeGroupA;
uint32_t responseWindowSize; uint32_t responseWindowSize;
uint32_t powerRampingStep; uint32_t powerRampingStep;
uint32_t preambleTransMax; uint32_t preambleTransMax;
uint32_t iniReceivedTargetPower; int32_t iniReceivedTargetPower;
int delta_preamble_db; int delta_preamble_db;
uint32_t contentionResolutionTimer; uint32_t contentionResolutionTimer;
uint32_t maskIndex; uint32_t maskIndex;

@ -124,13 +124,13 @@ public:
/* Get/Set PHY parameters interface from RRC */ /* Get/Set PHY parameters interface from RRC */
void get_config(phy_cfg_t *phy_cfg); void get_config(phy_cfg_t *phy_cfg);
void set_config(phy_cfg_t *phy_cfg); void set_config(phy_cfg_t *phy_cfg);
void set_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated); void set_config_dedicated(asn1::rrc::phys_cfg_ded_s* dedicated);
void set_config_common(phy_cfg_common_t *common); void set_config_common(phy_cfg_common_t *common);
void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd); void set_config_tdd(asn1::rrc::tdd_cfg_s* tdd);
void set_config_64qam_en(bool enable); void set_config_64qam_en(bool enable);
void set_config_mbsfn_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2); void set_config_mbsfn_sib2(asn1::rrc::sib_type2_s* sib2);
void set_config_mbsfn_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13); void set_config_mbsfn_sib13(asn1::rrc::sib_type13_r9_s* sib13);
void set_config_mbsfn_mcch(LIBLTE_RRC_MCCH_MSG_STRUCT *mcch); void set_config_mbsfn_mcch(asn1::rrc::mcch_msg_s* mcch);
/*Set MAC->PHY MCH period stopping point*/ /*Set MAC->PHY MCH period stopping point*/
void set_mch_period_stop(uint32_t stop); void set_mch_period_stop(uint32_t stop);

@ -52,7 +52,7 @@ namespace srsue {
signal_buffer = NULL; signal_buffer = NULL;
} }
~prach(); ~prach();
void init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config, uint32_t max_prb, phy_args_t *args, srslte::log *log_h); void init(asn1::rrc::prach_cfg_sib_s* config, uint32_t max_prb, phy_args_t* args, srslte::log* log_h);
bool set_cell(srslte_cell_t cell); bool set_cell(srslte_cell_t cell);
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1); bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1);
bool is_ready_to_send(uint32_t current_tti); bool is_ready_to_send(uint32_t current_tti);
@ -64,8 +64,8 @@ namespace srsue {
const static int MAX_LEN_SF = 3; const static int MAX_LEN_SF = 3;
LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config; asn1::rrc::prach_cfg_sib_s* config;
phy_args_t *args; phy_args_t* args;
srslte::log *log_h; srslte::log *log_h;
int preamble_idx; int preamble_idx;

@ -81,9 +81,9 @@ private:
bool running; bool running;
bool run_enable; bool run_enable;
int32 tun_fd; int32_t tun_fd;
struct ifreq ifr; struct ifreq ifr;
int32 sock; int32_t sock;
bool if_up; bool if_up;
uint32_t current_ip_addr; uint32_t current_ip_addr;

@ -82,7 +82,7 @@ public:
emm_state_t get_state(); emm_state_t get_state();
// RRC interface // RRC interface
void paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy); void paging(asn1::rrc::s_tmsi_s* ue_identiy);
void set_barring(barring_t barring); void set_barring(barring_t barring);
void write_pdu(uint32_t lcid, byte_buffer_t *pdu); void write_pdu(uint32_t lcid, byte_buffer_t *pdu);
uint32_t get_k_enb_count(); uint32_t get_k_enb_count();
@ -112,10 +112,10 @@ private:
nas_interface_rrc::barring_t current_barring; nas_interface_rrc::barring_t current_barring;
bool plmn_is_selected; bool plmn_is_selected;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT current_plmn; asn1::rrc::plmn_id_s current_plmn;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT home_plmn; asn1::rrc::plmn_id_s home_plmn;
std::vector<LIBLTE_RRC_PLMN_IDENTITY_STRUCT > known_plmns; std::vector<asn1::rrc::plmn_id_s> known_plmns;
LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info;

@ -74,7 +74,7 @@ public:
bool get_imsi_vec(uint8_t* imsi_, uint32_t n); bool get_imsi_vec(uint8_t* imsi_, uint32_t n);
bool get_imei_vec(uint8_t* imei_, uint32_t n); bool get_imei_vec(uint8_t* imei_, uint32_t n);
bool get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id); bool get_home_plmn_id(asn1::rrc::plmn_id_s* home_plmn_id);
auth_result_t generate_authentication_response(uint8_t *rand, auth_result_t generate_authentication_response(uint8_t *rand,
uint8_t *autn_enb, uint8_t *autn_enb,

@ -30,22 +30,24 @@
#include "pthread.h" #include "pthread.h"
#include "rrc_common.h" #include "rrc_common.h"
#include "srslte/common/bcd_helpers.h"
#include "srslte/common/block_queue.h"
#include "srslte/common/buffer_pool.h" #include "srslte/common/buffer_pool.h"
#include "srslte/common/log.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/log.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include "srslte/common/block_queue.h" #include "srslte/interfaces/ue_interfaces.h"
#include <math.h> #include <math.h>
#include <map> #include <map>
#include <queue> #include <queue>
#define SRSLTE_RRC_N_BANDS 43
typedef struct { typedef struct {
uint32_t ue_category; uint32_t ue_category;
uint32_t feature_group; uint32_t feature_group;
uint8_t supported_bands[LIBLTE_RRC_BAND_N_ITEMS]; uint8_t supported_bands[SRSLTE_RRC_N_BANDS];
uint32_t nof_supported_bands; uint32_t nof_supported_bands;
}rrc_args_t; }rrc_args_t;
@ -69,10 +71,12 @@ class cell_t
bool greater(cell_t *x) { bool greater(cell_t *x) {
return rsrp > x->rsrp || isnan(rsrp); return rsrp > x->rsrp || isnan(rsrp);
} }
bool plmn_equals(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { bool plmn_equals(asn1::rrc::plmn_id_s plmn_id)
{
if (has_valid_sib1) { if (has_valid_sib1) {
for (uint32_t i = 0; i < sib1.N_plmn_ids; i++) { for (uint32_t i = 0; i < sib1.cell_access_related_info.plmn_id_list.size(); i++) {
if (plmn_id.mcc == sib1.plmn_id[i].id.mcc && plmn_id.mnc == sib1.plmn_id[i].id.mnc) { if (plmn_id.mcc == sib1.cell_access_related_info.plmn_id_list[i].plmn_id.mcc &&
plmn_id.mnc == sib1.cell_access_related_info.plmn_id_list[i].plmn_id.mnc) {
return true; return true;
} }
} }
@ -82,26 +86,27 @@ class cell_t
uint32_t nof_plmns() { uint32_t nof_plmns() {
if (has_valid_sib1) { if (has_valid_sib1) {
return sib1.N_plmn_ids; return sib1.cell_access_related_info.plmn_id_list.size();
} else { } else {
return 0; return 0;
} }
} }
LIBLTE_RRC_PLMN_IDENTITY_STRUCT get_plmn(uint32_t idx) { asn1::rrc::plmn_id_s get_plmn(uint32_t idx)
if (idx < sib1.N_plmn_ids && has_valid_sib1) { {
return sib1.plmn_id[idx].id; if (idx < sib1.cell_access_related_info.plmn_id_list.size() && has_valid_sib1) {
return sib1.cell_access_related_info.plmn_id_list[idx].plmn_id;
} else { } else {
LIBLTE_RRC_PLMN_IDENTITY_STRUCT null; asn1::rrc::plmn_id_s null;
null.mnc = 0; bzero(&null.mcc[0], sizeof(null.mcc));
null.mcc = 0; bzero(&null.mnc[0], sizeof(null.mnc));
return null; return null;
} }
} }
uint16_t get_tac() { uint16_t get_tac() {
if (has_valid_sib1) { if (has_valid_sib1) {
return sib1.tracking_area_code; return (uint16_t)sib1.cell_access_related_info.tac.to_number();
} else { } else {
return 0; return 0;
} }
@ -147,20 +152,24 @@ class cell_t
return rsrp; return rsrp;
} }
void set_sib1(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1) { void set_sib1(asn1::rrc::sib_type1_s* sib1_)
memcpy(&this->sib1, sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); {
sib1 = *sib1_;
has_valid_sib1 = true; has_valid_sib1 = true;
} }
void set_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) { void set_sib2(asn1::rrc::sib_type2_s* sib2_)
memcpy(&this->sib2, sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); {
sib2 = *sib2_;
has_valid_sib2 = true; has_valid_sib2 = true;
} }
void set_sib3(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3) { void set_sib3(asn1::rrc::sib_type3_s* sib3_)
memcpy(&this->sib3, sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT)); {
sib3 = *sib3_;
has_valid_sib3 = true; has_valid_sib3 = true;
} }
void set_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) { void set_sib13(asn1::rrc::sib_type13_r9_s* sib13_)
memcpy(&this->sib13, sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT)); {
sib13 = *sib13_;
has_valid_sib13 = true; has_valid_sib13 = true;
} }
@ -172,22 +181,12 @@ class cell_t
return t[0].tv_sec; return t[0].tv_sec;
} }
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1ptr() { asn1::rrc::sib_type1_s* sib1ptr() { return &sib1; }
return &sib1; asn1::rrc::sib_type2_s* sib2ptr() { return &sib2; }
} asn1::rrc::sib_type3_s* sib3ptr() { return &sib3; }
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2ptr() { asn1::rrc::sib_type13_r9_s* sib13ptr() { return &sib13; }
return &sib2;
}
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3ptr() {
return &sib3;
}
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13ptr() {
return &sib13;
}
uint32_t get_cell_id() { uint32_t get_cell_id() { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); }
return sib1.cell_id;
}
bool has_sib1() { bool has_sib1() {
return has_valid_sib1; return has_valid_sib1;
@ -224,18 +223,25 @@ class cell_t
} }
uint16_t get_mcc() { uint16_t get_mcc() {
uint16_t mcc;
if (has_valid_sib1) { if (has_valid_sib1) {
if (sib1.N_plmn_ids > 0) { if (sib1.cell_access_related_info.plmn_id_list.size() > 0) {
return sib1.plmn_id[0].id.mcc; if (srslte::bytes_to_mcc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mcc[0], &mcc)) {
return mcc;
}
} }
} }
return 0; return 0;
} }
uint16_t get_mnc() { uint16_t get_mnc() {
uint16_t mnc;
if (has_valid_sib1) { if (has_valid_sib1) {
if (sib1.N_plmn_ids > 0) { if (sib1.cell_access_related_info.plmn_id_list.size() > 0) {
return sib1.plmn_id[0].id.mnc; if (srslte::bytes_to_mnc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc[0], &mnc,
sib1.cell_access_related_info.plmn_id_list[0].plmn_id.mnc.size())) {
return mnc;
}
} }
} }
return 0; return 0;
@ -244,11 +250,11 @@ class cell_t
phy_interface_rrc::phy_cell_t phy_cell; phy_interface_rrc::phy_cell_t phy_cell;
bool in_sync; bool in_sync;
bool has_mcch; bool has_mcch;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1; asn1::rrc::sib_type1_s sib1;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; asn1::rrc::sib_type2_s sib2;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3; asn1::rrc::sib_type3_s sib3;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13; asn1::rrc::sib_type13_r9_s sib13;
LIBLTE_RRC_MCCH_MSG_STRUCT mcch; asn1::rrc::mcch_msg_s mcch;
private: private:
float rsrp; float rsrp;
@ -261,14 +267,13 @@ private:
bool has_valid_sib13; bool has_valid_sib13;
}; };
class rrc class rrc : public rrc_interface_nas,
:public rrc_interface_nas public rrc_interface_phy,
,public rrc_interface_phy public rrc_interface_mac,
,public rrc_interface_mac public rrc_interface_pdcp,
,public rrc_interface_pdcp public rrc_interface_rlc,
,public rrc_interface_rlc public srslte::timer_callback,
,public srslte::timer_callback public thread
,public thread
{ {
public: public:
rrc(); rrc();
@ -291,7 +296,11 @@ public:
// Timeout callback interface // Timeout callback interface
void timer_expired(uint32_t timeout_id); void timer_expired(uint32_t timeout_id);
void liblte_rrc_log(char *str); void srslte_rrc_log(const char* str);
typedef enum { Rx = 0, Tx } direction_t;
template <class T>
void log_rrc_message(const std::string source, const direction_t dir, const byte_buffer_t* pdu, const T& msg);
void print_mbms(); void print_mbms();
bool mbms_service_start(uint32_t serv, uint32_t port); bool mbms_service_start(uint32_t serv, uint32_t port);
@ -302,10 +311,9 @@ public:
uint16_t get_mcc(); uint16_t get_mcc();
uint16_t get_mnc(); uint16_t get_mnc();
int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]); int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]);
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id); void plmn_select(asn1::rrc::plmn_id_s plmn_id);
bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, bool connection_request(asn1::rrc::establishment_cause_e cause, srslte::byte_buffer_t* dedicated_info_nas);
srslte::byte_buffer_t *dedicatedInfoNAS); void set_ue_idenity(asn1::rrc::s_tmsi_s s_tmsi);
void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi);
// PHY interface // PHY interface
void in_sync(); void in_sync();
@ -357,24 +365,23 @@ private:
usim_interface_rrc *usim; usim_interface_rrc *usim;
gw_interface_rrc *gw; gw_interface_rrc *gw;
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; asn1::rrc::ul_dcch_msg_s ul_dcch_msg;
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; asn1::rrc::ul_ccch_msg_s ul_ccch_msg;
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg; asn1::rrc::dl_ccch_msg_s dl_ccch_msg;
LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg; asn1::rrc::dl_dcch_msg_s dl_dcch_msg;
byte_buffer_t *dedicatedInfoNAS; byte_buffer_t* dedicated_info_nas;
byte_buffer_t* byte_align_and_pack();
void send_ul_ccch_msg(); void send_ul_ccch_msg();
void send_ul_dcch_msg(uint32_t lcid); void send_ul_dcch_msg(uint32_t lcid);
srslte::bit_buffer_t bit_buf; srslte::bit_buffer_t bit_buf;
pthread_mutex_t mutex; pthread_mutex_t mutex;
rrc_state_t state; rrc_state_t state, last_state;
uint8_t transaction_id; uint8_t transaction_id;
LIBLTE_RRC_S_TMSI_STRUCT ueIdentity; asn1::rrc::s_tmsi_s ue_identity;
bool ueIdentity_configured; bool ue_identity_configured;
bool drb_up; bool drb_up;
@ -387,7 +394,7 @@ private:
phy_interface_rrc::phy_cfg_t previous_phy_cfg; phy_interface_rrc::phy_cfg_t previous_phy_cfg;
mac_interface_rrc::mac_cfg_t previous_mac_cfg; mac_interface_rrc::mac_cfg_t previous_mac_cfg;
bool pending_mob_reconf; bool pending_mob_reconf;
LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT mob_reconf; asn1::rrc::rrc_conn_recfg_s mob_reconf;
uint8_t k_rrc_enc[32]; uint8_t k_rrc_enc[32];
uint8_t k_rrc_int[32]; uint8_t k_rrc_int[32];
@ -397,8 +404,8 @@ private:
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo;
std::map<uint32_t, LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT> srbs; std::map<uint32_t, asn1::rrc::srb_to_add_mod_s> srbs;
std::map<uint32_t, LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT> drbs; std::map<uint32_t, asn1::rrc::drb_to_add_mod_s> drbs;
// RRC constants and timers // RRC constants and timers
srslte::mac_interface_timers *mac_timers; srslte::mac_interface_timers *mac_timers;
@ -461,12 +468,15 @@ private:
bool go_idle; bool go_idle;
bool go_rlf; bool go_rlf;
uint32_t rlc_flush_counter;
uint32_t rlc_flush_timeout;
// Measurements sub-class // Measurements sub-class
class rrc_meas { class rrc_meas {
public: public:
void init(rrc *parent); void init(rrc *parent);
void reset(); void reset();
bool parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_config); bool parse_meas_config(asn1::rrc::meas_cfg_s* meas_config);
void new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti); void new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti);
void run_tti(uint32_t tti); void run_tti(uint32_t tti);
bool timer_expired(uint32_t timer_id); bool timer_expired(uint32_t timer_id);
@ -496,7 +506,7 @@ private:
uint32_t amount; uint32_t amount;
quantity_t trigger_quantity; quantity_t trigger_quantity;
quantity_t report_quantity; quantity_t report_quantity;
LIBLTE_RRC_EVENT_EUTRA_STRUCT event; asn1::rrc::eutra_event_s event;
enum {EVENT, PERIODIC} trigger_type; enum {EVENT, PERIODIC} trigger_type;
} report_cfg_t; } report_cfg_t;
@ -547,9 +557,8 @@ private:
bool find_earfcn_cell(uint32_t earfcn, uint32_t pci, meas_obj_t **object, int *cell_idx); bool find_earfcn_cell(uint32_t earfcn, uint32_t pci, meas_obj_t **object, int *cell_idx);
float range_to_value(quantity_t quant, uint8_t range); float range_to_value(quantity_t quant, uint8_t range);
uint8_t value_to_range(quantity_t quant, float value); uint8_t value_to_range(quantity_t quant, float value);
bool process_event(LIBLTE_RRC_EVENT_EUTRA_STRUCT *event, uint32_t tti, bool process_event(asn1::rrc::eutra_event_s* event, uint32_t tti, bool enter_condition, bool exit_condition,
bool enter_condition, bool exit_condition, meas_t* m, meas_value_t* cell);
meas_t *m, meas_value_t *cell);
void generate_report(uint32_t meas_id); void generate_report(uint32_t meas_id);
}; };
@ -597,7 +606,7 @@ private:
phy_interface_rrc::cell_search_ret_t cell_search(); phy_interface_rrc::cell_search_ret_t cell_search();
LIBLTE_RRC_PLMN_IDENTITY_STRUCT selected_plmn_id; asn1::rrc::plmn_id_s selected_plmn_id;
bool plmn_is_selected; bool plmn_is_selected;
bool security_is_activated; bool security_is_activated;
@ -606,25 +615,25 @@ private:
void max_retx_attempted(); void max_retx_attempted();
// Senders // Senders
void send_con_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause); void send_con_request(asn1::rrc::establishment_cause_e cause);
void send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause); void send_con_restablish_request(asn1::rrc::reest_cause_e cause);
void send_con_restablish_complete(); void send_con_restablish_complete();
void send_con_setup_complete(byte_buffer_t *nas_msg); void send_con_setup_complete(byte_buffer_t* nas_msg);
void send_ul_info_transfer(byte_buffer_t *nas_msg); void send_ul_info_transfer(byte_buffer_t* nas_msg);
void send_security_mode_complete(); void send_security_mode_complete();
void send_rrc_con_reconfig_complete(); void send_rrc_con_reconfig_complete();
void send_rrc_ue_cap_info(); void send_rrc_ue_cap_info();
// Parsers // Parsers
void process_pdu(uint32_t lcid, byte_buffer_t *pdu); void process_pdu(uint32_t lcid, byte_buffer_t* pdu);
void parse_dl_ccch(byte_buffer_t *pdu); void parse_dl_ccch(byte_buffer_t* pdu);
void parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu); void parse_dl_dcch(uint32_t lcid, byte_buffer_t* pdu);
void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t *pdu); void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t* pdu);
// Helpers // Helpers
bool con_reconfig(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig); bool con_reconfig(asn1::rrc::rrc_conn_recfg_s* reconfig);
void con_reconfig_failed(); void con_reconfig_failed();
bool con_reconfig_ho(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig); bool con_reconfig_ho(asn1::rrc::rrc_conn_recfg_s* reconfig);
bool ho_prepare(); bool ho_prepare();
void ho_failed(); void ho_failed();
void rrc_connection_release(); void rrc_connection_release();
@ -632,25 +641,25 @@ private:
void leave_connected(); void leave_connected();
void stop_timers(); void stop_timers();
void apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config); void apply_rr_config_common_dl(asn1::rrc::rr_cfg_common_s* config);
void apply_rr_config_common_ul(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config); void apply_rr_config_common_ul(asn1::rrc::rr_cfg_common_s* config);
void handle_sib1(); void handle_sib1();
void handle_sib2(); void handle_sib2();
void handle_sib3(); void handle_sib3();
void handle_sib13(); void handle_sib13();
void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2); void apply_sib2_configs(asn1::rrc::sib_type2_s* sib2);
void apply_sib13_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13); void apply_sib13_configs(asn1::rrc::sib_type13_r9_s* sib13);
void handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup); void handle_con_setup(asn1::rrc::rrc_conn_setup_s* setup);
void handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup); void handle_con_reest(asn1::rrc::rrc_conn_reest_s* setup);
void handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig); void handle_rrc_con_reconfig(uint32_t lcid, asn1::rrc::rrc_conn_recfg_s* reconfig);
void add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg); void add_srb(asn1::rrc::srb_to_add_mod_s* srb_cnfg);
void add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg); void add_drb(asn1::rrc::drb_to_add_mod_s* drb_cnfg);
void release_drb(uint32_t drb_id); void release_drb(uint32_t drb_id);
void add_mrb(uint32_t lcid, uint32_t port); void add_mrb(uint32_t lcid, uint32_t port);
bool apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg); bool apply_rr_config_dedicated(asn1::rrc::rr_cfg_ded_s* cnfg);
void apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults); void apply_phy_config_dedicated(asn1::rrc::phys_cfg_ded_s* phy_cnfg, bool apply_defaults);
void apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cfg, bool apply_defaults); void apply_mac_config_dedicated(asn1::rrc::mac_main_cfg_s* mac_cfg, bool apply_defaults);
// Helpers for setting default values // Helpers for setting default values
void set_phy_default_pucch_srs(); void set_phy_default_pucch_srs();

@ -50,7 +50,7 @@ public:
bool get_imsi_vec(uint8_t* imsi_, uint32_t n); bool get_imsi_vec(uint8_t* imsi_, uint32_t n);
bool get_imei_vec(uint8_t* imei_, uint32_t n); bool get_imei_vec(uint8_t* imei_, uint32_t n);
bool get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id); bool get_home_plmn_id(asn1::rrc::plmn_id_s* home_plmn_id);
auth_result_t generate_authentication_response(uint8_t *rand, auth_result_t generate_authentication_response(uint8_t *rand,
uint8_t *autn_enb, uint8_t *autn_enb,

@ -71,7 +71,7 @@ public:
virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0; virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0;
virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0; virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0;
virtual bool get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 0; virtual bool get_home_plmn_id(asn1::rrc::plmn_id_s* home_plmn_id) = 0;
virtual auth_result_t generate_authentication_response(uint8_t *rand, virtual auth_result_t generate_authentication_response(uint8_t *rand,
uint8_t *autn_enb, uint8_t *autn_enb,

@ -39,6 +39,7 @@ target_link_libraries(srsue srsue_mac
srslte_phy srslte_phy
srslte_upper srslte_upper
srslte_radio srslte_radio
rrc_asn1
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}) ${Boost_LIBRARIES})

@ -38,6 +38,7 @@
#include "srsue/hdr/mac/mac.h" #include "srsue/hdr/mac/mac.h"
#include "srslte/common/pcap.h" #include "srslte/common/pcap.h"
using namespace asn1::rrc;
namespace srsue { namespace srsue {
@ -279,7 +280,7 @@ void mac::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::
ra_procedure.new_grant_dl(grant, action); ra_procedure.new_grant_dl(grant, action);
} else if (grant.rnti_type == SRSLTE_RNTI_PCH) { } else if (grant.rnti_type == SRSLTE_RNTI_PCH) {
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t)); action->phy_grant = grant.phy_grant;
action->generate_ack = false; action->generate_ack = false;
action->decode_enabled[0] = true; action->decode_enabled[0] = true;
action->decode_enabled[1] = false; action->decode_enabled[1] = false;
@ -340,7 +341,7 @@ void mac::new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, bool ack, mac_i
void mac::new_mch_dl(srslte_ra_dl_grant_t phy_grant, tb_action_dl_t *action) void mac::new_mch_dl(srslte_ra_dl_grant_t phy_grant, tb_action_dl_t *action)
{ {
memcpy(&action->phy_grant, &phy_grant, sizeof(srslte_phy_grant_t)); action->phy_grant.dl = phy_grant;
action->generate_ack = false; action->generate_ack = false;
action->decode_enabled[0] = true; action->decode_enabled[0] = true;
srslte_softbuffer_rx_reset_cb(&mch_softbuffer, 1); srslte_softbuffer_rx_reset_cb(&mch_softbuffer, 1);
@ -372,10 +373,8 @@ void mac::setup_timers()
timer_alignment); timer_alignment);
} }
int value = int value = config.main.time_align_timer_ded.to_number();
liblte_rrc_time_alignment_timer_num[config.main.time_alignment_timer]; log_h->info("Set MAC Time Alignment Timer (0x%x) to %d \n", timer_alignment, value);
log_h->info("Set MAC Time Alignment Timer (0x%x) to: %d value: %d \n",
timer_alignment, config.main.time_alignment_timer, value);
if (value > 0) { if (value > 0) {
timers.get(timer_alignment)->set(this, value); timers.get(timer_alignment)->set(this, value);
} }
@ -403,7 +402,7 @@ void mac::timer_alignment_expire() {
void mac::get_rntis(ue_rnti_t* rntis) void mac::get_rntis(ue_rnti_t* rntis)
{ {
memcpy(rntis, &uernti, sizeof(ue_rnti_t)); *rntis = uernti;
} }
void mac::set_ho_rnti(uint16_t crnti, uint16_t target_pci) { void mac::set_ho_rnti(uint16_t crnti, uint16_t target_pci) {
@ -432,7 +431,7 @@ void mac::start_cont_ho()
void mac::get_config(mac_cfg_t* mac_cfg) void mac::get_config(mac_cfg_t* mac_cfg)
{ {
memcpy(mac_cfg, &config, sizeof(mac_cfg_t)); *mac_cfg = config;
} }
void mac::set_mbsfn_config(uint32_t nof_mbsfn_services) void mac::set_mbsfn_config(uint32_t nof_mbsfn_services)
@ -444,25 +443,25 @@ void mac::set_mbsfn_config(uint32_t nof_mbsfn_services)
void mac::set_config(mac_cfg_t* mac_cfg) void mac::set_config(mac_cfg_t* mac_cfg)
{ {
memcpy(&config, mac_cfg, sizeof(mac_cfg_t)); config = *mac_cfg;
setup_timers(); setup_timers();
} }
void mac::set_config_main(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT* main_cfg) void mac::set_config_main(mac_main_cfg_s* main_cfg)
{ {
memcpy(&config.main, main_cfg, sizeof(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT)); config.main = *main_cfg;
setup_timers(); setup_timers();
} }
void mac::set_config_rach(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT* rach_cfg, uint32_t prach_config_index) void mac::set_config_rach(rach_cfg_common_s* rach_cfg, uint32_t prach_config_index)
{ {
memcpy(&config.rach, rach_cfg, sizeof(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT)); config.rach = *rach_cfg;
config.prach_config_index = prach_config_index; config.prach_config_index = prach_config_index;
} }
void mac::set_config_sr(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT* sr_cfg) void mac::set_config_sr(sched_request_cfg_c* sr_cfg)
{ {
memcpy(&config.sr, sr_cfg, sizeof(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT)); config.sr = *sr_cfg;
} }
void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD)
@ -566,12 +565,6 @@ void mac::pdu_process::run_thread()
} }
} }
} }

@ -89,7 +89,7 @@ void bsr_proc::timer_expired(uint32_t timer_id) {
} }
} else if (timer_id == timer_retx_id) { } else if (timer_id == timer_retx_id) {
// Enable reTx of SR only if periodic timer is not infinity // Enable reTx of SR only if periodic timer is not infinity
int periodic = liblte_rrc_periodic_bsr_timer_num[mac_cfg->main.ulsch_cnfg.periodic_bsr_timer]; int periodic = mac_cfg->main.ul_sch_cfg.periodic_bsr_timer.to_number();
if (periodic >= 0) { if (periodic >= 0) {
triggered_bsr_type = REGULAR; triggered_bsr_type = REGULAR;
Debug("BSR: Triggering BSR reTX\n"); Debug("BSR: Triggering BSR reTX\n");
@ -226,14 +226,14 @@ void bsr_proc::step(uint32_t tti)
return; return;
} }
int periodic = liblte_rrc_periodic_bsr_timer_num[mac_cfg->main.ulsch_cnfg.periodic_bsr_timer]; int periodic = mac_cfg->main.ul_sch_cfg.periodic_bsr_timer.to_number();
if (periodic > 0 && (uint32_t)periodic != timers_db->get(timer_periodic_id)->get_timeout()) if (periodic > 0 && (uint32_t)periodic != timers_db->get(timer_periodic_id)->get_timeout())
{ {
timers_db->get(timer_periodic_id)->set(this, periodic); timers_db->get(timer_periodic_id)->set(this, periodic);
timers_db->get(timer_periodic_id)->run(); timers_db->get(timer_periodic_id)->run();
Info("BSR: Configured timer periodic %d ms\n", periodic); Info("BSR: Configured timer periodic %d ms\n", periodic);
} }
int retx = liblte_rrc_retransmission_bsr_timer_num[mac_cfg->main.ulsch_cnfg.retx_bsr_timer]; int retx = mac_cfg->main.ul_sch_cfg.retx_bsr_timer.to_number();
if (retx > 0 && (uint32_t)retx != timers_db->get(timer_retx_id)->get_timeout()) if (retx > 0 && (uint32_t)retx != timers_db->get(timer_retx_id)->get_timeout())
{ {
timers_db->get(timer_retx_id)->set(this, retx); timers_db->get(timer_retx_id)->set(this, retx);

@ -58,6 +58,8 @@ void phr_proc::init(phy_interface_mac* phy_h_, srslte::log* log_h_, mac_interfac
void phr_proc::reset() void phr_proc::reset()
{ {
timers_db->get(timer_periodic_id)->stop();
timers_db->get(timer_prohibit_id)->stop();
phr_is_triggered = false; phr_is_triggered = false;
timer_periodic_value = -2; timer_periodic_value = -2;
timer_prohibit_value = -2; timer_prohibit_value = -2;
@ -65,8 +67,12 @@ void phr_proc::reset()
} }
bool phr_proc::pathloss_changed() { bool phr_proc::pathloss_changed() {
if (not mac_cfg->main.phr_cfg_present or mac_cfg->main.phr_cfg.type() == asn1::rrc::setup_e::release) {
log_h->error("Pathloss has changed but phr_cfg is not present.\n");
return false;
}
int min_change = liblte_rrc_dl_pathloss_change_num[mac_cfg->main.phr_cnfg.dl_pathloss_change]; int min_change = mac_cfg->main.phr_cfg.setup().dl_pathloss_change.to_number();
int cur_pathloss_db = (int) phy_h->get_pathloss_db(); int cur_pathloss_db = (int) phy_h->get_pathloss_db();
if (abs(cur_pathloss_db - last_pathloss_db) > min_change && min_change > 0) { if (abs(cur_pathloss_db - last_pathloss_db) > min_change && min_change > 0) {
@ -81,15 +87,14 @@ void phr_proc::start_timer() {
timers_db->get(timer_periodic_id)->run(); timers_db->get(timer_periodic_id)->run();
} }
/* Trigger PHR when timers exire */ /* Trigger PHR when timers exires */
void phr_proc::timer_expired(uint32_t timer_id) { void phr_proc::timer_expired(uint32_t timer_id) {
if(timer_id == timer_periodic_id) { if (timer_id == timer_periodic_id) {
timers_db->get(timer_periodic_id)->reset(); timers_db->get(timer_periodic_id)->reset();
timers_db->get(timer_periodic_id)->run(); timers_db->get(timer_periodic_id)->run();
Debug("PHR: Triggered by timer periodic (timer expired).\n"); Debug("PHR: Triggered by timer periodic (timer expired).\n");
phr_is_triggered = true; phr_is_triggered = true;
} else if (timer_id == timer_prohibit_id) { } else if (timer_id == timer_prohibit_id) {
int pathloss_db = liblte_rrc_dl_pathloss_change_num[mac_cfg->main.phr_cnfg.dl_pathloss_change];
if (pathloss_changed()) { if (pathloss_changed()) {
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d (timer expired)\n", last_pathloss_db); Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d (timer expired)\n", last_pathloss_db);
phr_is_triggered = true; phr_is_triggered = true;
@ -105,8 +110,8 @@ void phr_proc::step(uint32_t tti)
return; return;
} }
if (mac_cfg->main.phr_cnfg.setup_present) { if (mac_cfg->main.phr_cfg.type() == asn1::rrc::setup_e::setup) {
int cfg_timer_periodic = liblte_rrc_periodic_phr_timer_num[mac_cfg->main.phr_cnfg.periodic_phr_timer]; int cfg_timer_periodic = mac_cfg->main.phr_cfg.setup().periodic_phr_timer.to_number();
// Setup timers and trigger PHR when configuration changed by higher layers // Setup timers and trigger PHR when configuration changed by higher layers
if (timer_periodic_value != cfg_timer_periodic && cfg_timer_periodic > 0) if (timer_periodic_value != cfg_timer_periodic && cfg_timer_periodic > 0)
@ -120,21 +125,21 @@ void phr_proc::step(uint32_t tti)
} }
int cfg_timer_prohibit = liblte_rrc_prohibit_phr_timer_num[mac_cfg->main.phr_cnfg.prohibit_phr_timer]; if (mac_cfg->main.phr_cfg_present) {
int cfg_timer_prohibit = mac_cfg->main.phr_cfg.setup().prohibit_phr_timer.to_number();
if (timer_prohibit_value != cfg_timer_prohibit && cfg_timer_prohibit > 0) if (timer_prohibit_value != cfg_timer_prohibit && cfg_timer_prohibit > 0) {
{
timer_prohibit_value = cfg_timer_prohibit; timer_prohibit_value = cfg_timer_prohibit;
timers_db->get(timer_prohibit_id)->set(this, timer_prohibit_value); timers_db->get(timer_prohibit_id)->set(this, timer_prohibit_value);
timers_db->get(timer_prohibit_id)->run(); timers_db->get(timer_prohibit_id)->run();
Info("PHR: Configured timer prohibit %d ms\n", timer_prohibit_value); Info("PHR: Configured timer prohibit %d ms\n", timer_prohibit_value);
phr_is_triggered = true; phr_is_triggered = true;
} }
if (pathloss_changed() && timers_db->get(timer_prohibit_id)->is_expired()) if (pathloss_changed() && timers_db->get(timer_prohibit_id)->is_expired()) {
{
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d\n", last_pathloss_db); Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d\n", last_pathloss_db);
phr_is_triggered = true; phr_is_triggered = true;
} }
}
} }
bool phr_proc::generate_phr_on_ul_grant(float *phr) bool phr_proc::generate_phr_on_ul_grant(float *phr)

@ -29,9 +29,10 @@
#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) #define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__)
#include <stdlib.h> #include <inttypes.h> // for printing uint64_t
#include <stdint.h>
#include <signal.h> #include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include "srsue/hdr/mac/proc_ra.h" #include "srsue/hdr/mac/proc_ra.h"
#include "srsue/hdr/mac/mac.h" #include "srsue/hdr/mac/mac.h"
@ -104,9 +105,9 @@ void ra_proc::read_params() {
preambleIndex = 0; // pass when called from higher layers for non-contention based RA preambleIndex = 0; // pass when called from higher layers for non-contention based RA
maskIndex = 0; // same maskIndex = 0; // same
} }
nof_preambles = liblte_rrc_number_of_ra_preambles_num[mac_cfg->rach.num_ra_preambles]; nof_preambles = mac_cfg->rach.preamb_info.nof_ra_preambs.to_number();
if (mac_cfg->rach.preambles_group_a_cnfg.present) { if (mac_cfg->rach.preamb_info.preambs_group_a_cfg_present) {
nof_groupA_preambles = liblte_rrc_size_of_ra_preambles_group_a_num[mac_cfg->rach.preambles_group_a_cnfg.size_of_ra]; nof_groupA_preambles = mac_cfg->rach.preamb_info.preambs_group_a_cfg.size_of_ra_preambs_group_a.to_number();
} else { } else {
nof_groupA_preambles = nof_preambles; nof_groupA_preambles = nof_preambles;
} }
@ -117,14 +118,14 @@ void ra_proc::read_params() {
nof_groupB_preambles = nof_preambles - nof_groupA_preambles; nof_groupB_preambles = nof_preambles - nof_groupA_preambles;
if (nof_groupB_preambles) { if (nof_groupB_preambles) {
messagePowerOffsetGroupB= liblte_rrc_message_power_offset_group_b_num[mac_cfg->rach.preambles_group_a_cnfg.msg_pwr_offset_group_b]; messagePowerOffsetGroupB = mac_cfg->rach.preamb_info.preambs_group_a_cfg.msg_pwr_offset_group_b.to_number();
messageSizeGroupA = liblte_rrc_message_size_group_a_num[mac_cfg->rach.preambles_group_a_cnfg.msg_size]; messageSizeGroupA = mac_cfg->rach.preamb_info.preambs_group_a_cfg.msg_size_group_a.to_number();
} }
responseWindowSize = liblte_rrc_ra_response_window_size_num[mac_cfg->rach.ra_resp_win_size]; responseWindowSize = mac_cfg->rach.ra_supervision_info.ra_resp_win_size.to_number();
powerRampingStep = liblte_rrc_power_ramping_step_num[mac_cfg->rach.pwr_ramping_step]; powerRampingStep = mac_cfg->rach.pwr_ramp_params.pwr_ramp_step.to_number();
preambleTransMax = liblte_rrc_preamble_trans_max_num[mac_cfg->rach.preamble_trans_max]; preambleTransMax = mac_cfg->rach.ra_supervision_info.preamb_trans_max.to_number();
iniReceivedTargetPower = liblte_rrc_preamble_initial_received_target_power_num[mac_cfg->rach.preamble_init_rx_target_pwr]; iniReceivedTargetPower = mac_cfg->rach.pwr_ramp_params.preamb_init_rx_target_pwr.to_number();
contentionResolutionTimer = liblte_rrc_mac_contention_resolution_timer_num[mac_cfg->rach.mac_con_res_timer]; contentionResolutionTimer = mac_cfg->rach.ra_supervision_info.mac_contention_resolution_timer.to_number();
delta_preamble_db = delta_preamble_db_table[configIndex%5]; delta_preamble_db = delta_preamble_db_table[configIndex%5];
@ -453,7 +454,7 @@ bool ra_proc::contention_resolution_id_received(uint64_t rx_contention_id) {
uecri_successful = true; uecri_successful = true;
state = COMPLETION; state = COMPLETION;
} else { } else {
rInfo("Transmitted UE Contention Id differs from received Contention ID (0x%lx != 0x%lx)\n", rInfo("Transmitted UE Contention Id differs from received Contention ID (0x%" PRIu64 " != 0x%" PRIu64 ")\n",
transmitted_contention_id, rx_contention_id); transmitted_contention_id, rx_contention_id);
// Discard MAC PDU // Discard MAC PDU
uecri_successful = false; uecri_successful = false;

@ -45,6 +45,8 @@ void sr_proc::init(phy_interface_mac* phy_h_, rrc_interface_mac *rrc_, srslte::l
mac_cfg = mac_cfg_; mac_cfg = mac_cfg_;
phy_h = phy_h_; phy_h = phy_h_;
initiated = true; initiated = true;
dsr_transmax = 0;
sr_counter = 0;
do_ra = false; do_ra = false;
} }
@ -75,7 +77,7 @@ void sr_proc::step(uint32_t tti)
{ {
if (initiated) { if (initiated) {
if (is_pending_sr) { if (is_pending_sr) {
if (mac_cfg->sr.setup_present) { if (mac_cfg->sr.type() == asn1::rrc::setup_e::setup) {
if (sr_counter < dsr_transmax) { if (sr_counter < dsr_transmax) {
if (sr_counter == 0 || need_tx(tti)) { if (sr_counter == 0 || need_tx(tti)) {
sr_counter++; sr_counter++;
@ -120,8 +122,10 @@ void sr_proc::start()
sr_counter = 0; sr_counter = 0;
is_pending_sr = true; is_pending_sr = true;
} }
dsr_transmax = liblte_rrc_dsr_trans_max_num[mac_cfg->sr.dsr_trans_max]; if (mac_cfg->sr.type() == asn1::rrc::setup_e::setup) {
Debug("SR: Starting Procedure. dsrTransMax=%d\n", dsr_transmax); dsr_transmax = mac_cfg->sr.setup().dsr_trans_max.to_number();
Info("SR: Starting Procedure. dsrTransMax=%d\n", dsr_transmax);
}
} }
} }

@ -54,7 +54,8 @@ namespace bpo = boost::program_options;
***********************************************************************/ ***********************************************************************/
string config_file; string config_file;
void parse_args(all_args_t *args, int argc, char *argv[]) { void parse_args(all_args_t* args, int argc, char* argv[])
{
// Command line only options // Command line only options
bpo::options_description general("General options"); bpo::options_description general("General options");
@ -65,6 +66,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
// Command line or config file options // Command line or config file options
bpo::options_description common("Configuration options"); bpo::options_description common("Configuration options");
// clang-format off
common.add_options() common.add_options()
("rf.dl_earfcn", bpo::value<string>(&args->rf.dl_earfcn)->default_value("3400"), "Downlink EARFCN list") ("rf.dl_earfcn", bpo::value<string>(&args->rf.dl_earfcn)->default_value("3400"), "Downlink EARFCN list")
("rf.freq_offset", bpo::value<float>(&args->rf.freq_offset)->default_value(0), "(optional) Frequency offset") ("rf.freq_offset", bpo::value<float>(&args->rf.freq_offset)->default_value(0), "(optional) Frequency offset")
@ -317,6 +319,8 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
bpo::options_description position("Positional options"); bpo::options_description position("Positional options");
position.add_options() position.add_options()
("config_file", bpo::value<string>(&config_file), "UE configuration file"); ("config_file", bpo::value<string>(&config_file), "UE configuration file");
// clang-format on
bpo::positional_options_description p; bpo::positional_options_description p;
p.add("config_file", -1); p.add("config_file", -1);
@ -370,14 +374,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
exit(1); exit(1);
} }
//Check conflicting OP/OPc options and which is being used // Check conflicting OP/OPc options and which is being used
if (vm.count("usim.op") && !vm["usim.op"].defaulted() && if (vm.count("usim.op") && !vm["usim.op"].defaulted() && vm.count("usim.opc") && !vm["usim.opc"].defaulted()) {
vm.count("usim.opc") && !vm["usim.opc"].defaulted())
{
cout << "Conflicting options OP and OPc. Please configure either one or the other." << endl; cout << "Conflicting options OP and OPc. Please configure either one or the other." << endl;
exit(1); exit(1);
} } else {
else {
args->usim.using_op = vm.count("usim.op"); args->usim.using_op = vm.count("usim.op");
} }
@ -412,7 +413,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
} }
} }
// Apply all_hex_limit to any unset layers // Apply all_hex_limit to any unset layers
if (vm.count("log.all_hex_limit")) { if (vm.count("log.all_hex_limit")) {
if (!vm.count("log.phy_hex_limit")) { if (!vm.count("log.phy_hex_limit")) {
@ -450,16 +450,18 @@ static bool show_mbms = false;
static bool mbms_service_start = false; static bool mbms_service_start = false;
uint32_t serv, port; uint32_t serv, port;
void sig_int_handler(int signo) { void sig_int_handler(int signo)
{
sigcnt++; sigcnt++;
running = false; running = false;
printf("Stopping srsUE... Press Ctrl+C %d more times to force stop\n", 10-sigcnt); printf("Stopping srsUE... Press Ctrl+C %d more times to force stop\n", 10 - sigcnt);
if (sigcnt >= 10) { if (sigcnt >= 10) {
exit(-1); exit(-1);
} }
} }
void *input_loop(void *m) { void* input_loop(void* m)
{
string key; string key;
while (running) { while (running) {
getline(cin, key); getline(cin, key);
@ -475,29 +477,27 @@ void *input_loop(void *m) {
cout << "Enter t to restart trace." << endl; cout << "Enter t to restart trace." << endl;
} }
metrics_screen.toggle_print(do_metrics); metrics_screen.toggle_print(do_metrics);
} else } else if (0 == key.compare("q")) {
if (0 == key.compare("q")) {
running = false; running = false;
} } else if (0 == key.compare("mbms")) {
else if (0 == key.compare("mbms")) {
show_mbms = true; show_mbms = true;
} else if (key.find("mbms_service_start") != string::npos) { } else if (key.find("mbms_service_start") != string::npos) {
char *dup = strdup(key.c_str()); char* dup = strdup(key.c_str());
strtok(dup, " "); strtok(dup, " ");
char *s = strtok(NULL, " "); char* s = strtok(NULL, " ");
char* p = strtok(NULL, " "); char* p = strtok(NULL, " ");
if(NULL == s) { if (NULL == s) {
cout << "Usage: mbms_service_start <service_id> <port_number>" << endl; cout << "Usage: mbms_service_start <service_id> <port_number>" << endl;
goto free_mem; goto free_mem;
} }
serv = atoi(s); serv = atoi(s);
if(NULL == p) { if (NULL == p) {
cout << "Usage: mbms_service_start <service_id> <port_number>" << endl; cout << "Usage: mbms_service_start <service_id> <port_number>" << endl;
goto free_mem; goto free_mem;
} }
port = atoi(p); port = atoi(p);
mbms_service_start = true; mbms_service_start = true;
free_mem: free_mem:
free(dup); free(dup);
} }
} }
@ -505,7 +505,7 @@ free_mem:
return NULL; return NULL;
} }
int main(int argc, char *argv[]) int main(int argc, char* argv[])
{ {
srslte::metrics_hub<ue_metrics_t> metricshub; srslte::metrics_hub<ue_metrics_t> metricshub;
signal(SIGINT, sig_int_handler); signal(SIGINT, sig_int_handler);
@ -517,7 +517,7 @@ int main(int argc, char *argv[])
parse_args(&args, argc, argv); parse_args(&args, argc, argv);
srsue_instance_type_t type = LTE; srsue_instance_type_t type = LTE;
ue_base *ue = ue_base::get_instance(type); ue_base* ue = ue_base::get_instance(type);
if (!ue) { if (!ue) {
cout << "Error creating UE instance." << endl << endl; cout << "Error creating UE instance." << endl << endl;
exit(1); exit(1);
@ -555,28 +555,27 @@ int main(int argc, char *argv[])
ue->start_plot(); ue->start_plot();
} }
// Auto-start MBMS service by default // Auto-start MBMS service by default
if(args.expert.mbms_service > -1){ if (args.expert.mbms_service > -1) {
serv = args.expert.mbms_service; serv = args.expert.mbms_service;
port = 4321; port = 4321;
mbms_service_start = true; mbms_service_start = true;
} }
} }
int cnt=0; int cnt = 0;
while (running) { while (running) {
// if (mbms_service_start) {
if(mbms_service_start) { if (ue->mbms_service_start(serv, port)) {
if(ue->mbms_service_start(serv, port)){
mbms_service_start = false; mbms_service_start = false;
} }
} }
if(show_mbms) { if (show_mbms) {
show_mbms = false; show_mbms = false;
ue->print_mbms(); ue->print_mbms();
} }
if (args.expert.print_buffer_state) { if (args.expert.print_buffer_state) {
cnt++; cnt++;
if (cnt==10) { if (cnt == 10) {
cnt=0; cnt = 0;
ue->print_pool(); ue->print_pool();
} }
} }

@ -24,17 +24,20 @@
* *
*/ */
#include "srsue/hdr/phy/phch_common.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/srslte.h"
#include <assert.h> #include <assert.h>
#include <string.h>
#include <sstream> #include <sstream>
#include "srslte/srslte.h" #include <string.h>
#include "srsue/hdr/phy/phch_common.h"
#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) #define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__)
#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) #define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__)
#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) #define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) #define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__)
using namespace asn1::rrc;
namespace srsue { namespace srsue {
cf_t zeros[50000]; cf_t zeros[50000];
@ -154,7 +157,7 @@ bool phch_common::get_pending_rar(uint32_t tti, srslte_dci_rar_grant_t *rar_gran
if (rar_grant_pending && tti >= rar_grant_tti) { if (rar_grant_pending && tti >= rar_grant_tti) {
if (rar_grant_) { if (rar_grant_) {
rar_grant_pending = false; rar_grant_pending = false;
memcpy(rar_grant_, &rar_grant, sizeof(srslte_dci_rar_grant_t)); *rar_grant_ = rar_grant;
} }
return true; return true;
} }
@ -391,7 +394,13 @@ void phch_common::build_mch_table()
bzero(&mch_table[0], sizeof(uint8_t)*40); bzero(&mch_table[0], sizeof(uint8_t)*40);
// 40 element table represents 4 frames (40 subframes) // 40 element table represents 4 frames (40 subframes)
generate_mch_table(&mch_table[0], config->mbsfn.mbsfn_subfr_cnfg.subfr_alloc,(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == config->mbsfn.mbsfn_subfr_cnfg.subfr_alloc_num_frames)?1:4); if (config->mbsfn.mbsfn_subfr_cnfg.sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::one_frame) {
generate_mch_table(&mch_table[0], (uint32_t)config->mbsfn.mbsfn_subfr_cnfg.sf_alloc.one_frame().to_number(), 1u);
} else if (config->mbsfn.mbsfn_subfr_cnfg.sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::four_frames) {
generate_mch_table(&mch_table[0], (uint32_t)config->mbsfn.mbsfn_subfr_cnfg.sf_alloc.four_frames().to_number(), 4u);
} else {
log_h->error("The subframe config has not been set for MBSFN\n");
}
// Debug // Debug
@ -407,7 +416,7 @@ void phch_common::build_mcch_table()
{ {
// First reset tables // First reset tables
bzero(&mcch_table[0], sizeof(uint8_t)*10); bzero(&mcch_table[0], sizeof(uint8_t)*10);
generate_mcch_table(&mcch_table[0], config->mbsfn.mbsfn_area_info.sf_alloc_info_r9); generate_mcch_table(&mcch_table[0], (uint32_t)config->mbsfn.mbsfn_area_info.mcch_cfg_r9.sf_alloc_info_r9.to_number());
// Debug // Debug
std::stringstream ss; std::stringstream ss;
ss << "|"; ss << "|";
@ -433,15 +442,15 @@ void phch_common::set_mch_period_stop(uint32_t stop)
} }
bool phch_common::is_mch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti) bool phch_common::is_mch_subframe(subframe_cfg_t* cfg, uint32_t phy_tti)
{ {
uint32_t sfn; // System Frame Number uint32_t sfn; // System Frame Number
uint8_t sf; // Subframe uint8_t sf; // Subframe
uint8_t offset; uint8_t offset;
uint8_t period; uint8_t period;
sfn = phy_tti/10; sfn = phy_tti / 10;
sf = phy_tti%10; sf = phy_tti % 10;
// Set some defaults // Set some defaults
cfg->mbsfn_area_id = 0; cfg->mbsfn_area_id = 0;
@ -450,41 +459,42 @@ bool phch_common::is_mch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti)
cfg->mbsfn_decode = false; cfg->mbsfn_decode = false;
cfg->is_mcch = false; cfg->is_mcch = false;
// Check for MCCH // Check for MCCH
if(is_mcch_subframe(cfg, phy_tti)) { if (is_mcch_subframe(cfg, phy_tti)) {
cfg->is_mcch = true; cfg->is_mcch = true;
return true; return true;
} }
// Not MCCH, check for MCH // Not MCCH, check for MCH
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT *subfr_cnfg = &config->mbsfn.mbsfn_subfr_cnfg; mbsfn_sf_cfg_s* subfr_cnfg = &config->mbsfn.mbsfn_subfr_cnfg;
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *area_info = &config->mbsfn.mbsfn_area_info; mbsfn_area_info_r9_s* area_info = &config->mbsfn.mbsfn_area_info;
offset = subfr_cnfg->radio_fr_alloc_offset; offset = subfr_cnfg->radioframe_alloc_offset;
period = liblte_rrc_radio_frame_allocation_period_num[subfr_cnfg->radio_fr_alloc_period]; period = subfr_cnfg->radioframe_alloc_period.to_number();
if(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == subfr_cnfg->subfr_alloc_num_frames) { if (subfr_cnfg->sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::one_frame) {
if((sfn%period == offset) && (mch_table[sf] > 0)) { if ((sfn % period == offset) && (mch_table[sf] > 0)) {
if(sib13_configured) { if (sib13_configured) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length]; cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number();
if(mcch_configured) { if (mcch_configured) {
// Iterate through PMCH configs to see which one applies in the current frame // Iterate through PMCH configs to see which one applies in the current frame
LIBLTE_RRC_MCCH_MSG_STRUCT *mcch = &config->mbsfn.mcch; mbsfn_area_cfg_r9_s* mcch = &config->mbsfn.mcch.msg.c1().mbsfn_area_cfg_r9();
uint32_t mbsfn_per_frame = mcch->pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9/liblte_rrc_mch_scheduling_period_r9_num[mcch->pmch_infolist_r9[0].pmch_config_r9.mch_schedulingperiod_r9]; uint32_t mbsfn_per_frame = mcch->pmch_info_list_r9[0].pmch_cfg_r9.sf_alloc_end_r9 /
uint32_t frame_alloc_idx = sfn%liblte_rrc_mbsfn_common_sf_alloc_period_r9_num[mcch->commonsf_allocperiod_r9]; mcch->pmch_info_list_r9[0].pmch_cfg_r9.mch_sched_period_r9.to_number();
uint32_t sf_alloc_idx = frame_alloc_idx*mbsfn_per_frame + ((sf<4)?sf-1:sf-3); uint32_t frame_alloc_idx = sfn % mcch->common_sf_alloc_period_r9.to_number();
uint32_t sf_alloc_idx = frame_alloc_idx * mbsfn_per_frame + ((sf < 4) ? sf - 1 : sf - 3);
pthread_mutex_lock(&mtch_mutex); pthread_mutex_lock(&mtch_mutex);
while(!have_mtch_stop) { while (!have_mtch_stop) {
pthread_cond_wait(&mtch_cvar, &mtch_mutex); pthread_cond_wait(&mtch_cvar, &mtch_mutex);
} }
pthread_mutex_unlock(&mtch_mutex); pthread_mutex_unlock(&mtch_mutex);
for(uint32_t i=0; i<mcch->pmch_infolist_r9_size; i++) { for (uint32_t i = 0; i < mcch->pmch_info_list_r9.size(); i++) {
if(sf_alloc_idx <= mch_period_stop) { if (sf_alloc_idx <= mch_period_stop) {
//trigger conditional variable, has ot be untriggered by mtch stop location // trigger conditional variable, has ot be untriggered by mtch stop location
cfg->mbsfn_mcs = mcch->pmch_infolist_r9[i].pmch_config_r9.datamcs_r9; cfg->mbsfn_mcs = mcch->pmch_info_list_r9[i].pmch_cfg_r9.data_mcs_r9;
cfg->mbsfn_decode = true; cfg->mbsfn_decode = true;
} else { } else {
//have_mtch_stop = false; // have_mtch_stop = false;
} }
} }
Debug("MCH subframe TTI:%d\n", phy_tti); Debug("MCH subframe TTI:%d\n", phy_tti);
@ -492,45 +502,45 @@ bool phch_common::is_mch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti)
} }
return true; return true;
} }
}else if(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_FOUR == subfr_cnfg->subfr_alloc_num_frames) { } else if (subfr_cnfg->sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::four_frames) {
uint8_t idx = sfn%period; uint8_t idx = sfn % period;
if((idx >= offset) && (idx < offset+4)) { if ((idx >= offset) && (idx < offset + 4)) {
if(mch_table[(idx*10)+sf] > 0){ if (mch_table[(idx * 10) + sf] > 0) {
if(sib13_configured) { if (sib13_configured) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length]; cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number();
// TODO: check for MCCH configuration, set MCS and decode // TODO: check for MCCH configuration, set MCS and decode
} }
return true; return true;
} }
} }
} else {
log_h->error("The subframe allocation type is not yet configured\n");
} }
return false; return false;
} }
bool phch_common::is_mcch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti) bool phch_common::is_mcch_subframe(subframe_cfg_t* cfg, uint32_t phy_tti)
{ {
uint32_t sfn; // System Frame Number uint32_t sfn; // System Frame Number
uint8_t sf; // Subframe uint8_t sf; // Subframe
uint8_t offset; uint8_t offset;
uint8_t period; uint16_t period;
sfn = phy_tti/10; sfn = phy_tti / 10;
sf = phy_tti%10; sf = (uint8_t)(phy_tti % 10);
if(sib13_configured) { if (sib13_configured) {
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT *subfr_cnfg = &config->mbsfn.mbsfn_subfr_cnfg; mbsfn_area_info_r9_s* area_info = &config->mbsfn.mbsfn_area_info;
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *area_info = &config->mbsfn.mbsfn_area_info;
offset = area_info->mcch_offset_r9; offset = area_info->mcch_cfg_r9.mcch_offset_r9;
period = liblte_rrc_mcch_repetition_period_r9_num[area_info->mcch_repetition_period_r9]; period = area_info->mcch_cfg_r9.mcch_repeat_period_r9.to_number();
if((sfn%period == offset) && mcch_table[sf] > 0) { if ((sfn % period == offset) && mcch_table[sf] > 0) {
cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9;
cfg->non_mbsfn_region_length = liblte_rrc_non_mbsfn_region_length_num[area_info->non_mbsfn_region_length]; cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number();
cfg->mbsfn_mcs = liblte_rrc_mcch_signalling_mcs_r9_num[area_info->signalling_mcs_r9]; cfg->mbsfn_mcs = area_info->mcch_cfg_r9.sig_mcs_r9.to_number();
cfg->mbsfn_decode = true; cfg->mbsfn_decode = true;
have_mtch_stop = false; have_mtch_stop = false;
Debug("MCCH subframe TTI:%d\n", phy_tti); Debug("MCCH subframe TTI:%d\n", phy_tti);
@ -542,10 +552,11 @@ bool phch_common::is_mcch_subframe(subframe_cfg_t *cfg, uint32_t phy_tti)
void phch_common::get_sf_config(subframe_cfg_t *cfg, uint32_t phy_tti) void phch_common::get_sf_config(subframe_cfg_t *cfg, uint32_t phy_tti)
{ {
if(is_mch_subframe(cfg, phy_tti)) {
cfg->sf_type = SUBFRAME_TYPE_MBSFN;
}else{
cfg->sf_type = SUBFRAME_TYPE_REGULAR; cfg->sf_type = SUBFRAME_TYPE_REGULAR;
if (sib13_configured) {
if (is_mch_subframe(cfg, phy_tti)) {
cfg->sf_type = SUBFRAME_TYPE_MBSFN;
}
} }
} }

@ -188,7 +188,7 @@ phy_interface_rrc::cell_search_ret_t phch_recv::cell_search(phy_interface_rrc::p
pthread_mutex_lock(&rrc_mutex); pthread_mutex_lock(&rrc_mutex);
// Move state to IDLE // Move state to IDLE
Info("Cell Search: Start EARFCN index=%u/%lu\n", cellsearch_earfcn_index, earfcn.size()); Info("Cell Search: Start EARFCN index=%u/%zd\n", cellsearch_earfcn_index, earfcn.size());
phy_state.go_idle(); phy_state.go_idle();
if (current_earfcn != (int) earfcn[cellsearch_earfcn_index]) { if (current_earfcn != (int) earfcn[cellsearch_earfcn_index]) {

@ -29,7 +29,6 @@
#include "srsue/hdr/phy/phch_worker.h" #include "srsue/hdr/phy/phch_worker.h"
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srslte/interfaces/ue_interfaces.h" #include "srslte/interfaces/ue_interfaces.h"
#include "srslte/asn1/liblte_rrc.h"
#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) #define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__)
#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) #define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__)
@ -51,6 +50,7 @@ static int plot_worker_id = -1;
#endif #endif
/*********************************************/ /*********************************************/
using namespace asn1::rrc;
namespace srsue { namespace srsue {
@ -288,7 +288,7 @@ void phch_worker::work_imp()
// Average RSSI over all symbols (make sure SF length is non-zero) // Average RSSI over all symbols (make sure SF length is non-zero)
float rssi_dbm = SRSLTE_SF_LEN_PRB(cell.nof_prb) > 0 ? (10*log10(srslte_vec_avg_power_cf(signal_buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb))) + 30) : 0; float rssi_dbm = SRSLTE_SF_LEN_PRB(cell.nof_prb) > 0 ? (10*log10(srslte_vec_avg_power_cf(signal_buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb))) + 30) : 0;
if (isnormal(rssi_dbm)) { if (std::isnormal(rssi_dbm)) {
phy->avg_rssi_dbm = SRSLTE_VEC_EMA(rssi_dbm, phy->avg_rssi_dbm, phy->args->snr_ema_coeff); phy->avg_rssi_dbm = SRSLTE_VEC_EMA(rssi_dbm, phy->avg_rssi_dbm, phy->args->snr_ema_coeff);
} }
@ -520,7 +520,7 @@ void phch_worker::work_imp()
} }
void phch_worker::compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr) { void phch_worker::compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr) {
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { if (phy->config->dedicated.ant_info.explicit_value().tx_mode == asn1::rrc::ant_info_ded_s::tx_mode_e_::tm3) {
if (ue_dl.nof_rx_antennas > 1) { if (ue_dl.nof_rx_antennas > 1) {
/* If 2 ort more receiving antennas, select RI */ /* If 2 ort more receiving antennas, select RI */
float cn = 0.0f; float cn = 0.0f;
@ -535,7 +535,7 @@ void phch_worker::compute_ri(uint8_t *ri, uint8_t *pmi, float *sinr) {
} }
} }
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
} else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { } else if (phy->config->dedicated.ant_info.explicit_value().tx_mode == asn1::rrc::ant_info_ded_s::tx_mode_e_::tm4) {
if (sinr) { if (sinr) {
srslte_ue_dl_ri_pmi_select(&ue_dl, ri, pmi, sinr); srslte_ue_dl_ri_pmi_select(&ue_dl, ri, pmi, sinr);
Debug("TM4 ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); Debug("TM4 ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]]));
@ -623,12 +623,12 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
Debug("Looking for RNTI=0x%x\n", dl_rnti); Debug("Looking for RNTI=0x%x\n", dl_rnti);
} }
if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cfi, tti%10, if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.ant_info.explicit_value().tx_mode, cfi, tti % 10,
dl_rnti, type, &dci_msg) != 1) { dl_rnti, type, &dci_msg) != 1) {
if (type == SRSLTE_RNTI_RAR) { if (type == SRSLTE_RNTI_RAR) {
Debug("RAR not found, SNR=%.1f dB, tti=%d, cfi=%d, tx_mode=%d, cell_id=%d\n", Debug("RAR not found, SNR=%.1f dB, tti=%d, cfi=%d, tx_mode=%d, cell_id=%d\n",
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), tti, cfi, 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), tti, cfi,
phy->config->dedicated.antenna_info_explicit_value.tx_mode, cell.id); phy->config->dedicated.ant_info.explicit_value().tx_mode.value, cell.id);
} }
return false; return false;
} }
@ -704,16 +704,16 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
} }
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant); uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
switch(phy->config->dedicated.antenna_info_explicit_value.tx_mode) { switch (phy->config->dedicated.ant_info.explicit_value().tx_mode.value) {
/* Implemented Tx Modes */ /* Implemented Tx Modes */
case LIBLTE_RRC_TRANSMISSION_MODE_1: case ant_info_ded_s::tx_mode_e_::tm1:
mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA; mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
if (nof_tb != 1) { if (nof_tb != 1) {
Error("Wrong number of transport blocks (%d) for single antenna.", nof_tb); Error("Wrong number of transport blocks (%d) for single antenna.", nof_tb);
valid_config = false; valid_config = false;
} }
break; break;
case LIBLTE_RRC_TRANSMISSION_MODE_2: case ant_info_ded_s::tx_mode_e_::tm2:
if (cell.nof_ports > 1) { if (cell.nof_ports > 1) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else { } else {
@ -724,7 +724,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
valid_config = false; valid_config = false;
} }
break; break;
case LIBLTE_RRC_TRANSMISSION_MODE_3: case ant_info_ded_s::tx_mode_e_::tm3:
if (nof_tb == 1) { if (nof_tb == 1) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) { } else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) {
@ -735,7 +735,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
valid_config = false; valid_config = false;
} }
break; break;
case LIBLTE_RRC_TRANSMISSION_MODE_4: case ant_info_ded_s::tx_mode_e_::tm4:
if (nof_tb == 1) { if (nof_tb == 1) {
mimo_type = (grant->pinfo == 0) ? SRSLTE_MIMO_TYPE_TX_DIVERSITY : SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; mimo_type = (grant->pinfo == 0) ? SRSLTE_MIMO_TYPE_TX_DIVERSITY : SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
} else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) { } else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) {
@ -748,24 +748,23 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
break; break;
/* Not implemented cases */ /* Not implemented cases */
case LIBLTE_RRC_TRANSMISSION_MODE_5: case ant_info_ded_s::tx_mode_e_::tm5:
case LIBLTE_RRC_TRANSMISSION_MODE_6: case ant_info_ded_s::tx_mode_e_::tm6:
case LIBLTE_RRC_TRANSMISSION_MODE_7: case ant_info_ded_s::tx_mode_e_::tm7:
case LIBLTE_RRC_TRANSMISSION_MODE_8: case ant_info_ded_s::tx_mode_e_::tm8_v920:
Error("Not implemented Tx mode (%d)\n", phy->config->dedicated.antenna_info_explicit_value.tx_mode); Error("Not implemented Tx mode (%d)\n", phy->config->dedicated.ant_info.explicit_value().tx_mode.value);
break; break;
/* Error cases */ /* Error cases */
case LIBLTE_RRC_TRANSMISSION_MODE_N_ITEMS:
default: default:
Error("Wrong Tx mode (%d)\n", phy->config->dedicated.antenna_info_explicit_value.tx_mode); Error("Wrong Tx mode (%d)\n", phy->config->dedicated.ant_info.explicit_value().tx_mode.value);
valid_config = false; valid_config = false;
} }
/* Set power allocation according to 3GPP 36.213 clause 5.2 Downlink power allocation */ /* Set power allocation according to 3GPP 36.213 clause 5.2 Downlink power allocation */
float rho_a = 1.0f, rho_b = 1.0f; float rho_a = 1.0f, rho_b = 1.0f;
if (phy->config->dedicated.pdsch_cnfg_ded < LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS) { if (phy->config->dedicated.pdsch_cfg_ded_present) {
float rho_a_db = liblte_rrc_pdsch_config_p_a_num[(int) phy->config->dedicated.pdsch_cnfg_ded]; float rho_a_db = phy->config->dedicated.pdsch_cfg_ded.p_a.to_number();
rho_a = powf(10.0f, rho_a_db / 20.0f) * ((cell.nof_ports == 1) ? 1.0f : sqrtf(2.0f)); rho_a = powf(10.0f, rho_a_db / 20.0f) * ((cell.nof_ports == 1) ? 1.0f : sqrtf(2.0f));
} }
if (phy->config->common.pdsch_cnfg.p_b < 4) { if (phy->config->common.pdsch_cnfg.p_b < 4) {
@ -811,7 +810,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
#endif #endif
char pinfo_str[16] = {0}; char pinfo_str[16] = {0};
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { if (phy->config->dedicated.ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm4) {
snprintf(pinfo_str, 15, ", pinfo=%x", grant->pinfo); snprintf(pinfo_str, 15, ", pinfo=%x", grant->pinfo);
} }
@ -1113,7 +1112,7 @@ void phch_worker::set_uci_periodic_cqi()
if (cqi_max >= 0 && cqi_report.wideband.wideband_cqi > cqi_max) { if (cqi_max >= 0 && cqi_report.wideband.wideband_cqi > cqi_max) {
cqi_report.wideband.wideband_cqi = cqi_max; cqi_report.wideband.wideband_cqi = cqi_max;
} }
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { if (phy->config->dedicated.ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm4) {
cqi_report.wideband.pmi_present = true; cqi_report.wideband.pmi_present = true;
cqi_report.wideband.pmi = phy->last_pmi; cqi_report.wideband.pmi = phy->last_pmi;
cqi_report.wideband.rank_is_not_one = (phy->last_ri != 0); cqi_report.wideband.rank_is_not_one = (phy->last_ri != 0);
@ -1132,12 +1131,12 @@ void phch_worker::set_uci_aperiodic_cqi()
{ {
float sinr_db = ue_dl.sinr[phy->last_ri % SRSLTE_MAX_LAYERS][phy->last_pmi%SRSLTE_MAX_CODEBOOKS]; float sinr_db = ue_dl.sinr[phy->last_ri % SRSLTE_MAX_LAYERS][phy->last_pmi%SRSLTE_MAX_CODEBOOKS];
if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) { if (phy->config->dedicated.cqi_report_cfg.cqi_report_mode_aperiodic_present) {
/* Compute RI, PMI and SINR */ /* Compute RI, PMI and SINR */
compute_ri(&phy->last_ri, &phy->last_pmi, &sinr_db); compute_ri(&phy->last_ri, &phy->last_pmi, &sinr_db);
switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) { switch (phy->config->dedicated.cqi_report_cfg.cqi_report_mode_aperiodic.value) {
case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30: case cqi_report_mode_aperiodic_e::rm30:
/* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1 /* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1
- A UE shall report a wideband CQI value which is calculated assuming transmission on set S subbands - A UE shall report a wideband CQI value which is calculated assuming transmission on set S subbands
- The UE shall also report one subband CQI value for each set S subband. The subband CQI - The UE shall also report one subband CQI value for each set S subband. The subband CQI
@ -1168,8 +1167,8 @@ void phch_worker::set_uci_aperiodic_cqi()
srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, SRSLTE_CQI_STR_MAX_CHAR); srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, SRSLTE_CQI_STR_MAX_CHAR);
/* Set RI = 1 */ /* Set RI = 1 */
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 || if (phy->config->dedicated.ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm3 ||
phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { phy->config->dedicated.ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm4) {
uci_data.uci_ri = phy->last_ri; uci_data.uci_ri = phy->last_ri;
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
} else { } else {
@ -1180,7 +1179,7 @@ void phch_worker::set_uci_aperiodic_cqi()
cqi_str, (uci_data.uci_ri_len)?((uci_data.uci_ri == 0)?"ri=0, ":"ri=1, "):"", phy->avg_snr_db_cqi, cqi_report.subband_hl.N); cqi_str, (uci_data.uci_ri_len)?((uci_data.uci_ri == 0)?"ri=0, ":"ri=1, "):"", phy->avg_snr_db_cqi, cqi_report.subband_hl.N);
} }
break; break;
case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31: case cqi_report_mode_aperiodic_e::rm31:
/* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1 /* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1
- A single precoding matrix is selected from the codebook subset assuming transmission on set S subbands - A single precoding matrix is selected from the codebook subset assuming transmission on set S subbands
- A UE shall report one subband CQI value per codeword for each set S subband which are calculated assuming - A UE shall report one subband CQI value per codeword for each set S subband which are calculated assuming
@ -1240,7 +1239,7 @@ void phch_worker::set_uci_aperiodic_cqi()
break; break;
default: default:
Warning("Received CQI request but mode %s is not supported\n", Warning("Received CQI request but mode %s is not supported\n",
liblte_rrc_cqi_report_mode_aperiodic_text[phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic]); phy->config->dedicated.cqi_report_cfg.cqi_report_mode_aperiodic.to_string().c_str());
break; break;
} }
} else { } else {
@ -1429,41 +1428,41 @@ void phch_worker::set_ul_params(bool pregen_disabled)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
phy_interface_rrc::phy_cfg_common_t *common = &phy->config->common; phy_interface_rrc::phy_cfg_common_t* common = &phy->config->common;
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &phy->config->dedicated; phys_cfg_ded_s* dedicated = &phy->config->dedicated;
Info("Setting new params worker_id=%d, pregen_disabled=%d\n", get_id(), pregen_disabled); Info("Setting new params worker_id=%d, pregen_disabled=%d\n", get_id(), pregen_disabled);
/* PUSCH DMRS signal configuration */ /* PUSCH DMRS signal configuration */
bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); dmrs_cfg.group_hopping_en = common->pusch_cnfg.ul_ref_sigs_pusch.group_hop_enabled;
dmrs_cfg.group_hopping_en = common->pusch_cnfg.ul_rs.group_hopping_enabled; dmrs_cfg.sequence_hopping_en = common->pusch_cnfg.ul_ref_sigs_pusch.seq_hop_enabled;
dmrs_cfg.sequence_hopping_en = common->pusch_cnfg.ul_rs.sequence_hopping_enabled; dmrs_cfg.cyclic_shift = common->pusch_cnfg.ul_ref_sigs_pusch.cyclic_shift;
dmrs_cfg.cyclic_shift = common->pusch_cnfg.ul_rs.cyclic_shift; dmrs_cfg.delta_ss = common->pusch_cnfg.ul_ref_sigs_pusch.group_assign_pusch;
dmrs_cfg.delta_ss = common->pusch_cnfg.ul_rs.group_assignment_pusch;
/* PUSCH Hopping configuration */ /* PUSCH Hopping configuration */
bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t)); pusch_hopping.n_sb = common->pusch_cnfg.pusch_cfg_basic.n_sb;
pusch_hopping.n_sb = common->pusch_cnfg.n_sb; pusch_hopping.hop_mode = common->pusch_cnfg.pusch_cfg_basic.hop_mode.value ==
pusch_hopping.hop_mode = common->pusch_cnfg.hopping_mode == LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME ? pusch_cfg_common_s::pusch_cfg_basic_s_::hop_mode_e_::intra_and_inter_sub_frame
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF : ? pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; : pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping.hopping_offset = common->pusch_cnfg.pusch_hopping_offset; pusch_hopping.hopping_offset = common->pusch_cnfg.pusch_cfg_basic.pusch_hop_offset;
/* PUSCH UCI configuration */ /* PUSCH UCI configuration */
bzero(&uci_cfg, sizeof(srslte_uci_cfg_t)); uci_cfg.I_offset_ack = dedicated->pusch_cfg_ded.beta_offset_ack_idx;
uci_cfg.I_offset_ack = dedicated->pusch_cnfg_ded.beta_offset_ack_idx; uci_cfg.I_offset_cqi = dedicated->pusch_cfg_ded.beta_offset_cqi_idx;
uci_cfg.I_offset_cqi = dedicated->pusch_cnfg_ded.beta_offset_cqi_idx; uci_cfg.I_offset_ri = dedicated->pusch_cfg_ded.beta_offset_ri_idx;
uci_cfg.I_offset_ri = dedicated->pusch_cnfg_ded.beta_offset_ri_idx;
/* PUCCH configuration */ /* PUCCH configuration */
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t)); bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
pucch_cfg.delta_pucch_shift = liblte_rrc_delta_pucch_shift_num[common->pucch_cnfg.delta_pucch_shift%LIBLTE_RRC_DELTA_PUCCH_SHIFT_N_ITEMS]; pucch_cfg.delta_pucch_shift = common->pucch_cnfg.delta_pucch_shift.to_number();
pucch_cfg.N_cs = common->pucch_cnfg.n_cs_an; pucch_cfg.N_cs = common->pucch_cnfg.n_cs_an;
pucch_cfg.n_rb_2 = common->pucch_cnfg.n_rb_cqi; pucch_cfg.n_rb_2 = common->pucch_cnfg.n_rb_cqi;
pucch_cfg.srs_configured = dedicated->srs_ul_cnfg_ded.setup_present; pucch_cfg.srs_configured = dedicated->srs_ul_cfg_ded_present and
dedicated->srs_ul_cfg_ded.type() == setup_e::setup and
common->srs_ul_cnfg.type().value == setup_e::setup;
if (pucch_cfg.srs_configured) { if (pucch_cfg.srs_configured) {
pucch_cfg.srs_cs_subf_cfg = liblte_rrc_srs_subfr_config_num[common->srs_ul_cnfg.subfr_cnfg%LIBLTE_RRC_SRS_SUBFR_CONFIG_N_ITEMS]; pucch_cfg.srs_cs_subf_cfg = common->srs_ul_cnfg.setup().srs_sf_cfg.to_number();
pucch_cfg.srs_simul_ack = common->srs_ul_cnfg.ack_nack_simul_tx; pucch_cfg.srs_simul_ack = common->srs_ul_cnfg.setup().ack_nack_srs_simul_tx;
} }
/* PUCCH Scheduling configuration */ /* PUCCH Scheduling configuration */
@ -1473,39 +1472,56 @@ void phch_worker::set_ul_params(bool pregen_disabled)
pucch_sched.n_pucch_1[2] = 0; pucch_sched.n_pucch_1[2] = 0;
pucch_sched.n_pucch_1[3] = 0; pucch_sched.n_pucch_1[3] = 0;
pucch_sched.N_pucch_1 = common->pucch_cnfg.n1_pucch_an; pucch_sched.N_pucch_1 = common->pucch_cnfg.n1_pucch_an;
pucch_sched.n_pucch_2 = dedicated->cqi_report_cnfg.report_periodic.pucch_resource_idx; if (dedicated->cqi_report_cfg.cqi_report_periodic_present and
pucch_sched.n_pucch_sr = dedicated->sched_request_cnfg.sr_pucch_resource_idx; dedicated->cqi_report_cfg.cqi_report_periodic.type().value == setup_e::setup) {
pucch_sched.n_pucch_2 = dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx;
} else {
// FIXME: put is_pucch_configured flag here?
pucch_sched.n_pucch_2 = 0;
}
/* SR configuration */
if (dedicated->sched_request_cfg_present and dedicated->sched_request_cfg.type() == setup_e::setup) {
I_sr = dedicated->sched_request_cfg.setup().sr_cfg_idx;
pucch_sched.n_pucch_sr = dedicated->sched_request_cfg.setup().sr_pucch_res_idx;
sr_configured = true;
} else {
pucch_sched.n_pucch_sr = 0;
sr_configured = false;
}
/* SRS Configuration */ /* SRS Configuration */
bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t)); bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
srs_cfg.configured = dedicated->srs_ul_cnfg_ded.setup_present; srs_cfg.configured = dedicated->srs_ul_cfg_ded_present and dedicated->srs_ul_cfg_ded.type() == setup_e::setup and
if (pucch_cfg.srs_configured) { common->srs_ul_cnfg.type() == setup_e::setup;
srs_cfg.subframe_config = liblte_rrc_srs_subfr_config_num[common->srs_ul_cnfg.subfr_cnfg%LIBLTE_RRC_SRS_SUBFR_CONFIG_N_ITEMS]; if (srs_cfg.configured) {
srs_cfg.bw_cfg = liblte_rrc_srs_bw_config_num[common->srs_ul_cnfg.bw_cnfg%LIBLTE_RRC_SRS_BW_CONFIG_N_ITEMS]; srs_cfg.subframe_config = common->srs_ul_cnfg.setup().srs_sf_cfg.to_number();
srs_cfg.I_srs = dedicated->srs_ul_cnfg_ded.srs_cnfg_idx; srs_cfg.bw_cfg = common->srs_ul_cnfg.setup().srs_bw_cfg.to_number();
srs_cfg.B = dedicated->srs_ul_cnfg_ded.srs_bandwidth; srs_cfg.I_srs = dedicated->srs_ul_cfg_ded.setup().srs_cfg_idx;
srs_cfg.b_hop = dedicated->srs_ul_cnfg_ded.srs_hopping_bandwidth; srs_cfg.B = dedicated->srs_ul_cfg_ded.setup().srs_bw;
srs_cfg.n_rrc = dedicated->srs_ul_cnfg_ded.freq_domain_pos; srs_cfg.b_hop = dedicated->srs_ul_cfg_ded.setup().srs_hop_bw;
srs_cfg.k_tc = dedicated->srs_ul_cnfg_ded.tx_comb; srs_cfg.n_rrc = dedicated->srs_ul_cfg_ded.setup().freq_domain_position;
srs_cfg.n_srs = dedicated->srs_ul_cnfg_ded.cyclic_shift; srs_cfg.k_tc = dedicated->srs_ul_cfg_ded.setup().tx_comb;
srs_cfg.n_srs = dedicated->srs_ul_cfg_ded.setup().cyclic_shift;
} }
/* UL power control configuration */ /* UL power control configuration */
bzero(&power_ctrl, sizeof(srslte_ue_ul_powerctrl_t)); bzero(&power_ctrl, sizeof(srslte_ue_ul_powerctrl_t));
power_ctrl.p0_nominal_pusch = common->ul_pwr_ctrl.p0_nominal_pusch; power_ctrl.p0_nominal_pusch = common->ul_pwr_ctrl.p0_nominal_pusch;
power_ctrl.alpha = liblte_rrc_ul_power_control_alpha_num[common->ul_pwr_ctrl.alpha%LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_N_ITEMS]; power_ctrl.alpha = common->ul_pwr_ctrl.alpha.to_number();
power_ctrl.p0_nominal_pucch = common->ul_pwr_ctrl.p0_nominal_pucch; power_ctrl.p0_nominal_pucch = common->ul_pwr_ctrl.p0_nominal_pucch;
power_ctrl.delta_f_pucch[0] = liblte_rrc_delta_f_pucch_format_1_num[common->ul_pwr_ctrl.delta_flist_pucch.format_1%LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_N_ITEMS]; power_ctrl.delta_f_pucch[0] = common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format1.to_number();
power_ctrl.delta_f_pucch[1] = liblte_rrc_delta_f_pucch_format_1b_num[common->ul_pwr_ctrl.delta_flist_pucch.format_1b%LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_N_ITEMS]; power_ctrl.delta_f_pucch[1] = common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format1b.to_number();
power_ctrl.delta_f_pucch[2] = liblte_rrc_delta_f_pucch_format_2_num[common->ul_pwr_ctrl.delta_flist_pucch.format_2%LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_N_ITEMS]; power_ctrl.delta_f_pucch[2] = common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2.to_number();
power_ctrl.delta_f_pucch[3] = liblte_rrc_delta_f_pucch_format_2a_num[common->ul_pwr_ctrl.delta_flist_pucch.format_2a%LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_N_ITEMS]; power_ctrl.delta_f_pucch[3] = common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2a.to_number();
power_ctrl.delta_f_pucch[4] = liblte_rrc_delta_f_pucch_format_2b_num[common->ul_pwr_ctrl.delta_flist_pucch.format_2b%LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_N_ITEMS]; power_ctrl.delta_f_pucch[4] = common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2b.to_number();
power_ctrl.delta_preamble_msg3 = common->ul_pwr_ctrl.delta_preamble_msg3; power_ctrl.delta_preamble_msg3 = common->ul_pwr_ctrl.delta_preamb_msg3;
power_ctrl.p0_ue_pusch = dedicated->ul_pwr_ctrl_ded.p0_ue_pusch; power_ctrl.p0_ue_pusch = dedicated->ul_pwr_ctrl_ded.p0_ue_pusch;
power_ctrl.delta_mcs_based = dedicated->ul_pwr_ctrl_ded.delta_mcs_en==LIBLTE_RRC_DELTA_MCS_ENABLED_EN0; power_ctrl.delta_mcs_based =
power_ctrl.acc_enabled = dedicated->ul_pwr_ctrl_ded.accumulation_en; dedicated->ul_pwr_ctrl_ded.delta_mcs_enabled == ul_pwr_ctrl_ded_s::delta_mcs_enabled_e_::en0;
power_ctrl.acc_enabled = dedicated->ul_pwr_ctrl_ded.accumulation_enabled;
power_ctrl.p0_ue_pucch = dedicated->ul_pwr_ctrl_ded.p0_ue_pucch; power_ctrl.p0_ue_pucch = dedicated->ul_pwr_ctrl_ded.p0_ue_pucch;
power_ctrl.p_srs_offset = dedicated->ul_pwr_ctrl_ded.p_srs_offset; power_ctrl.p_srs_offset = dedicated->ul_pwr_ctrl_ded.p_srs_offset;
@ -1513,23 +1529,25 @@ void phch_worker::set_ul_params(bool pregen_disabled)
/* CQI configuration */ /* CQI configuration */
bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t)); bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t));
period_cqi.configured = dedicated->cqi_report_cnfg.report_periodic_setup_present; period_cqi.configured = dedicated->cqi_report_cfg.cqi_report_periodic_present and
period_cqi.pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; dedicated->cqi_report_cfg.cqi_report_periodic.type() == setup_e::setup;
period_cqi.simul_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; if (period_cqi.configured) {
period_cqi.format_is_subband = dedicated->cqi_report_cnfg.report_periodic.format_ind_periodic == period_cqi.pmi_idx = dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx;
LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI; period_cqi.simul_cqi_ack = dedicated->cqi_report_cfg.cqi_report_periodic.setup().simul_ack_nack_and_cqi;
period_cqi.subband_size = dedicated->cqi_report_cnfg.report_periodic.format_ind_periodic_subband_k; period_cqi.format_is_subband =
dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.type().value ==
if (dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present) { cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::subband_cqi;
period_cqi.ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; if (period_cqi.format_is_subband) {
period_cqi.subband_size =
dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.subband_cqi().k;
}
if (dedicated->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present) {
period_cqi.ri_idx = dedicated->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx;
period_cqi.ri_idx_present = true; period_cqi.ri_idx_present = true;
} else { } else {
period_cqi.ri_idx_present = false; period_cqi.ri_idx_present = false;
} }
}
/* SR configuration */
I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;
sr_configured = true;
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
@ -1616,7 +1634,7 @@ void phch_worker::update_measurements()
// Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC // Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC
float rsrq_db = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); float rsrq_db = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest));
if (isnormal(rsrq_db)) { if (std::isnormal(rsrq_db)) {
if (!(tti%phy->pcell_report_period) || !phy->avg_rsrq_db) { if (!(tti%phy->pcell_report_period) || !phy->avg_rsrq_db) {
phy->avg_rsrq_db = rsrq_db; phy->avg_rsrq_db = rsrq_db;
} else { } else {
@ -1626,7 +1644,7 @@ void phch_worker::update_measurements()
// Average RSRP taken from CRS // Average RSRP taken from CRS
float rsrp_lin = srslte_chest_dl_get_rsrp(&ue_dl.chest); float rsrp_lin = srslte_chest_dl_get_rsrp(&ue_dl.chest);
if (isnormal(rsrp_lin)) { if (std::isnormal(rsrp_lin)) {
if (!phy->avg_rsrp) { if (!phy->avg_rsrp) {
phy->avg_rsrp = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp, snr_ema_coeff); phy->avg_rsrp = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp, snr_ema_coeff);
} else { } else {
@ -1638,7 +1656,7 @@ void phch_worker::update_measurements()
float rsrp_dbm = 10*log10(rsrp_lin) + 30 - phy->rx_gain_offset; float rsrp_dbm = 10*log10(rsrp_lin) + 30 - phy->rx_gain_offset;
// Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC // Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC
if (isnormal(rsrp_dbm)) { if (std::isnormal(rsrp_dbm)) {
if (!(tti%phy->pcell_report_period) || !phy->avg_rsrp_dbm) { if (!(tti%phy->pcell_report_period) || !phy->avg_rsrp_dbm) {
phy->avg_rsrp_dbm = rsrp_dbm; phy->avg_rsrp_dbm = rsrp_dbm;
} else { } else {
@ -1652,12 +1670,12 @@ void phch_worker::update_measurements()
} }
// Compute PL // Compute PL
float tx_crs_power = phy->config->common.pdsch_cnfg.rs_power; float tx_crs_power = phy->config->common.pdsch_cnfg.ref_sig_pwr;
phy->pathloss = tx_crs_power - phy->avg_rsrp_dbm; phy->pathloss = tx_crs_power - phy->avg_rsrp_dbm;
// Average noise // Average noise
float cur_noise = srslte_chest_dl_get_noise_estimate(&ue_dl.chest); float cur_noise = srslte_chest_dl_get_noise_estimate(&ue_dl.chest);
if (isnormal(cur_noise)) { if (std::isnormal(cur_noise)) {
if (!phy->avg_noise) { if (!phy->avg_noise) {
phy->avg_noise = cur_noise; phy->avg_noise = cur_noise;
} else { } else {

@ -43,10 +43,8 @@
#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) #define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) #define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__)
using namespace std; using namespace std;
using namespace asn1::rrc;
namespace srsue { namespace srsue {
@ -219,8 +217,8 @@ void phy::get_metrics(phy_metrics_t &m) {
workers_common.get_dl_metrics(m.dl); workers_common.get_dl_metrics(m.dl);
workers_common.get_ul_metrics(m.ul); workers_common.get_ul_metrics(m.ul);
workers_common.get_sync_metrics(m.sync); workers_common.get_sync_metrics(m.sync);
int dl_tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(m.dl.mcs), workers_common.get_nof_prb()); int dl_tbs = srslte_ra_tbs_from_idx(srslte_ra_dl_tbs_idx_from_mcs(m.dl.mcs), workers_common.get_nof_prb());
int ul_tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(m.ul.mcs), workers_common.get_nof_prb()); int ul_tbs = srslte_ra_tbs_from_idx(srslte_ra_ul_tbs_idx_from_mcs(m.ul.mcs), workers_common.get_nof_prb());
m.dl.mabr_mbps = dl_tbs/1000.0; // TBS is bits/ms - convert to mbps m.dl.mabr_mbps = dl_tbs/1000.0; // TBS is bits/ms - convert to mbps
m.ul.mabr_mbps = ul_tbs/1000.0; // TBS is bits/ms - convert to mbps m.ul.mabr_mbps = ul_tbs/1000.0; // TBS is bits/ms - convert to mbps
Info("PHY: MABR estimates. DL: %4.6f Mbps. UL: %4.6f Mbps.\n", m.dl.mabr_mbps, m.ul.mabr_mbps); Info("PHY: MABR estimates. DL: %4.6f Mbps. UL: %4.6f Mbps.\n", m.dl.mabr_mbps, m.ul.mabr_mbps);
@ -422,12 +420,12 @@ uint32_t phy::tti_to_subf(uint32_t tti) {
void phy::get_config(phy_interface_rrc::phy_cfg_t* phy_cfg) void phy::get_config(phy_interface_rrc::phy_cfg_t* phy_cfg)
{ {
memcpy(phy_cfg, &config, sizeof(phy_cfg_t)); *phy_cfg = config;
} }
void phy::set_config(phy_interface_rrc::phy_cfg_t* phy_cfg) void phy::set_config(phy_interface_rrc::phy_cfg_t* phy_cfg)
{ {
memcpy(&config, phy_cfg, sizeof(phy_cfg_t)); config = *phy_cfg;
} }
void phy::set_config_64qam_en(bool enable) void phy::set_config_64qam_en(bool enable)
@ -437,47 +435,49 @@ void phy::set_config_64qam_en(bool enable)
void phy::set_config_common(phy_interface_rrc::phy_cfg_common_t* common) void phy::set_config_common(phy_interface_rrc::phy_cfg_common_t* common)
{ {
memcpy(&config.common, common, sizeof(phy_cfg_common_t)); config.common = *common;
} }
void phy::set_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) void phy::set_config_dedicated(phys_cfg_ded_s* dedicated)
{ {
memcpy(&config.dedicated, dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT)); config.dedicated = *dedicated;
} }
void phy::set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT* tdd) void phy::set_config_tdd(tdd_cfg_s* tdd)
{ {
memcpy(&config.common.tdd_cnfg, tdd, sizeof(LIBLTE_RRC_TDD_CONFIG_STRUCT)); config.common.tdd_cnfg = *tdd;
} }
void phy::set_config_mbsfn_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) void phy::set_config_mbsfn_sib2(sib_type2_s* sib2)
{ {
if(sib2->mbsfn_subfr_cnfg_list_size > 1) { if (sib2->mbsfn_sf_cfg_list_present and sib2->mbsfn_sf_cfg_list.size() > 1) {
Warning("SIB2 has %d MBSFN subframe configs - only 1 supported\n", sib2->mbsfn_subfr_cnfg_list_size); Warning("SIB2 has %d MBSFN subframe configs - only 1 supported\n", sib2->mbsfn_sf_cfg_list.size());
} }
if(sib2->mbsfn_subfr_cnfg_list_size > 0) { if (sib2->mbsfn_sf_cfg_list_present and sib2->mbsfn_sf_cfg_list.size() > 0) {
memcpy(&config.mbsfn.mbsfn_subfr_cnfg, &sib2->mbsfn_subfr_cnfg_list[0], sizeof(LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT)); config.mbsfn.mbsfn_subfr_cnfg = sib2->mbsfn_sf_cfg_list[0];
workers_common.build_mch_table(); workers_common.build_mch_table();
} }
} }
void phy::set_config_mbsfn_sib13(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) void phy::set_config_mbsfn_sib13(sib_type13_r9_s* sib13)
{ {
memcpy(&config.mbsfn.mbsfn_notification_cnfg, &sib13->mbsfn_notification_config, sizeof(LIBLTE_RRC_MBSFN_NOTIFICATION_CONFIG_STRUCT)); config.mbsfn.mbsfn_notification_cnfg = sib13->notif_cfg_r9;
if(sib13->mbsfn_area_info_list_r9_size > 1) { if (sib13->mbsfn_area_info_list_r9.size() > 1) {
Warning("SIB13 has %d MBSFN area info elements - only 1 supported\n", sib13->mbsfn_area_info_list_r9_size); Warning("SIB13 has %d MBSFN area info elements - only 1 supported\n", sib13->mbsfn_area_info_list_r9.size());
} }
if(sib13->mbsfn_area_info_list_r9_size > 0) { if (sib13->mbsfn_area_info_list_r9.size() > 0) {
memcpy(&config.mbsfn.mbsfn_area_info, &sib13->mbsfn_area_info_list_r9[0], sizeof(LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT)); config.mbsfn.mbsfn_area_info = sib13->mbsfn_area_info_list_r9[0];
workers_common.build_mcch_table(); workers_common.build_mcch_table();
} }
} }
void phy::set_config_mbsfn_mcch(LIBLTE_RRC_MCCH_MSG_STRUCT *mcch) void phy::set_config_mbsfn_mcch(mcch_msg_s* mcch)
{ {
memcpy(&config.mbsfn.mcch, mcch, sizeof(LIBLTE_RRC_MCCH_MSG_STRUCT)); config.mbsfn.mcch = *mcch;
mac->set_mbsfn_config(config.mbsfn.mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size); mac->set_mbsfn_config(
workers_common.set_mch_period_stop(config.mbsfn.mcch.pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9); config.mbsfn.mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9.size());
workers_common.set_mch_period_stop(
config.mbsfn.mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].pmch_cfg_r9.sf_alloc_end_r9);
workers_common.set_mcch(); workers_common.set_mcch();
} }

@ -39,6 +39,8 @@
#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) #define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) #define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__)
using namespace asn1::rrc;
namespace srsue { namespace srsue {
@ -57,7 +59,7 @@ prach::~prach() {
} }
} }
void prach::init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config_, uint32_t max_prb, phy_args_t *args_, srslte::log* log_h_) void prach::init(prach_cfg_sib_s* config_, uint32_t max_prb, phy_args_t* args_, srslte::log* log_h_)
{ {
log_h = log_h_; log_h = log_h_;
config = config_; config = config_;
@ -92,14 +94,14 @@ bool prach::set_cell(srslte_cell_t cell_)
if (mem_initiated) { if (mem_initiated) {
// TODO: Check if other PRACH parameters changed // TODO: Check if other PRACH parameters changed
if (cell_.id != cell.id || !cell_initiated) { if (cell_.id != cell.id || !cell_initiated) {
memcpy(&cell, &cell_, sizeof(srslte_cell_t)); cell = cell_;
preamble_idx = -1; preamble_idx = -1;
uint32_t configIdx = config->prach_cnfg_info.prach_config_index; uint32_t configIdx = config->prach_cfg_info.prach_cfg_idx;
uint32_t rootSeq = config->root_sequence_index; uint32_t rootSeq = config->root_seq_idx;
uint32_t zeroCorrConfig = config->prach_cnfg_info.zero_correlation_zone_config; uint32_t zeroCorrConfig = config->prach_cfg_info.zero_correlation_zone_cfg;
uint32_t freq_offset = config->prach_cnfg_info.prach_freq_offset; uint32_t freq_offset = config->prach_cfg_info.prach_freq_offset;
bool highSpeed = config->prach_cnfg_info.high_speed_flag; bool highSpeed = config->prach_cfg_info.high_speed_flag;
if (6 + freq_offset > cell.nof_prb) { if (6 + freq_offset > cell.nof_prb) {
log_h->console("Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", freq_offset, cell.nof_prb); log_h->console("Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", freq_offset, cell.nof_prb);

@ -260,7 +260,6 @@ bool ue::init(all_args_t *args_) {
printf("Waiting PHY to initialize...\n"); printf("Waiting PHY to initialize...\n");
phy.wait_initialize(); phy.wait_initialize();
phy.configure_ul_params();
// Enable AGC once PHY is initialized // Enable AGC once PHY is initialized
if (args->rf.rx_gain < 0) { if (args->rf.rx_gain < 0) {

@ -24,19 +24,19 @@
* *
*/ */
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <srslte/asn1/liblte_mme.h>
#include "srslte/asn1/liblte_rrc.h"
#include "srsue/hdr/upper/nas.h" #include "srsue/hdr/upper/nas.h"
#include "srslte/common/security.h" #include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/bcd_helpers.h" #include "srslte/common/bcd_helpers.h"
#include "srslte/common/security.h"
#include <fstream>
#include <iomanip>
#include <iostream>
#include <srslte/asn1/liblte_mme.h>
#include <sstream>
#include <unistd.h>
using namespace srslte; using namespace srslte;
using namespace asn1::rrc;
namespace srsue { namespace srsue {
@ -72,8 +72,11 @@ void nas::init(usim_interface_nas *usim_,
if (!usim->get_home_plmn_id(&home_plmn)) { if (!usim->get_home_plmn_id(&home_plmn)) {
nas_log->error("Getting Home PLMN Id from USIM. Defaulting to 001-01\n"); nas_log->error("Getting Home PLMN Id from USIM. Defaulting to 001-01\n");
home_plmn.mcc = 61441; // This is 001 uint16_t mcc = 61441; // This is 001
home_plmn.mnc = 65281; // This is 01 uint16_t mnc = 65281; // This is 01
home_plmn.mcc_present = true;
srslte::mcc_to_bytes(mcc, &home_plmn.mcc[0]);
srslte::mnc_to_bytes(mnc, home_plmn.mnc);
} }
cfg = cfg_; cfg = cfg_;
@ -200,7 +203,8 @@ bool nas::is_attached() {
return state == EMM_STATE_REGISTERED; return state == EMM_STATE_REGISTERED;
} }
void nas::paging(LIBLTE_RRC_S_TMSI_STRUCT *ue_identiy) { void nas::paging(s_tmsi_s* ue_identiy)
{
if (state == EMM_STATE_REGISTERED) { if (state == EMM_STATE_REGISTERED) {
nas_log->info("Received paging: requesting RRC connection establishment\n"); nas_log->info("Received paging: requesting RRC connection establishment\n");
if (rrc_connect()) { if (rrc_connect()) {
@ -240,14 +244,14 @@ bool nas::rrc_connect() {
// Provide UE-Identity to RRC if have one // Provide UE-Identity to RRC if have one
if (have_guti) { if (have_guti) {
LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; s_tmsi_s s_tmsi;
s_tmsi.mmec = ctxt.guti.mme_code; s_tmsi.mmec.from_number(ctxt.guti.mme_code);
s_tmsi.m_tmsi = ctxt.guti.m_tmsi; s_tmsi.m_tmsi.from_number(ctxt.guti.m_tmsi);
rrc->set_ue_idenity(s_tmsi); rrc->set_ue_idenity(s_tmsi);
} }
// Set establishment cause // Set establishment cause
LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM establish_cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING; establishment_cause_e establish_cause = establishment_cause_e::mo_sig;
if (rrc->connection_request(establish_cause, dedicatedInfoNAS)) if (rrc->connection_request(establish_cause, dedicatedInfoNAS))
{ {
@ -631,9 +635,9 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
memcpy(&ctxt.guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); memcpy(&ctxt.guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT));
have_guti = true; have_guti = true;
// Update RRC UE-Idenity // Update RRC UE-Idenity
LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; s_tmsi_s s_tmsi;
s_tmsi.mmec = ctxt.guti.mme_code; s_tmsi.mmec.from_number(ctxt.guti.mme_code);
s_tmsi.m_tmsi = ctxt.guti.m_tmsi; s_tmsi.m_tmsi.from_number(ctxt.guti.m_tmsi);
rrc->set_ue_idenity(s_tmsi); rrc->set_ue_idenity(s_tmsi);
} }
if (attach_accept.lai_present) {} if (attach_accept.lai_present) {}
@ -1391,7 +1395,7 @@ void nas::send_detach_request(bool switch_off)
if (rrc->is_connected()) { if (rrc->is_connected()) {
rrc->write_sdu(pdu); rrc->write_sdu(pdu);
} else { } else {
rrc->connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING, pdu); rrc->connection_request(establishment_cause_e::mo_sig, pdu);
} }
} }

@ -33,6 +33,7 @@
#define CHECK_SIM_PIN 1 #define CHECK_SIM_PIN 1
using namespace srslte; using namespace srslte;
using namespace asn1::rrc;
namespace srsue{ namespace srsue{
@ -164,7 +165,7 @@ bool pcsc_usim::get_imei_vec(uint8_t* imei_, uint32_t n)
return true; return true;
} }
bool pcsc_usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) bool pcsc_usim::get_home_plmn_id(plmn_id_s* home_plmn_id)
{ {
if (!initiated) { if (!initiated) {
fprintf(stderr, "USIM not initiated!\n"); fprintf(stderr, "USIM not initiated!\n");
@ -174,20 +175,22 @@ bool pcsc_usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id)
uint8_t imsi_vec[15]; uint8_t imsi_vec[15];
get_imsi_vec(imsi_vec, 15); get_imsi_vec(imsi_vec, 15);
std::ostringstream mcc_str, mnc_str; std::ostringstream plmn_str;
int mcc_len = 3; int mcc_len = 3;
for (int i=0;i<mcc_len;i++) { for (int i=0;i<mcc_len;i++) {
mcc_str << (int) imsi_vec[i]; plmn_str << (int)imsi_vec[i];
} }
int mnc_len = sc.get_mnc_len(); int mnc_len = sc.get_mnc_len();
for (int i=mcc_len;i<mcc_len+mnc_len;i++) { for (int i=mcc_len;i<mcc_len+mnc_len;i++) {
mnc_str << (int) imsi_vec[i]; plmn_str << (int)imsi_vec[i];
} }
string_to_mcc(mcc_str.str(), &home_plmn_id->mcc); if (not string_to_plmn_id(*home_plmn_id, plmn_str.str())) {
string_to_mnc(mnc_str.str(), &home_plmn_id->mnc); log->error("Error reading home PLMN from SIM.\n");
return false;
}
log->info("Read Home PLMN Id=%s\n", log->info("Read Home PLMN Id=%s\n",
plmn_id_to_string(*home_plmn_id).c_str()); plmn_id_to_string(*home_plmn_id).c_str());

File diff suppressed because it is too large Load Diff

@ -30,6 +30,7 @@
#include "srslte/common/bcd_helpers.h" #include "srslte/common/bcd_helpers.h"
using namespace srslte; using namespace srslte;
using namespace asn1::rrc;
namespace srsue{ namespace srsue{
@ -161,7 +162,7 @@ bool usim::get_imei_vec(uint8_t* imei_, uint32_t n)
return true; return true;
} }
bool usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) bool usim::get_home_plmn_id(plmn_id_s* home_plmn_id)
{ {
if (!initiated) { if (!initiated) {
fprintf(stderr, "USIM not initiated!\n"); fprintf(stderr, "USIM not initiated!\n");
@ -193,8 +194,7 @@ bool usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id)
mnc_str << (int) imsi_vec[i]; mnc_str << (int) imsi_vec[i];
} }
string_to_mcc(mcc_str.str(), &home_plmn_id->mcc); string_to_plmn_id(*home_plmn_id, mcc_str.str() + mnc_str.str());
string_to_mnc(mnc_str.str(), &home_plmn_id->mnc);
usim_log->info("Read Home PLMN Id=%s\n", usim_log->info("Read Home PLMN Id=%s\n",
plmn_id_to_string(*home_plmn_id).c_str()); plmn_id_to_string(*home_plmn_id).c_str());

@ -19,5 +19,5 @@
# #
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch")
add_executable(mac_test mac_test.cc) add_executable(mac_test mac_test.cc)
target_link_libraries(mac_test srsue_mac srsue_phy srslte_common srslte_phy srslte_radio srslte_asn1 ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) target_link_libraries(mac_test srsue_mac srsue_phy srslte_common srslte_phy srslte_radio srslte_asn1 rrc_asn1 ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})

@ -28,15 +28,15 @@
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include "srslte/asn1/liblte_rrc.h" #include "srslte/asn1/rrc_asn1.h"
#include "srslte/radio/radio_multi.h"
#include "srsue/hdr/phy/phy.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"
#include "srsue/hdr/mac/mac.h"
#include "srslte/common/mac_pcap.h" #include "srslte/common/mac_pcap.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srslte/radio/radio_multi.h"
#include "srsue/hdr/mac/mac.h"
#include "srsue/hdr/phy/phy.h"
using namespace asn1::rrc;
/********************************************************************** /**********************************************************************
* Program arguments processing * Program arguments processing
@ -112,98 +112,97 @@ uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t x) {
return (period*10*(1+tti/(period*10))+x)%10240; // the 1 means next opportunity return (period*10*(1+tti/(period*10))+x)%10240; // the 1 means next opportunity
} }
void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srsue::mac *mac, srsue::phy *phy) { void setup_mac_phy_sib2(sib_type2_s* sib2, srsue::mac* mac, srsue::phy* phy)
{
// Apply RACH configuration // Apply RACH configuration
srsue::mac_interface_rrc::mac_cfg_t mac_cfg; srsue::mac_interface_rrc::mac_cfg_t mac_cfg;
mac->get_config(&mac_cfg); mac->get_config(&mac_cfg);
memcpy(&mac_cfg.rach, &sib2->rr_config_common_sib.rach_cnfg, sizeof(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT)); mac_cfg.rach = sib2->rr_cfg_common.rach_cfg_common;
mac->set_config(&mac_cfg); mac->set_config(&mac_cfg);
printf("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d, ContentionResolutionTimer=%d ms, MaxTrials=%d\n", printf("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d, ContentionResolutionTimer=%d ms, MaxTrials=%d\n",
liblte_rrc_number_of_ra_preambles_num[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles], sib2->rr_cfg_common.rach_cfg_common.preamb_info.nof_ra_preambs.to_number(),
liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size], sib2->rr_cfg_common.rach_cfg_common.ra_supervision_info.ra_resp_win_size.to_number(),
liblte_rrc_mac_contention_resolution_timer_num[sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer], sib2->rr_cfg_common.rach_cfg_common.ra_supervision_info.mac_contention_resolution_timer.to_number(),
liblte_rrc_preamble_trans_max_num[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]); sib2->rr_cfg_common.rach_cfg_common.ra_supervision_info.preamb_trans_max.to_number());
// Apply PHY RR Config Common // Apply PHY RR Config Common
srsue::phy_interface_rrc::phy_cfg_common_t common; srsue::phy_interface_rrc::phy_cfg_common_t common;
memcpy(&common.pdsch_cnfg, &sib2->rr_config_common_sib.pdsch_cnfg, sizeof(LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT)); common.pdsch_cnfg = sib2->rr_cfg_common.pdsch_cfg_common;
memcpy(&common.pusch_cnfg, &sib2->rr_config_common_sib.pusch_cnfg, sizeof(LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT)); common.pusch_cnfg = sib2->rr_cfg_common.pusch_cfg_common;
memcpy(&common.pucch_cnfg, &sib2->rr_config_common_sib.pucch_cnfg, sizeof(LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT)); common.pucch_cnfg = sib2->rr_cfg_common.pucch_cfg_common;
memcpy(&common.ul_pwr_ctrl, &sib2->rr_config_common_sib.ul_pwr_ctrl, sizeof(LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT)); common.ul_pwr_ctrl = sib2->rr_cfg_common.ul_pwr_ctrl_common;
memcpy(&common.prach_cnfg, &sib2->rr_config_common_sib.prach_cnfg, sizeof(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT)); common.prach_cnfg = sib2->rr_cfg_common.prach_cfg;
if (sib2->rr_config_common_sib.srs_ul_cnfg.present) { common.srs_ul_cnfg = sib2->rr_cfg_common.srs_ul_cfg_common;
memcpy(&common.srs_ul_cnfg, &sib2->rr_config_common_sib.srs_ul_cnfg, sizeof(LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT));
} else {
// default is release
common.srs_ul_cnfg.present = false;
}
phy->set_config_common(&common); phy->set_config_common(&common);
phy->configure_ul_params(); phy->configure_ul_params();
printf("Set PUSCH ConfigCommon: HopOffset=%d, RSGroup=%d, RSNcs=%d, N_sb=%d\n", printf("Set PUSCH ConfigCommon: HopOffset=%d, RSGroup=%d, RSNcs=%d, N_sb=%d\n",
sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset, sib2->rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.pusch_hop_offset,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch, sib2->rr_cfg_common.pusch_cfg_common.ul_ref_sigs_pusch.group_assign_pusch,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift, sib2->rr_cfg_common.pusch_cfg_common.ul_ref_sigs_pusch.cyclic_shift,
sib2->rr_config_common_sib.pusch_cnfg.n_sb); sib2->rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.n_sb);
printf("Set PUCCH ConfigCommon: DeltaShift=%d, CyclicShift=%d, N1=%d, NRB=%d\n", printf("Set PUCCH ConfigCommon: DeltaShift=%d, CyclicShift=%d, N1=%d, NRB=%d\n",
liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift], sib2->rr_cfg_common.pucch_cfg_common.delta_pucch_shift.to_number(),
sib2->rr_config_common_sib.pucch_cnfg.n_cs_an, sib2->rr_cfg_common.pucch_cfg_common.n_cs_an, sib2->rr_cfg_common.pucch_cfg_common.n1_pucch_an,
sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an, sib2->rr_cfg_common.pucch_cfg_common.n_rb_cqi);
sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi);
printf("Set PRACH ConfigCommon: SeqIdx=%d, HS=%d, FreqOffset=%d, ZC=%d, ConfigIndex=%d\n", printf("Set PRACH ConfigCommon: SeqIdx=%d, HS=%d, FreqOffset=%d, ZC=%d, ConfigIndex=%d\n",
sib2->rr_config_common_sib.prach_cnfg.root_sequence_index, sib2->rr_cfg_common.prach_cfg.root_seq_idx,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag?1:0, sib2->rr_cfg_common.prach_cfg.prach_cfg_info.high_speed_flag ? 1 : 0,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset, sib2->rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config, sib2->rr_cfg_common.prach_cfg.prach_cfg_info.zero_correlation_zone_cfg,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index); sib2->rr_cfg_common.prach_cfg.prach_cfg_info.prach_cfg_idx);
if (sib2->rr_cfg_common.srs_ul_cfg_common.type() == srs_ul_cfg_common_c::types::setup) {
srs_ul_cfg_common_c::setup_s_* setup = &sib2->rr_cfg_common.srs_ul_cfg_common.setup();
printf("Set SRS ConfigCommon: BW-Configuration=%d, SF-Configuration=%d, ACKNACK=%d\n", printf("Set SRS ConfigCommon: BW-Configuration=%d, SF-Configuration=%d, ACKNACK=%d\n",
sib2->rr_config_common_sib.srs_ul_cnfg.bw_cnfg, setup->srs_bw_cfg.to_number(), setup->srs_sf_cfg.to_number(), setup->ack_nack_srs_simul_tx ? 1 : 0);
sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg, }
sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx);
} }
void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srsue::mac *mac, srsue::phy *phy) { void process_connsetup(rrc_conn_setup_s* msg, srsue::mac* mac, srsue::phy* phy)
{
// FIXME: There's an error parsing the connectionSetup message. This value is hard-coded: // FIXME: There's an error parsing the connectionSetup message. This value is hard-coded:
if (msg->rr_cnfg.phy_cnfg_ded_present) { rr_cfg_ded_s* rr_ded = &msg->crit_exts.c1().rrc_conn_setup_r8().rr_cfg_ded;
phy->set_config_dedicated(&msg->rr_cnfg.phy_cnfg_ded); if (rr_ded->phys_cfg_ded_present) {
phy->set_config_dedicated(&rr_ded->phys_cfg_ded);
printf("Set PHY configuration: SR-n_pucch=%d, SR-ConfigIndex=%d, SRS-ConfigIndex=%d, SRS-bw=%d, SRS-Nrcc=%d, "
"SRS-hop=%d, SRS-Ncs=%d\n",
rr_ded->phys_cfg_ded.sched_request_cfg.setup().sr_pucch_res_idx,
rr_ded->phys_cfg_ded.sched_request_cfg.setup().sr_cfg_idx,
rr_ded->phys_cfg_ded.srs_ul_cfg_ded.setup().srs_cfg_idx,
rr_ded->phys_cfg_ded.srs_ul_cfg_ded.setup().srs_bw.to_number(),
rr_ded->phys_cfg_ded.srs_ul_cfg_ded.setup().freq_domain_position,
rr_ded->phys_cfg_ded.srs_ul_cfg_ded.setup().srs_hop_bw.to_number(),
rr_ded->phys_cfg_ded.srs_ul_cfg_ded.setup().cyclic_shift.to_number());
} }
printf("Set PHY configuration: SR-n_pucch=%d, SR-ConfigIndex=%d, SRS-ConfigIndex=%d, SRS-bw=%d, SRS-Nrcc=%d, SRS-hop=%d, SRS-Ncs=%d\n",
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx,
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_cnfg_idx,
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_bandwidth,
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.freq_domain_pos,
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_hopping_bandwidth,
msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.cyclic_shift);
srsue::mac_interface_rrc::mac_cfg_t mac_set; srsue::mac_interface_rrc::mac_cfg_t mac_set;
mac->get_config(&mac_set); mac->get_config(&mac_set);
memcpy(&mac_set.main, &msg->rr_cnfg.mac_main_cnfg, sizeof(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT)); mac_set.main = rr_ded->mac_main_cfg.explicit_value();
// SR is a PHY config but is needed by SR procedure in 36.321 5.4.4 // SR is a PHY config but is needed by SR procedure in 36.321 5.4.4
memcpy(&mac_set.sr, &msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg, sizeof(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT)); mac_set.sr = rr_ded->phys_cfg_ded.sched_request_cfg;
mac->set_config(&mac_set); mac->set_config(&mac_set);
printf("Set MAC configuration: dsr-TransMAX: %d, harq-MaxReTX=%d, bsr-TimerReTX=%d, bsr-TimerPeriodic=%d\n", printf("Set MAC configuration: dsr-TransMAX: %d, harq-MaxReTX=%d, bsr-TimerReTX=%d, bsr-TimerPeriodic=%d\n",
liblte_rrc_dsr_trans_max_num[msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.dsr_trans_max], rr_ded->phys_cfg_ded.sched_request_cfg.setup().dsr_trans_max.to_number(),
liblte_rrc_max_harq_tx_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx], rr_ded->mac_main_cfg.explicit_value().ul_sch_cfg.max_harq_tx.to_number(),
liblte_rrc_retransmission_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.retx_bsr_timer], rr_ded->mac_main_cfg.explicit_value().ul_sch_cfg.retx_bsr_timer.to_number(),
liblte_rrc_periodic_bsr_timer_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.periodic_bsr_timer]); rr_ded->mac_main_cfg.explicit_value().ul_sch_cfg.periodic_bsr_timer.to_number());
phy->configure_ul_params(); phy->configure_ul_params();
// Setup radio bearers // Setup radio bearers
for (uint32_t i=0;i<msg->rr_cnfg.srb_to_add_mod_list_size;i++) { for (uint32_t i = 0; i < rr_ded->srb_to_add_mod_list.size(); i++) {
if (msg->rr_cnfg.srb_to_add_mod_list[i].lc_default_cnfg_present) { if (rr_ded->srb_to_add_mod_list[i].lc_ch_cfg_present) {
printf("Setting up Default Configuration for SRB%d \n", msg->rr_cnfg.srb_to_add_mod_list[i].srb_id); printf("Setting up Default Configuration for SRB%d \n", rr_ded->srb_to_add_mod_list[i].srb_id);
switch(msg->rr_cnfg.srb_to_add_mod_list[i].srb_id) { switch (rr_ded->srb_to_add_mod_list[i].srb_id) {
case 1: case 1:
mac->setup_lcid(1, 0, 1, -1, -1); mac->setup_lcid(1, 0, 1, -1, -1);
break; break;
@ -305,27 +304,35 @@ public:
int read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) int read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes)
{ {
if (lcid == 0) { if (lcid == 0) {
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; ul_ccch_msg_s ul_ccch_msg;
// Prepare ConnectionRequest packet // Prepare ConnectionRequest packet
ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ; ul_ccch_msg.msg.set(ul_ccch_msg_type_c::types::c1);
ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE; ul_ccch_msg.msg.c1().set(ul_ccch_msg_type_c::c1_c_::types::rrc_conn_request);
ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000; ul_ccch_msg.msg.c1().rrc_conn_request().crit_exts.set(
ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING; rrc_conn_request_s::crit_exts_c_::types::rrc_conn_request_r8);
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg); ul_ccch_msg.msg.c1().rrc_conn_request().crit_exts.rrc_conn_request_r8().ue_id.set(
init_ue_id_c::types::random_value);
uint64_t uecri=0; ul_ccch_msg.msg.c1().rrc_conn_request().crit_exts.rrc_conn_request_r8().ue_id.random_value().from_number(1000);
uint8_t *ue_cri_ptr = (uint8_t*) &uecri; ul_ccch_msg.msg.c1().rrc_conn_request().crit_exts.rrc_conn_request_r8().establishment_cause =
uint32_t nbytes = bit_msg.N_bits/8; establishment_cause_e::mo_sig;
uint8_t *ptr = bit_msg.msg;
asn1::bit_ref bref(payload, nof_bytes);
ul_ccch_msg.pack(bref);
uint32_t nbytes = (uint32_t)bref.distance_bytes(payload);
// assert(nbytes<1024);
uint64_t uecri = 0;
uint8_t* ue_cri_ptr = (uint8_t*)&uecri;
uint8_t* ptr = bit_msg.msg;
for (uint32_t i=0;i<nbytes;i++) { for (uint32_t i=0;i<nbytes;i++) {
ue_cri_ptr[nbytes-i-1] = (uint8_t) srslte_bit_pack(&ptr, 8); ue_cri_ptr[nbytes - i - 1] = payload[i]; //(uint8_t) srslte_bit_pack(&ptr, 8);
} }
printf("Setting UE contention resolution ID: %lu\n", uecri); printf("Setting UE contention resolution ID: %lu\n", uecri);
mac.set_contention_id(uecri); mac.set_contention_id(uecri);
// Send ConnectionRequest Packet // Send ConnectionRequest Packet
printf("Send ConnectionRequest %d/%d bytes\n", nbytes, nof_bytes); printf("Send ConnectionRequest %d/%d bytes\n", nbytes, nof_bytes);
srslte_bit_pack_vector(bit_msg.msg, payload, nbytes*8);
bzero(&payload[nbytes], (nof_bytes-nbytes)*sizeof(uint8_t)); bzero(&payload[nbytes], (nof_bytes-nbytes)*sizeof(uint8_t));
return nof_bytes; return nof_bytes;
} else if (lcid == 1) { } else if (lcid == 1) {
@ -358,22 +365,23 @@ public:
void write_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) { void write_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) {
if (lcid == 0) { if (lcid == 0) {
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg; dl_ccch_msg_s dl_ccch_msg;
printf("ConnSetup received %d bytes\n", nof_bytes); printf("ConnSetup received %d bytes\n", nof_bytes);
srslte_vec_fprint_byte(stdout, payload, nof_bytes); srslte_vec_fprint_byte(stdout, payload, nof_bytes);
srslte_bit_unpack_vector(payload, bit_msg.msg, nof_bytes*8);
bit_msg.N_bits = nof_bytes*8; asn1::bit_ref bref(payload, nof_bytes);
liblte_rrc_unpack_dl_ccch_msg(&bit_msg, &dl_ccch_msg); dl_ccch_msg.unpack(bref);
printf("Response: %s\n", liblte_rrc_dl_ccch_msg_type_text[dl_ccch_msg.msg_type]);
switch (dl_ccch_msg.msg_type) { printf("Response: %s\n", dl_ccch_msg.msg.c1().type().to_string().c_str());
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP: switch (dl_ccch_msg.msg.c1().type().value) {
case dl_ccch_msg_type_c::c1_c_::types::rrc_conn_setup:
// Process ConnectionSetup // Process ConnectionSetup
process_connsetup(&dl_ccch_msg.msg.rrc_con_setup, &mac, &phy); process_connsetup(&dl_ccch_msg.msg.c1().rrc_conn_setup(), &mac, &phy);
connsetup_decoded = true; connsetup_decoded = true;
break; break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ: case dl_ccch_msg_type_c::c1_c_::types::rrc_conn_reject:
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST: case dl_ccch_msg_type_c::c1_c_::types::rrc_conn_reest:
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST_REJ: case dl_ccch_msg_type_c::c1_c_::types::rrc_conn_reest_reject:
break; break;
} }
} else if (lcid == 1) { } else if (lcid == 1) {
@ -386,33 +394,37 @@ public:
void write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes) void write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes)
{ {
LIBLTE_RRC_MIB_STRUCT mib; mib_s mib;
srslte_vec_fprint_byte(stdout, payload, nof_bytes); srslte_vec_fprint_byte(stdout, payload, nof_bytes);
srslte_bit_unpack_vector(payload, bit_msg.msg, nof_bytes*8);
bit_msg.N_bits = nof_bytes*8; asn1::bit_ref bref(payload, nof_bytes);
liblte_rrc_unpack_bcch_bch_msg(&bit_msg, &mib); mib.unpack(bref);
printf("MIB received %d bytes, BW=%s MHz\n", nof_bytes, liblte_rrc_dl_bandwidth_text[mib.dl_bw]);
printf("MIB received %d bytes, BW=%s MHz\n", nof_bytes, mib.dl_bw.to_string().c_str());
mib_decoded = true; mib_decoded = true;
} }
void write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes) void write_pdu_bcch_dlsch(uint8_t* payload, uint32_t nof_bytes)
{ {
LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg; bcch_dl_sch_msg_s dlsch_msg;
srslte_bit_unpack_vector(payload, bit_msg.msg, nof_bytes*8);
bit_msg.N_bits = nof_bytes*8; asn1::bit_ref bref(payload, nof_bytes);
liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg); dlsch_msg.unpack(bref);
if (dlsch_msg.N_sibs > 0) {
if (dlsch_msg.sibs[0].sib_type == LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 && !sib1_decoded) { if (dlsch_msg.msg.c1().type().value == bcch_dl_sch_msg_type_c::c1_c_::types::sib_type1) {
si_window_len = liblte_rrc_si_window_length_num[dlsch_msg.sibs[0].sib.sib1.si_window_length]; si_window_len = dlsch_msg.msg.c1().sib_type1().si_win_len.to_number();
sib2_period = liblte_rrc_si_periodicity_num[dlsch_msg.sibs[0].sib.sib1.sched_info[0].si_periodicity]; sib2_period = dlsch_msg.msg.c1().sib_type1().sched_info_list[0].si_periodicity.to_number();
printf("SIB1 received %d bytes, CellID=%d, si_window=%d, sib2_period=%d\n", printf("SIB1 received %d bytes, CellID=%d, si_window=%d, sib2_period=%d\n", nof_bytes,
nof_bytes, dlsch_msg.sibs[0].sib.sib1.cell_id&0xfff, si_window_len, sib2_period); (uint32_t)dlsch_msg.msg.c1().sib_type1().cell_access_related_info.cell_id.to_number() & 0xfff,
sib1_decoded = true; si_window_len, sib2_period);
mac.clear_rntis(); mac.clear_rntis();
} else if (dlsch_msg.sibs[0].sib_type == LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2) { } else {
sys_info_r8_ies_s::sib_type_and_info_l_& sib_list =
dlsch_msg.msg.c1().sys_info().crit_exts.sys_info_r8().sib_type_and_info;
if (sib_list.size() > 0 and sib_list[0].type() == sib_info_item_c::types::sib2) {
printf("SIB2 received %d bytes\n", nof_bytes); printf("SIB2 received %d bytes\n", nof_bytes);
setup_mac_phy_sib2(&dlsch_msg.sibs[0].sib.sib2, &mac, &phy); setup_mac_phy_sib2(&sib_list[0].sib2(), &mac, &phy);
sib2_decoded = true; sib2_decoded = true;
mac.clear_rntis(); mac.clear_rntis();
} }

@ -28,11 +28,11 @@ if(HAVE_PCSC)
endif(HAVE_PCSC) endif(HAVE_PCSC)
add_executable(rrc_reconfig_test rrc_reconfig_test.cc) add_executable(rrc_reconfig_test rrc_reconfig_test.cc)
target_link_libraries(rrc_reconfig_test srsue_upper srslte_upper srslte_phy) target_link_libraries(rrc_reconfig_test srsue_upper srslte_upper srslte_phy rrc_asn1)
add_test(rrc_reconfig_test rrc_reconfig_test) add_test(rrc_reconfig_test rrc_reconfig_test)
add_executable(nas_test nas_test.cc) add_executable(nas_test nas_test.cc)
target_link_libraries(nas_test srsue_upper srslte_upper srslte_phy) target_link_libraries(nas_test srsue_upper srslte_upper srslte_phy rrc_asn1)
add_test(nas_test nas_test) add_test(nas_test nas_test)
######################################################################## ########################################################################

@ -31,6 +31,8 @@
#define USE_RADIO #define USE_RADIO
#define PRINT_GW 0 #define PRINT_GW 0
using namespace asn1::rrc;
/********************************************************************** /**********************************************************************
* Program arguments processing * Program arguments processing
***********************************************************************/ ***********************************************************************/
@ -181,7 +183,7 @@ public:
// Instruct MAC to look for SIB2 // Instruct MAC to look for SIB2
usleep(10000); usleep(10000);
tti = mac->get_current_tti(); tti = mac->get_current_tti();
period = liblte_rrc_si_periodicity_num[sib1.sched_info[0].si_periodicity]; period = sib1.sched_info[0].si_periodicity.to_number();
si_win_start = sib_start_tti(tti, period, 0); si_win_start = sib_start_tti(tti, period, 0);
si_win_len = liblte_rrc_si_window_length_num[sib1.si_window_length]; si_win_len = liblte_rrc_si_window_length_num[sib1.si_window_length];
@ -555,7 +557,7 @@ int main(int argc, char *argv[])
} }
// Set MAC defaults // Set MAC defaults
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT default_cfg; mac_main_cfg_s default_cfg;
bzero(&default_cfg, sizeof(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT)); bzero(&default_cfg, sizeof(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT));
default_cfg.ulsch_cnfg.max_harq_tx = LIBLTE_RRC_MAX_HARQ_TX_N5; default_cfg.ulsch_cnfg.max_harq_tx = LIBLTE_RRC_MAX_HARQ_TX_N5;
default_cfg.ulsch_cnfg.periodic_bsr_timer = LIBLTE_RRC_PERIODIC_BSR_TIMER_INFINITY; default_cfg.ulsch_cnfg.periodic_bsr_timer = LIBLTE_RRC_PERIODIC_BSR_TIMER_INFINITY;

@ -41,6 +41,7 @@
using namespace srsue; using namespace srsue;
using namespace asn1::rrc;
#define LCID 1 #define LCID 1
@ -88,8 +89,9 @@ class rrc_dummy : public rrc_interface_nas
{ {
public: public:
rrc_dummy() : last_sdu_len(0) { rrc_dummy() : last_sdu_len(0) {
plmns.plmn_id.mcc = mcc; plmns.plmn_id.mcc_present = true;
plmns.plmn_id.mnc = mnc; mcc_to_bytes(mcc, plmns.plmn_id.mcc.data());
mnc_to_bytes(mnc, plmns.plmn_id.mnc);
plmns.tac = 0xffff; plmns.tac = 0xffff;
} }
void write_sdu(byte_buffer_t *sdu) void write_sdu(byte_buffer_t *sdu)
@ -107,9 +109,10 @@ public:
memcpy(found, &plmns, sizeof(found_plmn_t)); memcpy(found, &plmns, sizeof(found_plmn_t));
return 1; return 1;
}; };
void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {}; void plmn_select(plmn_id_s plmn_id){};
void set_ue_idenity(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) {} void set_ue_idenity(s_tmsi_s s_tmsi) {}
bool connection_request(LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM cause, srslte::byte_buffer_t *sdu) { bool connection_request(establishment_cause_e cause, srslte::byte_buffer_t* sdu)
{
printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); printf("NAS generated SDU (len=%d):\n", sdu->N_bytes);
last_sdu_len = sdu->N_bytes; last_sdu_len = sdu->N_bytes;
srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes);

@ -24,18 +24,28 @@
* *
*/ */
#include "srslte/asn1/liblte_mme.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/common/log_filter.h"
#include <iostream> #include <iostream>
#include <srslte/srslte.h> #include <srslte/srslte.h>
#include "srslte/common/log_filter.h"
#include "srslte/asn1/liblte_rrc.h" #define TESTASSERT(cond) \
#include "srslte/asn1/liblte_mme.h" { \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
}
using namespace asn1;
using namespace asn1::rrc;
void nas_test() { void nas_test() {
srslte::log_filter log1("NAS"); srslte::log_filter log1("NAS");
log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
uint32_t nas_message_len = 73;
uint8_t nas_message[128] = {0x27, 0x4f, 0xab, 0xef, 0x59, 0x01, 0x07, 0x42, uint8_t nas_message[128] = {0x27, 0x4f, 0xab, 0xef, 0x59, 0x01, 0x07, 0x42,
0x01, 0x49, 0x06, 0x40, 0x00, 0xf1, 0x10, 0x31, 0x01, 0x49, 0x06, 0x40, 0x00, 0xf1, 0x10, 0x31,
0x32, 0x00, 0x22, 0x52, 0x01, 0xc1, 0x05, 0x07, 0x32, 0x00, 0x22, 0x52, 0x01, 0xc1, 0x05, 0x07,
@ -46,6 +56,7 @@ void nas_test() {
0x00, 0xf1, 0x10, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x02, 0x01, 0x01, 0x00,
0x00, 0x62, 0x17, 0x2c, 0x59, 0x49, 0x64, 0x01, 0x00, 0x62, 0x17, 0x2c, 0x59, 0x49, 0x64, 0x01,
0x03}; 0x03};
uint32_t nas_message_len = sizeof(nas_message);
uint8 pd; uint8 pd;
uint8 msg_type; uint8 msg_type;
@ -93,44 +104,65 @@ void nas_test() {
} }
} }
void basic_test() { int basic_test()
{
srslte::log_filter log1("RRC"); srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
LIBLTE_BIT_MSG_STRUCT bit_buf; asn1::rrc::dl_dcch_msg_s dl_dcch_msg;
LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg;
uint8_t rrc_msg[256] = {
uint32_t rrc_message_len = 147; 0x22, 0x16, 0x95, 0xa0, 0x18, 0x00, 0x05, 0xaa, 0x50, 0x36, 0x00, 0x61, 0x08, 0x9c, 0xe3, 0x40, 0xb0, 0x84, 0x4e,
uint8_t rrc_message[256] = {0x22, 0x16, 0x95, 0xa0, 0x18, 0x00, 0x05, 0xaa, 0x71, 0xc0, 0x30, 0x84, 0x6e, 0x71, 0xe0, 0x70, 0x84, 0x6e, 0x70, 0x6c, 0x63, 0x1a, 0xc6, 0xb9, 0x8e, 0x7b, 0x1e,
0x50, 0x36, 0x00, 0x61, 0x08, 0x9c, 0xe3, 0x40, 0x84, 0xc0, 0x01, 0x24, 0x9d, 0x3e, 0xaf, 0xbd, 0x64, 0x04, 0x1d, 0x08, 0x05, 0x24, 0x19, 0x00, 0x03, 0xc4, 0x40,
0xb0, 0x84, 0x4e, 0x71, 0xc0, 0x30, 0x84, 0x6e, 0xc4, 0xc8, 0x00, 0x89, 0x48, 0x07, 0x04, 0x14, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0x30, 0x2d, 0xd9, 0xe9, 0xdd, 0xa5,
0x71, 0xe0, 0x70, 0x84, 0x6e, 0x70, 0x6c, 0x63, 0xb9, 0xd1, 0x95, 0xc9, 0xb9, 0x95, 0xd0, 0x14, 0x04, 0x38, 0x38, 0x38, 0x05, 0x78, 0x13, 0xfb, 0xfa, 0x05, 0x39,
0x1a, 0xc6, 0xb9, 0x8e, 0x7b, 0x1e, 0x84, 0xc0, 0x40, 0x2f, 0xd8, 0x03, 0xc4, 0x40, 0x00, 0x08, 0x04, 0x04, 0x00, 0x01, 0x88, 0x5c, 0xb1, 0x65, 0x25, 0x90, 0x04,
0x01, 0x24, 0x9d, 0x3e, 0xaf, 0xbd, 0x64, 0x04, 0x0d, 0xa9, 0xc0, 0x2a, 0x9a, 0x01, 0x99, 0x3b, 0x01, 0xf5, 0x12, 0xf0, 0x85, 0x0d, 0x85, 0xef, 0xc0, 0x01, 0xf2,
0x1d, 0x08, 0x05, 0x24, 0x19, 0x00, 0x03, 0xc4, 0x20, 0x60, 0x18, 0x07, 0x97, 0x09, 0x1f, 0xc3, 0x06, 0x00, 0x81, 0x00, 0x00, 0x11};
0x40, 0xc4, 0xc8, 0x00, 0x89, 0x48, 0x07, 0x04, uint32_t rrc_msg_len = sizeof(rrc_msg);
0x14, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0x30, 0x2d,
0xd9, 0xe9, 0xdd, 0xa5, 0xb9, 0xd1, 0x95, 0xc9, bit_ref bref(&rrc_msg[0], sizeof(rrc_msg));
0xb9, 0x95, 0xd0, 0x14, 0x04, 0x38, 0x38, 0x38, bit_ref bref0(&rrc_msg[0], sizeof(rrc_msg));
0x05, 0x78, 0x13, 0xfb, 0xfa, 0x05, 0x39, 0x40,
0x2f, 0xd8, 0x03, 0xc4, 0x40, 0x00, 0x08, 0x04, dl_dcch_msg.unpack(bref);
0x04, 0x00, 0x01, 0x88, 0x5c, 0xb1, 0x65, 0x25,
0x90, 0x04, 0x0d, 0xa9, 0xc0, 0x2a, 0x9a, 0x01, rrc_conn_recfg_r8_ies_s* reconf_r8 = &dl_dcch_msg.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8();
0x99, 0x3b, 0x01, 0xf5, 0x12, 0xf0, 0x85, 0x0d, TESTASSERT(reconf_r8->rr_cfg_ded_present);
0x85, 0xef, 0xc0, 0x01, 0xf2, 0x20, 0x60, 0x18, TESTASSERT(reconf_r8->rr_cfg_ded.mac_main_cfg.type().value == rr_cfg_ded_s::mac_main_cfg_c_::types::explicit_value);
0x07, 0x97, 0x09, 0x1f, 0xc3, 0x06, 0x00, 0x81, mac_main_cfg_s* mac_cfg = &reconf_r8->rr_cfg_ded.mac_main_cfg.explicit_value();
0x00, 0x00, 0x11}; TESTASSERT(mac_cfg->ext);
TESTASSERT(mac_cfg->phr_cfg_present);
srslte_bit_unpack_vector(rrc_message, bit_buf.msg, rrc_message_len*8); TESTASSERT(mac_cfg->phr_cfg.type() == setup_e::setup);
bit_buf.N_bits = rrc_message_len*8; TESTASSERT(mac_cfg->sr_prohibit_timer_r9_present);
liblte_rrc_unpack_dl_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &dl_dcch_msg); TESTASSERT(mac_cfg->sr_prohibit_timer_r9 == 0);
TESTASSERT(reconf_r8->rr_cfg_ded.phys_cfg_ded_present);
TESTASSERT(reconf_r8->rr_cfg_ded.phys_cfg_ded.pdsch_cfg_ded_present);
TESTASSERT(reconf_r8->rr_cfg_ded.phys_cfg_ded.pucch_cfg_ded_present);
TESTASSERT(reconf_r8->rr_cfg_ded.phys_cfg_ded.pusch_cfg_ded_present);
uint8_t rrc_msg2[rrc_msg_len];
bit_ref bref2(&rrc_msg2[0], rrc_msg_len);
dl_dcch_msg.pack(bref2);
//
bref = bit_ref(&rrc_msg2[0], rrc_msg_len);
dl_dcch_msg.unpack(bref);
bref = bit_ref(&rrc_msg[0], rrc_msg_len);
dl_dcch_msg.pack(bref);
uint32_t nof_bytes = (uint32_t)bref.distance_bytes(&rrc_msg[0]);
TESTASSERT(bref.distance(&rrc_msg[0]) == bref2.distance(&rrc_msg2[0]));
TESTASSERT(memcmp(rrc_msg2, rrc_msg, nof_bytes) == 0);
printf("done\n"); printf("done\n");
return 0;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
basic_test(); TESTASSERT(basic_test() == 0);
nas_test(); nas_test();
} }

Loading…
Cancel
Save