rework MAC logical channel prioritization

This commit is contained in:
Andre Puschmann 2019-06-14 22:11:25 +02:00
parent 6d586d84a8
commit da35f41dd5
14 changed files with 314 additions and 291 deletions

View File

@ -47,7 +47,6 @@ public:
last_sdu_idx(-1),
pdu_is_ul(false),
buffer_tx(nullptr),
sdu_offset_start(0),
total_sdu_len(0)
{
}
@ -71,9 +70,9 @@ public:
void init_rx(uint32_t pdu_len_bytes, bool is_ulsch = false) { init_(NULL, pdu_len_bytes, is_ulsch); }
void init_tx(uint8_t* payload, uint32_t pdu_len_bytes, bool is_ulsch = false)
void init_tx(byte_buffer_t* buffer, uint32_t pdu_len_bytes, bool is_ulsch = false)
{
init_(payload, pdu_len_bytes, is_ulsch);
init_(buffer, pdu_len_bytes, is_ulsch);
}
uint32_t nof_subh() { return nof_subheaders; }
@ -82,10 +81,9 @@ public:
{
if (nof_subheaders < (int)max_subheaders - 1 && rem_len > 0) {
nof_subheaders++;
next();
return true;
return next();
} else {
return false;
return -1;
}
}
@ -120,9 +118,13 @@ public:
bool is_ul() { return pdu_is_ul; }
uint8_t* get_current_sdu_ptr() { return &buffer_tx[total_sdu_len + sdu_offset_start]; }
uint8_t* get_current_sdu_ptr() { return (buffer_tx->msg + total_sdu_len); }
void add_sdu(uint32_t sdu_sz) { total_sdu_len += sdu_sz; }
void add_sdu(uint32_t sdu_sz)
{
buffer_tx->N_bytes += sdu_sz;
total_sdu_len += sdu_sz;
}
// Section 6.1.2
void parse_packet(uint8_t* ptr)
@ -150,20 +152,18 @@ protected:
int nof_subheaders;
uint32_t max_subheaders;
bool pdu_is_ul;
uint8_t* buffer_tx;
byte_buffer_t* buffer_tx = nullptr;
uint32_t total_sdu_len;
uint32_t sdu_offset_start;
int last_sdu_idx;
/* Prepares the PDU for parsing or writing by setting the number of subheaders to 0 and the pdu length */
virtual void init_(uint8_t* buffer_tx_ptr, uint32_t pdu_len_bytes, bool is_ulsch)
virtual void init_(byte_buffer_t* buffer_tx_, uint32_t pdu_len_bytes, bool is_ulsch)
{
nof_subheaders = 0;
pdu_len = pdu_len_bytes;
rem_len = pdu_len;
pdu_is_ul = is_ulsch;
buffer_tx = buffer_tx_ptr;
sdu_offset_start = max_subheaders * 2 + 13; // Assuming worst-case 2 bytes per sdu subheader + all possible CE
buffer_tx = buffer_tx_;
total_sdu_len = 0;
last_sdu_idx = -1;
reset();
@ -198,18 +198,7 @@ private:
class sch_subh : public subh<sch_subh>
{
public:
sch_subh(subh_type type_ = SCH_SUBH_TYPE)
{
lcid = 0;
nof_bytes = 0;
payload = NULL;
nof_mch_sched_ce = 0;
cur_mch_sched_ce = 0;
F_bit = false;
type = type_;
parent = NULL;
bzero(&w_payload_ce, sizeof(w_payload_ce));
}
sch_subh(subh_type type_ = SCH_SUBH_TYPE) : type(type_) {}
virtual ~sch_subh() {}
@ -288,14 +277,14 @@ public:
protected:
static const int MAX_CE_PAYLOAD_LEN = 8;
uint32_t lcid;
int nof_bytes;
uint8_t* payload;
uint8_t w_payload_ce[64];
uint8_t nof_mch_sched_ce;
uint8_t cur_mch_sched_ce;
bool F_bit;
subh_type type;
uint32_t lcid = 0;
int nof_bytes = 0;
uint8_t* payload = nullptr;
uint8_t w_payload_ce[64] = {};
uint8_t nof_mch_sched_ce = 0;
uint8_t cur_mch_sched_ce = 0;
bool F_bit = false;
subh_type type = SCH_SUBH_TYPE;
private:
uint32_t sizeof_ce(uint32_t lcid, bool is_ul);
@ -401,20 +390,17 @@ public:
private:
/* Prepares the PDU for parsing or writing by setting the number of subheaders to 0 and the pdu length */
virtual void init_(uint8_t* buffer_tx_ptr, uint32_t pdu_len_bytes, bool is_ulsch)
virtual void init_(byte_buffer_t* buffer_tx_, uint32_t pdu_len_bytes, bool is_ulsch)
{
nof_subheaders = 0;
pdu_len = pdu_len_bytes;
rem_len = pdu_len;
pdu_is_ul = is_ulsch;
buffer_tx = buffer_tx_ptr;
sdu_offset_start = max_subheaders * 2 + 13; // Assuming worst-case 2 bytes per sdu subheader + all possible CE
buffer_tx = buffer_tx_;
total_sdu_len = 0;
last_sdu_idx = -1;
reset();
for (uint32_t i = 0; i < max_subheaders; i++) {
mch_subh mch_subh1;
subheaders[i] = mch_subh1;
subheaders[i].parent = this;
subheaders[i].init();
}

View File

@ -28,5 +28,5 @@ add_dependencies(srslte_common gen_build_info)
add_executable(arch_select arch_select.cc)
target_include_directories(srslte_common PUBLIC ${SEC_INCLUDE_DIRS})
target_link_libraries(srslte_common ${SEC_LIBRARIES})
target_link_libraries(srslte_common srslte_phy ${SEC_LIBRARIES})
install(TARGETS srslte_common DESTINATION ${LIBRARY_DIR})

View File

@ -70,29 +70,15 @@ uint8_t* sch_pdu::write_packet()
/* Writes the MAC PDU in the packet, including the MAC headers and CE payload. Section 6.1.2 */
uint8_t* sch_pdu::write_packet(srslte::log* log_h)
{
int init_rem_len = rem_len;
sch_subh padding;
padding.set_padding();
if (nof_subheaders <= 0 && nof_subheaders < (int)max_subheaders) {
log_h->error("Trying to write packet with invalid number of subheaders (nof_subheaders=%d).\n", nof_subheaders);
return NULL;
}
if (init_rem_len < 0) {
log_h->error("init_rem_len=%d\n", init_rem_len);
return NULL;
}
/* If last SDU has zero payload, remove it. FIXME: Why happens this?? */
if (subheaders[nof_subheaders - 1].get_payload_size() == 0) {
del_subh();
}
/* Determine if we are transmitting CEs only. */
// Determine if we are transmitting CEs only
bool ce_only = last_sdu_idx < 0 ? true : false;
/* Determine if we will need multi-byte padding or 1/2 bytes padding */
// Determine if we will need multi-byte padding or 1/2 bytes padding
bool multibyte_padding = false;
uint32_t onetwo_padding = 0;
if (rem_len > 2) {
@ -108,7 +94,7 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h)
rem_len = 0;
}
/* Determine the header size and CE payload size */
// Determine the header size and CE payload size
uint32_t header_sz = 0;
uint32_t ce_payload_sz = 0;
for (int i = 0; i < nof_subheaders; i++) {
@ -122,29 +108,30 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h)
} else if (onetwo_padding) {
header_sz += onetwo_padding;
}
if (ce_payload_sz + header_sz >= sdu_offset_start) {
ERROR("Writing PDU: header sz + ce_payload_sz >= sdu_offset_start (%d>=%d). pdu_len=%d, total_sdu_len=%d\n",
header_sz + ce_payload_sz,
sdu_offset_start,
pdu_len,
total_sdu_len);
return NULL;
}
/* Start writing header and CE payload before the start of the SDU payload */
uint8_t* ptr = &buffer_tx[sdu_offset_start - header_sz - ce_payload_sz];
uint8_t* pdu_start_ptr = ptr;
uint32_t total_header_size = header_sz + ce_payload_sz;
// Rewind PDU pointer and leave space for entire header
buffer_tx->msg -= total_header_size;
buffer_tx->N_bytes += total_header_size;
// Start writing header and CE payload before the start of the SDU payload
uint8_t* ptr = buffer_tx->msg;
// Add single/two byte padding first
sch_subh padding;
padding.set_padding();
for (uint32_t i = 0; i < onetwo_padding; i++) {
padding.write_subheader(&ptr, false);
}
// Then write subheaders for MAC CE
for (int i = 0; i < nof_subheaders; i++) {
if (!subheaders[i].is_sdu()) {
subheaders[i].write_subheader(&ptr, ce_only && !multibyte_padding && i == (nof_subheaders - 1));
}
}
// Then for SDUs
if (!ce_only) {
for (int i = 0; i < nof_subheaders; i++) {
@ -168,7 +155,8 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h)
}
// Set padding to zeros (if any)
if (rem_len > 0) {
bzero(&pdu_start_ptr[pdu_len - rem_len], rem_len * sizeof(uint8_t));
bzero(&buffer_tx->msg[total_header_size + total_sdu_len], rem_len * sizeof(uint8_t));
buffer_tx->N_bytes += rem_len;
}
/* Sanity check and print if error */
@ -186,7 +174,7 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h)
rem_len);
} else {
printf("Wrote PDU: pdu_len=%d, header_and_ce=%d (%d+%d), nof_subh=%d, last_sdu=%d, sdu_len=%d, onepad=%d, "
"multi=%d, init_rem_len=%d\n",
"multi=%d\n",
pdu_len,
header_sz + ce_payload_sz,
header_sz,
@ -195,8 +183,7 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h)
last_sdu_idx,
total_sdu_len,
onetwo_padding,
rem_len,
init_rem_len);
rem_len);
}
if (rem_len + header_sz + ce_payload_sz + total_sdu_len != pdu_len) {
@ -206,7 +193,7 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h)
log_h->console("SUBH %d is_sdu=%d, payload=%d\n", i, subheaders[i].is_sdu(), subheaders[i].get_payload_size());
}
log_h->console("Wrote PDU: pdu_len=%d, header_and_ce=%d (%d+%d), nof_subh=%d, last_sdu=%d, sdu_len=%d, "
"onepad=%d, multi=%d, init_rem_len=%d\n",
"onepad=%d, multi=%d\n",
pdu_len,
header_sz + ce_payload_sz,
header_sz,
@ -215,13 +202,12 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h)
last_sdu_idx,
total_sdu_len,
onetwo_padding,
rem_len,
init_rem_len);
rem_len);
ERROR("Expected PDU len %d bytes but wrote %d\n", pdu_len, rem_len + header_sz + ce_payload_sz + total_sdu_len);
log_h->console("------------------------------\n");
log_h->error("Wrote PDU: pdu_len=%d, header_and_ce=%d (%d+%d), nof_subh=%d, last_sdu=%d, sdu_len=%d, onepad=%d, "
"multi=%d, init_rem_len=%d\n",
"multi=%d\n",
pdu_len,
header_sz + ce_payload_sz,
header_sz,
@ -230,21 +216,13 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h)
last_sdu_idx,
total_sdu_len,
onetwo_padding,
rem_len,
init_rem_len);
rem_len);
}
return NULL;
}
if ((int)(header_sz + ce_payload_sz) != (int)(ptr - pdu_start_ptr)) {
ERROR("Expected a header and CE payload of %d bytes but wrote %d\n",
header_sz + ce_payload_sz,
(int)(ptr - pdu_start_ptr));
return NULL;
}
return pdu_start_ptr;
return buffer_tx->msg;
}
int sch_pdu::rem_size()
@ -300,7 +278,6 @@ bool sch_pdu::has_space_sdu(uint32_t nbytes)
bool sch_pdu::update_space_sdu(uint32_t nbytes)
{
int init_rem = rem_len;
if (has_space_sdu(nbytes)) {
if (last_sdu_idx < 0) {
rem_len -= (nbytes + 1);
@ -514,7 +491,6 @@ uint32_t sch_subh::get_sdu_lcid()
}
uint32_t sch_subh::get_payload_size()
{
return nof_bytes;
}
@ -522,10 +498,7 @@ uint32_t sch_subh::get_payload_size()
uint32_t sch_subh::get_header_size(bool is_last)
{
if (!is_last) {
if (is_sdu()) {
return sch_pdu::size_header_sdu(nof_bytes);
}
if (lcid == MCH_SCHED_INFO && type == MCH_SUBH_TYPE) {
if (is_sdu() || (lcid == MCH_SCHED_INFO && type == MCH_SUBH_TYPE)) {
return sch_pdu::size_header_sdu(nof_bytes);
}
return 1; // All others are 1-byte
@ -647,14 +620,14 @@ bool sch_subh::set_next_mch_sched_info(uint8_t lcid_, uint16_t mtch_stop)
return false;
}
int sch_subh::set_sdu(uint32_t lcid_, uint32_t requested_bytes, read_pdu_interface* sdu_itf)
int sch_subh::set_sdu(uint32_t lcid_, uint32_t requested_bytes_, read_pdu_interface* sdu_itf_)
{
if (((sch_pdu*)parent)->has_space_sdu(requested_bytes)) {
if (((sch_pdu*)parent)->has_space_sdu(requested_bytes_)) {
lcid = lcid_;
payload = ((sch_pdu*)parent)->get_current_sdu_ptr();
// Copy data and get final number of bytes written to the MAC PDU
int sdu_sz = sdu_itf->read_pdu(lcid, payload, requested_bytes);
int sdu_sz = sdu_itf_->read_pdu(lcid, payload, requested_bytes_);
if (sdu_sz < 0) {
return -1;
@ -665,7 +638,7 @@ int sch_subh::set_sdu(uint32_t lcid_, uint32_t requested_bytes, read_pdu_interfa
// Save final number of written bytes
nof_bytes = sdu_sz;
if (nof_bytes > (int32_t)requested_bytes) {
if (nof_bytes > (int32_t)requested_bytes_) {
return -1;
}
}

View File

@ -152,10 +152,10 @@ private:
uint8_t* assemble_rar(sched_interface::dl_sched_rar_grant_t *grants, uint32_t nof_grants, int rar_idx, uint32_t pdu_len);
uint8_t* assemble_si(uint32_t index);
const static int rar_payload_len = 128;
std::vector<srslte::rar_pdu> rar_pdu_msg;
uint8_t rar_payload[sched_interface::MAX_RAR_LIST][rar_payload_len];
const static int rar_payload_len = 128;
std::vector<srslte::rar_pdu> rar_pdu_msg;
srslte::byte_buffer_t rar_payload[sched_interface::MAX_RAR_LIST];
typedef struct {
uint32_t preamble_idx;
uint32_t ta_cmd;

View File

@ -107,9 +107,8 @@ private:
uint8_t* pending_buffers[NOF_RX_HARQ_PROCESSES];
// For DL there are two buffers, one for each Transport block
const static int payload_buffer_len = 128*1024;
uint8_t tx_payload_buffer[SRSLTE_MAX_TB][payload_buffer_len];
srslte::byte_buffer_t tx_payload_buffer[SRSLTE_MAX_TB];
// For UL there are multiple buffers per PID and are managed by pdu_queue
srslte::pdu_queue pdus;
srslte::sch_pdu mac_msg_dl, mac_msg_ul;

View File

@ -747,10 +747,11 @@ int mac::get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res)
uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, uint32_t nof_grants, int rar_idx, uint32_t pdu_len)
{
uint8_t grant_buffer[64];
uint8_t grant_buffer[64] = {};
if (pdu_len < rar_payload_len) {
srslte::rar_pdu *pdu = &rar_pdu_msg[rar_idx];
pdu->init_tx(rar_payload[rar_idx], pdu_len);
rar_payload[rar_idx].clear();
pdu->init_tx(&rar_payload[rar_idx], pdu_len);
for (uint32_t i = 0; i < nof_grants; i++) {
srslte_dci_rar_pack(&grants[i].grant, grant_buffer);
if (pdu->new_subh()) {
@ -763,8 +764,8 @@ uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, uint32
bzero(&pending_rars[idx], sizeof(pending_rar_t));
}
}
pdu->write_packet(rar_payload[rar_idx]);
return rar_payload[rar_idx];
pdu->write_packet(rar_payload[rar_idx].msg);
return rar_payload[rar_idx].msg;
} else {
Error("Assembling RAR: pdu_len > rar_payload_len (%d>%d)\n", pdu_len, rar_payload_len);
return NULL;

View File

@ -62,9 +62,6 @@ ue::ue() :
bzero(&mutex, sizeof(pthread_mutex_t));
bzero(softbuffer_tx, sizeof(softbuffer_tx));
bzero(softbuffer_rx, sizeof(softbuffer_rx));
for (int i = 0; i < SRSLTE_MAX_TB; ++i) {
bzero(tx_payload_buffer, sizeof(uint8_t) * payload_buffer_len);
}
pthread_mutex_init(&mutex, NULL);
}
@ -418,7 +415,8 @@ uint8_t* ue::generate_pdu(uint32_t tb_idx, sched_interface::dl_sched_pdu_t pdu[s
uint8_t *ret = NULL;
pthread_mutex_lock(&mutex);
if (rlc) {
mac_msg_dl.init_tx(tx_payload_buffer[tb_idx], grant_size, false);
tx_payload_buffer->clear();
mac_msg_dl.init_tx(&tx_payload_buffer[tb_idx], grant_size, false);
for (uint32_t i=0;i<nof_pdu_elems;i++) {
if (pdu[i].lcid <= srslte::sch_subh::PHR_REPORT) {
allocate_sdu(&mac_msg_dl, pdu[i].lcid, pdu[i].nbytes);
@ -441,20 +439,22 @@ uint8_t* ue::generate_mch_pdu(sched_interface::dl_pdu_mch_t sched, uint32_t nof_
{
uint8_t *ret = NULL;
pthread_mutex_lock(&mutex);
mch_mac_msg_dl.init_tx(tx_payload_buffer[0],grant_size);
for(uint32_t i = 0; i <nof_pdu_elems;i++){
if(sched.pdu[i].lcid == srslte::mch_subh::MCH_SCHED_INFO) {
mch_mac_msg_dl.new_subh();
mch_mac_msg_dl.get()->set_next_mch_sched_info(sched.mtch_sched[i].lcid,sched.mtch_sched[i].stop);
} else if (sched.pdu[i].lcid == 0) {
mch_mac_msg_dl.new_subh();
mch_mac_msg_dl.get()->set_sdu(0, sched.pdu[i].nbytes, sched.mcch_payload);
} else if (sched.pdu[i].lcid <= srslte::mch_subh::MTCH_MAX_LCID) {
mch_mac_msg_dl.new_subh();
mch_mac_msg_dl.get()->set_sdu(sched.pdu[i].lcid, sched.pdu[i].nbytes,sched.mtch_sched[i].mtch_payload);
}
tx_payload_buffer->clear();
mch_mac_msg_dl.init_tx(&tx_payload_buffer[0], grant_size);
for (uint32_t i = 0; i < nof_pdu_elems; i++) {
if (sched.pdu[i].lcid == srslte::mch_subh::MCH_SCHED_INFO) {
mch_mac_msg_dl.new_subh();
mch_mac_msg_dl.get()->set_next_mch_sched_info(sched.mtch_sched[i].lcid, sched.mtch_sched[i].stop);
} else if (sched.pdu[i].lcid == 0) {
mch_mac_msg_dl.new_subh();
mch_mac_msg_dl.get()->set_sdu(0, sched.pdu[i].nbytes, sched.mcch_payload);
} else if (sched.pdu[i].lcid <= srslte::mch_subh::MTCH_MAX_LCID) {
mch_mac_msg_dl.new_subh();
mch_mac_msg_dl.get()->set_sdu(sched.pdu[i].lcid, sched.pdu[i].nbytes, sched.mtch_sched[i].mtch_payload);
}
}
ret = mch_mac_msg_dl.write_packet(log_h);
pthread_mutex_unlock(&mutex);
return ret;

View File

@ -50,6 +50,7 @@ class mac : public mac_interface_phy_lte,
{
public:
mac();
~mac();
bool init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface_mac* rrc, srslte::log* log_h);
void stop();
@ -75,8 +76,9 @@ public:
/******** Interface from RRC (RRC -> MAC) ****************/
void bcch_start_rx(int si_window_start, int si_window_length);
void bcch_stop_rx();
void pcch_start_rx();
void pcch_start_rx();
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
void setup_lcid(const logical_channel_config_t& config);
void mch_start_rx(uint32_t lcid);
void reconfiguration(const uint32_t& cc_idx, const bool& enable);
void reset();

View File

@ -26,24 +26,26 @@
#include <vector>
#include "srslte/common/log.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srslte/common/pdu.h"
#include "proc_bsr.h"
#include "proc_phr.h"
#include "srslte/common/common.h"
#include "srslte/common/log.h"
#include "srslte/common/pdu.h"
#include "srslte/interfaces/ue_interfaces.h"
/* Logical Channel Multiplexing and Prioritization + Msg3 Buffer */
typedef struct {
uint32_t id;
int Bj;
int PBR; // -1 sets to infinity
uint32_t BSD;
uint32_t priority;
int sched_len;
int buffer_len;
} lchid_t;
uint8_t lcid;
uint8_t lcg;
int Bj;
int PBR; // -1 sets to infinity
uint32_t BSD;
uint32_t priority;
int sched_len;
int buffer_len;
} logical_channel_config_t;
namespace srsue {
@ -57,30 +59,31 @@ public:
bool is_pending_any_sdu();
bool is_pending_sdu(uint32_t lcid);
uint8_t* pdu_get(uint8_t* payload, uint32_t pdu_sz, uint32_t pid);
uint8_t* msg3_get(uint8_t* payload, uint32_t pdu_sz);
uint8_t* pdu_get(srslte::byte_buffer_t* payload, uint32_t pdu_sz);
uint8_t* msg3_get(srslte::byte_buffer_t* payload, uint32_t pdu_sz);
void msg3_flush();
bool msg3_is_transmitted();
void msg3_prepare();
bool msg3_is_pending();
void append_crnti_ce_next_tx(uint16_t crnti);
void set_priority(uint32_t lcid, uint32_t priority, int PBR_x_tti, uint32_t BSD);
void clear_lch(uint32_t lch_id);
private:
int find_lchid(uint32_t lch_id);
void append_crnti_ce_next_tx(uint16_t crnti);
void setup_lcid(const logical_channel_config_t& config);
void print_logical_channel_state(const std::string& info);
private:
bool has_logical_channel(const uint32_t& lcid);
bool pdu_move_to_msg3(uint32_t pdu_sz);
bool allocate_sdu(uint32_t lcid, srslte::sch_pdu *pdu, int max_sdu_sz);
bool sched_sdu(lchid_t *ch, int *sdu_space, int max_sdu_sz);
const static int MIN_RLC_SDU_LEN = 0;
bool sched_sdu(logical_channel_config_t* ch, int* sdu_space, int max_sdu_sz);
const static int MIN_RLC_SDU_LEN = 2;
const static int MAX_NOF_SUBHEADERS = 20;
std::vector<lchid_t> lch;
std::vector<logical_channel_config_t> logical_channels;
// Mutex for exclusive access
pthread_mutex_t mutex;
@ -92,9 +95,7 @@ private:
uint16_t pending_crnti_ce;
/* Msg3 Buffer */
static const uint32_t MSG3_BUFF_SZ = 1024;
uint8_t msg3_buff[MSG3_BUFF_SZ];
uint8_t *msg3_buff_start_pdu;
srslte::byte_buffer_t msg_buff;
/* PDU Buffer */
srslte::sch_pdu pdu_msg;

View File

@ -36,6 +36,8 @@
#include "srslte/interfaces/ue_interfaces.h"
#include "ul_sps.h"
using namespace srslte;
namespace srsue {
class ul_harq_entity {
@ -93,7 +95,7 @@ private:
srslte_softbuffer_tx_t softbuffer;
const static int payload_buffer_len = 128 * 1024;
uint8_t* payload_buffer;
std::unique_ptr<byte_buffer_t> payload_buffer = nullptr;
uint8_t* pdu_ptr;
void generate_tx(mac_interface_phy_lte::tb_action_ul_t* action);

View File

@ -49,11 +49,22 @@ mac::mac() : timers(64), pdu_process_thread(&demux_unit), mch_msg(10), pcap(null
ul_harq.push_back(std::move(ul));
dl_harq.push_back(std::move(dl));
srslte_softbuffer_rx_init(&pch_softbuffer, 100);
srslte_softbuffer_rx_init(&mch_softbuffer, 100);
// Keep initialising members
bzero(&metrics, sizeof(mac_metrics_t));
clear_rntis();
}
mac::~mac()
{
stop();
srslte_softbuffer_rx_free(&pch_softbuffer);
srslte_softbuffer_rx_free(&mch_softbuffer);
}
bool mac::init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface_mac* rrc, srslte::log* log_h_)
{
phy_h = phy;
@ -61,9 +72,6 @@ bool mac::init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface
rrc_h = rrc;
log_h = log_h_;
srslte_softbuffer_rx_init(&pch_softbuffer, 100);
srslte_softbuffer_rx_init(&mch_softbuffer, 100);
timer_alignment = timers.get_unique_id();
uint32_t contention_resolution_timer = timers.get_unique_id();
@ -86,9 +94,6 @@ bool mac::init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface
void mac::stop()
{
srslte_softbuffer_rx_free(&pch_softbuffer);
srslte_softbuffer_rx_free(&mch_softbuffer);
pdu_process_thread.stop();
run_tti(0); // make sure it's not locked after last TTI
@ -165,9 +170,21 @@ void mac::reset()
bsr_procedure.reset();
phr_procedure.reset();
// Setup default LCID 0 and LCID1
setup_lcid(0, 0, 99, -1, -1);
setup_lcid(1, 0, 98, -1, -1);
// Setup default LCID 0 with highest priority
logical_channel_config_t config = {};
config.lcid = 0;
config.lcg = 0;
config.PBR = -1;
config.BSD = 50;
config.priority = 0;
setup_lcid(config);
// and LCID 1 with lower priority
config.lcid = 1;
config.priority = 1;
setup_lcid(config);
mux_unit.print_logical_channel_state("After MAC reset:");
is_first_ul_grant = true;
clear_rntis();
@ -546,11 +563,26 @@ void mac::set_config(mac_cfg_t& mac_cfg)
}
void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD)
{
logical_channel_config_t config = {};
config.lcid = lcid;
config.lcg = lcg;
config.priority = priority;
config.PBR = PBR_x_tti;
config.BSD = BSD;
setup_lcid(config);
}
void mac::setup_lcid(const logical_channel_config_t& config)
{
Info("Logical Channel Setup: LCID=%d, LCG=%d, priority=%d, PBR=%d, BSd=%d\n",
lcid, lcg, priority, PBR_x_tti, BSD);
mux_unit.set_priority(lcid, priority, PBR_x_tti, BSD);
bsr_procedure.setup_lcid(lcid, lcg, priority);
config.lcid,
config.lcg,
config.priority,
config.PBR,
config.BSD);
mux_unit.setup_lcid(config);
bsr_procedure.setup_lcid(config.lcid, config.lcg, config.priority);
}
void mac::mch_start_rx(uint32_t lcid)
@ -648,12 +680,14 @@ mac::pdu_process::~pdu_process()
void mac::pdu_process::stop()
{
mutex.lock();
running = false;
cvar.notify_all();
mutex.unlock();
wait_thread_finish();
if (running) {
{
std::lock_guard<std::mutex> ul(mutex);
running = false;
cvar.notify_all();
}
wait_thread_finish();
}
}
void mac::pdu_process::notify()

View File

@ -42,7 +42,7 @@ mux::mux() : pdu_msg(MAX_NOF_SUBHEADERS)
rlc = NULL;
bsr_procedure = NULL;
phr_procedure = NULL;
msg3_buff_start_pdu = NULL;
// msg3_buff_start_pdu = NULL;
msg3_flush();
}
@ -58,8 +58,8 @@ void mux::init(rlc_interface_mac *rlc_, srslte::log *log_h_, bsr_interface_mux *
void mux::reset()
{
for (uint32_t i=0;i<lch.size();i++) {
lch[i].Bj = 0;
for (uint32_t i = 0; i < logical_channels.size(); i++) {
logical_channels[i].Bj = 0;
}
msg3_pending = false;
pending_crnti_ce = 0;
@ -67,63 +67,78 @@ void mux::reset()
bool mux::is_pending_any_sdu()
{
for (uint32_t i=0;i<lch.size();i++) {
if (rlc->has_data(lch[i].id)) {
for (uint32_t i = 0; i < logical_channels.size(); i++) {
if (rlc->has_data(logical_channels[i].lcid)) {
return true;
}
}
return false;
}
bool mux::is_pending_sdu(uint32_t lch_id) {
return rlc->has_data(lch_id);
}
int mux::find_lchid(uint32_t lcid)
bool mux::has_logical_channel(const uint32_t& lcid)
{
for (uint32_t i=0;i<lch.size();i++) {
if(lch[i].id == lcid) {
return i;
for (auto& channel : logical_channels) {
if (channel.lcid == lcid) {
return true;
}
}
return -1;
return false;
}
bool sortPriority(lchid_t u1, lchid_t u2) {
return u1.priority < u2.priority;
}
void mux::clear_lch(uint32_t lch_id)
bool priority_compare(const logical_channel_config_t& u1, const logical_channel_config_t& u2)
{
int pos = find_lchid(lch_id);
if (pos >= 0) {
lch.erase(lch.begin()+pos);
} else {
Error("Deleting logical channel id %d. Does not exist\n", lch_id);
}
return u1.priority <= u2.priority;
}
void mux::set_priority(uint32_t lch_id, uint32_t new_priority, int set_PBR, uint32_t set_BSD)
void mux::setup_lcid(const logical_channel_config_t& config)
{
int pos = find_lchid(lch_id);
// Create new channel if it does not exist
if (pos < 0) {
lchid_t ch;
ch.id = lch_id;
ch.priority = new_priority;
ch.BSD = set_BSD;
ch.PBR = set_PBR;
ch.Bj = 0;
lch.push_back(ch);
if (has_logical_channel(config.lcid)) {
// update settings
for (auto& channel : logical_channels) {
if (channel.lcid == config.lcid) {
channel = config;
break;
}
}
// warn user if there is another LCID with same prio
for (auto& channel : logical_channels) {
if (channel.priority == config.priority) {
log_h->warning("LCID %d and %d have same priority.\n", channel.lcid, config.lcid);
}
}
} else {
lch[pos].priority = new_priority;
lch[pos].PBR = set_PBR;
lch[pos].BSD = set_BSD;
// add new entry
logical_channels.push_back(config);
}
// sort according to priority (increasing is lower priority)
std::sort(lch.begin(), lch.end(), sortPriority);
std::sort(logical_channels.begin(), logical_channels.end(), priority_compare);
}
void mux::print_logical_channel_state(const std::string& info)
{
std::string logline = info;
for (auto& channel : logical_channels) {
logline += "\n";
logline += "- lcid=";
logline += std::to_string(channel.lcid);
logline += ", lcg=";
logline += std::to_string(channel.lcg);
logline += ", prio=";
logline += std::to_string(channel.priority);
logline += ", Bj=";
logline += std::to_string(channel.Bj);
logline += ", PBR=";
logline += std::to_string(channel.PBR);
logline += ", BSD=";
logline += std::to_string(channel.BSD);
logline += ", buffer_len=";
logline += std::to_string(channel.buffer_len);
logline += ", sched_len=";
logline += std::to_string(channel.sched_len);
}
log_h->debug("%s\n", logline.c_str());
}
srslte::sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) {
@ -139,28 +154,30 @@ srslte::sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) {
}
// Multiplexing and logical channel priorization as defined in Section 5.4.3
uint8_t* mux::pdu_get(uint8_t* payload, uint32_t pdu_sz, uint32_t pid)
uint8_t* mux::pdu_get(srslte::byte_buffer_t* payload, uint32_t pdu_sz)
{
pthread_mutex_lock(&mutex);
// Update Bj
for (uint32_t i=0;i<lch.size();i++) {
// Add PRB unless it's infinity
if (lch[i].PBR >= 0) {
lch[i].Bj += lch[i].PBR;
// Reset sched_len and update Bj
for (auto& channel : logical_channels) {
// Add PRB unless it's infinity
if (channel.PBR >= 0) {
channel.Bj += channel.PBR;
}
if (lch[i].Bj >= (int)lch[i].BSD) {
lch[i].Bj = lch[i].BSD*lch[i].PBR;
}
if (channel.Bj >= (int)channel.BSD) {
channel.Bj = channel.BSD * channel.PBR;
}
channel.sched_len = 0;
}
// Logical Channel Procedure
bool is_rar = false;
payload->clear();
pdu_msg.init_tx(payload, pdu_sz, true);
// MAC control element for C-RNTI or data from UL-CCCH
if (!allocate_sdu(0, &pdu_msg, -1)) {
if (!allocate_sdu(0, &pdu_msg, pdu_sz)) {
if (pending_crnti_ce) {
is_rar = true;
if (pdu_msg.new_subh()) {
@ -175,8 +192,10 @@ uint8_t* mux::pdu_get(uint8_t* payload, uint32_t pdu_sz, uint32_t pid)
}
is_rar = true;
}
pending_crnti_ce = 0;
pending_crnti_ce = 0;
print_logical_channel_state("after CCCH scheduling");
bsr_proc::bsr_t bsr;
bool regular_bsr = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_msg.rem_size(), &bsr);
@ -197,43 +216,44 @@ uint8_t* mux::pdu_get(uint8_t* payload, uint32_t pdu_sz, uint32_t pid)
}
}
// FIXME: IMHO, it should not matter if this is a RAR UL or a normal UL, we fill the grant
if (!is_rar) {
// Update buffer states for all logical channels
int sdu_space = pdu_msg.get_sdu_space();
for (uint32_t i=0;i<lch.size();i++) {
lch[i].buffer_len = rlc->get_buffer_state(lch[i].id);
lch[i].sched_len = 0;
for (auto& channel : logical_channels) {
channel.buffer_len = rlc->get_buffer_state(channel.lcid);
}
int sdu_space = pdu_msg.get_sdu_space();
// data from any Logical Channel, except data from UL-CCCH;
// first only those with positive Bj
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].id != 0) {
if (sched_sdu(&lch[i], &sdu_space, (lch[i].PBR<0)?-1:lch[i].Bj) && lch[i].PBR >= 0) {
lch[i].Bj -= lch[i].sched_len;
for (auto& channel : logical_channels) {
// FIXME: IMHO we should not care if we read from UL-CCCH, the specs say "except" but CCCH has always
// higher priority, so if there is data, it should be allocated
if (channel.lcid != 0) {
int max_sdu_sz = (channel.PBR < 0) ? -1 : channel.Bj; // this can be zero if no PBR has been allocated
if (max_sdu_sz != 0) {
if (sched_sdu(&channel, &sdu_space, max_sdu_sz)) {
channel.Bj -= channel.sched_len;
}
}
}
}
print_logical_channel_state("First round of allocation:");
// If resources remain, allocate regardless of their Bj value
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].id != 0) {
sched_sdu(&lch[i], &sdu_space, -1);
for (auto& channel : logical_channels) {
if (channel.lcid != 0) {
sched_sdu(&channel, &sdu_space, -1);
}
}
// Maximize the dci utilization
if (lch.size() > 0) {
for (int i=(int)lch.size()-1;i>=0;i--) {
if (lch[i].sched_len > 0) {
lch[i].sched_len = -1;
break;
}
}
}
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].sched_len != 0) {
allocate_sdu(lch[i].id, &pdu_msg, lch[i].sched_len);
print_logical_channel_state("Second round of allocation:");
for (auto& channel : logical_channels) {
if (channel.sched_len != 0) {
allocate_sdu(channel.lcid, &pdu_msg, channel.sched_len);
}
}
}
@ -261,9 +281,8 @@ void mux::append_crnti_ce_next_tx(uint16_t crnti) {
pending_crnti_ce = crnti;
}
bool mux::sched_sdu(lchid_t *ch, int *sdu_space, int max_sdu_sz)
bool mux::sched_sdu(logical_channel_config_t* ch, int* sdu_space, int max_sdu_sz)
{
if (*sdu_space > 0) {
// Get n-th pending SDU pointer and length
int sched_len = ch->buffer_len;
@ -273,13 +292,22 @@ bool mux::sched_sdu(lchid_t *ch, int *sdu_space, int max_sdu_sz)
}
if (sched_len > *sdu_space) {
sched_len = *sdu_space;
}
}
log_h->debug("SDU: scheduled lcid=%d, rlc_buffer=%d, allocated=%d/%d\n",
ch->id, ch->buffer_len, sched_len, sdu_space?*sdu_space:0);
*sdu_space -= sched_len;
ch->buffer_len -= sched_len;
ch->lcid,
ch->buffer_len,
sched_len,
sdu_space ? *sdu_space : 0);
*sdu_space -= sched_len;
ch->buffer_len -= sched_len;
if (ch->sched_len == 0) {
// account for header for the first time
*sdu_space -= sch_pdu::size_header_sdu(sched_len);
}
ch->sched_len += sched_len;
return true;
}
@ -289,33 +317,46 @@ bool mux::sched_sdu(lchid_t *ch, int *sdu_space, int max_sdu_sz)
bool mux::allocate_sdu(uint32_t lcid, srslte::sch_pdu* pdu_msg, int max_sdu_sz)
{
// Get n-th pending SDU pointer and length
bool sdu_added = false;
int sdu_space = max_sdu_sz;
int sdu_len = rlc->get_buffer_state(lcid);
while (sdu_len > 0) { // there is pending SDU to allocate
while (sdu_len > 0 && sdu_space >= MIN_RLC_SDU_LEN) { // there is pending SDU to allocate
int buffer_state = sdu_len;
if (sdu_len > max_sdu_sz && max_sdu_sz >= 0) {
sdu_len = max_sdu_sz;
}
int sdu_space = pdu_msg->get_sdu_space();
if (sdu_len > sdu_space || max_sdu_sz < 0) {
sdu_len = sdu_space;
}
if (sdu_len > MIN_RLC_SDU_LEN) {
if (sdu_len >= MIN_RLC_SDU_LEN) {
if (pdu_msg->new_subh()) { // there is space for a new subheader
sdu_len = pdu_msg->get()->set_sdu(lcid, sdu_len, rlc);
if (sdu_len > 0) { // new SDU could be added
Debug("SDU: allocated lcid=%d, rlc_buffer=%d, allocated=%d/%d, max_sdu_sz=%d, remaining=%d\n",
lcid, buffer_state, sdu_len, sdu_space, max_sdu_sz, pdu_msg->rem_size());
sdu_len = rlc->get_buffer_state(lcid);
sdu_space -= sdu_len;
sdu_added = true;
sdu_len = rlc->get_buffer_state(lcid);
} else {
Warning("SDU: rlc_buffer=%d, allocated=%d/%d, remaining=%d\n",
buffer_state, sdu_len, sdu_space, pdu_msg->rem_size());
pdu_msg->del_subh();
}
}
} else {
Warning("SDU: rlc_buffer=%d, allocated=%d/%d, remaining=%d\n",
buffer_state,
sdu_len,
sdu_space,
pdu_msg->rem_size());
}
} else {
Warning("SDU: rlc_buffer=%d, allocated=%d/%d, remaining=%d\n",
buffer_state,
sdu_len,
sdu_space,
pdu_msg->rem_size());
}
}
return sdu_added;
@ -328,8 +369,6 @@ void mux::msg3_flush()
}
msg3_has_been_transmitted = false;
msg3_pending = false;
bzero(msg3_buff, sizeof(MSG3_BUFF_SZ));
msg3_buff_start_pdu = NULL;
}
bool mux::msg3_is_transmitted()
@ -346,26 +385,14 @@ bool mux::msg3_is_pending() {
}
/* Returns a pointer to the Msg3 buffer */
uint8_t* mux::msg3_get(uint8_t *payload, uint32_t pdu_sz)
uint8_t* mux::msg3_get(srslte::byte_buffer_t* payload, uint32_t pdu_sz)
{
if (pdu_sz < MSG3_BUFF_SZ - 32) {
if (!msg3_buff_start_pdu) {
msg3_buff_start_pdu = pdu_get(msg3_buff, pdu_sz, 0);
if (!msg3_buff_start_pdu) {
Error("Moving PDU from Mux unit to Msg3 buffer\n");
return NULL;
}
msg3_has_been_transmitted = true;
msg3_pending = false;
}
} else {
Error("Msg3 size (%d) is longer than internal msg3_buff size=%d, (see mux.h)\n", pdu_sz, MSG3_BUFF_SZ-32);
return NULL;
if (pdu_get(payload, pdu_sz) != nullptr) {
msg3_pending = false;
msg3_has_been_transmitted = true;
return payload->msg;
}
memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz);
msg3_has_been_transmitted = true;
return payload;
return nullptr;
}
}

View File

@ -369,7 +369,7 @@ bool bsr_proc::generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t* bsr)
pthread_mutex_lock(&mutex);
if (triggered_bsr_type != NONE || nof_padding_bytes >= 2) {
if (triggered_bsr_type != NONE && nof_padding_bytes >= 2) {
generate_bsr(bsr, nof_padding_bytes);
ret = true;

View File

@ -148,9 +148,6 @@ ul_harq_entity::ul_harq_process::ul_harq_process()
ul_harq_entity::ul_harq_process::~ul_harq_process()
{
if (is_initiated) {
if (payload_buffer) {
free(payload_buffer);
}
srslte_softbuffer_tx_free(&softbuffer);
}
}
@ -167,12 +164,12 @@ bool ul_harq_entity::ul_harq_process::init(uint32_t pid, ul_harq_entity* parent)
is_initiated = true;
this->pid = pid;
payload_buffer = (uint8_t*)srslte_vec_malloc(payload_buffer_len * sizeof(uint8_t));
payload_buffer = std::unique_ptr<byte_buffer_t>(new byte_buffer_t);
if (!payload_buffer) {
Error("Allocating memory\n");
return false;
}
pdu_ptr = payload_buffer;
pdu_ptr = payload_buffer->msg;
return true;
}
@ -182,6 +179,7 @@ void ul_harq_entity::ul_harq_process::reset()
current_irv = 0;
is_grant_configured = false;
bzero(&cur_grant, sizeof(mac_interface_phy_lte::mac_grant_ul_t));
payload_buffer->clear();
}
void ul_harq_entity::ul_harq_process::reset_ndi()
@ -256,7 +254,7 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr
if (grant_is_rar()) {
if (harq_entity->mux_unit->msg3_is_pending()) {
Debug("Getting Msg3 buffer payload, dci size=%d bytes\n", grant.tb.tbs);
pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer, grant.tb.tbs);
pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer.get(), grant.tb.tbs);
if (pdu_ptr) {
generate_new_tx(grant, action);
} else {
@ -268,7 +266,7 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr
// Normal UL dci
} else {
// Request a MAC PDU from the Multiplexing & Assemble Unit
pdu_ptr = harq_entity->mux_unit->pdu_get(payload_buffer, grant.tb.tbs, pid);
pdu_ptr = harq_entity->mux_unit->pdu_get(payload_buffer.get(), grant.tb.tbs);
if (pdu_ptr) {
generate_new_tx(grant, action);
} else {