ttcn3: split SS interface and protect SS main thread properly

the SS main thread and the provided interaces weren't protecting members
correctly
master
Andre Puschmann 5 years ago
parent 80ef7f8497
commit 487fdd5616

@ -25,8 +25,8 @@
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/interfaces/ue_interfaces.h" #include "srslte/interfaces/ue_interfaces.h"
// Interface used by system interface to communicate with main component // Interfaces used by system interface to communicate with main component
class syssim_interface class ss_ut_interface
{ {
public: public:
virtual void tc_start(const char* name) = 0; virtual void tc_start(const char* name) = 0;
@ -36,12 +36,15 @@ public:
virtual void switch_off_ue() = 0; virtual void switch_off_ue() = 0;
virtual void enable_data() = 0; virtual void enable_data() = 0;
virtual void disable_data() = 0; virtual void disable_data() = 0;
virtual void set_cell_config(std::string cell_name, uint32_t earfcn, srslte_cell_t cell, const float power) = 0; };
virtual void set_cell_attenuation(std::string cell_name, const float attenuation) = 0;
class ss_sys_interface
{
public:
virtual void add_bcch_pdu(srslte::unique_byte_buffer_t pdu) = 0; virtual void add_bcch_pdu(srslte::unique_byte_buffer_t pdu) = 0;
virtual void add_ccch_pdu(srslte::unique_byte_buffer_t pdu) = 0;
virtual void add_dcch_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
virtual void add_pch_pdu(srslte::unique_byte_buffer_t pdu) = 0; virtual void add_pch_pdu(srslte::unique_byte_buffer_t pdu) = 0;
virtual void set_cell_attenuation(std::string cell_name, const float attenuation) = 0;
virtual void set_cell_config(std::string cell_name, uint32_t earfcn, srslte_cell_t cell, const float power) = 0;
virtual void add_srb(uint32_t lcid, srslte::pdcp_config_t pdcp_config) = 0; virtual void add_srb(uint32_t lcid, srslte::pdcp_config_t pdcp_config) = 0;
virtual void del_srb(uint32_t lcid) = 0; virtual void del_srb(uint32_t lcid) = 0;
virtual uint32_t get_tti() = 0; virtual uint32_t get_tti() = 0;
@ -53,12 +56,18 @@ public:
const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0; const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
}; };
class ss_srb_interface
{
public:
virtual void add_ccch_pdu(srslte::unique_byte_buffer_t pdu) = 0;
virtual void add_dcch_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
};
class syssim_interface_phy class syssim_interface_phy
{ {
public: public:
virtual void prach_indication(uint32_t preamble_index, const uint32_t& cell_id) = 0; virtual void prach_indication(uint32_t preamble_index, const uint32_t& cell_id) = 0;
virtual void sr_req(uint32_t tti_tx) = 0; virtual void sr_req(uint32_t tti_tx) = 0;
// 0; virtual void
virtual void tx_pdu(const uint8_t* payload, const int len, const uint32_t tx_tti) = 0; virtual void tx_pdu(const uint8_t* payload, const int len, const uint32_t tx_tti) = 0;
}; };

@ -34,10 +34,10 @@ using namespace srslte;
class ttcn3_srb_interface : public netsource_handler class ttcn3_srb_interface : public netsource_handler
{ {
public: public:
ttcn3_srb_interface() : syssim(nullptr), pool(byte_buffer_pool::get_instance()), netsource_handler("TTCN3_SRB_IF"){}; ttcn3_srb_interface() : pool(byte_buffer_pool::get_instance()), netsource_handler("TTCN3_SRB_IF"){};
~ttcn3_srb_interface(){}; ~ttcn3_srb_interface(){};
void init(syssim_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_) void init(ss_srb_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_)
{ {
syssim = syssim_; syssim = syssim_;
log = log_; log = log_;
@ -166,7 +166,7 @@ private:
syssim->add_dcch_pdu(lcid, std::move(pdu)); syssim->add_dcch_pdu(lcid, std::move(pdu));
} }
syssim_interface* syssim = nullptr; ss_srb_interface* syssim = nullptr;
byte_buffer_pool* pool = nullptr; byte_buffer_pool* pool = nullptr;
}; };

@ -35,7 +35,7 @@ public:
ttcn3_sys_interface() : netsource_handler("TTCN3_SYS_IF"){}; ttcn3_sys_interface() : netsource_handler("TTCN3_SYS_IF"){};
~ttcn3_sys_interface(){}; ~ttcn3_sys_interface(){};
void init(syssim_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_) void init(ss_sys_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_)
{ {
syssim = syssim_; syssim = syssim_;
net_ip = net_ip_; net_ip = net_ip_;
@ -596,7 +596,7 @@ private:
} }
phy_interface_syssim* phy = nullptr; phy_interface_syssim* phy = nullptr;
syssim_interface* syssim = nullptr; ss_sys_interface* syssim = nullptr;
byte_buffer_pool* pool = nullptr; byte_buffer_pool* pool = nullptr;
}; };

@ -25,6 +25,7 @@
#include "dut_utils.h" #include "dut_utils.h"
#include "srslte/common/netsource_handler.h" #include "srslte/common/netsource_handler.h"
#include "srslte/common/pdu_queue.h" #include "srslte/common/pdu_queue.h"
#include "srslte/common/threads.h"
#include "srslte/upper/pdcp.h" #include "srslte/upper/pdcp.h"
#include "srslte/upper/rlc.h" #include "srslte/upper/rlc.h"
#include "ttcn3_ip_ctrl_interface.h" #include "ttcn3_ip_ctrl_interface.h"
@ -33,14 +34,16 @@
#include "ttcn3_sys_interface.h" #include "ttcn3_sys_interface.h"
#include "ttcn3_ue.h" #include "ttcn3_ue.h"
#include "ttcn3_ut_interface.h" #include "ttcn3_ut_interface.h"
#include <pthread.h>
#include <srslte/interfaces/ue_interfaces.h> #include <srslte/interfaces/ue_interfaces.h>
#define TTCN3_CRNTI (0x1001) #define TTCN3_CRNTI (0x1001)
class ttcn3_syssim : public thread, class ttcn3_syssim : public thread,
public syssim_interface_phy, public syssim_interface_phy,
public syssim_interface, public ss_ut_interface,
public ss_sys_interface,
public ss_srb_interface,
public rrc_interface_rlc, public rrc_interface_rlc,
public rlc_interface_pdcp, public rlc_interface_pdcp,
public rrc_interface_pdcp, public rrc_interface_pdcp,
@ -63,6 +66,8 @@ public:
void init(const all_args_t& args_) void init(const all_args_t& args_)
{ {
std::lock_guard<std::mutex> lock(mutex);
args = args_; args = args_;
// Make sure to get SS logging as well // Make sure to get SS logging as well
@ -121,6 +126,7 @@ public:
void stop() void stop()
{ {
std::lock_guard<std::mutex> lock(mutex);
running = false; running = false;
@ -136,6 +142,7 @@ public:
srb.stop(); srb.stop();
} }
// Internal function called with acquired lock
void reset() void reset()
{ {
rlc.reset(); rlc.reset();
@ -147,6 +154,8 @@ public:
// Called from UT before starting testcase // Called from UT before starting testcase
void tc_start(const char* name) void tc_start(const char* name)
{ {
std::lock_guard<std::mutex> lock(mutex);
if (ue == nullptr) { if (ue == nullptr) {
// strip testsuite name // strip testsuite name
std::string tc_name = get_tc_name(name); std::string tc_name = get_tc_name(name);
@ -191,6 +200,8 @@ public:
void tc_end() void tc_end()
{ {
std::lock_guard<std::mutex> lock(mutex);
if (ue != NULL) { if (ue != NULL) {
// ask periodic thread to stop // ask periodic thread to stop
running = false; running = false;
@ -220,47 +231,16 @@ public:
// only return after new UE instance is up and running // only return after new UE instance is up and running
} }
void switch_on_ue() // Called from outside
{ void switch_on_ue() { event_queue.push(UE_SWITCH_ON); }
if (ue != nullptr) {
log.info("Switching on UE ID=%d\n", run_id);
log.console("Switching on UE ID=%d\n", run_id);
// Trigger attach procedure
ue->switch_on();
} else {
log.error("UE not initialized. Can't switch UE on.\n");
}
}
void switch_off_ue() void switch_off_ue() { event_queue.push(UE_SWITCH_OFF); }
{
if (ue != nullptr) {
log.info("Switching off UE ID=%d\n", run_id);
log.console("Switching off UE ID=%d\n", run_id);
ue->switch_off();
} else {
log.error("UE not initialized. Can't switch UE off.\n");
}
}
void enable_data() void enable_data() { event_queue.push(ENABLE_DATA); }
{
if (ue) {
log.info("Enabling data services on UE ID=%d\n", run_id);
ue->enable_data();
}
}
void disable_data() void disable_data() { event_queue.push(DISABLE_DATA); }
{
if (ue) {
log.info("Disabling data services on UE ID=%d\n", run_id);
ue->disable_data();
}
}
// Interface for PHY // Called from PHY but always from the SS main thread with lock being hold
void prach_indication(uint32_t preamble_index_, const uint32_t& cell_id) void prach_indication(uint32_t preamble_index_, const uint32_t& cell_id)
{ {
// store TTI for providing UL grant for Msg3 transmission // store TTI for providing UL grant for Msg3 transmission
@ -276,6 +256,76 @@ public:
} }
} }
// Called from PHY but always from the SS main thread with lock being hold
void sr_req(uint32_t tti_tx)
{
log.info("Received SR from PHY\n");
sr_tti = tti_tx;
}
// Called from PHY but always from the SS main thread with lock being hold
void tx_pdu(const uint8_t* payload, const int len, const uint32_t tx_tti)
{
if (payload == NULL) {
ss_mac_log.error("Received NULL as PDU payload. Dropping.\n");
return;
}
// Parse MAC
mac_msg_ul.init_rx(len, true);
mac_msg_ul.parse_packet((uint8_t*)payload);
while (mac_msg_ul.next()) {
assert(mac_msg_ul.get());
if (mac_msg_ul.get()->is_sdu()) {
// Route logical channel
ss_mac_log.info_hex(mac_msg_ul.get()->get_sdu_ptr(),
mac_msg_ul.get()->get_payload_size(),
"PDU: rnti=0x%x, lcid=%d, %d bytes\n",
0xdead,
mac_msg_ul.get()->get_sdu_lcid(),
mac_msg_ul.get()->get_payload_size());
// Push PDU to our own RLC (needed to handle status reporting, etc. correctly
ss_mac_log.info_hex(mac_msg_ul.get()->get_sdu_ptr(),
mac_msg_ul.get()->get_payload_size(),
"Route PDU to LCID=%d (%d B)\n",
mac_msg_ul.get()->get_sdu_lcid(),
mac_msg_ul.get()->get_payload_size());
rlc.write_pdu(
mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size());
// Save contention resolution if lcid == 0
if (mac_msg_ul.get()->get_sdu_lcid() == 0) {
int nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN;
if (mac_msg_ul.get()->get_payload_size() >= (uint32_t)nbytes) {
uint8_t* ue_cri_ptr = (uint8_t*)&conres_id;
uint8_t* pkt_ptr = mac_msg_ul.get()->get_sdu_ptr(); // Warning here: we want to include the
for (int i = 0; i < nbytes; i++) {
ue_cri_ptr[nbytes - i - 1] = pkt_ptr[i];
}
ss_mac_log.info_hex(ue_cri_ptr, nbytes, "Contention resolution ID:\n");
} else {
ss_mac_log.error("Received CCCH UL message of invalid size=%d bytes\n",
mac_msg_ul.get()->get_payload_size());
}
}
}
}
mac_msg_ul.reset();
/* Process CE after all SDUs because we need to update BSR after */
bool bsr_received = false;
while (mac_msg_ul.next()) {
assert(mac_msg_ul.get());
if (!mac_msg_ul.get()->is_sdu()) {
// Process MAC Control Element
bsr_received |= process_ce(mac_msg_ul.get());
}
}
}
// Internal function called from main thread
void send_rar(uint32_t preamble_index) void send_rar(uint32_t preamble_index)
{ {
log.info("Sending RAR for RAPID=%d\n", preamble_index); log.info("Sending RAR for RAPID=%d\n", preamble_index);
@ -316,6 +366,7 @@ public:
prach_tti = -1; prach_tti = -1;
} }
// Internal function called from main thread
void send_msg3_grant() void send_msg3_grant()
{ {
log.info("Sending Msg3 grant for C-RNTI=%d\n", crnti); log.info("Sending Msg3 grant for C-RNTI=%d\n", crnti);
@ -330,10 +381,9 @@ public:
ue->new_grant_ul(ul_grant); ue->new_grant_ul(ul_grant);
} }
void sr_req(uint32_t tti_tx) // Internal function called from main thread
void send_sr_ul_grant()
{ {
log.info("Received SR from PHY\n");
// Provide new UL grant to UE // Provide new UL grant to UE
mac_interface_phy_lte::mac_grant_ul_t ul_grant = {}; mac_interface_phy_lte::mac_grant_ul_t ul_grant = {};
ul_grant.tb.tbs = 100; // FIXME: reasonable size? ul_grant.tb.tbs = 100; // FIXME: reasonable size?
@ -343,73 +393,13 @@ public:
ul_grant.pid = get_pid(tti); ul_grant.pid = get_pid(tti);
ue->new_grant_ul(ul_grant); ue->new_grant_ul(ul_grant);
}
void tx_pdu(const uint8_t* payload, const int len, const uint32_t tx_tti)
{
if (payload == NULL) {
ss_mac_log.error("Received NULL as PDU payload. Dropping.\n");
return;
}
// Parse MAC
mac_msg_ul.init_rx(len, true);
mac_msg_ul.parse_packet((uint8_t*)payload);
while (mac_msg_ul.next()) {
assert(mac_msg_ul.get());
if (mac_msg_ul.get()->is_sdu()) {
// Route logical channel
ss_mac_log.info_hex(mac_msg_ul.get()->get_sdu_ptr(),
mac_msg_ul.get()->get_payload_size(),
"PDU: rnti=0x%x, lcid=%d, %d bytes\n",
0xdead,
mac_msg_ul.get()->get_sdu_lcid(),
mac_msg_ul.get()->get_payload_size());
// Push PDU to our own RLC (needed to handle status reporting, etc. correctly sr_tti = -1;
ss_mac_log.info_hex(mac_msg_ul.get()->get_sdu_ptr(),
mac_msg_ul.get()->get_payload_size(),
"Route PDU to LCID=%d (%d B)\n",
mac_msg_ul.get()->get_sdu_lcid(),
mac_msg_ul.get()->get_payload_size());
rlc.write_pdu(
mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size());
// Save contention resolution if lcid == 0
if (mac_msg_ul.get()->get_sdu_lcid() == 0) {
int nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN;
if (mac_msg_ul.get()->get_payload_size() >= (uint32_t)nbytes) {
uint8_t* ue_cri_ptr = (uint8_t*)&conres_id;
uint8_t* pkt_ptr = mac_msg_ul.get()->get_sdu_ptr(); // Warning here: we want to include the
for (int i = 0; i < nbytes; i++) {
ue_cri_ptr[nbytes - i - 1] = pkt_ptr[i];
}
ss_mac_log.info_hex(ue_cri_ptr, nbytes, "Contention resolution ID:\n");
} else {
ss_mac_log.error("Received CCCH UL message of invalid size=%d bytes\n",
mac_msg_ul.get()->get_payload_size());
}
}
}
}
mac_msg_ul.reset();
/* Process CE after all SDUs because we need to update BSR after */
bool bsr_received = false;
while (mac_msg_ul.next()) {
assert(mac_msg_ul.get());
if (!mac_msg_ul.get()->is_sdu()) {
// Process MAC Control Element
bsr_received |= process_ce(mac_msg_ul.get());
}
}
} }
// internal function called from tx_pdu (called from main thread)
bool process_ce(srslte::sch_subh* subh) bool process_ce(srslte::sch_subh* subh)
{ {
uint16_t rnti = dl_rnti; uint16_t rnti = dl_rnti;
uint32_t buff_size[4] = {0, 0, 0, 0}; uint32_t buff_size[4] = {0, 0, 0, 0};
@ -421,22 +411,10 @@ public:
case srslte::sch_subh::PHR_REPORT: case srslte::sch_subh::PHR_REPORT:
phr = subh->get_phr(); phr = subh->get_phr();
ss_mac_log.info("CE: Received PHR from rnti=0x%x, value=%.0f\n", rnti, phr); ss_mac_log.info("CE: Received PHR from rnti=0x%x, value=%.0f\n", rnti, phr);
#if 0
//sched->ul_phr(rnti, (int) phr);
//metrics_phr(phr);
#endif
break; break;
case srslte::sch_subh::CRNTI: case srslte::sch_subh::CRNTI:
old_rnti = subh->get_c_rnti(); old_rnti = subh->get_c_rnti();
ss_mac_log.info("CE: Received C-RNTI from temp_rnti=0x%x, rnti=0x%x\n", rnti, old_rnti); ss_mac_log.info("CE: Received C-RNTI from temp_rnti=0x%x, rnti=0x%x\n", rnti, old_rnti);
#if 0
if (sched->ue_exists(old_rnti)) {
rrc->upd_user(rnti, old_rnti);
rnti = old_rnti;
} else {
Error("Updating user C-RNTI: rnti=0x%x already released\n", old_rnti);
}
#endif
break; break;
case srslte::sch_subh::TRUNC_BSR: case srslte::sch_subh::TRUNC_BSR:
case srslte::sch_subh::SHORT_BSR: case srslte::sch_subh::SHORT_BSR:
@ -445,13 +423,6 @@ public:
ss_mac_log.error("Invalid Index Passed to lc groups\n"); ss_mac_log.error("Invalid Index Passed to lc groups\n");
break; break;
} }
#if 0
for (uint32_t i=0;i<lc_groups[idx].size();i++) {
// Indicate BSR to scheduler
sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]);
}
#endif
ss_mac_log.info("CE: Received %s BSR rnti=0x%x, lcg=%d, value=%d\n", ss_mac_log.info("CE: Received %s BSR rnti=0x%x, lcg=%d, value=%d\n",
subh->ce_type() == srslte::sch_subh::SHORT_BSR ? "Short" : "Trunc", subh->ce_type() == srslte::sch_subh::SHORT_BSR ? "Short" : "Trunc",
rnti, rnti,
@ -461,13 +432,6 @@ public:
break; break;
case srslte::sch_subh::LONG_BSR: case srslte::sch_subh::LONG_BSR:
subh->get_bsr(buff_size); subh->get_bsr(buff_size);
#if 0
for (idx=0;idx<4;idx++) {
for (uint32_t i=0;i<lc_groups[idx].size();i++) {
sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]);
}
}
#endif
is_bsr = true; is_bsr = true;
ss_mac_log.info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", ss_mac_log.info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n",
rnti, rnti,
@ -486,7 +450,7 @@ public:
return is_bsr; return is_bsr;
} }
uint32_t get_pid(const uint32_t tti) { return tti % (2 * FDD_HARQ_DELAY_MS); } uint32_t get_pid(const uint32_t tti_) { return tti_ % (2 * FDD_HARQ_DELAY_MS); }
bool get_ndi_for_new_ul_tx(const uint32_t tti_) bool get_ndi_for_new_ul_tx(const uint32_t tti_)
{ {
@ -511,112 +475,147 @@ public:
uint32_t sib_idx = 0; uint32_t sib_idx = 0;
while (running) { while (running) {
log.debug("SYSSIM-TTI=%d\n", tti); {
ue->set_current_tti(tti); std::lock_guard<std::mutex> lock(mutex);
dl_rnti = ue->get_dl_sched_rnti(tti);
tti = (tti + 1) % 10240;
if (SRSLTE_RNTI_ISSI(dl_rnti)) {
// deliver SIBs one after another log.debug("SYSSIM-TTI=%d\n", tti);
mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; ue->set_current_tti(tti);
dl_grant.pid = get_pid(tti);
dl_grant.rnti = dl_rnti; // process events, if any
dl_grant.tb[0].tbs = sibs[sib_idx]->N_bytes; while (not event_queue.empty()) {
dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); ss_events_t ev = event_queue.wait_pop();
ue->new_tb(dl_grant, sibs[sib_idx]->msg); switch (ev) {
case UE_SWITCH_ON:
sib_idx = (sib_idx + 1) % sibs.size(); log.console("Switching on UE ID=%d\n", run_id);
} else if (SRSLTE_RNTI_ISRAR(dl_rnti)) { ue->switch_on();
if (prach_tti != -1) { break;
rar_tti = (prach_tti + 3) % 10240; case UE_SWITCH_OFF:
if (tti == rar_tti) { log.console("Switching off UE ID=%d\n", run_id);
send_rar(prach_preamble_index); ue->switch_off();
break;
case ENABLE_DATA:
log.console("Enabling data for UE ID=%d\n", run_id);
ue->enable_data();
break;
case DISABLE_DATA:
log.console("Disabling data for UE ID=%d\n", run_id);
ue->disable_data();
break;
} }
} }
} else if (SRSLTE_RNTI_ISPA(dl_rnti)) {
log.debug("Searching for paging RNTI\n"); dl_rnti = ue->get_dl_sched_rnti(tti);
// PCH will be triggered from SYSSIM after receiving Paging
} else if (SRSLTE_RNTI_ISUSER(dl_rnti)) { if (SRSLTE_RNTI_ISSI(dl_rnti)) {
// check if this is for contention resolution after PRACH/RAR // deliver SIBs one after another
if (dl_rnti == crnti) { mac_interface_phy_lte::mac_grant_dl_t dl_grant = {};
log.debug("Searching for C-RNTI=%d\n", crnti); dl_grant.pid = get_pid(tti);
dl_grant.rnti = dl_rnti;
if (rar_tti != -1) { dl_grant.tb[0].tbs = sibs[sib_idx]->N_bytes;
msg3_tti = (rar_tti + 3) % 10240; dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti);
if (tti == msg3_tti) { ue->new_tb(dl_grant, sibs[sib_idx]->msg);
send_msg3_grant();
rar_tti = -1; sib_idx = (sib_idx + 1) % sibs.size();
} else if (SRSLTE_RNTI_ISRAR(dl_rnti)) {
if (prach_tti != -1) {
rar_tti = (prach_tti + 3) % 10240;
if (tti == rar_tti) {
send_rar(prach_preamble_index);
} }
} }
} } else if (SRSLTE_RNTI_ISPA(dl_rnti)) {
if (dl_rnti != 0) { log.debug("Searching for paging RNTI\n");
log.debug("Searching for RNTI=%d\n", dl_rnti); // PCH will be triggered from SYSSIM after receiving Paging
} else if (SRSLTE_RNTI_ISUSER(dl_rnti)) {
// look for DL data to be send in each bearer and provide grant accordingly // check if this is for contention resolution after PRACH/RAR
for (int lcid = 0; lcid < SRSLTE_N_RADIO_BEARERS; lcid++) { if (dl_rnti == crnti) {
uint32_t buf_state = rlc.get_buffer_state(lcid); log.debug("Searching for C-RNTI=%d\n", crnti);
if (buf_state > 0) {
log.debug("LCID=%d, buffer_state=%d\n", lcid, buf_state); if (rar_tti != -1) {
const uint32_t mac_header_size = 10; // Add MAC header (10 B for all subheaders, etc) msg3_tti = (rar_tti + 3) % 10240;
if (tmp_rlc_buffer.get_tailroom() > (buf_state + mac_header_size)) { if (tti == msg3_tti) {
uint32_t pdu_size = rlc.read_pdu(lcid, tmp_rlc_buffer.msg, buf_state); send_msg3_grant();
tx_payload_buffer.clear(); rar_tti = -1;
mac_msg_dl.init_tx(&tx_payload_buffer, pdu_size + mac_header_size, false); }
}
// check if this is Msg4 that needs to contain the contention resolution ID CE }
if (msg3_tti != -1) {
if (lcid == 0) { // check for SR
if (mac_msg_dl.new_subh()) { if (sr_tti != -1) {
if (mac_msg_dl.get()->set_con_res_id(conres_id)) { send_sr_ul_grant();
log.info("CE: Added Contention Resolution ID=0x%lx\n", conres_id); }
if (dl_rnti != 0) {
log.debug("Searching for RNTI=%d\n", dl_rnti);
// look for DL data to be send in each bearer and provide grant accordingly
for (int lcid = 0; lcid < SRSLTE_N_RADIO_BEARERS; lcid++) {
uint32_t buf_state = rlc.get_buffer_state(lcid);
if (buf_state > 0) {
log.debug("LCID=%d, buffer_state=%d\n", lcid, buf_state);
const uint32_t mac_header_size = 10; // Add MAC header (10 B for all subheaders, etc)
if (tmp_rlc_buffer.get_tailroom() > (buf_state + mac_header_size)) {
uint32_t pdu_size = rlc.read_pdu(lcid, tmp_rlc_buffer.msg, buf_state);
tx_payload_buffer.clear();
mac_msg_dl.init_tx(&tx_payload_buffer, pdu_size + mac_header_size, false);
// check if this is Msg4 that needs to contain the contention resolution ID CE
if (msg3_tti != -1) {
if (lcid == 0) {
if (mac_msg_dl.new_subh()) {
if (mac_msg_dl.get()->set_con_res_id(conres_id)) {
log.info("CE: Added Contention Resolution ID=0x%lx\n", conres_id);
} else {
log.error("CE: Setting Contention Resolution ID CE\n");
}
} else { } else {
log.error("CE: Setting Contention Resolution ID CE\n"); log.error("CE: Setting Contention Resolution ID CE. No space for a subheader\n");
} }
} else { msg3_tti = -1;
log.error("CE: Setting Contention Resolution ID CE. No space for a subheader\n");
} }
msg3_tti = -1;
} }
}
// Add payload // Add payload
if (mac_msg_dl.new_subh()) { if (mac_msg_dl.new_subh()) {
int n = mac_msg_dl.get()->set_sdu(lcid, pdu_size, tmp_rlc_buffer.msg); int n = mac_msg_dl.get()->set_sdu(lcid, pdu_size, tmp_rlc_buffer.msg);
if (n == -1) { if (n == -1) {
log.error("Error while adding SDU (%d B) to MAC PDU\n", pdu_size); log.error("Error while adding SDU (%d B) to MAC PDU\n", pdu_size);
mac_msg_dl.del_subh(); mac_msg_dl.del_subh();
}
} }
}
uint8_t* mac_pdu_ptr = mac_msg_dl.write_packet(&log);
if (mac_pdu_ptr != nullptr) {
log.info_hex(mac_pdu_ptr, mac_msg_dl.get_pdu_len(), "DL MAC PDU (%d B):\n", mac_msg_dl.get_pdu_len());
// Prepare MAC grant for CCCH uint8_t* mac_pdu_ptr = mac_msg_dl.write_packet(&log);
mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; if (mac_pdu_ptr != nullptr) {
dl_grant.pid = get_pid(tti); log.info_hex(
dl_grant.rnti = dl_rnti; mac_pdu_ptr, mac_msg_dl.get_pdu_len(), "DL MAC PDU (%d B):\n", mac_msg_dl.get_pdu_len());
dl_grant.tb[0].tbs = mac_msg_dl.get_pdu_len();
dl_grant.tb[0].ndi_present = true; // Prepare MAC grant for CCCH
dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); mac_interface_phy_lte::mac_grant_dl_t dl_grant = {};
dl_grant.pid = get_pid(tti);
ue->new_tb(dl_grant, (const uint8_t*)mac_pdu_ptr); dl_grant.rnti = dl_rnti;
dl_grant.tb[0].tbs = mac_msg_dl.get_pdu_len();
dl_grant.tb[0].ndi_present = true;
dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti);
ue->new_tb(dl_grant, (const uint8_t*)mac_pdu_ptr);
} else {
log.error("Error writing DL MAC PDU\n");
}
mac_msg_dl.reset();
} else { } else {
log.error("Error writing DL MAC PDU\n"); log.error("Can't fit RLC PDU into buffer (%d > %d)\n", buf_state, tmp_rlc_buffer.get_tailroom());
} }
mac_msg_dl.reset();
} else {
log.error("Can't fit RLC PDU into buffer (%d > %d)\n", buf_state, tmp_rlc_buffer.get_tailroom());
} }
} }
// Check if we need to provide a UL grant as well
} }
// Check if we need to provide a UL grant as well } else {
log.debug("Not handling RNTI=%d\n", dl_rnti);
} }
} else {
log.debug("Not handling RNTI=%d\n", dl_rnti);
} }
usleep(1000); usleep(1000);
tti = (tti + 1) % 10240;
} }
log.info("Leaving main thread.\n"); log.info("Leaving main thread.\n");
@ -625,10 +624,12 @@ public:
uint32_t get_tti() { return tti; } uint32_t get_tti() { return tti; }
void process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel) { log.info("%s\n", __PRETTY_FUNCTION__); } void process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel) {}
void set_cell_config(std::string name, uint32_t earfcn_, srslte_cell_t cell_, const float power) void set_cell_config(std::string name, uint32_t earfcn_, srslte_cell_t cell_, const float power)
{ {
std::lock_guard<std::mutex> lock(mutex);
// check if cell already exists // check if cell already exists
if (not syssim_has_cell(name)) { if (not syssim_has_cell(name)) {
// insert new cell // insert new cell
@ -647,6 +648,7 @@ public:
update_cell_map(); update_cell_map();
} }
// internal function
bool syssim_has_cell(std::string cell_name) bool syssim_has_cell(std::string cell_name)
{ {
for (uint32_t i = 0; i < cells.size(); ++i) { for (uint32_t i = 0; i < cells.size(); ++i) {
@ -659,6 +661,7 @@ public:
void set_cell_attenuation(std::string cell_name, const float value) void set_cell_attenuation(std::string cell_name, const float value)
{ {
std::lock_guard<std::mutex> lock(mutex);
if (not syssim_has_cell(cell_name)) { if (not syssim_has_cell(cell_name)) {
log.error("Can't set cell power. Cell not found.\n"); log.error("Can't set cell power. Cell not found.\n");
} }
@ -674,10 +677,14 @@ public:
update_cell_map(); update_cell_map();
} }
// Internal function
void update_cell_map() void update_cell_map()
{ {
// Find cell with highest power and select as serving cell // Find cell with highest power and select as serving cell
if (ue != NULL) { if (not ue) {
log.error("Can't configure cell. UE not initialized.\n");
}
// convert syssim cell list to phy cell list // convert syssim cell list to phy cell list
lte_ttcn3_phy::cell_list_t phy_cells; lte_ttcn3_phy::cell_list_t phy_cells;
for (uint32_t i = 0; i < cells.size(); ++i) { for (uint32_t i = 0; i < cells.size(); ++i) {
@ -691,21 +698,26 @@ public:
// SYSSIM defines what cells the UE can connect to // SYSSIM defines what cells the UE can connect to
ue->set_cell_map(phy_cells); ue->set_cell_map(phy_cells);
} else {
log.error("Can't configure cell. UE not initialized.\n");
}
} }
void add_bcch_pdu(unique_byte_buffer_t pdu) { sibs.push_back(std::move(pdu)); } void add_bcch_pdu(unique_byte_buffer_t pdu)
{
std::lock_guard<std::mutex> lock(mutex);
sibs.push_back(std::move(pdu));
}
void add_ccch_pdu(unique_byte_buffer_t pdu) void add_ccch_pdu(unique_byte_buffer_t pdu)
{ {
std::lock_guard<std::mutex> lock(mutex);
// Add to SRB0 Tx queue // Add to SRB0 Tx queue
rlc.write_sdu(0, std::move(pdu)); rlc.write_sdu(0, std::move(pdu));
} }
void add_dcch_pdu(uint32_t lcid, unique_byte_buffer_t pdu) void add_dcch_pdu(uint32_t lcid, unique_byte_buffer_t pdu)
{ {
std::lock_guard<std::mutex> lock(mutex);
// push to PDCP and create DL grant for it // push to PDCP and create DL grant for it
log.info("Writing PDU (%d B) to LCID=%d\n", pdu->N_bytes, lcid); log.info("Writing PDU (%d B) to LCID=%d\n", pdu->N_bytes, lcid);
pdcp.write_sdu(lcid, std::move(pdu)); pdcp.write_sdu(lcid, std::move(pdu));
@ -713,6 +725,7 @@ public:
void add_pch_pdu(unique_byte_buffer_t pdu) void add_pch_pdu(unique_byte_buffer_t pdu)
{ {
std::lock_guard<std::mutex> lock(mutex);
log.info("Received PCH PDU (%d B)\n", pdu->N_bytes); log.info("Received PCH PDU (%d B)\n", pdu->N_bytes);
// Prepare MAC grant for PCH // Prepare MAC grant for PCH
@ -735,12 +748,14 @@ public:
void add_srb(uint32_t lcid, pdcp_config_t pdcp_config) void add_srb(uint32_t lcid, pdcp_config_t pdcp_config)
{ {
std::lock_guard<std::mutex> lock(mutex);
pdcp.add_bearer(lcid, pdcp_config); pdcp.add_bearer(lcid, pdcp_config);
rlc.add_bearer(lcid, srslte::rlc_config_t::srb_config(lcid)); rlc.add_bearer(lcid, srslte::rlc_config_t::srb_config(lcid));
} }
void del_srb(uint32_t lcid) void del_srb(uint32_t lcid)
{ {
std::lock_guard<std::mutex> lock(mutex);
// Only delete SRB1/2 // Only delete SRB1/2
if (lcid > 0) { if (lcid > 0) {
pdcp.del_bearer(lcid); pdcp.del_bearer(lcid);
@ -779,8 +794,7 @@ public:
void write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); } void write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); }
void write_pdu_pcch(unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); } void write_pdu_pcch(unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); }
void write_pdu_mch(uint32_t lcid, unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); } void write_pdu_mch(uint32_t lcid, unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); }
void max_retx_attempted() { log.error("%s not implemented.\n", __FUNCTION__); }
void max_retx_attempted() { log.debug("max_retx_attempted\n"); }
std::string get_rb_name(uint32_t lcid) std::string get_rb_name(uint32_t lcid)
{ {
@ -848,12 +862,15 @@ private:
all_args_t args = {}; all_args_t args = {};
bool running = false;
srslte::byte_buffer_pool* pool = nullptr; srslte::byte_buffer_pool* pool = nullptr;
// Simulator vars // Simulator vars
unique_ptr<ttcn3_ue> ue = nullptr; unique_ptr<ttcn3_ue> ue = nullptr;
std::mutex mutex;
bool running = false;
typedef enum { UE_SWITCH_ON = 0, UE_SWITCH_OFF, ENABLE_DATA, DISABLE_DATA } ss_events_t;
block_queue<ss_events_t> event_queue;
uint32_t run_id = 0; uint32_t run_id = 0;
@ -862,6 +879,7 @@ private:
int32_t prach_tti = -1; int32_t prach_tti = -1;
int32_t rar_tti = -1; int32_t rar_tti = -1;
int32_t msg3_tti = -1; int32_t msg3_tti = -1;
int32_t sr_tti = -1;
uint32_t prach_preamble_index = 0; uint32_t prach_preamble_index = 0;
uint16_t dl_rnti = 0; uint16_t dl_rnti = 0;
uint16_t crnti = TTCN3_CRNTI; uint16_t crnti = TTCN3_CRNTI;

@ -37,7 +37,7 @@ public:
ttcn3_ut_interface() : netsource_handler("TTCN3_UT_IF") {} ttcn3_ut_interface() : netsource_handler("TTCN3_UT_IF") {}
~ttcn3_ut_interface(){}; ~ttcn3_ut_interface(){};
void init(syssim_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_) void init(ss_ut_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_)
{ {
syssim = syssim_; syssim = syssim_;
log = log_; log = log_;
@ -181,7 +181,7 @@ private:
} }
} }
syssim_interface* syssim = nullptr; ss_ut_interface* syssim = nullptr;
}; };
#endif // SRSUE_TTCN3_UT_INTERFACE_H #endif // SRSUE_TTCN3_UT_INTERFACE_H

@ -75,6 +75,8 @@ void lte_ttcn3_phy::set_cell_map(const cell_list_t& cells_)
// The interface for RRC // The interface for RRC
void lte_ttcn3_phy::get_current_cell(srslte_cell_t* cell_, uint32_t* earfcn_) void lte_ttcn3_phy::get_current_cell(srslte_cell_t* cell_, uint32_t* earfcn_)
{ {
std::lock_guard<std::mutex> lock(mutex);
if (cell_) { if (cell_) {
memcpy(cell_, &pcell.info, sizeof(srslte_cell_t)); memcpy(cell_, &pcell.info, sizeof(srslte_cell_t));
} }
@ -202,6 +204,8 @@ std::string lte_ttcn3_phy::get_type()
phy_interface_mac_lte::prach_info_t lte_ttcn3_phy::prach_get_info() phy_interface_mac_lte::prach_info_t lte_ttcn3_phy::prach_get_info()
{ {
std::lock_guard<std::mutex> lock(mutex);
prach_info_t info = {}; prach_info_t info = {};
if (prach_tti_tx != -1) { if (prach_tti_tx != -1) {
info.is_transmitted = true; info.is_transmitted = true;
@ -281,6 +285,8 @@ float lte_ttcn3_phy::get_pathloss_db()
// Calling function hold mutex // Calling function hold mutex
void lte_ttcn3_phy::new_grant_ul(mac_interface_phy_lte::mac_grant_ul_t ul_mac_grant) void lte_ttcn3_phy::new_grant_ul(mac_interface_phy_lte::mac_grant_ul_t ul_mac_grant)
{ {
std::lock_guard<std::mutex> lock(mutex);
mac_interface_phy_lte::tb_action_ul_t ul_action = {}; mac_interface_phy_lte::tb_action_ul_t ul_action = {};
// Deliver grant and retrieve payload // Deliver grant and retrieve payload

Loading…
Cancel
Save