diff --git a/lib/include/srslte/common/mac_nr_pdu.h b/lib/include/srslte/common/mac_nr_pdu.h index f7363785f..883228630 100644 --- a/lib/include/srslte/common/mac_nr_pdu.h +++ b/lib/include/srslte/common/mac_nr_pdu.h @@ -37,6 +37,7 @@ public: // 3GPP 38.321 v15.3.0 Combined Tables 6.2.1-1, 6.2.1-2 typedef enum { // Values for DL-SCH + CCCH = 0b000000, DRX_CMD = 0b111100, TA_CMD = 0b111101, CON_RES_ID = 0b111110, @@ -45,12 +46,13 @@ public: CRNTI = 0b111010, SHORT_TRUNC_BSR = 0b111011, LONG_TRUNC_BSR = 0b111100, + CCCH_SIZE_48 = 0b110100, + CCCH_SIZE_64 = 0b000000, SHORT_BSR = 0b111101, LONG_BSR = 0b111110, // Common - CCCH = 0b000000, PADDING = 0b111111, } nr_lcid_sch_t; @@ -59,6 +61,7 @@ public: nr_lcid_sch_t get_type(); bool is_sdu(); bool is_var_len_ce(); + bool is_ul_ccch(); uint32_t read_subheader(const uint8_t* ptr); uint32_t get_total_length(); @@ -103,7 +106,7 @@ public: uint32_t get_remaing_len(); private: - uint32_t size_header_sdu(const uint32_t nbytes); + uint32_t size_header_sdu(const uint32_t lcid_, const uint32_t nbytes); bool ulsch = false; std::vector subpdus; diff --git a/lib/src/common/mac_nr_pdu.cc b/lib/src/common/mac_nr_pdu.cc index 8b0878709..478a448f5 100644 --- a/lib/src/common/mac_nr_pdu.cc +++ b/lib/src/common/mac_nr_pdu.cc @@ -53,7 +53,7 @@ uint32_t mac_nr_sch_subpdu::read_subheader(const uint8_t* ptr) ptr++; header_length = 1; - if (is_sdu() || is_var_len_ce()) { + if ((is_sdu() || is_var_len_ce()) && not is_ul_ccch()) { // Read first length byte sdu_length = (uint32_t)*ptr; ptr++; @@ -76,8 +76,15 @@ void mac_nr_sch_subpdu::set_sdu(const uint32_t lcid_, const uint8_t* payload_, c { lcid = lcid_; sdu = const_cast(payload_); + header_length = is_ul_ccch() ? 1 : 2; sdu_length = len_; - header_length = 2; + if (is_ul_ccch()) { + F_bit = false; + sdu_length = sizeof_ce(lcid, parent->is_ulsch()); + if (len_ != static_cast(sdu_length)) { + fprintf(stderr, "Invalid SDU length of UL-SCH SDU (%d != %d)\n", len_, sdu_length); + } + } if (sdu_length >= 256) { F_bit = true; @@ -153,32 +160,41 @@ uint8_t* mac_nr_sch_subpdu::get_sdu() uint32_t mac_nr_sch_subpdu::sizeof_ce(uint32_t lcid, bool is_ul) { - if (is_ul) { - switch (lcid) { - case CRNTI: - return 2; - case SHORT_TRUNC_BSR: - return 1; - case SHORT_BSR: - return 1; - case PADDING: - return 0; - } - } else { - switch (lcid) { - case CON_RES_ID: - return 6; - case TA_CMD: - return 1; - case DRX_CMD: - return 0; - case PADDING: - return 0; - } + if (is_ul) { + switch (lcid) { + case CCCH_SIZE_48: + return 6; + case CCCH_SIZE_64: + return 8; + case CRNTI: + return 2; + case SHORT_TRUNC_BSR: + return 1; + case SHORT_BSR: + return 1; + case PADDING: + return 0; + } + } else { + switch (lcid) { + case CON_RES_ID: + return 6; + case TA_CMD: + return 1; + case DRX_CMD: + return 0; + case PADDING: + return 0; } + } return 0; } +inline bool mac_nr_sch_subpdu::is_ul_ccch() +{ + return (parent->is_ulsch() && (lcid == CCCH_SIZE_48 || lcid == CCCH_SIZE_64)); +} + void mac_nr_sch_pdu::pack() { // SDUs are written in place, only add padding if needed @@ -231,12 +247,16 @@ void mac_nr_sch_pdu::init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool uls ulsch = ulsch_; } -uint32_t mac_nr_sch_pdu::size_header_sdu(const uint32_t nbytes) +uint32_t mac_nr_sch_pdu::size_header_sdu(const uint32_t lcid, const uint32_t nbytes) { - if (nbytes < 256) { - return 2; + if (ulsch && (lcid == mac_nr_sch_subpdu::CCCH_SIZE_48 || lcid == mac_nr_sch_subpdu::CCCH_SIZE_64)) { + return 1; } else { - return 3; + if (nbytes < 256) { + return 2; + } else { + return 3; + } } } @@ -247,7 +267,7 @@ uint32_t mac_nr_sch_pdu::get_remaing_len() uint32_t mac_nr_sch_pdu::add_sdu(const uint32_t lcid_, const uint8_t* payload_, const uint32_t len_) { - int header_size = size_header_sdu(len_); + int header_size = size_header_sdu(lcid_, len_); if (header_size + len_ > remaining_len) { printf("Header and SDU exceed space in PDU (%d > %d).\n", header_size + len_, remaining_len); diff --git a/lib/test/common/mac_nr_pdu_test.cc b/lib/test/common/mac_nr_pdu_test.cc index e79e0dac0..19ff9f776 100644 --- a/lib/test/common/mac_nr_pdu_test.cc +++ b/lib/test/common/mac_nr_pdu_test.cc @@ -289,6 +289,54 @@ int mac_ul_sch_pdu_unpack_test1() return SRSLTE_SUCCESS; } +int mac_ul_sch_pdu_unpack_and_pack_test2() +{ + // MAC PDU with UL-SCH (for UL-CCCH) subheader + // Bit 1-8 + // | | | | | | | | | + // | R | R | LCID | Octet 1 + + // TV1 - MAC PDU with short subheader for CCCH, MAC SDU length is 8 B, total PDU is 10 B + uint8_t mac_ul_sch_pdu_1[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + + if (pcap_handle) { + pcap_handle->write_ul_crnti(mac_ul_sch_pdu_1, sizeof(mac_ul_sch_pdu_1), PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::mac_nr_sch_pdu pdu(true); + pdu.unpack(mac_ul_sch_pdu_1, sizeof(mac_ul_sch_pdu_1)); + TESTASSERT(pdu.get_num_subpdus() == 1); + + mac_nr_sch_subpdu subpdu = pdu.get_subpdu(0); + TESTASSERT(subpdu.get_total_length() == 9); + TESTASSERT(subpdu.get_sdu_length() == 8); + TESTASSERT(subpdu.get_lcid() == 0); + + // pack PDU again + byte_buffer_t tx_buffer; + + srslte::mac_nr_sch_pdu tx_pdu; + tx_pdu.init_tx(&tx_buffer, sizeof(mac_ul_sch_pdu_1), true); + + // Add SDU part of TV from above + tx_pdu.add_sdu(0, &mac_ul_sch_pdu_1[1], 8); + + TESTASSERT(tx_pdu.get_remaing_len() == 0); + TESTASSERT(tx_buffer.N_bytes == sizeof(mac_ul_sch_pdu_1)); + TESTASSERT(memcmp(tx_buffer.msg, mac_ul_sch_pdu_1, tx_buffer.N_bytes) == 0); + + if (pcap_handle) { + pcap_handle->write_ul_crnti(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::log_filter log("MAC"); + log.set_level(srslte::LOG_LEVEL_DEBUG); + log.set_hex_limit(100000); + log.info_hex(tx_buffer.msg, tx_buffer.N_bytes, "Generated MAC PDU (%d B)\n", tx_buffer.N_bytes); + + return SRSLTE_SUCCESS; +} + int main(int argc, char** argv) { #if PCAP @@ -326,5 +374,10 @@ int main(int argc, char** argv) return SRSLTE_ERROR; } + if (mac_ul_sch_pdu_unpack_and_pack_test2()) { + fprintf(stderr, "mac_ul_sch_pdu_unpack_and_pack_test2() failed.\n"); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; }