Merge branch 'next' into agpl_next

# Conflicts:
#	srsenb/hdr/stack/upper/pdcp_nr.h
#	srsenb/hdr/stack/upper/rlc_nr.h
#	srsenb/src/stack/upper/pdcp_nr.cc
#	srsenb/src/stack/upper/rlc_nr.cc
master
Codebot 3 years ago committed by Your Name
commit 8c3332f894

@ -64,7 +64,7 @@ struct choice_storage_t {
}
template <typename U>
void destroy_unsafe()
void destroy_unchecked()
{
get_unchecked<U>().~U();
};
@ -80,7 +80,7 @@ struct CopyCtorVisitor {
template <typename T>
void operator()(const T& t)
{
c->construct_unsafe(t);
c->construct_unchecked(t);
}
C* c;
};
@ -91,18 +91,18 @@ struct MoveCtorVisitor {
template <typename T>
void operator()(T&& t)
{
c->construct_unsafe(std::move(t));
c->construct_unchecked(std::move(t));
}
C* c;
};
template <typename C>
struct DtorUnsafeVisitor {
explicit DtorUnsafeVisitor(C* c_) : c(c_) {}
struct DtorUncheckVisitor {
explicit DtorUncheckVisitor(C* c_) : c(c_) {}
template <typename T>
void operator()(T& t)
{
c->template destroy_unsafe<T>();
c->template destroy_unchecked<T>();
}
C* c;
};
@ -119,12 +119,12 @@ struct tagged_union_t
std::size_t type_id;
using base_t::destroy_unsafe;
using base_t::destroy_unchecked;
using base_t::get_buffer;
using base_t::get_unchecked;
template <typename U, typename... Args2>
void construct_emplace_unsafe(Args2&&... args)
void construct_emplace_unchecked(Args2&&... args)
{
using U2 = typename std::decay<U>::type;
static_assert(type_list_contains<U2, Args...>(),
@ -134,7 +134,7 @@ struct tagged_union_t
}
template <typename U>
void construct_unsafe(U&& u)
void construct_unchecked(U&& u)
{
using U2 = typename std::decay<U>::type;
static_assert(type_list_contains<U2, Args...>(),
@ -143,11 +143,11 @@ struct tagged_union_t
new (get_buffer()) U2(std::forward<U>(u));
}
void copy_unsafe(const this_type& other) { visit(CopyCtorVisitor<this_type>{this}, other); }
void copy_unchecked(const this_type& other) { visit(CopyCtorVisitor<this_type>{this}, other); }
void move_unsafe(this_type&& other) { visit(MoveCtorVisitor<this_type>{this}, other); }
void move_unchecked(this_type&& other) { visit(MoveCtorVisitor<this_type>{this}, other); }
void dtor_unsafe() { visit(choice_details::DtorUnsafeVisitor<base_t>{this}, *this); }
void dtor_unchecked() { visit(choice_details::DtorUncheckVisitor<base_t>{this}, *this); }
size_t get_type_idx() const { return type_id; }
@ -189,51 +189,51 @@ public:
typename = typename std::enable_if<std::is_constructible<default_type, Args2...>::value>::type>
explicit choice_t(Args2&&... args) noexcept
{
base_t::template construct_emplace_unsafe<default_type>(std::forward<Args2>(args)...);
base_t::template construct_emplace_unchecked<default_type>(std::forward<Args2>(args)...);
}
choice_t(const choice_t<Args...>& other) noexcept { base_t::copy_unsafe(other); }
choice_t(const choice_t<Args...>& other) noexcept { base_t::copy_unchecked(other); }
choice_t(choice_t<Args...>&& other) noexcept { base_t::move_unsafe(std::move(other)); }
choice_t(choice_t<Args...>&& other) noexcept { base_t::move_unchecked(std::move(other)); }
template <typename U, typename = enable_if_can_hold<U> >
choice_t(U&& u) noexcept
{
base_t::construct_unsafe(std::forward<U>(u));
base_t::construct_unchecked(std::forward<U>(u));
}
~choice_t() { base_t::dtor_unsafe(); }
~choice_t() { base_t::dtor_unchecked(); }
template <typename U, typename = enable_if_can_hold<U> >
choice_t& operator=(U&& u) noexcept
{
if (not base_t::template is<U>()) {
base_t::dtor_unsafe();
base_t::dtor_unchecked();
}
base_t::construct_unsafe(std::forward<U>(u));
base_t::construct_unchecked(std::forward<U>(u));
return *this;
}
template <typename U, typename... Args2>
void emplace(Args2&&... args) noexcept
{
base_t::dtor_unsafe();
base_t::template construct_emplace_unsafe<U>(std::forward<Args2>(args)...);
base_t::dtor_unchecked();
base_t::template construct_emplace_unchecked<U>(std::forward<Args2>(args)...);
}
choice_t& operator=(const choice_t& other) noexcept
{
if (this != &other) {
base_t::dtor_unsafe();
base_t::copy_unsafe(other);
base_t::dtor_unchecked();
base_t::copy_unchecked(other);
}
return *this;
}
choice_t& operator=(choice_t&& other) noexcept
{
base_t::dtor_unsafe();
base_t::move_unsafe(std::move(other));
base_t::dtor_unchecked();
base_t::move_unchecked(std::move(other));
return *this;
}

@ -99,7 +99,12 @@ public:
{
public:
const_iterator() = default;
const_iterator(const static_circular_map<K, T, N>* map, size_t idx_) : ptr(map), idx(idx_) {}
const_iterator(const static_circular_map<K, T, N>* map, size_t idx_) : ptr(map), idx(idx_)
{
if (idx < ptr->capacity() and not ptr->present[idx]) {
++(*this);
}
}
const_iterator& operator++()
{

@ -130,7 +130,7 @@ public:
void* node = grow_pool.allocate_node();
if (grow_pool.size() < batch_threshold) {
allocate_batch_in_background_unlocked();
allocate_batch_in_background_nolock();
}
return node;
}
@ -155,7 +155,7 @@ public:
}
private:
void allocate_batch_in_background_unlocked()
void allocate_batch_in_background_nolock()
{
if (state->dispatched) {
// new batch allocation already ongoing

File diff suppressed because it is too large Load Diff

@ -2480,7 +2480,7 @@ public:
private:
SRSASN_CODE unpack(asn1::cbit_ref& bref);
SRSASN_CODE pack(asn1::bit_ref& bref);
srslog::detail::any msg_container;
srslog::detail::any msg_container = srslog::detail::any{registration_request_t()};
};
} // namespace nas_5g
} // namespace srsran

@ -114,6 +114,15 @@ public:
*/
double get_ul_center_freq(const srsran_carrier_nr_t& carrier);
/**
* @brief Compute the absolute frequency point A for a arfcn
*
* @param nof_prb Number of PRBs.
* @param arfcn Given ARFCN.
* @return frequency point A in arfcn notation.
*/
uint32_t get_abs_freq_point_a_arfcn(uint32_t nof_prb, uint32_t arfcn);
class sync_raster_t
{
protected:
@ -148,6 +157,8 @@ private:
// internal helper
double get_center_freq_from_abs_freq_point_a(uint32_t nof_prb, uint32_t freq_point_a_arfcn);
double get_abs_freq_point_a_from_center_freq(uint32_t nof_prb, double center_freq);
// Elements of TS 38.101-1 Table 5.2-1: NR operating bands in FR1
struct nr_operating_band {
uint16_t band;
@ -249,22 +260,22 @@ private:
{1, KHZ_100, 384000, 20, 396000, 422000, 20, 434000},
{2, KHZ_100, 370000, 20, 382000, 386000, 20, 398000},
{3, KHZ_100, 342000, 20, 357000, 361000, 20, 376000},
{5, KHZ_100, 164800, 20, 169800, 173800, 20, 178800},
{7, KHZ_100, 500000, 20, 514000, 524000, 20, 538000},
{8, KHZ_100, 176000, 20, 183000, 185000, 20, 192000},
{12, KHZ_100, 139800, 20, 143200, 145800, 20, 149200},
{20, KHZ_100, 166400, 20, 172400, 158200, 20, 164200},
{25, KHZ_100, 370000, 20, 383000, 386000, 20, 399000},
{28, KHZ_100, 140600, 20, 149600, 151600, 20, 160600},
{34, KHZ_100, 402000, 20, 405000, 402000, 20, 405000},
{38, KHZ_100, 514000, 20, 524000, 514000, 20, 524000},
{39, KHZ_100, 376000, 20, 384000, 376000, 20, 384000},
{40, KHZ_100, 460000, 20, 480000, 460000, 20, 480000},
{41, KHZ_15, 499200, 3, 537999, 499200, 3, 537999},
@ -272,13 +283,13 @@ private:
{50, KHZ_100, 286400, 20, 303400, 286400, 20, 303400},
{51, KHZ_100, 285400, 20, 286400, 285400, 20, 286400},
{66, KHZ_100, 342000, 20, 356000, 422000, 20, 440000},
{70, KHZ_100, 339000, 20, 342000, 399000, 20, 404000},
{71, KHZ_100, 132600, 20, 139600, 123400, 20, 130400},
{74, KHZ_100, 285400, 20, 294000, 295000, 20, 303600},
{75, KHZ_100, 0, 0, 0, 286400, 20, 303400},
{76, KHZ_100, 0, 0, 0, 285400, 20, 286400},
@ -297,23 +308,22 @@ private:
{83, KHZ_100, 140600, 20, 149600, 0, 0, 0},
{84, KHZ_100, 384000, 20, 396000, 0, 0, 0},
{86, KHZ_100, 342000, 20, 356000, 0, 0, 0}
// clang-format on
// clang-format on
}};
static const uint32_t nof_nr_bands_fr2 = 8;
static constexpr std::array<nr_band, nof_nr_bands_fr2> nr_band_table_fr2 = {{
{257, KHZ_60, 2054166, 1, 2104165, 2054166, 1, 2104165},
{257, KHZ_120, 2054167, 2, 2104165, 2054167, 20, 2104165},
{258, KHZ_60, 2016667, 1, 2070832, 2016667, 1, 2070832},
{258, KHZ_120, 2016667, 2, 2070831, 2016667, 2, 2070832},
{260, KHZ_60, 2229166, 1, 2279165, 2229166, 1, 2279165},
{260, KHZ_120, 2229167, 2, 2279165, 2229167, 2, 2279165},
{261, KHZ_60, 2070833, 1, 2084999, 2070833, 1, 2084999},
{261, KHZ_120, 2070833, 2, 2084999, 2070833, 2, 2084999}
}};
static constexpr std::array<nr_band, nof_nr_bands_fr2> nr_band_table_fr2 = {
{{257, KHZ_60, 2054166, 1, 2104165, 2054166, 1, 2104165},
{257, KHZ_120, 2054167, 2, 2104165, 2054167, 20, 2104165},
{258, KHZ_60, 2016667, 1, 2070832, 2016667, 1, 2070832},
{258, KHZ_120, 2016667, 2, 2070831, 2016667, 2, 2070832},
{260, KHZ_60, 2229166, 1, 2279165, 2229166, 1, 2279165},
{260, KHZ_120, 2229167, 2, 2279165, 2229167, 2, 2279165},
{261, KHZ_60, 2070833, 1, 2084999, 2070833, 1, 2084999},
{261, KHZ_120, 2070833, 2, 2084999, 2070833, 2, 2084999}}};
// Elements of TS 38.101-1 Table 5.4.3.3-1 : Applicable SS raster entries per operating band
struct nr_band_ss_raster {
@ -326,35 +336,35 @@ private:
};
static const uint32_t nof_nr_band_ss_raster = 29;
static constexpr std::array<nr_band_ss_raster, nof_nr_band_ss_raster> nr_band_ss_raster_table = {{
{1, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5419},
{2, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4969},
{3, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4517, 1, 4693},
{5, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2177, 1, 2230},
{5, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 2183, 1, 2224},
{7, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6554, 1, 6718},
{8, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2318, 1, 2395},
{12, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1828, 1, 1858},
{20, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1982, 1, 2047},
{25, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4981},
{28, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1901, 1, 2002},
{34, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5030, 1, 5056},
{38, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6431, 1, 6544},
{39, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4706, 1, 4795},
{40, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5756, 1, 5995},
{41, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6246, 3, 6717},
{41, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 6252, 3, 6714},
{50, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787},
{51, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574},
{66, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5494},
{66, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 5285, 1, 5488},
{70, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4993, 1, 5044},
{71, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1547, 1, 1624},
{74, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3692, 1, 3790},
{75, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787},
{76, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574},
{77, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8329},
{78, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8051},
{79, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 8480, 16, 8880},
{1, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5419},
{2, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4969},
{3, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4517, 1, 4693},
{5, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2177, 1, 2230},
{5, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 2183, 1, 2224},
{7, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6554, 1, 6718},
{8, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2318, 1, 2395},
{12, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1828, 1, 1858},
{20, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1982, 1, 2047},
{25, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4981},
{28, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1901, 1, 2002},
{34, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5030, 1, 5056},
{38, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6431, 1, 6544},
{39, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4706, 1, 4795},
{40, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5756, 1, 5995},
{41, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6246, 3, 6717},
{41, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 6252, 3, 6714},
{50, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787},
{51, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574},
{66, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5494},
{66, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 5285, 1, 5488},
{70, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4993, 1, 5044},
{71, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1547, 1, 1624},
{74, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3692, 1, 3790},
{75, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787},
{76, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574},
{77, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8329},
{78, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8051},
{79, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 8480, 16, 8880},
}};
};

@ -44,7 +44,6 @@ namespace srsran {
template <typename myobj>
class block_queue
{
public:
// Callback functions for mutexed operations inside pop/push methods
class call_mutexed_itf
@ -116,7 +115,7 @@ public:
bool full()
{ // queue is full?
pthread_mutex_lock(&mutex);
bool ret = not check_queue_space_unlocked(false);
bool ret = not check_queue_space_nolock(false);
pthread_mutex_unlock(&mutex);
return ret;
}
@ -172,7 +171,7 @@ private:
return ret;
}
bool check_queue_space_unlocked(bool block)
bool check_queue_space_nolock(bool block)
{
num_threads++;
if (capacity > 0) {
@ -199,7 +198,7 @@ private:
return std::move(value);
}
pthread_mutex_lock(&mutex);
bool ret = check_queue_space_unlocked(block);
bool ret = check_queue_space_nolock(block);
if (ret) {
if (mutexed_callback) {
mutexed_callback->pushing(value);
@ -219,7 +218,7 @@ private:
return false;
}
pthread_mutex_lock(&mutex);
bool ret = check_queue_space_unlocked(block);
bool ret = check_queue_space_nolock(block);
if (ret) {
if (mutexed_callback) {
mutexed_callback->pushing(value);

@ -46,9 +46,12 @@ const char* __tsan_default_options()
const char* __tsan_default_suppressions()
{
// External uninstrumented libraries
return "called_from_lib:libzmq.so\n"
"called_from_lib:libpgm-5.2.so\n";
return
// External uninstrumented libraries
"called_from_lib:libzmq.so\n"
"called_from_lib:libpgm-5.2.so\n"
// Lock order inversion issue in this function, ignore it as it uses rw locks in read mode
"deadlock:srsenb::mac::rlc_buffer_state\n";
}
#ifdef __cplusplus

@ -40,7 +40,8 @@ struct gtpu_args_t {
class gtpu_interface_pdcp
{
public:
virtual void write_pdu(uint16_t rnti, uint32_t bearer_id, srsran::unique_byte_buffer_t pdu) = 0;
// PDCP will only know LCIDs, translation to EPS bearer id will be done by gtpu_pdcp_adapter
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) = 0;
};
// GTPU interface for RRC
@ -58,6 +59,7 @@ public:
uint32_t eps_bearer_id,
uint32_t addr,
uint32_t teid_out,
uint32_t& addr_in,
const bearer_props* props = nullptr) = 0;
virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0;
virtual void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) = 0;

@ -266,8 +266,7 @@ public:
// Combined interface for PHY to access stack (MAC and RRC)
class stack_interface_phy_lte : public mac_interface_phy_lte
{
};
{};
} // namespace srsenb

@ -40,6 +40,7 @@ public:
class pdcp_interface_rrc
{
public:
virtual void set_enabled(uint16_t rnti, uint32_t lcid, bool enable) = 0;
virtual void reset(uint16_t rnti) = 0;
virtual void add_user(uint16_t rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;

@ -19,6 +19,7 @@
*
*/
#include "srsran/interfaces/enb_gtpu_interfaces.h"
#include "srsran/interfaces/enb_pdcp_interfaces.h"
#include "srsran/interfaces/enb_rrc_interface_types.h"
@ -89,6 +90,13 @@ public:
* @param nr_rnti The RNTI that has been assigned to the UE on the SgNB
*/
virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0;
/**
* @brief Signal user activity (i.e. DL/UL traffic) for given RNTI
*
* @param eutra_rnti The RNTI that the EUTRA RRC uses
*/
virtual void set_activity_user(uint16_t eutra_rnti) = 0;
};
class stack_nr_interface_stack_eutra
@ -102,7 +110,8 @@ public:
class x2_interface : public rrc_nr_interface_rrc,
public rrc_eutra_interface_rrc_nr,
public stack_nr_interface_stack_eutra,
public pdcp_interface_gtpu
public pdcp_interface_gtpu, // allow GTPU to access PDCP in DL direction
public gtpu_interface_pdcp // allow PDCP to access GTPU in UL direction
{};
} // namespace srsenb

@ -143,8 +143,9 @@ public:
virtual int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) = 0;
/// User management
virtual int add_user(uint16_t rnti) = 0;
virtual int update_user(uint16_t new_rnti, uint16_t old_rnti) = 0;
virtual int add_user(uint16_t rnti) = 0;
virtual int update_user(uint16_t new_rnti, uint16_t old_rnti) = 0;
virtual void set_activity_user(uint16_t rnti) = 0;
};
// NR interface is almost identical to EUTRA version
@ -169,6 +170,7 @@ public:
srsran_carrier_nr_t carrier;
srsran_pdcch_cfg_nr_t pdcch;
srsran_prach_cfg_t prach;
srsran_duplex_mode_t duplex_mode;
};
virtual int set_common_cfg(const common_cfg_t& common_cfg) = 0;

@ -36,6 +36,8 @@ public:
virtual uint16_t reserve_rnti(uint32_t enb_cc_idx) = 0;
virtual int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) = 0;
virtual int remove_ue(uint16_t rnti) = 0;
};
// NR interface is identical to EUTRA interface

@ -21,20 +21,38 @@
#ifndef SRSRAN_GNB_RRC_NR_INTERFACES_H
#define SRSRAN_GNB_RRC_NR_INTERFACES_H
#include "srsenb/hdr/phy/phy_interfaces.h"
#include "srsran/asn1/ngap.h"
#include "srsran/common/byte_buffer.h"
namespace srsenb {
class rrc_interface_ngap_nr
{
public:
virtual int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key) = 0;
virtual int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) = 0;
virtual int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) = 0;
virtual int start_security_mode_procedure(uint16_t rnti) = 0;
virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0;
virtual int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key) = 0;
virtual int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) = 0;
virtual int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) = 0;
virtual int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) = 0;
virtual int start_security_mode_procedure(uint16_t rnti) = 0;
virtual int
establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid) = 0;
virtual int allocate_lcid(uint16_t rnti) = 0;
virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0;
};
// Cell/Sector configuration for NR cells
struct rrc_cell_cfg_nr_t {
phy_cell_cfg_nr_t phy_cell; // already contains all PHY-related parameters (i.e. RF port, PCI, etc.)
uint32_t tac; // Tracking area code
uint32_t dl_arfcn; // DL freq already included in phy_cell
uint32_t ul_arfcn; // UL freq also in phy_cell
uint32_t band;
srsran_duplex_mode_t duplex_mode;
};
typedef std::vector<rrc_cell_cfg_nr_t> rrc_cell_list_nr_t;
} // namespace srsenb
#endif // SRSRAN_GNB_RRC_NR_INTERFACES_H

@ -194,6 +194,49 @@ inline std::string to_string(const scg_failure_cause_t& cause)
"nulltype"};
return enum_to_text(options, (uint32_t)scg_failure_cause_t::nulltype, (uint32_t)cause);
}
enum class nr_establishment_cause_t {
emergency,
highPriorityAccess,
mt_Access,
mo_Signalling,
mo_Data,
mo_VoiceCall,
mo_VideoCall,
mo_SMS,
mps_PriorityAccess,
mcs_PriorityAccess,
spare6,
spare5,
spare4,
spare3,
spare2,
spare1,
nulltype
};
inline std::string to_string(const nr_establishment_cause_t& cause)
{
constexpr static const char* options[] = {
"emergency",
"highPriorityAccess",
"mt_Access",
"mo_Signalling",
"mo_Data",
"mo_VoiceCall",
"mo_VideoCall",
"mo_SMS",
"mps_PriorityAccess",
"mcs_PriorityAccess",
"spare6",
"spare5",
"spare4",
"spare3",
"spare2",
"spare1",
};
return enum_to_text(options, (uint32_t)nr_establishment_cause_t::nulltype, (uint32_t)cause);
}
/***************************
* PHY Config
**************************/

@ -22,10 +22,26 @@
#ifndef SRSRAN_UE_NAS_INTERFACES_H
#define SRSRAN_UE_NAS_INTERFACES_H
#include "srsran/asn1/nas_5g_ies.h"
#include "srsran/interfaces/rrc_interface_types.h"
namespace srsue {
enum apn_types {
ipv4 = 0b001,
ipv6 = 0b010,
ipv4v6 = 0b011,
unstructured = 0b100,
ethernet = 0b101,
};
class pdu_session_cfg_t
{
public:
std::string apn_name;
apn_types apn_type;
std::string apn_user;
std::string apn_pass;
};
class nas_interface_rrc
{
public:
@ -51,12 +67,20 @@ public:
class nas_5g_interface_rrc_nr
{
public:
virtual int write_pdu(srsran::unique_byte_buffer_t pdu) = 0;
};
class nas_5g_interface_procedures
{
public:
virtual int send_registration_request() = 0;
virtual int send_pdu_session_establishment_request(uint32_t transaction_identity,
uint16_t pdu_session_id,
const pdu_session_cfg_t& pdu_session) = 0;
virtual int
add_pdu_session(uint16_t pdu_session_id, uint16_t pdu_session_type, srsran::nas_5g::pdu_address_t pdu_address) = 0;
virtual uint32_t allocate_next_proc_trans_id() = 0;
};
} // namespace srsue

@ -33,6 +33,7 @@ public:
virtual void reestablish() = 0;
virtual void reestablish(uint32_t lcid) = 0;
virtual void reset() = 0;
virtual void set_enabled(uint32_t lcid, bool enabled) = 0;
virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu, int sn = -1) = 0;
virtual int add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg) = 0;
virtual void del_bearer(uint32_t lcid) = 0;

@ -125,6 +125,12 @@ public:
class rrc_nr_interface_nas_5g
{
public:
virtual ~rrc_nr_interface_nas_5g() = default;
virtual int write_sdu(srsran::unique_byte_buffer_t sdu) = 0;
virtual bool is_connected() = 0;
virtual int connection_request(srsran::nr_establishment_cause_t cause, srsran::unique_byte_buffer_t sdu) = 0;
virtual uint16_t get_mcc() = 0;
virtual uint16_t get_mnc() = 0;
};
} // namespace srsue

@ -366,6 +366,14 @@ typedef enum SRSRAN_API {
SRSRAN_DUPLEX_MODE_INVALID
} srsran_duplex_mode_t;
/**
* @brief Determines whether the first DMRS goes into symbol index 2 or 3
*/
typedef enum {
srsran_dmrs_sch_typeA_pos_2 = 0, // Start in slot symbol index 2 (default)
srsran_dmrs_sch_typeA_pos_3 // Start in slot symbol index 3
} srsran_dmrs_sch_typeA_pos_t;
/**
* @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP)
*/

@ -22,6 +22,7 @@
#ifndef SRSRAN_GNB_DL_H
#define SRSRAN_GNB_DL_H
#include "srsran/phy/ch_estimation/csi_rs.h"
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/dft/ofdm.h"
#include "srsran/phy/phch/pdcch_cfg_nr.h"
@ -87,4 +88,8 @@ srsran_gnb_dl_pdcch_dl_info(const srsran_gnb_dl_t* q, const srsran_dci_dl_nr_t*
SRSRAN_API int
srsran_gnb_dl_pdcch_ul_info(const srsran_gnb_dl_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len);
SRSRAN_API int srsran_gnb_dl_nzp_csi_rs_put(srsran_gnb_dl_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_resource_t* resource);
#endif // SRSRAN_GNB_DL_H

@ -0,0 +1,62 @@
/**
*
* \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_PBCH_MSG_NR_H
#define SRSRAN_PBCH_MSG_NR_H
#include "srsran/config.h"
#include "srsran/phy/common/phy_common_nr.h"
#include <stdbool.h>
#include <stdint.h>
/**
* @brief NR PBCH payload size generated by higher layers, deduced from TS 38.331 MIB description
*/
#define SRSRAN_PBCH_MSG_NR_SZ 24
/**
* @brief Describes the NR PBCH message
*/
typedef struct SRSRAN_API {
uint8_t payload[SRSRAN_PBCH_MSG_NR_SZ]; ///< Actual PBCH payload provided by higher layers
uint8_t sfn_4lsb; ///< SFN 4 LSB
uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1
uint8_t k_ssb_msb; ///< Subcarrier offset MSB described in TS 38.211 7.4.3.1
bool hrf; ///< Half Radio Frame bit
bool crc; ///< Decoder only, it is true only if the received CRC matches
} srsran_pbch_msg_nr_t;
typedef struct SRSRAN_API {
uint32_t sfn; ///< System frame number
uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1
bool hrf; ///< Half Radio Frame bit
srsran_subcarrier_spacing_t scs_common; ///< Subcarrier spacing common
uint32_t ssb_offset; ///< SSB subcarrier offset
srsran_dmrs_sch_typeA_pos_t dmrs_typeA_pos; ///< DMRS typeA position
uint32_t coreset0_idx; ///< CORESET Zero configuration index (0-15)
uint32_t ss0_idx; ///< SearchSpace Zero configuration index (0-15)
bool cell_barred; ///< Set to true if the cell is barred
bool intra_freq_reselection; ///< Set to true if allowed
uint32_t spare; ///< Unused bits
} srsran_mib_nr_t;
SRSRAN_API bool srsran_pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg);
SRSRAN_API int srsran_pbch_msg_nr_mib_pack(const srsran_mib_nr_t* mib, srsran_pbch_msg_nr_t* msg);
SRSRAN_API int srsran_pbch_msg_nr_mib_unpack(const srsran_pbch_msg_nr_t* pbch_msg, srsran_mib_nr_t* mib);
SRSRAN_API uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len);
SRSRAN_API uint32_t srsran_pbch_msg_nr_mib_info(const srsran_mib_nr_t* mib, char* str, uint32_t str_len);
#endif // SRSRAN_PBCH_MSG_NR_H

@ -29,11 +29,7 @@
#include "srsran/phy/fec/polar/polar_encoder.h"
#include "srsran/phy/fec/polar/polar_rm.h"
#include "srsran/phy/modem/modem_table.h"
/**
* @brief NR PBCH payload size generated by higher layers, deduced from TS 38.331 MIB description
*/
#define SRSRAN_PBCH_NR_PAYLOAD_SZ 24
#include "srsran/phy/phch/pbch_msg_nr.h"
/**
* @brief Describes the NR PBCH object initialisation arguments
@ -68,18 +64,6 @@ typedef struct SRSRAN_API {
srsran_modem_table_t qpsk;
} srsran_pbch_nr_t;
/**
* @brief Describes the PBCH message
*/
typedef struct SRSRAN_API {
uint8_t payload[SRSRAN_PBCH_NR_PAYLOAD_SZ]; ///< Actual PBCH payload provided by higher layers
uint8_t sfn_4lsb; ///< SFN 4 LSB
uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1
uint8_t k_ssb_msb; ///< Subcarrier offset MSB described in TS 38.211 7.4.3.1
bool hrf; ///< Half Radio Frame bit
bool crc; ///< Decoder only, it is true only if the received CRC matches
} srsran_pbch_msg_nr_t;
/**
* @brief Initialises an NR PBCH object with the provided arguments
* @param q NR PBCH object
@ -121,6 +105,4 @@ SRSRAN_API int srsran_pbch_nr_decode(srsran_pbch_nr_t* q,
const cf_t ce[SRSRAN_SSB_NOF_RE],
srsran_pbch_msg_nr_t* msg);
SRSRAN_API uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len);
#endif // SRSRAN_PBCH_NR_H

@ -58,14 +58,6 @@ typedef enum {
srsran_dmrs_sch_len_2 // double, 2 symbol long
} srsran_dmrs_sch_len_t;
/**
* @brief Determines whether the first pilot goes into symbol index 2 or 3
*/
typedef enum {
srsran_dmrs_sch_typeA_pos_2 = 0, // Start in slot symbol index 2 (default)
srsran_dmrs_sch_typeA_pos_3 // Start in slot symbol index 3
} srsran_dmrs_sch_typeA_pos_t;
/**
* @brief Determines additional symbols if possible to be added
*/

@ -32,6 +32,7 @@
#include "srsran/config.h"
#include "srsran/phy/common/phy_common.h"
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/dft/dft.h"
#include <complex.h>
#include <stdbool.h>
@ -126,7 +127,7 @@ typedef struct SRSRAN_API {
} srsran_prach_sf_config_t;
///@brief Maximum number of subframe number candidates for PRACH NR configuration
#define PRACH_NR_CFG_MAX_NOF_SF 5
#define PRACH_NR_CFG_MAX_NOF_SF 10
/**
* @brief PRACH configuration for NR as described in TS 38.211 Tables 6.3.3.2-2, 6.3.3.2-3 and 6.3.3.2-4
@ -186,11 +187,17 @@ SRSRAN_API bool srsran_prach_tti_opportunity_config_tdd(uint32_t config_idx,
uint32_t current_tti,
uint32_t* prach_idx);
SRSRAN_API const prach_nr_config_t* srsran_prach_nr_get_cfg_fr1_paired(uint32_t config_idx);
SRSRAN_API bool srsran_prach_nr_tti_opportunity_fr1_paired(uint32_t config_idx, uint32_t current_tti);
SRSRAN_API uint32_t srsran_prach_nr_start_symbol_fr1_paired(uint32_t config_idx);
SRSRAN_API const prach_nr_config_t* srsran_prach_nr_get_cfg_fr1_unpaired(uint32_t config_idx);
SRSRAN_API bool srsran_prach_nr_tti_opportunity_fr1_unpaired(uint32_t config_idx, uint32_t current_tti);
SRSRAN_API uint32_t srsran_prach_nr_start_symbol_fr1_unpaired(uint32_t config_idx);
SRSRAN_API uint32_t srsran_prach_nr_start_symbol(uint32_t config_idx, srsran_duplex_mode_t duplex_mode);
SRSRAN_API uint32_t srsran_prach_f_ra_tdd(uint32_t config_idx,
uint32_t tdd_ul_dl_config,

@ -401,6 +401,7 @@ private:
void update_notification_ack_info(uint32_t rlc_sn);
void debug_state();
void empty_queue_nolock();
int required_buffer_size(const rlc_amd_retx_t& retx);
void retransmit_pdu(uint32_t sn);

@ -77,6 +77,7 @@ private:
std::atomic<bool> tx_enabled = {true};
std::mutex metrics_mutex;
rlc_bearer_metrics_t metrics = {};
// Thread-safe queues for MAC messages

@ -174,6 +174,7 @@ protected:
bool tx_enabled = false;
bool rx_enabled = false;
std::mutex metrics_mutex;
rlc_bearer_metrics_t metrics = {};
};

@ -22,23 +22,15 @@
#ifndef SRSUE_RRC_COMMON_H
#define SRSUE_RRC_COMMON_H
namespace srsue {
namespace srsran {
#include <stdint.h>
// RRC states (3GPP 36.331 v10.0.0)
typedef enum {
RRC_STATE_IDLE = 0,
RRC_STATE_CONNECTED,
RRC_STATE_N_ITEMS,
} 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
} // namespace srsran
#endif // SRSUE_RRC_COMMON_H

@ -67,8 +67,11 @@ namespace srsran {
#define GTPU_MSG_END_MARKER 254
#define GTPU_MSG_DATA_PDU 255
#define GTPU_EXT_NO_MORE_EXTENSION_HEADERS 0x00
#define GTPU_EXT_HEADER_PDCP_PDU_NUMBER 0b11000000
#define GTPU_EXT_HEADER_PDU_SESSION_CONTAINER 0x85
#define GTPU_EXT_HEADER_PDU_SESSION_CONTAINER_LEN 4
struct gtpu_header_t {
uint8_t flags = 0;
uint8_t message_type = 0;

@ -45,6 +45,7 @@ public:
void reestablish() override;
void reestablish(uint32_t lcid) override;
void reset() override;
void set_enabled(uint32_t lcid, bool enabled) override;
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn = -1) override;
void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu);
int add_bearer(uint32_t lcid, pdcp_config_t cnfg) override;

@ -69,6 +69,7 @@ public:
virtual void reset() = 0;
virtual void reestablish() = 0;
void set_enabled(bool enabled) { active = enabled; }
bool is_active() { return active; }
bool is_srb() { return cfg.rb_type == PDCP_RB_IS_SRB; }
bool is_drb() { return cfg.rb_type == PDCP_RB_IS_DRB; }

@ -283,6 +283,8 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common,
srsran_duplex_config_nr_t* in_srsran_duplex_config_nr)
{
srsran_duplex_config_nr_t srsran_duplex_config_nr = {};
srsran_duplex_config_nr.mode = SRSRAN_DUPLEX_MODE_TDD;
switch (tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity) {
case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1:
srsran_duplex_config_nr.tdd.pattern1.period_ms = 1;

@ -36,6 +36,7 @@ set(SOURCES arch_select.cc
pcap.c
phy_cfg_nr.cc
phy_cfg_nr_default.cc
rrc_common.cc
rlc_pcap.cc
s1ap_pcap.cc
security.cc

@ -50,7 +50,7 @@ uint32_t srsran_band_helper::freq_to_nr_arfcn(double freq)
if (not is_valid_raster_param(params)) {
return 0;
}
return (((freq + params.F_REF_Offs_MHz * 1e6) / 1e3 / params.delta_F_global_kHz) + params.N_REF_Offs);
return (((freq - params.F_REF_Offs_MHz * 1e6) / 1e3 / params.delta_F_global_kHz) + params.N_REF_Offs);
}
// Implements 5.4.2.1 in TS 38.104
@ -138,6 +138,20 @@ double srsran_band_helper::get_center_freq_from_abs_freq_point_a(uint32_t nof_pr
SRSRAN_NRE);
}
uint32_t srsran_band_helper::get_abs_freq_point_a_arfcn(uint32_t nof_prb, uint32_t arfcn)
{
return freq_to_nr_arfcn(get_abs_freq_point_a_from_center_freq(nof_prb, nr_arfcn_to_freq(arfcn)));
}
double srsran_band_helper::get_abs_freq_point_a_from_center_freq(uint32_t nof_prb, double center_freq)
{
// for FR1 unit of resources blocks for freq calc is always 180kHz regardless for actual SCS of carrier
// TODO: add offset_to_carrier
return center_freq -
(nof_prb / 2 * SRSRAN_SUBC_SPACING_NR(srsran_subcarrier_spacing_t::srsran_subcarrier_spacing_15kHz) *
SRSRAN_NRE);
}
srsran_ssb_patern_t srsran_band_helper::get_ssb_pattern(uint16_t band, srsran_subcarrier_spacing_t scs) const
{
// Look for the given band and SCS

@ -73,6 +73,47 @@ static double get_time_stamp()
return std::chrono::duration_cast<std::chrono::milliseconds>(tp).count() * 1e-3;
}
/// Escapes the input string.
static std::string escape_string(const std::string& s)
{
fmt::memory_buffer buff;
for (auto c : s) {
switch (c) {
case ' ':
break;
case '"':
fmt::format_to(buff, "\\\"");
break;
case '\\':
fmt::format_to(buff, "\\\\");
break;
case '\b':
fmt::format_to(buff, "\\b");
break;
case '\f':
fmt::format_to(buff, "\\f");
break;
case '\n':
fmt::format_to(buff, "\\n");
break;
case '\r':
fmt::format_to(buff, "\\r");
break;
case '\t':
fmt::format_to(buff, "\\t");
break;
default:
// Cast to signed char for machines that treat chars as an unsigned type.
if ((signed char)c >= '\x00' && (signed char)c <= '\x1f') {
fmt::format_to(buff, "\\u{:04x}", c);
} else {
buff.push_back(c);
}
}
}
return fmt::to_string(buff);
}
namespace {
/// Common metrics to all events.
@ -200,7 +241,8 @@ public:
{
rrc_event_t ctx("");
const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str;
const std::string& asn1 =
(asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str);
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
@ -284,7 +326,8 @@ public:
{
meas_report_event_t ctx("");
const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str;
const std::string& asn1 =
(asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str);
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
@ -304,7 +347,8 @@ public:
{
rlf_report_event_t ctx("");
const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str;
const std::string& asn1 =
(asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str);
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());

@ -466,6 +466,8 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
make_prach_default_lte(prach);
break;
}
prach.tdd_config.configured = (duplex.mode == SRSRAN_DUPLEX_MODE_TDD);
}
} // namespace srsran

@ -19,9 +19,9 @@
*
*/
#include "srsue/hdr/stack/rrc/rrc_common.h"
#include "srsran/rrc/rrc_common.h"
namespace srsue {
namespace srsran {
uint8_t rrc_value_to_range(quant_s quant, const float value)
{
@ -57,4 +57,4 @@ float rrc_range_to_value(quant_s quant, const uint8_t range)
return val;
}
} // namespace srsue
} // namespace srsran

@ -86,6 +86,9 @@ int bands_test_nr()
TESTASSERT(band_vector.at(0) == 77);
TESTASSERT(band_vector.at(1) == 78);
// n78
TESTASSERT(bands.get_abs_freq_point_a_arfcn(52, 634240) == 633928);
// Invalid configs
// For 30 kHz, 620001 is not a valid ARFCN, only every 2nd
band_vector = bands.get_bands_nr(620001, srsran::srsran_band_helper::KHZ_30);

@ -121,17 +121,26 @@ bool gtpu_read_ext_header(srsran::byte_buffer_t* pdu,
return true;
}
if (header->next_ext_hdr_type == GTPU_EXT_HEADER_PDCP_PDU_NUMBER) {
pdu->msg += HEADER_PDCP_PDU_NUMBER_SIZE;
pdu->N_bytes -= HEADER_PDCP_PDU_NUMBER_SIZE;
header->ext_buffer.resize(HEADER_PDCP_PDU_NUMBER_SIZE);
for (size_t i = 0; i < HEADER_PDCP_PDU_NUMBER_SIZE; ++i) {
header->ext_buffer[i] = **ptr;
(*ptr)++;
}
} else {
logger.error("gtpu_read_header - Unhandled GTP-U Extension Header Type: 0x%x", header->next_ext_hdr_type);
return false;
// TODO: Iterate over next headers until no more extension headers
switch (header->next_ext_hdr_type) {
case GTPU_EXT_HEADER_PDCP_PDU_NUMBER:
pdu->msg += HEADER_PDCP_PDU_NUMBER_SIZE;
pdu->N_bytes -= HEADER_PDCP_PDU_NUMBER_SIZE;
header->ext_buffer.resize(HEADER_PDCP_PDU_NUMBER_SIZE);
for (size_t i = 0; i < HEADER_PDCP_PDU_NUMBER_SIZE; ++i) {
header->ext_buffer[i] = **ptr;
(*ptr)++;
}
break;
case GTPU_EXT_HEADER_PDU_SESSION_CONTAINER:
pdu->msg += GTPU_EXT_HEADER_PDU_SESSION_CONTAINER_LEN;
pdu->N_bytes -= GTPU_EXT_HEADER_PDU_SESSION_CONTAINER_LEN;
logger.warning("skip parsing of GTPU_EXT_HEADER_PDU_SESSION_CONTAINER");
// TODO: Save Header Extension
break;
default:
logger.error("gtpu_read_header - Unhandled GTP-U Extension Header Type: 0x%x", header->next_ext_hdr_type);
return false;
}
return true;
}

@ -72,6 +72,15 @@ void pdcp::reset()
pdcp_array.clear();
}
void pdcp::set_enabled(uint32_t lcid, bool enabled)
{
if (valid_lcid(lcid)) {
pdcp_array.at(lcid)->set_enabled(enabled);
} else {
logger.warning("LCID %d doesn't exist while setting enabled", lcid);
}
}
/*******************************************************************************
RRC/GW interface
*******************************************************************************/

@ -143,6 +143,11 @@ void pdcp_entity_lte::reset()
// GW/RRC interface
void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn)
{
if (!active) {
logger.warning("Dropping %s SDU due to inactive bearer", rrc->get_rb_name(lcid));
return;
}
if (rlc->sdu_queue_is_full(lcid)) {
logger.info(sdu->msg, sdu->N_bytes, "Dropping %s SDU due to full queue", rrc->get_rb_name(lcid));
return;
@ -225,6 +230,11 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn)
// RLC interface
void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu)
{
if (!active) {
logger.warning("Dropping %s PDU due to inactive bearer", rrc->get_rb_name(lcid));
return;
}
// Handle control PDUs
if (is_drb() && is_control_pdu(pdu)) {
logger.info("Handling PDCP control PDU");

@ -176,7 +176,7 @@ void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q)
return;
}
float norm_factor = gnb_dl_get_norm_factor(q->pdcch.carrier.nof_prb);
float norm_factor = gnb_dl_get_norm_factor(q->pdsch.carrier.nof_prb);
for (uint32_t i = 0; i < q->nof_tx_antennas; i++) {
srsran_ofdm_tx_sf(&q->fft[i]);
@ -318,3 +318,19 @@ int srsran_gnb_dl_pdcch_ul_info(const srsran_gnb_dl_t* q, const srsran_dci_ul_nr
return len;
}
int srsran_gnb_dl_nzp_csi_rs_put(srsran_gnb_dl_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_resource_t* resource)
{
if (q == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (srsran_csi_rs_nzp_put_resource(&q->carrier, slot_cfg, resource, q->sf_symbols[0]) < SRSRAN_SUCCESS) {
ERROR("Error putting NZP-CSI-RS resource");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}

@ -1278,7 +1278,7 @@ static uint32_t dci_nr_format_1_0_to_str(const srsran_dci_dl_nr_t* dci, char* st
// HARQ process number 4 bits
if (rnti_type == srsran_rnti_type_c || rnti_type == srsran_rnti_type_tc) {
len = srsran_print_check(str, str_len, len, "harq_id=%d ", dci->harq_feedback);
len = srsran_print_check(str, str_len, len, "harq_id=%d ", dci->pid);
}
// System information indicator 1 bit

@ -0,0 +1,179 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsran/phy/phch/pbch_msg_nr.h"
#include "srsran/phy/utils/bit.h"
#include "srsran/phy/utils/vector.h"
static bool pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg)
{
return msg->payload[0] == 0;
}
bool srsran_pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg)
{
if (msg == NULL) {
return false;
}
return pbch_msg_nr_is_mib(msg);
}
int srsran_pbch_msg_nr_mib_pack(const srsran_mib_nr_t* mib, srsran_pbch_msg_nr_t* pbch_msg)
{
if (mib == NULL || pbch_msg == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Copy PBCH message context
pbch_msg->sfn_4lsb = mib->sfn & 0b1111;
pbch_msg->ssb_idx = mib->ssb_idx;
pbch_msg->k_ssb_msb = mib->ssb_offset >> 4U;
pbch_msg->hrf = mib->hrf;
// Pack MIB payload
uint8_t* y = pbch_msg->payload;
// MIB - 1 bit
*(y++) = 0;
// systemFrameNumber - 6 bits MSB
srsran_bit_unpack(mib->sfn >> 4U, &y, 6);
// subCarrierSpacingCommon - 1 bit
*(y++) = (mib->scs_common == srsran_subcarrier_spacing_15kHz || mib->scs_common == srsran_subcarrier_spacing_60kHz)
? 0
: 1;
// ssb-SubcarrierOffset - 4 bits
srsran_bit_unpack(mib->ssb_offset, &y, 4);
// dmrs-TypeA-Position - 1 bit
*(y++) = (mib->dmrs_typeA_pos == srsran_dmrs_sch_typeA_pos_2) ? 0 : 1;
// pdcch-ConfigSIB1
// controlResourceSetZero - 4 bits
srsran_bit_unpack(mib->coreset0_idx, &y, 4);
// searchSpaceZero - 4 bits
srsran_bit_unpack(mib->ss0_idx, &y, 4);
// Barred - 1 bit
*(y++) = (mib->cell_barred) ? 0 : 1;
// intraFreqReselection - 1 bit
*(y++) = (mib->intra_freq_reselection) ? 0 : 1;
// Spare - 1 bit
srsran_bit_unpack(mib->spare, &y, 1);
return SRSRAN_SUCCESS;
}
int srsran_pbch_msg_nr_mib_unpack(const srsran_pbch_msg_nr_t* pbch_msg, srsran_mib_nr_t* mib)
{
if (mib == NULL || pbch_msg == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Copy PBCH message context
mib->sfn = pbch_msg->sfn_4lsb;
mib->ssb_idx = pbch_msg->ssb_idx;
mib->hrf = pbch_msg->hrf;
mib->ssb_offset = pbch_msg->k_ssb_msb << 4U;
// Pack MIB payload
uint8_t* y = (uint8_t*)pbch_msg->payload;
// MIB - 1 bit
if (!pbch_msg_nr_is_mib(pbch_msg)) {
return SRSRAN_ERROR;
}
y++;
// systemFrameNumber - 6 bits MSB
mib->sfn |= srsran_bit_pack(&y, 6) << 4U;
// subCarrierSpacingCommon - 1 bit
mib->scs_common = *(y++) == 0 ? srsran_subcarrier_spacing_15kHz : srsran_subcarrier_spacing_30kHz;
// ssb-SubcarrierOffset - 4 bits
mib->ssb_offset |= srsran_bit_pack(&y, 4);
// dmrs-TypeA-Position - 1 bit
mib->dmrs_typeA_pos = *(y++) == 0 ? srsran_dmrs_sch_typeA_pos_2 : srsran_dmrs_sch_typeA_pos_3;
// pdcch-ConfigSIB1
// controlResourceSetZero - 4 bits
mib->coreset0_idx = srsran_bit_pack(&y, 4);
// searchSpaceZero - 4 bits
mib->ss0_idx = srsran_bit_pack(&y, 4);
// Barred - 1 bit
mib->cell_barred = (*(y++) == 0);
// intraFreqReselection - 1 bit
mib->intra_freq_reselection = (*(y++) == 0);
// Spare - 1 bit
mib->spare = srsran_bit_pack(&y, 1);
return SRSRAN_SUCCESS;
}
uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len)
{
if (msg == NULL || str == NULL || str_len == 0) {
return 0;
}
uint32_t len = 0;
len = srsran_print_check(str, str_len, len, "payload=");
len += srsran_vec_sprint_hex(&str[len], str_len - len, (uint8_t*)msg->payload, SRSRAN_PBCH_MSG_NR_SZ);
len = srsran_print_check(str,
str_len,
len,
" sfn_lsb=%d ssb_idx=%d k_ssb_msb=%d hrf=%d ",
msg->sfn_4lsb,
msg->ssb_idx,
msg->k_ssb_msb,
msg->hrf);
return len;
}
uint32_t srsran_pbch_msg_nr_mib_info(const srsran_mib_nr_t* mib, char* str, uint32_t str_len)
{
uint32_t len = 0;
len = srsran_print_check(str,
str_len,
len,
"sfn=%d ssb_idx=%d hrf=%c scs=%d ssb_offset=%d dmrs_typeA_pos=%s coreset0=%d ss0=%d "
"barred=%c intra_freq_reselection=%c spare=%d",
mib->sfn,
mib->ssb_idx,
mib->hrf ? 'y' : 'n',
SRSRAN_SUBC_SPACING_NR(mib->scs_common) / 1000,
mib->ssb_offset,
mib->dmrs_typeA_pos == srsran_dmrs_sch_typeA_pos_2 ? "pos2" : "pos3",
mib->coreset0_idx,
mib->ss0_idx,
mib->cell_barred ? 'y' : 'n',
mib->intra_freq_reselection ? 'y' : 'n',
mib->spare);
return len;
}

@ -52,7 +52,7 @@
/*
* Number of generated payload bits, called A
*/
#define PBCH_NR_A (SRSRAN_PBCH_NR_PAYLOAD_SZ + 8)
#define PBCH_NR_A (SRSRAN_PBCH_MSG_NR_SZ + 8)
/*
* Number of payload bits plus CRC
@ -193,7 +193,7 @@ static void
pbch_nr_pbch_msg_pack(const srsran_pbch_nr_cfg_t* cfg, const srsran_pbch_msg_nr_t* msg, uint8_t a[PBCH_NR_A])
{
// Extract actual payload size
uint32_t A_hat = SRSRAN_PBCH_NR_PAYLOAD_SZ;
uint32_t A_hat = SRSRAN_PBCH_MSG_NR_SZ;
// Put SFN in a_hat[A_hat] to a_hat[A_hat + 3]
uint32_t j_sfn = 0;
@ -240,7 +240,7 @@ pbch_nr_pbch_msg_unpack(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PBCH_NR
}
// Extract actual payload size
uint32_t A_hat = SRSRAN_PBCH_NR_PAYLOAD_SZ;
uint32_t A_hat = SRSRAN_PBCH_MSG_NR_SZ;
// Put SFN in a_hat[A_hat] to a_hat[A_hat + 3]
uint32_t j_sfn = 0;
@ -660,27 +660,3 @@ int srsran_pbch_nr_decode(srsran_pbch_nr_t* q,
return SRSRAN_SUCCESS;
}
uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len)
{
if (msg == NULL || str == NULL || str_len == 0) {
return 0;
}
uint32_t len = 0;
len = srsran_print_check(str, str_len, len, "payload=");
len += srsran_vec_sprint_hex(&str[len], str_len - len, (uint8_t*)msg->payload, SRSRAN_PBCH_NR_PAYLOAD_SZ);
len = srsran_print_check(str,
str_len,
len,
" sfn_lsb=%d ssb_idx=%d k_ssb_msb=%d hrf=%d ",
msg->sfn_4lsb,
msg->ssb_idx,
msg->k_ssb_msb,
msg->hrf);
return len;
}

@ -24,6 +24,7 @@
#include <string.h>
#include "srsran/phy/common/phy_common.h"
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/phch/prach.h"
#include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/vector.h"
@ -127,16 +128,20 @@ bool srsran_prach_tti_opportunity(srsran_prach_t* p, uint32_t current_tti, int a
return false;
}
if (p->is_nr) {
return srsran_prach_nr_tti_opportunity_fr1_unpaired(p->config_idx, current_tti);
}
uint32_t config_idx = p->config_idx;
if (!p->tdd_config.configured) {
return srsran_prach_tti_opportunity_config_fdd(config_idx, current_tti, allowed_subframe);
if (p->tdd_config.configured) {
if (p->is_nr) {
return srsran_prach_nr_tti_opportunity_fr1_unpaired(p->config_idx, current_tti);
} else {
return srsran_prach_tti_opportunity_config_tdd(
config_idx, p->tdd_config.sf_config, current_tti, &p->current_prach_idx);
}
} else {
return srsran_prach_tti_opportunity_config_tdd(
config_idx, p->tdd_config.sf_config, current_tti, &p->current_prach_idx);
if (p->is_nr) {
return srsran_prach_nr_tti_opportunity_fr1_paired(p->config_idx, current_tti);
} else {
return srsran_prach_tti_opportunity_config_fdd(config_idx, current_tti, allowed_subframe);
}
}
}
@ -290,6 +295,66 @@ void srsran_prach_sf_config(uint32_t config_idx, srsran_prach_sf_config_t* sf_co
memcpy(sf_config, &prach_sf_config[config_idx % 16], sizeof(srsran_prach_sf_config_t));
}
const prach_nr_config_t* srsran_prach_nr_get_cfg_fr1_paired(uint32_t config_idx)
{
if (config_idx < PRACH_NR_CFG_FR1_PAIRED_NOF_CFG) {
return &prach_nr_cfg_fr1_paired[config_idx];
}
ERROR("Invalid configuration index %d", config_idx);
return NULL;
}
bool srsran_prach_nr_tti_opportunity_fr1_paired(uint32_t config_idx, uint32_t current_tti)
{
uint32_t sfn = current_tti / SRSRAN_NOF_SF_X_FRAME;
uint32_t sf_idx = current_tti % SRSRAN_NOF_SF_X_FRAME;
// Get configuration
const prach_nr_config_t* cfg = srsran_prach_nr_get_cfg_fr1_paired(config_idx);
if (cfg == NULL) {
return false;
}
// Protect zero division
if (cfg->x == 0) {
ERROR("Invalid Zero value");
return false;
}
// Check for System Frame Number match
if (sfn % cfg->x != cfg->y) {
return false;
}
// Protect subframe number vector access
if (cfg->nof_subframe_number > PRACH_NR_CFG_MAX_NOF_SF) {
ERROR("Invalid number of subframes (%d)", cfg->nof_subframe_number);
return false;
}
// Check for subframe number match
for (uint32_t i = 0; i < cfg->nof_subframe_number; i++) {
if (cfg->subframe_number[i] == sf_idx) {
return true;
}
}
// If reached here, no opportunity
return false;
}
uint32_t srsran_prach_nr_start_symbol_fr1_paired(uint32_t config_idx)
{
// Get configuration
const prach_nr_config_t* cfg = srsran_prach_nr_get_cfg_fr1_paired(config_idx);
if (cfg == NULL) {
return 0;
}
return cfg->starting_symbol;
}
const prach_nr_config_t* srsran_prach_nr_get_cfg_fr1_unpaired(uint32_t config_idx)
{
if (config_idx < PRACH_NR_CFG_FR1_UNPAIRED_NOF_CFG) {
@ -339,12 +404,21 @@ bool srsran_prach_nr_tti_opportunity_fr1_unpaired(uint32_t config_idx, uint32_t
return false;
}
uint32_t srsran_prach_nr_start_symbol_fr1_unpaired(uint32_t config_idx)
uint32_t srsran_prach_nr_start_symbol(uint32_t config_idx, srsran_duplex_mode_t duplex_mode)
{
// Get configuration
const prach_nr_config_t* cfg = srsran_prach_nr_get_cfg_fr1_unpaired(config_idx);
if (cfg == NULL) {
return false;
const prach_nr_config_t* cfg;
if (duplex_mode == SRSRAN_DUPLEX_MODE_TDD) {
// Get configuration
cfg = srsran_prach_nr_get_cfg_fr1_unpaired(config_idx);
if (cfg == NULL) {
return 0;
}
} else {
// Get configuration
cfg = srsran_prach_nr_get_cfg_fr1_paired(config_idx);
if (cfg == NULL) {
return 0;
}
}
return cfg->starting_symbol;

@ -455,10 +455,29 @@ static const prach_nr_config_t prach_nr_cfg_fr1_unpaired[PRACH_NR_CFG_FR1_UNPAIR
{0, 1, 0, {8}, 1, 0}, {0, 1, 0, {7}, 1, 0},
{0, 1, 0, {6}, 1, 0}, {0, 1, 0, {5}, 1, 0},
{0, 1, 0, {4}, 1, 0}, {0, 1, 0, {3}, 1, 0},
{0, 1, 0, {2}, 1, 0}, {0, 1, 0, {1, 6}, 1, 0},
{0, 1, 0, {1, 6}, 1, 7}, {0, 1, 0, {4, 9}, 1, 0},
{0, 1, 0, {3, 8}, 1, 0}, {0, 1, 0, {2, 7}, 1, 0},
{0, 1, 0, {8, 9}, 1, 0}, {0, 1, 0, {4, 8, 9}, 1, 0},
{0, 1, 0, {3, 4, 9}, 1, 0}, {0, 1, 0, {7, 8, 9}, 1, 0},
{0, 1, 0, {3, 4, 8, 9}, 1, 0}, {0, 1, 0, {6, 7, 8, 9}, 1, 0},
{0, 1, 0, {1, 4, 6, 9}, 1, 0}, {0, 1, 0, {1, 3, 5, 7, 9}, 1, 0}};
{0, 1, 0, {2}, 1, 0}, {0, 1, 0, {1, 6}, 2, 0},
{0, 1, 0, {1, 6}, 2, 7}, {0, 1, 0, {4, 9}, 2, 0},
{0, 1, 0, {3, 8}, 2, 0}, {0, 1, 0, {2, 7}, 2, 0},
{0, 1, 0, {8, 9}, 2, 0}, {0, 1, 0, {4, 8, 9}, 3, 0},
{0, 1, 0, {3, 4, 9}, 3, 0}, {0, 1, 0, {7, 8, 9}, 3, 0},
{0, 1, 0, {3, 4, 8, 9}, 4, 0}, {0, 1, 0, {6, 7, 8, 9}, 4, 0},
{0, 1, 0, {1, 4, 6, 9}, 4, 0}, {0, 1, 0, {1, 3, 5, 7, 9}, 5, 0}};
#define PRACH_NR_CFG_FR1_PAIRED_NOF_CFG 28
// Table 6.3.3.2-2: Random access configurations for FR1 and paired spectrum.
static const prach_nr_config_t prach_nr_cfg_fr1_paired[PRACH_NR_CFG_FR1_PAIRED_NOF_CFG] = {
{0, 16, 1, {1}, 1, 0}, {0, 16, 1, {4}, 1, 0},
{0, 16, 1, {7}, 1, 0}, {0, 16, 1, {9}, 1, 0},
{0, 8, 1, {1}, 1, 0}, {0, 8, 1, {4}, 1, 0},
{0, 8, 1, {7}, 1, 0}, {0, 8, 1, {9}, 1, 0},
{0, 4, 1, {1}, 1, 0}, {0, 4, 1, {4}, 1, 0},
{0, 4, 1, {7}, 1, 0}, {0, 4, 1, {9}, 1, 0},
{0, 2, 1, {1}, 1, 0}, {0, 2, 1, {4}, 1, 0},
{0, 2, 1, {7}, 1, 0}, {0, 2, 1, {9}, 1, 0},
{0, 1, 0, {1}, 1, 0}, {0, 1, 0, {4}, 1, 0},
{0, 1, 0, {7}, 1, 0}, {0, 1, 0, {1, 6}, 2, 0},
{0, 1, 0, {2, 7}, 2, 0}, {0, 1, 0, {3, 8}, 2, 0},
{0, 1, 0, {1, 4, 7}, 3, 0}, {0, 1, 0, {2, 5, 8}, 3, 0},
{0, 1, 0, {3, 6, 9}, 3, 0}, {0, 1, 0, {0, 2, 4, 6, 8}, 5, 0},
{0, 1, 0, {1, 3, 5, 7, 9}, 5, 0}, {0, 1, 0, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 10, 0}};

@ -616,6 +616,7 @@ int regs_num_x_symbol(uint32_t symbol, uint32_t nof_port, srsran_cp_t cp)
ERROR("Invalid symbol %d", symbol);
return SRSRAN_ERROR;
}
return SRSRAN_ERROR;
}
/**

@ -639,6 +639,10 @@ add_executable(dci_nr_test dci_nr_test.c)
target_link_libraries(dci_nr_test srsran_phy)
add_nr_test(dci_nr_test dci_nr_test)
add_executable(mib_nr_test mib_nr_test.c)
target_link_libraries(mib_nr_test srsran_phy)
add_nr_test(mib_nr_test mib_nr_test)
add_executable(pucch_nr_test pucch_nr_test.c)
target_link_libraries(pucch_nr_test srsran_phy)
add_nr_test(pucch_nr_test pucch_nr_test)

@ -0,0 +1,109 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsran/phy/phch/pbch_msg_nr.h"
#include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/random.h"
#include "srsran/support/srsran_test.h"
#include <getopt.h>
#include <string.h>
static uint32_t nof_repetitions = 16;
static srsran_random_t random_gen = NULL;
static int test_packing_unpacking()
{
for (uint32_t r = 0; r < nof_repetitions; r++) {
srsran_mib_nr_t mib = {};
mib.sfn = srsran_random_uniform_int_dist(random_gen, 0, 1023);
mib.ssb_idx = srsran_random_uniform_int_dist(random_gen, 0, 127);
mib.hrf = srsran_random_bool(random_gen, 0.5f);
mib.scs_common =
srsran_random_bool(random_gen, 0.5f) ? srsran_subcarrier_spacing_15kHz : srsran_subcarrier_spacing_30kHz;
mib.ssb_offset = srsran_random_uniform_int_dist(random_gen, 0, 31);
mib.dmrs_typeA_pos =
srsran_random_bool(random_gen, 0.5f) ? srsran_dmrs_sch_typeA_pos_2 : srsran_dmrs_sch_typeA_pos_3;
mib.coreset0_idx = srsran_random_uniform_int_dist(random_gen, 0, 15);
mib.ss0_idx = srsran_random_uniform_int_dist(random_gen, 0, 15);
mib.cell_barred = srsran_random_bool(random_gen, 0.5f);
mib.intra_freq_reselection = srsran_random_bool(random_gen, 0.5f);
mib.spare = srsran_random_uniform_int_dist(random_gen, 0, 1);
srsran_pbch_msg_nr_t pbch_msg = {};
TESTASSERT(srsran_pbch_msg_nr_mib_pack(&mib, &pbch_msg) == SRSRAN_SUCCESS);
TESTASSERT(srsran_pbch_msg_nr_is_mib(&pbch_msg));
srsran_mib_nr_t mib2 = {};
TESTASSERT(srsran_pbch_msg_nr_mib_unpack(&pbch_msg, &mib2) == SRSRAN_SUCCESS);
char str1[256];
char str2[256];
char strp[256];
srsran_pbch_msg_nr_mib_info(&mib, str1, (uint32_t)sizeof(str1));
srsran_pbch_msg_nr_mib_info(&mib2, str2, (uint32_t)sizeof(str2));
srsran_pbch_msg_info(&pbch_msg, strp, (uint32_t)sizeof(strp));
if (memcmp(&mib, &mib2, sizeof(srsran_mib_nr_t)) != 0) {
ERROR("Failed packing/unpacking MIB");
printf(" Source: %s\n", str1);
printf("Unpacked: %s\n", str2);
printf(" Packed: %s\n", strp);
return SRSRAN_ERROR;
}
}
return SRSRAN_SUCCESS;
}
static void usage(char* prog)
{
printf("Usage: %s [cpndv]\n", prog);
printf("\t-v Increase verbose [default none]\n");
printf("\t-R Set number of Packing/Unpacking [default %d]\n", nof_repetitions);
}
static void parse_args(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "vR")) != -1) {
switch (opt) {
case 'v':
srsran_verbose++;
break;
case 'R':
nof_repetitions = (uint32_t)strtol(argv[optind], NULL, 10);
break;
default:
usage(argv[0]);
exit(-1);
}
}
}
int main(int argc, char** argv)
{
parse_args(argc, argv);
int ret = SRSRAN_ERROR;
random_gen = srsran_random_init(1234);
if (test_packing_unpacking() < SRSRAN_SUCCESS) {
goto clean_exit;
}
ret = SRSRAN_SUCCESS;
clean_exit:
srsran_random_free(random_gen);
return ret;
}

@ -498,7 +498,7 @@ bool rf_uhd_rx_wait_lo_locked(void* h)
return is_locked;
}
static inline int rf_uhd_start_rx_stream_unsafe(rf_uhd_handler_t* handler)
static inline int rf_uhd_start_rx_stream_nolock(rf_uhd_handler_t* handler)
{
// Check if stream was not created or started
if (not handler->uhd->is_rx_ready() or handler->rx_stream_enabled) {
@ -521,10 +521,10 @@ int rf_uhd_start_rx_stream(void* h, bool now)
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
std::unique_lock<std::mutex> lock(handler->rx_mutex);
return rf_uhd_start_rx_stream_unsafe(handler);
return rf_uhd_start_rx_stream_nolock(handler);
}
static inline int rf_uhd_stop_rx_stream_unsafe(rf_uhd_handler_t* handler)
static inline int rf_uhd_stop_rx_stream_nolock(rf_uhd_handler_t* handler)
{
// Check if stream was created or stream was not started
if (not handler->uhd->is_rx_ready() or not handler->rx_stream_enabled) {
@ -547,7 +547,7 @@ int rf_uhd_stop_rx_stream(void* h)
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
std::unique_lock<std::mutex> lock(handler->rx_mutex);
if (rf_uhd_stop_rx_stream_unsafe(handler) < SRSRAN_SUCCESS) {
if (rf_uhd_stop_rx_stream_nolock(handler) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
@ -946,7 +946,7 @@ int rf_uhd_close(void* h)
return SRSRAN_SUCCESS;
}
static inline void rf_uhd_set_master_clock_rate_unsafe(rf_uhd_handler_t* handler, double rate)
static inline void rf_uhd_set_master_clock_rate_nolock(rf_uhd_handler_t* handler, double rate)
{
// Set master clock rate if it is allowed and change is required
if (handler->dynamic_master_rate and handler->current_master_clock != rate) {
@ -994,14 +994,14 @@ double rf_uhd_set_rx_srate(void* h, double freq)
// Stop RX streamer
if (RF_UHD_IMP_PROHIBITED_STOP_START.count(handler->devname) == 0) {
if (rf_uhd_stop_rx_stream_unsafe(handler) != SRSRAN_SUCCESS) {
if (rf_uhd_stop_rx_stream_nolock(handler) != SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
}
// Set master clock rate
if (fmod(handler->current_master_clock, freq) > 0.0) {
rf_uhd_set_master_clock_rate_unsafe(handler, 4 * freq);
rf_uhd_set_master_clock_rate_nolock(handler, 4 * freq);
}
if (handler->nof_rx_channels > 1) {
@ -1052,7 +1052,7 @@ double rf_uhd_set_tx_srate(void* h, double freq)
// Set master clock rate
if (fmod(handler->current_master_clock, freq) > 0.0) {
rf_uhd_set_master_clock_rate_unsafe(handler, 4 * freq);
rf_uhd_set_master_clock_rate_nolock(handler, 4 * freq);
}
if (handler->nof_tx_channels > 1) {
@ -1267,7 +1267,7 @@ int rf_uhd_recv_with_time_multi(void* h,
// Start stream if not started
if (not handler->rx_stream_enabled) {
if (rf_uhd_start_rx_stream_unsafe(handler) != SRSRAN_SUCCESS) {
if (rf_uhd_start_rx_stream_nolock(handler) != SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
}
@ -1312,7 +1312,7 @@ int rf_uhd_recv_with_time_multi(void* h,
if (RF_UHD_IMP_PROHIBITED_STOP_START.count(handler->devname) == 0) {
// Stop Rx stream
rf_uhd_stop_rx_stream_unsafe(handler);
rf_uhd_stop_rx_stream_nolock(handler);
}
return -1;

@ -141,11 +141,21 @@ add_test(cfo_test_2 cfo_test -f 0.99849 -n 1000)
add_executable(ssb_measure_test ssb_measure_test.c)
target_link_libraries(ssb_measure_test srsran_phy)
add_nr_test(ssb_measure_test ssb_measure_test)
add_executable(ssb_decode_test ssb_decode_test.c)
target_link_libraries(ssb_decode_test srsran_phy)
add_nr_test(ssb_decode_test ssb_decode_test)
# For each supported SSB subcarrier spacing
foreach (SSB_SCS 15 30)
# For each supported Cell/Carrier subcarrier spacing
foreach (CELL_SCS 15 30)
# Test SSB measurements
add_nr_test(ssb_measure_test_${SSB_SCS}_${CELL_SCS} ssb_measure_test -s ${SSB_SCS} -S ${CELL_SCS})
# Test SSB PBCH decoding
add_nr_test(ssb_decode_test_${SSB_SCS}_${CELL_SCS} ssb_decode_test -s ${SSB_SCS} -S ${CELL_SCS})
endforeach ()
endforeach ()
add_executable(ssb_file_test ssb_file_test.c)
target_link_libraries(ssb_file_test srsran_phy)

@ -50,14 +50,30 @@ static cf_t* buffer = NULL; // Base-band buffer
static void usage(char* prog)
{
printf("Usage: %s [v]\n", prog);
printf("\t-s SSB subcarrier spacing [default, %s kHz]\n", srsran_subcarrier_spacing_to_str(ssb_scs));
printf("\t-S cell/carrier subcarrier spacing [default, %s kHz]\n", srsran_subcarrier_spacing_to_str(carrier_scs));
printf("\t-v [set srsran_verbose to debug, default none]\n");
}
static void parse_args(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "v")) != -1) {
while ((opt = getopt(argc, argv, "Ssv")) != -1) {
switch (opt) {
case 's':
ssb_scs = srsran_subcarrier_spacing_from_str(argv[optind]);
if (ssb_scs == srsran_subcarrier_spacing_invalid) {
ERROR("Invalid SSB subcarrier spacing %s\n", argv[optind]);
exit(-1);
}
break;
case 'S':
carrier_scs = srsran_subcarrier_spacing_from_str(argv[optind]);
if (carrier_scs == srsran_subcarrier_spacing_invalid) {
ERROR("Invalid Cell/Carrier subcarrier spacing %s\n", argv[optind]);
exit(-1);
}
break;
case 'v':
srsran_verbose++;
break;
@ -91,7 +107,7 @@ static void gen_pbch_msg(srsran_pbch_msg_nr_t* pbch_msg, uint32_t ssb_idx)
SRSRAN_MEM_ZERO(pbch_msg, srsran_pbch_msg_nr_t, 1);
// Generate payload
srsran_random_bit_vector(random_gen, pbch_msg->payload, SRSRAN_PBCH_NR_PAYLOAD_SZ);
srsran_random_bit_vector(random_gen, pbch_msg->payload, SRSRAN_PBCH_MSG_NR_SZ);
pbch_msg->ssb_idx = ssb_idx;
pbch_msg->crc = true;

@ -54,14 +54,30 @@ static cf_t* buffer = NULL; // Base-band buffer
static void usage(char* prog)
{
printf("Usage: %s [v]\n", prog);
printf("\t-s SSB subcarrier spacing [default, %s kHz]\n", srsran_subcarrier_spacing_to_str(ssb_scs));
printf("\t-S cell/carrier subcarrier spacing [default, %s kHz]\n", srsran_subcarrier_spacing_to_str(carrier_scs));
printf("\t-v [set srsran_verbose to debug, default none]\n");
}
static void parse_args(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "v")) != -1) {
while ((opt = getopt(argc, argv, "Ssv")) != -1) {
switch (opt) {
case 's':
ssb_scs = srsran_subcarrier_spacing_from_str(argv[optind]);
if (ssb_scs == srsran_subcarrier_spacing_invalid) {
ERROR("Invalid SSB subcarrier spacing %s\n", argv[optind]);
exit(-1);
}
break;
case 'S':
carrier_scs = srsran_subcarrier_spacing_from_str(argv[optind]);
if (carrier_scs == srsran_subcarrier_spacing_invalid) {
ERROR("Invalid Cell/Carrier subcarrier spacing %s\n", argv[optind]);
exit(-1);
}
break;
case 'v':
srsran_verbose++;
break;

@ -23,6 +23,7 @@
#include "srsran/common/standard_streams.h"
#include "srsran/common/string_helpers.h"
#include "srsran/config.h"
#include "srsran/support/srsran_assert.h"
#include <list>
#include <string>
#include <unistd.h>
@ -711,6 +712,13 @@ void radio::set_rx_srate(const double& srate)
}
}
// Assert ratio is integer
srsran_assert(((uint32_t)cur_rx_srate % (uint32_t)srate) == 0,
"The sampling rate ratio is not integer (%.2f MHz / %.2 MHz = %.3f)",
cur_rx_srate / 1e6,
srate / 1e6,
cur_rx_srate / srate);
// Update decimators
uint32_t ratio = (uint32_t)ceil(cur_rx_srate / srate);
for (uint32_t ch = 0; ch < nof_channels; ch++) {
@ -957,6 +965,13 @@ void radio::set_tx_srate(const double& srate)
}
}
// Assert ratio is integer
srsran_assert(((uint32_t)cur_tx_srate % (uint32_t)srate) == 0,
"The sampling rate ratio is not integer (%.2f MHz / %.2 MHz = %.3f)",
cur_rx_srate / 1e6,
srate / 1e6,
cur_rx_srate / srate);
// Update interpolators
uint32_t ratio = (uint32_t)ceil(cur_tx_srate / srate);
for (uint32_t ch = 0; ch < nof_channels; ch++) {

@ -308,6 +308,7 @@ void rlc_am_lte::rlc_am_lte_tx::set_bsr_callback(bsr_callback_t callback)
bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
{
std::lock_guard<std::mutex> lock(mutex);
if (cfg_.tx_queue_length > MAX_SDUS_PER_RLC_PDU) {
logger.error("Configuring Tx queue length of %d PDUs too big. Maximum value is %d.",
cfg_.tx_queue_length,
@ -334,6 +335,8 @@ bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
poll_retx_timer.set(static_cast<uint32_t>(cfg.t_poll_retx), [this](uint32_t timerid) { timer_expired(timerid); });
}
// make sure Tx queue is empty before attempting to resize
empty_queue_nolock();
tx_sdu_queue.resize(cfg_.tx_queue_length);
tx_enabled = true;
@ -343,10 +346,10 @@ bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
void rlc_am_lte::rlc_am_lte_tx::stop()
{
empty_queue();
std::lock_guard<std::mutex> lock(mutex);
empty_queue_nolock();
tx_enabled = false;
if (parent->timers != nullptr && poll_retx_timer.is_valid()) {
@ -378,7 +381,11 @@ void rlc_am_lte::rlc_am_lte_tx::stop()
void rlc_am_lte::rlc_am_lte_tx::empty_queue()
{
std::lock_guard<std::mutex> lock(mutex);
empty_queue_nolock();
}
void rlc_am_lte::rlc_am_lte_tx::empty_queue_nolock()
{
// deallocate all SDUs in transmit queue
while (tx_sdu_queue.size() > 0) {
unique_byte_buffer_t buf = tx_sdu_queue.read();

@ -135,11 +135,13 @@ uint32_t rlc_tm::get_buffer_state()
rlc_bearer_metrics_t rlc_tm::get_metrics()
{
std::lock_guard<std::mutex> lock(metrics_mutex);
return metrics;
}
void rlc_tm::reset_metrics()
{
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics = {};
}
@ -165,6 +167,7 @@ uint32_t rlc_tm::read_pdu(uint8_t* payload, uint32_t nof_bytes)
ul_queue.size(),
ul_queue.size_bytes());
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_tx_pdu_bytes += pdu_size;
return pdu_size;
} else {
@ -184,8 +187,11 @@ void rlc_tm::write_pdu(uint8_t* payload, uint32_t nof_bytes)
memcpy(buf->msg, payload, nof_bytes);
buf->N_bytes = nof_bytes;
buf->set_timestamp();
metrics.num_rx_pdu_bytes += nof_bytes;
metrics.num_rx_pdus++;
{
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_rx_pdu_bytes += nof_bytes;
metrics.num_rx_pdus++;
}
if (srsran::srb_to_lcid(srsran::lte_srb::srb0) == lcid) {
rrc->write_pdu(lcid, std::move(buf));
} else {

@ -91,15 +91,18 @@ void rlc_um_base::write_sdu(unique_byte_buffer_t sdu)
{
if (not tx_enabled || not tx) {
logger.debug("%s is currently deactivated. Dropping SDU (%d B)", rb_name.c_str(), sdu->N_bytes);
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_lost_sdus++;
return;
}
int sdu_bytes = sdu->N_bytes; //< Store SDU length for book-keeping
if (tx->try_write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) {
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_tx_sdus++;
metrics.num_tx_sdu_bytes += sdu_bytes;
} else {
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_lost_sdus++;
}
}
@ -111,6 +114,7 @@ void rlc_um_base::discard_sdu(uint32_t discard_sn)
return;
}
tx->discard_sdu(discard_sn);
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_lost_sdus++;
}
@ -144,6 +148,7 @@ uint32_t rlc_um_base::read_pdu(uint8_t* payload, uint32_t nof_bytes)
if (tx && tx_enabled) {
uint32_t len = tx->build_data_pdu(payload, nof_bytes);
if (len > 0) {
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_tx_pdu_bytes += len;
metrics.num_tx_pdus++;
}
@ -155,19 +160,24 @@ uint32_t rlc_um_base::read_pdu(uint8_t* payload, uint32_t nof_bytes)
void rlc_um_base::write_pdu(uint8_t* payload, uint32_t nof_bytes)
{
if (rx && rx_enabled) {
metrics.num_rx_pdus++;
metrics.num_rx_pdu_bytes += nof_bytes;
{
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics.num_rx_pdus++;
metrics.num_rx_pdu_bytes += nof_bytes;
}
rx->handle_data_pdu(payload, nof_bytes);
}
}
rlc_bearer_metrics_t rlc_um_base::get_metrics()
{
std::lock_guard<std::mutex> lock(metrics_mutex);
return metrics;
}
void rlc_um_base::reset_metrics()
{
std::lock_guard<std::mutex> lock(metrics_mutex);
metrics = {};
}

@ -1230,43 +1230,142 @@ int test_cell_group_config_fdd()
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = true;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.set_setup();
//TODO?
// nzp-CSI-RS Resource
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list_present = true;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(1);
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(5);
auto& nzp_csi_res =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0];
nzp_csi_res.nzp_csi_rs_res_id = 0;
nzp_csi_res.res_map.freq_domain_alloc.set_row2();
nzp_csi_res.res_map.freq_domain_alloc.row2().from_number(0b100000000000);
nzp_csi_res.res_map.nrof_ports = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1;
nzp_csi_res.res_map.first_ofdm_symbol_in_time_domain = 4;
nzp_csi_res.res_map.cdm_type = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm;
nzp_csi_res.res_map.density.set_one();
nzp_csi_res.res_map.freq_band.start_rb = 0;
nzp_csi_res.res_map.freq_band.nrof_rbs = 52;
nzp_csi_res.pwr_ctrl_offset = 0;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup();
// item 0
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].nzp_csi_rs_res_id = 0;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.set_row2();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.row2().from_number(0b100000000000);
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.nrof_ports =
asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.first_ofdm_symbol_in_time_domain = 4;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.cdm_type =
asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.density.set_one();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.start_rb = 0;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.nrof_rbs = 52;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].pwr_ctrl_offset = 0;
// Skip pwr_ctrl_offset_ss_present
nzp_csi_res.scrambling_id = 500;
nzp_csi_res.periodicity_and_offset_present = true;
nzp_csi_res.periodicity_and_offset.set_slots80();
nzp_csi_res.periodicity_and_offset.slots80() = 1;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].scrambling_id = 500;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.set_slots80();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.slots80() = 1;
// optional
nzp_csi_res.qcl_info_periodic_csi_rs_present = true;
nzp_csi_res.qcl_info_periodic_csi_rs = 0;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].qcl_info_periodic_csi_rs_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].qcl_info_periodic_csi_rs = 0;
// item 1
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].nzp_csi_rs_res_id = 1;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_domain_alloc.set_row1();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_domain_alloc.row1().from_number(0b0001);
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.nrof_ports =
asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.first_ofdm_symbol_in_time_domain = 4;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.cdm_type =
asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.density.set_three();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_band.start_rb = 0;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_band.nrof_rbs = 52;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].pwr_ctrl_offset = 0;
// Skip pwr_ctrl_offset_ss_present
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].scrambling_id = 500;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset.set_slots40();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset.slots40() = 11;
// optional
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].qcl_info_periodic_csi_rs_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].qcl_info_periodic_csi_rs = 0;
// item 2
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].nzp_csi_rs_res_id = 2;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_domain_alloc.set_row1();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_domain_alloc.row1().from_number(0b0001);
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.nrof_ports =
asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.first_ofdm_symbol_in_time_domain = 8;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.cdm_type =
asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.density.set_three();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_band.start_rb = 0;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_band.nrof_rbs = 52;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].pwr_ctrl_offset = 0;
// Skip pwr_ctrl_offset_ss_present
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].scrambling_id = 500;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset.set_slots40();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset.slots40() = 11;
// optional
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].qcl_info_periodic_csi_rs_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].qcl_info_periodic_csi_rs = 0;
// item 3
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].nzp_csi_rs_res_id = 3;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_domain_alloc.set_row1();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_domain_alloc.row1().from_number(0b0001);
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.nrof_ports =
asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.first_ofdm_symbol_in_time_domain = 4;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.cdm_type =
asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.density.set_three();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_band.start_rb = 0;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_band.nrof_rbs = 52;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].pwr_ctrl_offset = 0;
// Skip pwr_ctrl_offset_ss_present
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].scrambling_id = 500;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset.set_slots40();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset.slots40() = 12;
// optional
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].qcl_info_periodic_csi_rs_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].qcl_info_periodic_csi_rs = 0;
// item 4
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].nzp_csi_rs_res_id = 4;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_domain_alloc.set_row1();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_domain_alloc.row1().from_number(0b0001);
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.nrof_ports =
asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.first_ofdm_symbol_in_time_domain = 8;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.cdm_type =
asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.density.set_three();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_band.start_rb = 0;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_band.nrof_rbs = 52;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].pwr_ctrl_offset = 0;
// Skip pwr_ctrl_offset_ss_present
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].scrambling_id = 500;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset.set_slots40();
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset.slots40() = 12;
// optional
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].qcl_info_periodic_csi_rs_present = true;
nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].qcl_info_periodic_csi_rs = 0;
//TODO?
// nzp-CSI-RS ResourceSet
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list_present =
true;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1);
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(2);
auto& nzp_csi_res_set =
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0];
nzp_csi_res_set.nzp_csi_res_set_id = 1;
nzp_csi_res_set.nzp_csi_rs_res.resize(1);
nzp_csi_res_set.nzp_csi_rs_res[0] = 1;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup();
// item 0
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_res_set_id = 0;
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_rs_res.resize(1);
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_rs_res[0] = 0;
// item 1
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_res_set_id = 1;
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res.resize(4);
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[0] = 1;
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[1] = 2;
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[2] = 3;
nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[3] = 4;
// Skip TRS info
// CSI IM config
// TODO: add csi im config
// CSI resource config
// TODO: add csi resource config
// CSI report config
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list_present = true;
cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list.resize(1);
@ -1396,6 +1495,10 @@ int test_cell_group_config_fdd()
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.dummy = time_align_timer_opts::ms500;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul.freq_band_list
.push_back(5);
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul.absolute_freq_point_a =
166364;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul
.scs_specific_carrier_list.resize(1);
auto& ul_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul

@ -89,15 +89,15 @@ int test_tagged_union()
{
using srsran::choice_details::tagged_union_t;
tagged_union_t<char, int, double, C> u;
u.construct_unsafe(5);
u.construct_unchecked(5);
TESTASSERT(u.is<int>());
TESTASSERT(u.get_unchecked<int>() == 5);
u.destroy_unsafe<int>();
u.destroy_unchecked<int>();
TESTASSERT(C::counter == 0);
u.construct_unsafe<C>(C{});
u.construct_unchecked<C>(C{});
TESTASSERT(C::counter == 1);
u.destroy_unsafe<C>();
u.destroy_unchecked<C>();
TESTASSERT(C::counter == 0);
return SRSRAN_SUCCESS;

@ -178,7 +178,8 @@ enable = false
# target_bler: Target BLER (in decimal) to achieve via adaptive link
# max_delta_dl_cqi: Maximum shift in CQI for adaptive DL link
# max_delta_ul_snr: Maximum shift in UL SNR for adaptive UL link
# adaptive_link_step_size: Step size or learning rate used in adaptive link
# adaptive_dl_mcs_step_size: Step size or learning rate used in adaptive DL MCS link
# adaptive_ul_mcs_step_size: Step size or learning rate used in adaptive UL MCS link
# min_tpc_tti_interval: Minimum TTI interval between TPCs different than 1
# ul_snr_avg_alpha: Exponential Average alpha coefficient used in estimation of UL SNR
# init_ul_snr_value: Initial UL SNR value used for computing MCS in the first UL grant
@ -204,7 +205,8 @@ enable = false
#target_bler = 0.05
#max_delta_dl_cqi = 5
#max_delta_ul_snr = 5
#adaptive_link_step_size = 0.001
#adaptive_dl_mcs_step_size = 0.001
#adaptive_ul_mcs_step_size = 0.001
#min_tpc_tti_interval = 1
#ul_snr_avg_alpha=0.05
#init_ul_snr_value=5

@ -157,13 +157,13 @@ public:
private:
const static int ENB_POOL_SIZE = 1024 * 10;
int parse_args(const all_args_t& args_, rrc_cfg_t& rrc_cfg);
int parse_args(const all_args_t& args_, rrc_cfg_t& rrc_cfg_, rrc_nr_cfg_t& rrc_cfg_nr_);
srslog::sink& log_sink;
srslog::basic_logger& enb_log;
all_args_t args = {};
bool started = false;
all_args_t args = {};
std::atomic<bool> started = {false};
phy_cfg_t phy_cfg = {};
rrc_cfg_t rrc_cfg = {};
@ -173,8 +173,8 @@ private:
x2_adapter x2;
std::unique_ptr<enb_stack_base> eutra_stack = nullptr;
std::unique_ptr<enb_stack_base> nr_stack = nullptr;
std::unique_ptr<srsran::radio_base> radio = nullptr;
std::unique_ptr<enb_phy_base> phy = nullptr;
std::unique_ptr<srsran::radio_base> radio = nullptr;
std::unique_ptr<enb_phy_base> phy = nullptr;
// System metrics processor.
srsran::sys_metrics_processor sys_proc;

@ -35,10 +35,9 @@ namespace srsenb {
class metrics_json : public srsran::metrics_listener<enb_metrics_t>
{
public:
metrics_json(srslog::log_channel& c) : log_c(c) {}
metrics_json(srslog::log_channel& c, enb_metrics_interface* enb_) : log_c(c), enb(enb_) {}
void set_metrics(const enb_metrics_t& m, const uint32_t period_usec) override;
void set_handle(enb_metrics_interface* enb_);
void stop() override {}
private:

@ -127,6 +127,10 @@ public:
{
rrc.sgnb_addition_complete(eutra_rnti, nr_rnti);
}
void set_activity_user(uint16_t eutra_rnti) final { rrc.set_activity_user(eutra_rnti); }
// gtpu_interface_pdcp
void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu);
private:
static const int STACK_MAIN_THREAD_PRIO = 4;

@ -29,8 +29,6 @@
#include "srsenb/hdr/stack/mac/nr/mac_nr.h"
#include "srsenb/hdr/stack/rrc/rrc_nr.h"
#include "srsenb/hdr/stack/upper/pdcp_nr.h"
#include "srsenb/hdr/stack/upper/rlc_nr.h"
#include "upper/pdcp.h"
#include "upper/rlc.h"
#include "upper/sdap.h"
@ -38,10 +36,6 @@
#include "enb_stack_base.h"
#include "srsran/interfaces/gnb_interfaces.h"
// This is needed for GW
#include "srsran/interfaces/ue_interfaces.h"
#include "srsue/hdr/stack/upper/gw.h"
namespace srsenb {
class gnb_stack_nr final : public srsenb::enb_stack_base,

@ -37,16 +37,17 @@
namespace srsenb {
struct mac_nr_args_t {
srsran::phy_cfg_nr_t phy_base_cfg = {};
int fixed_dl_mcs = -1;
int fixed_ul_mcs = -1;
srsenb::pcap_args_t pcap;
srsran::phy_cfg_nr_t phy_base_cfg = {};
int fixed_dl_mcs = -1;
int fixed_ul_mcs = -1;
sched_nr_interface::sched_cfg_t sched_cfg = {};
srsenb::pcap_args_t pcap;
};
class mac_nr final : public mac_interface_phy_nr, public mac_interface_rrc_nr, public mac_interface_rlc_nr
{
public:
mac_nr(srsran::task_sched_handle task_sched_, const srsenb::sched_nr_interface::sched_cfg_t& sched_cfg = {});
explicit mac_nr(srsran::task_sched_handle task_sched_);
~mac_nr();
int init(const mac_nr_args_t& args_,
@ -63,13 +64,12 @@ public:
uint16_t reserve_rnti(uint32_t enb_cc_idx) override;
int read_pdu_bcch_bch(uint8_t* payload);
int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override;
int remove_ue(uint16_t rnti) override;
// MAC interface for RLC
// TODO:
int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) override { return 0; }
int rlc_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t tx_queue, uint32_t retx_queue) override;
// Interface for PHY
void process_pdus();
int slot_indication(const srsran_slot_cfg_t& slot_cfg) override;
int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override;
int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override;
@ -80,11 +80,10 @@ public:
private:
uint16_t add_ue_(uint32_t enb_cc_idx);
uint16_t alloc_ue(uint32_t enb_cc_idx);
int remove_ue(uint16_t rnti);
// internal misc helpers
bool is_rnti_valid_unsafe(uint16_t rnti);
bool is_rnti_active_unsafe(uint16_t rnti);
bool is_rnti_valid_nolock(uint16_t rnti);
bool is_rnti_active_nolock(uint16_t rnti);
// handle UCI data from either PUCCH or PUSCH
bool handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg, const srsran_uci_value_nr_t& value);
@ -93,7 +92,7 @@ private:
int handle_pdu(srsran::unique_byte_buffer_t pdu);
// Encoding
srsran::byte_buffer_t* assemble_rar(srsran::const_span<sched_nr_interface::sched_rar_grant_t> grants);
srsran::byte_buffer_t* assemble_rar(srsran::const_span<sched_nr_interface::sched_rar_grant_t> grants);
srsran::unique_byte_buffer_t rar_pdu_buffer = nullptr;
// Interaction with other components
@ -112,10 +111,10 @@ private:
std::atomic<bool> started = {false};
const static uint32_t NUMEROLOGY_IDX = 0; /// only 15kHz supported at this stage
srsran::slot_point pdsch_slot, pusch_slot;
srsenb::sched_nr sched;
std::vector<sched_nr_interface::cell_cfg_t> cell_config;
const static uint32_t NUMEROLOGY_IDX = 0; /// only 15kHz supported at this stage
srsran::slot_point pdsch_slot, pusch_slot;
srsenb::sched_nr sched;
std::vector<sched_nr_interface::cell_cfg_t> cell_config;
// Map of active UEs
pthread_rwlock_t rwlock = {};

@ -45,9 +45,9 @@ class ul_sched_result_buffer;
class sched_nr final : public sched_nr_interface
{
public:
explicit sched_nr(const sched_cfg_t& sched_cfg);
explicit sched_nr();
~sched_nr() override;
int cell_cfg(srsran::const_span<cell_cfg_t> cell_list) override;
int config(const sched_cfg_t& sched_cfg, srsran::const_span<cell_cfg_t> cell_list) override;
void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override;
void ue_rem(uint16_t rnti) override;
bool ue_exists(uint16_t rnti) override;
@ -56,7 +56,7 @@ public:
void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override;
void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) override;
void ul_sr_info(slot_point slot_rx, uint16_t rnti) override;
void ul_sr_info(uint16_t rnti) override;
void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) override;
void dl_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t newtx, uint32_t retx);
@ -68,7 +68,7 @@ private:
// args
sched_nr_impl::sched_params cfg;
srslog::basic_logger& logger;
srslog::basic_logger* logger = nullptr;
using sched_worker_manager = sched_nr_impl::sched_worker_manager;
std::unique_ptr<sched_worker_manager> sched_workers;

@ -39,12 +39,16 @@ const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS;
using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t;
using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t;
using pdsch_t = mac_interface_phy_nr::pdsch_t;
using pusch_t = mac_interface_phy_nr::pusch_t;
using pucch_t = mac_interface_phy_nr::pucch_t;
using pdcch_dl_list_t = srsran::bounded_vector<pdcch_dl_t, MAX_GRANTS>;
using pdcch_ul_list_t = srsran::bounded_vector<pdcch_ul_t, MAX_GRANTS>;
using pucch_t = mac_interface_phy_nr::pucch_t;
using pucch_list_t = srsran::bounded_vector<pucch_t, MAX_GRANTS>;
using pusch_t = mac_interface_phy_nr::pusch_t;
using pusch_list_t = srsran::bounded_vector<pusch_t, MAX_GRANTS>;
using nzp_csi_rs_list = srsran::bounded_vector<srsran_csi_rs_nzp_resource_t, mac_interface_phy_nr::MAX_NZP_CSI_RS>;
using ssb_t = mac_interface_phy_nr::ssb_t;
using ssb_list = srsran::bounded_vector<ssb_t, mac_interface_phy_nr::MAX_SSB>;
using sched_cfg_t = sched_nr_interface::sched_cfg_t;
using cell_cfg_t = sched_nr_interface::cell_cfg_t;
@ -102,9 +106,10 @@ struct sched_cell_params {
};
struct sched_params {
const sched_cfg_t sched_cfg;
sched_cfg_t sched_cfg;
std::vector<sched_cell_params> cells;
sched_params() = default;
explicit sched_params(const sched_cfg_t& sched_cfg_);
};

@ -32,6 +32,7 @@
namespace srsenb {
namespace sched_nr_impl {
// typedefs
using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -39,9 +40,9 @@ using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t;
const static size_t MAX_CORESET_PER_BWP = 3;
using slot_coreset_list = std::array<srsran::optional<coreset_region>, MAX_CORESET_PER_BWP>;
using pdsch_t = mac_interface_phy_nr::pdsch_t;
using pdsch_list_t = srsran::bounded_vector<pdsch_t, MAX_GRANTS>;
using sched_rar_list_t = sched_nr_interface::sched_rar_list_t;
using pucch_list_t = srsran::bounded_vector<pucch_t, MAX_GRANTS>;
struct harq_ack_t {
const srsran::phy_cfg_nr_t* phy_cfg;
@ -55,9 +56,12 @@ struct bwp_slot_grid {
bwp_rb_bitmap dl_prbs;
bwp_rb_bitmap ul_prbs;
ssb_list ssb;
nzp_csi_rs_list nzp_csi_rs;
pdcch_dl_list_t dl_pdcchs;
pdcch_ul_list_t ul_pdcchs;
pdsch_list_t pdschs;
pucch_list_t pucch;
sched_rar_list_t rar;
slot_coreset_list coresets;
pusch_list_t puschs;

@ -52,6 +52,12 @@ void fill_ul_dci_ue_fields(const slot_ue& ue,
srsran_dci_location_t dci_pos,
srsran_dci_ul_nr_t& dci);
/// Log UE state for slot being scheduled
void log_sched_slot_ues(srslog::basic_logger& logger,
slot_point pdcch_slot,
uint32_t cc,
const slot_ue_map_t& slot_ues);
/// Log Scheduling Result for a given BWP and slot
void log_sched_bwp_result(srslog::basic_logger& logger,
slot_point pdcch_slot,

@ -39,6 +39,7 @@ const static size_t SCHED_NR_MAX_NOF_RBGS = 18;
const static size_t SCHED_NR_MAX_TB = 1;
const static size_t SCHED_NR_MAX_HARQ = 16;
const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2;
const static size_t SCHED_NR_MAX_LCID = 32;
class sched_nr_interface
{
@ -78,7 +79,7 @@ public:
bool pdsch_enabled = true;
bool pusch_enabled = true;
bool auto_refill_buffer = false;
std::string logger_name = "MAC";
std::string logger_name = "MAC-NR";
};
struct ue_cc_cfg_t {
@ -91,7 +92,8 @@ public:
int fixed_dl_mcs = -1;
int fixed_ul_mcs = -1;
srsran::bounded_vector<ue_cc_cfg_t, SCHED_NR_MAX_CARRIERS> carriers;
srsran::phy_cfg_nr_t phy_cfg = {};
std::array<mac_lc_ch_cfg_t, SCHED_NR_MAX_LCID> ue_bearers = {};
srsran::phy_cfg_nr_t phy_cfg = {};
};
////// RACH //////
@ -124,17 +126,17 @@ public:
dl_sched_t dl_sched;
};
virtual ~sched_nr_interface() = default;
virtual int cell_cfg(srsran::const_span<sched_nr_interface::cell_cfg_t> ue_cfg) = 0;
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
virtual void ue_rem(uint16_t rnti) = 0;
virtual bool ue_exists(uint16_t rnti) = 0;
virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_res_t& result) = 0;
virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0;
virtual ~sched_nr_interface() = default;
virtual int config(const sched_cfg_t& sched_cfg, srsran::const_span<sched_nr_interface::cell_cfg_t> ue_cfg) = 0;
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
virtual void ue_rem(uint16_t rnti) = 0;
virtual bool ue_exists(uint16_t rnti) = 0;
virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_res_t& result) = 0;
virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0;
virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0;
virtual void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) = 0;
virtual void ul_sr_info(slot_point, uint16_t rnti) = 0;
virtual void ul_sr_info(uint16_t rnti) = 0;
virtual void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) = 0;
};

@ -0,0 +1,36 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_NR_SIGNALLING_H
#define SRSRAN_SCHED_NR_SIGNALLING_H
#include "sched_nr_cfg.h"
#include "sched_nr_interface.h"
namespace srsenb {
namespace sched_nr_impl {
/// Schedule NZP-CSI-RS resources for given slot
void sched_nzp_csi_rs(srsran::const_span<srsran_csi_rs_nzp_set_t> nzp_csi_rs_sets,
const srsran_slot_cfg_t& slot_cfg,
nzp_csi_rs_list& csi_rs_list);
/// For a given BWP and slot, schedule SSB, NZP CSI RS and SIBs
void sched_dl_signalling(const bwp_params& bwp_params,
slot_point sl_pdcch,
ssb_list& ssb_list,
nzp_csi_rs_list& nzp_csi_rs);
} // namespace sched_nr_impl
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_SIGNALLING_H

@ -54,16 +54,17 @@ public:
int dl_pending_bytes = 0, ul_pending_bytes = 0;
// UE parameters that are sector specific
const bwp_ue_cfg* cfg = nullptr;
harq_entity* harq_ent = nullptr;
slot_point pdcch_slot;
slot_point pdsch_slot;
slot_point pusch_slot;
slot_point uci_slot;
uint32_t dl_cqi = 0;
uint32_t ul_cqi = 0;
dl_harq_proc* h_dl = nullptr;
ul_harq_proc* h_ul = nullptr;
const bwp_ue_cfg* cfg = nullptr;
harq_entity* harq_ent = nullptr;
slot_point pdcch_slot;
slot_point pdsch_slot;
slot_point pusch_slot;
slot_point uci_slot;
uint32_t dl_cqi = 0;
uint32_t ul_cqi = 0;
dl_harq_proc* h_dl = nullptr;
ul_harq_proc* h_ul = nullptr;
srsran_uci_cfg_nr_t uci_cfg = {};
};
class ue_carrier
@ -100,7 +101,7 @@ public:
void rlc_buffer_state(uint32_t lcid, uint32_t newtx, uint32_t retx) { buffers.dl_buffer_state(lcid, newtx, retx); }
void ul_bsr(uint32_t lcg, uint32_t bsr_val) { buffers.ul_bsr(lcg, bsr_val); }
void ul_sr_info(slot_point slot_rx) { last_sr_slot = slot_rx; }
void ul_sr_info() { last_sr_slot = last_pdcch_slot - TX_ENB_DELAY; }
bool has_ca() const
{
@ -117,6 +118,7 @@ private:
const uint16_t rnti;
const sched_params& sched_cfg;
slot_point last_pdcch_slot;
slot_point last_sr_slot;
int ul_pending_bytes = 0, dl_pending_bytes = 0;

@ -61,6 +61,7 @@ private:
void alloc_dl_ues();
void alloc_ul_ues();
void postprocess_decisions();
const sched_cell_params& cfg;
serv_cell_manager& cell;

@ -71,7 +71,8 @@ public:
float target_bler = 0.05;
float max_delta_dl_cqi = 5;
float max_delta_ul_snr = 5;
float adaptive_link_step_size = 0.001;
float adaptive_dl_mcs_step_size = 0.001;
float adaptive_ul_mcs_step_size = 0.001;
uint32_t min_tpc_tti_interval = 1;
float ul_snr_avg_alpha = 0.05;
int init_ul_snr_value = 5;

@ -103,7 +103,8 @@ private:
cc_st cc_state_ = cc_st::idle;
// CQI
float delta_inc = 0, delta_dec = 0;
float ul_delta_inc = 0, ul_delta_dec = 0;
float dl_delta_inc = 0, dl_delta_dec = 0;
float dl_cqi_coeff = 0, ul_snr_coeff = 0;
float max_cqi_coeff = -5, max_snr_coeff = 5;

@ -37,6 +37,7 @@
#include "srsran/common/threads.h"
#include "srsran/interfaces/gnb_ngap_interfaces.h"
#include "srsran/interfaces/gnb_rrc_nr_interfaces.h"
#include "srsran/interfaces/enb_gtpu_interfaces.h"
#include "srsran/srslog/srslog.h"
#include <iostream>
#include <unordered_map>
@ -51,7 +52,7 @@ public:
srslog::basic_logger& logger,
srsran::socket_manager_itf* rx_socket_handler);
~ngap();
int init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_);
int init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_, gtpu_interface_rrc* gtpu_);
void stop();
// RRC NR interface
@ -93,6 +94,7 @@ private:
// args
rrc_interface_ngap_nr* rrc = nullptr;
gtpu_interface_rrc* gtpu = nullptr;
ngap_args_t args = {};
srslog::basic_logger& logger;
srsran::task_sched_handle task_sched;
@ -134,7 +136,7 @@ private:
// TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request
bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg);
// TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request
bool handle_pdu_session_resource_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg);
bool handle_ue_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg);
class user_list
{

@ -22,11 +22,17 @@
#ifndef SRSENB_NGAP_INTERFACES_H
#define SRSENB_NGAP_INTERFACES_H
#include "srsran/asn1/ngap_utils.h"
namespace srsenb {
class ngap_interface_ngap_proc
{
public:
virtual bool send_initial_ctxt_setup_response() = 0;
virtual bool
send_pdu_session_resource_setup_response(uint16_t pdu_session_id,
uint32_t teid_out,
asn1::bounded_bitstring<1, 160, true, true> transport_layer_address) = 0;
};
} // namespace srsenb

@ -22,16 +22,21 @@
#define SRSENB_NGAP_UE_H
#include "ngap.h"
#include "ngap_ue_bearer_manager.h"
#include "ngap_ue_proc.h"
#include "ngap_ue_utils.h"
#include "srsran/asn1/asn1_utils.h"
#include "srsran/asn1/ngap.h"
#include "srsran/interfaces/enb_gtpu_interfaces.h"
namespace srsenb {
class ngap::ue : public ngap_interface_ngap_proc
{
public:
explicit ue(ngap* ngap_ptr_, rrc_interface_ngap_nr* rrc_ptr_, srslog::basic_logger& logger_);
explicit ue(ngap* ngap_ptr_,
rrc_interface_ngap_nr* rrc_ptr_,
gtpu_interface_rrc* gtpu_ptr_,
srslog::basic_logger& logger_);
virtual ~ue();
// TS 38.413 - Section 9.2.5.1 - Initial UE Message
bool send_initial_ue_message(asn1::ngap_nr::rrcestablishment_cause_e cause,
@ -44,31 +49,39 @@ public:
bool send_initial_ctxt_setup_response();
// TS 38.413 - Section 9.2.2.3 - Initial Context Setup Failure
bool send_initial_ctxt_setup_failure(asn1::ngap_nr::cause_c cause);
// TS 38.413 - Section 9.2.1.2 - PDU Session Resource Setup Response
bool send_pdu_session_resource_setup_response(uint16_t pdu_session_id,
uint32_t teid_in,
asn1::bounded_bitstring<1, 160, true, true> addr_in);
// TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request
bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg);
// TS 38.413 - Section 9.2.2.5 - UE Context Release Command
bool handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg);
// TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request
bool handle_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg);
bool was_uectxtrelease_requested() const { return release_requested; }
void ue_ctxt_setup_complete();
void notify_rrc_reconf_complete(const bool reconf_complete_outcome);
srsran::proc_t<ngap_ue_initial_context_setup_proc> initial_context_setup_proc;
srsran::proc_t<ngap_ue_ue_context_release_proc> ue_context_release_proc;
ngap_ue_ctxt_t ctxt = {};
uint16_t stream_id = 1;
private:
// args
ngap* ngap_ptr;
rrc_interface_ngap_nr* rrc_ptr;
ngap* ngap_ptr = nullptr;
// state
bool release_requested = false;
bool release_requested = false;
ngap_ue_bearer_manager bearer_manager;
// logger
srslog::basic_logger& logger;
// procedures
srsran::proc_t<ngap_ue_initial_context_setup_proc> initial_context_setup_proc;
srsran::proc_t<ngap_ue_ue_context_release_proc> ue_context_release_proc;
srsran::proc_t<ngap_ue_pdu_session_res_setup_proc> ue_pdu_session_res_setup_proc;
};
} // namespace srsenb

@ -0,0 +1,73 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSENB_NGAP_UE_BEARER_MANAGER_H
#define SRSENB_NGAP_UE_BEARER_MANAGER_H
#include "srsran/asn1/asn1_utils.h"
#include "srsran/asn1/ngap.h"
#include "srsran/config.h"
#include "srsran/interfaces/enb_gtpu_interfaces.h"
#include "srsran/interfaces/gnb_rrc_nr_interfaces.h"
namespace srsenb {
/**
* @brief Manages the GTPU bearers as part of the NGAP session procedures
* */
class ngap_ue_bearer_manager
{
public:
struct pdu_session_t {
struct gtpu_tunnel {
uint32_t teid_out = 0;
uint32_t teid_in = 0;
asn1::bounded_bitstring<1, 160, true, true> address_out;
asn1::bounded_bitstring<1, 160, true, true> address_in;
};
uint8_t id = 0;
uint8_t lcid = 0;
asn1::ngap_nr::qos_flow_level_qos_params_s qos_params;
std::vector<gtpu_tunnel> tunnels;
};
ngap_ue_bearer_manager(rrc_interface_ngap_nr* rrc_, gtpu_interface_rrc* gtpu_, srslog::basic_logger& logger_);
~ngap_ue_bearer_manager();
int add_pdu_session(uint16_t rnti,
uint8_t pdu_session_id,
const asn1::ngap_nr::qos_flow_level_qos_params_s& qos,
const asn1::bounded_bitstring<1, 160, true, true>& addr,
uint32_t teid_out,
uint16_t& lcid,
asn1::bounded_bitstring<1, 160, true, true>& addr_in,
uint32_t& teid_in,
asn1::ngap_nr::cause_c& cause);
private:
gtpu_interface_rrc* gtpu = nullptr;
rrc_interface_ngap_nr* rrc = nullptr;
std::map<uint8_t, pdu_session_t> pdu_session_list;
srslog::basic_logger& logger;
int add_gtpu_bearer(uint16_t rnti,
uint32_t lcid,
uint32_t pdu_session_id,
uint32_t teid_out,
asn1::bounded_bitstring<1, 160, true, true> address,
pdu_session_t::gtpu_tunnel& tunnel, // out parameter
const gtpu_interface_rrc::bearer_props* props = nullptr);
void rem_gtpu_bearer(uint16_t rnti, uint32_t pdu_session_id);
};
} // namespace srsenb
#endif // SRSENB_NGAP_UE_BEARER_MANAGER_H

@ -30,6 +30,7 @@
#include "srsran/common/buffer_pool.h"
#include "srsran/common/stack_procedure.h"
#include "srsran/interfaces/gnb_rrc_nr_interfaces.h"
#include "srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h"
#include <map>
#include <string>
@ -44,9 +45,10 @@ class ngap_ue_initial_context_setup_proc
public:
explicit ngap_ue_initial_context_setup_proc(ngap_interface_ngap_proc* parent_,
rrc_interface_ngap_nr* rrc_,
ngap_ue_ctxt_t* ue_ctxt);
ngap_ue_ctxt_t* ue_ctxt,
srslog::basic_logger& logger_);
srsran::proc_outcome_t init(const asn1::ngap_nr::init_context_setup_request_s& msg);
srsran::proc_outcome_t react(const bool security_mode_command_outcome);
srsran::proc_outcome_t react(const bool rrc_reconf_outcome);
srsran::proc_outcome_t step();
static const char* name() { return "Initial Context Setup"; }
@ -63,7 +65,8 @@ class ngap_ue_ue_context_release_proc
public:
explicit ngap_ue_ue_context_release_proc(ngap_interface_ngap_proc* parent_,
rrc_interface_ngap_nr* rrc_,
ngap_ue_ctxt_t* ue_ctxt);
ngap_ue_ctxt_t* ue_ctxt,
srslog::basic_logger& logger_);
srsran::proc_outcome_t init(const asn1::ngap_nr::ue_context_release_cmd_s& msg);
srsran::proc_outcome_t step();
static const char* name() { return "UE Context Release"; }
@ -79,7 +82,7 @@ private:
class ngap_ue_ue_context_modification_proc
{
public:
explicit ngap_ue_ue_context_modification_proc(ngap_interface_ngap_proc* parent_);
explicit ngap_ue_ue_context_modification_proc(ngap_interface_ngap_proc* parent_, srslog::basic_logger& logger_);
srsran::proc_outcome_t init();
srsran::proc_outcome_t step();
static const char* name() { return "UE Context Modification"; }
@ -88,6 +91,26 @@ private:
ngap_interface_ngap_proc* parent;
};
class ngap_ue_pdu_session_res_setup_proc
{
public:
explicit ngap_ue_pdu_session_res_setup_proc(ngap_interface_ngap_proc* parent_,
rrc_interface_ngap_nr* rrc_,
ngap_ue_ctxt_t* ue_ctxt,
ngap_ue_bearer_manager* bearer_manager,
srslog::basic_logger& logger_);
srsran::proc_outcome_t init(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg);
srsran::proc_outcome_t step();
static const char* name() { return "UE PDU Session Resource Setup"; }
private:
ngap_ue_ctxt_t* ue_ctxt;
ngap_interface_ngap_proc* parent;
ngap_ue_bearer_manager* bearer_manager;
rrc_interface_ngap_nr* rrc = nullptr;
srslog::basic_logger& logger;
};
} // namespace srsenb
#endif

@ -136,8 +136,9 @@ public:
const enb_cell_common_list& enb_common_list);
~ue_cell_ded_list();
ue_cell_ded* add_cell(uint32_t enb_cc_idx);
ue_cell_ded* add_cell(uint32_t enb_cc_idx, bool init_pucch = true);
bool rem_last_cell();
bool init_pucch_pcell();
bool set_cells(const std::vector<uint32_t>& enb_cc_idxs);
ue_cell_ded* get_ue_cc_idx(uint32_t ue_cc_idx) { return (ue_cc_idx < nof_cells()) ? &cell_list[ue_cc_idx] : nullptr; }

@ -73,12 +73,12 @@ struct rrc_cfg_t {
bool meas_cfg_present = false;
srsran_cell_t cell;
cell_list_t cell_list;
cell_list_t cell_list_nr;
uint32_t max_mac_dl_kos;
uint32_t max_mac_ul_kos;
uint32_t rlf_release_timer_ms;
srb_cfg_t srb1_cfg;
srb_cfg_t srb2_cfg;
uint32_t num_nr_cells = 0; /// number of configured NR cells (used to configure RF)
uint32_t max_mac_dl_kos;
uint32_t max_mac_ul_kos;
uint32_t rlf_release_timer_ms;
srb_cfg_t srb1_cfg;
srb_cfg_t srb2_cfg;
};
constexpr uint32_t UE_PCELL_CC_IDX = 0;

@ -23,6 +23,7 @@
#define SRSRAN_RRC_CONFIG_NR_H
#include "srsran/asn1/rrc_nr.h"
#include "srsran/interfaces/gnb_rrc_nr_interfaces.h"
#include "srsue/hdr/phy/phy_common.h"
namespace srsenb {
@ -43,7 +44,7 @@ struct rrc_nr_cfg_t {
uint32_t nof_sibs;
rrc_nr_cfg_sr_t sr_cfg;
rrc_cfg_cqi_t cqi_cfg;
srsran_cell_t cell;
rrc_cell_list_nr_t cell_list;
std::string log_level;
uint32_t log_hex_limit;

@ -57,7 +57,16 @@ public:
uint16_t nr_rnti; /// RNTI assigned to UE on NR carrier
};
rrc_endc(srsenb::rrc::ue* outer_ue);
// Parameter of the (NR)-carrier required for NR cell measurement handling
struct rrc_endc_cfg_t {
bool act_from_b1_event = true; // ENDC will only be activated from B1 measurment
uint32_t nr_dl_arfcn = 634176;
uint32_t nr_band = 78;
asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_e_ ssb_ssc =
asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_opts::khz15;
};
rrc_endc(srsenb::rrc::ue* outer_ue, const rrc_endc_cfg_t& endc_cfg_);
bool fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg);
void handle_eutra_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps);
@ -66,8 +75,8 @@ public:
bool is_endc_supported();
private:
// Send SgNB addition request to gNB
bool start_sgnb_addition();
// Send SgNB addition request to gNB (either triggered through MeasReport or upon start)
void start_sgnb_addition();
bool is_endc_activation_running() const { return not is_in_state<endc_deactivated_st>(); }
@ -77,6 +86,7 @@ private:
// vars
bool endc_supported = false;
rrc_endc_cfg_t endc_cfg = {};
asn1::rrc::rrc_conn_recfg_complete_s pending_recfg_complete;
// fixed ENDC variables

@ -71,14 +71,18 @@ public:
void get_metrics(srsenb::rrc_metrics_t& m);
rrc_nr_cfg_t update_default_cfg(const rrc_nr_cfg_t& rrc_cfg);
int add_user(uint16_t rnti);
int update_user(uint16_t new_rnti, uint16_t old_rnti);
void config_phy();
void config_mac();
int32_t generate_sibs();
int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) final;
int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) final;
/// User manegement
int add_user(uint16_t rnti);
void rem_user(uint16_t rnti);
int update_user(uint16_t new_rnti, uint16_t old_rnti);
void set_activity_user(uint16_t rnti);
// RLC interface
// TODO
void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) {}
@ -99,7 +103,10 @@ public:
int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates);
int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps);
int start_security_mode_procedure(uint16_t rnti);
int establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid);
void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu);
int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates);
int allocate_lcid(uint16_t rnti);
class ue
{
@ -117,6 +124,7 @@ public:
bool is_idle() { return state == rrc_nr_state_t::RRC_IDLE; }
bool is_inactive() { return state == rrc_nr_state_t::RRC_INACTIVE; }
bool is_endc() { return endc; }
uint16_t get_eutra_rnti() { return eutra_rnti; }
// setters
@ -142,6 +150,9 @@ public:
asn1::rrc_nr::cell_group_cfg_s cell_group_cfg;
asn1::rrc_nr::radio_bearer_cfg_s radio_bearer_cfg;
// MAC controller
sched_nr_interface::ue_cfg_t uecfg{};
const uint32_t drb1_lcid = 4;
// NSA specific variables
@ -150,7 +161,8 @@ public:
};
private:
rrc_nr_cfg_t cfg = {};
static constexpr uint32_t UE_PSCELL_CC_IDX = 0; // first NR cell is always Primary Secondary Cell for UE
rrc_nr_cfg_t cfg = {};
// interfaces
phy_interface_stack_nr* phy = nullptr;

@ -60,6 +60,9 @@ public:
void protocol_failure();
void deactivate_bearers() { mac_ctrl.set_radio_bearer_state(mac_lc_ch_cfg_t::IDLE); }
// Init PUCCH resources for PCell
bool init_pucch();
rrc_state_t get_state();
void get_metrics(rrc_ue_metrics_t& ue_metrics) const;

@ -54,18 +54,18 @@ class bearer_cfg_handler;
struct ue_var_cfg_t;
/// Fill RadioResourceConfigDedicated with data known at the RRCSetup/Reestablishment stage
void fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg,
const rrc_cfg_t& enb_cfg,
const ue_cell_ded_list& ue_cell_list);
int fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg,
const rrc_cfg_t& enb_cfg,
const ue_cell_ded_list& ue_cell_list);
/// Apply Reconf updates and update current state
void apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8,
ue_var_cfg_t& current_ue_cfg,
const rrc_cfg_t& enb_cfg,
const ue_cell_ded_list& ue_cell_list,
bearer_cfg_handler& bearers,
const srsran::rrc_ue_capabilities_t& ue_caps,
bool phy_cfg_updated);
int apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8,
ue_var_cfg_t& current_ue_cfg,
const rrc_cfg_t& enb_cfg,
const ue_cell_ded_list& ue_cell_list,
bearer_cfg_handler& bearers,
const srsran::rrc_ue_capabilities_t& ue_caps,
bool phy_cfg_updated);
/// Apply radioResourceConfigDedicated updates to the current UE RRC configuration
void apply_rr_cfg_ded_diff(asn1::rrc::rr_cfg_ded_s& current_rr_cfg_ded,

@ -154,6 +154,7 @@ public:
uint32_t eps_bearer_id,
uint32_t addr,
uint32_t teid_out,
uint32_t& addr_in,
const bearer_props* props = nullptr) override;
void set_tunnel_status(uint32_t teidin, bool dl_active) override;
void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) override;

@ -53,6 +53,7 @@ public:
void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {}
// pdcp_interface_rrc
void set_enabled(uint16_t rnti, uint32_t lcid, bool enabled) override;
void reset(uint16_t rnti) override;
void add_user(uint16_t rnti) override;
void rem_user(uint16_t rnti) override;

@ -1,126 +0,0 @@
/**
* Copyright 2013-2021 Software Radio Systems Limited
*
* This file is part of srsRAN.
*
* srsRAN is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsRAN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsran/interfaces/gnb_interfaces.h"
#include "srsran/interfaces/ue_gw_interfaces.h"
#include "srsran/interfaces/ue_rlc_interfaces.h"
#include "srsran/upper/pdcp.h"
#include <map>
#ifndef SRSENB_PDCP_NR_H
#define SRSENB_PDCP_NR_H
namespace srsenb {
struct pdcp_nr_args_t {
std::string log_level;
uint32_t log_hex_limit;
};
class pdcp_nr : public pdcp_interface_rlc_nr, public pdcp_interface_sdap_nr, public pdcp_interface_rrc_nr
{
public:
explicit pdcp_nr(srsran::task_sched_handle task_sched_, const char* logname);
virtual ~pdcp_nr() = default;
void init(const pdcp_nr_args_t& args_,
rlc_interface_pdcp_nr* rlc_,
rrc_interface_pdcp_nr* rrc_,
sdap_interface_pdcp_nr* gtpu_);
void stop();
// pdcp_interface_rlc_nr
void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu);
void notify_delivery(uint16_t rnti, uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn);
void notify_failure(uint16_t rnti, uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn);
void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {}
// pdcp_interface_rrc_nr
void reset(uint16_t rnti) final;
void add_user(uint16_t rnti) final;
void rem_user(uint16_t rnti) final;
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) final;
void add_bearer(uint16_t rnti, uint32_t lcid, srsran::pdcp_config_t cnfg) final;
void config_security(uint16_t rnti, uint32_t lcid, srsran::as_security_config_t sec_cfg) final;
void enable_integrity(uint16_t rnti, uint32_t lcid) final;
void enable_encryption(uint16_t rnti, uint32_t lcid) final;
private:
class user_interface_rlc final : public srsue::rlc_interface_pdcp
{
public:
uint16_t rnti;
srsenb::rlc_interface_pdcp_nr* rlc;
// rlc_interface_pdcp_nr
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) final;
void discard_sdu(uint32_t lcid, uint32_t discard_sn) final;
bool rb_is_um(uint32_t lcid) final;
bool sdu_queue_is_full(uint32_t lcid) final;
};
class user_interface_sdap : public srsue::gw_interface_pdcp
{
public:
uint16_t rnti;
srsenb::sdap_interface_pdcp_nr* sdap;
// gw_interface_pdcp
void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final;
void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) final {}
};
class user_interface_rrc : public srsue::rrc_interface_pdcp
{
public:
uint16_t rnti;
srsenb::rrc_interface_pdcp_nr* rrc;
// rrc_interface_pdcp_nr
void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final;
void write_pdu_bcch_bch(srsran::unique_byte_buffer_t pdu) final;
void write_pdu_bcch_dlsch(srsran::unique_byte_buffer_t pdu) final;
void write_pdu_pcch(srsran::unique_byte_buffer_t pdu) final;
void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final {}
void notify_pdcp_integrity_error(uint32_t lcid) final {}
const char* get_rb_name(uint32_t lcid) final;
};
class user_interface
{
public:
user_interface_rlc rlc_itf;
user_interface_sdap sdap_itf;
user_interface_rrc rrc_itf;
std::unique_ptr<srsran::pdcp> pdcp;
};
// args
pdcp_nr_args_t m_args = {};
rlc_interface_pdcp_nr* m_rlc = nullptr;
rrc_interface_pdcp_nr* m_rrc = nullptr;
sdap_interface_pdcp_nr* m_sdap = nullptr;
std::map<uint32_t, user_interface> users;
srsran::task_sched_handle task_sched;
srslog::basic_logger& logger;
};
} // namespace srsenb
#endif // SRSENB_PDCP_NR_H

@ -1,104 +0,0 @@
/**
* Copyright 2013-2021 Software Radio Systems Limited
*
* This file is part of srsRAN.
*
* srsRAN is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsRAN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSENB_RLC_NR_H
#define SRSENB_RLC_NR_H
#include "srsran/interfaces/gnb_interfaces.h"
#include "srsran/interfaces/gnb_mac_interfaces.h"
#include "srsran/rlc/rlc.h"
#include <map>
namespace srsenb {
typedef struct {
uint32_t lcid;
uint32_t plmn;
uint16_t mtch_stop;
uint8_t* payload;
} mch_service_t;
class rlc_nr final : public rlc_interface_mac_nr, public rlc_interface_rrc_nr, public rlc_interface_pdcp_nr
{
public:
explicit rlc_nr(const char* logname);
void init(pdcp_interface_rlc_nr* pdcp_,
rrc_interface_rlc_nr* rrc_,
mac_interface_rlc_nr* mac_,
srsran::timer_handler* timers_);
void stop();
// rlc_interface_rrc_nr
void clear_buffer(uint16_t rnti);
void add_user(uint16_t rnti);
void rem_user(uint16_t rnti);
void add_bearer(uint16_t rnti, uint32_t lcid, srsran::rlc_config_t cnfg);
void add_bearer_mrb(uint16_t rnti, uint32_t lcid);
// rlc_interface_pdcp_nr
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu);
bool rb_is_um(uint16_t rnti, uint32_t lcid);
bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid);
const char* get_rb_name(uint32_t lcid);
// rlc_interface_mac_nr
int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);
// void read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload);
void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);
void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size);
private:
class user_interface : public srsue::pdcp_interface_rlc, public srsue::rrc_interface_rlc
{
public:
void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu);
void notify_delivery(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns);
void notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns);
void write_pdu_bcch_bch(srsran::unique_byte_buffer_t sdu);
void write_pdu_bcch_dlsch(srsran::unique_byte_buffer_t sdu);
void write_pdu_pcch(srsran::unique_byte_buffer_t sdu);
void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {}
void max_retx_attempted() final;
void protocol_failure() final;
const char* get_rb_name(uint32_t lcid) final;
uint16_t rnti;
srsenb::pdcp_interface_rlc_nr* m_pdcp = nullptr;
srsenb::rrc_interface_rlc_nr* m_rrc = nullptr;
std::unique_ptr<srsran::rlc> m_rlc;
rlc_nr* parent = nullptr;
};
// args
srsran::timer_handler* timers = nullptr;
mac_interface_rlc_nr* m_mac = nullptr;
pdcp_interface_rlc_nr* m_pdcp = nullptr;
rrc_interface_rlc_nr* m_rrc = nullptr;
srslog::basic_logger& logger;
// state
std::map<uint32_t, user_interface> users;
std::vector<mch_service_t> mch_services;
};
} // namespace srsenb
#endif // SRSENB_RLC_NR_H

@ -94,6 +94,14 @@ public:
eutra_stack->sgnb_addition_complete(eutra_rnti, nr_rnti);
}
void set_activity_user(uint16_t eutra_rnti)
{
if (eutra_stack == nullptr) {
return;
}
eutra_stack->set_activity_user(eutra_rnti);
}
// stack_nr_interface_stack_eutra
void tti_clock()
{
@ -119,6 +127,15 @@ public:
return nr_stack->get_buffered_pdus(rnti, lcid);
}
// gtpu_interface_pdcp
void write_pdu(uint16_t rnti, uint32_t bearer_id, srsran::unique_byte_buffer_t pdu)
{
if (eutra_stack == nullptr) {
return;
}
eutra_stack->write_pdu(rnti, bearer_id, std::move(pdu));
}
private:
enb_stack_lte* eutra_stack = nullptr;
gnb_stack_nr* nr_stack = nullptr;

@ -87,14 +87,25 @@ cell_list =
}
);
// ReportCfg (only A3 supported)
meas_report_desc = {
a3_report_type = "RSRP";
a3_offset = 6;
a3_hysteresis = 0;
a3_time_to_trigger = 480;
rsrq_config = 4;
};
// Select measurement report configuration (all reports are combined with all measurement objects)
meas_report_desc =
(
{
eventA = 3
a3_offset = 6;
hysteresis = 0;
time_to_trigger = 480;
trigger_quant = "RSRP";
max_report_cells = 1;
report_interv = 120;
report_amount = 1;
}
);
meas_quant_desc = {
// averaging filter coefficient
rsrq_config = 4;
rsrp_config = 4;
};
}
// Add here more cells
);

@ -52,7 +52,7 @@ int enb::init(const all_args_t& args_)
enb_log.info("%s", get_build_string().c_str());
// Validate arguments
if (parse_args(args_, rrc_cfg)) {
if (parse_args(args_, rrc_cfg, rrc_nr_cfg)) {
srsran::console("Error processing arguments.\n");
return SRSRAN_ERROR;
}
@ -72,7 +72,7 @@ int enb::init(const all_args_t& args_)
}
std::unique_ptr<gnb_stack_nr> tmp_nr_stack;
if (not rrc_cfg.cell_list_nr.empty()) {
if (not rrc_nr_cfg.cell_list.empty()) {
// add NR stack
tmp_nr_stack.reset(new gnb_stack_nr(log_sink));
if (tmp_nr_stack == nullptr) {
@ -157,6 +157,10 @@ void enb::stop()
{
if (started) {
// tear down in reverse order
if (radio) {
radio->stop();
}
if (phy) {
phy->stop();
}
@ -169,10 +173,6 @@ void enb::stop()
nr_stack->stop();
}
if (radio) {
radio->stop();
}
// Now that everything is teared down, log sector stop events.
const std::string& sib9_hnb_name =
rrc_cfg.sibs[8].sib9().hnb_name_present ? rrc_cfg.sibs[8].sib9().hnb_name.to_string() : "";
@ -184,11 +184,11 @@ void enb::stop()
}
}
int enb::parse_args(const all_args_t& args_, rrc_cfg_t& _rrc_cfg)
int enb::parse_args(const all_args_t& args_, rrc_cfg_t& rrc_cfg_, rrc_nr_cfg_t& rrc_cfg_nr_)
{
// set member variable
args = args_;
return enb_conf_sections::parse_cfg_files(&args, &_rrc_cfg, &phy_cfg);
return enb_conf_sections::parse_cfg_files(&args, &rrc_cfg_, &rrc_cfg_nr_, &phy_cfg);
}
void enb::start_plot()
@ -203,12 +203,15 @@ void enb::print_pool()
bool enb::get_metrics(enb_metrics_t* m)
{
if (!started) {
return false;
}
radio->get_metrics(&m->rf);
phy->get_metrics(m->phy);
if (eutra_stack) {
eutra_stack->get_metrics(&m->stack);
}
m->running = started;
m->running = true;
m->sys = sys_proc.get_metrics();
return true;
}
@ -240,6 +243,9 @@ std::string enb::get_build_string()
void enb::toggle_padding()
{
if (!started) {
return;
}
if (eutra_stack) {
eutra_stack->toggle_padding();
}
@ -247,6 +253,9 @@ void enb::toggle_padding()
void enb::tti_clock()
{
if (!started) {
return;
}
if (eutra_stack) {
eutra_stack->tti_clock();
}

@ -25,6 +25,7 @@
#include "srsran/common/band_helper.h"
#include "srsran/common/multiqueue.h"
#include "srsran/phy/common/phy_common.h"
#include "srsran/rrc/rrc_common.h"
#include <boost/algorithm/string.hpp>
#define HANDLEPARSERCODE(cond) \
@ -644,7 +645,7 @@ int field_qci::parse(libconfig::Setting& root)
namespace rr_sections {
int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_)
int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr_cfg_)
{
/* Transmission mode config section */
if (args_->enb.transmission_mode < 1 || args_->enb.transmission_mode > 4) {
@ -759,7 +760,7 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_)
bool nr_cell_cnfg_present = false;
parser::section nr_cell_cnfg("nr_cell_list");
nr_cell_cnfg.set_optional(&nr_cell_cnfg_present);
nr_cell_cnfg.add_field(new rr_sections::nr_cell_list_section(args_, rrc_cfg_));
nr_cell_cnfg.add_field(new rr_sections::nr_cell_list_section(args_, rrc_nr_cfg_, rrc_cfg_));
// Run parser with two sections
parser p(args_->enb_files.rr_config);
@ -787,30 +788,92 @@ static int parse_meas_cell_list(rrc_meas_cfg_t* meas_cfg, Setting& root)
return 0;
}
static int parse_meas_report_desc(rrc_meas_cfg_t* meas_cfg, Setting& root)
static int parse_meas_report_desc(rrc_meas_cfg_t* meas_cfg, Setting& cellroot)
{
// NOTE: For now, only support one meas_report for all cells.
// TODO: for a1
// TODO: for a2
// meas report parsing
meas_cfg->meas_reports.resize(1);
asn1::rrc::report_cfg_eutra_s& meas_item = meas_cfg->meas_reports[0];
HANDLEPARSERCODE(asn1_parsers::str_to_enum(meas_item.trigger_quant, root["a3_report_type"]));
auto& event = meas_item.trigger_type.set_event();
event.event_id.set_event_a3().report_on_leave = false;
event.event_id.event_a3().a3_offset = (int)root["a3_offset"];
event.hysteresis = (int)root["a3_hysteresis"];
meas_item.max_report_cells = 1; // TODO: parse
meas_item.report_amount.value = report_cfg_eutra_s::report_amount_e_::r1; // TODO: parse
meas_item.report_interv.value = report_interv_e::ms120; // TODO: parse
meas_item.report_quant.value = report_cfg_eutra_s::report_quant_opts::both; // TODO: parse
// NOTE: Events A1, A2, A3 and A4 are supported. A3 and A4 will be configured for all neighbour cells
Setting& root = cellroot["meas_report_desc"];
meas_cfg->meas_reports.resize(root.getLength());
for (int i = 0; i < root.getLength(); i++) {
asn1::rrc::report_cfg_eutra_s& meas_item = meas_cfg->meas_reports[i];
// Parse trigger quantity before event
HANDLEPARSERCODE(asn1_parsers::str_to_enum(meas_item.trigger_quant, root[i]["trigger_quant"]));
auto& event = meas_item.trigger_type.set_event();
// Configure event
switch ((int)root[i]["eventA"]) {
case 1:
if (!root[i].exists("a1_thresh")) {
ERROR("Missing a1_thresh field for A1 event\n");
return SRSRAN_ERROR;
}
if (meas_item.trigger_quant == report_cfg_eutra_s::trigger_quant_opts::rsrp) {
event.event_id.set_event_a1().a1_thres.set_thres_rsrp() =
rrc_value_to_range(srsran::quant_rsrp, (int)root[i]["a1_thresh"]);
} else {
event.event_id.set_event_a1().a1_thres.set_thres_rsrq() =
rrc_value_to_range(srsran::quant_rsrq, (int)root[i]["a1_thresh"]);
}
break;
case 2:
if (!root[i].exists("a2_thresh")) {
ERROR("Missing a2_thresh field for A2 event\n");
return SRSRAN_ERROR;
}
if (meas_item.trigger_quant == report_cfg_eutra_s::trigger_quant_opts::rsrp) {
event.event_id.set_event_a2().a2_thres.set_thres_rsrp() =
rrc_value_to_range(srsran::quant_rsrp, (int)root[i]["a2_thresh"]);
} else {
event.event_id.set_event_a2().a2_thres.set_thres_rsrq() =
rrc_value_to_range(srsran::quant_rsrq, (int)root[i]["a2_thresh"]);
}
break;
case 3:
if (!root[i].exists("a3_offset")) {
ERROR("Missing a3_offset field for A3 event\n");
return SRSRAN_ERROR;
}
event.event_id.set_event_a3().report_on_leave = false;
event.event_id.event_a3().a3_offset = (int)root[i]["a3_offset"];
break;
case 4:
if (!root[i].exists("a4_thresh")) {
ERROR("Missing a4_thresh field for A4 event\n");
return SRSRAN_ERROR;
}
if (meas_item.trigger_quant == report_cfg_eutra_s::trigger_quant_opts::rsrp) {
event.event_id.set_event_a4().a4_thres.set_thres_rsrp() =
rrc_value_to_range(srsran::quant_rsrp, (int)root[i]["a4_thresh"]);
} else {
event.event_id.set_event_a4().a4_thres.set_thres_rsrq() =
rrc_value_to_range(srsran::quant_rsrq, (int)root[i]["a4_thresh"]);
}
break;
default:
ERROR("Invalid or unsupported event A%d in meas_report_desc (only A1-A4 are supported)\n",
(int)root[i]["eventA"]);
return SRSRAN_ERROR;
}
// Configure common variables
event.hysteresis = (int)root[i]["hysteresis"];
HANDLEPARSERCODE(asn1_parsers::number_to_enum(event.time_to_trigger, root[i]["time_to_trigger"]));
meas_item.report_quant.value = report_cfg_eutra_s::report_quant_opts::both; // TODO: parse
meas_item.max_report_cells = (int)root[i]["max_report_cells"];
HANDLEPARSERCODE(asn1_parsers::number_to_enum(meas_item.report_interv, root[i]["report_interv"]));
HANDLEPARSERCODE(asn1_parsers::number_to_enum(meas_item.report_amount, root[i]["report_amount"]));
}
// quant coeff parsing
auto& quant = meas_cfg->quant_cfg;
HANDLEPARSERCODE(asn1_parsers::number_to_enum(event.time_to_trigger, root["a3_time_to_trigger"]));
HANDLEPARSERCODE(
asn1_parsers::opt_number_to_enum(quant.filt_coef_rsrp, quant.filt_coef_rsrp_present, root, "rsrp_config"));
HANDLEPARSERCODE(
asn1_parsers::opt_number_to_enum(quant.filt_coef_rsrq, quant.filt_coef_rsrq_present, root, "rsrq_config"));
HANDLEPARSERCODE(asn1_parsers::opt_number_to_enum(
quant.filt_coef_rsrp, quant.filt_coef_rsrp_present, cellroot["meas_quant_desc"], "rsrp_config"));
HANDLEPARSERCODE(asn1_parsers::opt_number_to_enum(
quant.filt_coef_rsrq, quant.filt_coef_rsrq_present, cellroot["meas_quant_desc"], "rsrq_config"));
return SRSRAN_SUCCESS;
}
@ -873,7 +936,7 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
ERROR("PARSER ERROR: \"ho_active\" is set to true, but field \"meas_report_desc\" doesn't exist.\n");
return SRSRAN_ERROR;
}
HANDLEPARSERCODE(parse_meas_report_desc(&cell_cfg.meas_cfg, cellroot["meas_report_desc"]));
HANDLEPARSERCODE(parse_meas_report_desc(&cell_cfg.meas_cfg, cellroot));
}
if (cellroot.exists("scell_list")) {
@ -903,46 +966,55 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
return SRSRAN_SUCCESS;
}
static int parse_nr_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
static int parse_nr_cell_list(all_args_t* args, rrc_nr_cfg_t* rrc_cfg_nr, rrc_cfg_t* rrc_cfg_eutra, Setting& root)
{
for (uint32_t n = 0; n < (uint32_t)root.getLength(); ++n) {
cell_cfg_t cell_cfg = {};
auto& cellroot = root[n];
rrc_cell_cfg_nr_t cell_cfg = {};
auto& cellroot = root[n];
parse_opt_field(cell_cfg.rf_port, cellroot, "rf_port");
HANDLEPARSERCODE(parse_required_field(cell_cfg.cell_id, cellroot, "cell_id"));
parse_opt_field(cell_cfg.phy_cell.rf_port, cellroot, "rf_port");
HANDLEPARSERCODE(parse_required_field(cell_cfg.phy_cell.carrier.pci, cellroot, "pci"));
HANDLEPARSERCODE(parse_required_field(cell_cfg.phy_cell.cell_id, cellroot, "cell_id"));
HANDLEPARSERCODE(parse_required_field(cell_cfg.phy_cell.root_seq_idx, cellroot, "root_seq_idx"));
HANDLEPARSERCODE(parse_required_field(cell_cfg.tac, cellroot, "tac"));
HANDLEPARSERCODE(parse_required_field(cell_cfg.pci, cellroot, "pci"));
cell_cfg.pci = cell_cfg.pci % SRSRAN_NOF_NID_NR;
HANDLEPARSERCODE(parse_required_field(cell_cfg.dl_earfcn, cellroot, "dl_arfcn"));
cell_cfg.phy_cell.carrier.pci = cell_cfg.phy_cell.carrier.pci % SRSRAN_NOF_NID_NR;
HANDLEPARSERCODE(parse_required_field(cell_cfg.dl_arfcn, cellroot, "dl_arfcn"));
parse_opt_field(cell_cfg.ul_arfcn, cellroot, "ul_arfcn");
// frequencies get derived from ARFCN
// Add further cell-specific parameters
// TODO: Add further cell-specific parameters
rrc_cfg->cell_list_nr.push_back(cell_cfg);
rrc_cfg_nr->cell_list.push_back(cell_cfg);
}
// Configuration check
for (auto it = rrc_cfg->cell_list_nr.begin(); it != rrc_cfg->cell_list_nr.end(); ++it) {
for (auto it = rrc_cfg_nr->cell_list.begin(); it != rrc_cfg_nr->cell_list.end(); ++it) {
// check against NR cells
for (auto it2 = it + 1; it2 != rrc_cfg->cell_list_nr.end(); it2++) {
for (auto it2 = it + 1; it2 != rrc_cfg_nr->cell_list.end(); it2++) {
// Check RF port is not repeated
if (it->rf_port == it2->rf_port) {
if (it->phy_cell.rf_port == it2->phy_cell.rf_port) {
ERROR("Repeated RF port for multiple cells");
return SRSRAN_ERROR;
}
// Check cell ID is not repeated
if (it->cell_id == it2->cell_id) {
// Check cell PCI not repeated
if (it->phy_cell.carrier.pci == it2->phy_cell.carrier.pci) {
ERROR("Repeated cell PCI");
return SRSRAN_ERROR;
}
// Check cell PCI and cell ID is not repeated
if (it->phy_cell.cell_id == it2->phy_cell.cell_id) {
ERROR("Repeated Cell identifier");
return SRSRAN_ERROR;
}
}
// also check RF port against EUTRA cells
for (auto it_eutra = rrc_cfg->cell_list.begin(); it_eutra != rrc_cfg->cell_list.end(); ++it_eutra) {
for (auto it_eutra = rrc_cfg_eutra->cell_list.begin(); it_eutra != rrc_cfg_eutra->cell_list.end(); ++it_eutra) {
// Check RF port is not repeated
if (it->rf_port == it_eutra->rf_port) {
if (it->phy_cell.rf_port == it_eutra->rf_port) {
ERROR("Repeated RF port for multiple cells");
return SRSRAN_ERROR;
}
@ -960,7 +1032,7 @@ int cell_list_section::parse(libconfig::Setting& root)
int nr_cell_list_section::parse(libconfig::Setting& root)
{
HANDLEPARSERCODE(parse_nr_cell_list(args, rrc_cfg, root));
HANDLEPARSERCODE(parse_nr_cell_list(args, nr_rrc_cfg, eutra_rrc_cfg, root));
return 0;
}
@ -999,7 +1071,7 @@ int parse_cell_cfg(all_args_t* args_, srsran_cell_t* cell)
return SRSRAN_SUCCESS;
}
int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_)
int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr_cfg_, phy_cfg_t* phy_cfg_)
{
// Parse config files
srsran_cell_t cell_common_cfg = {};
@ -1031,7 +1103,7 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_)
}
try {
if (rr_sections::parse_rr(args_, rrc_cfg_) != SRSRAN_SUCCESS) {
if (rr_sections::parse_rr(args_, rrc_cfg_, rrc_nr_cfg_) != SRSRAN_SUCCESS) {
fprintf(stderr, "Error parsing Radio Resources configuration\n");
return SRSRAN_ERROR;
}
@ -1057,7 +1129,22 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_)
}
// Set fields derived from others, and check for correctness of the parsed configuration
return enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, cell_common_cfg);
if (enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, cell_common_cfg) != SRSRAN_SUCCESS) {
fprintf(stderr, "Error deriving EUTRA cell parameters\n");
return SRSRAN_ERROR;
}
// do the same for NR
if (enb_conf_sections::set_derived_args_nr(args_, rrc_nr_cfg_, phy_cfg_) != SRSRAN_SUCCESS) {
fprintf(stderr, "Error deriving NR cell parameters\n");
return SRSRAN_ERROR;
}
// update number of NR cells
rrc_cfg_->num_nr_cells = rrc_nr_cfg_->cell_list.size();
args_->rf.nof_carriers = rrc_cfg_->cell_list.size() + rrc_nr_cfg_->cell_list.size();
return SRSRAN_SUCCESS;
}
int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, const srsran_cell_t& cell_cfg_)
@ -1164,59 +1251,6 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
phy_cfg_->phy_cell_cfg.push_back(phy_cell_cfg);
}
// Use helper class to derive NR carrier parameters
srsran::srsran_band_helper band_helper;
// Create NR dedicated cell configuration from RRC configuration
for (auto it = rrc_cfg_->cell_list_nr.begin(); it != rrc_cfg_->cell_list_nr.end(); ++it) {
auto& cfg = *it;
phy_cell_cfg_nr_t phy_cell_cfg = {};
phy_cell_cfg.carrier.max_mimo_layers = cell_cfg_.nof_ports;
switch (cell_cfg_.nof_prb) {
case 25:
phy_cell_cfg.carrier.nof_prb = 25;
break;
case 50:
phy_cell_cfg.carrier.nof_prb = 52;
break;
case 100:
phy_cell_cfg.carrier.nof_prb = 106;
break;
default:
ERROR("The only accepted number of PRB is: 25, 50, 100");
return SRSRAN_ERROR;
}
phy_cell_cfg.carrier.pci = cfg.pci;
phy_cell_cfg.cell_id = cfg.cell_id;
phy_cell_cfg.root_seq_idx = cfg.root_seq_idx;
phy_cell_cfg.rf_port = cfg.rf_port;
phy_cell_cfg.num_ra_preambles =
rrc_cfg_->sibs[1].sib2().rr_cfg_common.rach_cfg_common.preamb_info.nof_ra_preambs.to_number();
if (cfg.dl_freq_hz > 0) {
phy_cell_cfg.dl_freq_hz = cfg.dl_freq_hz;
} else {
phy_cell_cfg.dl_freq_hz = band_helper.nr_arfcn_to_freq(cfg.dl_earfcn);
}
if (cfg.ul_freq_hz > 0) {
phy_cell_cfg.ul_freq_hz = cfg.ul_freq_hz;
} else {
// auto-detect UL frequency
if (cfg.ul_earfcn == 0) {
// derive UL ARFCN from given DL ARFCN
cfg.ul_earfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_earfcn);
if (cfg.ul_earfcn == 0) {
ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_earfcn);
return SRSRAN_ERROR;
}
}
phy_cell_cfg.ul_freq_hz = band_helper.nr_arfcn_to_freq(cfg.ul_earfcn);
}
phy_cfg_->phy_cell_cfg_nr.push_back(phy_cell_cfg);
}
if (args_->enb.transmission_mode == 1) {
phy_cfg_->pdsch_cnfg.p_b = 0; // Default TM1
rrc_cfg_->sibs[1].sib2().rr_cfg_common.pdsch_cfg_common.p_b = 0;
@ -1327,7 +1361,6 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
}
// Patch certain args that are not exposed yet
args_->rf.nof_carriers = rrc_cfg_->cell_list.size() + rrc_cfg_->cell_list_nr.size();
args_->rf.nof_antennas = args_->enb.nof_ports;
// MAC needs to know the cell bandwidth to dimension softbuffers
@ -1353,6 +1386,75 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
return SRSRAN_SUCCESS;
}
/**
* @brief Set the derived args for the NR RRC and PHY config
*
* Mainly configures the RRC parameter based on the arguments and config files
* read. Since for NSA we are still using a commong PHY between EUTRA and NR
* the PHY configuration is also updated accordingly.
*
* @param args_
* @param nr_rrc_cfg
* @param phy_cfg_
* @return int
*/
int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_)
{
// Use helper class to derive NR carrier parameters
srsran::srsran_band_helper band_helper;
// Create NR dedicated cell configuration from RRC configuration
for (auto it = rrc_cfg_->cell_list.begin(); it != rrc_cfg_->cell_list.end(); ++it) {
auto& cfg = *it;
cfg.phy_cell.carrier.max_mimo_layers = args_->enb.nof_ports;
// NR cells have the same bandwidth as EUTRA cells, adjust PRB sizes
switch (args_->enb.n_prb) {
case 25:
cfg.phy_cell.carrier.nof_prb = 25;
break;
case 50:
cfg.phy_cell.carrier.nof_prb = 52;
break;
case 100:
cfg.phy_cell.carrier.nof_prb = 106;
break;
default:
ERROR("The only accepted number of PRB is: 25, 50, 100");
return SRSRAN_ERROR;
}
// phy_cell_cfg.root_seq_idx = cfg.root_seq_idx;
cfg.phy_cell.num_ra_preambles = 52; // FIXME: read from config
if (cfg.phy_cell.dl_freq_hz == 0) {
cfg.phy_cell.dl_freq_hz = band_helper.nr_arfcn_to_freq(cfg.dl_arfcn);
}
if (cfg.phy_cell.ul_freq_hz == 0) {
// auto-detect UL frequency
if (cfg.ul_arfcn == 0) {
// derive UL ARFCN from given DL ARFCN
cfg.ul_arfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_arfcn);
if (cfg.ul_arfcn == 0) {
ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_arfcn);
return SRSRAN_ERROR;
}
}
cfg.phy_cell.ul_freq_hz = band_helper.nr_arfcn_to_freq(cfg.ul_arfcn);
}
// band
cfg.band = band_helper.get_band_from_dl_arfcn(cfg.dl_arfcn);
// duplex mode
cfg.duplex_mode = band_helper.get_duplex_mode(cfg.band);
phy_cfg_->phy_cell_cfg_nr.push_back(cfg.phy_cell);
}
return SRSRAN_SUCCESS;
}
} // namespace enb_conf_sections
namespace sib_sections {

@ -19,8 +19,8 @@
*
*/
#ifndef ENB_CFG_PARSER_SIB1_H
#define ENB_CFG_PARSER_SIB1_H
#ifndef ENB_CFG_PARSER_H
#define ENB_CFG_PARSER_H
#include "srsenb/hdr/parser.h"
#include <iostream>
@ -31,6 +31,7 @@
#include <string>
#include "srsenb/hdr/stack/rrc/rrc.h"
#include "srsenb/hdr/stack/rrc/rrc_config_nr.h"
#include "srsran/asn1/asn1_utils.h"
namespace srsenb {
@ -46,8 +47,9 @@ bool sib_is_present(const asn1::rrc::sched_info_list_l& l, asn1::rrc::sib_type_e
namespace enb_conf_sections {
int parse_cell_cfg(all_args_t* args_, srsran_cell_t* cell);
int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_);
int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_cfg_nr_, phy_cfg_t* phy_cfg_);
int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, const srsran_cell_t& cell_cfg_);
int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_);
} // namespace enb_conf_sections
@ -94,15 +96,18 @@ private:
class nr_cell_list_section final : public parser::field_itf
{
public:
explicit nr_cell_list_section(all_args_t* all_args_, rrc_cfg_t* rrc_cfg_) : args(all_args_), rrc_cfg(rrc_cfg_) {}
explicit nr_cell_list_section(all_args_t* all_args_, rrc_nr_cfg_t* nr_rrc_cfg_, rrc_cfg_t* eutra_rrc_cfg_) :
args(all_args_), nr_rrc_cfg(nr_rrc_cfg_), eutra_rrc_cfg(eutra_rrc_cfg_)
{}
int parse(Setting& root) override;
const char* get_name() override { return "nr_cell_list"; }
private:
rrc_cfg_t* rrc_cfg;
all_args_t* args;
rrc_nr_cfg_t* nr_rrc_cfg;
rrc_cfg_t* eutra_rrc_cfg;
all_args_t* args;
};
} // namespace rr_sections
@ -582,4 +587,4 @@ private:
};
} // namespace srsenb
#endif
#endif // ENB_CFG_PARSER_H

@ -165,7 +165,8 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("scheduler.target_bler", bpo::value<float>(&args->stack.mac.sched.target_bler)->default_value(0.05), "Target BLER (in decimal) to achieve via adaptive link")
("scheduler.max_delta_dl_cqi", bpo::value<float>(&args->stack.mac.sched.max_delta_dl_cqi)->default_value(5.0), "Maximum shift in CQI for adaptive DL link")
("scheduler.max_delta_ul_snr", bpo::value<float>(&args->stack.mac.sched.max_delta_ul_snr)->default_value(5.0), "Maximum shift in UL SNR for adaptive UL link")
("scheduler.adaptive_link_step_size", bpo::value<float>(&args->stack.mac.sched.adaptive_link_step_size)->default_value(0.001), "Step size or learning rate used in adaptive link")
("scheduler.adaptive_dl_mcs_step_size", bpo::value<float>(&args->stack.mac.sched.adaptive_dl_mcs_step_size)->default_value(0.001), "Step size or learning rate used in adaptive DL MCS link")
("scheduler.adaptive_ul_mcs_step_size", bpo::value<float>(&args->stack.mac.sched.adaptive_ul_mcs_step_size)->default_value(0.001), "Step size or learning rate used in adaptive UL MCS link")
("scheduler.min_tpc_tti_interval", bpo::value<uint32_t>(&args->stack.mac.sched.min_tpc_tti_interval)->default_value(1), "Minimum TTI interval between positive or negative TPCs")
("scheduler.ul_snr_avg_alpha", bpo::value<float>(&args->stack.mac.sched.ul_snr_avg_alpha)->default_value(0.05), "Exponential Average alpha coefficient used in estimation of UL SNR")
("scheduler.init_ul_snr_value", bpo::value<int>(&args->stack.mac.sched.init_ul_snr_value)->default_value(5), "Initial UL SNR value used for computing MCS in the first UL grant")
@ -615,10 +616,9 @@ int main(int argc, char* argv[])
metrics_file.set_handle(enb.get());
}
srsenb::metrics_json json_metrics(json_channel);
srsenb::metrics_json json_metrics(json_channel, enb.get());
if (args.general.report_json_enable) {
metricshub.add_listener(&json_metrics);
json_metrics.set_handle(enb.get());
}
// create input thread

@ -24,11 +24,6 @@
using namespace srsenb;
void metrics_json::set_handle(enb_metrics_interface* enb_)
{
enb = enb_;
}
namespace {
/// Bearer container metrics.

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save