mirror of https://github.com/PentHertz/srsLTE.git
mac: implement MAC RAR PDU unpacking for NR
* add class for mac_rar_pdu_nr * extend test case
This commit is contained in:
parent
da9e3363f1
commit
f88943653b
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSLTE_MAC_RAR_PDU_NR_H
|
||||
#define SRSLTE_MAC_RAR_PDU_NR_H
|
||||
|
||||
#include "srslte/common/common.h"
|
||||
#include "srslte/config.h"
|
||||
#include "srslte/srslog/srslog.h"
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace srslte {
|
||||
|
||||
class mac_rar_pdu_nr;
|
||||
|
||||
// 3GPP 38.321 v15.3.0 Sec 6.1.5
|
||||
class mac_rar_subpdu_nr
|
||||
{
|
||||
public:
|
||||
// Possible types of RAR subpdus (same like EUTRA)
|
||||
typedef enum { BACKOFF = 0, RAPID } rar_subh_type_t;
|
||||
|
||||
mac_rar_subpdu_nr(mac_rar_pdu_nr* parent_);
|
||||
|
||||
// RAR content length in bits (38.321 Sec 6.2.3)
|
||||
static const uint32_t UL_GRANT_NBITS = 27;
|
||||
static const uint32_t TA_COMMAND_NBITS = 12;
|
||||
|
||||
// getter
|
||||
bool read_subpdu(const uint8_t* ptr);
|
||||
bool has_more_subpdus();
|
||||
uint32_t get_total_length();
|
||||
bool has_rapid();
|
||||
uint8_t get_rapid();
|
||||
uint16_t get_temp_crnti();
|
||||
uint32_t get_ta();
|
||||
void get_ul_grant(std::array<uint8_t, UL_GRANT_NBITS>& grant);
|
||||
|
||||
bool has_backoff();
|
||||
uint8_t get_backoff();
|
||||
|
||||
// setter
|
||||
uint32_t write_subpdu(const uint8_t* start_);
|
||||
void set_backoff(const uint8_t backoff_indicator_);
|
||||
|
||||
std::string to_string();
|
||||
|
||||
private:
|
||||
int header_length = 1; // RAR PDU subheader is always 1 B
|
||||
int payload_length = 0; // only used if MAC RAR is included
|
||||
|
||||
std::array<uint8_t, UL_GRANT_NBITS> ul_grant = {};
|
||||
uint16_t ta = 0; // 12bit TA
|
||||
uint16_t temp_crnti = 0;
|
||||
uint16_t rapid = 0;
|
||||
uint8_t backoff_indicator = 0;
|
||||
rar_subh_type_t type = BACKOFF;
|
||||
bool E_bit = 0;
|
||||
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
mac_rar_pdu_nr* parent = nullptr;
|
||||
};
|
||||
|
||||
class mac_rar_pdu_nr
|
||||
{
|
||||
public:
|
||||
mac_rar_pdu_nr();
|
||||
~mac_rar_pdu_nr() = default;
|
||||
|
||||
bool pack();
|
||||
bool unpack(const uint8_t* payload, const uint32_t& len);
|
||||
uint32_t get_num_subpdus();
|
||||
const mac_rar_subpdu_nr& get_subpdu(const uint32_t& index);
|
||||
|
||||
uint32_t get_remaining_len();
|
||||
|
||||
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();
|
||||
|
||||
std::string to_string();
|
||||
|
||||
private:
|
||||
std::vector<mac_rar_subpdu_nr> subpdus;
|
||||
uint32_t remaining_len = 0;
|
||||
uint16_t si_rapid = 0;
|
||||
bool si_rapid_set = false;
|
||||
srslog::basic_logger& logger;
|
||||
};
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
#endif // SRSLTE_MAC_RAR_PDU_NR_H
|
|
@ -9,7 +9,7 @@
|
|||
SET(SOURCES pdu.cc pdu_queue.cc)
|
||||
|
||||
if (ENABLE_5GNR)
|
||||
set(SOURCES ${SOURCES} mac_sch_pdu_nr.cc)
|
||||
set(SOURCES ${SOURCES} mac_sch_pdu_nr.cc mac_rar_pdu_nr.cc)
|
||||
endif(ENABLE_5GNR)
|
||||
|
||||
add_library(srslte_mac STATIC ${SOURCES})
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srslte/mac/mac_rar_pdu_nr.h"
|
||||
#include <sstream>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include "srslte/phy/utils/bit.h"
|
||||
#include "srslte/phy/utils/vector.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace srslte {
|
||||
|
||||
mac_rar_subpdu_nr::mac_rar_subpdu_nr(mac_rar_pdu_nr* parent_) :
|
||||
parent(parent_), logger(srslog::fetch_basic_logger("MAC"))
|
||||
{}
|
||||
|
||||
// Return true if subPDU could be parsed correctly, false otherwise
|
||||
bool mac_rar_subpdu_nr::read_subpdu(const uint8_t* ptr)
|
||||
{
|
||||
E_bit = (bool)(*ptr & 0x80) ? true : false;
|
||||
type = (*ptr & 0x40) ? RAPID : BACKOFF;
|
||||
if (type == RAPID) {
|
||||
rapid = *ptr & 0x3f;
|
||||
// if PDU is not configured with SI request, extract MAC RAR
|
||||
if (parent->has_si_rapid() == false) {
|
||||
const uint32_t MAC_RAR_NBYTES = 7;
|
||||
if (parent->get_remaining_len() >= MAC_RAR_NBYTES) {
|
||||
uint8_t* rar = const_cast<uint8_t*>(ptr + 1);
|
||||
// check reserved bits
|
||||
if (*rar & 0x80) {
|
||||
logger.error("Error parsing RAR PDU, reserved bit is set.");
|
||||
return false;
|
||||
}
|
||||
// TA is first 7 bits of 1st + 5 bits of 2nd octet
|
||||
ta = (uint16_t)(((*(rar + 0) & 0x7f) << 5 | ((*(rar + 1) & 0xf8) >> 3)));
|
||||
// Extract the first 3 bits of the UL grant from the 2nd octet
|
||||
ul_grant.at(0) = *(rar + 1) & 0x4 ? 1 : 0;
|
||||
ul_grant.at(1) = *(rar + 1) & 0x2 ? 1 : 0;
|
||||
ul_grant.at(2) = *(rar + 1) & 0x1 ? 1 : 0;
|
||||
// And now the remaining 3 full octets
|
||||
uint8_t* x = &ul_grant.at(3);
|
||||
srslte_bit_unpack(*(rar + 2), &x, 8);
|
||||
srslte_bit_unpack(*(rar + 3), &x, 8);
|
||||
srslte_bit_unpack(*(rar + 4), &x, 8);
|
||||
// Temp CRNTI is octet 6 + 7
|
||||
temp_crnti = ((uint16_t) * (rar + 5)) << 8 | *(rar + 6);
|
||||
payload_length = MAC_RAR_NBYTES;
|
||||
} else {
|
||||
logger.error("Error parsing RAR PDU, remaining bytes not sufficant (%d < %d)",
|
||||
parent->get_remaining_len(),
|
||||
MAC_RAR_NBYTES);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// check reserved bits
|
||||
if (*ptr & 0x10 || *ptr & 0x20) {
|
||||
logger.error("Error parsing RAR PDU, reserved bit is set.");
|
||||
return false;
|
||||
}
|
||||
backoff_indicator = *ptr & 0xf;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true if another subPDU follows after that
|
||||
bool mac_rar_subpdu_nr::has_more_subpdus()
|
||||
{
|
||||
return E_bit;
|
||||
}
|
||||
|
||||
// Section 6.1.2
|
||||
uint32_t mac_rar_subpdu_nr::write_subpdu(const uint8_t* start_)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t mac_rar_subpdu_nr::get_total_length()
|
||||
{
|
||||
return (header_length + payload_length);
|
||||
}
|
||||
|
||||
bool mac_rar_subpdu_nr::has_rapid()
|
||||
{
|
||||
return (type == rar_subh_type_t::RAPID);
|
||||
}
|
||||
|
||||
uint8_t mac_rar_subpdu_nr::get_rapid()
|
||||
{
|
||||
return rapid;
|
||||
}
|
||||
|
||||
uint32_t mac_rar_subpdu_nr::get_ta()
|
||||
{
|
||||
return ta;
|
||||
}
|
||||
|
||||
uint16_t mac_rar_subpdu_nr::get_temp_crnti()
|
||||
{
|
||||
return temp_crnti;
|
||||
}
|
||||
|
||||
bool mac_rar_subpdu_nr::has_backoff()
|
||||
{
|
||||
return (type == rar_subh_type_t::BACKOFF);
|
||||
}
|
||||
|
||||
void mac_rar_subpdu_nr::set_backoff(const uint8_t backoff_indicator_)
|
||||
{
|
||||
backoff_indicator = backoff_indicator_;
|
||||
}
|
||||
|
||||
void mac_rar_subpdu_nr::get_ul_grant(std::array<uint8_t, UL_GRANT_NBITS>& grant_)
|
||||
{
|
||||
grant_ = ul_grant;
|
||||
}
|
||||
|
||||
std::string mac_rar_subpdu_nr::to_string()
|
||||
{
|
||||
std::stringstream ss;
|
||||
if (has_rapid()) {
|
||||
ss << "RAPID: " << rapid << ", Temp C-RNTI: " << temp_crnti << ", TA: " << ta << ", UL Grant: ";
|
||||
} else {
|
||||
ss << "Backoff Indicator: " << backoff_indicator << " ";
|
||||
}
|
||||
|
||||
char tmp[16] = {};
|
||||
srslte_vec_sprint_hex(tmp, sizeof(tmp), ul_grant.data(), UL_GRANT_NBITS);
|
||||
ss << tmp;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
mac_rar_pdu_nr::mac_rar_pdu_nr() : logger(srslog::fetch_basic_logger("MAC")) {}
|
||||
|
||||
bool mac_rar_pdu_nr::pack()
|
||||
{
|
||||
// not implemented yet
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mac_rar_pdu_nr::has_si_rapid()
|
||||
{
|
||||
return si_rapid_set;
|
||||
}
|
||||
|
||||
void mac_rar_pdu_nr::set_si_rapid(uint16_t si_rapid_)
|
||||
{
|
||||
si_rapid = si_rapid_;
|
||||
si_rapid_set = true;
|
||||
}
|
||||
|
||||
// Return true if PDU could be parsed successfully
|
||||
bool mac_rar_pdu_nr::unpack(const uint8_t* payload, const uint32_t& len)
|
||||
{
|
||||
bool ret = false;
|
||||
bool have_more_subpdus = false;
|
||||
uint32_t offset = 0;
|
||||
|
||||
remaining_len = len;
|
||||
|
||||
do {
|
||||
mac_rar_subpdu_nr rar_subpdu(this);
|
||||
ret = rar_subpdu.read_subpdu(payload + offset);
|
||||
have_more_subpdus = rar_subpdu.has_more_subpdus();
|
||||
offset += rar_subpdu.get_total_length();
|
||||
remaining_len -= rar_subpdu.get_total_length();
|
||||
|
||||
// only append if subPDU could be read successfully
|
||||
if (ret == true) {
|
||||
subpdus.push_back(rar_subpdu);
|
||||
}
|
||||
// continue reading as long as subPDUs can be extracted ok and we are not overrunning the PDU length
|
||||
} while (ret && have_more_subpdus && offset <= len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t mac_rar_pdu_nr::get_num_subpdus()
|
||||
{
|
||||
return subpdus.size();
|
||||
}
|
||||
|
||||
const mac_rar_subpdu_nr& mac_rar_pdu_nr::get_subpdu(const uint32_t& index)
|
||||
{
|
||||
return subpdus.at(index);
|
||||
}
|
||||
|
||||
uint32_t mac_rar_pdu_nr::get_remaining_len()
|
||||
{
|
||||
return remaining_len;
|
||||
}
|
||||
|
||||
std::string mac_rar_pdu_nr::to_string()
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (auto& subpdu : subpdus) {
|
||||
ss << subpdu.to_string() << " ";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace srslte
|
|
@ -16,6 +16,6 @@ add_test(mac_pcap_test mac_pcap_test)
|
|||
|
||||
if (ENABLE_5GNR)
|
||||
add_executable(mac_pdu_nr_test mac_pdu_nr_test.cc)
|
||||
target_link_libraries(mac_pdu_nr_test srslte_phy srslte_mac srslte_common ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(mac_pdu_nr_test srslte_mac srslte_common ${CMAKE_THREAD_LIBS_INIT})
|
||||
add_test(mac_pdu_nr_test mac_pdu_nr_test)
|
||||
endif (ENABLE_5GNR)
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
|
||||
#include "srslte/common/log_filter.h"
|
||||
#include "srslte/common/mac_nr_pcap.h"
|
||||
#include "srslte/common/test_common.h"
|
||||
#include "srslte/config.h"
|
||||
#include "srslte/mac/mac_rar_pdu_nr.h"
|
||||
#include "srslte/mac/mac_sch_pdu_nr.h"
|
||||
|
||||
#include <array>
|
||||
|
@ -20,14 +22,6 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#define TESTASSERT(cond) \
|
||||
{ \
|
||||
if (!(cond)) { \
|
||||
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
|
||||
return -1; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PCAP 0
|
||||
#define PCAP_CRNTI (0x1001)
|
||||
#define PCAP_TTI (666)
|
||||
|
@ -260,6 +254,88 @@ int mac_dl_sch_pdu_unpack_test6()
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int mac_rar_pdu_unpack_test7()
|
||||
{
|
||||
// MAC PDU with RAR PDU with single RAPID=0
|
||||
// rapid=0
|
||||
// ta=180
|
||||
// ul_grant:
|
||||
// hopping_flag=0
|
||||
// riv=0x1
|
||||
// time_domain_rsc=1
|
||||
// mcs=4
|
||||
// tpc_command=3
|
||||
// csi_request=0
|
||||
// tc-rnti=0x4616
|
||||
|
||||
// Bit 1-8
|
||||
// | | | | | | | | |
|
||||
// | R |T=1| RAPID=0 | Octet 1
|
||||
// | RAR | Octet 2-8
|
||||
const uint32_t tv_rapid = 0;
|
||||
const uint32_t tv_ta = 180;
|
||||
const uint16_t tv_tcrnti = 0x4616;
|
||||
const uint8_t tv_msg3_grant[mac_rar_subpdu_nr::UL_GRANT_NBITS] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00}; // unpacked UL grant
|
||||
|
||||
uint8_t mac_dl_rar_pdu[] = {0x40, 0x05, 0xa0, 0x00, 0x11, 0x46, 0x46, 0x16, 0x00, 0x00, 0x00};
|
||||
|
||||
if (pcap_handle) {
|
||||
pcap_handle->write_dl_ra_rnti(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu), 0x0016, true, PCAP_TTI);
|
||||
}
|
||||
|
||||
srslte::mac_rar_pdu_nr pdu;
|
||||
TESTASSERT(pdu.unpack(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)) == true);
|
||||
|
||||
std::cout << pdu.to_string() << std::endl;
|
||||
|
||||
TESTASSERT(pdu.get_num_subpdus() == 1);
|
||||
|
||||
mac_rar_subpdu_nr subpdu = pdu.get_subpdu(0);
|
||||
TESTASSERT(subpdu.has_rapid() == true);
|
||||
TESTASSERT(subpdu.has_backoff() == false);
|
||||
TESTASSERT(subpdu.get_temp_crnti() == tv_tcrnti);
|
||||
TESTASSERT(subpdu.get_ta() == tv_ta);
|
||||
TESTASSERT(subpdu.get_rapid() == tv_rapid);
|
||||
|
||||
std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> msg3_grant;
|
||||
subpdu.get_ul_grant(msg3_grant);
|
||||
TESTASSERT(memcmp(msg3_grant.data(), tv_msg3_grant, msg3_grant.size()) == 0);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int mac_rar_pdu_unpack_test8()
|
||||
{
|
||||
// Malformed MAC PDU, says it has RAR PDU but is too short to include MAC RAR
|
||||
|
||||
// Bit 1-8
|
||||
// | | | | | | | | |
|
||||
// | E |T=1| RAPID=0 | Octet 1
|
||||
// | RAR_fragment | Octet 2
|
||||
uint8_t mac_dl_rar_pdu[] = {0x40, 0x05};
|
||||
|
||||
if (pcap_handle) {
|
||||
pcap_handle->write_dl_ra_rnti(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu), 0x0016, true, PCAP_TTI);
|
||||
}
|
||||
|
||||
// unpacking should fail
|
||||
srslte::mac_rar_pdu_nr pdu;
|
||||
TESTASSERT(pdu.unpack(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)) == false);
|
||||
TESTASSERT(pdu.get_num_subpdus() == 0);
|
||||
|
||||
// Malformed PDU with reserved bits set
|
||||
// Bit 1-8
|
||||
// | | | | | | | | |
|
||||
// | E |T=0| R | R | BI | Octet 1
|
||||
uint8_t mac_dl_rar_pdu2[] = {0x10};
|
||||
TESTASSERT(pdu.unpack(mac_dl_rar_pdu2, sizeof(mac_dl_rar_pdu2)) == false);
|
||||
TESTASSERT(pdu.get_num_subpdus() == 0);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int mac_ul_sch_pdu_unpack_test1()
|
||||
{
|
||||
// UL-SCH MAC PDU with fixed-size CE and DL-SCH subheader with 16-bit length field
|
||||
|
@ -498,6 +574,16 @@ int main(int argc, char** argv)
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (mac_rar_pdu_unpack_test7()) {
|
||||
fprintf(stderr, "mac_rar_pdu_unpack_test7() failed.\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (mac_rar_pdu_unpack_test8()) {
|
||||
fprintf(stderr, "mac_rar_pdu_unpack_test8() failed.\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (mac_ul_sch_pdu_unpack_test1()) {
|
||||
fprintf(stderr, "mac_ul_sch_pdu_unpack_test1() failed.\n");
|
||||
return SRSLTE_ERROR;
|
||||
|
|
Loading…
Reference in New Issue