add basic support for TimingInfo field from tester

this fixes an issue where commands are received out of
order and we are therefore applying configs incorrectly. if
commands include a timinginfo we are now putting the command
on a queue that the SS reads after the start of a new TTI.

the security and cell reconfig commands will be added in another
PR after the AS_security command has been fixed.
master
Andre Puschmann 5 years ago
parent 746de79859
commit 81e28aa9dc

@ -29,6 +29,7 @@
#include "rapidjson/document.h" // rapidjson's DOM-style API #include "rapidjson/document.h" // rapidjson's DOM-style API
#include "rapidjson/prettywriter.h" // for stringify JSON #include "rapidjson/prettywriter.h" // for stringify JSON
#include "ttcn3_interfaces.h"
#include <algorithm> #include <algorithm>
#include <assert.h> #include <assert.h>
#include <bitset> #include <bitset>
@ -355,6 +356,32 @@ public:
return config_flag.GetBool(); return config_flag.GetBool();
} }
static timing_info_t get_timing_info(Document& document)
{
timing_info_t timing = {};
// check for Now flag
if (document.HasMember("Common") && document["Common"].HasMember("TimingInfo") &&
document["Common"]["TimingInfo"].HasMember("Now")) {
timing.now = true;
}
if (document.HasMember("Common") && document["Common"].HasMember("TimingInfo") &&
document["Common"]["TimingInfo"].HasMember("SubFrame") &&
document["Common"]["TimingInfo"]["SubFrame"].HasMember("SFN") &&
document["Common"]["TimingInfo"]["SubFrame"]["SFN"].HasMember("Number")) {
timing.tti = document["Common"]["TimingInfo"]["SubFrame"]["SFN"]["Number"].GetInt() * 10;
// check SF index only
if (document["Common"]["TimingInfo"]["SubFrame"].HasMember("Subframe") &&
document["Common"]["TimingInfo"]["SubFrame"]["Subframe"].HasMember("Number")) {
timing.tti += document["Common"]["TimingInfo"]["SubFrame"]["Subframe"]["Number"].GetInt();
}
}
return timing;
}
}; };
#endif // SRSUE_TTCN3_HELPERS_H #endif // SRSUE_TTCN3_HELPERS_H

@ -25,6 +25,11 @@
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/interfaces/ue_interfaces.h" #include "srslte/interfaces/ue_interfaces.h"
typedef struct {
bool now; ///< If set to false, the TTI field contains a valid TTI
uint32_t tti;
} timing_info_t;
// Interfaces used by system interface to communicate with main component // Interfaces used by system interface to communicate with main component
class ss_ut_interface class ss_ut_interface
{ {
@ -45,8 +50,8 @@ public:
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_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 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(const timing_info_t timing, const uint32_t lcid, const srslte::pdcp_config_t pdcp_config) = 0;
virtual void del_srb(uint32_t lcid) = 0; virtual void del_srb(const timing_info_t timing, const uint32_t lcid) = 0;
virtual uint32_t get_tti() = 0; virtual uint32_t get_tti() = 0;
virtual int set_as_security(const uint32_t lcid, virtual int set_as_security(const uint32_t lcid,
const std::array<uint8_t, 32> k_rrc_enc, const std::array<uint8_t, 32> k_rrc_enc,
@ -60,8 +65,8 @@ public:
class ss_srb_interface class ss_srb_interface
{ {
public: public:
virtual void add_ccch_pdu(srslte::unique_byte_buffer_t pdu) = 0; virtual void add_ccch_pdu(const timing_info_t timing, 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_dcch_pdu(const timing_info_t timing, uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
virtual void reestablish_bearer(uint32_t lcid) = 0; virtual void reestablish_bearer(uint32_t lcid) = 0;
}; };

@ -119,7 +119,7 @@ private:
pdu->N_bytes = len; pdu->N_bytes = len;
memcpy(pdu->msg, payload, pdu->N_bytes); memcpy(pdu->msg, payload, pdu->N_bytes);
syssim->add_ccch_pdu(std::move(pdu)); syssim->add_ccch_pdu(ttcn3_helpers::get_timing_info(document), std::move(pdu));
// TODO: is there a better way to check for RRCConnectionReestablishment? // TODO: is there a better way to check for RRCConnectionReestablishment?
if (ccch_is_rrc_reestablishment(document)) { if (ccch_is_rrc_reestablishment(document)) {
@ -137,7 +137,7 @@ private:
pdu->N_bytes = len; pdu->N_bytes = len;
memcpy(pdu->msg, payload, pdu->N_bytes); memcpy(pdu->msg, payload, pdu->N_bytes);
syssim->add_dcch_pdu(lcid, std::move(pdu)); syssim->add_dcch_pdu(ttcn3_helpers::get_timing_info(document), lcid, std::move(pdu));
} }
bool ccch_is_rrc_reestablishment(Document& document) bool ccch_is_rrc_reestablishment(Document& document)

@ -212,6 +212,10 @@ private:
const Value& b = a["ControlInfo"]; const Value& b = a["ControlInfo"];
assert(b.HasMember("CnfFlag")); assert(b.HasMember("CnfFlag"));
if (ttcn3_helpers::get_timing_info(document).now == false) {
log->error("Timing info not supported in %s\n", __FUNCTION__);
}
// Handle cell creation // Handle cell creation
if (document["Request"]["Cell"].HasMember("AddOrReconfigure")) { if (document["Request"]["Cell"].HasMember("AddOrReconfigure")) {
if (document["Request"]["Cell"]["AddOrReconfigure"].HasMember("Basic")) { if (document["Request"]["Cell"]["AddOrReconfigure"].HasMember("Basic")) {
@ -287,7 +291,6 @@ private:
if (config.HasMember("AddOrReconfigure")) { if (config.HasMember("AddOrReconfigure")) {
uint32_t lcid = id["Srb"].GetInt(); uint32_t lcid = id["Srb"].GetInt();
if (lcid > 0) { if (lcid > 0) {
log->info("Configure SRB%d\n", lcid);
pdcp_config_t pdcp_cfg = {.bearer_id = static_cast<uint8_t>(lcid), pdcp_config_t pdcp_cfg = {.bearer_id = static_cast<uint8_t>(lcid),
.rb_type = PDCP_RB_IS_SRB, .rb_type = PDCP_RB_IS_SRB,
.tx_direction = SECURITY_DIRECTION_DOWNLINK, .tx_direction = SECURITY_DIRECTION_DOWNLINK,
@ -295,12 +298,11 @@ private:
.sn_len = PDCP_SN_LEN_5, .sn_len = PDCP_SN_LEN_5,
.t_reorderding = srslte::pdcp_t_reordering_t::ms500, .t_reorderding = srslte::pdcp_t_reordering_t::ms500,
.discard_timer = srslte::pdcp_discard_timer_t::infinity}; .discard_timer = srslte::pdcp_discard_timer_t::infinity};
syssim->add_srb(lcid, pdcp_cfg); syssim->add_srb(ttcn3_helpers::get_timing_info(document), lcid, pdcp_cfg);
} }
} else if (config.HasMember("Release")) { } else if (config.HasMember("Release")) {
log->info("Releasing SRB%d\n", id["Srb"].GetInt());
uint32_t lcid = id["Srb"].GetInt(); uint32_t lcid = id["Srb"].GetInt();
syssim->del_srb(lcid); syssim->del_srb(ttcn3_helpers::get_timing_info(document), lcid);
} else { } else {
log->error("Unknown config.\n"); log->error("Unknown config.\n");
} }
@ -336,6 +338,10 @@ private:
const Value& cells = req["CellAttenuationList"]; const Value& cells = req["CellAttenuationList"];
assert(cells.IsArray()); assert(cells.IsArray());
if (ttcn3_helpers::get_timing_info(document).now == false) {
log->error("Timing info not supported in %s\n", __FUNCTION__);
}
// iterate over all bearers and configure them // iterate over all bearers and configure them
for (Value::ConstValueIterator itr = cells.Begin(); itr != cells.End(); ++itr) { for (Value::ConstValueIterator itr = cells.Begin(); itr != cells.End(); ++itr) {
assert(itr->HasMember("CellId")); assert(itr->HasMember("CellId"));
@ -422,6 +428,11 @@ private:
const Value& req = document["Request"]; const Value& req = document["Request"];
assert(req.HasMember("AS_Security")); assert(req.HasMember("AS_Security"));
if (ttcn3_helpers::get_timing_info(document).now == false) {
log->error("Timing info not supported in %s\n", __FUNCTION__);
// continue ...
}
// check AS security start // check AS security start
const Value& as_sec = req["AS_Security"]; const Value& as_sec = req["AS_Security"];
if (as_sec.HasMember("StartRestart")) { if (as_sec.HasMember("StartRestart")) {

@ -24,7 +24,6 @@
#include "dut_utils.h" #include "dut_utils.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_common.h" #include "ttcn3_common.h"
@ -196,10 +195,20 @@ public:
tti = (tti + 1) % 10240; tti = (tti + 1) % 10240;
log.step(tti); log.step(tti);
log.debug("Start new TTI\n"); log.debug("Start TTI\n");
ue->set_current_tti(tti); ue->set_current_tti(tti);
// check scheduled actions for this TTI
if (tti_actions.find(tti) != tti_actions.end()) {
while (!tti_actions[tti].empty()) {
log.debug("Running scheduled action\n");
move_task_t task = std::move(tti_actions[tti].back());
task();
tti_actions[tti].pop_back();
}
}
// process events, if any // process events, if any
while (not event_queue.empty()) { while (not event_queue.empty()) {
ss_events_t ev = event_queue.wait_pop(); ss_events_t ev = event_queue.wait_pop();
@ -439,14 +448,14 @@ public:
prach_preamble_index = preamble_index_; prach_preamble_index = preamble_index_;
} }
// Called from PHY but always from the SS main thread with lock being hold // Called from PHY
void sr_req(uint32_t tti_tx) void sr_req(uint32_t tti_tx)
{ {
log.info("Received SR from PHY\n"); log.info("Received SR from PHY\n");
sr_tti = tti_tx; sr_tti = tti_tx;
} }
// Called from PHY but always from the SS main thread with lock being hold // Called from PHY
void tx_pdu(const uint8_t* payload, const int len, const uint32_t tx_tti) void tx_pdu(const uint8_t* payload, const int len, const uint32_t tx_tti)
{ {
if (payload == NULL) { if (payload == NULL) {
@ -692,8 +701,6 @@ public:
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
@ -725,7 +732,6 @@ 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");
} }
@ -765,8 +771,6 @@ public:
void add_bcch_dlsch_pdu(const string cell_name, unique_byte_buffer_t pdu) void add_bcch_dlsch_pdu(const string cell_name, unique_byte_buffer_t pdu)
{ {
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 add BCCH to cell. Cell not found.\n"); log.error("Can't add BCCH to cell. Cell not found.\n");
} }
@ -780,18 +784,31 @@ public:
} }
} }
void add_ccch_pdu(unique_byte_buffer_t pdu) void add_ccch_pdu(const timing_info_t timing, unique_byte_buffer_t pdu)
{ {
std::lock_guard<std::mutex> lock(mutex); if (timing.now) {
// Add to SRB0 Tx queue
// Add to SRB0 Tx queue rlc.write_sdu(0, std::move(pdu));
rlc.write_sdu(0, std::move(pdu)); } else {
log.debug("Scheduling CCCH PDU for TTI=%d\n", timing.tti);
auto task = [this](srslte::unique_byte_buffer_t& pdu) { rlc.write_sdu(0, std::move(pdu)); };
tti_actions[timing.tti].push_back(std::bind(task, std::move(pdu)));
}
} }
void add_dcch_pdu(uint32_t lcid, unique_byte_buffer_t pdu) void add_dcch_pdu(const timing_info_t timing, uint32_t lcid, unique_byte_buffer_t pdu)
{ {
std::lock_guard<std::mutex> lock(mutex); if (timing.now) {
add_dcch_pdu_impl(lcid, std::move(pdu));
} else {
log.debug("Scheduling DCCH PDU for TTI=%d\n", timing.tti);
auto task = [this](uint32_t lcid, srslte::unique_byte_buffer_t& pdu) { add_dcch_pdu_impl(lcid, std::move(pdu)); };
tti_actions[timing.tti].push_back(std::bind(task, lcid, std::move(pdu)));
}
}
void add_dcch_pdu_impl(uint32_t lcid, unique_byte_buffer_t pdu)
{
// 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), true); pdcp.write_sdu(lcid, std::move(pdu), true);
@ -799,7 +816,6 @@ 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
@ -814,9 +830,18 @@ public:
void step_timer() { timers.step_all(); } void step_timer() { timers.step_all(); }
void add_srb(uint32_t lcid, pdcp_config_t pdcp_config) void add_srb(const timing_info_t timing, const uint32_t lcid, const pdcp_config_t pdcp_config)
{
if (timing.now) {
add_srb_impl(lcid, pdcp_config);
} else {
log.debug("Scheduling SRB%d addition for TTI=%d\n", lcid, timing.tti);
tti_actions[timing.tti].push_back([this, lcid, pdcp_config]() { add_srb_impl(lcid, pdcp_config); });
}
}
void add_srb_impl(const uint32_t lcid, const pdcp_config_t pdcp_config)
{ {
std::lock_guard<std::mutex> lock(mutex);
log.info("Adding SRB%d\n", lcid); log.info("Adding SRB%d\n", lcid);
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));
@ -832,15 +857,23 @@ public:
void reestablish_bearer(uint32_t lcid) void reestablish_bearer(uint32_t lcid)
{ {
std::lock_guard<std::mutex> lock(mutex);
log.info("Reestablishing LCID=%d\n", lcid); log.info("Reestablishing LCID=%d\n", lcid);
pdcp.reestablish(lcid); pdcp.reestablish(lcid);
rlc.reestablish(lcid); rlc.reestablish(lcid);
} }
void del_srb(uint32_t lcid) void del_srb(const timing_info_t timing, const uint32_t lcid)
{
if (timing.now) {
del_srb_impl(lcid);
} else {
log.debug("Scheduling SRB%d deletion for TTI=%d\n", lcid, timing.tti);
tti_actions[timing.tti].push_back([this, lcid]() { del_srb_impl(lcid); });
}
}
void del_srb_impl(uint32_t lcid)
{ {
std::lock_guard<std::mutex> lock(mutex);
log.info("Deleting SRB%d\n", lcid); log.info("Deleting SRB%d\n", lcid);
// Only delete SRB1/2 // Only delete SRB1/2
if (lcid > 0) { if (lcid > 0) {
@ -1027,6 +1060,11 @@ private:
bool last_dl_ndi[2 * FDD_HARQ_DELAY_MS] = {}; bool last_dl_ndi[2 * FDD_HARQ_DELAY_MS] = {};
bool last_ul_ndi[2 * FDD_HARQ_DELAY_MS] = {}; bool last_ul_ndi[2 * FDD_HARQ_DELAY_MS] = {};
// For events/actions that need to be carried out in a specific TTI
typedef std::vector<move_task_t> task_list_t;
typedef std::map<const uint32_t, task_list_t> tti_action_map_t;
tti_action_map_t tti_actions;
// Map between the cellId (name) used by 3GPP test suite and srsLTE cell struct // Map between the cellId (name) used by 3GPP test suite and srsLTE cell struct
typedef struct { typedef struct {
std::string name; std::string name;

Loading…
Cancel
Save