mirror of https://github.com/pvnis/srsRAN_4G.git
Merge branch 'next' into agpl_next
# Conflicts: # srsue/hdr/stack/bearer_manager.h # srsue/src/stack/bearer_manager.ccmaster
commit
de59c88954
@ -0,0 +1,100 @@
|
||||
/**
|
||||
*
|
||||
* \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_BEARER_MANAGER_H
|
||||
#define SRSRAN_BEARER_MANAGER_H
|
||||
|
||||
#include "srsran/common/common.h"
|
||||
#include "srsran/common/rwlock_guard.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace srsran {
|
||||
|
||||
/**
|
||||
* @brief Helper class to manage the mapping between EPS bearer and radio bearer
|
||||
*
|
||||
* The class maps EPS bearers that are known to NAS and GW (UE) or GTPU (eNB)
|
||||
* to radio bearer (RB) that are only known to RRC.
|
||||
* Since the lifetime of a EPS bearer is usually longer than the lifetime of a RB,
|
||||
* the GW/GTPU needs to query the Stack to check whether a
|
||||
* given EPS bearer is active, i.e. a DRB is established, or not.
|
||||
*
|
||||
* The class also maps between RATs since each LCID can exist on either EUTRA or NR RATs, or both.
|
||||
*
|
||||
* Since the access of this class is happening from two different threads (GW+RRC/Stack)
|
||||
* it's public interface is protected.
|
||||
*
|
||||
* The class provides two interfaces to be used with RNTI or without. The version without
|
||||
* RNTI is used by the UE. The version with RNTI in the interface is intented to be
|
||||
* used by the eNB.
|
||||
*
|
||||
*/
|
||||
class bearer_manager
|
||||
{
|
||||
public:
|
||||
bearer_manager();
|
||||
~bearer_manager();
|
||||
|
||||
struct radio_bearer_t {
|
||||
srsran::srsran_rat_t rat;
|
||||
uint32_t lcid;
|
||||
uint32_t eps_bearer_id;
|
||||
bool is_valid() const { return rat != srsran_rat_t::nulltype; }
|
||||
};
|
||||
|
||||
/// Single user interface (for UE)
|
||||
|
||||
// RRC interface
|
||||
/// Registers EPS bearer with PDCP RAT type and LCID
|
||||
void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid);
|
||||
|
||||
/// Single EPS bearer is removed from map when the associated DRB is deleted
|
||||
void remove_eps_bearer(uint8_t eps_bearer_id);
|
||||
|
||||
/// All registered bearer are removed (e.g. after connection release)
|
||||
void reset();
|
||||
|
||||
// GW interface
|
||||
bool has_active_radio_bearer(uint32_t eps_bearer_id);
|
||||
|
||||
// Stack interface to retrieve active RB
|
||||
radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id);
|
||||
|
||||
radio_bearer_t get_lcid_bearer(uint16_t rnti, uint32_t lcid);
|
||||
|
||||
/// Multi-user interface (see comments above)
|
||||
void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid);
|
||||
void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id);
|
||||
void reset(uint16_t rnti);
|
||||
bool has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id);
|
||||
radio_bearer_t get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id);
|
||||
|
||||
private:
|
||||
pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
typedef std::map<uint32_t, radio_bearer_t> eps_rb_map_t;
|
||||
struct user_bearers {
|
||||
eps_rb_map_t bearers;
|
||||
std::map<uint32_t, uint32_t> lcid_to_eps_bearer_id;
|
||||
};
|
||||
std::map<uint16_t, user_bearers> users_map;
|
||||
|
||||
const uint16_t default_key = 0xffff; // dummy RNTI used for public interface without explicit RNTI
|
||||
radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0, 0};
|
||||
};
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_BEARER_MANAGER_H
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
*
|
||||
* \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_GNB_MAC_INTERFACES_H
|
||||
#define SRSRAN_GNB_MAC_INTERFACES_H
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
class mac_interface_rrc_nr
|
||||
{
|
||||
public:
|
||||
// Provides cell configuration including SIB periodicity, etc.
|
||||
virtual int cell_cfg(const sched_interface::cell_cfg_t& cell,
|
||||
srsran::const_span<sched_nr_interface::cell_cfg_t> nr_cells) = 0;
|
||||
|
||||
/// Allocates a new user/RNTI at MAC. Returns RNTI on success or SRSRAN_INVALID_RNTI otherwise.
|
||||
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;
|
||||
};
|
||||
|
||||
// NR interface is identical to EUTRA interface
|
||||
class mac_interface_rlc_nr : public mac_interface_rlc
|
||||
{};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_GNB_MAC_INTERFACES_H
|
@ -0,0 +1,23 @@
|
||||
/**
|
||||
*
|
||||
* \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_SLIV_H
|
||||
#define SRSRAN_SLIV_H
|
||||
|
||||
#include "srsran/config.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
SRSRAN_API void srsran_sliv_to_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L);
|
||||
|
||||
SRSRAN_API uint32_t srsran_sliv_from_s_and_l(uint32_t N, uint32_t S, uint32_t L);
|
||||
|
||||
#endif // SRSRAN_SLIV_H
|
@ -0,0 +1,153 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/bearer_manager.h"
|
||||
|
||||
namespace srsran {
|
||||
|
||||
bearer_manager::bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false))
|
||||
{
|
||||
pthread_rwlock_init(&rwlock, nullptr);
|
||||
}
|
||||
|
||||
bearer_manager::~bearer_manager()
|
||||
{
|
||||
pthread_rwlock_destroy(&rwlock);
|
||||
}
|
||||
|
||||
void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
|
||||
{
|
||||
add_eps_bearer(default_key, eps_bearer_id, rat, lcid);
|
||||
}
|
||||
|
||||
void bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
|
||||
{
|
||||
srsran::rwlock_write_guard rw_lock(rwlock);
|
||||
auto user_it = users_map.find(rnti);
|
||||
if (user_it == users_map.end()) {
|
||||
// add empty bearer map
|
||||
auto p = users_map.emplace(rnti, user_bearers{});
|
||||
user_it = p.first;
|
||||
}
|
||||
|
||||
auto bearer_it = user_it->second.bearers.find(eps_bearer_id);
|
||||
if (bearer_it != user_it->second.bearers.end()) {
|
||||
logger.error("EPS bearer ID %d already registered", eps_bearer_id);
|
||||
return;
|
||||
}
|
||||
user_it->second.bearers.emplace(eps_bearer_id, radio_bearer_t{rat, lcid, eps_bearer_id});
|
||||
user_it->second.lcid_to_eps_bearer_id.emplace(lcid, eps_bearer_id);
|
||||
logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str());
|
||||
}
|
||||
|
||||
void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id)
|
||||
{
|
||||
remove_eps_bearer(default_key, eps_bearer_id);
|
||||
}
|
||||
|
||||
void bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id)
|
||||
{
|
||||
srsran::rwlock_write_guard rw_lock(rwlock);
|
||||
|
||||
auto user_it = users_map.find(rnti);
|
||||
if (user_it == users_map.end()) {
|
||||
logger.error("No EPS bearer registered for rnti=%x", rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
auto bearer_it = user_it->second.bearers.find(eps_bearer_id);
|
||||
if (bearer_it == user_it->second.bearers.end()) {
|
||||
logger.error("Can't remove EPS bearer ID %d", eps_bearer_id);
|
||||
return;
|
||||
}
|
||||
uint32_t lcid = bearer_it->second.lcid;
|
||||
user_it->second.bearers.erase(bearer_it);
|
||||
user_it->second.lcid_to_eps_bearer_id.erase(lcid);
|
||||
logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id);
|
||||
}
|
||||
|
||||
void bearer_manager::reset()
|
||||
{
|
||||
reset(default_key);
|
||||
}
|
||||
|
||||
void bearer_manager::reset(uint16_t rnti)
|
||||
{
|
||||
srsran::rwlock_write_guard rw_lock(rwlock);
|
||||
|
||||
auto user_it = users_map.find(rnti);
|
||||
if (user_it == users_map.end()) {
|
||||
logger.error("No EPS bearer registered for rnti=%x", rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
user_it->second.lcid_to_eps_bearer_id.clear();
|
||||
user_it->second.bearers.clear();
|
||||
logger.info("Reset EPS bearer manager");
|
||||
}
|
||||
|
||||
// GW interface
|
||||
bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id)
|
||||
{
|
||||
return has_active_radio_bearer(default_key, eps_bearer_id);
|
||||
}
|
||||
|
||||
bool bearer_manager::has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id)
|
||||
{
|
||||
srsran::rwlock_read_guard rw_lock(rwlock);
|
||||
|
||||
auto user_it = users_map.find(rnti);
|
||||
if (user_it == users_map.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end();
|
||||
}
|
||||
|
||||
// Stack interface
|
||||
bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint32_t eps_bearer_id)
|
||||
{
|
||||
return get_radio_bearer(default_key, eps_bearer_id);
|
||||
}
|
||||
|
||||
bearer_manager::radio_bearer_t bearer_manager::get_lcid_bearer(uint16_t rnti, uint32_t lcid)
|
||||
{
|
||||
srsran::rwlock_read_guard rw_lock(rwlock);
|
||||
|
||||
auto user_it = users_map.find(rnti);
|
||||
if (user_it == users_map.end()) {
|
||||
return invalid_rb;
|
||||
}
|
||||
|
||||
auto lcid_it = user_it->second.lcid_to_eps_bearer_id.find(lcid);
|
||||
if (lcid_it != user_it->second.lcid_to_eps_bearer_id.end()) {
|
||||
return user_it->second.bearers.at(lcid_it->second);
|
||||
}
|
||||
return invalid_rb;
|
||||
}
|
||||
|
||||
bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id)
|
||||
{
|
||||
srsran::rwlock_read_guard rw_lock(rwlock);
|
||||
|
||||
auto user_it = users_map.find(rnti);
|
||||
if (user_it == users_map.end()) {
|
||||
return invalid_rb;
|
||||
}
|
||||
|
||||
if (user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end()) {
|
||||
return user_it->second.bearers.at(eps_bearer_id);
|
||||
}
|
||||
return invalid_rb;
|
||||
}
|
||||
|
||||
} // namespace srsran
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
*
|
||||
* \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/common/sliv.h"
|
||||
|
||||
void srsran_sliv_to_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L)
|
||||
{
|
||||
uint32_t low = v % N;
|
||||
uint32_t high = v / N;
|
||||
if (high + 1 + low <= N) {
|
||||
*S = low;
|
||||
*L = high + 1;
|
||||
} else {
|
||||
*S = N - 1 - low;
|
||||
*L = N - high + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t srsran_sliv_from_s_and_l(uint32_t N, uint32_t S, uint32_t L)
|
||||
{
|
||||
if ((L - 1) <= N / 2) {
|
||||
return N * (L - 1) + S;
|
||||
}
|
||||
return N * (N - L + 1) + (N - 1 - S);
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/common/sliv.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static uint32_t N = 48;
|
||||
|
||||
static int test()
|
||||
{
|
||||
for (uint32_t s = 0; s < N; s++) {
|
||||
for (uint32_t l = 1; l < N - s; l++) {
|
||||
uint32_t sliv = srsran_sliv_from_s_and_l(N, s, l);
|
||||
|
||||
uint32_t S = 0;
|
||||
uint32_t L = 0;
|
||||
srsran_sliv_to_s_and_l(N, sliv, &S, &L);
|
||||
|
||||
if (s != S || l != L) {
|
||||
printf("s=%d; l=%d; SLIV=%d; Start: %d; Length: %d;\n", s, l, sliv, S, L);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Parse N
|
||||
if (argc >= 2) {
|
||||
N = (uint32_t)strtol(argv[1], NULL, 10);
|
||||
}
|
||||
|
||||
// If two arguments, run brute force test
|
||||
if (argc == 2) {
|
||||
return test();
|
||||
}
|
||||
|
||||
// if three arguments, calculate start and length from sliv
|
||||
if (argc == 3) {
|
||||
uint32_t sliv = (uint32_t)strtol(argv[2], NULL, 10);
|
||||
uint32_t S = 0;
|
||||
uint32_t L = 0;
|
||||
srsran_sliv_to_s_and_l(N, sliv, &S, &L);
|
||||
|
||||
printf("SLIV=%d; Start: %d; Length: %d;\n", sliv, S, L);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// if four arguments, calculate sliv from start and length
|
||||
if (argc == 4) {
|
||||
uint32_t s = (uint32_t)strtol(argv[2], NULL, 10);
|
||||
uint32_t l = (uint32_t)strtol(argv[3], NULL, 10);
|
||||
uint32_t sliv = srsran_sliv_from_s_and_l(N, s, l);
|
||||
|
||||
printf("SLIV=%d; Start: %d; Length: %d;\n", sliv, s, l);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/**
|
||||
*
|
||||
* \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_CONFIG_H
|
||||
#define SRSRAN_SCHED_CONFIG_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
/**
|
||||
* Structure used in UE logical channel configuration
|
||||
*/
|
||||
struct mac_lc_ch_cfg_t {
|
||||
enum direction_t { IDLE = 0, UL, DL, BOTH } direction = IDLE;
|
||||
int priority = 1; // channel priority (1 is highest)
|
||||
uint32_t bsd = 1000; // msec
|
||||
uint32_t pbr = -1; // prioritised bit rate
|
||||
int group = 0; // logical channel group
|
||||
|
||||
bool is_active() const { return direction != IDLE; }
|
||||
bool is_dl() const { return direction == DL or direction == BOTH; }
|
||||
bool is_ul() const { return direction == UL or direction == BOTH; }
|
||||
bool operator==(const mac_lc_ch_cfg_t& other) const
|
||||
{
|
||||
return direction == other.direction and priority == other.priority and bsd == other.bsd and pbr == other.pbr and
|
||||
group == other.group;
|
||||
}
|
||||
bool operator!=(const mac_lc_ch_cfg_t& other) const { return not(*this == other); }
|
||||
};
|
||||
|
||||
inline const char* to_string(mac_lc_ch_cfg_t::direction_t dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case mac_lc_ch_cfg_t::direction_t::IDLE:
|
||||
return "idle";
|
||||
case mac_lc_ch_cfg_t::direction_t::BOTH:
|
||||
return "bi-dir";
|
||||
case mac_lc_ch_cfg_t::direction_t::DL:
|
||||
return "DL";
|
||||
case mac_lc_ch_cfg_t::direction_t::UL:
|
||||
return "UL";
|
||||
default:
|
||||
return "unrecognized direction";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_CONFIG_H
|
@ -0,0 +1,96 @@
|
||||
/**
|
||||
*
|
||||
* \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_UE_BUFFER_MANAGER_H
|
||||
#define SRSRAN_UE_BUFFER_MANAGER_H
|
||||
|
||||
#include "sched_config.h"
|
||||
#include "srsran/common/common_lte.h"
|
||||
#include "srsran/common/common_nr.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include "srsran/support/srsran_assert.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
/**
|
||||
* Class to handle UE DL+UL RLC and MAC buffers state
|
||||
*/
|
||||
template <bool isNR>
|
||||
class ue_buffer_manager
|
||||
{
|
||||
protected:
|
||||
const static uint32_t MAX_LC_ID = isNR ? srsran::MAX_NR_NOF_BEARERS : srsran::MAX_LTE_LCID;
|
||||
const static uint32_t MAX_LCG_ID = isNR ? 7 : 3;
|
||||
const static uint32_t MAX_SRB_LC_ID = isNR ? srsran::MAX_NR_SRB_ID : srsran::MAX_LTE_SRB_ID;
|
||||
const static uint32_t MAX_NOF_LCIDS = MAX_LC_ID + 1;
|
||||
const static uint32_t MAX_NOF_LCGS = MAX_LCG_ID + 1;
|
||||
constexpr static uint32_t pbr_infinity = -1;
|
||||
|
||||
public:
|
||||
explicit ue_buffer_manager(srslog::basic_logger& logger_);
|
||||
|
||||
// Bearer configuration
|
||||
void config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg);
|
||||
|
||||
// Buffer Status update
|
||||
void ul_bsr(uint32_t lcg_id, uint32_t val);
|
||||
void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue);
|
||||
|
||||
// Configuration getters
|
||||
bool is_bearer_active(uint32_t lcid) const { return get_cfg(lcid).is_active(); }
|
||||
bool is_bearer_ul(uint32_t lcid) const { return get_cfg(lcid).is_ul(); }
|
||||
bool is_bearer_dl(uint32_t lcid) const { return get_cfg(lcid).is_dl(); }
|
||||
const mac_lc_ch_cfg_t& get_cfg(uint32_t lcid) const
|
||||
{
|
||||
srsran_assert(is_lcid_valid(lcid), "Provided LCID=%d is above limit=%d", lcid, MAX_LC_ID);
|
||||
return channels[lcid].cfg;
|
||||
}
|
||||
|
||||
/// DL newtx buffer status for given LCID (no RLC overhead included)
|
||||
int get_dl_tx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_tx : 0; }
|
||||
|
||||
/// DL retx buffer status for given LCID (no RLC overhead included)
|
||||
int get_dl_retx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_retx : 0; }
|
||||
|
||||
/// Sum of DL RLC newtx and retx buffer status for given LCID (no RLC overhead included)
|
||||
int get_dl_tx_total(uint32_t lcid) const { return get_dl_tx(lcid) + get_dl_retx(lcid); }
|
||||
|
||||
/// Sum of DL RLC newtx and retx buffer status for all LCIDS
|
||||
int get_dl_tx_total() const;
|
||||
|
||||
// UL BSR methods
|
||||
bool is_lcg_active(uint32_t lcg) const;
|
||||
int get_bsr(uint32_t lcg) const;
|
||||
int get_bsr() const;
|
||||
const std::array<int, MAX_NOF_LCGS>& get_bsr_state() const { return lcg_bsr; }
|
||||
|
||||
static bool is_lcid_valid(uint32_t lcid) { return lcid <= MAX_LC_ID; }
|
||||
static bool is_lcg_valid(uint32_t lcg) { return lcg <= MAX_LCG_ID; }
|
||||
|
||||
protected:
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
struct logical_channel {
|
||||
mac_lc_ch_cfg_t cfg;
|
||||
int buf_tx = 0;
|
||||
int buf_retx = 0;
|
||||
int Bj = 0;
|
||||
int bucket_size = 0;
|
||||
};
|
||||
std::array<logical_channel, MAX_NOF_LCIDS> channels;
|
||||
|
||||
std::array<int, MAX_NOF_LCGS> lcg_bsr;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_UE_BUFFER_MANAGER_H
|
@ -0,0 +1,10 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(SOURCES ue_buffer_manager.cc)
|
||||
add_library(srsenb_mac_common STATIC ${SOURCES})
|
@ -0,0 +1,134 @@
|
||||
/**
|
||||
*
|
||||
* \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 "srsenb/hdr/stack/mac/common/ue_buffer_manager.h"
|
||||
#include "srsran/common/string_helpers.h"
|
||||
#include "srsran/srslog/bundled/fmt/format.h"
|
||||
#include "srsran/srslog/bundled/fmt/ranges.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
template <bool isNR>
|
||||
ue_buffer_manager<isNR>::ue_buffer_manager(srslog::basic_logger& logger_) : logger(logger_)
|
||||
{
|
||||
std::fill(lcg_bsr.begin(), lcg_bsr.end(), 0);
|
||||
}
|
||||
|
||||
template <bool isNR>
|
||||
void ue_buffer_manager<isNR>::config_lcid(uint32_t lcid, const mac_lc_ch_cfg_t& bearer_cfg)
|
||||
{
|
||||
if (not is_lcid_valid(lcid)) {
|
||||
logger.warning("Configuring bearer with invalid logical channel id=%d", lcid);
|
||||
return;
|
||||
}
|
||||
if (not is_lcg_valid(bearer_cfg.group)) {
|
||||
logger.warning("Configuring bearer with invalid logical channel group id=%d", bearer_cfg.group);
|
||||
return;
|
||||
}
|
||||
|
||||
// update bearer config
|
||||
if (bearer_cfg != channels[lcid].cfg) {
|
||||
channels[lcid].cfg = bearer_cfg;
|
||||
if (channels[lcid].cfg.pbr == pbr_infinity) {
|
||||
channels[lcid].bucket_size = std::numeric_limits<int>::max();
|
||||
channels[lcid].Bj = std::numeric_limits<int>::max();
|
||||
} else {
|
||||
channels[lcid].bucket_size = channels[lcid].cfg.bsd * channels[lcid].cfg.pbr;
|
||||
channels[lcid].Bj = 0;
|
||||
}
|
||||
logger.info("SCHED: bearer configured: lcid=%d, mode=%s, prio=%d",
|
||||
lcid,
|
||||
to_string(channels[lcid].cfg.direction),
|
||||
channels[lcid].cfg.priority);
|
||||
}
|
||||
}
|
||||
|
||||
template <bool isNR>
|
||||
int ue_buffer_manager<isNR>::get_dl_tx_total() const
|
||||
{
|
||||
int sum = 0;
|
||||
for (size_t lcid = 0; is_lcid_valid(lcid); ++lcid) {
|
||||
sum += get_dl_tx_total(lcid);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
template <bool isNR>
|
||||
bool ue_buffer_manager<isNR>::is_lcg_active(uint32_t lcg) const
|
||||
{
|
||||
if (lcg == 0) {
|
||||
return true;
|
||||
}
|
||||
for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) {
|
||||
if (is_bearer_ul(lcid) and channels[lcid].cfg.group == (int)lcg) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <bool isNR>
|
||||
int ue_buffer_manager<isNR>::get_bsr(uint32_t lcg) const
|
||||
{
|
||||
return is_lcg_active(lcg) ? lcg_bsr[lcg] : 0;
|
||||
}
|
||||
|
||||
template <bool isNR>
|
||||
int ue_buffer_manager<isNR>::get_bsr() const
|
||||
{
|
||||
uint32_t count = 0;
|
||||
for (uint32_t lcg = 0; is_lcg_valid(lcg); ++lcg) {
|
||||
if (is_lcg_active(lcg)) {
|
||||
count += lcg_bsr[lcg];
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <bool isNR>
|
||||
void ue_buffer_manager<isNR>::ul_bsr(uint32_t lcg_id, uint32_t val)
|
||||
{
|
||||
if (not is_lcg_valid(lcg_id)) {
|
||||
logger.warning("The provided logical channel group id=%d is not valid", lcg_id);
|
||||
return;
|
||||
}
|
||||
lcg_bsr[lcg_id] = val;
|
||||
|
||||
if (logger.debug.enabled()) {
|
||||
fmt::memory_buffer str_buffer;
|
||||
fmt::format_to(str_buffer, "{}", lcg_bsr);
|
||||
logger.debug("SCHED: lcg_id=%d, bsr=%d. Current state=%s", lcg_id, val, srsran::to_c_str(str_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
template <bool isNR>
|
||||
void ue_buffer_manager<isNR>::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue)
|
||||
{
|
||||
if (not is_lcid_valid(lcid)) {
|
||||
logger.warning("The provided lcid=%d is not valid", lcid);
|
||||
return;
|
||||
}
|
||||
if (lcid <= MAX_SRB_LC_ID and
|
||||
(channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_retx != (int)retx_queue)) {
|
||||
logger.info("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue);
|
||||
} else {
|
||||
logger.debug("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue);
|
||||
}
|
||||
channels[lcid].buf_retx = retx_queue;
|
||||
channels[lcid].buf_tx = tx_queue;
|
||||
}
|
||||
|
||||
// Explicit instantiation
|
||||
template class ue_buffer_manager<true>;
|
||||
template class ue_buffer_manager<false>;
|
||||
|
||||
} // namespace srsenb
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue