From af69551c8d74941c2817313bf0cb54f0dfd8a027 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 15 Oct 2021 16:46:59 +0200 Subject: [PATCH] mac_sch_pdu_nr: add LBSR unpacking * add LBSR unpacking * add pretty printer * also simplify and unify general unpacking code --- lib/include/srsran/mac/mac_sch_pdu_nr.h | 15 +++-- lib/src/mac/mac_sch_pdu_nr.cc | 76 ++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/lib/include/srsran/mac/mac_sch_pdu_nr.h b/lib/include/srsran/mac/mac_sch_pdu_nr.h index fb15b1768..7b3114d5f 100644 --- a/lib/include/srsran/mac/mac_sch_pdu_nr.h +++ b/lib/include/srsran/mac/mac_sch_pdu_nr.h @@ -59,7 +59,7 @@ public: nr_lcid_sch_t get_type(); bool is_sdu(); bool is_valid_lcid(); - bool is_var_len_ce(); + bool is_var_len_ce(uint32_t lcid); bool is_ul_ccch(); int32_t read_subheader(const uint8_t* ptr); @@ -78,9 +78,13 @@ public: uint8_t lcg_id; uint8_t buffer_size; }; - lcg_bsr_t get_sbsr(); - static const uint8_t max_num_lcg_lbsr = 8; - std::array get_lbsr(); + lcg_bsr_t get_sbsr(); + static const uint8_t max_num_lcg_lbsr = 8; + struct lbsr_t { + uint8_t bitmap; // the first octet of LBSR and Long Trunc BSR + std::vector list; // one entry for each reported LCG + }; + lbsr_t get_lbsr(); // TA struct ta_t { @@ -107,6 +111,9 @@ public: private: srslog::basic_logger* logger; + // internal helpers + bool has_length_field(); + uint32_t lcid = 0; int header_length = 0; int sdu_length = 0; diff --git a/lib/src/mac/mac_sch_pdu_nr.cc b/lib/src/mac/mac_sch_pdu_nr.cc index 28645ff0b..e9f6b4f3a 100644 --- a/lib/src/mac/mac_sch_pdu_nr.cc +++ b/lib/src/mac/mac_sch_pdu_nr.cc @@ -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() { - // for UL-SCH LCID 52 is also valid for carrying SDUs - return (lcid <= 32 || (parent->is_ulsch() && lcid == 52)); + return (lcid <= 32); +} + +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 @@ -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))); } -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) @@ -50,7 +66,7 @@ int32_t mac_sch_subpdu_nr::read_subheader(const uint8_t* ptr) header_length = 1; if (is_valid_lcid()) { - if ((is_sdu() || is_var_len_ce()) && not is_ul_ccch()) { + if (has_length_field()) { // Read first length byte sdu_length = (uint32_t)*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() { 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(); sbsr.lcg_id = (ptr[0] & 0xe0) >> 5; 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; } +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) { if (is_ul) { @@ -307,9 +361,13 @@ void mac_sch_subpdu_nr::to_string(fmt::memory_buffer& buffer) lcg_bsr_t sbsr = get_sbsr(); fmt::format_to(buffer, " SBSR: lcg={} bs={}", sbsr.lcg_id, sbsr.buffer_size); } break; - case mac_sch_subpdu_nr::LONG_BSR: - fmt::format_to(buffer, " LBSR: len={}", get_total_length()); - break; + case mac_sch_subpdu_nr::LONG_BSR: { + mac_sch_subpdu_nr::lbsr_t lbsr = get_lbsr(); + 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: fmt::format_to(buffer, " SE_PHR: ph={} pc={}", get_phr(), get_pcmax()); break;