mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'next' into agpl_next
This commit is contained in:
commit
d1d38d1826
|
@ -22,8 +22,8 @@
|
|||
#ifndef SRSRAN_DYN_BITSET_H
|
||||
#define SRSRAN_DYN_BITSET_H
|
||||
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/srslog/bundled/fmt/format.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <cstdint>
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define SRSRAN_BOUNDED_VECTOR_H
|
||||
|
||||
#include "srsran/adt/detail/type_storage.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "srsran/adt/detail/type_storage.h"
|
||||
#include "srsran/adt/expected.h"
|
||||
#include "srsran/adt/pool/pool_utils.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "detail/type_storage.h"
|
||||
#include "expected.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <array>
|
||||
|
||||
namespace srsran {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#ifndef SRSRAN_EXPECTED_H
|
||||
#define SRSRAN_EXPECTED_H
|
||||
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#ifndef SRSRAN_INTERVAL_H
|
||||
#define SRSRAN_INTERVAL_H
|
||||
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/srslog/bundled/fmt/format.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define SRSRAN_MOVE_CALLBACK_H
|
||||
|
||||
#include "detail/type_storage.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
@ -69,7 +69,7 @@ public:
|
|||
constexpr empty_table_t() = default;
|
||||
R call(void* src, Args... args) const final
|
||||
{
|
||||
srsran_terminate("ERROR: bad function call (cause: function ptr is empty)");
|
||||
srsran_assertion_failure("bad function call (cause: function ptr is empty)");
|
||||
}
|
||||
void move(void* src, void* dest) const final {}
|
||||
void dtor(void* src) const final {}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define SRSRAN_OPTIONAL_H
|
||||
|
||||
#include "detail/type_storage.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
|
@ -31,6 +31,8 @@ template <typename T>
|
|||
class optional
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
optional() : has_val_(false) {}
|
||||
optional(const T& t) : has_val_(true) { storage.emplace(t); }
|
||||
optional(T&& t) : has_val_(true) { storage.emplace(std::move(t)); }
|
||||
|
|
|
@ -0,0 +1,396 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_OPTIONAL_ARRAY_H
|
||||
#define SRSRAN_OPTIONAL_ARRAY_H
|
||||
|
||||
#include "optional.h"
|
||||
#include "span.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <array>
|
||||
|
||||
namespace srsran {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Vec>
|
||||
class base_optional_span
|
||||
{
|
||||
using base_t = base_optional_span<Vec>;
|
||||
using T = typename Vec::value_type::value_type;
|
||||
|
||||
protected:
|
||||
template <typename Obj>
|
||||
class iterator_impl
|
||||
{
|
||||
using It = iterator_impl<Obj>;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = Obj;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = Obj*;
|
||||
using reference = Obj&;
|
||||
|
||||
iterator_impl() = default;
|
||||
iterator_impl(base_t* parent_, size_t idx_) : parent(parent_), idx(idx_)
|
||||
{
|
||||
if (idx < parent->vec.size() and not parent->contains(idx)) {
|
||||
++(*this);
|
||||
}
|
||||
}
|
||||
|
||||
It& operator++()
|
||||
{
|
||||
while (++idx < parent->vec.size() and not parent->contains(idx)) {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
It& operator--()
|
||||
{
|
||||
while (--idx < parent->vec.size() and not parent->contains(idx)) {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator*() { return parent->operator[](idx); }
|
||||
pointer operator->() { return &parent->operator[](idx); }
|
||||
|
||||
bool operator==(const It& other) const { return idx == other.idx and parent == other.parent; }
|
||||
bool operator!=(const It& other) const { return not(*this == other); }
|
||||
|
||||
private:
|
||||
friend base_t;
|
||||
|
||||
base_t* parent = nullptr;
|
||||
size_t idx = std::numeric_limits<size_t>::max();
|
||||
};
|
||||
|
||||
size_t nof_elems = 0;
|
||||
Vec vec;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using iterator = iterator_impl<T>;
|
||||
using const_iterator = iterator_impl<const T>;
|
||||
|
||||
// Find first position that is empty
|
||||
size_t find_first_empty(size_t start_guess = 0)
|
||||
{
|
||||
if (nof_elems == vec.size()) {
|
||||
return vec.size();
|
||||
}
|
||||
for (size_t i = start_guess; i < vec.size(); ++i) {
|
||||
if (not vec[i].has_value()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return vec.size();
|
||||
}
|
||||
|
||||
bool contains(size_t idx) const { return idx < vec.size() and vec[idx].has_value(); }
|
||||
|
||||
T& operator[](size_t idx) { return *vec[idx]; }
|
||||
const T& operator[](size_t idx) const { return *vec[idx]; }
|
||||
|
||||
bool empty() const { return nof_elems == 0; }
|
||||
size_t size() const { return nof_elems; }
|
||||
|
||||
iterator begin() { return iterator{this, 0}; }
|
||||
iterator end() { return iterator{this, vec.size()}; }
|
||||
const_iterator begin() const { return const_iterator{this, 0}; }
|
||||
const_iterator end() const { return const_iterator{this, vec.size()}; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
this->nof_elems = 0;
|
||||
for (auto& e : *this) {
|
||||
e.reset();
|
||||
}
|
||||
}
|
||||
void erase(size_t idx)
|
||||
{
|
||||
srsran_assert(idx < this->vec.size(), "Out-of-bounds access to array: %zd>=%zd", idx, this->vec.size());
|
||||
if (this->contains(idx)) {
|
||||
this->nof_elems--;
|
||||
this->vec[idx].reset();
|
||||
}
|
||||
}
|
||||
void erase(iterator it) { erase(it.idx); }
|
||||
|
||||
template <typename U>
|
||||
void insert(size_t idx, U&& u)
|
||||
{
|
||||
srsran_assert(idx < this->vec.size(), "Out-of-bounds access to array: %zd>=%zd", idx, this->vec.size());
|
||||
this->nof_elems += this->contains(idx) ? 0 : 1;
|
||||
this->vec[idx] = std::forward<U>(u);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Vec>
|
||||
class base_optional_vector : public base_optional_span<Vec>
|
||||
{
|
||||
using base_t = base_optional_span<Vec>;
|
||||
|
||||
public:
|
||||
using value_type = typename base_optional_span<Vec>::value_type;
|
||||
using iterator = typename base_optional_span<Vec>::iterator;
|
||||
using const_iterator = typename base_optional_span<Vec>::const_iterator;
|
||||
|
||||
base_optional_vector() = default;
|
||||
base_optional_vector(const base_optional_vector&) = default;
|
||||
base_optional_vector(base_optional_vector&& other) noexcept : base_t::vec(std::move(other.vec)),
|
||||
base_t::nof_elems(other.nof_elems)
|
||||
{
|
||||
other.nof_elems = 0;
|
||||
}
|
||||
base_optional_vector& operator=(const base_optional_vector&) = default;
|
||||
base_optional_vector& operator =(base_optional_vector&& other) noexcept
|
||||
{
|
||||
this->vec = std::move(other.vec);
|
||||
this->nof_elems = other.nof_elems;
|
||||
this->nof_elems = 0;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Array of optional items. The iteration is in order of indexes and correctly skips non-present items
|
||||
* Pointer/References/Iterators remain valid throughout the object lifetime
|
||||
* NOTE: The sorted iteration and pointer validation guarantees add some overhead if the array is very fragmented
|
||||
* @tparam T type of objects
|
||||
* @tparam N static size of max nof items
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
class optional_array : public detail::base_optional_vector<std::array<optional<T>, N> >
|
||||
{};
|
||||
|
||||
/**
|
||||
* Contrarily to optional_array, this class may allocate and cause pointer/reference/iterator invalidation.
|
||||
* However, the indexes will remain valid.
|
||||
* @tparam T
|
||||
*/
|
||||
template <typename T>
|
||||
class optional_vector : public detail::base_optional_vector<std::vector<optional<T> > >
|
||||
{
|
||||
using base_t = detail::base_optional_vector<std::vector<optional<T> > >;
|
||||
|
||||
public:
|
||||
/// May allocate and cause pointer invalidation
|
||||
template <typename U>
|
||||
void insert(size_t idx, U&& u)
|
||||
{
|
||||
if (idx >= this->vec.size()) {
|
||||
this->vec.resize(idx + 1);
|
||||
}
|
||||
base_t::insert(idx, std::forward<U>(u));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class optional_span : public detail::base_optional_span<srsran::span<optional<T> > >
|
||||
{
|
||||
using base_t = detail::base_optional_span<srsran::span<optional<T> > >;
|
||||
|
||||
public:
|
||||
template <size_t N>
|
||||
optional_span(const optional_array<T, N>& ar) : base_t::vec(ar)
|
||||
{}
|
||||
optional_span(const optional_vector<T>& ar) : base_t::vec(ar) {}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
class base_split_optional_span
|
||||
{
|
||||
protected:
|
||||
using presence_type = typename std::conditional<std::is_const<T>::value, const bool, bool>::type;
|
||||
|
||||
T* ptr = nullptr;
|
||||
presence_type* present_ptr = nullptr;
|
||||
size_t len = 0;
|
||||
|
||||
template <typename Obj>
|
||||
class iterator_impl
|
||||
{
|
||||
using It = iterator_impl<Obj>;
|
||||
using Parent = typename std::
|
||||
conditional<std::is_const<Obj>::value, const base_split_optional_span<T>, base_split_optional_span<T> >::type;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = Obj;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = Obj*;
|
||||
using reference = Obj&;
|
||||
|
||||
iterator_impl() = default;
|
||||
iterator_impl(Parent* parent_, size_t idx_) : parent(parent_), idx(idx_)
|
||||
{
|
||||
if (idx < parent->len and not parent->contains(idx)) {
|
||||
++(*this);
|
||||
}
|
||||
}
|
||||
|
||||
It& operator++()
|
||||
{
|
||||
while (++idx < parent->len and not parent->contains(idx)) {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
It& operator--()
|
||||
{
|
||||
while (--idx < parent->len and not parent->contains(idx)) {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator*() { return parent->operator[](idx); }
|
||||
pointer operator->() { return &parent->operator[](idx); }
|
||||
|
||||
bool operator==(const It& other) const { return idx == other.idx and parent == other.parent; }
|
||||
bool operator!=(const It& other) const { return not(*this == other); }
|
||||
|
||||
size_t get_idx() const { return idx; }
|
||||
|
||||
private:
|
||||
Parent* parent = nullptr;
|
||||
size_t idx = std::numeric_limits<size_t>::max();
|
||||
};
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using iterator = iterator_impl<T>;
|
||||
using const_iterator = iterator_impl<const T>;
|
||||
|
||||
constexpr base_split_optional_span() = default;
|
||||
template <std::size_t N>
|
||||
constexpr base_split_optional_span(value_type (&arr)[N], presence_type (&present)[N]) noexcept : ptr(arr),
|
||||
present_ptr(present),
|
||||
len(N)
|
||||
{}
|
||||
constexpr base_split_optional_span(value_type* arr, presence_type* present, size_t N) :
|
||||
ptr(arr), present_ptr(present), len(N)
|
||||
{}
|
||||
|
||||
bool contains(size_t idx) const { return idx < len and present_ptr[idx]; }
|
||||
bool empty() const
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (present_ptr[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
size_t c = 0;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
c += present_ptr[i] ? 1 : 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
size_t capacity() const { return len; }
|
||||
|
||||
const T& operator[](size_t idx) const { return ptr[idx]; }
|
||||
T& operator[](size_t idx) { return ptr[idx]; }
|
||||
const T& at(size_t idx) const
|
||||
{
|
||||
srsran_assert(contains(idx), "Access to inexistent element of index=%zd", idx);
|
||||
return ptr[idx];
|
||||
}
|
||||
T& at(size_t idx)
|
||||
{
|
||||
srsran_assert(this->contains(idx), "Access to inexistent element of index=%zd", idx);
|
||||
return this->ptr[idx];
|
||||
}
|
||||
|
||||
const_iterator begin() const { return const_iterator(this, 0); }
|
||||
const_iterator end() const { return const_iterator(this, len); }
|
||||
iterator begin() { return iterator(this, 0); }
|
||||
iterator end() { return iterator(this, this->len); }
|
||||
|
||||
// Find first position that is empty
|
||||
size_t find_first_empty(size_t start_guess = 0) { return begin().get_idx(); }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
class split_optional_span : public detail::base_split_optional_span<T>
|
||||
{
|
||||
using base_t = detail::base_split_optional_span<T>;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using const_iterator = typename base_t::const_iterator;
|
||||
using iterator = typename base_t::iterator;
|
||||
|
||||
using base_t::base_t;
|
||||
|
||||
template <typename U>
|
||||
void insert(size_t idx, U&& u)
|
||||
{
|
||||
srsran_assert(idx < this->len, "Out-of-bounds access to array: %zd>=%zd", idx, this->len);
|
||||
this->present_ptr[idx] = true;
|
||||
this->ptr[idx] = std::forward<U>(u);
|
||||
}
|
||||
void erase(size_t idx)
|
||||
{
|
||||
srsran_assert(idx < this->len, "Out-of-bounds access to array: %zd>=%zd", idx, this->len);
|
||||
this->present_ptr[idx] = false;
|
||||
}
|
||||
void erase(iterator it) { erase(it.get_idx()); }
|
||||
void clear()
|
||||
{
|
||||
for (size_t i = 0; i < this->len; ++i) {
|
||||
this->present_ptr[i] = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename U>
|
||||
class split_optional_span<const U> : public detail::base_split_optional_span<const U>
|
||||
{
|
||||
using base_t = detail::base_split_optional_span<const U>;
|
||||
using presence_type = typename base_t::presence_type;
|
||||
|
||||
public:
|
||||
using value_type = const U;
|
||||
using const_iterator = typename base_t::const_iterator;
|
||||
|
||||
using base_t::base_t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
split_optional_span<T>
|
||||
make_optional_span(T* array,
|
||||
typename std::conditional<std::is_const<T>::value, const bool, bool>::type* present,
|
||||
size_t N)
|
||||
{
|
||||
return split_optional_span<T>(array, present, N);
|
||||
}
|
||||
template <typename T, size_t N>
|
||||
split_optional_span<T>
|
||||
make_optional_span(T (&array)[N],
|
||||
typename std::conditional<std::is_const<T>::value, const bool, bool>::type (&present)[N])
|
||||
{
|
||||
return split_optional_span<T>(array, present);
|
||||
}
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_OPTIONAL_ARRAY_H
|
|
@ -24,8 +24,8 @@
|
|||
|
||||
#include "memblock_cache.h"
|
||||
#include "pool_utils.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/common/thread_pool.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define SRSRAN_LINEAR_ALLOCATOR_H
|
||||
|
||||
#include "pool_utils.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#ifndef SRSASN_COMMON_UTILS_H
|
||||
#define SRSASN_COMMON_UTILS_H
|
||||
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define SRSRAN_SLOT_POINT_H
|
||||
|
||||
#include "srsran/adt/interval.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
#define SRSRAN_TEST_COMMON_H
|
||||
|
||||
#include "srsran/config.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "srsran/common/buffer_pool.h"
|
||||
#include "srsran/common/crash_handler.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/common/standard_streams.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include <atomic>
|
||||
|
@ -168,20 +168,6 @@ inline void copy_msg_to_buffer(unique_byte_buffer_t& pdu, const_byte_span msg)
|
|||
|
||||
#define TESTERROR(fmt, ...) CONDERROR(true, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define TESTASSERT(cond) srsran_assert((cond), "Fail at \"%s\"", (#cond))
|
||||
|
||||
#else // if C
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define TESTASSERT(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
printf("[%s][Line %d] Fail at \"%s\"\n", __FUNCTION__, __LINE__, (#cond)); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // SRSRAN_TEST_COMMON_H
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
|
||||
#include "srsran/adt/interval.h"
|
||||
#include "srsran/common/common.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
|
|
|
@ -165,6 +165,15 @@ public:
|
|||
|
||||
// TODO: Support the following configurations
|
||||
// bool do_rohc;
|
||||
|
||||
bool operator==(const pdcp_config_t& other) const
|
||||
{
|
||||
return bearer_id == other.bearer_id and rb_type == other.rb_type and tx_direction == other.tx_direction and
|
||||
rx_direction == other.rx_direction and sn_len == other.sn_len and hdr_len_bytes == other.hdr_len_bytes and
|
||||
t_reordering == other.t_reordering and discard_timer == other.discard_timer and rat == other.rat and
|
||||
status_report_required == other.status_report_required;
|
||||
}
|
||||
bool operator!=(const pdcp_config_t& other) const { return not(*this == other); }
|
||||
};
|
||||
|
||||
// Specifies in which direction security (integrity and ciphering) are enabled for PDCP
|
||||
|
|
|
@ -286,7 +286,7 @@ SRSRAN_API int srsran_dci_nr_dl_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_
|
|||
|
||||
/**
|
||||
* @brief Packs an UL NR DCI into a DCI message
|
||||
* @param q NR DCI object with precomputed DCI parameters
|
||||
* @param q NR DCI object with precomputed DCI parameters (not required for RAR type, set to NULL)
|
||||
* @param dci UL NR DCI to pack (serialize)
|
||||
* @param[out] msg resultant DCI message
|
||||
* @return SRSRAN_SUCCESS if provided arguments are valid, SRSRAN_ERROR code otherwise
|
||||
|
@ -295,7 +295,7 @@ SRSRAN_API int srsran_dci_nr_ul_pack(const srsran_dci_nr_t* q, const srsran_dci_
|
|||
|
||||
/**
|
||||
* @brief Unpacks an NR DCI message into an UL NR DCI
|
||||
* @param q NR DCI object with precomputed DCI parameters
|
||||
* @param q NR DCI object with precomputed DCI parameters (not required for RAR type, set to NULL)
|
||||
* @param msg DCI message to unpack (deserialize)
|
||||
* @param[out] dci Resultant unpacked UL DCI
|
||||
* @return SRSRAN_SUCCESS if provided arguments are valid, SRSRAN_ERROR code otherwise
|
||||
|
@ -309,7 +309,7 @@ SRSRAN_API int srsran_dci_nr_ul_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_
|
|||
* @param str_len Destination string length
|
||||
* @return The number of written characters
|
||||
*/
|
||||
SRSRAN_API int srsran_dci_ctx_to_str(const srsran_dci_ctx_t* ctx, char* str, uint32_t str_len);
|
||||
SRSRAN_API uint32_t srsran_dci_ctx_to_str(const srsran_dci_ctx_t* ctx, char* str, uint32_t str_len);
|
||||
|
||||
/**
|
||||
* @brief Stringifies a DL NR DCI structure
|
||||
|
@ -319,8 +319,10 @@ SRSRAN_API int srsran_dci_ctx_to_str(const srsran_dci_ctx_t* ctx, char* str, uin
|
|||
* @param str_len Destination string length
|
||||
* @return The number of written characters
|
||||
*/
|
||||
SRSRAN_API int
|
||||
srsran_dci_dl_nr_to_str(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len);
|
||||
SRSRAN_API uint32_t srsran_dci_dl_nr_to_str(const srsran_dci_nr_t* q,
|
||||
const srsran_dci_dl_nr_t* dci,
|
||||
char* str,
|
||||
uint32_t str_len);
|
||||
|
||||
/**
|
||||
* @brief Stringifies an UL NR DCI structure
|
||||
|
@ -330,7 +332,9 @@ srsran_dci_dl_nr_to_str(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci,
|
|||
* @param str_len Destination string length
|
||||
* @return The number of written characters
|
||||
*/
|
||||
SRSRAN_API int
|
||||
srsran_dci_ul_nr_to_str(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len);
|
||||
SRSRAN_API uint32_t srsran_dci_ul_nr_to_str(const srsran_dci_nr_t* q,
|
||||
const srsran_dci_ul_nr_t* dci,
|
||||
char* str,
|
||||
uint32_t str_len);
|
||||
|
||||
#endif // SRSRAN_DCI_NR_H
|
||||
|
|
|
@ -53,6 +53,7 @@ typedef struct {
|
|||
|
||||
/**
|
||||
* @brief Uplink Control Information bits configuration for PUSCH transmission
|
||||
* @attention Set nof_layers, nof_re or R to 0 to indicate this structure is not initialised.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t l0; ///< First OFDM symbol that does not carry DMRS of the PUSCH, after the first DMRS symbol(s)
|
||||
|
@ -62,12 +63,12 @@ typedef struct {
|
|||
uint32_t K_sum; ///< Sum of UL-SCH code block sizes, set to zero if no UL-SCH
|
||||
srsran_mod_t modulation; ///< Modulation for the PUSCH
|
||||
uint32_t nof_layers; ///< Number of layers for PUSCH
|
||||
uint32_t nof_re; ///< Total number of resource elements allocated for the grant
|
||||
float R; ///< Code rate of the PUSCH
|
||||
float alpha; ///< Higher layer parameter scaling
|
||||
float beta_harq_ack_offset;
|
||||
float beta_csi1_offset;
|
||||
float beta_csi2_offset;
|
||||
uint32_t nof_re;
|
||||
bool csi_part2_present;
|
||||
} srsran_uci_nr_pusch_cfg_t;
|
||||
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
#include "srsran/adt/intrusive_list.h"
|
||||
#include "srsran/common/buffer_pool.h"
|
||||
#include "srsran/common/common.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/common/task_scheduler.h"
|
||||
#include "srsran/common/timeout.h"
|
||||
#include "srsran/interfaces/pdcp_interface_types.h"
|
||||
#include "srsran/rlc/rlc_am_base.h"
|
||||
#include "srsran/rlc/rlc_common.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
#include "srsran/upper/byte_buffer_queue.h"
|
||||
#include <deque>
|
||||
#include <list>
|
||||
|
|
|
@ -22,38 +22,54 @@
|
|||
#ifndef SRSRAN_ASSERT_H
|
||||
#define SRSRAN_ASSERT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include <cstdio>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define srsran_unlikely(expr) __builtin_expect(!!(expr), 0)
|
||||
|
||||
#define srsran_terminate(fmt, ...) \
|
||||
srslog::flush(); \
|
||||
std::fprintf(stderr, "%s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
|
||||
std::abort()
|
||||
/**
|
||||
* Command to terminate srsRAN application with an error message, ensuring first that the log is flushed
|
||||
*/
|
||||
[[gnu::noinline, noreturn]] inline bool srsran_terminate(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
srslog::flush();
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
#ifdef ASSERTS_ENABLED
|
||||
#define srsran_assertion_failure(fmt, ...) \
|
||||
srsran_terminate("%s:%d: Assertion Failure: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Macro that asserts condition is true. If false, it logs the remaining parameters, prints the backtrace and closes
|
||||
* the application
|
||||
* Macro that asserts condition is true. If false, it logs the remaining macro args, flushes the log,
|
||||
* prints the backtrace (if it was activated) and closes the application.
|
||||
*/
|
||||
#define srsran_assert(condition, fmt, ...) \
|
||||
do { \
|
||||
if (srsran_unlikely(not(condition))) { \
|
||||
srsran_terminate(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define srsran_always_assert(condition, fmt, ...) (void)((condition) || srsran_assertion_failure(fmt, ##__VA_ARGS__))
|
||||
|
||||
#define SRSRAN_IS_DEFINED(x) SRSRAN_IS_DEFINED2(x)
|
||||
#define SRSRAN_IS_DEFINED2(x) (#x[0] == 0 || (#x[0] >= '1' && #x[0] <= '9'))
|
||||
|
||||
/**
|
||||
* Same as "srsran_always_assert" but it is only active when "enable_check" flag is defined
|
||||
*/
|
||||
#define srsran_assert_ifdef(enable_check, condition, fmt, ...) \
|
||||
(void)((not SRSRAN_IS_DEFINED(enable_check)) || (srsran_always_assert(condition, fmt, ##__VA_ARGS__), 0))
|
||||
|
||||
/**
|
||||
* Specialization of "srsran_assert_ifdef" for the ASSERTS_ENABLED flag
|
||||
*/
|
||||
#define srsran_assert(condition, fmt, ...) srsran_assert_ifdef(ASSERTS_ENABLED, condition, fmt, ##__VA_ARGS__)
|
||||
|
||||
#ifdef STOP_ON_WARNING
|
||||
|
||||
/**
|
||||
* Macro that verifies if condition is true. If false, and STOP_ON_WARNING is true, it behaves like srsran_assert.
|
||||
* If STOP_ON_WARNING is false, it logs a warning.
|
||||
*/
|
||||
#define srsran_expect(condition, fmt, ...) srsran_assert(condition, fmt, ##__VA_ARGS__)
|
||||
|
||||
#else // STOP_ON_WARNING
|
||||
#else
|
||||
|
||||
#define srsran_expect(condition, fmt, ...) \
|
||||
do { \
|
||||
|
@ -62,16 +78,20 @@
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // STOP_ON_WARNING
|
||||
#endif
|
||||
|
||||
#else // ASSERTS_ENABLED
|
||||
#else // __ifcplusplus
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#ifdef ASSERTS_ENABLED
|
||||
#define srsran_assert(condition, fmt, ...) (void)((condition) || (__assert(#condition, __FILE__, __FLAG__), 0))
|
||||
#else
|
||||
#define srsran_assert(condition, fmt, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#define srsran_expect(condition, fmt, ...) srsran_assert(condition, fmt, ##__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // __ifcplusplus
|
||||
|
||||
#endif // SRSRAN_ASSERT_H
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_SRSRAN_TEST_H
|
||||
#define SRSRAN_SRSRAN_TEST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "srsran_assert.h"
|
||||
|
||||
namespace srsran {
|
||||
namespace detail {
|
||||
|
||||
template <typename T, typename U>
|
||||
[[gnu::noinline, noreturn]] void assert_eq_failure(const T& expected_val, const U& actual_val)
|
||||
{
|
||||
std::string s = fmt::format("Actual value '{}' differs from expected '{}'", actual_val, expected_val);
|
||||
srsran_assertion_failure("%s", s.c_str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[gnu::noinline, noreturn]] void assert_neq_failure(const T& actual_val)
|
||||
{
|
||||
std::string s = fmt::format("Value should not be equal to '{}'", actual_val);
|
||||
srsran_assertion_failure("%s", s.c_str());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace srsran
|
||||
|
||||
#define TESTASSERT_EQ(EXPECTED, ACTUAL) \
|
||||
(void)((EXPECTED == ACTUAL) || (::srsran::detail::assert_eq_failure(EXPECTED, ACTUAL), 0))
|
||||
|
||||
#define TESTASSERT_NEQ(EXPECTED, ACTUAL) \
|
||||
(void)((EXPECTED != ACTUAL) || (::srsran::detail::assert_neq_failure(ACTUAL), 0))
|
||||
|
||||
#define TESTASSERT(cond) srsran_assert((cond), "Fail at \"%s\"", (#cond))
|
||||
|
||||
#define TESTASSERT_SUCCESS(cond) srsran_assert((cond == SRSRAN_SUCCESS), "Operation \"%s\" was not successful", (#cond))
|
||||
|
||||
#else // __cplusplus
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define TESTASSERT(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
printf("[%s][Line %d] Fail at \"%s\"\n", __FUNCTION__, __LINE__, (#cond)); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // SRSRAN_SRSRAN_TEST_H
|
|
@ -43,7 +43,7 @@ phy_cfg_nr_default_t::reference_cfg_t::reference_cfg_t(const std::string& args)
|
|||
|
||||
// Skip if size is invalid
|
||||
if (param.size() != 2) {
|
||||
srsran_terminate("Invalid reference argument '%s'", e.c_str());
|
||||
srsran_assertion_failure("Invalid reference argument '%s'", e.c_str());
|
||||
}
|
||||
|
||||
if (param.front() == "carrier") {
|
||||
|
@ -68,7 +68,7 @@ phy_cfg_nr_default_t::reference_cfg_t::reference_cfg_t(const std::string& args)
|
|||
}
|
||||
srsran_assert(pdsch != R_PDSCH_COUNT, "Invalid PDSCH reference configuration '%s'", param.back().c_str());
|
||||
} else {
|
||||
srsran_terminate("Invalid %s reference component", param.front().c_str());
|
||||
srsran_assertion_failure("Invalid %s reference component", param.front().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,6 +148,10 @@ void phy_cfg_nr_default_t::make_pdcch_custom_common_ss(srsran_pdcch_cfg_nr_t& pd
|
|||
pdcch.search_space[1].nof_candidates[L] =
|
||||
SRSRAN_MIN(2, srsran_pdcch_nr_max_candidates_coreset(&pdcch.coreset[1], L));
|
||||
}
|
||||
|
||||
pdcch.ra_search_space_present = true;
|
||||
pdcch.ra_search_space = pdcch.search_space[1];
|
||||
pdcch.ra_search_space.type = srsran_search_space_type_common_1;
|
||||
}
|
||||
|
||||
void phy_cfg_nr_default_t::make_pdsch_default(srsran_sch_hl_cfg_nr_t& pdsch)
|
||||
|
@ -221,7 +225,7 @@ void make_nzp_csi_rs_ts38101_table_5_2_1(const srsran_carrier_nr_t& carrier, srs
|
|||
res3.periodicity.offset = 21;
|
||||
res4.periodicity.offset = 21;
|
||||
} else {
|
||||
srsran_terminate("Invalid subcarrier spacing %d kHz", 15U << (uint32_t)carrier.scs);
|
||||
srsran_assertion_failure("Invalid subcarrier spacing %d kHz", 15U << (uint32_t)carrier.scs);
|
||||
}
|
||||
|
||||
res1.resource_mapping.freq_band = {0, carrier.nof_prb};
|
||||
|
@ -379,7 +383,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
|
|||
make_carrier_custom_20MHz(carrier);
|
||||
break;
|
||||
case reference_cfg_t::R_CARRIER_COUNT:
|
||||
srsran_terminate("Invalid carrier reference");
|
||||
srsran_assertion_failure("Invalid carrier reference");
|
||||
}
|
||||
|
||||
switch (reference_cfg.tdd) {
|
||||
|
@ -390,7 +394,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
|
|||
make_tdd_fr1_15_1(tdd);
|
||||
break;
|
||||
case reference_cfg_t::R_TDD_COUNT:
|
||||
srsran_terminate("Invalid TDD reference");
|
||||
srsran_assertion_failure("Invalid TDD reference");
|
||||
}
|
||||
|
||||
switch (reference_cfg.pdcch) {
|
||||
|
@ -407,7 +411,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
|
|||
make_pdsch_2_1_1_tdd(carrier, pdsch);
|
||||
break;
|
||||
case reference_cfg_t::R_PDSCH_COUNT:
|
||||
srsran_terminate("Invalid PDSCH reference configuration");
|
||||
srsran_assertion_failure("Invalid PDSCH reference configuration");
|
||||
}
|
||||
|
||||
switch (reference_cfg.pusch) {
|
||||
|
|
|
@ -102,8 +102,7 @@ void pdcp::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu)
|
|||
int pdcp::add_bearer(uint32_t lcid, pdcp_config_t cfg)
|
||||
{
|
||||
if (valid_lcid(lcid)) {
|
||||
logger.error("Bearer %s already configured.", rrc->get_rb_name(lcid));
|
||||
return SRSRAN_ERROR;
|
||||
return pdcp_array[lcid]->configure(cfg) ? SRSRAN_SUCCESS : SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
std::unique_ptr<pdcp_entity_base> entity;
|
||||
|
|
|
@ -60,6 +60,15 @@ pdcp_entity_lte::~pdcp_entity_lte()
|
|||
|
||||
bool pdcp_entity_lte::configure(const pdcp_config_t& cnfg_)
|
||||
{
|
||||
if (active) {
|
||||
// Already configured
|
||||
if (cnfg_ != cfg) {
|
||||
logger.error("Bearer reconfiguration not supported. LCID=%d.", rrc->get_rb_name(lcid));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
cfg = cnfg_;
|
||||
maximum_pdcp_sn = (1u << cfg.sn_len) - 1u;
|
||||
st.last_submitted_pdcp_rx_sn = maximum_pdcp_sn;
|
||||
|
|
|
@ -52,6 +52,15 @@ void pdcp_entity_nr::reestablish()
|
|||
|
||||
bool pdcp_entity_nr::configure(const pdcp_config_t& cnfg_)
|
||||
{
|
||||
if (active) {
|
||||
// Already configured
|
||||
if (cnfg_ != cfg) {
|
||||
logger.error("Bearer reconfiguration not supported. LCID=%d.", rrc->get_rb_name(lcid));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
cfg = cnfg_;
|
||||
window_size = 1 << (cfg.sn_len - 1);
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/srsran.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include <complex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/ch_estimation/csi_rs.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
|
||||
static srsran_carrier_nr_t carrier = {};
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/ch_estimation/csi_rs.h"
|
||||
#include "srsran/phy/utils/vector.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include <getopt.h>
|
||||
#include <srsran/srsran.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/ch_estimation/dmrs_pdcch.h"
|
||||
#include "srsran/phy/phch/pdcch_nr.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include <complex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/ch_estimation/dmrs_sch.h"
|
||||
#include "srsran/phy/phch/ra_dl_nr.h"
|
||||
#include "srsran/srsran.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include <complex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/fec/block/block.h"
|
||||
#include "srsran/phy/utils/debug.h"
|
||||
#include "srsran/phy/utils/random.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include <memory.h>
|
||||
#include <srsran/phy/utils/vector.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
*/
|
||||
|
||||
#include "polar_interleaver_gold.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/fec/polar/polar_interleaver.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
|
|
@ -224,7 +224,8 @@ static int dci_nr_format_0_0_pack(const srsran_dci_nr_t* q, const srsran_dci_ul_
|
|||
msg->ctx = dci->ctx;
|
||||
|
||||
// Check RNTI type
|
||||
if (rnti_type != srsran_rnti_type_c && rnti_type != srsran_rnti_type_cs && rnti_type != srsran_rnti_type_mcs_c) {
|
||||
if (rnti_type != srsran_rnti_type_c && rnti_type != srsran_rnti_type_cs && rnti_type != srsran_rnti_type_mcs_c &&
|
||||
rnti_type != srsran_rnti_type_tc) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
|
@ -294,7 +295,8 @@ static int dci_nr_format_0_0_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_
|
|||
uint32_t N_UL_BWP_RB = SRSRAN_SEARCH_SPACE_IS_COMMON(ss_type) ? q->cfg.bwp_ul_initial_bw : q->cfg.bwp_ul_active_bw;
|
||||
|
||||
// Check RNTI type
|
||||
if (rnti_type != srsran_rnti_type_c && rnti_type != srsran_rnti_type_cs && rnti_type != srsran_rnti_type_mcs_c) {
|
||||
if (rnti_type != srsran_rnti_type_c && rnti_type != srsran_rnti_type_cs && rnti_type != srsran_rnti_type_mcs_c &&
|
||||
rnti_type != srsran_rnti_type_tc) {
|
||||
ERROR("Unsupported %s", srsran_rnti_type_str(rnti_type));
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
@ -356,7 +358,7 @@ static int dci_nr_format_0_0_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_
|
|||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int dci_nr_format_0_0_to_str(const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len)
|
||||
static uint32_t dci_nr_format_0_0_to_str(const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
|
@ -715,7 +717,7 @@ static int dci_nr_format_0_1_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_
|
|||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
static uint32_t
|
||||
dci_nr_format_0_1_to_str(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
@ -820,6 +822,112 @@ dci_nr_format_0_1_to_str(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci
|
|||
return len;
|
||||
}
|
||||
|
||||
static uint32_t dci_nr_rar_sizeof()
|
||||
{
|
||||
// Fields described by TS 38.213 Table 8.2-1: Random Access Response Grant Content field size
|
||||
uint32_t count = 0;
|
||||
|
||||
// Frequency hopping flag - 1 bit
|
||||
count += 1;
|
||||
|
||||
// PUSCH frequency resource allocation - 14 bits
|
||||
count += 14;
|
||||
|
||||
// PUSCH time resource allocation - 4 bits
|
||||
count += 4;
|
||||
|
||||
// MCS - 4 bits
|
||||
count += 4;
|
||||
|
||||
// TPC command for PUSCH - 3 bits
|
||||
count += 3;
|
||||
|
||||
// CSI request - 1 bits
|
||||
count += 1;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int dci_nr_rar_pack(const srsran_dci_ul_nr_t* dci, srsran_dci_msg_nr_t* msg)
|
||||
{
|
||||
// Fields described by TS 38.213 Table 8.2-1: Random Access Response Grant Content field size
|
||||
uint8_t* y = msg->payload;
|
||||
|
||||
// Frequency hopping flag - 1 bit
|
||||
srsran_bit_unpack(dci->freq_hopping_flag, &y, 1);
|
||||
|
||||
// PUSCH frequency resource allocation - 14 bits
|
||||
srsran_bit_unpack(dci->freq_domain_assigment, &y, 14);
|
||||
|
||||
// PUSCH time resource allocation - 4 bits
|
||||
srsran_bit_unpack(dci->time_domain_assigment, &y, 4);
|
||||
|
||||
// MCS - 4 bits
|
||||
srsran_bit_unpack(dci->mcs, &y, 4);
|
||||
|
||||
// TPC command for PUSCH - 3 bits
|
||||
srsran_bit_unpack(dci->tpc, &y, 3);
|
||||
|
||||
// CSI request - 1 bits
|
||||
srsran_bit_unpack(dci->csi_request, &y, 1);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int dci_nr_rar_unpack(srsran_dci_msg_nr_t* msg, srsran_dci_ul_nr_t* dci)
|
||||
{
|
||||
// Fields described by TS 38.213 Table 8.2-1: Random Access Response Grant Content field size
|
||||
uint8_t* y = msg->payload;
|
||||
|
||||
// Copy DCI MSG fields
|
||||
dci->ctx = msg->ctx;
|
||||
|
||||
// Frequency hopping flag - 1 bit
|
||||
dci->freq_hopping_flag = srsran_bit_pack(&y, 1);
|
||||
|
||||
// PUSCH frequency resource allocation - 14 bits
|
||||
dci->freq_domain_assigment = srsran_bit_pack(&y, 14);
|
||||
|
||||
// PUSCH time resource allocation - 4 bits
|
||||
dci->time_domain_assigment = srsran_bit_pack(&y, 4);
|
||||
|
||||
// MCS -4 bits
|
||||
dci->mcs = srsran_bit_pack(&y, 4);
|
||||
|
||||
// TPC command for PUSCH - 3 bits
|
||||
dci->tpc = srsran_bit_pack(&y, 3);
|
||||
|
||||
// CSI request - 1 bits
|
||||
dci->csi_request = srsran_bit_pack(&y, 1);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static uint32_t dci_nr_rar_to_str(const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
// Frequency hopping flag
|
||||
len = srsran_print_check(str, str_len, len, "hop=%d ", dci->freq_hopping_flag);
|
||||
|
||||
// PUSCH frequency resource allocation
|
||||
len = srsran_print_check(str, str_len, len, "f_alloc=0x%x ", dci->freq_domain_assigment);
|
||||
|
||||
// PUSCH time resource allocation
|
||||
len = srsran_print_check(str, str_len, len, "t_alloc=0x%x ", dci->time_domain_assigment);
|
||||
|
||||
// Modulation and coding scheme
|
||||
len = srsran_print_check(str, str_len, len, "mcs=%d ", dci->mcs);
|
||||
|
||||
// TPC command for scheduled PUSCH
|
||||
len = srsran_print_check(str, str_len, len, "tpc=%d ", dci->tpc);
|
||||
|
||||
// CSI request
|
||||
len = srsran_print_check(str, str_len, len, "csi=%d ", dci->csi_request);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static uint32_t dci_nr_format_1_0_sizeof(uint32_t N_DL_BWP_RB, srsran_rnti_type_t rnti_type)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
@ -1132,7 +1240,7 @@ static int dci_nr_format_1_0_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_
|
|||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int dci_nr_format_1_0_to_str(const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len)
|
||||
static uint32_t dci_nr_format_1_0_to_str(const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
srsran_rnti_type_t rnti_type = dci->ctx.rnti_type;
|
||||
|
@ -1569,7 +1677,7 @@ static int dci_nr_format_1_1_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_
|
|||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
static uint32_t
|
||||
dci_nr_format_1_1_to_str(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
@ -1684,6 +1792,10 @@ dci_nr_format_1_1_to_str(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci
|
|||
|
||||
int srsran_dci_nr_set_cfg(srsran_dci_nr_t* q, const srsran_dci_cfg_nr_t* cfg)
|
||||
{
|
||||
if (q == NULL || cfg == NULL) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Reset current setup
|
||||
SRSRAN_MEM_ZERO(q, srsran_dci_nr_t, 1);
|
||||
|
||||
|
@ -1825,6 +1937,11 @@ uint32_t srsran_dci_nr_size(const srsran_dci_nr_t* q, srsran_search_space_type_t
|
|||
return q->dci_1_1_size;
|
||||
}
|
||||
|
||||
// RAR packed MSG3 DCI
|
||||
if (format == srsran_dci_format_nr_rar) {
|
||||
return dci_nr_rar_sizeof();
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
return 0;
|
||||
}
|
||||
|
@ -1853,71 +1970,12 @@ bool srsran_dci_nr_valid_direction(const srsran_dci_msg_nr_t* dci)
|
|||
return (dci->ctx.format == srsran_dci_format_nr_1_0);
|
||||
}
|
||||
|
||||
static int dci_nr_rar_pack(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, srsran_dci_msg_nr_t* msg)
|
||||
int srsran_dci_nr_dl_pack(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, srsran_dci_msg_nr_t* msg)
|
||||
{
|
||||
ERROR("Not implemented");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
static int dci_nr_rar_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_ul_nr_t* dci)
|
||||
{
|
||||
if (msg == NULL || dci == NULL) {
|
||||
if (q == NULL || dci == NULL || msg == NULL) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint8_t* y = msg->payload;
|
||||
|
||||
// Copy DCI MSG fields
|
||||
dci->ctx = msg->ctx;
|
||||
|
||||
// Frequency hopping flag - 1 bit
|
||||
dci->freq_hopping_flag = srsran_bit_pack(&y, 1);
|
||||
|
||||
// PUSCH frequency resource allocation - 14 bits
|
||||
dci->freq_domain_assigment = srsran_bit_pack(&y, 14);
|
||||
|
||||
// PUSCH time resource allocation - 4 bits
|
||||
dci->time_domain_assigment = srsran_bit_pack(&y, 4);
|
||||
|
||||
// MCS -4 bits
|
||||
dci->mcs = srsran_bit_pack(&y, 4);
|
||||
|
||||
// TPC command for PUSCH - 3 bits
|
||||
dci->tpc = srsran_bit_pack(&y, 3);
|
||||
|
||||
// CSI request - 1 bits
|
||||
dci->csi_request = srsran_bit_pack(&y, 3);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int dci_nr_rar_to_str(const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
// Frequency hopping flag
|
||||
len = srsran_print_check(str, str_len, len, "hop=%d ", dci->freq_hopping_flag);
|
||||
|
||||
// PUSCH frequency resource allocation
|
||||
len = srsran_print_check(str, str_len, len, "f_alloc=0x%x ", dci->freq_domain_assigment);
|
||||
|
||||
// PUSCH time resource allocation
|
||||
len = srsran_print_check(str, str_len, len, "t_alloc=0x%x ", dci->time_domain_assigment);
|
||||
|
||||
// Modulation and coding scheme
|
||||
len = srsran_print_check(str, str_len, len, "mcs=%d ", dci->mcs);
|
||||
|
||||
// TPC command for scheduled PUSCH
|
||||
len = srsran_print_check(str, str_len, len, "tpc=%d ", dci->tpc);
|
||||
|
||||
// CSI request
|
||||
len = srsran_print_check(str, str_len, len, "csi=%d ", dci->csi_request);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int srsran_dci_nr_dl_pack(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, srsran_dci_msg_nr_t* msg)
|
||||
{
|
||||
// Copy DCI MSG fields
|
||||
msg->ctx = dci->ctx;
|
||||
|
||||
|
@ -1936,6 +1994,10 @@ int srsran_dci_nr_dl_pack(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dc
|
|||
|
||||
int srsran_dci_nr_dl_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_dl_nr_t* dci)
|
||||
{
|
||||
if (q == NULL || dci == NULL || msg == NULL) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Copy DCI MSG fields
|
||||
dci->ctx = msg->ctx;
|
||||
|
||||
|
@ -1953,6 +2015,14 @@ int srsran_dci_nr_dl_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg,
|
|||
|
||||
int srsran_dci_nr_ul_pack(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, srsran_dci_msg_nr_t* msg)
|
||||
{
|
||||
if (msg == NULL || dci == NULL) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (dci->ctx.format != srsran_dci_format_nr_rar && q == NULL) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Copy DCI MSG fields
|
||||
msg->ctx = dci->ctx;
|
||||
|
||||
|
@ -1963,7 +2033,7 @@ int srsran_dci_nr_ul_pack(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dc
|
|||
case srsran_dci_format_nr_0_1:
|
||||
return dci_nr_format_0_1_pack(q, dci, msg);
|
||||
case srsran_dci_format_nr_rar:
|
||||
return dci_nr_rar_pack(q, dci, msg);
|
||||
return dci_nr_rar_pack(dci, msg);
|
||||
default:
|
||||
ERROR("Unsupported DCI format %d", msg->ctx.format);
|
||||
}
|
||||
|
@ -1973,6 +2043,14 @@ int srsran_dci_nr_ul_pack(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dc
|
|||
|
||||
int srsran_dci_nr_ul_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_ul_nr_t* dci)
|
||||
{
|
||||
if (msg == NULL || dci == NULL) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (msg->ctx.format != srsran_dci_format_nr_rar && q == NULL) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Copy DCI MSG fields
|
||||
dci->ctx = msg->ctx;
|
||||
|
||||
|
@ -1983,15 +2061,19 @@ int srsran_dci_nr_ul_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg,
|
|||
case srsran_dci_format_nr_0_1:
|
||||
return dci_nr_format_0_1_unpack(q, msg, dci);
|
||||
case srsran_dci_format_nr_rar:
|
||||
return dci_nr_rar_unpack(q, msg, dci);
|
||||
return dci_nr_rar_unpack(msg, dci);
|
||||
default:
|
||||
ERROR("Unsupported DCI format %d", msg->ctx.format);
|
||||
}
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
int srsran_dci_ctx_to_str(const srsran_dci_ctx_t* ctx, char* str, uint32_t str_len)
|
||||
uint32_t srsran_dci_ctx_to_str(const srsran_dci_ctx_t* ctx, char* str, uint32_t str_len)
|
||||
{
|
||||
if (ctx == NULL || str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t len = 0;
|
||||
|
||||
// Print base
|
||||
|
@ -2010,8 +2092,12 @@ int srsran_dci_ctx_to_str(const srsran_dci_ctx_t* ctx, char* str, uint32_t str_l
|
|||
return len;
|
||||
}
|
||||
|
||||
int srsran_dci_ul_nr_to_str(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len)
|
||||
uint32_t srsran_dci_ul_nr_to_str(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len)
|
||||
{
|
||||
if (q == NULL || dci == NULL || str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t len = 0;
|
||||
|
||||
len += srsran_dci_ctx_to_str(&dci->ctx, &str[len], str_len - len);
|
||||
|
@ -2035,8 +2121,12 @@ int srsran_dci_ul_nr_to_str(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t*
|
|||
return len;
|
||||
}
|
||||
|
||||
int srsran_dci_dl_nr_to_str(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len)
|
||||
uint32_t srsran_dci_dl_nr_to_str(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len)
|
||||
{
|
||||
if (q == NULL || dci == NULL || str == NULL) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t len = 0;
|
||||
|
||||
len += srsran_dci_ctx_to_str(&dci->ctx, &str[len], str_len - len);
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/phch/dci_nr.h"
|
||||
#include "srsran/phy/utils/debug.h"
|
||||
#include "srsran/phy/utils/random.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include <getopt.h>
|
||||
|
||||
static uint32_t nof_repetitions = 1024;
|
||||
|
@ -99,6 +99,7 @@ static int test_52prb_base()
|
|||
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_ue, srsran_dci_format_nr_1_0) == 39);
|
||||
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_ue, srsran_dci_format_nr_0_1) == 36);
|
||||
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_ue, srsran_dci_format_nr_1_1) == 41);
|
||||
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_rar, srsran_dci_format_nr_rar) == 27);
|
||||
|
||||
srsran_dci_ctx_t ctx = {};
|
||||
ctx.rnti = 0x1234;
|
||||
|
@ -202,6 +203,55 @@ static int test_52prb_base()
|
|||
TESTASSERT(memcmp(&dci_tx, &dci_rx, sizeof(srsran_dci_ul_nr_t)) == 0);
|
||||
}
|
||||
|
||||
// Test UL DCI RAR Packing/Unpacking and info
|
||||
ctx.ss_type = srsran_search_space_type_rar;
|
||||
ctx.format = srsran_dci_format_nr_rar;
|
||||
for (uint32_t i = 0; i < nof_repetitions; i++) {
|
||||
srsran_dci_ul_nr_t dci_tx = {};
|
||||
dci_tx.ctx = ctx;
|
||||
dci_tx.freq_domain_assigment = srsran_random_uniform_int_dist(random_gen, 0, (int)(1U << 14U) - 1); // 14 bit
|
||||
dci_tx.time_domain_assigment = srsran_random_uniform_int_dist(random_gen, 0, (int)(1U << 4U) - 1); // 4 bit
|
||||
dci_tx.freq_hopping_flag = srsran_random_uniform_int_dist(random_gen, 0, (int)(1U << 1U) - 1); // 1 bit
|
||||
dci_tx.mcs = srsran_random_uniform_int_dist(random_gen, 0, (int)(1U << 4U) - 1); // 4 bit
|
||||
dci_tx.rv = 0; // unavailable
|
||||
dci_tx.ndi = 0; // unavailable
|
||||
dci_tx.pid = 0; // unavailable
|
||||
dci_tx.tpc = srsran_random_uniform_int_dist(random_gen, 0, (int)(1U << 3U) - 1); // 3 bit
|
||||
dci_tx.frequency_offset = 0; // unavailable
|
||||
dci_tx.csi_request = srsran_random_uniform_int_dist(random_gen, 0, (int)(1U << 1U) - 1); // 1 bit
|
||||
dci_tx.sul = 0; // unavailable
|
||||
dci_tx.cc_id = 0; // unavailable
|
||||
dci_tx.bwp_id = 0; // unavailable
|
||||
dci_tx.dai1 = 0; // unavailable
|
||||
dci_tx.dai2 = 0; // unavailable
|
||||
dci_tx.srs_id = 0; // unavailable
|
||||
dci_tx.ports = 0; // unavailabale
|
||||
dci_tx.srs_request = 0; // unavailabale
|
||||
dci_tx.cbg_info = 0; // unavailable
|
||||
dci_tx.ptrs_id = 0; // unavailable
|
||||
dci_tx.beta_id = 0; // unavailable
|
||||
dci_tx.dmrs_id = 0; // unavailabale
|
||||
dci_tx.ulsch = 0; // unavailabale
|
||||
|
||||
// Pack
|
||||
srsran_dci_msg_nr_t dci_msg = {};
|
||||
TESTASSERT(srsran_dci_nr_ul_pack(&dci, &dci_tx, &dci_msg) == SRSRAN_SUCCESS);
|
||||
|
||||
// Unpack
|
||||
srsran_dci_ul_nr_t dci_rx = {};
|
||||
TESTASSERT(srsran_dci_nr_ul_unpack(&dci, &dci_msg, &dci_rx) == SRSRAN_SUCCESS);
|
||||
|
||||
// To string
|
||||
char str[512];
|
||||
TESTASSERT(srsran_dci_ul_nr_to_str(&dci, &dci_tx, str, (uint32_t)sizeof(str)) != 0);
|
||||
INFO("Tx: %s", str);
|
||||
TESTASSERT(srsran_dci_ul_nr_to_str(&dci, &dci_rx, str, (uint32_t)sizeof(str)) != 0);
|
||||
INFO("Rx: %s", str);
|
||||
|
||||
// Assert
|
||||
TESTASSERT(memcmp(&dci_tx, &dci_rx, sizeof(srsran_dci_ul_nr_t)) == 0);
|
||||
}
|
||||
|
||||
// Test UL DCI 1_0 Packing/Unpacking and info
|
||||
ctx.format = srsran_dci_format_nr_1_0;
|
||||
for (uint32_t i = 0; i < nof_repetitions; i++) {
|
||||
|
@ -255,7 +305,7 @@ static int test_52prb_base()
|
|||
TESTASSERT(memcmp(&dci_tx, &dci_rx, sizeof(srsran_dci_dl_nr_t)) == 0);
|
||||
}
|
||||
|
||||
// Test UL DCI 1_0 Packing/Unpacking and info
|
||||
// Test UL DCI 1_1 Packing/Unpacking and info
|
||||
ctx.format = srsran_dci_format_nr_1_1;
|
||||
for (uint32_t i = 0; i < nof_repetitions; i++) {
|
||||
srsran_dci_dl_nr_t dci_tx = {};
|
||||
|
|
|
@ -42,6 +42,40 @@ uint32_t srsran_uci_nr_crc_len(uint32_t A)
|
|||
return (A <= 11) ? 0 : (A < 20) ? 6 : 11;
|
||||
}
|
||||
|
||||
static inline int uci_nr_pusch_cfg_valid(const srsran_uci_nr_pusch_cfg_t* cfg)
|
||||
{
|
||||
// No data pointer
|
||||
if (cfg == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Unset configuration is unset
|
||||
if (cfg->nof_re == 0 && cfg->nof_layers == 0 && !isnormal(cfg->R)) {
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// Detect invalid number of layers
|
||||
if (cfg->nof_layers == 0) {
|
||||
ERROR("Invalid number of layers %d", cfg->nof_layers);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Detect invalid number of RE
|
||||
if (cfg->nof_re == 0) {
|
||||
ERROR("Invalid number of RE %d", cfg->nof_re);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Detect invalid Rate
|
||||
if (!isnormal(cfg->R)) {
|
||||
ERROR("Invalid R %f", cfg->R);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Otherwise it is set and valid
|
||||
return 1;
|
||||
}
|
||||
|
||||
int srsran_uci_nr_init(srsran_uci_nr_t* q, const srsran_uci_nr_args_t* args)
|
||||
{
|
||||
if (q == NULL || args == NULL) {
|
||||
|
@ -1024,10 +1058,6 @@ uint32_t srsran_uci_nr_info(const srsran_uci_data_nr_t* uci_data, char* str, uin
|
|||
|
||||
static int uci_nr_pusch_Q_prime_ack(const srsran_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack)
|
||||
{
|
||||
if (cfg == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
uint32_t L_ack = srsran_uci_nr_crc_len(O_ack); // Number of CRC bits
|
||||
uint32_t Qm = srsran_mod_bits_x_symbol(cfg->modulation); // modulation order of the PUSCH
|
||||
|
||||
|
@ -1055,14 +1085,15 @@ static int uci_nr_pusch_Q_prime_ack(const srsran_uci_nr_pusch_cfg_t* cfg, uint32
|
|||
|
||||
int srsran_uci_nr_pusch_ack_nof_bits(const srsran_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack)
|
||||
{
|
||||
// Check inputs
|
||||
if (cfg == NULL) {
|
||||
// Validate configuration
|
||||
int err = uci_nr_pusch_cfg_valid(cfg);
|
||||
if (err < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
if (cfg->nof_layers == 0) {
|
||||
ERROR("Invalid number of layers (%d)", cfg->nof_layers);
|
||||
return SRSRAN_ERROR;
|
||||
// Configuration is unset
|
||||
if (err == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Q_ack_prime = uci_nr_pusch_Q_prime_ack(cfg, O_ack);
|
||||
|
@ -1186,11 +1217,17 @@ static int uci_nr_pusch_Q_prime_csi1(const srsran_uci_nr_pusch_cfg_t* cfg, uint3
|
|||
|
||||
int srsran_uci_nr_pusch_csi1_nof_bits(const srsran_uci_cfg_nr_t* cfg)
|
||||
{
|
||||
// Check inputs
|
||||
if (cfg == NULL) {
|
||||
// Validate configuration
|
||||
int err = uci_nr_pusch_cfg_valid(&cfg->pusch);
|
||||
if (err < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Configuration is unset
|
||||
if (err == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int O_csi1 = srsran_csi_part1_nof_bits(cfg->csi, cfg->nof_csi);
|
||||
if (O_csi1 < SRSRAN_SUCCESS) {
|
||||
ERROR("Errpr calculating CSI part 1 number of bits");
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/utils/re_pattern.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
|
|
|
@ -73,3 +73,7 @@ add_test(optional_test optional_test)
|
|||
add_executable(cached_alloc_test cached_alloc_test.cc)
|
||||
target_link_libraries(cached_alloc_test srsran_common)
|
||||
add_test(cached_alloc_test cached_alloc_test)
|
||||
|
||||
add_executable(optional_array_test optional_array_test.cc)
|
||||
target_link_libraries(optional_array_test srsran_common)
|
||||
add_test(optional_array_test optional_array_test)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
#include "srsran/adt/bounded_vector.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
|
@ -61,7 +61,7 @@ struct moveonly {
|
|||
moveonly& operator=(moveonly&&) noexcept = default;
|
||||
};
|
||||
|
||||
int test_ctor()
|
||||
void test_ctor()
|
||||
{
|
||||
// TEST: default ctor
|
||||
bounded_vector<int, 10> a;
|
||||
|
@ -97,11 +97,9 @@ int test_ctor()
|
|||
bounded_vector<int, 20> a6(std::move(a5));
|
||||
TESTASSERT(a6.size() == 7);
|
||||
TESTASSERT(a5.size() == 0);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int test_obj_add_rem()
|
||||
void test_obj_add_rem()
|
||||
{
|
||||
// TEST: push_back / emplace_back
|
||||
bounded_vector<C, 10> a;
|
||||
|
@ -163,11 +161,9 @@ int test_obj_add_rem()
|
|||
a2.clear();
|
||||
a = std::move(a2);
|
||||
TESTASSERT(a.empty() and a2.empty());
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int test_move_only_type()
|
||||
void test_move_only_type()
|
||||
{
|
||||
bounded_vector<moveonly, 10> a(5);
|
||||
TESTASSERT(a.size() == 5);
|
||||
|
@ -184,24 +180,21 @@ int test_move_only_type()
|
|||
|
||||
a2.push_back(moveonly());
|
||||
TESTASSERT(a2.size() == 7);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int assert_dtor_consistency()
|
||||
void assert_dtor_consistency()
|
||||
{
|
||||
TESTASSERT(C::nof_dtor == C::nof_copy_ctor + C::nof_value_ctor + C::nof_move_ctor);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
int main()
|
||||
{
|
||||
TESTASSERT(srsran::test_ctor() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(srsran::test_obj_add_rem() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(srsran::test_move_only_type() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(srsran::assert_dtor_consistency() == SRSRAN_SUCCESS);
|
||||
srsran::test_ctor();
|
||||
srsran::test_obj_add_rem();
|
||||
srsran::test_move_only_type();
|
||||
srsran::assert_dtor_consistency();
|
||||
printf("Success\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsran/adt/optional_array.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
void test_optional_array()
|
||||
{
|
||||
optional_array<int, 5> table1;
|
||||
TESTASSERT(table1.size() == 0 and table1.empty());
|
||||
|
||||
TESTASSERT(not table1.contains(0));
|
||||
table1.insert(0, 5);
|
||||
TESTASSERT(table1.size() == 1 and not table1.empty());
|
||||
table1.erase(0);
|
||||
TESTASSERT(table1.size() == 0 and table1.empty());
|
||||
table1.insert(1, 3);
|
||||
table1.insert(4, 2);
|
||||
TESTASSERT(table1.size() == 2);
|
||||
TESTASSERT(table1[4] == 2 and table1[1] == 3);
|
||||
|
||||
size_t count = 0;
|
||||
int array[] = {3, 2};
|
||||
for (int e : table1) {
|
||||
TESTASSERT(array[count++] == e);
|
||||
}
|
||||
|
||||
auto it = table1.begin();
|
||||
TESTASSERT(*it == 3);
|
||||
table1.erase(it);
|
||||
TESTASSERT(table1.size() == 1);
|
||||
}
|
||||
|
||||
void test_optional_vector()
|
||||
{
|
||||
optional_vector<int> table1;
|
||||
TESTASSERT(table1.size() == 0 and table1.empty());
|
||||
|
||||
TESTASSERT(not table1.contains(0));
|
||||
table1.insert(0, 5);
|
||||
TESTASSERT(table1.size() == 1 and not table1.empty());
|
||||
table1.erase(0);
|
||||
TESTASSERT(table1.size() == 0 and table1.empty());
|
||||
table1.insert(1, 3);
|
||||
table1.insert(4, 2);
|
||||
TESTASSERT(table1.size() == 2);
|
||||
TESTASSERT(table1[4] == 2 and table1[1] == 3);
|
||||
|
||||
size_t count = 0;
|
||||
int array[] = {3, 2};
|
||||
for (int e : table1) {
|
||||
TESTASSERT(array[count++] == e);
|
||||
}
|
||||
|
||||
auto it = table1.begin();
|
||||
TESTASSERT(*it == 3);
|
||||
table1.erase(it);
|
||||
TESTASSERT(table1.size() == 1);
|
||||
}
|
||||
|
||||
void test_split_optional_span()
|
||||
{
|
||||
constexpr size_t L = 7;
|
||||
int some_list[L] = {};
|
||||
bool some_list_presence[L] = {};
|
||||
split_optional_span<int> view(some_list, some_list_presence, L);
|
||||
|
||||
TESTASSERT(view.size() == 0 and view.empty());
|
||||
TESTASSERT(view.begin() == view.end());
|
||||
TESTASSERT(not view.contains(0));
|
||||
TESTASSERT(view.find_first_empty() == L);
|
||||
|
||||
view.insert(1, 1);
|
||||
TESTASSERT(view.size() == 1 and not view.empty());
|
||||
TESTASSERT(view.begin() != view.end() and *view.begin() == 1);
|
||||
TESTASSERT(view.contains(1));
|
||||
TESTASSERT(view[1] == 1);
|
||||
TESTASSERT(view.find_first_empty() == 1);
|
||||
|
||||
view.insert(3, 3);
|
||||
TESTASSERT(view[3] == 3);
|
||||
size_t c = 0;
|
||||
for (auto& e : view) {
|
||||
TESTASSERT(c == 0 ? e == 1 : e == 3);
|
||||
c++;
|
||||
}
|
||||
TESTASSERT(view.size() == 2);
|
||||
|
||||
view.erase(view.begin());
|
||||
TESTASSERT(view.size() == 1);
|
||||
TESTASSERT(not view.contains(1) and view.contains(3));
|
||||
|
||||
view.clear();
|
||||
TESTASSERT(view.empty());
|
||||
}
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
auto& test_log = srslog::fetch_basic_logger("TEST");
|
||||
test_log.set_level(srslog::basic_levels::info);
|
||||
|
||||
srsran::test_init(argc, argv);
|
||||
|
||||
srsran::test_optional_array();
|
||||
srsran::test_optional_vector();
|
||||
srsran::test_split_optional_span();
|
||||
|
||||
printf("Success\n");
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
|
@ -19,8 +19,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/common/timers.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <srsran/common/tti_sync_cv.h>
|
||||
|
@ -30,7 +30,7 @@ using namespace srsran;
|
|||
|
||||
static_assert(timer_handler::max_timer_duration() == 1073741823, "Invalid max duration");
|
||||
|
||||
int timers_test1()
|
||||
void timers_test1()
|
||||
{
|
||||
timer_handler timers;
|
||||
uint32_t dur = 5;
|
||||
|
@ -119,8 +119,6 @@ int timers_test1()
|
|||
}
|
||||
// TEST: timer dtor is called and removes "timer" from "timers"
|
||||
TESTASSERT(timers.nof_timers() == 0);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +126,7 @@ int timers_test1()
|
|||
* - calling stop() early, forbids the timer from getting expired
|
||||
* - calling stop() after timer has expired should be a noop
|
||||
*/
|
||||
int timers_test2()
|
||||
void timers_test2()
|
||||
{
|
||||
timer_handler timers;
|
||||
uint32_t duration = 2;
|
||||
|
@ -154,15 +152,13 @@ int timers_test2()
|
|||
// TEST 2: call utimer.stop() after it expires and assert it is still expired
|
||||
utimer2.stop();
|
||||
TESTASSERT(utimer2.is_expired());
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* - setting a new duration while the timer is already running should not stop timer, and should extend timeout
|
||||
*/
|
||||
int timers_test3()
|
||||
void timers_test3()
|
||||
{
|
||||
timer_handler timers;
|
||||
uint32_t duration = 5;
|
||||
|
@ -185,8 +181,6 @@ int timers_test3()
|
|||
}
|
||||
timers.step_all();
|
||||
TESTASSERT(not utimer.is_running() and utimer.is_expired());
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
struct timers_test4_ctxt {
|
||||
|
@ -227,7 +221,7 @@ static void timers2_test4_thread(timers_test4_ctxt* ctx)
|
|||
}
|
||||
}
|
||||
|
||||
int timers_test4()
|
||||
void timers_test4()
|
||||
{
|
||||
timer_handler timers;
|
||||
timers_test4_ctxt ctx;
|
||||
|
@ -304,14 +298,12 @@ int timers_test4()
|
|||
for (uint32_t i = 0; i < nof_timers; i++) {
|
||||
TESTASSERT(not ctx.timers[i].is_running());
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description: Delaying a callback using the timer_handler
|
||||
*/
|
||||
int timers_test5()
|
||||
void timers_test5()
|
||||
{
|
||||
timer_handler timers;
|
||||
TESTASSERT(timers.nof_timers() == 0);
|
||||
|
@ -363,14 +355,12 @@ int timers_test5()
|
|||
TESTASSERT(timers.nof_timers() == 1);
|
||||
TESTASSERT(vals.size() == 3);
|
||||
TESTASSERT(vals[2] == 3);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description: Check if erasure of a running timer is safe
|
||||
*/
|
||||
int timers_test6()
|
||||
void timers_test6()
|
||||
{
|
||||
timer_handler timers;
|
||||
|
||||
|
@ -408,8 +398,6 @@ int timers_test6()
|
|||
// TEST: The second timer's callback should be the one being called, and should be called only once
|
||||
timers.step_all();
|
||||
TESTASSERT(vals.size() == 1 and vals[0] == 3);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -417,7 +405,7 @@ int timers_test6()
|
|||
* - check if timer update is safe when its new updated wheel position matches the previous wheel position
|
||||
* - multime timers can exist in the same wheel position
|
||||
*/
|
||||
int timers_test7()
|
||||
void timers_test7()
|
||||
{
|
||||
timer_handler timers;
|
||||
size_t wheel_size = timer_handler::get_wheel_size();
|
||||
|
@ -458,19 +446,17 @@ int timers_test7()
|
|||
TESTASSERT(not t2.is_expired() and t2.is_running());
|
||||
TESTASSERT(t3.is_expired() and not t3.is_running());
|
||||
TESTASSERT(timers.nof_running_timers() == 1 and timers.nof_timers() == 3);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TESTASSERT(timers_test1() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(timers_test2() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(timers_test3() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(timers_test4() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(timers_test5() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(timers_test6() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(timers_test7() == SRSRAN_SUCCESS);
|
||||
timers_test1();
|
||||
timers_test2();
|
||||
timers_test3();
|
||||
timers_test4();
|
||||
timers_test5();
|
||||
timers_test6();
|
||||
timers_test7();
|
||||
printf("Success\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
*/
|
||||
|
||||
#include "srsran/common/slot_point.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/common/tti_point.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
|
||||
using srsran::tti_point;
|
||||
|
||||
int test_tti_type()
|
||||
void test_tti_type()
|
||||
{
|
||||
// TEST: constructors
|
||||
tti_point tti1;
|
||||
|
@ -72,8 +72,6 @@ int test_tti_type()
|
|||
TESTASSERT(tti_point{1u - 2u} == tti_point{10239});
|
||||
TESTASSERT(tti_point{1u - 100u} == tti_point{10141});
|
||||
TESTASSERT(tti_point{10239u + 3u} == tti_point{2});
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
void test_nr_slot_type()
|
||||
|
|
|
@ -30,6 +30,30 @@
|
|||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
/// SIB scheduler
|
||||
class si_sched
|
||||
{
|
||||
public:
|
||||
explicit si_sched(const bwp_params& bwp_cfg_);
|
||||
|
||||
void run_slot(bwp_slot_allocator& slot_alloc);
|
||||
|
||||
private:
|
||||
const bwp_params* bwp_cfg = nullptr;
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
struct sched_si_t {
|
||||
uint32_t n = 0;
|
||||
uint32_t len = 0;
|
||||
uint32_t win_len = 0;
|
||||
uint32_t period = 0;
|
||||
uint32_t n_tx = 0;
|
||||
alloc_result result = alloc_result::invalid_coderate;
|
||||
slot_point win_start;
|
||||
};
|
||||
srsran::bounded_vector<sched_si_t, 10> pending_sis;
|
||||
};
|
||||
|
||||
using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t;
|
||||
|
||||
/// RAR/Msg3 scheduler
|
||||
|
@ -38,9 +62,9 @@ class ra_sched
|
|||
public:
|
||||
explicit ra_sched(const bwp_params& bwp_cfg_);
|
||||
|
||||
int dl_rach_info(const dl_sched_rar_info_t& rar_info);
|
||||
void run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues);
|
||||
size_t empty() const { return pending_rars.empty(); }
|
||||
int dl_rach_info(const dl_sched_rar_info_t& rar_info);
|
||||
void run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues);
|
||||
bool empty() const { return pending_rars.empty(); }
|
||||
|
||||
private:
|
||||
struct pending_rar_t {
|
||||
|
|
|
@ -65,6 +65,12 @@ struct bwp_params {
|
|||
uint32_t P;
|
||||
uint32_t N_rbg;
|
||||
|
||||
struct slot_cfg {
|
||||
bool is_dl;
|
||||
bool is_ul;
|
||||
};
|
||||
srsran::bounded_vector<slot_cfg, SRSRAN_NOF_SF_X_FRAME> slots;
|
||||
|
||||
struct pusch_ra_time_cfg {
|
||||
uint32_t msg3_delay; ///< Includes K2 and delta. See TS 36.214 6.1.2.1.1-2/4/5
|
||||
uint32_t K;
|
||||
|
|
|
@ -52,7 +52,6 @@ struct bwp_slot_grid {
|
|||
uint32_t slot_idx;
|
||||
const bwp_params* cfg;
|
||||
|
||||
bool is_dl, is_ul;
|
||||
bwp_rb_bitmap dl_prbs;
|
||||
bwp_rb_bitmap ul_prbs;
|
||||
pdcch_dl_list_t dl_pdcchs;
|
||||
|
@ -65,6 +64,9 @@ struct bwp_slot_grid {
|
|||
bwp_slot_grid() = default;
|
||||
explicit bwp_slot_grid(const bwp_params& bwp_params, uint32_t slot_idx_);
|
||||
void reset();
|
||||
|
||||
bool is_dl() const { return cfg->slots[slot_idx].is_dl; }
|
||||
bool is_ul() const { return cfg->slots[slot_idx].is_ul; }
|
||||
};
|
||||
|
||||
struct bwp_res_grid {
|
||||
|
@ -92,6 +94,7 @@ public:
|
|||
|
||||
void new_slot(slot_point pdcch_slot_) { pdcch_slot = pdcch_slot_; }
|
||||
|
||||
alloc_result alloc_si(uint32_t aggr_idx, uint32_t si_idx, uint32_t si_ntx, const prb_interval& prbs);
|
||||
alloc_result alloc_rar_and_msg3(uint16_t ra_rnti,
|
||||
uint32_t aggr_idx,
|
||||
prb_interval interv,
|
||||
|
|
|
@ -64,11 +64,13 @@ public:
|
|||
srsran_sch_hl_cfg_nr_t pdsch = {};
|
||||
srsran_sch_hl_cfg_nr_t pusch = {};
|
||||
uint32_t rar_window_size = 8;
|
||||
uint32_t numerology_idx = 0;
|
||||
};
|
||||
|
||||
struct cell_cfg_t {
|
||||
srsran_carrier_nr_t carrier = {};
|
||||
srsran_tdd_config_nr_t tdd = {};
|
||||
srsran::phy_cfg_nr_t::ssb_cfg_t ssb = {};
|
||||
srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1}; // idx0 for BWP-common
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "srsran/adt/bounded_bitset.h"
|
||||
#include "srsran/adt/interval.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
extern "C" {
|
||||
#include "srsran/phy/phch/ra.h"
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ inline uint32_t cell_nof_prb_to_rbg(uint32_t nof_prbs)
|
|||
case 100:
|
||||
return 25;
|
||||
default:
|
||||
srsran_terminate("Provided nof PRBs not valid");
|
||||
srsran_assertion_failure("Provided nof PRBs not valid");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ inline uint32_t cell_nof_rbg_to_prb(uint32_t nof_rbgs)
|
|||
case 25:
|
||||
return 100;
|
||||
default:
|
||||
srsran_terminate("Provided nof PRBs not valid");
|
||||
srsran_assertion_failure("Provided nof PRBs not valid");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,64 @@
|
|||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
si_sched::si_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger("MAC")) {}
|
||||
|
||||
void si_sched::run_slot(bwp_slot_allocator& slot_alloc)
|
||||
{
|
||||
const uint32_t si_aggr_level = 2;
|
||||
slot_point pdcch_slot = slot_alloc.get_pdcch_tti();
|
||||
const prb_bitmap& prbs = slot_alloc.res_grid()[pdcch_slot].dl_prbs.prbs();
|
||||
|
||||
// Update SI windows
|
||||
uint32_t N = bwp_cfg->slots.size();
|
||||
for (sched_si_t& si : pending_sis) {
|
||||
uint32_t x = (si.n - 1) * si.win_len;
|
||||
|
||||
if (not si.win_start.valid() and (pdcch_slot.sfn() % si.period == x / N) and
|
||||
pdcch_slot.slot_idx() == x % bwp_cfg->slots.size()) {
|
||||
// If start o SI message window
|
||||
si.win_start = pdcch_slot;
|
||||
} else if (si.win_start.valid() and si.win_start + si.win_len >= pdcch_slot) {
|
||||
// If end of SI message window
|
||||
logger.warning(
|
||||
"SCHED: Could not allocate SI message idx=%d, len=%d. Cause: %s", si.n, si.len, to_string(si.result));
|
||||
si.win_start.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule pending SIs
|
||||
if (bwp_cfg->slots[pdcch_slot.slot_idx()].is_dl) {
|
||||
for (sched_si_t& si : pending_sis) {
|
||||
if (not si.win_start.valid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: NOTE 2: The UE is not required to monitor PDCCH monitoring occasion(s) corresponding to each transmitted
|
||||
// SSB in SI-window.
|
||||
|
||||
// Attempt grants with increasing number of PRBs (if the number of PRBs is too low, the coderate is invalid)
|
||||
si.result = alloc_result::invalid_coderate;
|
||||
uint32_t prb_start_idx = 0;
|
||||
for (uint32_t nprbs = 4; nprbs < bwp_cfg->cfg.rb_width and si.result == alloc_result::invalid_coderate; ++nprbs) {
|
||||
prb_interval grant = find_empty_interval_of_length(prbs, nprbs, prb_start_idx);
|
||||
prb_start_idx = grant.start();
|
||||
if (grant.length() != nprbs) {
|
||||
si.result = alloc_result::no_sch_space;
|
||||
break;
|
||||
}
|
||||
si.result = slot_alloc.alloc_si(si_aggr_level, si.n, si.n_tx, grant);
|
||||
if (si.result == alloc_result::success) {
|
||||
// SIB scheduled successfully
|
||||
si.win_start.clear();
|
||||
si.n_tx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ra_sched::ra_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger("MAC")) {}
|
||||
|
||||
alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid,
|
||||
|
@ -43,7 +101,7 @@ alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid,
|
|||
uint32_t start_prb_idx = 0;
|
||||
for (uint32_t nprb = 4; nprb < bwp_cfg->cfg.rb_width and ret == alloc_result::invalid_coderate; ++nprb) {
|
||||
prb_interval interv = find_empty_interval_of_length(prbs, nprb, start_prb_idx);
|
||||
start_prb_idx = interv.stop();
|
||||
start_prb_idx = interv.start();
|
||||
if (interv.length() == nprb) {
|
||||
ret = slot_grid.alloc_rar_and_msg3(
|
||||
rar.ra_rnti, rar_aggr_level, interv, slot_ues, msg3_grants.subspan(0, nof_grants_alloc));
|
||||
|
@ -67,20 +125,8 @@ void ra_sched::run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues)
|
|||
{
|
||||
slot_point pdcch_slot = slot_grid.get_pdcch_tti();
|
||||
slot_point msg3_slot = pdcch_slot + bwp_cfg->pusch_ra_list[0].msg3_delay;
|
||||
if (not slot_grid.res_grid()[pdcch_slot].is_dl) {
|
||||
// RAR only allowed if PDCCH is available
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark RAR window start, regardless of whether PUSCH is available
|
||||
for (auto& rar : pending_rars) {
|
||||
if (rar.rar_win.empty()) {
|
||||
rar.rar_win = {pdcch_slot, pdcch_slot + bwp_cfg->cfg.rar_window_size};
|
||||
}
|
||||
}
|
||||
|
||||
if (not slot_grid.res_grid()[msg3_slot].is_ul) {
|
||||
// RAR only allowed if respective Msg3 slot is available for UL
|
||||
if (not bwp_cfg->slots[pdcch_slot.slot_idx()].is_dl or not bwp_cfg->slots[msg3_slot.slot_idx()].is_ul) {
|
||||
// RAR only allowed if PDCCH is available and respective Msg3 slot is available for UL
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -137,13 +183,6 @@ void ra_sched::run_slot(bwp_slot_allocator& slot_grid, slot_ue_map_t& slot_ues)
|
|||
/// See TS 38.321, 5.1.3 - RAP transmission
|
||||
int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info)
|
||||
{
|
||||
logger.info("SCHED: New PRACH slot=%d, preamble=%d, temp_crnti=0x%x, ta_cmd=%d, msg3_size=%d",
|
||||
rar_info.prach_slot.to_uint(),
|
||||
rar_info.preamble_idx,
|
||||
rar_info.temp_crnti,
|
||||
rar_info.ta_cmd,
|
||||
rar_info.msg3_size);
|
||||
|
||||
// RA-RNTI = 1 + s_id + 14 × t_id + 14 × 80 × f_id + 14 × 80 × 8 × ul_carrier_id
|
||||
// s_id = index of the first OFDM symbol (0 <= s_id < 14)
|
||||
// t_id = index of first slot of the PRACH (0 <= t_id < 80)
|
||||
|
@ -151,6 +190,14 @@ int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info)
|
|||
// ul_carrier_id = 0 for NUL and 1 for SUL carrier
|
||||
uint16_t ra_rnti = 1 + rar_info.ofdm_symbol_idx + 14 * rar_info.prach_slot.slot_idx() + 14 * 80 * rar_info.freq_idx;
|
||||
|
||||
logger.info("SCHED: New PRACH slot=%d, preamble=%d, ra-rnti=0x%x, temp_crnti=0x%x, ta_cmd=%d, msg3_size=%d",
|
||||
rar_info.prach_slot.to_uint(),
|
||||
rar_info.preamble_idx,
|
||||
ra_rnti,
|
||||
rar_info.temp_crnti,
|
||||
rar_info.ta_cmd,
|
||||
rar_info.msg3_size);
|
||||
|
||||
// find pending rar with same RA-RNTI
|
||||
for (pending_rar_t& r : pending_rars) {
|
||||
if (r.prach_slot == rar_info.prach_slot and ra_rnti == r.ra_rnti) {
|
||||
|
@ -165,8 +212,14 @@ int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info)
|
|||
|
||||
// create new RAR
|
||||
pending_rar_t p;
|
||||
p.ra_rnti = ra_rnti;
|
||||
p.prach_slot = rar_info.prach_slot;
|
||||
p.ra_rnti = ra_rnti;
|
||||
p.prach_slot = rar_info.prach_slot;
|
||||
const static uint32_t prach_duration = 1;
|
||||
for (slot_point t = rar_info.prach_slot + prach_duration; t < rar_info.prach_slot + bwp_cfg->slots.size(); ++t) {
|
||||
if (bwp_cfg->slots[t.slot_idx()].is_dl) {
|
||||
p.rar_win = {t, t + bwp_cfg->cfg.rar_window_size};
|
||||
}
|
||||
}
|
||||
p.msg3_grant.push_back(rar_info);
|
||||
pending_rars.push_back(p);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h"
|
||||
#include "srsran/adt/optional_array.h"
|
||||
extern "C" {
|
||||
#include "srsran/phy/phch/ra_ul_nr.h"
|
||||
}
|
||||
|
@ -36,6 +37,15 @@ bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, ui
|
|||
P = get_P(cfg.rb_width, cfg.pdsch.rbg_size_cfg_1);
|
||||
N_rbg = get_nof_rbgs(cfg.rb_width, cfg.start_rb, cfg.pdsch.rbg_size_cfg_1);
|
||||
|
||||
// Derive params of individual slots
|
||||
uint32_t nof_slots = SRSRAN_NSLOTS_PER_FRAME_NR(cfg.numerology_idx);
|
||||
for (size_t sl = 0; sl < nof_slots; ++sl) {
|
||||
slot_cfg sl_cfg{};
|
||||
sl_cfg.is_dl = srsran_tdd_nr_is_dl(&cell_cfg.tdd, cfg.numerology_idx, sl);
|
||||
sl_cfg.is_ul = srsran_tdd_nr_is_ul(&cell_cfg.tdd, cfg.numerology_idx, sl);
|
||||
slots.push_back(sl_cfg);
|
||||
}
|
||||
|
||||
pusch_ra_list.resize(cfg.pusch.nof_common_time_ra);
|
||||
const uint32_t coreset_id = 0;
|
||||
srsran_sch_grant_nr_t grant;
|
||||
|
@ -103,45 +113,40 @@ bwp_ue_cfg::bwp_ue_cfg(uint16_t rnti_, const bwp_params& bwp_cfg_, const ue_cfg_
|
|||
rnti(rnti_), cfg_(&uecfg_), bwp_cfg(&bwp_cfg_)
|
||||
{
|
||||
std::fill(ss_id_to_cce_idx.begin(), ss_id_to_cce_idx.end(), SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE);
|
||||
const auto& pdcch = phy().pdcch;
|
||||
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++i) {
|
||||
if (pdcch.search_space_present[i]) {
|
||||
const auto& ss = pdcch.search_space[i];
|
||||
srsran_assert(pdcch.coreset_present[ss.coreset_id],
|
||||
"Invalid mapping search space id=%d to coreset id=%d",
|
||||
ss.id,
|
||||
ss.coreset_id);
|
||||
const auto& coreset = pdcch.coreset[ss.coreset_id];
|
||||
cce_positions_list.emplace_back();
|
||||
get_dci_locs(coreset, ss, rnti, cce_positions_list.back());
|
||||
ss_id_to_cce_idx[ss.id] = cce_positions_list.size() - 1;
|
||||
}
|
||||
const auto& pdcch = phy().pdcch;
|
||||
auto ss_view = srsran::make_optional_span(pdcch.search_space, pdcch.search_space_present);
|
||||
auto coreset_view = srsran::make_optional_span(pdcch.coreset, pdcch.coreset_present);
|
||||
for (const auto& ss : ss_view) {
|
||||
srsran_assert(coreset_view.contains(ss.coreset_id),
|
||||
"Invalid mapping search space id=%d to coreset id=%d",
|
||||
ss.id,
|
||||
ss.coreset_id);
|
||||
cce_positions_list.emplace_back();
|
||||
get_dci_locs(coreset_view[ss.coreset_id], ss, rnti, cce_positions_list.back());
|
||||
ss_id_to_cce_idx[ss.id] = cce_positions_list.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg_t(uecfg), rnti(rnti_)
|
||||
{
|
||||
auto ss_view = srsran::make_optional_span(phy_cfg.pdcch.search_space, phy_cfg.pdcch.search_space_present);
|
||||
auto coreset_view = srsran::make_optional_span(phy_cfg.pdcch.coreset, phy_cfg.pdcch.coreset_present);
|
||||
cc_params.resize(carriers.size());
|
||||
for (uint32_t cc = 0; cc < cc_params.size(); ++cc) {
|
||||
cc_params[cc].bwps.resize(1);
|
||||
auto& bwp = cc_params[cc].bwps[0];
|
||||
for (uint32_t ssid = 0; ssid < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ssid) {
|
||||
if (phy_cfg.pdcch.search_space_present[ssid]) {
|
||||
auto& ss = phy_cfg.pdcch.search_space[ssid];
|
||||
bwp.ss_list[ss.id].emplace();
|
||||
bwp.ss_list[ss.id]->cfg = &ss;
|
||||
get_dci_locs(phy_cfg.pdcch.coreset[ss.coreset_id], ss, rnti, bwp.ss_list[ss.id]->cce_positions);
|
||||
}
|
||||
for (auto& ss : ss_view) {
|
||||
bwp.ss_list[ss.id].emplace();
|
||||
bwp.ss_list[ss.id]->cfg = &ss;
|
||||
get_dci_locs(phy_cfg.pdcch.coreset[ss.coreset_id], ss, rnti, bwp.ss_list[ss.id]->cce_positions);
|
||||
}
|
||||
for (uint32_t idx = 0; idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++idx) {
|
||||
if (phy_cfg.pdcch.coreset_present[idx]) {
|
||||
bwp.coresets.emplace_back();
|
||||
auto& coreset = bwp.coresets.back();
|
||||
coreset.cfg = &phy_cfg.pdcch.coreset[idx];
|
||||
for (auto& ss : bwp.ss_list) {
|
||||
if (ss.has_value() and ss->cfg->coreset_id == coreset.cfg->id) {
|
||||
coreset.ss_list.push_back(ss->cfg->id);
|
||||
}
|
||||
for (auto& coreset_cfg : coreset_view) {
|
||||
bwp.coresets.emplace_back();
|
||||
auto& coreset = bwp.coresets.back();
|
||||
coreset.cfg = &coreset_cfg;
|
||||
for (auto& ss : bwp.ss_list) {
|
||||
if (ss.has_value() and ss->cfg->coreset_id == coreset.cfg->id) {
|
||||
coreset.ss_list.push_back(ss->cfg->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,15 +26,11 @@
|
|||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
#define NUMEROLOGY_IDX 0
|
||||
|
||||
bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) :
|
||||
dl_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1),
|
||||
ul_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1),
|
||||
slot_idx(slot_idx_),
|
||||
cfg(&bwp_cfg_),
|
||||
is_dl(srsran_tdd_nr_is_dl(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)),
|
||||
is_ul(srsran_tdd_nr_is_ul(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_))
|
||||
cfg(&bwp_cfg_)
|
||||
{
|
||||
for (uint32_t cs_idx = 0; cs_idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++cs_idx) {
|
||||
if (cfg->cfg.pdcch.coreset_present[cs_idx]) {
|
||||
|
@ -73,6 +69,27 @@ bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) :
|
|||
logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cfg), bwp_grid(bwp_grid_)
|
||||
{}
|
||||
|
||||
alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, uint32_t si_ntx, const prb_interval& prbs)
|
||||
{
|
||||
bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_slot];
|
||||
if (not bwp_pdcch_slot.is_dl()) {
|
||||
logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdcch_slot.slot_idx);
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
pdcch_dl_list_t& pdsch_grants = bwp_pdcch_slot.dl_pdcchs;
|
||||
if (pdsch_grants.full()) {
|
||||
logger.warning("SCHED: Maximum number of DL allocations reached");
|
||||
return alloc_result::no_grant_space;
|
||||
}
|
||||
if (bwp_pdcch_slot.dl_prbs.collides(prbs)) {
|
||||
return alloc_result::sch_collision;
|
||||
}
|
||||
|
||||
// TODO: Allocate PDCCH and PDSCH
|
||||
|
||||
return alloc_result::success;
|
||||
}
|
||||
|
||||
alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t ra_rnti,
|
||||
uint32_t aggr_idx,
|
||||
prb_interval interv,
|
||||
|
@ -140,15 +157,19 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
|
|||
srsran_slot_cfg_t slot_cfg;
|
||||
slot_cfg.idx = msg3_slot.slot_idx();
|
||||
for (const dl_sched_rar_info_t& grant : pending_rars) {
|
||||
slot_ue& ue = ues[grant.temp_crnti];
|
||||
slot_ue& ue = ues[grant.temp_crnti];
|
||||
|
||||
// Allocate Msg3
|
||||
prb_interval msg3_interv{last_msg3, last_msg3 + msg3_nof_prbs};
|
||||
ue.h_ul = ue.harq_ent->find_empty_ul_harq();
|
||||
bool success = ue.h_ul->new_tx(msg3_slot, msg3_slot, msg3_interv, mcs, 100, max_harq_msg3_retx);
|
||||
srsran_assert(success, "Failed to allocate Msg3");
|
||||
last_msg3 += msg3_nof_prbs;
|
||||
pdcch_ul_t msg3_pdcch;
|
||||
pdcch_ul_t msg3_pdcch; // dummy PDCCH for retx=0
|
||||
fill_dci_msg3(ue, *bwp_grid.cfg, msg3_pdcch.dci);
|
||||
msg3_pdcch.dci.time_domain_assigment = dai++;
|
||||
|
||||
// Generate PUSCH
|
||||
bwp_msg3_slot.puschs.emplace_back();
|
||||
pusch_t& pusch = bwp_msg3_slot.puschs.back();
|
||||
success = ue.cfg->phy().get_pusch_cfg(slot_cfg, msg3_pdcch.dci, pusch.sch);
|
||||
|
@ -175,7 +196,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr
|
|||
bwp_slot_grid& bwp_pdcch_slot = bwp_grid[ue.pdcch_slot];
|
||||
bwp_slot_grid& bwp_pdsch_slot = bwp_grid[ue.pdsch_slot];
|
||||
bwp_slot_grid& bwp_uci_slot = bwp_grid[ue.uci_slot];
|
||||
if (not bwp_pdsch_slot.is_dl) {
|
||||
if (not bwp_pdsch_slot.is_dl()) {
|
||||
logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdsch_slot.slot_idx);
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
|
@ -308,13 +329,13 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const prb_grant& ul_pr
|
|||
|
||||
alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_grid, bwp_slot_grid* pdcch_grid) const
|
||||
{
|
||||
if (not pusch_grid.is_ul) {
|
||||
if (not pusch_grid.is_ul()) {
|
||||
logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", pusch_grid.slot_idx);
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
if (pdcch_grid != nullptr) {
|
||||
// DCI needed
|
||||
if (not pdcch_grid->is_dl) {
|
||||
if (not pdcch_grid->is_dl()) {
|
||||
logger.warning("SCHED: Trying to allocate PDCCH in TDD non-DL slot index=%d", pdcch_grid->slot_idx);
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
|
|
|
@ -57,12 +57,16 @@ void fill_dci_common(const slot_ue& ue, const bwp_params& bwp_cfg, DciDlOrUl& dc
|
|||
bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci)
|
||||
{
|
||||
dci.mcs = 5;
|
||||
dci.ctx.format = srsran_dci_format_nr_rar;
|
||||
dci.ctx.format = srsran_dci_format_nr_1_0;
|
||||
dci.ctx.ss_type = srsran_search_space_type_rar;
|
||||
dci.ctx.rnti_type = srsran_rnti_type_ra;
|
||||
dci.ctx.rnti = ra_rnti;
|
||||
dci.ctx.coreset_id = bwp_cfg.cfg.pdcch.ra_search_space.coreset_id;
|
||||
dci.freq_domain_assigment = srsran_ra_nr_type1_riv(bwp_cfg.cfg.rb_width, interv.start(), interv.length());
|
||||
dci.time_domain_assigment = 0;
|
||||
dci.tpc = 1;
|
||||
dci.bwp_id = bwp_cfg.bwp_id;
|
||||
dci.cc_id = bwp_cfg.cc;
|
||||
// TODO: Fill
|
||||
|
||||
return true;
|
||||
|
@ -70,6 +74,7 @@ bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params& bwp_c
|
|||
|
||||
bool fill_dci_msg3(const slot_ue& ue, const bwp_params& bwp_cfg, srsran_dci_ul_nr_t& msg3_dci)
|
||||
{
|
||||
fill_dci_common(ue, bwp_cfg, msg3_dci);
|
||||
msg3_dci.ctx.coreset_id = ue.cfg->phy().pdcch.ra_search_space.coreset_id;
|
||||
msg3_dci.ctx.rnti_type = srsran_rnti_type_tc;
|
||||
msg3_dci.ctx.rnti = ue.rnti;
|
||||
|
@ -79,7 +84,6 @@ bool fill_dci_msg3(const slot_ue& ue, const bwp_params& bwp_cfg, srsran_dci_ul_n
|
|||
} else {
|
||||
msg3_dci.ctx.format = srsran_dci_format_nr_0_0;
|
||||
}
|
||||
fill_dci_common(ue, bwp_cfg, msg3_dci);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -145,20 +145,21 @@ void slot_cc_worker::log_result() const
|
|||
fmt::memory_buffer fmtbuf;
|
||||
if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) {
|
||||
const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti];
|
||||
fmt::format_to(fmtbuf,
|
||||
"SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, dai={}, tbs={}, tti_pdsch={}, tti_ack={}",
|
||||
ue.h_dl->nof_retx() == 0 ? "tx" : "retx",
|
||||
cell.cfg.cc,
|
||||
ue.rnti,
|
||||
pdcch.dci.pid,
|
||||
srsran_dci_format_nr_string(pdcch.dci.ctx.format),
|
||||
ue.h_dl->nof_retx(),
|
||||
pdcch.dci.dai,
|
||||
ue.h_dl->tbs(),
|
||||
ue.pdsch_slot,
|
||||
ue.uci_slot);
|
||||
fmt::format_to(
|
||||
fmtbuf,
|
||||
"SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, dai={}, tbs={}, tti_pdsch={}, tti_ack={}",
|
||||
ue.h_dl->nof_retx() == 0 ? "tx" : "retx",
|
||||
cell.cfg.cc,
|
||||
ue.rnti,
|
||||
pdcch.dci.pid,
|
||||
srsran_dci_format_nr_string(pdcch.dci.ctx.format),
|
||||
ue.h_dl->nof_retx(),
|
||||
pdcch.dci.dai,
|
||||
ue.h_dl->tbs(),
|
||||
ue.pdsch_slot,
|
||||
ue.uci_slot);
|
||||
} else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) {
|
||||
fmt::format_to(fmtbuf, "SCHED: DL RAR, cc={}", cell.cfg.cc);
|
||||
fmt::format_to(fmtbuf, "SCHED: DL RAR, cc={}, ra-rnti=0x{:x}", cell.cfg.cc, pdcch.dci.ctx.rnti);
|
||||
} else {
|
||||
fmt::format_to(fmtbuf, "SCHED: unknown format");
|
||||
}
|
||||
|
|
|
@ -688,13 +688,21 @@ void rrc::ue::rrc_mobility::s1_source_ho_st::handle_ho_cmd(wait_ho_cmd& s, const
|
|||
rrc_ue->mac_ctrl.update_mac(mac_controller::proc_stage_t::other);
|
||||
|
||||
// Send HO Command to UE
|
||||
if (not rrc_ue->send_dl_dcch(&dl_dcch_msg)) {
|
||||
std::string octet_str;
|
||||
if (not rrc_ue->send_dl_dcch(&dl_dcch_msg, nullptr, &octet_str)) {
|
||||
asn1::s1ap::cause_c cause;
|
||||
cause.set_protocol().value = asn1::s1ap::cause_protocol_opts::unspecified;
|
||||
trigger(ho_cancel_ev{cause});
|
||||
return;
|
||||
}
|
||||
|
||||
// Log rrc release event.
|
||||
event_logger::get().log_rrc_event(rrc_ue->ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
|
||||
octet_str,
|
||||
static_cast<unsigned>(rrc_event_type::con_reconf),
|
||||
static_cast<unsigned>(procedure_result_code::none),
|
||||
rrc_ue->rnti);
|
||||
|
||||
/* Start S1AP eNBStatusTransfer Procedure */
|
||||
asn1::s1ap::cause_c cause = start_enb_status_transfer(*ho_cmd.s1ap_ho_cmd);
|
||||
if (cause.type().value != asn1::s1ap::cause_c::types_opts::nulltype) {
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
#include "srsenb/hdr/stack/rrc/ue_rr_cfg.h"
|
||||
#include "srsran/asn1/rrc_utils.h"
|
||||
#include "srsran/common/enb_events.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/common/standard_streams.h"
|
||||
#include "srsran/interfaces/enb_pdcp_interfaces.h"
|
||||
#include "srsran/interfaces/enb_rlc_interfaces.h"
|
||||
#include "srsran/interfaces/enb_s1ap_interfaces.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
|
||||
using namespace asn1::rrc;
|
||||
|
||||
|
@ -1429,7 +1429,7 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg)
|
|||
} else if (srb.srb_id == 2) {
|
||||
srb_cfg = &parent->cfg.srb2_cfg;
|
||||
} else {
|
||||
srsran_terminate("Invalid LTE SRB id=%d", srb.srb_id);
|
||||
srsran_assertion_failure("Invalid LTE SRB id=%d", srb.srb_id);
|
||||
}
|
||||
|
||||
if (srb_cfg->rlc_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) {
|
||||
|
|
|
@ -558,7 +558,7 @@ bool s1ap::handle_mme_rx_msg(srsran::unique_byte_buffer_t pdu,
|
|||
if (flags & MSG_NOTIFICATION) {
|
||||
// Received notification
|
||||
union sctp_notification* notification = (union sctp_notification*)pdu->msg;
|
||||
logger.debug("SCTP Notification %d", notification->sn_header.sn_type);
|
||||
logger.info("SCTP Notification %04x", notification->sn_header.sn_type);
|
||||
if (notification->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) {
|
||||
logger.info("SCTP Association Shutdown. Association: %d", sri.sinfo_assoc_id);
|
||||
srsran::console("SCTP Association Shutdown. Association: %d\n", sri.sinfo_assoc_id);
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
#include "srsran/upper/gtpu.h"
|
||||
#include "srsenb/hdr/stack/upper/gtpu.h"
|
||||
#include "srsran/common/network_utils.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/common/standard_streams.h"
|
||||
#include "srsran/common/string_helpers.h"
|
||||
#include "srsran/interfaces/enb_interfaces.h"
|
||||
#include "srsran/interfaces/enb_pdcp_interfaces.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <linux/ip.h>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "srsenb/hdr/stack/mac/sched_lte_common.h"
|
||||
#include "srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h"
|
||||
#include "srsran/common/common_lte.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
|
@ -260,7 +260,7 @@ int test_min_mcs_tbs_specific()
|
|||
CONDERROR(result.tbs_bytes * 8 != 120, "Invalid min TBS calculation");
|
||||
|
||||
args.req_bytes = 50;
|
||||
TESTASSERT(test_min_mcs_tbs_dl_helper(cell_params, args, &result) == SRSRAN_SUCCESS);
|
||||
TESTASSERT_SUCCESS(test_min_mcs_tbs_dl_helper(cell_params, args, &result));
|
||||
CONDERROR(result.tbs_bytes < (int)args.req_bytes, "Invalid MCS calculation");
|
||||
CONDERROR(result.tbs_bytes * 8 != 424, "Invalid min TBS calculation");
|
||||
|
||||
|
@ -273,7 +273,7 @@ int test_min_mcs_tbs_specific()
|
|||
|
||||
// Check equality case
|
||||
args.req_bytes = 109;
|
||||
TESTASSERT(test_min_mcs_tbs_dl_helper(cell_params, args, &result) == SRSRAN_SUCCESS);
|
||||
TESTASSERT_SUCCESS(test_min_mcs_tbs_dl_helper(cell_params, args, &result));
|
||||
CONDERROR(result.tbs_bytes < (int)args.req_bytes, "Invalid MCS calculation");
|
||||
CONDERROR(result.tbs_bytes * 8 != 872, "Invalid min TBS calculation");
|
||||
|
||||
|
@ -303,18 +303,18 @@ void test_ul_mcs_tbs_derivation()
|
|||
};
|
||||
|
||||
cqi = 0;
|
||||
TESTASSERT(compute_tbs_mcs(25, 25 - 4).mcs == 0);
|
||||
TESTASSERT(compute_tbs_mcs(50, 50 - 5).mcs == 0);
|
||||
TESTASSERT_EQ(0, compute_tbs_mcs(25, 25 - 4).mcs);
|
||||
TESTASSERT_EQ(0, compute_tbs_mcs(50, 50 - 5).mcs);
|
||||
|
||||
cqi = 5;
|
||||
TESTASSERT(compute_tbs_mcs(25, 25 - 4).mcs == 9);
|
||||
TESTASSERT(compute_tbs_mcs(50, 50 - 5).mcs == 9);
|
||||
TESTASSERT_EQ(9, compute_tbs_mcs(25, 25 - 4).mcs);
|
||||
TESTASSERT_EQ(9, compute_tbs_mcs(50, 50 - 5).mcs);
|
||||
|
||||
cqi = 15;
|
||||
TESTASSERT(compute_tbs_mcs(25, 25 - 4).mcs == 23);
|
||||
TESTASSERT(compute_tbs_mcs(50, 50 - 5).mcs == 23);
|
||||
TESTASSERT(compute_tbs_mcs(75, 75 - 5).mcs == 24);
|
||||
TESTASSERT(compute_tbs_mcs(100, 100 - 5).mcs == 23);
|
||||
TESTASSERT_EQ(23, compute_tbs_mcs(25, 25 - 4).mcs);
|
||||
TESTASSERT_EQ(23, compute_tbs_mcs(50, 50 - 5).mcs);
|
||||
TESTASSERT_EQ(24, compute_tbs_mcs(75, 75 - 5).mcs);
|
||||
TESTASSERT_EQ(23, compute_tbs_mcs(100, 100 - 5).mcs);
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -358,8 +358,19 @@ int test_ra(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
|
|||
// TEST: No UL allocs except for Msg3 before Msg4
|
||||
for (uint32_t i = 0; i < ul_cc_res.pusch.size(); ++i) {
|
||||
if (ul_cc_res.pusch[i].dci.rnti == rnti) {
|
||||
CONDERROR(not ue.rar_tti_rx.is_valid(), "No UL allocs before RAR allowed");
|
||||
srsran::tti_point expected_msg3_tti = ue.rar_tti_rx + MSG3_DELAY_MS;
|
||||
tti_point rar_tti_rx = ue.rar_tti_rx;
|
||||
if (not rar_tti_rx.is_valid()) {
|
||||
for (uint32_t j = 0; j < dl_cc_res.rar.size(); ++j) {
|
||||
for (const auto& grant : dl_cc_res.rar[i].msg3_grant) {
|
||||
if (grant.data.temp_crnti == ue.rnti) {
|
||||
rar_tti_rx = sf_out.tti_rx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CONDERROR(not rar_tti_rx.is_valid(), "No UL allocs before RAR allowed");
|
||||
srsran::tti_point expected_msg3_tti = rar_tti_rx + MSG3_DELAY_MS;
|
||||
CONDERROR(expected_msg3_tti > sf_out.tti_rx, "No UL allocs before Msg3 is scheduled");
|
||||
if (expected_msg3_tti < sf_out.tti_rx) {
|
||||
bool msg3_retx =
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "rrc_cell.h"
|
||||
#include "rrc_common.h"
|
||||
#include "rrc_metrics.h"
|
||||
#include "rrc_rlf_report.h"
|
||||
#include "srsran/asn1/rrc_utils.h"
|
||||
#include "srsran/common/bcd_helpers.h"
|
||||
#include "srsran/common/block_queue.h"
|
||||
|
@ -227,6 +228,9 @@ private:
|
|||
|
||||
const char* get_rb_name(uint32_t lcid) { return srsran::is_lte_rb(lcid) ? rb_id_str[lcid].c_str() : "invalid RB"; }
|
||||
|
||||
// Var-RLF-Report class
|
||||
rrc_rlf_report var_rlf_report;
|
||||
|
||||
// Measurements private subclass
|
||||
class rrc_meas;
|
||||
std::unique_ptr<rrc_meas> measurements;
|
||||
|
@ -384,6 +388,7 @@ private:
|
|||
void handle_con_reest(const asn1::rrc::rrc_conn_reest_s& setup);
|
||||
void handle_rrc_con_reconfig(uint32_t lcid, const asn1::rrc::rrc_conn_recfg_s& reconfig);
|
||||
void handle_ue_capability_enquiry(const asn1::rrc::ue_cap_enquiry_s& enquiry);
|
||||
void handle_ue_info_request(const ue_info_request_r9_s& request);
|
||||
void add_srb(const asn1::rrc::srb_to_add_mod_s& srb_cnfg);
|
||||
void add_drb(const asn1::rrc::drb_to_add_mod_s& drb_cnfg);
|
||||
void release_drb(uint32_t drb_id);
|
||||
|
|
|
@ -156,6 +156,7 @@ public:
|
|||
bool has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const;
|
||||
uint32_t nof_plmns() const { return has_sib1() ? sib1.cell_access_related_info.plmn_id_list.size() : 0; }
|
||||
srsran::plmn_id_t get_plmn(uint32_t idx) const;
|
||||
asn1::rrc::plmn_id_s get_plmn_asn1(uint32_t idx) const;
|
||||
|
||||
uint16_t get_tac() const { return has_sib1() ? (uint16_t)sib1.cell_access_related_info.tac.to_number() : 0; }
|
||||
|
||||
|
@ -170,6 +171,7 @@ public:
|
|||
const asn1::rrc::sib_type13_r9_s* sib13ptr() const { return has_sib13() ? &sib13 : nullptr; }
|
||||
|
||||
uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); }
|
||||
asn1::fixed_bitstring<28> get_cell_id_bit() const { return sib1.cell_access_related_info.cell_id; }
|
||||
|
||||
bool has_sib13() const { return has_valid_sib13; }
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
namespace srsue {
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// RRC states (3GPP 36.331 v10.0.0)
|
||||
typedef enum {
|
||||
RRC_STATE_IDLE = 0,
|
||||
|
@ -32,6 +34,11 @@ typedef enum {
|
|||
} rrc_state_t;
|
||||
static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", "CONNECTED"};
|
||||
|
||||
enum quant_s { quant_rsrp, quant_rsrq };
|
||||
|
||||
uint8_t rrc_value_to_range(quant_s quant, const float value);
|
||||
float rrc_range_to_value(quant_s quant, const uint8_t range);
|
||||
|
||||
} // namespace srsue
|
||||
|
||||
#endif // SRSUE_RRC_COMMON_H
|
||||
|
|
|
@ -201,8 +201,6 @@ private:
|
|||
rrc* rrc_ptr = nullptr;
|
||||
|
||||
// Static functions
|
||||
static uint8_t value_to_range(const report_cfg_eutra_s::trigger_quant_opts::options q, float value);
|
||||
static float range_to_value(const report_cfg_eutra_s::trigger_quant_opts::options q, const uint8_t range);
|
||||
static uint8_t value_to_range_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const float value);
|
||||
static float range_to_value_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const uint8_t range);
|
||||
static uint8_t offset_val(const meas_obj_eutra_s& meas_obj);
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#ifndef SRSRAN_RRC_RLF_REPORT_H_
|
||||
#define SRSRAN_RRC_RLF_REPORT_H_
|
||||
|
||||
#include "rrc_cell.h"
|
||||
#include "srsran/asn1/rrc.h"
|
||||
#include "srsran/common/common.h"
|
||||
|
||||
namespace srsue {
|
||||
|
||||
using namespace asn1::rrc;
|
||||
|
||||
// RRC RLF-Report class
|
||||
class rrc_rlf_report
|
||||
{
|
||||
public:
|
||||
enum failure_type_t { rlf, hof };
|
||||
|
||||
void init(srsran::task_sched_handle task_sched);
|
||||
|
||||
// Returns true if VarRLF-Report structure has info available
|
||||
bool has_info();
|
||||
|
||||
// Called upon T304 expiry (type == hof) or Detection of radio link failure (type == rlf)
|
||||
void set_failure(meas_cell_list<meas_cell_eutra>& meas_cells, failure_type_t type);
|
||||
|
||||
// Called upon transmission of ReestablishmentRequest message
|
||||
void set_reest_gci(const asn1::fixed_bitstring<28>& gci, const asn1::rrc::plmn_id_s& plmn_id);
|
||||
|
||||
// Called upon initiation of RadioReconfiguration message including MobilityInfo IE
|
||||
void received_ho_command(const asn1::fixed_bitstring<28>& current_gci);
|
||||
|
||||
// Returns a copy of the rlf_report_r9 ASN1 struct
|
||||
rlf_report_r9_s get_report();
|
||||
|
||||
// Clears VarRLF-Report contents
|
||||
void clear();
|
||||
|
||||
private:
|
||||
asn1::fixed_bitstring<28> ho_gci;
|
||||
|
||||
bool has_event = false;
|
||||
rlf_report_r9_s rlf_report = {};
|
||||
srsran::timer_handler::unique_timer timer_conn_failure = {};
|
||||
};
|
||||
} // namespace srsue
|
||||
|
||||
#endif // SRSRAN_RRC_RLF_REPORT_H_
|
|
@ -185,7 +185,7 @@ void cc_worker::decode_pdcch_dl()
|
|||
for (uint32_t i = 0; i < ue_dl.pdcch_info_count; i++) {
|
||||
const srsran_ue_dl_nr_pdcch_info_t* info = &ue_dl.pdcch_info[i];
|
||||
logger.debug("PDCCH: dci=%s, rnti=%x, crst_id=%d, ss_type=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; "
|
||||
"nof_bits=%d; crc=%s;",
|
||||
"evm=%f; nof_bits=%d; crc=%s;",
|
||||
srsran_dci_format_nr_string(info->dci_ctx.format),
|
||||
info->dci_ctx.rnti,
|
||||
info->dci_ctx.coreset_id,
|
||||
|
@ -195,6 +195,7 @@ void cc_worker::decode_pdcch_dl()
|
|||
info->measure.epre_dBfs,
|
||||
info->measure.rsrp_dBfs,
|
||||
info->measure.norm_corr,
|
||||
info->result.evm,
|
||||
info->nof_bits,
|
||||
info->result.crc ? "OK" : "KO");
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#include "srsran/asn1/rrc/rr_common.h"
|
||||
#include "srsran/asn1/rrc_utils.h"
|
||||
#include "srsran/common/mac_pcap.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/common/tsan_options.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include "srsran/test/ue_test_interfaces.h"
|
||||
#include "srsue/hdr/stack/mac/mac.h"
|
||||
#include "srsue/hdr/stack/mac/mux.h"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
add_subdirectory(test)
|
||||
|
||||
set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc phy_controller.cc)
|
||||
set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc rrc_common.cc rrc_rlf_report.cc phy_controller.cc)
|
||||
add_library(srsue_rrc STATIC ${SOURCES})
|
||||
|
||||
set(SOURCES rrc_nr.cc)
|
||||
|
|
|
@ -148,6 +148,8 @@ void rrc::init(phy_interface_rrc_lte* phy_,
|
|||
t311 = task_sched.get_unique_timer();
|
||||
t304 = task_sched.get_unique_timer();
|
||||
|
||||
var_rlf_report.init(task_sched);
|
||||
|
||||
transaction_id = 0;
|
||||
|
||||
cell_clean_cnt = 0;
|
||||
|
@ -683,6 +685,9 @@ void rrc::radio_link_failure_process()
|
|||
// TODO: Generate and store failure report
|
||||
srsran::console("Warning: Detected Radio-Link Failure\n");
|
||||
|
||||
// Store the information in VarRLF-Report
|
||||
var_rlf_report.set_failure(meas_cells, rrc_rlf_report::rlf);
|
||||
|
||||
if (state == RRC_STATE_CONNECTED) {
|
||||
if (security_is_activated) {
|
||||
logger.info("Detected Radio-Link Failure with active AS security. Starting ConnectionReestablishment...");
|
||||
|
@ -866,6 +871,9 @@ void rrc::send_con_restablish_request(reest_cause_e cause, uint16_t crnti, uint1
|
|||
// Clean reestablishment type
|
||||
reestablishment_successful = false;
|
||||
|
||||
// set the reestablishmentCellId in the VarRLF-Report to the global cell identity of the selected cell;
|
||||
var_rlf_report.set_reest_gci(meas_cells.serving_cell().get_cell_id_bit(), meas_cells.serving_cell().get_plmn_asn1(0));
|
||||
|
||||
if (cause.value != reest_cause_opts::ho_fail) {
|
||||
if (cause.value != reest_cause_opts::other_fail) {
|
||||
pci = meas_cells.serving_cell().get_pci();
|
||||
|
@ -954,6 +962,15 @@ void rrc::send_con_restablish_complete()
|
|||
ul_dcch_msg.msg.set_c1().set_rrc_conn_reest_complete().crit_exts.set_rrc_conn_reest_complete_r8();
|
||||
ul_dcch_msg.msg.c1().rrc_conn_reest_complete().rrc_transaction_id = transaction_id;
|
||||
|
||||
// Include rlf-InfoAvailable
|
||||
if (var_rlf_report.has_info()) {
|
||||
ul_dcch_msg.msg.c1().rrc_conn_reest_complete().crit_exts.rrc_conn_reest_complete_r8().non_crit_ext_present = true;
|
||||
ul_dcch_msg.msg.c1()
|
||||
.rrc_conn_reest_complete()
|
||||
.crit_exts.rrc_conn_reest_complete_r8()
|
||||
.non_crit_ext.rlf_info_available_r9_present = true;
|
||||
}
|
||||
|
||||
send_ul_dcch_msg(srb_to_lcid(lte_srb::srb1), ul_dcch_msg);
|
||||
|
||||
reestablishment_successful = true;
|
||||
|
@ -970,6 +987,13 @@ void rrc::send_con_setup_complete(srsran::unique_byte_buffer_t nas_msg)
|
|||
|
||||
ul_dcch_msg.msg.c1().rrc_conn_setup_complete().rrc_transaction_id = transaction_id;
|
||||
|
||||
// Include rlf-InfoAvailable
|
||||
if (var_rlf_report.has_info()) {
|
||||
rrc_conn_setup_complete->non_crit_ext_present = true;
|
||||
rrc_conn_setup_complete->non_crit_ext.non_crit_ext_present = true;
|
||||
rrc_conn_setup_complete->non_crit_ext.non_crit_ext.rlf_info_available_r10_present = true;
|
||||
}
|
||||
|
||||
rrc_conn_setup_complete->sel_plmn_id = 1;
|
||||
rrc_conn_setup_complete->ded_info_nas.resize(nas_msg->N_bytes);
|
||||
memcpy(rrc_conn_setup_complete->ded_info_nas.data(), nas_msg->msg, nas_msg->N_bytes); // TODO Check!
|
||||
|
@ -1014,6 +1038,13 @@ void rrc::send_rrc_con_reconfig_complete(bool contains_nr_complete)
|
|||
&ul_dcch_msg.msg.set_c1().set_rrc_conn_recfg_complete().crit_exts.set_rrc_conn_recfg_complete_r8();
|
||||
ul_dcch_msg.msg.c1().rrc_conn_recfg_complete().rrc_transaction_id = transaction_id;
|
||||
|
||||
// Include rlf-InfoAvailable
|
||||
if (var_rlf_report.has_info()) {
|
||||
rrc_conn_recfg_complete_r8->non_crit_ext_present = true;
|
||||
rrc_conn_recfg_complete_r8->non_crit_ext.non_crit_ext_present = true;
|
||||
rrc_conn_recfg_complete_r8->non_crit_ext.non_crit_ext.rlf_info_available_r10_present = true;
|
||||
}
|
||||
|
||||
if (contains_nr_complete == true) {
|
||||
logger.debug("Preparing RRC Connection Reconfig Complete with NR Complete");
|
||||
|
||||
|
@ -1064,6 +1095,10 @@ void rrc::start_go_idle()
|
|||
void rrc::ho_failed()
|
||||
{
|
||||
ho_handler.trigger(ho_proc::t304_expiry{});
|
||||
|
||||
// Store the information in VarRLF-Report
|
||||
var_rlf_report.set_failure(meas_cells, rrc_rlf_report::hof);
|
||||
|
||||
start_con_restablishment(reest_cause_e::ho_fail);
|
||||
}
|
||||
|
||||
|
@ -1766,6 +1801,10 @@ void rrc::parse_dl_dcch(uint32_t lcid, unique_byte_buffer_t pdu)
|
|||
case dl_dcch_msg_type_c::c1_c_::types::rrc_conn_release:
|
||||
rrc_connection_release(c1->rrc_conn_release().crit_exts.c1().rrc_conn_release_r8().release_cause.to_string());
|
||||
break;
|
||||
case dl_dcch_msg_type_c::c1_c_::types::ue_info_request_r9:
|
||||
transaction_id = c1->ue_info_request_r9().rrc_transaction_id;
|
||||
handle_ue_info_request(c1->ue_info_request_r9());
|
||||
break;
|
||||
default:
|
||||
logger.error("The provided DL-CCCH message type is not recognized or supported");
|
||||
break;
|
||||
|
@ -2145,6 +2184,42 @@ void rrc::handle_ue_capability_enquiry(const ue_cap_enquiry_s& enquiry)
|
|||
send_ul_dcch_msg(srb_to_lcid(lte_srb::srb1), ul_dcch_msg);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
* UEInformationRequest message
|
||||
*
|
||||
*
|
||||
*
|
||||
*******************************************************************************/
|
||||
void rrc::handle_ue_info_request(const ue_info_request_r9_s& request)
|
||||
{
|
||||
logger.debug("Preparing UEInformationResponse message");
|
||||
|
||||
ul_dcch_msg_s ul_dcch_msg;
|
||||
ue_info_resp_r9_ies_s* resp =
|
||||
&ul_dcch_msg.msg.set_c1().set_ue_info_resp_r9().crit_exts.set_c1().set_ue_info_resp_r9();
|
||||
ul_dcch_msg.msg.c1().ue_info_resp_r9().rrc_transaction_id = transaction_id;
|
||||
|
||||
// if rach-ReportReq is set to true, set the contents of the rach-Report in the UEInformationResponse message as
|
||||
// follows
|
||||
if (request.crit_exts.c1().ue_info_request_r9().rach_report_req_r9) {
|
||||
// todo...
|
||||
}
|
||||
|
||||
// Include rlf-Report if rlf-ReportReq is set to true
|
||||
if (request.crit_exts.c1().ue_info_request_r9().rlf_report_req_r9 && var_rlf_report.has_info()) {
|
||||
resp->rlf_report_r9_present = true;
|
||||
resp->rlf_report_r9 = var_rlf_report.get_report();
|
||||
|
||||
// fixme: should be cleared upon successful delivery
|
||||
var_rlf_report.clear();
|
||||
}
|
||||
|
||||
send_ul_dcch_msg(srb_to_lcid(lte_srb::srb1), ul_dcch_msg);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
*
|
||||
|
|
|
@ -42,6 +42,15 @@ srsran::plmn_id_t meas_cell_eutra::get_plmn(uint32_t idx) const
|
|||
}
|
||||
}
|
||||
|
||||
asn1::rrc::plmn_id_s meas_cell_eutra::get_plmn_asn1(uint32_t idx) const
|
||||
{
|
||||
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 {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void meas_cell_eutra::set_sib1(const asn1::rrc::sib_type1_s& sib1_)
|
||||
{
|
||||
sib1 = sib1_;
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsue/hdr/stack/rrc/rrc_common.h"
|
||||
|
||||
namespace srsue {
|
||||
|
||||
uint8_t rrc_value_to_range(quant_s quant, const float value)
|
||||
{
|
||||
uint8_t range = 0;
|
||||
if (quant == quant_rsrp) {
|
||||
if (value < -140) {
|
||||
range = 0;
|
||||
} else if (value < -44) {
|
||||
range = 1u + (uint8_t)(value + 140);
|
||||
} else {
|
||||
range = 97;
|
||||
}
|
||||
} else {
|
||||
if (value < -19.5) {
|
||||
range = 0;
|
||||
} else if (value < -3) {
|
||||
range = 1u + (uint8_t)(2 * (value + 19.5));
|
||||
} else {
|
||||
range = 34;
|
||||
}
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
float rrc_range_to_value(quant_s quant, const uint8_t range)
|
||||
{
|
||||
float val = 0;
|
||||
if (quant == quant_rsrp) {
|
||||
val = -140 + (float)range;
|
||||
} else {
|
||||
val = -19.5f + (float)range / 2;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
} // namespace srsue
|
|
@ -139,50 +139,6 @@ void rrc::rrc_meas::run_tti()
|
|||
meas_cfg.report_triggers();
|
||||
}
|
||||
|
||||
uint8_t rrc::rrc_meas::value_to_range(const report_cfg_eutra_s::trigger_quant_opts::options quant, const float value)
|
||||
{
|
||||
uint8_t range = 0;
|
||||
switch (quant) {
|
||||
case report_cfg_eutra_s::trigger_quant_opts::rsrp:
|
||||
if (value < -140) {
|
||||
range = 0;
|
||||
} else if (value < -44) {
|
||||
range = 1u + (uint8_t)(value + 140);
|
||||
} else {
|
||||
range = 97;
|
||||
}
|
||||
break;
|
||||
case report_cfg_eutra_s::trigger_quant_opts::rsrq:
|
||||
if (value < -19.5) {
|
||||
range = 0;
|
||||
} else if (value < -3) {
|
||||
range = 1u + (uint8_t)(2 * (value + 19.5));
|
||||
} else {
|
||||
range = 34;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
float rrc::rrc_meas::range_to_value(const report_cfg_eutra_s::trigger_quant_opts::options quant, const uint8_t range)
|
||||
{
|
||||
float val = 0;
|
||||
switch (quant) {
|
||||
case report_cfg_eutra_s::trigger_quant_opts::rsrp:
|
||||
val = -140 + (float)range;
|
||||
break;
|
||||
case report_cfg_eutra_s::trigger_quant_opts::rsrq:
|
||||
val = -19.5f + (float)range / 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// For thresholds, the actual value is (field value – 156) dBm, except for field value 127, in which case the actual
|
||||
// value is infinity.
|
||||
float rrc::rrc_meas::range_to_value_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const uint8_t range)
|
||||
|
@ -312,8 +268,8 @@ void rrc::rrc_meas::var_meas_report_list::generate_report_eutra(meas_results_s*
|
|||
break;
|
||||
}
|
||||
rc.pci = (uint16_t)cell.pci;
|
||||
rc.meas_result.rsrp_result = value_to_range(report_cfg_eutra_s::trigger_quant_opts::rsrp, rsrp_value);
|
||||
rc.meas_result.rsrq_result = value_to_range(report_cfg_eutra_s::trigger_quant_opts::rsrq, rsrq_value);
|
||||
rc.meas_result.rsrp_result = rrc_value_to_range(quant_rsrp, rsrp_value);
|
||||
rc.meas_result.rsrq_result = rrc_value_to_range(quant_rsrq, rsrq_value);
|
||||
|
||||
logger.info("MEAS: Adding to report neighbour=%d, pci=%d, earfcn=%d, rsrp=%+.1f, rsrq=%+.1f",
|
||||
neigh_list.size(),
|
||||
|
@ -457,10 +413,8 @@ void rrc::rrc_meas::var_meas_report_list::generate_report(const uint32_t measId)
|
|||
meas_results_s* report = &ul_dcch_msg.msg.c1().meas_report().crit_exts.c1().meas_report_r8().meas_results;
|
||||
|
||||
report->meas_id = (uint8_t)measId;
|
||||
report->meas_result_pcell.rsrp_result =
|
||||
value_to_range(report_cfg_eutra_s::trigger_quant_opts::rsrp, serv_cell->get_rsrp());
|
||||
report->meas_result_pcell.rsrq_result =
|
||||
value_to_range(report_cfg_eutra_s::trigger_quant_opts::rsrq, serv_cell->get_rsrq());
|
||||
report->meas_result_pcell.rsrp_result = rrc_value_to_range(quant_rsrp, serv_cell->get_rsrp());
|
||||
report->meas_result_pcell.rsrq_result = rrc_value_to_range(quant_rsrq, serv_cell->get_rsrq());
|
||||
|
||||
logger.info("MEAS: Generate report MeasId=%d, Pcell rsrp=%f rsrq=%f",
|
||||
report->meas_id,
|
||||
|
@ -814,6 +768,14 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
|
|||
float Ofs,
|
||||
float Ocs)
|
||||
{
|
||||
auto asn1_quant_convert = [](report_cfg_eutra_s::trigger_quant_e_ q) {
|
||||
if (q == report_cfg_eutra_s::trigger_quant_opts::rsrp) {
|
||||
return quant_rsrp;
|
||||
} else {
|
||||
return quant_rsrq;
|
||||
}
|
||||
};
|
||||
|
||||
double hyst = 0.5 * report_cfg.trigger_type.event().hysteresis;
|
||||
float Ms = is_rsrp(report_cfg.trigger_quant.value) ? serv_cell->get_rsrp() : serv_cell->get_rsrq();
|
||||
|
||||
|
@ -832,17 +794,21 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
|
|||
bool exit_condition = false;
|
||||
if (event_id.type() == eutra_event_s::event_id_c_::types::event_a1) {
|
||||
if (event_id.event_a1().a1_thres.type().value == thres_eutra_c::types::thres_rsrp) {
|
||||
thresh = range_to_value(report_cfg.trigger_quant, event_id.event_a1().a1_thres.thres_rsrp());
|
||||
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant),
|
||||
event_id.event_a1().a1_thres.thres_rsrp());
|
||||
} else {
|
||||
thresh = range_to_value(report_cfg.trigger_quant, event_id.event_a1().a1_thres.thres_rsrq());
|
||||
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant),
|
||||
event_id.event_a1().a1_thres.thres_rsrq());
|
||||
}
|
||||
enter_condition = Ms - hyst > thresh;
|
||||
exit_condition = Ms + hyst < thresh;
|
||||
} else {
|
||||
if (event_id.event_a2().a2_thres.type() == thres_eutra_c::types::thres_rsrp) {
|
||||
thresh = range_to_value(report_cfg.trigger_quant, event_id.event_a2().a2_thres.thres_rsrp());
|
||||
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant),
|
||||
event_id.event_a2().a2_thres.thres_rsrp());
|
||||
} else {
|
||||
thresh = range_to_value(report_cfg.trigger_quant, event_id.event_a2().a2_thres.thres_rsrq());
|
||||
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant),
|
||||
event_id.event_a2().a2_thres.thres_rsrq());
|
||||
}
|
||||
enter_condition = Ms + hyst < thresh;
|
||||
exit_condition = Ms - hyst > thresh;
|
||||
|
@ -893,7 +859,7 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
|
|||
} else {
|
||||
range = event_id.event_a4().a4_thres.thres_rsrq();
|
||||
}
|
||||
thresh = range_to_value(report_cfg.trigger_quant.value, range);
|
||||
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant.value), range);
|
||||
enter_condition = Mn + Ofn + Ocn - hyst > thresh;
|
||||
exit_condition = Mn + Ofn + Ocn + hyst < thresh;
|
||||
break;
|
||||
|
@ -908,8 +874,8 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
|
|||
} else {
|
||||
range2 = event_id.event_a5().a5_thres2.thres_rsrq();
|
||||
}
|
||||
th1 = range_to_value(report_cfg.trigger_quant.value, range);
|
||||
th2 = range_to_value(report_cfg.trigger_quant.value, range2);
|
||||
th1 = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant.value), range);
|
||||
th2 = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant.value), range2);
|
||||
enter_condition = (Ms + hyst < th1) && (Mn + Ofn + Ocn - hyst > th2);
|
||||
exit_condition = (Ms - hyst > th1) && (Mn + Ofn + Ocn + hyst < th2);
|
||||
break;
|
||||
|
@ -1479,19 +1445,18 @@ void rrc::rrc_meas::var_meas_cfg::log_debug_trigger_value_eutra(const eutra_even
|
|||
switch (e.type()) {
|
||||
case eutra_event_s::event_id_c_::types_opts::event_a1:
|
||||
logger.debug("MEAS: A1-threshold=%.1f dBm",
|
||||
range_to_value(report_cfg_eutra_s::trigger_quant_opts::rsrp, e.event_a1().a1_thres.thres_rsrp()));
|
||||
rrc_range_to_value(quant_rsrp, e.event_a1().a1_thres.thres_rsrp()));
|
||||
break;
|
||||
case eutra_event_s::event_id_c_::types_opts::event_a2:
|
||||
logger.debug("MEAS: A2-threshold=%.1f dBm",
|
||||
range_to_value(report_cfg_eutra_s::trigger_quant_opts::rsrp, e.event_a2().a2_thres.thres_rsrp()));
|
||||
rrc_range_to_value(quant_rsrp, e.event_a2().a2_thres.thres_rsrp()));
|
||||
break;
|
||||
case eutra_event_s::event_id_c_::types_opts::event_a3:
|
||||
logger.debug("MEAS: A3-offset=%.1f dB",
|
||||
range_to_value(report_cfg_eutra_s::trigger_quant_opts::rsrp, e.event_a3().a3_offset));
|
||||
logger.debug("MEAS: A3-offset=%.1f dB", rrc_range_to_value(quant_rsrp, e.event_a3().a3_offset));
|
||||
break;
|
||||
case eutra_event_s::event_id_c_::types_opts::event_a4:
|
||||
logger.debug("MEAS: A4-threshold=%.1f dBm",
|
||||
range_to_value(report_cfg_eutra_s::trigger_quant_opts::rsrp, e.event_a4().a4_thres.thres_rsrp()));
|
||||
rrc_range_to_value(quant_rsrp, e.event_a4().a4_thres.thres_rsrp()));
|
||||
break;
|
||||
default:
|
||||
logger.debug("MEAS: Unsupported");
|
||||
|
@ -1606,7 +1571,7 @@ bool rrc::rrc_meas::var_meas_cfg::parse_meas_config(const meas_cfg_s* cfg, bool
|
|||
// set the parameter s-Measure within VarMeasConfig to the lowest value of the RSRP ranges indicated by the
|
||||
// received value of s-Measure
|
||||
if (cfg->s_measure) {
|
||||
s_measure_value = range_to_value(report_cfg_eutra_s::trigger_quant_opts::options::rsrp, cfg->s_measure);
|
||||
s_measure_value = rrc_range_to_value(quant_rsrp, cfg->s_measure);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1665,6 +1665,9 @@ srsran::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc
|
|||
rrc_ptr->t304.set(mob_ctrl_info->t304.to_number(), [this](uint32_t tid) { rrc_ptr->timer_expired(tid); });
|
||||
rrc_ptr->t304.run();
|
||||
|
||||
// Indicate RLF-Report that a new HO has been received
|
||||
rrc_ptr->var_rlf_report.received_ho_command(rrc_ptr->meas_cells.serving_cell().get_cell_id_bit());
|
||||
|
||||
// starting at start synchronising to the DL of the target PCell
|
||||
rrc_ptr->set_serving_cell(target_cell, false);
|
||||
Info("Starting cell selection of target cell PCI=%d EARFCN=%d", target_cell.pci, target_cell.earfcn);
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsue/hdr/stack/rrc/rrc_rlf_report.h"
|
||||
#include "srsue/hdr/stack/rrc/rrc_common.h"
|
||||
|
||||
namespace srsue {
|
||||
|
||||
void rrc_rlf_report::init(srsran::task_sched_handle task_sched)
|
||||
{
|
||||
timer_conn_failure = task_sched.get_unique_timer();
|
||||
}
|
||||
|
||||
// Returns true if VarRLF-Report structure has info available
|
||||
bool rrc_rlf_report::has_info()
|
||||
{
|
||||
return has_event;
|
||||
}
|
||||
|
||||
// Called upon T304 expiry (type == hof) or Detection of radio link failure (type == rlf)
|
||||
void rrc_rlf_report::set_failure(meas_cell_list<meas_cell_eutra>& meas_cells, failure_type_t type)
|
||||
{
|
||||
has_event = true;
|
||||
|
||||
// clear the information included in VarRLF-Report, if any
|
||||
rlf_report = {};
|
||||
|
||||
// set the plmn-Identity to the RPLMN
|
||||
|
||||
// set the measResultLastServCell to include the RSRP and RSRQ, if available, of the PCell based on
|
||||
// measurements collected up to the moment the UE detected radio link failure
|
||||
rlf_report.meas_result_last_serv_cell_r9.rsrp_result_r9 =
|
||||
rrc_value_to_range(quant_rsrp, meas_cells.serving_cell().get_rsrp());
|
||||
rlf_report.meas_result_last_serv_cell_r9.rsrq_result_r9 =
|
||||
rrc_value_to_range(quant_rsrq, meas_cells.serving_cell().get_rsrq());
|
||||
rlf_report.meas_result_last_serv_cell_r9.rsrq_result_r9_present = true;
|
||||
|
||||
// set the measResultNeighCells to include the best measured cells, other than the PCell, ordered such that
|
||||
// the best cell is listed first, and based on measurements collected up to the moment the UE detected radio
|
||||
// link failure
|
||||
if (meas_cells.nof_neighbours() > 0) {
|
||||
rlf_report.meas_result_neigh_cells_r9_present = true;
|
||||
rlf_report.meas_result_neigh_cells_r9.meas_result_list_eutra_r9_present = true;
|
||||
rlf_report.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.clear();
|
||||
meas_cells.sort_neighbour_cells();
|
||||
// It is not clear how the sorting and grouping of cells per frequency must be done.
|
||||
// We use a separate MeasResultList2EUTRA-r9 struct for each pci/frequency pair
|
||||
for (const auto& f : meas_cells) {
|
||||
meas_result2_eutra_r9_s meas2 = {};
|
||||
meas2.carrier_freq_r9 = f->get_earfcn();
|
||||
meas_result_eutra_s meas = {};
|
||||
meas.pci = f->get_pci();
|
||||
meas.meas_result.rsrp_result_present = true;
|
||||
meas.meas_result.rsrq_result_present = true;
|
||||
meas.meas_result.rsrp_result = rrc_value_to_range(quant_rsrp, f->get_rsrp());
|
||||
meas.meas_result.rsrq_result = rrc_value_to_range(quant_rsrq, f->get_rsrq());
|
||||
meas2.meas_result_list_r9.push_back(meas);
|
||||
rlf_report.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.push_back(meas2);
|
||||
}
|
||||
}
|
||||
|
||||
// set the failedPCellId to the global cell identity, if available, and otherwise to the physical cell identity and
|
||||
// carrier frequency of the PCell where radio link failure is detected;
|
||||
rlf_report.failed_pcell_id_r10.set_present(true);
|
||||
if (meas_cells.serving_cell().has_sib1()) {
|
||||
rlf_report.failed_pcell_id_r10->set_cell_global_id_r10().cell_id = meas_cells.serving_cell().get_cell_id_bit();
|
||||
rlf_report.failed_pcell_id_r10->cell_global_id_r10().plmn_id = meas_cells.serving_cell().get_plmn_asn1(0);
|
||||
} else {
|
||||
rlf_report.failed_pcell_id_r10->set_pci_arfcn_r10();
|
||||
rlf_report.failed_pcell_id_r10->pci_arfcn_r10().pci_r10 = meas_cells.serving_cell().get_pci();
|
||||
rlf_report.failed_pcell_id_r10->pci_arfcn_r10().carrier_freq_r10 = meas_cells.serving_cell().get_earfcn();
|
||||
}
|
||||
|
||||
// if an RRCConnectionReconfiguration message including the mobilityControlInfo was received before the
|
||||
// connection failure
|
||||
if (timer_conn_failure.is_running()) {
|
||||
timer_conn_failure.stop();
|
||||
|
||||
// include previousPCellId and set it to the global cell identity of the PCell where the last
|
||||
// RRCConnectionReconfiguration including the mobilityControlInfo message was received;
|
||||
rlf_report.prev_pcell_id_r10.set_present(true);
|
||||
rlf_report.prev_pcell_id_r10->cell_id = ho_gci;
|
||||
rlf_report.prev_pcell_id_r10->plmn_id = meas_cells.serving_cell().get_plmn_asn1(0);
|
||||
|
||||
// set the timeConnFailure to the elapsed time since reception of the last
|
||||
// RRCConnectionReconfiguration message including the mobilityControlInfo;
|
||||
rlf_report.time_conn_fail_r10_present = true;
|
||||
rlf_report.time_conn_fail_r10 = timer_conn_failure.time_elapsed() / 100; // 1 unit = 100 ms
|
||||
}
|
||||
|
||||
// set the connectionFailureType
|
||||
rlf_report.conn_fail_type_r10_present = true;
|
||||
rlf_report.conn_fail_type_r10 =
|
||||
type == rlf ? rlf_report_r9_s::conn_fail_type_r10_opts::rlf : rlf_report_r9_s::conn_fail_type_r10_opts::hof;
|
||||
|
||||
rlf_report.ext = true;
|
||||
}
|
||||
|
||||
void rrc_rlf_report::set_reest_gci(const asn1::fixed_bitstring<28>& gci, const asn1::rrc::plmn_id_s& plmn_id)
|
||||
{
|
||||
rlf_report.reest_cell_id_r10.set_present(true);
|
||||
rlf_report.reest_cell_id_r10->cell_id = gci;
|
||||
rlf_report.reest_cell_id_r10->plmn_id = plmn_id;
|
||||
}
|
||||
|
||||
void rrc_rlf_report::received_ho_command(const asn1::fixed_bitstring<28>& current_gci)
|
||||
{
|
||||
if (timer_conn_failure.is_valid()) {
|
||||
timer_conn_failure.stop();
|
||||
timer_conn_failure.run();
|
||||
ho_gci = current_gci;
|
||||
}
|
||||
}
|
||||
|
||||
rlf_report_r9_s rrc_rlf_report::get_report()
|
||||
{
|
||||
return rlf_report;
|
||||
}
|
||||
|
||||
// Clears VarRLF-Report contents
|
||||
void rrc_rlf_report::clear()
|
||||
{
|
||||
has_event = false;
|
||||
rlf_report = {};
|
||||
}
|
||||
|
||||
} // namespace srsue
|
|
@ -34,6 +34,10 @@ add_executable(rrc_cell_test rrc_cell_test.cc)
|
|||
target_link_libraries(rrc_cell_test srsue_rrc srsue_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1)
|
||||
add_test(rrc_cell_test rrc_cell_test)
|
||||
|
||||
add_executable(rrc_rlf_report_test rrc_rlf_report_test.cc)
|
||||
target_link_libraries(rrc_rlf_report_test srsue_rrc srsue_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1)
|
||||
add_test(rrc_rlf_report_test rrc_rlf_report_test)
|
||||
|
||||
add_executable(ue_rrc_nr_test ue_rrc_nr_test.cc)
|
||||
target_link_libraries(ue_rrc_nr_test srsue_rrc_nr srsue_upper srsran_common srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1)
|
||||
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsue/hdr/stack/rrc/rrc_cell.h"
|
||||
#include "srsue/hdr/stack/rrc/rrc_rlf_report.h"
|
||||
|
||||
using namespace srsue;
|
||||
|
||||
int test_single()
|
||||
{
|
||||
srsran::task_scheduler task_sched;
|
||||
rrc_rlf_report rlf_report;
|
||||
meas_cell_list<meas_cell_eutra> list{&task_sched};
|
||||
|
||||
phy_meas_t pmeas{};
|
||||
pmeas.rsrp = -20;
|
||||
pmeas.pci = 1;
|
||||
pmeas.earfcn = 3400;
|
||||
pmeas.rsrq = -10;
|
||||
|
||||
list.add_meas_cell(pmeas);
|
||||
list.set_serving_cell(phy_cell_t{1, 3400}, false);
|
||||
|
||||
rlf_report.set_failure(list, rrc_rlf_report::rlf);
|
||||
|
||||
asn1::json_writer jw;
|
||||
asn1::rrc::rlf_report_r9_s out = rlf_report.get_report();
|
||||
out.to_json(jw);
|
||||
printf("test_single: %s\n", jw.to_string().c_str());
|
||||
|
||||
TESTASSERT(!out.meas_result_neigh_cells_r9_present);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.size() == 0);
|
||||
TESTASSERT(out.failed_pcell_id_r10.is_present());
|
||||
TESTASSERT(out.failed_pcell_id_r10->pci_arfcn_r10().pci_r10 == 1);
|
||||
TESTASSERT(out.failed_pcell_id_r10->pci_arfcn_r10().carrier_freq_r10 = 3400);
|
||||
TESTASSERT(out.conn_fail_type_r10_present);
|
||||
TESTASSERT(out.conn_fail_type_r10.value == asn1::rrc::rlf_report_r9_s::conn_fail_type_r10_e_::rlf);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int test_neighbours()
|
||||
{
|
||||
srsran::task_scheduler task_sched;
|
||||
rrc_rlf_report rlf_report;
|
||||
meas_cell_list<meas_cell_eutra> list{&task_sched};
|
||||
|
||||
phy_meas_t pmeas{};
|
||||
pmeas.rsrp = -20;
|
||||
pmeas.pci = 1;
|
||||
pmeas.earfcn = 3400;
|
||||
pmeas.rsrq = -10;
|
||||
|
||||
list.add_meas_cell(pmeas);
|
||||
pmeas.pci = 4;
|
||||
list.add_meas_cell(pmeas);
|
||||
pmeas.pci = 6;
|
||||
list.add_meas_cell(pmeas);
|
||||
list.set_serving_cell(phy_cell_t{4, 3400}, false);
|
||||
|
||||
TESTASSERT(!rlf_report.has_info());
|
||||
|
||||
rlf_report.set_failure(list, rrc_rlf_report::hof);
|
||||
|
||||
asn1::json_writer jw;
|
||||
asn1::rrc::rlf_report_r9_s out = rlf_report.get_report();
|
||||
out.to_json(jw);
|
||||
printf("test_neighbours: %s\n", jw.to_string().c_str());
|
||||
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9_present);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9_present);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.size() == 2);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9[0].carrier_freq_r9 = 3400);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9[0].meas_result_list_r9[0].pci == 1);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9[1].carrier_freq_r9 = 3400);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9[1].meas_result_list_r9[0].pci == 6);
|
||||
TESTASSERT(out.failed_pcell_id_r10.is_present());
|
||||
TESTASSERT(out.failed_pcell_id_r10->pci_arfcn_r10().pci_r10 == 4);
|
||||
TESTASSERT(out.failed_pcell_id_r10->pci_arfcn_r10().carrier_freq_r10 = 3400);
|
||||
TESTASSERT(out.conn_fail_type_r10_present);
|
||||
TESTASSERT(out.conn_fail_type_r10.value == asn1::rrc::rlf_report_r9_s::conn_fail_type_r10_e_::hof);
|
||||
|
||||
TESTASSERT(rlf_report.has_info());
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int test_reest()
|
||||
{
|
||||
srsran::task_scheduler task_sched;
|
||||
rrc_rlf_report rlf_report;
|
||||
meas_cell_list<meas_cell_eutra> list{&task_sched};
|
||||
|
||||
phy_meas_t pmeas{};
|
||||
pmeas.rsrp = -20;
|
||||
pmeas.pci = 1;
|
||||
pmeas.earfcn = 3400;
|
||||
pmeas.rsrq = -10;
|
||||
|
||||
list.add_meas_cell(pmeas);
|
||||
pmeas.pci = 4;
|
||||
list.add_meas_cell(pmeas);
|
||||
pmeas.pci = 6;
|
||||
list.add_meas_cell(pmeas);
|
||||
list.set_serving_cell(phy_cell_t{4, 3400}, false);
|
||||
|
||||
TESTASSERT(!rlf_report.has_info());
|
||||
|
||||
rlf_report.set_failure(list, rrc_rlf_report::hof);
|
||||
rlf_report.set_reest_gci(list.serving_cell().get_cell_id_bit(), list.serving_cell().get_plmn_asn1(0));
|
||||
|
||||
asn1::json_writer jw;
|
||||
asn1::rrc::rlf_report_r9_s out = rlf_report.get_report();
|
||||
out.to_json(jw);
|
||||
printf("test_reest: %s\n", jw.to_string().c_str());
|
||||
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9_present);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9_present);
|
||||
TESTASSERT(out.failed_pcell_id_r10.is_present());
|
||||
TESTASSERT(out.conn_fail_type_r10_present);
|
||||
TESTASSERT(out.conn_fail_type_r10.value == asn1::rrc::rlf_report_r9_s::conn_fail_type_r10_e_::hof);
|
||||
TESTASSERT(out.reest_cell_id_r10.is_present());
|
||||
|
||||
TESTASSERT(rlf_report.has_info());
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int test_ho()
|
||||
{
|
||||
srsran::task_scheduler task_sched;
|
||||
rrc_rlf_report rlf_report;
|
||||
meas_cell_list<meas_cell_eutra> list{&task_sched};
|
||||
|
||||
rlf_report.init(&task_sched);
|
||||
|
||||
phy_meas_t pmeas{};
|
||||
pmeas.rsrp = -20;
|
||||
pmeas.pci = 1;
|
||||
pmeas.earfcn = 3400;
|
||||
pmeas.rsrq = -10;
|
||||
|
||||
list.add_meas_cell(pmeas);
|
||||
pmeas.pci = 4;
|
||||
list.add_meas_cell(pmeas);
|
||||
pmeas.pci = 6;
|
||||
list.add_meas_cell(pmeas);
|
||||
list.set_serving_cell(phy_cell_t{4, 3400}, false);
|
||||
|
||||
TESTASSERT(!rlf_report.has_info());
|
||||
|
||||
rlf_report.received_ho_command(list.serving_cell().get_cell_id_bit());
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
task_sched.tic();
|
||||
task_sched.run_pending_tasks();
|
||||
}
|
||||
rlf_report.set_failure(list, rrc_rlf_report::hof);
|
||||
rlf_report.set_reest_gci(list.serving_cell().get_cell_id_bit(), list.serving_cell().get_plmn_asn1(0));
|
||||
|
||||
asn1::json_writer jw;
|
||||
asn1::rrc::rlf_report_r9_s out = rlf_report.get_report();
|
||||
out.to_json(jw);
|
||||
printf("test_ho: %s\n", jw.to_string().c_str());
|
||||
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9_present);
|
||||
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9_present);
|
||||
TESTASSERT(out.failed_pcell_id_r10.is_present());
|
||||
TESTASSERT(out.conn_fail_type_r10_present);
|
||||
TESTASSERT(out.conn_fail_type_r10.value == asn1::rrc::rlf_report_r9_s::conn_fail_type_r10_e_::hof);
|
||||
TESTASSERT(out.reest_cell_id_r10.is_present());
|
||||
|
||||
TESTASSERT(rlf_report.has_info());
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TESTASSERT(test_single() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(test_neighbours() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(test_reest() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(test_ho() == SRSRAN_SUCCESS);
|
||||
printf("Success\n");
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
|
@ -20,10 +20,10 @@
|
|||
*/
|
||||
|
||||
#include "srsran/common/bcd_helpers.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/common/tsan_options.h"
|
||||
#include "srsran/interfaces/ue_pdcp_interfaces.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include "srsran/test/ue_test_interfaces.h"
|
||||
#include "srsue/hdr/stack/upper/gw.h"
|
||||
#include "srsue/hdr/stack/upper/nas.h"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/support/srsran_test.h"
|
||||
#include "srsue/hdr/stack/upper/usim.h"
|
||||
|
||||
using namespace srsue;
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
srsran_rnti_type_t dl_rnti_type = srsran_rnti_type_c;
|
||||
uint16_t rnti = 0;
|
||||
bool valid = false;
|
||||
uint32_t sr_period = 0;
|
||||
|
@ -81,7 +82,7 @@ public:
|
|||
}
|
||||
}
|
||||
int sf_indication(const uint32_t tti) override { return 0; }
|
||||
sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; }
|
||||
sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return {rnti, dl_rnti_type}; }
|
||||
sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; }
|
||||
void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) override
|
||||
{
|
||||
|
@ -98,7 +99,11 @@ public:
|
|||
action->tb.payload = tx_harq_proc[grant.pid].get_tb(grant.tbs);
|
||||
action->tb.softbuffer = &tx_harq_proc[grant.pid].get_softbuffer(grant.ndi);
|
||||
}
|
||||
void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {}
|
||||
void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override
|
||||
{
|
||||
dl_rnti_type = srsran_rnti_type_ra;
|
||||
rnti = 1 + s_id + 14 * t_id + 14 * 80 * f_id + 14 * 80 * 8 * ul_carrier_id;
|
||||
}
|
||||
bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override
|
||||
{
|
||||
if (sr_period == 0) {
|
||||
|
|
Loading…
Reference in New Issue