mac_rar_pdu_nr: add packing routines

* add packing for RAR PDUs
* rewrite to_string() to use fmt lib
* add test case for packer
master
Andre Puschmann 3 years ago
parent b20fefbe45
commit ede81be5e4

@ -13,6 +13,7 @@
#ifndef SRSRAN_MAC_RAR_PDU_NR_H #ifndef SRSRAN_MAC_RAR_PDU_NR_H
#define SRSRAN_MAC_RAR_PDU_NR_H #define SRSRAN_MAC_RAR_PDU_NR_H
#include "srsran/common/byte_buffer.h"
#include "srsran/common/common.h" #include "srsran/common/common.h"
#include "srsran/config.h" #include "srsran/config.h"
#include "srsran/phy/common/phy_common_nr.h" #include "srsran/phy/common/phy_common_nr.h"
@ -51,12 +52,19 @@ public:
uint8_t get_backoff() const; uint8_t get_backoff() const;
// setter // setter
uint32_t write_subpdu(const uint8_t* start_); void write_subpdu(const uint8_t* start_);
void set_backoff(const uint8_t backoff_indicator_); void set_backoff(const uint8_t backoff_indicator_);
void set_ta(const uint32_t ta_);
void set_temp_crnti(const uint16_t temp_crnti_);
void set_rapid(const uint8_t rapid_);
void set_ul_grant(std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> ul_grant_);
void set_is_last_subpdu();
std::string to_string(); void to_string(fmt::memory_buffer& buffer);
private: private:
const uint32_t MAC_RAR_NBYTES = 7; // see TS 38.321 Sec 6.2.3
int header_length = 1; // RAR PDU subheader is always 1 B int header_length = 1; // RAR PDU subheader is always 1 B
int payload_length = 0; // only used if MAC RAR is included int payload_length = 0; // only used if MAC RAR is included
@ -66,7 +74,7 @@ private:
uint16_t rapid = 0; uint16_t rapid = 0;
uint8_t backoff_indicator = 0; uint8_t backoff_indicator = 0;
rar_subh_type_t type = BACKOFF; rar_subh_type_t type = BACKOFF;
bool E_bit = 0; bool E_bit = true;
srslog::basic_logger& logger; srslog::basic_logger& logger;
@ -79,7 +87,8 @@ public:
mac_rar_pdu_nr(); mac_rar_pdu_nr();
~mac_rar_pdu_nr() = default; ~mac_rar_pdu_nr() = default;
bool pack(); int init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_);
int pack();
bool unpack(const uint8_t* payload, const uint32_t& len); bool unpack(const uint8_t* payload, const uint32_t& len);
uint32_t get_num_subpdus(); uint32_t get_num_subpdus();
// Returns reference to a single subPDU // Returns reference to a single subPDU
@ -92,13 +101,20 @@ public:
void set_si_rapid(uint16_t si_rapid_); // configured through SIB1 for on-demand SI request (See 38.331 Sec 5.2.1) void set_si_rapid(uint16_t si_rapid_); // configured through SIB1 for on-demand SI request (See 38.331 Sec 5.2.1)
bool has_si_rapid(); bool has_si_rapid();
std::string to_string(); // returns reference to added RAR subPDU
mac_rar_subpdu_nr& add_subpdu();
void to_string(fmt::memory_buffer& buffer);
private: private:
std::vector<mac_rar_subpdu_nr> subpdus; std::vector<mac_rar_subpdu_nr> subpdus;
uint32_t pdu_len = 0;
uint32_t remaining_len = 0; uint32_t remaining_len = 0;
uint16_t si_rapid = 0; uint16_t si_rapid = 0;
bool si_rapid_set = false; bool si_rapid_set = false;
byte_buffer_t* buffer = nullptr;
srslog::basic_logger& logger; srslog::basic_logger& logger;
}; };

@ -34,7 +34,6 @@ bool mac_rar_subpdu_nr::read_subpdu(const uint8_t* ptr)
rapid = *ptr & 0x3f; rapid = *ptr & 0x3f;
// if PDU is not configured with SI request, extract MAC RAR // if PDU is not configured with SI request, extract MAC RAR
if (parent->has_si_rapid() == false) { if (parent->has_si_rapid() == false) {
const uint32_t MAC_RAR_NBYTES = 7;
if (parent->get_remaining_len() >= MAC_RAR_NBYTES) { if (parent->get_remaining_len() >= MAC_RAR_NBYTES) {
uint8_t* rar = const_cast<uint8_t*>(ptr + 1); uint8_t* rar = const_cast<uint8_t*>(ptr + 1);
// check reserved bits // check reserved bits
@ -81,9 +80,42 @@ bool mac_rar_subpdu_nr::has_more_subpdus()
} }
// Section 6.1.2 // Section 6.1.2
uint32_t mac_rar_subpdu_nr::write_subpdu(const uint8_t* start_) void mac_rar_subpdu_nr::write_subpdu(const uint8_t* start_)
{ {
return 0; uint8_t* ptr = const_cast<uint8_t*>(start_);
if (type == RAPID) {
// write E/T/RAPID MAC subheader
*ptr = (uint8_t)((E_bit ? 1 : 0) << 7) | ((int)rar_subh_type_t::RAPID << 6) | ((uint8_t)rapid & 0x3f);
ptr += 1;
// if PDU is not configured with SI request, insert MAC RAR
if (parent->has_si_rapid() == false) {
// high 7 bits of TA go into first octet
*ptr = (uint8_t)((ta >> 5) & 0x7f);
ptr += 1;
// low 5 bit of TA and first 3 bit of UL grant
*ptr = (uint8_t)((ta & 0x1f) << 3) | (ul_grant.at(0) << 2) | (ul_grant.at(1) << 1) | (ul_grant.at(2));
ptr += 1;
// add remaining 3 full octets of UL grant
uint8_t* x = &ul_grant.at(3);
*(ptr + 0) = (uint8_t)srsran_bit_pack(&x, 8);
*(ptr + 1) = (uint8_t)srsran_bit_pack(&x, 8);
*(ptr + 2) = (uint8_t)srsran_bit_pack(&x, 8);
ptr += 3;
// 2 byte C-RNTI
*(ptr + 0) = (uint8_t)((temp_crnti & 0xff00) >> 8);
*(ptr + 1) = (uint8_t)(temp_crnti & 0x00ff);
ptr += 2;
}
} else {
// write E/T/R/R/BI MAC subheader
*ptr = (uint8_t)((E_bit ? 1 : 0) << 7) | ((int)rar_subh_type_t::BACKOFF << 6) | ((uint8_t)backoff_indicator & 0xf);
ptr += 1;
}
} }
uint32_t mac_rar_subpdu_nr::get_total_length() uint32_t mac_rar_subpdu_nr::get_total_length()
@ -118,6 +150,8 @@ bool mac_rar_subpdu_nr::has_backoff() const
void mac_rar_subpdu_nr::set_backoff(const uint8_t backoff_indicator_) void mac_rar_subpdu_nr::set_backoff(const uint8_t backoff_indicator_)
{ {
type = rar_subh_type_t::BACKOFF;
payload_length = 0;
backoff_indicator = backoff_indicator_; backoff_indicator = backoff_indicator_;
} }
@ -131,28 +165,99 @@ std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> mac_rar_subpdu_nr::get_ul
return ul_grant; return ul_grant;
} }
std::string mac_rar_subpdu_nr::to_string() void mac_rar_subpdu_nr::set_ta(const uint32_t ta_)
{
ta = ta_;
}
void mac_rar_subpdu_nr::set_temp_crnti(const uint16_t temp_crnti_)
{
temp_crnti = temp_crnti_;
}
void mac_rar_subpdu_nr::set_rapid(const uint8_t rapid_)
{
type = rar_subh_type_t::RAPID;
payload_length = MAC_RAR_NBYTES;
rapid = rapid_;
}
void mac_rar_subpdu_nr::set_ul_grant(std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> ul_grant_)
{
ul_grant = ul_grant_;
}
void mac_rar_subpdu_nr::set_is_last_subpdu()
{ {
std::stringstream ss; E_bit = false;
}
void mac_rar_subpdu_nr::to_string(fmt::memory_buffer& buffer)
{
// Add space for new subPDU
fmt::format_to(buffer, " ");
if (has_rapid()) { if (has_rapid()) {
ss << "RAPID: " << rapid << ", Temp C-RNTI: " << std::hex << temp_crnti << ", TA: " << ta << ", UL Grant: "; char tmp[16] = {};
srsran_vec_sprint_hex(tmp, sizeof(tmp), ul_grant.data(), UL_GRANT_NBITS);
fmt::format_to(buffer, "RAPID: {}, Temp C-RNTI: {:#04x}, TA: {}, UL Grant: {}", rapid, temp_crnti, ta, tmp);
} else { } else {
ss << "Backoff Indicator: " << backoff_indicator << " "; fmt::format_to(buffer, "Backoff Indicator: {}", backoff_indicator);
} }
}
char tmp[16] = {}; mac_rar_pdu_nr::mac_rar_pdu_nr() : logger(srslog::fetch_basic_logger("MAC-NR")) {}
srsran_vec_sprint_hex(tmp, sizeof(tmp), ul_grant.data(), UL_GRANT_NBITS);
ss << tmp;
return ss.str(); int mac_rar_pdu_nr::init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_)
{
if (buffer_ == nullptr || buffer_->msg == nullptr) {
logger.error("Invalid buffer");
return SRSRAN_ERROR;
}
buffer = buffer_;
subpdus.clear();
pdu_len = pdu_len_;
remaining_len = pdu_len_;
return SRSRAN_SUCCESS;
} }
mac_rar_pdu_nr::mac_rar_pdu_nr() : logger(srslog::fetch_basic_logger("MAC-NR")) {} mac_rar_subpdu_nr& mac_rar_pdu_nr::add_subpdu()
{
mac_rar_subpdu_nr rar_subpdu(this);
subpdus.push_back(rar_subpdu);
return subpdus.back();
}
bool mac_rar_pdu_nr::pack() int mac_rar_pdu_nr::pack()
{ {
// not implemented yet int ret = SRSRAN_ERROR;
return false; if (buffer == nullptr) {
logger.error("Invalid buffer");
return ret;
}
// set E_bit for last subPDU
subpdus.back().set_is_last_subpdu();
// write subPDUs one by one
for (uint32_t i = 0; i < subpdus.size(); ++i) {
mac_rar_subpdu_nr& subpdu = subpdus.at(i);
if (remaining_len >= subpdu.get_total_length()) {
subpdu.write_subpdu(buffer->msg + buffer->N_bytes);
buffer->N_bytes += subpdu.get_total_length();
remaining_len -= subpdu.get_total_length();
} else {
logger.error("Not enough space in PDU to write subPDU");
return ret;
}
}
// fill up with padding, if any
buffer->N_bytes += remaining_len;
ret = SRSRAN_SUCCESS;
return ret;
} }
bool mac_rar_pdu_nr::has_si_rapid() bool mac_rar_pdu_nr::has_si_rapid()
@ -212,13 +317,12 @@ uint32_t mac_rar_pdu_nr::get_remaining_len()
return remaining_len; return remaining_len;
} }
std::string mac_rar_pdu_nr::to_string() void mac_rar_pdu_nr::to_string(fmt::memory_buffer& buffer)
{ {
std::stringstream ss; fmt::format_to(buffer, "DL");
for (auto& subpdu : subpdus) { for (auto& subpdu : subpdus) {
ss << subpdu.to_string() << " "; subpdu.to_string(buffer);
} }
return ss.str();
} }
} // namespace srsran } // namespace srsran

@ -24,6 +24,7 @@
#define PCAP 0 #define PCAP 0
#define PCAP_CRNTI (0x1001) #define PCAP_CRNTI (0x1001)
#define PCAP_RAR_RNTI (0x0016)
#define PCAP_TTI (666) #define PCAP_TTI (666)
using namespace srsran; using namespace srsran;
@ -251,7 +252,7 @@ int mac_dl_sch_pdu_unpack_test6()
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
int mac_rar_pdu_unpack_test7() int mac_rar_pdu_test7()
{ {
// MAC PDU with RAR PDU with single RAPID=0 // MAC PDU with RAR PDU with single RAPID=0
// rapid=0 // rapid=0
@ -279,13 +280,17 @@ int mac_rar_pdu_unpack_test7()
uint8_t mac_dl_rar_pdu[] = {0x40, 0x05, 0xa0, 0x00, 0x11, 0x46, 0x46, 0x16, 0x00, 0x00, 0x00}; uint8_t mac_dl_rar_pdu[] = {0x40, 0x05, 0xa0, 0x00, 0x11, 0x46, 0x46, 0x16, 0x00, 0x00, 0x00};
if (pcap_handle) { if (pcap_handle) {
pcap_handle->write_dl_ra_rnti_nr(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu), 0x0016, true, PCAP_TTI); pcap_handle->write_dl_ra_rnti_nr(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu), PCAP_RAR_RNTI, true, PCAP_TTI);
} }
srsran::mac_rar_pdu_nr pdu; srsran::mac_rar_pdu_nr pdu;
TESTASSERT(pdu.unpack(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)) == true); TESTASSERT(pdu.unpack(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)) == true);
std::cout << pdu.to_string() << std::endl; fmt::memory_buffer buff;
pdu.to_string(buff);
auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.info("Rx PDU: %s", srsran::to_c_str(buff));
TESTASSERT(pdu.get_num_subpdus() == 1); TESTASSERT(pdu.get_num_subpdus() == 1);
@ -299,6 +304,31 @@ int mac_rar_pdu_unpack_test7()
std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> msg3_grant = subpdu.get_ul_grant(); std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> msg3_grant = subpdu.get_ul_grant();
TESTASSERT(memcmp(msg3_grant.data(), tv_msg3_grant, msg3_grant.size()) == 0); TESTASSERT(memcmp(msg3_grant.data(), tv_msg3_grant, msg3_grant.size()) == 0);
// pack again
const uint32_t pdu_size = 11;
byte_buffer_t tx_buffer;
tx_buffer.clear();
srsran::mac_rar_pdu_nr tx_pdu;
tx_pdu.init_tx(&tx_buffer, pdu_size);
mac_rar_subpdu_nr& rar_subpdu = tx_pdu.add_subpdu();
rar_subpdu.set_ta(tv_ta);
rar_subpdu.set_rapid(tv_rapid);
rar_subpdu.set_temp_crnti(tv_tcrnti);
rar_subpdu.set_ul_grant(msg3_grant);
TESTASSERT(tx_pdu.pack() == SRSRAN_SUCCESS);
TESTASSERT(tx_buffer.N_bytes == sizeof(mac_dl_rar_pdu));
TESTASSERT(memcmp(tx_buffer.msg, mac_dl_rar_pdu, tx_buffer.N_bytes) == 0);
tx_pdu.to_string(buff);
mac_logger.info("Tx PDU: %s", srsran::to_c_str(buff));
if (pcap_handle) {
pcap_handle->write_dl_ra_rnti_nr(tx_buffer.msg, tx_buffer.N_bytes, PCAP_RAR_RNTI, true, PCAP_TTI);
}
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
@ -599,7 +629,7 @@ int mac_dl_sch_pdu_unpack_and_pack_test6()
pdu_rx.to_string(buff); pdu_rx.to_string(buff);
auto& mac_logger = srslog::fetch_basic_logger("MAC"); auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.info("Received PDU: %s", srsran::to_c_str(buff)); mac_logger.info("Rx PDU: %s", srsran::to_c_str(buff));
} }
// Let's pack the entire PDU again // Let's pack the entire PDU again
@ -625,6 +655,13 @@ int mac_dl_sch_pdu_unpack_and_pack_test6()
// finish PDU packing // finish PDU packing
pdu_tx.pack(); pdu_tx.pack();
// pretty print PDU
fmt::memory_buffer buff;
pdu_tx.to_string(buff);
auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.info("Tx PDU: %s", srsran::to_c_str(buff));
// compare PDUs // compare PDUs
TESTASSERT(tx_buffer.N_bytes == sizeof(tv)); TESTASSERT(tx_buffer.N_bytes == sizeof(tv));
TESTASSERT(memcmp(tx_buffer.msg, tv, tx_buffer.N_bytes) == 0); TESTASSERT(memcmp(tx_buffer.msg, tv, tx_buffer.N_bytes) == 0);
@ -705,7 +742,7 @@ int main(int argc, char** argv)
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
if (mac_rar_pdu_unpack_test7()) { if (mac_rar_pdu_test7()) {
fprintf(stderr, "mac_rar_pdu_unpack_test7() failed.\n"); fprintf(stderr, "mac_rar_pdu_unpack_test7() failed.\n");
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
@ -759,5 +796,7 @@ int main(int argc, char** argv)
pcap_handle->close(); pcap_handle->close();
} }
srslog::flush();
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }

@ -196,7 +196,10 @@ void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::tb_action_dl_
logger.warning("Error unpacking RAR PDU"); logger.warning("Error unpacking RAR PDU");
return; return;
} }
logger.info("%s", pdu.to_string());
fmt::memory_buffer buff;
pdu.to_string(buff);
logger.info("%s", srsran::to_c_str(buff));
for (auto& subpdu : pdu.get_subpdus()) { for (auto& subpdu : pdu.get_subpdus()) {
if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) { if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) {

Loading…
Cancel
Save