srsLTE/srsue/test/mac_test.cc

187 lines
6.5 KiB
C++
Raw Normal View History

2019-04-23 01:53:11 -07:00
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/common/log_filter.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srsue/hdr/mac/mac.h"
#include <assert.h>
#include <iostream>
using namespace srsue;
using namespace srslte;
#define TESTASSERT(cond) \
{ \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return SRSLTE_ERROR; \
} \
}
namespace srslte {
// fake classes
class rlc_dummy : public srsue::rlc_interface_mac
{
public:
rlc_dummy(srslte::log_filter* log_) : received_bytes(0), log(log_) {}
bool has_data(const uint32_t lcid) { return false; }
uint32_t get_buffer_state(const uint32_t lcid) { return 10; }
int read_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) { return 0; };
void write_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
{
log->debug_hex(payload, nof_bytes, "Received %d B on LCID %d\n", nof_bytes, lcid);
received_bytes += nof_bytes;
};
void write_pdu_bcch_bch(uint8_t* payload, uint32_t nof_bytes){};
void write_pdu_bcch_dlsch(uint8_t* payload, uint32_t nof_bytes){};
void write_pdu_pcch(uint8_t* payload, uint32_t nof_bytes){};
void write_pdu_mch(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes){};
uint32_t get_received_bytes() { return received_bytes; }
private:
uint32_t received_bytes;
srslte::log_filter* log;
};
class phy_dummy : public phy_interface_mac
{
public:
phy_dummy() : scell_cmd(0){};
// phy_interface_mac
void configure_prach_params(){};
virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm){};
prach_info_t prach_get_info()
{
prach_info_t info = {};
return info;
};
void sr_send(){};
int sr_last_tx_tti() { return 0; };
void set_mch_period_stop(uint32_t stop){};
// phy_interface_mac_common
void set_crnti(uint16_t rnti){};
void set_timeadv_rar(uint32_t ta_cmd){};
void set_timeadv(uint32_t ta_cmd){};
void set_activation_deactivation_scell(uint32_t cmd) { scell_cmd = cmd; };
void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rnti){};
uint32_t get_current_tti() { return 0; }
float get_phr() { return 0; };
float get_pathloss_db() { return 0; };
// getter for test execution
uint32_t get_scell_cmd() { return scell_cmd; }
private:
uint32_t scell_cmd;
};
class rrc_dummy : public rrc_interface_mac
{
public:
void ho_ra_completed(bool ra_successful) { printf("%s\n", __FUNCTION__); }
void release_pucch_srs() { printf("%s\n", __FUNCTION__); }
void run_tti(uint32_t tti) { printf("%s\n", __FUNCTION__); }
void ra_problem() { printf("%s\n", __FUNCTION__); }
};
} // namespace srslte
int mac_unpack_test()
{
// This MAC PDU contains three subheaders
const uint32_t mac_header_len = 4;
// Subheader 1 is SCell Activation/Deactivation CE
// - 1 byte SDU payload 0x02
const uint32_t mac_pdu1_len = 1;
// Subheader 2 is for LCID 1
// - 2 bytes SDU payload 0x00 0x08
const uint32_t mac_pdu2_len = 2;
// Subheader 3 is for LCID 3 (RLC AM PDU with 2 B header and 54 B data)
// - 56 bytes SDU payload 0x98 .. 0x89, 0x00, 0x00
const uint32_t mac_pdu3_len = 56;
uint8_t dl_sch_pdu[] = {0x3b, 0x21, 0x02, 0x03, 0x02, 0x00, 0x08, 0x98, 0x1b, 0x45, 0x00, 0x05, 0xda,
0xc7, 0x23, 0x40, 0x00, 0x40, 0x11, 0xe6, 0x9b, 0xc0, 0xa8, 0x03, 0x01, 0xc0,
0xa8, 0x03, 0x02, 0xd8, 0x29, 0x13, 0x89, 0x05, 0xc6, 0x2b, 0x73, 0x00, 0x0d,
0xc3, 0xb3, 0x5c, 0xa3, 0x23, 0xad, 0x00, 0x03, 0x20, 0x1b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x89, 0x00, 0x00};
srslte::log_filter rlc_log("RLC");
srslte::log_filter mac_log("MAC");
mac_log.set_level(srslte::LOG_LEVEL_DEBUG);
mac_log.set_hex_limit(100000);
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000);
// dummy layers
phy_dummy phy;
rlc_dummy rlc(&rlc_log);
rrc_dummy rrc;
// the actual MAC
mac mac;
mac.init(&phy, &rlc, &rrc, &mac_log);
// create dummy DL action and grant and push MAC PDU
mac_interface_phy::tb_action_dl_t dl_action;
mac_interface_phy::mac_grant_dl_t mac_grant;
bzero(&dl_action, sizeof(dl_action));
bzero(&mac_grant, sizeof(mac_grant));
mac_grant.rnti = 0xbeaf;
mac_grant.tb[0].tbs = sizeof(dl_sch_pdu);
int cc_idx = 0;
// Send grant to MAC and get action for this TB, then call tb_decoded to unlock MAC
mac.new_grant_dl(cc_idx, mac_grant, &dl_action);
// Copy PDU into provided buffer
bool dl_ack[SRSLTE_MAX_CODEWORDS] = {true, false};
memcpy(dl_action.tb[0].payload, dl_sch_pdu, sizeof(dl_sch_pdu));
dl_action.tb[0].enabled = true;
mac.tb_decoded(cc_idx, mac_grant, dl_ack);
// make sure MAC PDU thread picks up before stopping
sleep(1);
mac.run_tti(0);
mac.stop();
// check length of both received RLC PDUs
TESTASSERT(rlc.get_received_bytes() == mac_pdu2_len + mac_pdu3_len);
// check received SCell activation command
TESTASSERT(phy.get_scell_cmd() == 2);
return SRSLTE_SUCCESS;
}
int main(int argc, char** argv)
{
if (mac_unpack_test()) {
printf("MAC PDU unpack test failed.\n");
return -1;
}
return 0;
}