|
|
|
@ -21,6 +21,9 @@
|
|
|
|
|
|
|
|
|
|
#include "rrc_nr_test_helpers.h"
|
|
|
|
|
#include "srsran/common/test_common.h"
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
#define NAS_SEC_CMD_STR "d9119b97d7bb59fc842d5b9cc12f00c27e9d5e4c80ee4cceb99a0dbbc6e0b54daa21a5d9e36d2e3b"
|
|
|
|
|
|
|
|
|
|
using namespace asn1::rrc_nr;
|
|
|
|
|
|
|
|
|
@ -30,6 +33,7 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched,
|
|
|
|
|
rrc_nr& rrc_obj,
|
|
|
|
|
rlc_nr_rrc_tester& rlc,
|
|
|
|
|
mac_nr_dummy& mac,
|
|
|
|
|
ngap_rrc_tester& ngap,
|
|
|
|
|
uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
srsran::unique_byte_buffer_t pdu;
|
|
|
|
@ -105,8 +109,9 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched,
|
|
|
|
|
complete_ies.registered_amf.amf_id.from_number(0x800101);
|
|
|
|
|
complete_ies.guami_type_present = true;
|
|
|
|
|
complete_ies.guami_type.value = rrc_setup_complete_ies_s::guami_type_opts::native;
|
|
|
|
|
complete_ies.ded_nas_msg.from_string("7E01280E534C337E004109000BF200F110800101347B80802E02F07071002D7E004109000BF200F"
|
|
|
|
|
"110800101347B80801001002E02F0702F0201015200F11000006418010174000090530101");
|
|
|
|
|
std::string NAS_msg_str = "7E01280E534C337E004109000BF200F110800101347B80802E02F07071002D7E004109000BF200F11080010134"
|
|
|
|
|
"7B80801001002E02F0702F0201015200F11000006418010174000090530101";
|
|
|
|
|
auto& ded_nas_msg = complete_ies.ded_nas_msg.from_string(NAS_msg_str);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
pdu = srsran::make_byte_buffer();
|
|
|
|
@ -127,6 +132,77 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
TESTASSERT(ss_ue_found); /// Ensure UE-specific SearchSpace was added
|
|
|
|
|
|
|
|
|
|
// Check here if the MSG sent to NGAP is correct
|
|
|
|
|
// Create a unbounded_octstring<false> for the expected MSG
|
|
|
|
|
asn1::unbounded_octstring<false> expected;
|
|
|
|
|
expected.from_string(NAS_msg_str);
|
|
|
|
|
TESTASSERT(expected == ngap.last_pdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched,
|
|
|
|
|
rrc_nr& rrc_obj,
|
|
|
|
|
pdcp_nr_rrc_tester& pdcp,
|
|
|
|
|
ngap_rrc_tester& ngap,
|
|
|
|
|
uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
// STEP 1 : Send DLInformationTransfer (gNB -> UE)
|
|
|
|
|
// generate sdu to pass as NAS message in DLInformationTransfer
|
|
|
|
|
srsran::unique_byte_buffer_t nsa_sdu;
|
|
|
|
|
nsa_sdu = srsran::make_byte_buffer();
|
|
|
|
|
|
|
|
|
|
// create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message)
|
|
|
|
|
asn1::unbounded_octstring<false> NAS_DL_msg;
|
|
|
|
|
NAS_DL_msg.from_string("21d9dfe07800371095c79a751be8352fb44aba7d69b836f5aad594ede9e72b8e34105ca8d7669d5c");
|
|
|
|
|
nsa_sdu->append_bytes(NAS_DL_msg.data(), NAS_DL_msg.size());
|
|
|
|
|
|
|
|
|
|
// trigger the RRC to send the DLInformationTransfer
|
|
|
|
|
rrc_obj.write_dl_info(rnti, std::move(nsa_sdu));
|
|
|
|
|
|
|
|
|
|
// Test whether there exists the SRB1 initiated in the Connection Establishment
|
|
|
|
|
// We test this as the SRB1 was setup in a different function
|
|
|
|
|
TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti);
|
|
|
|
|
TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid);
|
|
|
|
|
|
|
|
|
|
// Send SecurityModeCommand (gNB -> UE)
|
|
|
|
|
dl_dcch_msg_s dl_dcch_msg;
|
|
|
|
|
{
|
|
|
|
|
asn1::cbit_ref bref{pdcp.last_sdu->data(), pdcp.last_sdu->size()};
|
|
|
|
|
TESTASSERT_SUCCESS(dl_dcch_msg.unpack(bref));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test if the unpacked message retrived from PCDP is correct
|
|
|
|
|
TESTASSERT_EQ(dl_dcch_msg_type_c::types_opts::c1, dl_dcch_msg.msg.type().value);
|
|
|
|
|
TESTASSERT_EQ(dl_dcch_msg_type_c::c1_c_::types_opts::dl_info_transfer, dl_dcch_msg.msg.c1().type().value);
|
|
|
|
|
TESTASSERT_EQ(dl_info_transfer_s::crit_exts_c_::types_opts::dl_info_transfer,
|
|
|
|
|
dl_dcch_msg.msg.c1().dl_info_transfer().crit_exts.type().value);
|
|
|
|
|
|
|
|
|
|
dl_info_transfer_ies_s& ies_DL = dl_dcch_msg.msg.c1().dl_info_transfer().crit_exts.dl_info_transfer();
|
|
|
|
|
TESTASSERT(ies_DL.ded_nas_msg_present == true);
|
|
|
|
|
TESTASSERT(NAS_DL_msg == ies_DL.ded_nas_msg);
|
|
|
|
|
|
|
|
|
|
// STEP 2: Send ULInformationTransfer (UE -> gNB)
|
|
|
|
|
ul_dcch_msg_s ul_dcch_msg;
|
|
|
|
|
auto& ies_UL = ul_dcch_msg.msg.set_c1().set_ul_info_transfer().crit_exts.set_ul_info_transfer();
|
|
|
|
|
ies_UL.ded_nas_msg_present = true;
|
|
|
|
|
|
|
|
|
|
// Create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message)
|
|
|
|
|
// We reuse ies_UL below to compare the string with the message sent to and unpacked by the gNB
|
|
|
|
|
ies_UL.ded_nas_msg.from_string("6671f8bc80b1860f29b3a8b3b8563ce6c36a591bb1a3dc6612674448fb958d274426d326356aa9aa");
|
|
|
|
|
|
|
|
|
|
srsran::unique_byte_buffer_t pdu;
|
|
|
|
|
{
|
|
|
|
|
pdu = srsran::make_byte_buffer();
|
|
|
|
|
asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()};
|
|
|
|
|
TESTASSERT_SUCCESS(ul_dcch_msg.pack(bref));
|
|
|
|
|
pdu->N_bytes = bref.distance_bytes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// send message to RRC
|
|
|
|
|
rrc_obj.write_pdu(rnti, 1, std::move(pdu));
|
|
|
|
|
|
|
|
|
|
// compare if the actual transmitted matches with the MSG created from the original string
|
|
|
|
|
TESTASSERT(ies_UL.ded_nas_msg == ngap.last_pdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched,
|
|
|
|
@ -134,17 +210,22 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched,
|
|
|
|
|
pdcp_nr_rrc_tester& pdcp,
|
|
|
|
|
uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
srsran::unique_byte_buffer_t pdu;
|
|
|
|
|
// create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message)
|
|
|
|
|
asn1::unbounded_octstring<false> NAS_msg;
|
|
|
|
|
NAS_msg.from_string(NAS_SEC_CMD_STR);
|
|
|
|
|
srsran::unique_byte_buffer_t nas_pdu;
|
|
|
|
|
nas_pdu = srsran::make_byte_buffer();
|
|
|
|
|
nas_pdu->append_bytes(NAS_msg.data(), NAS_msg.size());
|
|
|
|
|
|
|
|
|
|
// Trigger Send SecurityCommand (simulate request from NGAP)
|
|
|
|
|
rrc_obj.start_security_mode_procedure(rnti, nullptr);
|
|
|
|
|
rrc_obj.start_security_mode_procedure(rnti, std::move(nas_pdu));
|
|
|
|
|
|
|
|
|
|
// Test whether there exists the SRB1 initiated in the Connection Establishment
|
|
|
|
|
// We test this as the SRB1 was setup in a different function
|
|
|
|
|
TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti);
|
|
|
|
|
TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), 1);
|
|
|
|
|
TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid);
|
|
|
|
|
|
|
|
|
|
// Send SecurityModeCommand (gNB -> UE)
|
|
|
|
|
// STEP 1 - Send SecurityModeCommand (gNB -> UE)
|
|
|
|
|
dl_dcch_msg_s dl_dcch_msg;
|
|
|
|
|
{
|
|
|
|
|
asn1::cbit_ref bref{pdcp.last_sdu->data(), pdcp.last_sdu->size()};
|
|
|
|
@ -161,12 +242,13 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched,
|
|
|
|
|
ies.security_cfg_smc.security_algorithm_cfg.integrity_prot_algorithm.value);
|
|
|
|
|
TESTASSERT_EQ(ciphering_algorithm_opts::nea0, ies.security_cfg_smc.security_algorithm_cfg.ciphering_algorithm.value);
|
|
|
|
|
|
|
|
|
|
// Send SecurityModeComplete (UE -> gNB)
|
|
|
|
|
// STEP 2 - Send SecurityModeComplete (UE -> gNB)
|
|
|
|
|
ul_dcch_msg_s ul_dcch_msg;
|
|
|
|
|
auto& sec_cmd_complete_msg = ul_dcch_msg.msg.set_c1().set_security_mode_complete();
|
|
|
|
|
sec_cmd_complete_msg.rrc_transaction_id = dl_dcch_msg.msg.c1().security_mode_cmd().rrc_transaction_id;
|
|
|
|
|
auto& ies_complete = sec_cmd_complete_msg.crit_exts.set_security_mode_complete();
|
|
|
|
|
|
|
|
|
|
srsran::unique_byte_buffer_t pdu;
|
|
|
|
|
{
|
|
|
|
|
pdu = srsran::make_byte_buffer();
|
|
|
|
|
asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()};
|
|
|
|
@ -178,4 +260,141 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched,
|
|
|
|
|
rrc_obj.write_pdu(rnti, 1, std::move(pdu));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched,
|
|
|
|
|
rrc_nr& rrc_obj,
|
|
|
|
|
pdcp_nr_rrc_tester& pdcp,
|
|
|
|
|
ngap_rrc_tester& ngap,
|
|
|
|
|
uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
// Test whether there exists the SRB1 initiated in the Connection Establishment
|
|
|
|
|
// We test this as the SRB1 was set up in a different function
|
|
|
|
|
TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti);
|
|
|
|
|
TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid);
|
|
|
|
|
|
|
|
|
|
dl_dcch_msg_s dl_dcch_msg;
|
|
|
|
|
{
|
|
|
|
|
asn1::cbit_ref bref{pdcp.last_sdu->data(), pdcp.last_sdu->size()};
|
|
|
|
|
TESTASSERT_SUCCESS(dl_dcch_msg.unpack(bref));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test whether the unpacked message is correct
|
|
|
|
|
TESTASSERT_EQ(dl_dcch_msg_type_c::types_opts::c1, dl_dcch_msg.msg.type().value);
|
|
|
|
|
TESTASSERT_EQ(dl_dcch_msg_type_c::c1_c_::types_opts::rrc_recfg, dl_dcch_msg.msg.c1().type().value);
|
|
|
|
|
TESTASSERT_EQ(rrc_recfg_s::crit_exts_c_::types_opts::rrc_recfg,
|
|
|
|
|
dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.type().value);
|
|
|
|
|
const rrc_recfg_ies_s& reconf_ies = dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.rrc_recfg();
|
|
|
|
|
|
|
|
|
|
// create an unbounded_octstring object that contains the same NAS message as in SecurityModeCommand
|
|
|
|
|
// The RRCreconfiguration reads the SecurityModeCommand NAS msg previously saved in the queue
|
|
|
|
|
asn1::unbounded_octstring<false> NAS_msg;
|
|
|
|
|
NAS_msg.from_string(NAS_SEC_CMD_STR);
|
|
|
|
|
TESTASSERT_EQ(true, reconf_ies.non_crit_ext.ded_nas_msg_list_present);
|
|
|
|
|
// Test if NAS_msg is the same as the one sent in SecurityModeCommand
|
|
|
|
|
TESTASSERT(NAS_msg == reconf_ies.non_crit_ext.ded_nas_msg_list[0]);
|
|
|
|
|
|
|
|
|
|
// STEP 2 - Send RRCReconfiguration (UE -> gNB)
|
|
|
|
|
ul_dcch_msg_s ul_dcch_msg;
|
|
|
|
|
auto& RRC_recfg_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete();
|
|
|
|
|
RRC_recfg_complete.rrc_transaction_id = dl_dcch_msg.msg.c1().rrc_recfg().rrc_transaction_id;
|
|
|
|
|
RRC_recfg_complete.crit_exts.set_rrc_recfg_complete();
|
|
|
|
|
|
|
|
|
|
srsran::unique_byte_buffer_t pdu;
|
|
|
|
|
{
|
|
|
|
|
pdu = srsran::make_byte_buffer();
|
|
|
|
|
asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()};
|
|
|
|
|
TESTASSERT_SUCCESS(ul_dcch_msg.pack(bref));
|
|
|
|
|
pdu->N_bytes = bref.distance_bytes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// send message to RRC
|
|
|
|
|
rrc_obj.write_pdu(rnti, 1, std::move(pdu));
|
|
|
|
|
|
|
|
|
|
// Verify the NGAP gets notified for the RRCReconfigurationComplete
|
|
|
|
|
TESTASSERT_EQ(true, ngap.last_rrc_recnf_complete);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void test_rrc_nr_2nd_reconfiguration(srsran::task_scheduler& task_sched,
|
|
|
|
|
rrc_nr& rrc_obj,
|
|
|
|
|
pdcp_nr_rrc_tester& pdcp,
|
|
|
|
|
ngap_rrc_tester& ngap,
|
|
|
|
|
uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
// Make sure the NGAP RRCReconfigurationComplete bool is reset to false
|
|
|
|
|
ngap.last_rrc_recnf_complete = false;
|
|
|
|
|
|
|
|
|
|
// create an unbounded_octstring object that contains a NAS message (we simulate a random NAS nas)
|
|
|
|
|
asn1::unbounded_octstring<false> NAS_msg;
|
|
|
|
|
NAS_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9");
|
|
|
|
|
|
|
|
|
|
// STEP 2 - Trigger and send RRCReconfiguration command (gNB -> UE)
|
|
|
|
|
rrc_obj.establish_rrc_bearer(rnti, 1, NAS_msg, srsran::srb_to_lcid(srsran::nr_srb::srb1));
|
|
|
|
|
|
|
|
|
|
// Test whether there exists the SRB1 initiated in the Connection Establishment
|
|
|
|
|
// We test this as the SRB1 was set up in a different function
|
|
|
|
|
TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti);
|
|
|
|
|
TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid);
|
|
|
|
|
|
|
|
|
|
dl_dcch_msg_s dl_dcch_msg;
|
|
|
|
|
{
|
|
|
|
|
asn1::cbit_ref bref{pdcp.last_sdu->data(), pdcp.last_sdu->size()};
|
|
|
|
|
TESTASSERT_SUCCESS(dl_dcch_msg.unpack(bref));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test whether the unpacked message is correct
|
|
|
|
|
TESTASSERT_EQ(dl_dcch_msg_type_c::types_opts::c1, dl_dcch_msg.msg.type().value);
|
|
|
|
|
TESTASSERT_EQ(dl_dcch_msg_type_c::c1_c_::types_opts::rrc_recfg, dl_dcch_msg.msg.c1().type().value);
|
|
|
|
|
TESTASSERT_EQ(rrc_recfg_s::crit_exts_c_::types_opts::rrc_recfg,
|
|
|
|
|
dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.type().value);
|
|
|
|
|
const rrc_recfg_ies_s& reconf_ies = dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.rrc_recfg();
|
|
|
|
|
TESTASSERT_EQ(true, reconf_ies.radio_bearer_cfg_present);
|
|
|
|
|
TESTASSERT_EQ(true, reconf_ies.radio_bearer_cfg.srb_to_add_mod_list_present);
|
|
|
|
|
TESTASSERT_EQ(1, reconf_ies.radio_bearer_cfg.srb_to_add_mod_list.size());
|
|
|
|
|
TESTASSERT_EQ(2, reconf_ies.radio_bearer_cfg.srb_to_add_mod_list[0].srb_id);
|
|
|
|
|
TESTASSERT_EQ(1, reconf_ies.radio_bearer_cfg.drb_to_add_mod_list.size());
|
|
|
|
|
auto& drb = reconf_ies.radio_bearer_cfg.drb_to_add_mod_list[0];
|
|
|
|
|
TESTASSERT_EQ(1, drb.drb_id);
|
|
|
|
|
|
|
|
|
|
TESTASSERT_EQ(true, reconf_ies.non_crit_ext_present);
|
|
|
|
|
TESTASSERT_EQ(true, reconf_ies.non_crit_ext.master_cell_group_present);
|
|
|
|
|
auto& master_group_msg = reconf_ies.non_crit_ext.master_cell_group;
|
|
|
|
|
|
|
|
|
|
cell_group_cfg_s master_cell_group;
|
|
|
|
|
{
|
|
|
|
|
asn1::cbit_ref bref{master_group_msg.data(), master_group_msg.size()};
|
|
|
|
|
TESTASSERT_SUCCESS(master_cell_group.unpack(bref));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test if the master_cell_group SRB and DRB IDs match those in the RadioBearerConfig
|
|
|
|
|
TESTASSERT_EQ(0, master_cell_group.cell_group_id);
|
|
|
|
|
TESTASSERT_EQ(true, master_cell_group.rlc_bearer_to_add_mod_list_present);
|
|
|
|
|
auto& rlc_srb = master_cell_group.rlc_bearer_to_add_mod_list[0];
|
|
|
|
|
TESTASSERT_EQ(reconf_ies.radio_bearer_cfg.srb_to_add_mod_list[0].srb_id, rlc_srb.served_radio_bearer.srb_id());
|
|
|
|
|
auto& rlc_drb = master_cell_group.rlc_bearer_to_add_mod_list[1];
|
|
|
|
|
TESTASSERT_EQ(reconf_ies.radio_bearer_cfg.drb_to_add_mod_list[0].drb_id, rlc_drb.served_radio_bearer.drb_id());
|
|
|
|
|
|
|
|
|
|
// Test if NAS_msg is the same as the one sent in DLInformationTransfer
|
|
|
|
|
TESTASSERT_EQ(true, reconf_ies.non_crit_ext.ded_nas_msg_list_present);
|
|
|
|
|
TESTASSERT(NAS_msg == reconf_ies.non_crit_ext.ded_nas_msg_list[0]);
|
|
|
|
|
|
|
|
|
|
// STEP 2 - Send RRCReconfiguration (UE -> gNB)
|
|
|
|
|
ul_dcch_msg_s ul_dcch_msg;
|
|
|
|
|
auto& RRC_recfg_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete();
|
|
|
|
|
RRC_recfg_complete.rrc_transaction_id = dl_dcch_msg.msg.c1().rrc_recfg().rrc_transaction_id;
|
|
|
|
|
RRC_recfg_complete.crit_exts.set_rrc_recfg_complete();
|
|
|
|
|
|
|
|
|
|
srsran::unique_byte_buffer_t pdu;
|
|
|
|
|
{
|
|
|
|
|
pdu = srsran::make_byte_buffer();
|
|
|
|
|
asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()};
|
|
|
|
|
TESTASSERT_SUCCESS(ul_dcch_msg.pack(bref));
|
|
|
|
|
pdu->N_bytes = bref.distance_bytes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// send message to RRC
|
|
|
|
|
rrc_obj.write_pdu(rnti, 1, std::move(pdu));
|
|
|
|
|
|
|
|
|
|
// Verify the NGAP gets notified for the RRCReconfigurationComplete
|
|
|
|
|
TESTASSERT_EQ(true, ngap.last_rrc_recnf_complete);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace srsenb
|
|
|
|
|