|
|
@ -25,8 +25,18 @@ mac_sch_subpdu_nr::nr_lcid_sch_t mac_sch_subpdu_nr::get_type()
|
|
|
|
|
|
|
|
|
|
|
|
bool mac_sch_subpdu_nr::is_sdu()
|
|
|
|
bool mac_sch_subpdu_nr::is_sdu()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// for UL-SCH LCID 52 is also valid for carrying SDUs
|
|
|
|
return (lcid <= 32);
|
|
|
|
return (lcid <= 32 || (parent->is_ulsch() && lcid == 52));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool mac_sch_subpdu_nr::has_length_field()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// CCCH (both versions) don't have a length field in the UL
|
|
|
|
|
|
|
|
if (parent->is_ulsch()) {
|
|
|
|
|
|
|
|
if (lcid == CCCH_SIZE_48 || lcid == CCCH_SIZE_64) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return (is_sdu() || is_var_len_ce(lcid));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// returns false for all reserved values in Table 6.2.1-1 and 6.2.1-2
|
|
|
|
// returns false for all reserved values in Table 6.2.1-1 and 6.2.1-2
|
|
|
@ -35,10 +45,16 @@ bool mac_sch_subpdu_nr::is_valid_lcid()
|
|
|
|
return (lcid <= 63 && ((parent->is_ulsch() && (lcid <= 32 || lcid >= 52)) || (lcid <= 32 || lcid >= 47)));
|
|
|
|
return (lcid <= 63 && ((parent->is_ulsch() && (lcid <= 32 || lcid >= 52)) || (lcid <= 32 || lcid >= 47)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool mac_sch_subpdu_nr::is_var_len_ce()
|
|
|
|
bool mac_sch_subpdu_nr::is_var_len_ce(uint32_t lcid)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (lcid) {
|
|
|
|
|
|
|
|
case LONG_TRUNC_BSR:
|
|
|
|
|
|
|
|
case LONG_BSR:
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// return length of PDU (or SRSRAN_ERROR otherwise)
|
|
|
|
// return length of PDU (or SRSRAN_ERROR otherwise)
|
|
|
|
int32_t mac_sch_subpdu_nr::read_subheader(const uint8_t* ptr)
|
|
|
|
int32_t mac_sch_subpdu_nr::read_subheader(const uint8_t* ptr)
|
|
|
@ -50,7 +66,7 @@ int32_t mac_sch_subpdu_nr::read_subheader(const uint8_t* ptr)
|
|
|
|
header_length = 1;
|
|
|
|
header_length = 1;
|
|
|
|
|
|
|
|
|
|
|
|
if (is_valid_lcid()) {
|
|
|
|
if (is_valid_lcid()) {
|
|
|
|
if ((is_sdu() || is_var_len_ce()) && not is_ul_ccch()) {
|
|
|
|
if (has_length_field()) {
|
|
|
|
// Read first length byte
|
|
|
|
// Read first length byte
|
|
|
|
sdu_length = (uint32_t)*ptr;
|
|
|
|
sdu_length = (uint32_t)*ptr;
|
|
|
|
ptr++;
|
|
|
|
ptr++;
|
|
|
@ -236,7 +252,7 @@ mac_sch_subpdu_nr::ta_t mac_sch_subpdu_nr::get_ta()
|
|
|
|
mac_sch_subpdu_nr::lcg_bsr_t mac_sch_subpdu_nr::get_sbsr()
|
|
|
|
mac_sch_subpdu_nr::lcg_bsr_t mac_sch_subpdu_nr::get_sbsr()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
lcg_bsr_t sbsr = {};
|
|
|
|
lcg_bsr_t sbsr = {};
|
|
|
|
if (parent->is_ulsch() && lcid == SHORT_BSR) {
|
|
|
|
if (parent->is_ulsch() && (lcid == SHORT_BSR || lcid == SHORT_TRUNC_BSR)) {
|
|
|
|
uint8_t* ptr = sdu.ptr();
|
|
|
|
uint8_t* ptr = sdu.ptr();
|
|
|
|
sbsr.lcg_id = (ptr[0] & 0xe0) >> 5;
|
|
|
|
sbsr.lcg_id = (ptr[0] & 0xe0) >> 5;
|
|
|
|
sbsr.buffer_size = ptr[0] & 0x1f;
|
|
|
|
sbsr.buffer_size = ptr[0] & 0x1f;
|
|
|
@ -244,6 +260,44 @@ mac_sch_subpdu_nr::lcg_bsr_t mac_sch_subpdu_nr::get_sbsr()
|
|
|
|
return sbsr;
|
|
|
|
return sbsr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mac_sch_subpdu_nr::lbsr_t mac_sch_subpdu_nr::get_lbsr()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lbsr_t lbsr = {};
|
|
|
|
|
|
|
|
lbsr.list.reserve(mac_sch_subpdu_nr::max_num_lcg_lbsr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (parent->is_ulsch() && (lcid == LONG_BSR || lcid == LONG_TRUNC_BSR)) {
|
|
|
|
|
|
|
|
uint8_t* ptr = sdu.ptr();
|
|
|
|
|
|
|
|
lbsr.bitmap = *ptr; // read LCG bitmap
|
|
|
|
|
|
|
|
ptr++; // skip LCG bitmap
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// early stop if LBSR is empty
|
|
|
|
|
|
|
|
if (lbsr.bitmap == 0) {
|
|
|
|
|
|
|
|
return lbsr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int bsr_cnt = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < mac_sch_subpdu_nr::max_num_lcg_lbsr; i++) {
|
|
|
|
|
|
|
|
// If LCGi bit is enabled, it means the next 8-bit BSR value corresponds to it
|
|
|
|
|
|
|
|
if (lbsr.bitmap & (0x1 << i)) {
|
|
|
|
|
|
|
|
lcg_bsr_t bsr = {};
|
|
|
|
|
|
|
|
bsr.lcg_id = i;
|
|
|
|
|
|
|
|
// For the Long truncated, some BSR words can be not present, assume BSR > 0 in that case
|
|
|
|
|
|
|
|
if (1 + bsr_cnt < sdu_length) {
|
|
|
|
|
|
|
|
bsr.buffer_size = ptr[bsr_cnt];
|
|
|
|
|
|
|
|
bsr_cnt++;
|
|
|
|
|
|
|
|
} else if (lcid == LONG_TRUNC_BSR) {
|
|
|
|
|
|
|
|
bsr.buffer_size = 63; // just assume it has 526 bytes to transmit
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
fprintf(stderr, "Error parsing LongBSR CE: sdu_length=%d but there are %d active bsr\n", sdu_length, bsr_cnt);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
lbsr.list.push_back(bsr);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return lbsr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t mac_sch_subpdu_nr::sizeof_ce(uint32_t lcid, bool is_ul)
|
|
|
|
uint32_t mac_sch_subpdu_nr::sizeof_ce(uint32_t lcid, bool is_ul)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (is_ul) {
|
|
|
|
if (is_ul) {
|
|
|
@ -307,9 +361,13 @@ void mac_sch_subpdu_nr::to_string(fmt::memory_buffer& buffer)
|
|
|
|
lcg_bsr_t sbsr = get_sbsr();
|
|
|
|
lcg_bsr_t sbsr = get_sbsr();
|
|
|
|
fmt::format_to(buffer, " SBSR: lcg={} bs={}", sbsr.lcg_id, sbsr.buffer_size);
|
|
|
|
fmt::format_to(buffer, " SBSR: lcg={} bs={}", sbsr.lcg_id, sbsr.buffer_size);
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
case mac_sch_subpdu_nr::LONG_BSR:
|
|
|
|
case mac_sch_subpdu_nr::LONG_BSR: {
|
|
|
|
fmt::format_to(buffer, " LBSR: len={}", get_total_length());
|
|
|
|
mac_sch_subpdu_nr::lbsr_t lbsr = get_lbsr();
|
|
|
|
break;
|
|
|
|
fmt::format_to(buffer, " LBSR: bitmap={:#02x}", lbsr.bitmap);
|
|
|
|
|
|
|
|
for (const auto& lcg : lbsr.list) {
|
|
|
|
|
|
|
|
fmt::format_to(buffer, " lcg={} bs={}", lcg.lcg_id, lcg.buffer_size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
|
|
|
case mac_sch_subpdu_nr::SE_PHR:
|
|
|
|
case mac_sch_subpdu_nr::SE_PHR:
|
|
|
|
fmt::format_to(buffer, " SE_PHR: ph={} pc={}", get_phr(), get_pcmax());
|
|
|
|
fmt::format_to(buffer, " SE_PHR: ph={} pc={}", get_phr(), get_pcmax());
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|