ttcn3: refactor cell handling in SS

this rather large patch changes the way cells are handled in the SS.
It moves RLC and PDCP entities to the cell map of the SS, such that each cell
has its own entities. This allows to support HO operation, for example,
in which two cells need to send SRB messages.

It also extends most of the syssim interface to include the cell name
in all commands so they can be applied on the specified cell only.
master
Andre Puschmann 4 years ago
parent 4650a620d9
commit 624c8142ad

@ -128,7 +128,11 @@ private:
pdu->N_bytes = len;
memcpy(pdu->msg, payload, pdu->N_bytes);
syssim->add_dcch_pdu(ttcn3_helpers::get_timing_info(document), lcid, std::move(pdu), follow_on);
syssim->add_dcch_pdu(ttcn3_helpers::get_timing_info(document),
ttcn3_helpers::get_cell_name(document),
lcid,
std::move(pdu),
follow_on);
}
ss_srb_interface* syssim = nullptr;

@ -366,6 +366,16 @@ public:
return config_flag.GetBool();
}
static std::string get_cell_name(Document& document)
{
const Value& a = document["Common"];
assert(a.HasMember("CellId"));
const Value& cell_id = a["CellId"];
return cell_id.GetString();
}
static timing_info_t get_timing_info(Document& document)
{
timing_info_t timing = {};

@ -49,29 +49,41 @@ public:
const std::string cell_name,
const float attenuation) = 0;
virtual void set_cell_config(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t earfcn,
const srslte_cell_t cell,
const float power) = 0;
// Intermediate struct containing all values of (current) interest from the big SS Cell Request
class cell_config_t
{
public:
std::string name;
uint32_t earfcn = 0;
srslte_cell_t phy_cell = {};
float initial_power = -90.0;
float attenuation = 0.0;
uint16_t crnti = 0;
};
virtual void set_cell_config(const ttcn3_helpers::timing_info_t timing, const cell_config_t cell) = 0;
virtual void
add_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid, const srslte::pdcp_config_t pdcp_config) = 0;
virtual void del_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid) = 0;
virtual void
add_drb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid, const srslte::pdcp_config_t pdcp_config) = 0;
virtual void del_drb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid) = 0;
virtual void add_srb(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t lcid,
const srslte::pdcp_config_t pdcp_config) = 0;
virtual void del_srb(const ttcn3_helpers::timing_info_t timing, const std::string cell_name, const uint32_t lcid) = 0;
virtual void add_drb(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t lcid,
const srslte::pdcp_config_t pdcp_config) = 0;
virtual void del_drb(const ttcn3_helpers::timing_info_t timing, const std::string cell_name, const uint32_t lcid) = 0;
virtual void set_as_security(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const std::array<uint8_t, 32> k_rrc_enc,
const std::array<uint8_t, 32> k_rrc_int,
const std::array<uint8_t, 32> k_up_enc,
const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo,
const ttcn3_helpers::pdcp_count_map_t bearers) = 0;
virtual void release_as_security(const ttcn3_helpers::timing_info_t timing) = 0;
virtual void release_as_security(const ttcn3_helpers::timing_info_t timing, const std::string cell_name) = 0;
virtual ttcn3_helpers::pdcp_count_map_t get_pdcp_count() = 0;
virtual ttcn3_helpers::pdcp_count_map_t get_pdcp_count(const std::string cell_name) = 0;
virtual uint32_t get_tti() = 0;
virtual void set_forced_lcid(int lcid) = 0;
};
@ -79,14 +91,17 @@ public:
class ss_srb_interface
{
public:
virtual void add_ccch_pdu(const ttcn3_helpers::timing_info_t timing, srslte::unique_byte_buffer_t pdu) = 0;
virtual void add_ccch_pdu(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
srslte::unique_byte_buffer_t pdu) = 0;
virtual void add_dcch_pdu(const ttcn3_helpers::timing_info_t timing,
uint32_t lcid,
const std::string cell_name,
const uint32_t lcid,
srslte::unique_byte_buffer_t pdu,
bool follow_on_flag) = 0;
virtual void reestablish_bearer(uint32_t lcid) = 0;
virtual void reestablish_bearer(const std::string cell_name, const uint32_t lcid) = 0;
};
class syssim_interface_phy

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

@ -113,6 +113,9 @@ private:
} else if (request.HasMember("Paging")) {
log->info("Received Paging request.\n");
handle_request_paging(document, &rx_buf->at(rx_buf_offset), n - rx_buf_offset);
} else if (request.HasMember("PdcpHandoverControl")) {
log->info("Received PdcpHandoverControl.\n");
handle_request_pdcp_handover_control(document);
} else {
log->error("Received unknown request.\n");
}
@ -127,39 +130,49 @@ private:
assert(cell_name.IsString());
if (document["Request"]["Cell"]["AddOrReconfigure"]["Basic"].HasMember("StaticCellInfo")) {
// Fill all relevant info from the cell request
ss_sys_interface::cell_config_t cell;
// set name
cell.name = cell_name.GetString();
// Extract EARFCN
const Value& earfcn =
document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["StaticCellInfo"]["Downlink"]["Earfcn"];
assert(earfcn.IsInt());
cell.earfcn = earfcn.GetInt();
// Extract cell config
const Value& common_config = document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["StaticCellInfo"]["Common"];
const Value& dl_config = document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["StaticCellInfo"]["Downlink"];
const Value& phy_dl_config = document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["PhysicalLayerConfigDL"];
srslte_cell_t cell = {};
cell.id = common_config["PhysicalCellId"].GetInt();
cell.cp = (strcmp(dl_config["CyclicPrefix"].GetString(), "normal") == 0) ? SRSLTE_CP_NORM : SRSLTE_CP_EXT;
cell.nof_ports =
cell.phy_cell.id = common_config["PhysicalCellId"].GetInt();
cell.phy_cell.cp =
(strcmp(dl_config["CyclicPrefix"].GetString(), "normal") == 0) ? SRSLTE_CP_NORM : SRSLTE_CP_EXT;
cell.phy_cell.nof_ports =
(strcmp(phy_dl_config["AntennaGroup"]["AntennaInfoCommon"]["R8"]["antennaPortsCount"].GetString(), "an1") ==
0)
? 1
: 2;
cell.nof_prb = (strcmp(dl_config["Bandwidth"].GetString(), "n25") == 0) ? 25 : 0;
cell.phich_length =
cell.phy_cell.nof_prb = (strcmp(dl_config["Bandwidth"].GetString(), "n25") == 0) ? 25 : 0;
cell.phy_cell.phich_length =
(strcmp(phy_dl_config["Phich"]["PhichConfig"]["R8"]["phich_Duration"].GetString(), "normal") == 0)
? SRSLTE_PHICH_NORM
: SRSLTE_PHICH_EXT;
cell.phich_resources =
cell.phy_cell.phich_resources =
(strcmp(phy_dl_config["Phich"]["PhichConfig"]["R8"]["phich_Resource"].GetString(), "one") == 0)
? SRSLTE_PHICH_R_1
: SRSLTE_PHICH_R_1_6;
log->info("DL EARFCN is %d with n_prb=%d\n", earfcn.GetInt(), cell.nof_prb);
log->info("DL EARFCN is %d with n_prb=%d\n", cell.earfcn, cell.phy_cell.nof_prb);
const Value& ref_power =
document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["InitialCellPower"]["MaxReferencePower"];
assert(ref_power.IsInt());
// set power
cell.initial_power = ref_power.GetInt();
const Value& att = document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["InitialCellPower"]["Attenuation"];
float att_value = 0;
@ -174,9 +187,15 @@ private:
}
}
// Extract CRNTI
if (document["Request"]["Cell"]["AddOrReconfigure"].HasMember("Active")) {
const Value& crnti_string = document["Request"]["Cell"]["AddOrReconfigure"]["Active"]["C_RNTI"];
assert(crnti_string.IsString());
cell.crnti = std::bitset<16>(crnti_string.GetString()).to_ulong();
}
// Now configure cell
syssim->set_cell_config(
ttcn3_helpers::get_timing_info(document), cell_name.GetString(), earfcn.GetInt(), cell, ref_power.GetInt());
syssim->set_cell_config(ttcn3_helpers::get_timing_info(document), cell);
log->info("Configuring attenuation of %s to %.2f dB\n", cell_name.GetString(), att_value);
syssim->set_cell_attenuation(ttcn3_helpers::get_timing_info(document), cell_name.GetString(), att_value);
}
@ -214,10 +233,28 @@ private:
// Create response for template car_CellConfig_CNF(CellId_Type p_CellId)
std::string cell_id = document["Common"]["CellId"].GetString();
ss_sys_interface::cell_config_t cell;
cell.name = cell_id;
// Extract CRNTI
if (document["Request"]["Cell"]["AddOrReconfigure"].HasMember("Active")) {
if (document["Request"]["Cell"]["AddOrReconfigure"]["Active"].HasMember("C_RNTI")) {
const Value& crnti_string = document["Request"]["Cell"]["AddOrReconfigure"]["Active"]["C_RNTI"];
assert(crnti_string.IsString());
cell.crnti = std::bitset<16>(crnti_string.GetString()).to_ulong();
}
}
syssim->set_cell_config(ttcn3_helpers::get_timing_info(document), cell);
if (ttcn3_helpers::requires_confirm(document)) {
std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_id, "Cell");
log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length());
send((const uint8_t*)resp.c_str(), resp.length());
} else {
log->info("Skipping response for request cell active message.\n");
}
}
void handle_request_cell(Document& document, const uint8_t* payload, const uint16_t len)
@ -322,11 +359,12 @@ private:
}
if (lcid > 0) {
pdcp_config_t pdcp_cfg = make_srb_pdcp_config_t(static_cast<uint8_t>(lcid), false);
syssim->add_srb(ttcn3_helpers::get_timing_info(document), lcid, pdcp_cfg);
syssim->add_srb(
ttcn3_helpers::get_timing_info(document), ttcn3_helpers::get_cell_name(document), lcid, pdcp_cfg);
}
} else if (config.HasMember("Release")) {
uint32_t lcid = id["Srb"].GetInt();
syssim->del_srb(ttcn3_helpers::get_timing_info(document), lcid);
syssim->del_srb(ttcn3_helpers::get_timing_info(document), ttcn3_helpers::get_cell_name(document), lcid);
} else {
log->error("Unknown config.\n");
}
@ -339,21 +377,26 @@ private:
uint32_t lcid = aor["LogicalChannelId"].GetInt();
if (lcid > 0) {
pdcp_config_t pdcp_cfg = make_drb_pdcp_config_t(static_cast<uint8_t>(lcid), false);
syssim->add_drb(ttcn3_helpers::get_timing_info(document), lcid, pdcp_cfg);
syssim->add_drb(
ttcn3_helpers::get_timing_info(document), ttcn3_helpers::get_cell_name(document), lcid, pdcp_cfg);
}
} else if (config.HasMember("Release")) {
uint32_t lcid = id["Drb"].GetInt() + 2;
syssim->del_drb(ttcn3_helpers::get_timing_info(document), lcid);
syssim->del_drb(ttcn3_helpers::get_timing_info(document), ttcn3_helpers::get_cell_name(document), lcid);
} else {
log->error("Unknown config.\n");
}
}
}
if (ttcn3_helpers::requires_confirm(document)) {
std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_id.GetString(), "RadioBearerList");
log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length());
send((const uint8_t*)resp.c_str(), resp.length());
} else {
log->info("Skipping response for radio bearer list message.\n");
}
}
void handle_request_cell_attenuation_list(Document& document)
@ -427,7 +470,8 @@ private:
const Value& get = pdcp_count["Get"];
assert(get.HasMember("AllRBs"));
std::string resp = ttcn3_helpers::get_pdcp_count_response(cell_id.GetString(), syssim->get_pdcp_count());
std::string resp = ttcn3_helpers::get_pdcp_count_response(
cell_id.GetString(), syssim->get_pdcp_count(ttcn3_helpers::get_cell_name(document)));
log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length());
send((const uint8_t*)resp.c_str(), resp.length());
@ -532,11 +576,17 @@ private:
}
// configure SS to use AS security
syssim->set_as_security(
ttcn3_helpers::get_timing_info(document), k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo, bearers);
syssim->set_as_security(ttcn3_helpers::get_timing_info(document),
cell_id.GetString(),
k_rrc_enc,
k_rrc_int,
k_up_enc,
cipher_algo,
integ_algo,
bearers);
} else if (as_sec.HasMember("Release")) {
// release all security configs
syssim->release_as_security(ttcn3_helpers::get_timing_info(document));
syssim->release_as_security(ttcn3_helpers::get_timing_info(document), cell_id.GetString());
}
if (config_flag.GetBool() == true) {
@ -627,6 +677,39 @@ private:
}
}
void handle_request_pdcp_handover_control(Document& document)
{
const Value& a = document["Common"];
assert(a.HasMember("CellId"));
const Value& cell_id = a["CellId"];
// check cnf flag
assert(a.HasMember("ControlInfo"));
const Value& b = a["ControlInfo"];
assert(b.HasMember("CnfFlag"));
// check request
const Value& req = document["Request"];
assert(req.HasMember("PdcpHandoverControl"));
const Value& ho_control = req["PdcpHandoverControl"];
if (ho_control.HasMember("HandoverInit")) {
const Value& ho_init = ho_control["HandoverInit"];
assert(ho_init.HasMember("SourceCellId"));
const Value& ho_source_cellid = ho_init["SourceCellId"];
}
// send confirm
if (ttcn3_helpers::requires_confirm(document)) {
std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_id.GetString(), "PdcpHandoverControl");
log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length());
send((const uint8_t*)resp.c_str(), resp.length());
}
}
ss_sys_interface* syssim = nullptr;
byte_buffer_pool* pool = nullptr;
};

@ -37,8 +37,6 @@
#include "ttcn3_ut_interface.h"
#include <functional>
#define TTCN3_CRNTI (0x1001)
class ttcn3_syssim : public syssim_interface_phy,
public ss_ut_interface,
public ss_sys_interface,
@ -117,54 +115,47 @@ public:
void process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel);
void set_cell_config(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t earfcn,
const srslte_cell_t cell,
const float power);
void set_cell_config_impl(const std::string cell_name_,
const uint32_t earfcn_,
const srslte_cell_t cell_,
const float power_);
// internal function
bool syssim_has_cell(std::string cell_name);
void set_cell_config(const ttcn3_helpers::timing_info_t timing, const cell_config_t cell);
void set_cell_config_impl(const cell_config_t cell);
// cell helper
void set_cell_attenuation(const ttcn3_helpers::timing_info_t timing, const std::string cell_name, const float value);
void set_cell_attenuation_impl(const std::string cell_name, const float value);
// Internal function
void update_cell_map();
bool have_valid_pcell();
void add_bcch_dlsch_pdu(const string cell_name, unique_byte_buffer_t pdu);
void add_ccch_pdu(const ttcn3_helpers::timing_info_t timing, unique_byte_buffer_t pdu);
void
add_dcch_pdu(const ttcn3_helpers::timing_info_t timing, uint32_t lcid, unique_byte_buffer_t pdu, bool follow_on_flag);
void add_ccch_pdu(const ttcn3_helpers::timing_info_t timing, const std::string cell_name, unique_byte_buffer_t pdu);
void add_ccch_pdu_impl(const std::string cell_name, unique_byte_buffer_t pdu);
void add_dcch_pdu_impl(uint32_t lcid, unique_byte_buffer_t pdu, bool follow_on_flag);
void add_dcch_pdu(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
uint32_t lcid,
unique_byte_buffer_t pdu,
bool follow_on_flag);
void add_dcch_pdu_impl(const std::string cell_name, uint32_t lcid, unique_byte_buffer_t pdu, bool follow_on_flag);
void add_pch_pdu(unique_byte_buffer_t pdu);
void step_stack();
void add_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid, const pdcp_config_t pdcp_config);
void add_srb_impl(const uint32_t lcid, const pdcp_config_t pdcp_config);
void add_srb(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t lcid,
const pdcp_config_t pdcp_config);
void add_srb_impl(const std::string cell_name, const uint32_t lcid, const pdcp_config_t pdcp_config);
void reestablish_bearer(uint32_t lcid);
void reestablish_bearer(const std::string cell_name, const uint32_t lcid);
void del_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid);
void del_srb_impl(uint32_t lcid);
void del_srb(const ttcn3_helpers::timing_info_t timing, const std::string cell_name, const uint32_t lcid);
void del_srb_impl(const std::string cell_name, const uint32_t lcid);
void add_drb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid, const pdcp_config_t pdcp_config);
void add_drb_impl(const uint32_t lcid, const pdcp_config_t pdcp_config);
void del_drb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid);
void del_drb_impl(uint32_t lcid);
void add_drb(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t lcid,
const pdcp_config_t pdcp_config);
void add_drb_impl(const std::string cell_name, const uint32_t lcid, const pdcp_config_t pdcp_config);
void del_drb(const ttcn3_helpers::timing_info_t timing, const std::string cell_name, const uint32_t lcid);
void del_drb_impl(const std::string cell_name, const uint32_t lcid);
// RRC interface for PDCP, PDCP calls RRC to push RRC SDU
void write_pdu(uint32_t lcid, unique_byte_buffer_t pdu);
@ -187,6 +178,7 @@ public:
bool sdu_queue_is_full(uint32_t lcid);
void set_as_security(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_int_,
std::array<uint8_t, 32> k_up_enc_,
@ -194,20 +186,21 @@ public:
const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_,
const ttcn3_helpers::pdcp_count_map_t bearers_);
void set_as_security_impl(std::array<uint8_t, 32> k_rrc_enc_,
void set_as_security_impl(const std::string cell_name,
std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_int_,
std::array<uint8_t, 32> k_up_enc_,
const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_,
const ttcn3_helpers::pdcp_count_map_t bearers);
void release_as_security(const ttcn3_helpers::timing_info_t timing);
void release_as_security(const ttcn3_helpers::timing_info_t timing, const std::string cell_name);
void release_as_security_impl();
void release_as_security_impl(const std::string cell_name);
void select_cell(srslte_cell_t phy_cell);
ttcn3_helpers::pdcp_count_map_t get_pdcp_count();
ttcn3_helpers::pdcp_count_map_t get_pdcp_count(const std::string cell_name);
private:
// SYS interface
@ -260,7 +253,6 @@ private:
int32_t sr_tti = -1;
uint32_t prach_preamble_index = 0;
uint16_t dl_rnti = 0;
uint16_t crnti = TTCN3_CRNTI;
int force_lcid = -1;
srsue::stack_test_dummy stack;
bool last_dl_ndi[SRSLTE_FDD_NOF_HARQ] = {};
@ -272,19 +264,37 @@ private:
tti_action_map_t tti_actions;
// Map between the cellId (name) used by 3GPP test suite and srsLTE cell struct
typedef struct {
std::string name;
srslte_cell_t cell = {};
float initial_power = 0.0;
float attenuation = 0.0;
uint32_t earfcn = 0;
class syssim_cell_t
{
public:
syssim_cell_t(ttcn3_syssim* ss) :
rlc(ss->ss_rlc_log->get_service_name().c_str()),
pdcp(&ss->stack.task_sched, ss->ss_pdcp_log->get_service_name().c_str())
{}
cell_config_t config;
std::vector<unique_byte_buffer_t> sibs;
int sib_idx = 0; ///< Index of SIB scheduled for next transmission
} syssim_cell_t;
// Simulator objects
srslte::rlc rlc;
srslte::pdcp pdcp;
std::map<uint32_t, bool> bearer_follow_on_map; ///< Indicates if for a given LCID the follow_on_flag is set or not
// security config
ttcn3_helpers::pdcp_count_map_t pending_bearer_config; ///< List of bearers with pending security configuration
srslte::as_security_config_t sec_cfg;
};
typedef std::unique_ptr<syssim_cell_t> unique_syssim_cell_t;
std::vector<unique_syssim_cell_t> cells;
int32_t pcell_idx = -1;
// Internal function
void update_cell_map();
bool syssim_has_cell(std::string cell_name);
syssim_cell_t* get_cell(const std::string cell_name);
bool have_valid_pcell();
srslte::pdu_queue pdus;
srslte::sch_pdu mac_msg_dl, mac_msg_ul;
@ -294,15 +304,6 @@ private:
uint64_t conres_id = 0;
// Simulator objects
srslte::rlc rlc;
srslte::pdcp pdcp;
std::map<uint32_t, bool> bearer_follow_on_map; ///< Indicates if for a given LCID the follow_on_flag is set or not
// security config
ttcn3_helpers::pdcp_count_map_t pending_bearer_config; ///< List of bearers with pending security configuration
srslte::as_security_config_t sec_cfg;
std::vector<std::string> rb_id_vec =
{"SRB0", "SRB1", "SRB2", "DRB1", "DRB2", "DRB3", "DRB4", "DRB5", "DRB6", "DRB7", "DRB8"};

@ -47,10 +47,8 @@ ttcn3_syssim::ttcn3_syssim(swappable_log& logger_file_, srslte::logger& logger_s
logger(&logger_file),
pool(byte_buffer_pool::get_instance()),
ue(ue_),
rlc(ss_rlc_log->get_service_name().c_str()),
signal_handler(&running),
timer_handler(create_tti_timer(), [&](uint64_t res) { new_tti_indication(res); }),
pdcp(&stack.task_sched, ss_pdcp_log->get_service_name().c_str())
timer_handler(create_tti_timer(), [&](uint64_t res) { new_tti_indication(res); })
{
if (ue->init(all_args_t{}, logger, this, "INIT_TEST") != SRSLTE_SUCCESS) {
ue->stop();
@ -124,10 +122,8 @@ int ttcn3_syssim::init(const all_args_t& args_)
return SRSLTE_ERROR;
}
// Init SS layers
// Init common SS layers
pdus.init(this, log);
rlc.init(&pdcp, this, stack.task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */);
pdcp.init(&rlc, this, this);
return SRSLTE_SUCCESS;
}
@ -273,8 +269,8 @@ void ttcn3_syssim::new_tti_indication(uint64_t res)
// PCH will be triggered from SYSSIM after receiving Paging
} else if (SRSLTE_RNTI_ISUSER(dl_rnti)) {
// check if this is for contention resolution after PRACH/RAR
if (dl_rnti == crnti) {
log->debug("Searching for C-RNTI=%d\n", crnti);
if (dl_rnti == cells[pcell_idx]->config.crnti) {
log->debug("Searching for C-RNTI=%d\n", dl_rnti);
if (rar_tti != -1) {
msg3_tti = (rar_tti + 3) % 10240;
@ -295,9 +291,10 @@ void ttcn3_syssim::new_tti_indication(uint64_t res)
// 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);
uint32_t buf_state = cells[pcell_idx]->rlc.get_buffer_state(lcid);
// Schedule DL transmission if there is data in RLC buffer or we need to send Msg4
if ((buf_state > 0 && bearer_follow_on_map[lcid] == false) || (msg3_tti != -1 && conres_id != 0)) {
if ((buf_state > 0 && cells[pcell_idx]->bearer_follow_on_map[lcid] == false) ||
(msg3_tti != -1 && conres_id != 0)) {
log->debug("LCID=%d, buffer_state=%d\n", lcid, buf_state);
tx_payload_buffer.clear();
@ -324,14 +321,14 @@ void ttcn3_syssim::new_tti_indication(uint64_t res)
// allocate SDUs
while (buf_state > 0) { // there is pending SDU to allocate
if (mac_msg_dl.new_subh()) {
int n = mac_msg_dl.get()->set_sdu(lcid, buf_state, &rlc);
int n = mac_msg_dl.get()->set_sdu(lcid, buf_state, &cells[pcell_idx]->rlc);
if (n == -1) {
log->error("Error while adding SDU (%d B) to MAC PDU\n", buf_state);
mac_msg_dl.del_subh();
}
// update buffer state
buf_state = rlc.get_buffer_state(lcid);
buf_state = cells[pcell_idx]->rlc.get_buffer_state(lcid);
if (mac_msg_dl.nof_subh() == 1) {
has_single_sdu = true;
@ -370,7 +367,7 @@ void ttcn3_syssim::new_tti_indication(uint64_t res)
}
mac_msg_dl.reset();
} else if (bearer_follow_on_map[lcid]) {
} else if (cells[pcell_idx]->bearer_follow_on_map[lcid]) {
log->info("Waiting for more PDUs for transmission on LCID=%d\n", lcid);
}
}
@ -390,11 +387,8 @@ void ttcn3_syssim::stop()
void ttcn3_syssim::reset()
{
log->info("Resetting SS\n");
rlc.reset();
pdcp.reset();
cells.clear();
pcell_idx = -1;
pending_bearer_config.clear();
}
// Called from UT before starting testcase
@ -453,7 +447,7 @@ void ttcn3_syssim::tc_end()
run_id++;
// Reset SS' RLC and PDCP
// Reset SS
reset();
}
@ -487,8 +481,9 @@ void ttcn3_syssim::disable_data()
void ttcn3_syssim::prach_indication(uint32_t preamble_index_, const uint32_t& cell_id)
{
// verify that UE intends to send PRACH on current Pcell
if (cells[pcell_idx]->cell.id != cell_id) {
log->error("UE is attempting to PRACH on pci=%d, current Pcell=%d\n", cell_id, cells[pcell_idx]->cell.id);
if (cells[pcell_idx]->config.phy_cell.id != cell_id) {
log->error(
"UE is attempting to PRACH on pci=%d, current Pcell=%d\n", cell_id, cells[pcell_idx]->config.phy_cell.id);
return;
}
@ -512,6 +507,11 @@ void ttcn3_syssim::tx_pdu(const uint8_t* payload, const int len, const uint32_t
return;
}
if (pcell_idx == -1) {
log->debug("Skipping TTI. Pcell not yet selected.\n");
return;
}
log->info_hex(payload, len, "UL MAC PDU (%d B):\n", len);
// Parse MAC
@ -527,7 +527,7 @@ void ttcn3_syssim::tx_pdu(const uint8_t* payload, const int len, const uint32_t
"Route UL PDU to LCID=%d (%d B)\n",
mac_msg_ul.get()->get_sdu_lcid(),
mac_msg_ul.get()->get_payload_size());
rlc.write_pdu(
cells[pcell_idx]->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
@ -581,7 +581,7 @@ void ttcn3_syssim::send_rar(uint32_t preamble_index)
if (rar_pdu.new_subh()) {
rar_pdu.get()->set_rapid(preamble_index);
rar_pdu.get()->set_ta_cmd(0);
rar_pdu.get()->set_temp_crnti(crnti);
rar_pdu.get()->set_temp_crnti(cells[pcell_idx]->config.crnti);
rar_pdu.get()->set_sched_grant(grant_buffer);
}
rar_pdu.write_packet(rar_buffer.msg);
@ -605,14 +605,14 @@ void ttcn3_syssim::send_rar(uint32_t preamble_index)
// Internal function called from main thread
void ttcn3_syssim::send_msg3_grant()
{
log->info("Sending Msg3 grant for C-RNTI=%d\n", crnti);
log->info("Sending Msg3 grant for C-RNTI=%d\n", cells[pcell_idx]->config.crnti);
mac_interface_phy_lte::mac_grant_ul_t ul_grant = {};
ul_grant.tti_tx = (tti + 3) % 10240;
ul_grant.tb.tbs = 32;
ul_grant.tb.ndi_present = true;
ul_grant.tb.ndi = get_ndi_for_new_ul_tx(tti);
ul_grant.rnti = crnti;
ul_grant.rnti = cells[pcell_idx]->config.crnti;
ul_grant.pid = get_pid(tti);
ul_grant.is_rar = true;
@ -628,7 +628,7 @@ void ttcn3_syssim::send_sr_ul_grant()
ul_grant.tb.tbs = 100; // TODO: reasonable size?
ul_grant.tb.ndi_present = true;
ul_grant.tb.ndi = get_ndi_for_new_ul_tx(tti);
ul_grant.rnti = crnti;
ul_grant.rnti = cells[pcell_idx]->config.crnti;
ul_grant.pid = get_pid(tti);
ue->new_grant_ul(ul_grant);
@ -758,55 +758,67 @@ uint32_t ttcn3_syssim::get_tti()
void ttcn3_syssim::process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel) {}
void ttcn3_syssim::set_cell_config(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t earfcn,
const srslte_cell_t cell,
const float power)
void ttcn3_syssim::set_cell_config(const ttcn3_helpers::timing_info_t timing, const cell_config_t cell)
{
if (timing.now) {
set_cell_config_impl(cell_name, earfcn, cell, power);
set_cell_config_impl(cell);
} else {
log->debug("Scheduling Cell configuration of %s for TTI=%d\n", cell_name.c_str(), timing.tti);
tti_actions[timing.tti].push_back(
[this, cell_name, earfcn, cell, power]() { set_cell_config_impl(cell_name, earfcn, cell, power); });
log->debug("Scheduling Cell configuration of %s for TTI=%d\n", cell.name.c_str(), timing.tti);
tti_actions[timing.tti].push_back([this, cell]() { set_cell_config_impl(cell); });
}
}
void ttcn3_syssim::set_cell_config_impl(const std::string cell_name_,
const uint32_t earfcn_,
const srslte_cell_t cell_,
const float power_)
void ttcn3_syssim::set_cell_config_impl(const cell_config_t config)
{
// check if cell already exists
if (not syssim_has_cell(cell_name_)) {
if (not syssim_has_cell(config.name)) {
// insert new cell
log->info("Adding cell %s with cellId=%d and power=%.2f dBm\n", cell_name_.c_str(), cell_.id, power_);
unique_syssim_cell_t cell = unique_syssim_cell_t(new syssim_cell_t);
cell->name = cell_name_;
cell->cell = cell_;
cell->initial_power = power_;
cell->earfcn = earfcn_;
log->info("Adding cell %s with cellId=%d and initial_power=%.2f dBm\n",
config.name.c_str(),
config.phy_cell.id,
config.initial_power);
unique_syssim_cell_t cell = unique_syssim_cell_t(new syssim_cell_t(this));
cell->config = config;
// init RLC and PDCP
cell->rlc.init(&cell->pdcp, this, stack.task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */);
cell->pdcp.init(&cell->rlc, this, this);
cells.push_back(std::move(cell));
} else {
// cell is already there
log->info("Cell already there, reconfigure\n");
// We only support C-RNTI reconfiguration
syssim_cell_t* ss_cell = get_cell(config.name);
if (config.crnti > 0) {
ss_cell->config.crnti = config.crnti;
}
}
update_cell_map();
}
// internal function
bool ttcn3_syssim::syssim_has_cell(std::string cell_name)
bool ttcn3_syssim::syssim_has_cell(const std::string cell_name)
{
for (auto& cell : cells) {
if (cell->name == cell_name) {
if (cell->config.name == cell_name) {
return true;
}
}
return false;
}
ttcn3_syssim::syssim_cell_t* ttcn3_syssim::get_cell(const std::string cell_name)
{
for (auto& cell : cells) {
if (cell->config.name == cell_name) {
return cell.get();
}
}
return nullptr;
}
void ttcn3_syssim::set_cell_attenuation(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const float value)
@ -823,15 +835,12 @@ void ttcn3_syssim::set_cell_attenuation_impl(const std::string cell_name, const
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't set cell power. Cell not found.\n");
return;
}
// update cell's power
for (auto& cell : cells) {
if (cell->name == cell_name) {
cell->attenuation = value;
break;
}
}
auto cell = get_cell(cell_name);
cell->config.attenuation = value;
update_cell_map();
}
@ -840,20 +849,18 @@ void ttcn3_syssim::set_cell_attenuation_impl(const std::string cell_name, const
void ttcn3_syssim::update_cell_map()
{
// convert syssim cell list to phy cell list
{
lte_ttcn3_phy::cell_list_t phy_cells;
for (auto& ss_cell : cells) {
lte_ttcn3_phy::cell_t phy_cell = {};
phy_cell.info = ss_cell->cell;
phy_cell.power = ss_cell->initial_power - ss_cell->attenuation;
phy_cell.earfcn = ss_cell->earfcn;
phy_cell.info = ss_cell->config.phy_cell;
phy_cell.power = ss_cell->config.initial_power - ss_cell->config.attenuation;
phy_cell.earfcn = ss_cell->config.earfcn;
log->info("Configuring cell with PCI=%d with TxPower=%.2f\n", phy_cell.info.id, phy_cell.power);
phy_cells.push_back(phy_cell);
}
// SYSSIM defines what cells the UE can connect to
ue->set_cell_map(phy_cells);
}
}
bool ttcn3_syssim::have_valid_pcell()
@ -865,51 +872,72 @@ void ttcn3_syssim::add_bcch_dlsch_pdu(const string cell_name, unique_byte_buffer
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't add BCCH to cell. Cell not found.\n");
return;
}
// add SIB
for (auto& cell : cells) {
if (cell->name == cell_name) {
auto cell = get_cell(cell_name);
cell->sibs.push_back(std::move(pdu));
break;
}
}
}
void ttcn3_syssim::add_ccch_pdu(const ttcn3_helpers::timing_info_t timing, unique_byte_buffer_t pdu)
void ttcn3_syssim::add_ccch_pdu(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
unique_byte_buffer_t pdu)
{
if (timing.now) {
// Add to SRB0 Tx queue
rlc.write_sdu(0, std::move(pdu));
add_ccch_pdu_impl(cell_name, 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)); };
auto task = [this, cell_name](srslte::unique_byte_buffer_t& pdu) { add_ccch_pdu_impl(cell_name, std::move(pdu)); };
tti_actions[timing.tti].push_back(std::bind(task, std::move(pdu)));
}
}
void ttcn3_syssim::add_ccch_pdu_impl(const std::string cell_name, unique_byte_buffer_t pdu)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't add CCCH to cell. Cell not found.\n");
return;
}
auto cell = get_cell(cell_name);
// Add to SRB0 Tx queue
cell->rlc.write_sdu(0, std::move(pdu));
}
void ttcn3_syssim::add_dcch_pdu(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
uint32_t lcid,
unique_byte_buffer_t pdu,
bool follow_on_flag)
{
if (timing.now) {
add_dcch_pdu_impl(lcid, std::move(pdu), follow_on_flag);
add_dcch_pdu_impl(cell_name, lcid, std::move(pdu), follow_on_flag);
} else {
log->debug("Scheduling DCCH PDU for TTI=%d\n", timing.tti);
auto task = [this](uint32_t lcid, srslte::unique_byte_buffer_t& pdu, bool follow_on_flag) {
add_dcch_pdu_impl(lcid, std::move(pdu), follow_on_flag);
auto task = [this, cell_name](uint32_t lcid, srslte::unique_byte_buffer_t& pdu, bool follow_on_flag) {
add_dcch_pdu_impl(cell_name, lcid, std::move(pdu), follow_on_flag);
};
tti_actions[timing.tti].push_back(std::bind(task, lcid, std::move(pdu), follow_on_flag));
}
}
void ttcn3_syssim::add_dcch_pdu_impl(uint32_t lcid, unique_byte_buffer_t pdu, bool follow_on_flag)
void ttcn3_syssim::add_dcch_pdu_impl(const std::string cell_name,
uint32_t lcid,
unique_byte_buffer_t pdu,
bool follow_on_flag)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't add CCCH to cell. Cell %s not found.\n", cell_name.c_str());
return;
}
auto cell = get_cell(cell_name);
// push to PDCP and create DL grant for it
log->info("Writing PDU (%d B) to LCID=%d\n", pdu->N_bytes, lcid);
pdcp.write_sdu(lcid, std::move(pdu));
bearer_follow_on_map[lcid] = follow_on_flag;
cell->pdcp.write_sdu(lcid, std::move(pdu));
cell->bearer_follow_on_map[lcid] = follow_on_flag;
}
void ttcn3_syssim::add_pch_pdu(unique_byte_buffer_t pdu)
@ -933,89 +961,128 @@ void ttcn3_syssim::step_stack()
}
void ttcn3_syssim::add_srb(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t lcid,
const pdcp_config_t pdcp_config)
{
if (timing.now) {
add_srb_impl(lcid, pdcp_config);
add_srb_impl(cell_name, 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); });
tti_actions[timing.tti].push_back(
[this, cell_name, lcid, pdcp_config]() { add_srb_impl(cell_name, lcid, pdcp_config); });
}
}
void ttcn3_syssim::add_srb_impl(const uint32_t lcid, const pdcp_config_t pdcp_config)
void ttcn3_syssim::add_srb_impl(const std::string cell_name, const uint32_t lcid, const pdcp_config_t pdcp_config)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't add SRB to cell. Cell %s not found.\n", cell_name.c_str());
return;
}
auto cell = get_cell(cell_name);
log->info("Adding SRB%d\n", lcid);
pdcp.add_bearer(lcid, pdcp_config);
rlc.add_bearer(lcid, srslte::rlc_config_t::srb_config(lcid));
cell->pdcp.add_bearer(lcid, pdcp_config);
cell->rlc.add_bearer(lcid, srslte::rlc_config_t::srb_config(lcid));
}
void ttcn3_syssim::reestablish_bearer(uint32_t lcid)
void ttcn3_syssim::reestablish_bearer(const std::string cell_name, const uint32_t lcid)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't reestablish bearer. Cell %s not found.\n", cell_name.c_str());
return;
}
auto cell = get_cell(cell_name);
log->info("Reestablishing LCID=%d\n", lcid);
pdcp.reestablish(lcid);
rlc.reestablish(lcid);
cell->pdcp.reestablish(lcid);
cell->rlc.reestablish(lcid);
}
void ttcn3_syssim::del_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid)
void ttcn3_syssim::del_srb(const ttcn3_helpers::timing_info_t timing, const std::string cell_name, const uint32_t lcid)
{
if (timing.now) {
del_srb_impl(lcid);
del_srb_impl(cell_name, 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); });
tti_actions[timing.tti].push_back([this, cell_name, lcid]() { del_srb_impl(cell_name, lcid); });
}
}
void ttcn3_syssim::del_srb_impl(uint32_t lcid)
void ttcn3_syssim::del_srb_impl(const std::string cell_name, const uint32_t lcid)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't delete bearer. Cell %s not found.\n", cell_name.c_str());
return;
}
auto cell = get_cell(cell_name);
log->info("Deleting SRB%d\n", lcid);
// Only delete SRB1/2
if (lcid > 0) {
pdcp.del_bearer(lcid);
rlc.del_bearer(lcid);
cell->pdcp.del_bearer(lcid);
cell->rlc.del_bearer(lcid);
}
}
void ttcn3_syssim::add_drb(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
const uint32_t lcid,
const srslte::pdcp_config_t pdcp_config)
{
if (timing.now) {
add_drb_impl(lcid, pdcp_config);
add_drb_impl(cell_name, lcid, pdcp_config);
} else {
log->debug("Scheduling DRB%d addition for TTI=%d\n", lcid - 2, timing.tti);
tti_actions[timing.tti].push_back([this, lcid, pdcp_config]() { add_drb_impl(lcid, pdcp_config); });
tti_actions[timing.tti].push_back(
[this, cell_name, lcid, pdcp_config]() { add_drb_impl(cell_name, lcid, pdcp_config); });
}
}
void ttcn3_syssim::add_drb_impl(const uint32_t lcid, const pdcp_config_t pdcp_config)
void ttcn3_syssim::add_drb_impl(const std::string cell_name, const uint32_t lcid, const pdcp_config_t pdcp_config)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't add DRB. Cell %s not found.\n", cell_name.c_str());
return;
}
auto cell = get_cell(cell_name);
if (lcid > 2) {
log->info("Adding DRB%d\n", lcid - 2);
pdcp.add_bearer(lcid, pdcp_config);
rlc.add_bearer(lcid, srslte::rlc_config_t::default_rlc_am_config());
cell->pdcp.add_bearer(lcid, pdcp_config);
cell->rlc.add_bearer(lcid, srslte::rlc_config_t::default_rlc_am_config());
}
}
void ttcn3_syssim::del_drb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid)
void ttcn3_syssim::del_drb(const ttcn3_helpers::timing_info_t timing, const std::string cell_name, const uint32_t lcid)
{
if (timing.now) {
del_drb_impl(lcid);
del_drb_impl(cell_name, lcid);
} else {
log->debug("Scheduling DRB%d deletion for TTI=%d\n", lcid - 2, timing.tti);
tti_actions[timing.tti].push_back([this, lcid]() { del_drb_impl(lcid); });
tti_actions[timing.tti].push_back([this, cell_name, lcid]() { del_drb_impl(cell_name, lcid); });
}
}
void ttcn3_syssim::del_drb_impl(uint32_t lcid)
void ttcn3_syssim::del_drb_impl(const std::string cell_name, const uint32_t lcid)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't delete DRB. Cell %s not found.\n", cell_name.c_str());
return;
}
auto cell = get_cell(cell_name);
// Only delete DRB
if (lcid > 2) {
log->info("Deleting DRB%d\n", lcid - 2);
pdcp.del_bearer(lcid);
rlc.del_bearer(lcid);
cell->pdcp.del_bearer(lcid);
cell->rlc.del_bearer(lcid);
}
}
@ -1026,15 +1093,16 @@ void ttcn3_syssim::write_pdu(uint32_t lcid, unique_byte_buffer_t pdu)
pdu->N_bytes,
"RRC SDU received for LCID=%d cell_id=%d (%d B)\n",
lcid,
cells[pcell_idx]->cell.id,
cells[pcell_idx]->config.phy_cell.id,
pdu->N_bytes);
// push content to Titan
if (lcid <= 2) {
std::string out = ttcn3_helpers::get_rrc_pdu_ind_for_pdu(tti, lcid, cells[pcell_idx]->name, std::move(pdu));
std::string out = ttcn3_helpers::get_rrc_pdu_ind_for_pdu(tti, lcid, cells[pcell_idx]->config.name, std::move(pdu));
srb.tx(reinterpret_cast<const uint8_t*>(out.c_str()), out.length());
} else {
std::string out = ttcn3_helpers::get_drb_common_ind_for_pdu(tti, lcid, cells[pcell_idx]->name, std::move(pdu));
std::string out =
ttcn3_helpers::get_drb_common_ind_for_pdu(tti, lcid, cells[pcell_idx]->config.name, std::move(pdu));
drb.tx(reinterpret_cast<const uint8_t*>(out.c_str()), out.length());
}
}
@ -1102,6 +1170,7 @@ bool ttcn3_syssim::sdu_queue_is_full(uint32_t lcid)
}
void ttcn3_syssim::set_as_security(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name,
std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_int_,
std::array<uint8_t, 32> k_up_enc_,
@ -1110,24 +1179,33 @@ void ttcn3_syssim::set_as_security(const ttcn3_helpers::timing_info_t tim
const ttcn3_helpers::pdcp_count_map_t bearers_)
{
if (timing.now) {
set_as_security_impl(k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_);
set_as_security_impl(cell_name, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_);
} else {
log->debug("Scheduling AS security configuration for TTI=%d\n", timing.tti);
tti_actions[timing.tti].push_back([this, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_]() {
set_as_security_impl(k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_);
tti_actions[timing.tti].push_back(
[this, cell_name, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_]() {
set_as_security_impl(cell_name, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_);
});
}
}
void ttcn3_syssim::set_as_security_impl(std::array<uint8_t, 32> k_rrc_enc_,
void ttcn3_syssim::set_as_security_impl(const std::string cell_name,
std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_int_,
std::array<uint8_t, 32> k_up_enc_,
const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_,
const ttcn3_helpers::pdcp_count_map_t bearers)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't configure AS security. Cell %s not found.\n", cell_name.c_str());
return;
}
auto cell = get_cell(cell_name);
// store security config for later use (i.e. new bearer added)
sec_cfg = {.k_rrc_int = k_rrc_int_,
cell->sec_cfg = {.k_rrc_int = k_rrc_int_,
.k_rrc_enc = k_rrc_enc_,
.k_up_int = {},
.k_up_enc = k_up_enc_,
@ -1135,54 +1213,69 @@ void ttcn3_syssim::set_as_security_impl(std::array<uint8_t, 32>
.cipher_algo = cipher_algo_};
for (auto& lcid : bearers) {
pdcp.config_security(lcid.rb_id, sec_cfg);
cell->pdcp.config_security(lcid.rb_id, cell->sec_cfg);
log->info("Setting AS security for LCID=%d in DL direction from SN=%d onwards\n", lcid.rb_id, lcid.dl_value);
pdcp.enable_security_timed(lcid.rb_id, DIRECTION_TX, lcid.dl_value);
cell->pdcp.enable_security_timed(lcid.rb_id, DIRECTION_TX, lcid.dl_value);
log->info("Setting AS security for LCID=%d in UL direction from SN=%d onwards\n", lcid.rb_id, lcid.ul_value);
pdcp.enable_security_timed(lcid.rb_id, DIRECTION_RX, lcid.ul_value);
cell->pdcp.enable_security_timed(lcid.rb_id, DIRECTION_RX, lcid.ul_value);
}
}
void ttcn3_syssim::release_as_security(const ttcn3_helpers::timing_info_t timing)
void ttcn3_syssim::release_as_security(const ttcn3_helpers::timing_info_t timing, const std::string cell_name)
{
if (timing.now) {
release_as_security_impl();
release_as_security_impl(cell_name);
} else {
log->debug("Scheduling Release of AS security for TTI=%d\n", timing.tti);
tti_actions[timing.tti].push_back([this]() { release_as_security_impl(); });
tti_actions[timing.tti].push_back([this, cell_name]() { release_as_security_impl(cell_name); });
}
}
void ttcn3_syssim::release_as_security_impl()
void ttcn3_syssim::release_as_security_impl(const std::string cell_name)
{
if (not syssim_has_cell(cell_name)) {
log->error("Can't release AS security. Cell %s not found.\n", cell_name.c_str());
return;
}
auto cell = get_cell(cell_name);
log->info("Releasing AS security\n");
pending_bearer_config.clear();
cell->pending_bearer_config.clear();
}
void ttcn3_syssim::select_cell(srslte_cell_t phy_cell)
{
// find matching cell in SS cell list
for (uint32_t i = 0; i < cells.size(); ++i) {
if (cells[i]->cell.id == phy_cell.id) {
if (cells[i]->config.phy_cell.id == phy_cell.id) {
pcell_idx = i;
log->info("New PCell: PCI=%d\n", cells[pcell_idx]->cell.id);
log->info("New PCell: PCI=%d\n", cells[pcell_idx]->config.phy_cell.id);
return;
}
}
}
ttcn3_helpers::pdcp_count_map_t ttcn3_syssim::get_pdcp_count()
ttcn3_helpers::pdcp_count_map_t ttcn3_syssim::get_pdcp_count(const std::string cell_name)
{
// prepare response to SS
std::vector<ttcn3_helpers::pdcp_count_t> bearers;
if (not syssim_has_cell(cell_name)) {
log->error("Can't obtain PDCP count. Cell %s not found.\n", cell_name.c_str());
return bearers;
}
auto cell = get_cell(cell_name);
for (uint32_t i = 0; i < rb_id_vec.size(); i++) {
if (pdcp.is_lcid_enabled(i)) {
if (cell->pdcp.is_lcid_enabled(i)) {
ttcn3_helpers::pdcp_count_t bearer;
uint16_t tmp; // not handling HFN
srslte::pdcp_lte_state_t pdcp_state;
pdcp.get_bearer_state(i, &pdcp_state);
cell->pdcp.get_bearer_state(i, &pdcp_state);
bearer.rb_is_srb = i <= 2;
bearer.rb_id = i;
bearer.dl_value = pdcp_state.next_pdcp_tx_sn;

Loading…
Cancel
Save