mac_sch_pdu_nr: add LBSR unpacking

* add LBSR unpacking
* add pretty printer
* also simplify and unify general unpacking code
master
Andre Puschmann 3 years ago
parent cc87af2986
commit af69551c8d

@ -59,7 +59,7 @@ public:
nr_lcid_sch_t get_type(); nr_lcid_sch_t get_type();
bool is_sdu(); bool is_sdu();
bool is_valid_lcid(); bool is_valid_lcid();
bool is_var_len_ce(); bool is_var_len_ce(uint32_t lcid);
bool is_ul_ccch(); bool is_ul_ccch();
int32_t read_subheader(const uint8_t* ptr); int32_t read_subheader(const uint8_t* ptr);
@ -78,9 +78,13 @@ public:
uint8_t lcg_id; uint8_t lcg_id;
uint8_t buffer_size; uint8_t buffer_size;
}; };
lcg_bsr_t get_sbsr(); lcg_bsr_t get_sbsr();
static const uint8_t max_num_lcg_lbsr = 8; static const uint8_t max_num_lcg_lbsr = 8;
std::array<lcg_bsr_t, max_num_lcg_lbsr> get_lbsr(); struct lbsr_t {
uint8_t bitmap; // the first octet of LBSR and Long Trunc BSR
std::vector<lcg_bsr_t> list; // one entry for each reported LCG
};
lbsr_t get_lbsr();
// TA // TA
struct ta_t { struct ta_t {
@ -107,6 +111,9 @@ public:
private: private:
srslog::basic_logger* logger; srslog::basic_logger* logger;
// internal helpers
bool has_length_field();
uint32_t lcid = 0; uint32_t lcid = 0;
int header_length = 0; int header_length = 0;
int sdu_length = 0; int sdu_length = 0;

@ -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,9 +45,15 @@ 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)
{ {
return false; switch (lcid) {
case LONG_TRUNC_BSR:
case LONG_BSR:
return true;
default:
return false;
}
} }
// return length of PDU (or SRSRAN_ERROR otherwise) // return length of PDU (or SRSRAN_ERROR otherwise)
@ -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;

Loading…
Cancel
Save