Commit d75a1097 authored by batuhanduyuler's avatar batuhanduyuler Committed by batuhan duyuler

N2 Handover Target gNB Implementation

Handover Request Message Processing
	- AMF selection respect to GUAMI
	- UE Context Creation in CU - NGAP
	- UE Context Setup Request with HO Preparation Information according to F1AP Spec

UE Context Setup Request Processing
	- If HO Preparation Information Exists, DU process this message in another function
	- Cell Group Configuration is created from target gNB's initial cell group. Then it is updated using UE Capability
	- Reconfiguration with sync IE is prepared similar to the used one for NSA

nr_pdcp_config_set_security function signature is changed and security_mode_completed input is added because from beginning we want to set pdcp_entity's security mode completed flag to true in case of handover.
Handover Request Acknowledge message preparation is done.
After reception of RRC Reconfiguration Complete message on target gNB; Handover Notify Message is triggered
parent 10629df5
......@@ -371,6 +371,8 @@ typedef struct cu_to_du_rrc_information_s {
uint32_t uE_CapabilityRAT_ContainerList_length;
uint8_t * measConfig;
uint32_t measConfig_length;
uint8_t * handoverPreparationInfo;
uint32_t handoverPreparationInfo_length;
}cu_to_du_rrc_information_t;
typedef struct du_to_cu_rrc_information_s {
......
......@@ -74,9 +74,12 @@ MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, ngap_pdu
MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_resp_t , ngap_pdusession_modify_resp)
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdusession_release_resp_t , ngap_pdusession_release_resp)
MESSAGE_DEF(NGAP_HANDOVER_REQUIRED , MESSAGE_PRIORITY_MED, ngap_handover_required_t , ngap_handover_required)
MESSAGE_DEF(NGAP_HANDOVER_REQUEST_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, ngap_handover_request_ack_t , ngap_handover_request_ack)
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, ngap_path_switch_req_t , ngap_path_switch_req)
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, ngap_path_switch_req_ack_t , ngap_path_switch_req_ack)
MESSAGE_DEF(NGAP_PDUSESSION_MODIFICATION_IND , MESSAGE_PRIORITY_MED, ngap_pdusession_modification_ind_t , ngap_pdusession_modification_ind)
MESSAGE_DEF(NGAP_HANDOVER_NOTIFY , MESSAGE_PRIORITY_MED, ngap_handover_notify_t , ngap_handover_notify)
/* NGAP -> RRC messages */
MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas )
......@@ -88,6 +91,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_REQ , MESSAGE_PRIORITY_MED, ngap_pd
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_COMMAND , MESSAGE_PRIORITY_MED, ngap_pdusession_release_command_t , ngap_pdusession_release_command)
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND, MESSAGE_PRIORITY_MED, ngap_ue_release_command_t , ngap_ue_release_command)
MESSAGE_DEF(NGAP_HANDOVER_COMMAND , MESSAGE_PRIORITY_MED, ngap_handover_command_t , ngap_handover_command)
MESSAGE_DEF(NGAP_HANDOVER_REQUEST , MESSAGE_PRIORITY_MED, ngap_handover_request_t , ngap_handover_request)
/* NGAP <-> RRC messages (can be initiated either by MME or gNB) */
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req)
......@@ -67,6 +67,9 @@
#define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind
#define NGAP_HANDOVER_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_required
#define NGAP_HANDOVER_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_command
#define NGAP_HANDOVER_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request
#define NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request_ack
#define NGAP_HANDOVER_NOTIFY(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_notify
#define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req
#define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command
......@@ -550,6 +553,11 @@ typedef struct handover_drb_item_s {
bool isActive;
} handover_drb_item_t;
typedef struct ngap_handover_notify_s {
uint32_t gNB_ue_ngap_id;
uint64_t amf_ue_ngap_id;
uint32_t nrCellId;
} ngap_handover_notify_t;
typedef struct ngap_handover_required_s {
uint32_t gNB_ue_ngap_id;
......@@ -563,6 +571,14 @@ typedef struct ngap_handover_required_s {
uint32_t handoverType; // 0 for intra5gs
} ngap_handover_required_t;
typedef struct ngap_handover_request_ack_s {
uint32_t gNB_ue_ngap_id;
uint64_t amf_ue_ngap_id;
pdusession_setup_t pdusessions[NGAP_MAX_PDUSESSION];
uint8_t nb_of_pdusessions;
ngap_pdu_t targetToSourceTransparentContainer;
} ngap_handover_request_ack_t;
typedef struct ngap_handover_command_s {
uint32_t gNB_ue_ngap_id;
uint64_t amf_ue_ngap_id;
......@@ -573,6 +589,22 @@ typedef struct ngap_handover_command_s {
pdusession_setup_t pduSessionResourceHandoverList[NGAP_MAX_PDUSESSION]; //for data forwarding
} ngap_handover_command_t;
typedef struct ngap_handover_request_s {
uint64_t amf_ue_ngap_id;
uint8_t nb_of_pdusessions;
pdusession_t pduSessionResourceSetupHOList[NGAP_MAX_PDUSESSION];
ngap_pdu_t sourceToTargetTransparentContainer;
ngap_ambr_t ue_ambr;
ngap_guami_t guami;
uint8_t nb_allowed_nssais;
nssai_t allowed_nssai[8];
ngap_security_capabilities_t security_capabilities;
uint8_t next_hop[SECURITY_KEY_LENGTH];
uint8_t next_hop_chain_count;
uint8_t mobility_restriction_flag;
ngap_mobility_restriction_t mobility_restriction;
} ngap_handover_request_t;
typedef struct ngap_ue_cap_info_ind_s {
uint32_t gNB_ue_ngap_id;
ngap_pdu_t ue_radio_cap;
......
......@@ -887,7 +887,7 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig
if (ra_index == NR_NB_RA_PROC_MAX) {
LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti);
return false;
}
}
NR_RA_t *ra = &cc->ra[ra_index];
ra->cfra = true;
ra->rnti = rnti;
......@@ -905,7 +905,7 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig
}
}
}
LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", rnti);
LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup with RA Index %u\n", ra->cfra ? "CFRA" : "CBRA", rnti, ra_index);
return true;
}
......
......@@ -134,12 +134,10 @@ static int nr_process_mac_pdu(instance_t module_idP,
uint16_t mac_len=0;
uint16_t mac_subheader_len=sizeof(NR_MAC_SUBHEADER_FIXED);
uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID;
LOG_D(NR_MAC, "In %s: received UL-SCH sub-PDU with LCID 0x%x in %d.%d (remaining PDU length %d)\n", __func__, rx_lcid, frameP, slot, pdu_len);
unsigned char *ce_ptr;
int n_Lcg = 0;
switch(rx_lcid){
// MAC CE
/*#ifdef DEBUG_HEADER_PARSING
......@@ -483,12 +481,13 @@ static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid)
sched_ctrl->sched_ul_bytes = 0;
}
static bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, const int CC_id, const frame_t frame, const sub_frame_t slot)
static bool get_UE_waiting_CFRA_msg3(const NR_UE_info_t *UE, const gNB_MAC_INST *gNB_mac, const int CC_id, const frame_t frame, const sub_frame_t slot)
{
bool UE_waiting_CFRA_msg3 = false;
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
const NR_RA_t *ra = &gNB_mac->common_channels[CC_id].ra[i];
if (ra->cfra == true && ra->state == WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot) {
// LOG_D(NR_MAC, "\nra-cfra: %d , ra->state: %d, raMsg3Frame: %u, raMsg3 Slot: %u\n", ra->cfra, ra->state, ra->Msg3_frame, ra->Msg3_slot);
if (ra->cfra == true && ra->state == WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot && UE->rnti == ra->rnti) {
UE_waiting_CFRA_msg3 = true;
break;
}
......@@ -506,7 +505,7 @@ void handle_nr_ul_harq(const int CC_idP,
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti);
bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(nrmac, CC_idP, frame, slot);
bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(UE, nrmac, CC_idP, frame, slot);
if (!UE || UE_waiting_CFRA_msg3 == true) {
LOG_D(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti);
......@@ -598,8 +597,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
const int pusch_failure_thres = gNB_mac->pusch_failure_thres;
NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti);
bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(gNB_mac, CC_idP, frameP, slotP);
bool UE_waiting_CFRA_msg3 = false;
if (UE != NULL)
{
UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(UE, gNB_mac, CC_idP, frameP, slotP);
}
if (UE && UE_waiting_CFRA_msg3 == false) {
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
......@@ -684,7 +688,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
}
}
} else if(sduP) {
bool no_sig = true;
for (int k = 0; k < sdu_lenP; k++) {
if(sduP[k]!=0) {
......@@ -716,13 +719,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// random access pusch with TC-RNTI
if (ra->rnti != current_rnti) {
LOG_D(NR_MAC,
LOG_E(NR_MAC,
"expected TC_RNTI %04x to match current RNTI %04x\n",
ra->rnti,
current_rnti);
if( (frameP==ra->Msg3_frame) && (slotP==ra->Msg3_slot) ) {
LOG_D(NR_MAC, "Random Access %i failed at state %i (TC_RNTI %04x RNTI %04x)\n", i, ra->state,ra->rnti,current_rnti);
LOG_E(NR_MAC, "Random Access %i failed at state %i (TC_RNTI %04x RNTI %04x)\n", i, ra->state,ra->rnti,current_rnti);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
}
......@@ -742,12 +745,12 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// re-initialize ta update variables after RA procedure completion
UE_msg3_stage->UE_sched_ctrl.ta_frame = frameP;
LOG_D(NR_MAC,
LOG_E(NR_MAC,
"reset RA state information for RA-RNTI 0x%04x/index %d\n",
ra->rnti,
i);
LOG_I(NR_MAC,
LOG_E(NR_MAC,
"[gNB %d][RAPROC] PUSCH with TC_RNTI 0x%04x received correctly, "
"adding UE MAC Context RNTI 0x%04x\n",
gnb_mod_idP,
......@@ -761,15 +764,21 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
UE_scheduling_control->ta_update = timing_advance;
UE_scheduling_control->raw_rssi = rssi;
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640;
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE_msg3_stage->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
LOG_E(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE_msg3_stage->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
if (ra->cfra) {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti);
nr_mac_reset_ul_failure(UE_scheduling_control);
reset_dl_harq_list(UE_scheduling_control);
reset_ul_harq_list(UE_scheduling_control);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
process_CellGroup(ra->CellGroup, UE_msg3_stage);
if (UE->isUEDoingHandover)
{
LOG_I(NR_MAC, "HO LOG: NR Process PDU is calling after CFRA for rnti: 0x%04x\n", UE->rnti);
nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, 0);
UE->Msg4_ACKed = true;
} else {
process_CellGroup(ra->CellGroup, UE_msg3_stage);
}
} else {
LOG_A(NR_MAC,"[RAPROC] RA-Msg3 received (sdu_lenP %d)\n",sdu_lenP);
......@@ -836,7 +845,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// for CFRA (NSA) do not schedule retransmission of msg3
if (ra->cfra) {
LOG_D(NR_MAC, "Random Access %i failed at state %i (NSA msg3 reception failed)\n", i, ra->state);
LOG_E(NR_MAC, "Random Access %i failed at state %i (NSA msg3 reception failed)\n", i, ra->state);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
return;
}
......
......@@ -24,10 +24,13 @@
#include "mac_proto.h"
#include "openair2/F1AP/f1ap_ids.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
#include "oai_asn1.h"
#include "F1AP_CauseRadioNetwork.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
#include "SIMULATION/TOOLS/sim.h" // for taus();
// Standarized 5QI values and Default Priority levels as mentioned in 3GPP TS 23.501 Table 5.7.4-1
const uint64_t qos_fiveqi[26] = {1, 2, 3, 4, 65, 66, 67, 71, 72, 73, 74, 76, 5, 6, 7, 8, 9, 69, 70, 79, 80, 82, 83, 84, 85, 86};
......@@ -291,8 +294,163 @@ static void set_QoSConfig(const f1ap_ue_context_modif_req_t *req, NR_UE_sched_ct
}
}
void clone_SCC(const NR_ServingCellConfigCommon_t *orig, NR_ServingCellConfigCommon_t** cloned)
{
uint8_t buf[16636];
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_ServingCellConfigCommon, NULL, orig, buf, sizeof(buf));
AssertFatal(enc_rval.encoded > 0, "could not clone Serving Cell Config Common: problem while encoding\n");
asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_ServingCellConfigCommon, (void **)&(*cloned), buf, enc_rval.encoded, 0, 0);
AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded,
"could not clone Serving Cell Config Common: problem while decoding\n");
}
void fill_reconfiguration_with_sync_for_new_ue(NR_UE_info_t** ue_pP)
{
NR_UE_info_t* UE = *ue_pP;
gNB_MAC_INST *mac = RC.nrmac[0];
int CC_id = 0;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
UE->CellGroup->spCellConfig->reconfigurationWithSync = calloc(1, sizeof(*(UE->CellGroup->spCellConfig->reconfigurationWithSync)));
NR_ReconfigurationWithSync_t *reconfigurationWithSync = UE->CellGroup->spCellConfig->reconfigurationWithSync;
reconfigurationWithSync->newUE_Identity = UE->rnti;
reconfigurationWithSync->t304 = NR_ReconfigurationWithSync__t304_ms2000;
reconfigurationWithSync->rach_ConfigDedicated = NULL;
reconfigurationWithSync->ext1 = NULL;
// For 2-step contention-free random access procedure
reconfigurationWithSync->rach_ConfigDedicated = calloc(1, sizeof(*reconfigurationWithSync->rach_ConfigDedicated));
reconfigurationWithSync->rach_ConfigDedicated->present = NR_ReconfigurationWithSync__rach_ConfigDedicated_PR_uplink;
reconfigurationWithSync->rach_ConfigDedicated->choice.uplink = calloc(1, sizeof(struct NR_RACH_ConfigDedicated));
reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra = calloc(1, sizeof(struct NR_CFRA));
reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->ra_Prioritization = NULL;
reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions = calloc(1, sizeof(struct NR_CFRA__occasions));
memcpy(&reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->rach_ConfigGeneric,
&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric,
sizeof(NR_RACH_ConfigGeneric_t));
asn1cCallocOne(reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion,
NR_CFRA__occasions__ssb_perRACH_Occasion_one);
reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb;
reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb =
calloc(1, sizeof(struct NR_CFRA__resources__ssb));
reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0;
uint64_t bitmap = get_ssb_bitmap(scc);
int n_ssb = 0;
struct NR_CFRA_SSB_Resource *ssbElem[64];
for (int i = 0; i < 64; i++) {
if ((bitmap >> (63 - i)) & 0x01) {
ssbElem[n_ssb] = calloc(1, sizeof(struct NR_CFRA_SSB_Resource));
ssbElem[n_ssb]->ssb = i;
ssbElem[n_ssb]->ra_PreambleIndex = 63 - (UE->uid % 64);
asn1cSeqAdd(&UE->CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources
.choice.ssb->ssb_ResourceList.list,
ssbElem[n_ssb]);
n_ssb++;
}
}
reconfigurationWithSync->spCellConfigCommon = (NR_ServingCellConfigCommon_t*)calloc(1, sizeof(NR_ServingCellConfigCommon_t));
scc->uplinkConfigCommon->dummy = NR_TimeAlignmentTimer_infinity;
clone_SCC(scc, &(reconfigurationWithSync->spCellConfigCommon));
UE->CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->ext1 = NULL;
}
void process_ue_context_setup_request_for_handover(const f1ap_ue_context_setup_t* req) {
gNB_MAC_INST *mac = RC.nrmac[0];
f1ap_ue_context_setup_t resp = {
.gNB_CU_ue_id = req->gNB_CU_ue_id,
};
NR_SCHED_LOCK(&mac->sched_lock);
rnti_t newUE_Identity = (rnti_t)(taus() & 0xffff);
NR_UE_info_t* UE = add_new_nr_ue(mac, newUE_Identity, NULL);
f1_ue_data_t new_ue_data = {.secondary_ue = req->gNB_CU_ue_id};
du_add_f1_ue_data(UE->rnti, &new_ue_data);
/* create this UE's initial CellGroup */
int CC_id = 0;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig;
NR_CellGroupConfig_t * cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
UE->CellGroup = cellGroupConfig;
UE->isUEDoingHandover = true;
fill_reconfiguration_with_sync_for_new_ue(&UE);
nr_rlc_activate_srb0(UE->rnti, UE, send_initial_ul_rrc_message);
NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup);
if (req->srbs_to_be_setup_length > 0) {
resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE->rnti,
req->srbs_to_be_setup_length,
req->srbs_to_be_setup,
&resp.srbs_to_be_setup,
new_CellGroup);
}
if (req->drbs_to_be_setup_length > 0) {
resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE->rnti,
req->drbs_to_be_setup_length,
req->drbs_to_be_setup,
&resp.drbs_to_be_setup,
new_CellGroup);
}
//Take this guy from HO Prep Information!
NR_UE_NR_Capability_t *ue_cap = NULL;
if (req->cu_to_du_rrc_information != NULL) {
AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
ue_cap = get_ue_nr_cap(UE->rnti,
req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList,
req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length);
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n");
}
UE->capability = ue_cap;
if (ue_cap != NULL) {
// store the new UE capabilities, and update the cellGroupConfig
LOG_I(NR_MAC, "UE %04x: received capabilities, updating CellGroupConfig\n", UE->rnti);
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
}
resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t));
AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024);
AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n");
asn_enc_rval_t enc_rval =
uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, resp.du_to_cu_rrc_information->cellGroupConfig, 1024);
AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
nr_mac_enable_ue_rrc_processing_timer(mac, UE, true);
/* Set NSSAI config in MAC for each active DRB */
set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl);
NR_SCHED_UNLOCK(&mac->sched_lock);
LOG_I(NR_MAC, "HO LOG: UE Cell Group Config is successfully assigned for the UE with rnti: %u\n", UE->rnti);
resp.gNB_DU_ue_id = UE->rnti;
mac->mac_rrc.ue_context_setup_response(req, &resp);
/* free the memory we allocated above */
free(resp.srbs_to_be_setup);
free(resp.drbs_to_be_setup);
free(resp.du_to_cu_rrc_information->cellGroupConfig);
free(resp.du_to_cu_rrc_information);
}
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
{
if (req->cu_to_du_rrc_information != NULL && req->cu_to_du_rrc_information->handoverPreparationInfo != NULL && req->cu_to_du_rrc_information->handoverPreparationInfo_length > 0) {
LOG_I(NR_MAC, "HO LOG: UE Context Setup Request has came for Handover!\n");
process_ue_context_setup_request_for_handover(req);
return;
}
gNB_MAC_INST *mac = RC.nrmac[0];
/* response has same type as request... */
f1ap_ue_context_setup_t resp = {
......@@ -596,7 +754,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
du_add_f1_ue_data(dl_rrc->gNB_DU_ue_id, &new_ue_data);
}
if (UE->expect_reconfiguration && dl_rrc->srb_id == DCCH) {
if (UE->expect_reconfiguration && dl_rrc->srb_id == DCCH && UE->isUEDoingHandover == false) {
/* we expected a reconfiguration, and this is on DCCH. We assume this is
* the reconfiguration: nr_mac_prepare_cellgroup_update() already stored
* the CellGroupConfig. Below, we trigger a timer, and the CellGroupConfig
......
......@@ -70,7 +70,7 @@ static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req,
{
DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length);
(void) req; /* we don't need the request -- it is to set up GTP in F1 case */
// (void) req; /* we don't need the request -- it is to set up GTP in F1 case */
MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP);
msg->ittiMsgHeader.originInstance = -1; // means monolithic
f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg);
......
......@@ -718,6 +718,7 @@ typedef struct {
float ul_thr_ue;
float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook;
bool isUEDoingHandover;
} NR_UE_info_t;
typedef struct {
......
......@@ -103,7 +103,6 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
}
rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn;
if (entity->has_ciphering)
entity->cipher(entity->security_context,
buffer+header_size, size-header_size,
......
......@@ -21,6 +21,7 @@
#include "nr_pdcp_integrity_nia1.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
......@@ -52,6 +53,8 @@ void nr_pdcp_integrity_nia1_integrity(void *integrity_context,
ctx->bearer = bearer-1;
ctx->direction = direction;
ctx->blength = length * 8;
fprintf(stdout, "PDCP Context For NIA1 Integrity: count: %u\n", ctx->count);
fflush(stdout);
stream_compute_integrity(EIA1_128_ALG_ID, ctx, out);
}
......
......@@ -1019,7 +1019,8 @@ void nr_pdcp_config_set_security(ue_id_t ue_id,
const uint8_t security_modeP,
uint8_t *const kRRCenc_pP,
uint8_t *const kRRCint_pP,
uint8_t *const kUPenc_pP)
uint8_t *const kUPenc_pP,
bool security_mode_completed)
{
nr_pdcp_ue_t *ue;
nr_pdcp_entity_t *rb;
......@@ -1044,7 +1045,7 @@ void nr_pdcp_config_set_security(ue_id_t ue_id,
ciphering_algorithm = security_modeP & 0x0f;
rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP,
ciphering_algorithm, (char *)kRRCenc_pP);
rb->security_mode_completed = false;
rb->security_mode_completed = security_mode_completed;
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
......
......@@ -85,7 +85,8 @@ void nr_pdcp_config_set_security(ue_id_t ue_id,
const uint8_t security_modeP,
uint8_t *const kRRCenc_pP,
uint8_t *const kRRCint_pP,
uint8_t *const kUPenc_pP);
uint8_t *const kUPenc_pP,
bool security_mode_completed);
bool cu_f1u_data_req(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
......
......@@ -665,7 +665,7 @@ int do_NR_RRCRelease(uint8_t *buffer, size_t buffer_size, uint8_t Transaction_id
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_DL_DCCH_Message, &dl_dcch_msg);
return((enc_rval.encoded+7)/8);
}
int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
uint8_t *buffer,
size_t buffer_size,
......@@ -676,7 +676,8 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
NR_SecurityConfig_t *security_config,
NR_MeasConfig_t *meas_config,
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList,
NR_CellGroupConfig_t *cellGroupConfig)
NR_CellGroupConfig_t *cellGroupConfig,
bool masterKeyUpdate)
//------------------------------------------------------------------------------
{
asn_enc_rval_t enc_rval;
......@@ -697,6 +698,16 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
ie->radioBearerConfig->drb_ToReleaseList = DRB_releaseList;
}
if (masterKeyUpdate) {
ie->radioBearerConfig->securityConfig = (NR_SecurityConfig_t*)calloc(1, sizeof(NR_SecurityConfig_t));
ie->radioBearerConfig->securityConfig->keyToUse = (long*)calloc(1, sizeof(long));
*ie->radioBearerConfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master;
ie->radioBearerConfig->securityConfig->securityAlgorithmConfig = (NR_SecurityAlgorithmConfig_t*)calloc(1, sizeof(NR_SecurityAlgorithmConfig_t));
ie->radioBearerConfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = UE->ciphering_algorithm;
ie->radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm = (NR_IntegrityProtAlgorithm_t*)calloc(1, sizeof(NR_IntegrityProtAlgorithm_t));
*ie->radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm = UE->integrity_algorithm;
}
/******************** Meas Config ********************/
// measConfig
ie->measConfig = meas_config;
......@@ -709,6 +720,18 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
}
if (cellGroupConfig != NULL) {
if (cellGroupConfig->rlc_BearerToAddModList == NULL)
{
cellGroupConfig->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
for (int i = 1; i < UE->masterCellGroup->rlc_BearerToAddModList->list.count; ++i)
asn1cSeqAdd(&cellGroupConfig->rlc_BearerToAddModList->list, UE->masterCellGroup->rlc_BearerToAddModList->list.array[i]);
}
for (int i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) {
asn1cCallocOne(cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC,
NR_RLC_BearerConfig__reestablishRLC_true);
}
uint8_t *buf = NULL;
ssize_t len = uper_encode_to_new_buffer(&asn_DEF_NR_CellGroupConfig, NULL, cellGroupConfig, (void **)&buf);
AssertFatal(len > 0, "ASN1 message encoding failed (%lu)!\n", len);
......@@ -720,6 +743,11 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
ie->nonCriticalExtension->masterCellGroup->size = len;
}
if (masterKeyUpdate) {
ie->nonCriticalExtension->masterKeyUpdate = calloc(1, sizeof(NR_MasterKeyUpdate_t));
ie->nonCriticalExtension->masterKeyUpdate->keySetChangeIndicator = false;
ie->nonCriticalExtension->masterKeyUpdate->nextHopChainingCount = UE->nh_ncc;
}
rrcReconf->criticalExtensions.choice.rrcReconfiguration = ie;
......@@ -1312,6 +1340,114 @@ NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs)
return mc;
}
void remove_source_gnb_measurement_configuration(rrc_gNB_ue_context_t *ue_context_p)
{
gNB_RRC_UE_t* UE = &ue_context_p->ue_context;
if (UE->measConfig == NULL) {
LOG_E(NR_RRC, "HO LOG: UE's Measurement Configuration is NULL!\n");
return;
}
NR_HandoverPreparationInformation_t *hoPrepInformation = NULL;
asn_dec_rval_t hoPrep_dec_rval = uper_decode_complete(NULL,
&asn_DEF_NR_HandoverPreparationInformation,
(void **)&hoPrepInformation,
(uint8_t *)UE->ue_handover_prep_info_buffer.buf,
UE->ue_handover_prep_info_buffer.len);
AssertFatal(hoPrep_dec_rval.code == RC_OK && hoPrep_dec_rval.consumed > 0, "Handover Prep Info decode error\n");
NR_RRCReconfiguration_t* rrcReconf = NULL;
NR_AS_Config_t* sourceConfig = hoPrepInformation->criticalExtensions.choice.c1->choice.handoverPreparationInformation->sourceConfig;
asn_dec_rval_t rrcReconf_dec_rval = uper_decode_complete(NULL,
&asn_DEF_NR_RRCReconfiguration,
(void **)&rrcReconf,
(uint8_t *)sourceConfig->rrcReconfiguration.buf,
sourceConfig->rrcReconfiguration.size);
AssertFatal(rrcReconf_dec_rval.code == RC_OK && rrcReconf_dec_rval.consumed > 0, "Source gNB RRC Reconfig decode error\n");
if (rrcReconf->criticalExtensions.choice.rrcReconfiguration->measConfig == NULL)
return;
NR_MeasConfig_t *sourceMC = rrcReconf->criticalExtensions.choice.rrcReconfiguration->measConfig;
NR_MeasConfig_t *currentMC = UE->measConfig;
if (sourceMC->measObjectToAddModList->list.count > 0) {
currentMC->measObjectToRemoveList = calloc(1, sizeof(*currentMC->measObjectToRemoveList));
for (int i = 0; i < sourceMC->measObjectToAddModList->list.count; i++) {
NR_MeasObjectId_t* measObjId = calloc(1, sizeof(NR_MeasObjectId_t));
*measObjId = sourceMC->measObjectToAddModList->list.array[i]->measObjectId;
asn1cSeqAdd(&currentMC->measObjectToRemoveList->list, measObjId);
}
}
if (sourceMC->reportConfigToAddModList->list.count > 0) {
currentMC->reportConfigToRemoveList = calloc(1, sizeof(*currentMC->reportConfigToRemoveList));
for (int i = 0; i < sourceMC->reportConfigToAddModList->list.count; i++) {
NR_ReportConfigId_t* reportConfigId = calloc(1, sizeof(NR_ReportConfigId_t));
*reportConfigId = sourceMC->reportConfigToAddModList->list.array[i]->reportConfigId;
asn1cSeqAdd(&currentMC->reportConfigToRemoveList->list, reportConfigId);
}
}
if (sourceMC->measIdToAddModList->list.count > 0) {
currentMC->measIdToRemoveList = calloc(1, sizeof(*currentMC->measIdToRemoveList));
for (int i = 0; i < sourceMC->measIdToAddModList->list.count; i++) {
NR_MeasId_t* measId = calloc(1, sizeof(NR_MeasId_t));
*measId = sourceMC->measIdToAddModList->list.array[i]->measId;
asn1cSeqAdd(&currentMC->measIdToRemoveList->list, measId);
}
}
}
int16_t get_HandoverCommandMessage(const gNB_RRC_UE_t* ue_p,NR_SRB_ToAddModList_t **SRBs, NR_DRB_ToAddModList_t **DRBs, uint8_t** buffer, size_t buffer_size, uint8_t transactionId) {
uint8_t rrc_reconfiguration_buffer[RRC_BUF_SIZE] = {0};
int reconfigSize = do_HO_RRCReconfiguration(ue_p,
rrc_reconfiguration_buffer,
RRC_BUF_SIZE,
transactionId,
*SRBs,
*DRBs,
NULL,
NULL,
ue_p->measConfig,
NULL,
ue_p->masterCellGroup,
true);
NR_HandoverCommand_t HoCommand={0};
NR_HandoverCommand_IEs_t *ie;
asn_enc_rval_t enc_rval;
HoCommand.criticalExtensions.present = NR_HandoverCommand__criticalExtensions_PR_c1;
asn1cCalloc(HoCommand.criticalExtensions.choice.c1, c1);
c1->present = NR_HandoverCommand__criticalExtensions__c1_PR_handoverCommand;
ie = calloc(1, sizeof(NR_HandoverCommand_IEs_t));
OCTET_STRING_fromBuf(&ie->handoverCommandMessage,
(const char *)rrc_reconfiguration_buffer, reconfigSize);
HoCommand.criticalExtensions.choice.c1->choice.handoverCommand = ie;
if ( LOG_DEBUGFLAG(DEBUG_ASN1) )
xer_fprint(stdout, &asn_DEF_NR_HandoverCommand, (void *)&HoCommand);
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_HandoverCommand,
NULL,
(void *)&HoCommand,
(*buffer),
buffer_size);
AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
LOG_D(NR_RRC,"HO LOG: Handover Command for UE %u Encoded %zd bits (%zd bytes)\n",
ue_p->rrc_ue_id,
enc_rval.encoded,
(enc_rval.encoded+7)/8);
return((enc_rval.encoded+7)/8);
}
int16_t get_HandoverPreparationInformation(const gNB_RRC_UE_t* ue_p, NR_SRB_ToAddModList_t *SRBs, NR_DRB_ToAddModList_t *DRBs, uint8_t** buffer, size_t buffer_size) {
uint8_t rrc_reconfiguration_buffer[RRC_BUF_SIZE] = {0};
......@@ -1325,7 +1461,8 @@ int16_t get_HandoverPreparationInformation(const gNB_RRC_UE_t* ue_p, NR_SRB_ToAd
NULL,
ue_p->measConfig,
NULL,
ue_p->masterCellGroup);
ue_p->masterCellGroup,
false);
NR_HandoverPreparationInformation_t HoPrepInfo={0};
......
......@@ -150,7 +150,8 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
NR_SecurityConfig_t *security_config,
NR_MeasConfig_t *meas_config,
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList,
NR_CellGroupConfig_t *cellGroupConfig);
NR_CellGroupConfig_t *cellGroupConfig,
bool masterKeyUpdate);
int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier);
struct NR_HandoverPreparationInformation; //forward declare
......@@ -162,6 +163,8 @@ int16_t prepare_DL_DCCH_for_HO_Command(const gNB_RRC_UE_t *UE,
size_t hoCommandLength,
uint8_t* buffer,
size_t buffer_size);
void remove_source_gnb_measurement_configuration(rrc_gNB_ue_context_t * ue_p);
int16_t get_HandoverCommandMessage(const gNB_RRC_UE_t* ue_p,NR_SRB_ToAddModList_t **SRBs, NR_DRB_ToAddModList_t **DRBs, uint8_t** buffer, size_t buffer_size, uint8_t transactionId);
void free_defaultMeasConfig(NR_MeasConfig_t *mc);
uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
......
......@@ -35,6 +35,7 @@
#include "executables/softmodem-common.h"
#include "oai_asn1.h"
#include "SIMULATION/TOOLS/sim.h" // for taus();
#include "rrc_gNB_du.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
......@@ -236,7 +237,7 @@ static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int curr_bwp, uin
return coreset;
}
static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc)
uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc)
{
uint64_t bitmap=0;
switch (scc->ssb_PositionsInBurst->present) {
......@@ -2974,3 +2975,71 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
}
return secondaryCellGroup;
}
int get_dl_band(const f1ap_served_cell_info_t *cell_info)
{
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.freqinfo.band : cell_info->fdd.dl_freqinfo.band;
}
int get_ssb_scs(const f1ap_served_cell_info_t *cell_info)
{
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs;
}
int get_dl_arfcn(const f1ap_served_cell_info_t *cell_info)
{
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.freqinfo.arfcn : cell_info->fdd.dl_freqinfo.arfcn;
}
int get_dl_bw(const f1ap_served_cell_info_t *cell_info)
{
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.nrb : cell_info->fdd.dl_tbw.nrb;
}
int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_t *mib, const NR_SIB1_t *sib1)
{
DevAssert(cell_info != NULL && sib1 != NULL && mib != NULL);
const NR_FrequencyInfoDL_SIB_t* freq_info = &sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL;
AssertFatal(freq_info->scs_SpecificCarrierList.list.count == 1, "cannot handle more than one carrier, but has %d\n", freq_info->scs_SpecificCarrierList.list.count);
AssertFatal(freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier == 0, "cannot handle offsetToCarrier != 0, but is %ld\n", freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier);
long offsetToPointA = freq_info->offsetToPointA;
long kssb = mib->ssb_SubcarrierOffset;
uint32_t dl_arfcn = get_dl_arfcn(cell_info);
int scs = get_ssb_scs(cell_info);
int band = get_dl_band(cell_info);
// FR1 includes frequency bands from 410 MHz (ARFCN 82000) to 7125 MHz (ARFCN 875000)
// FR2 includes frequency bands from 24.25 GHz (ARFCN 2016667) to 71.0 GHz (ARFCN 2795832)
uint64_t scaling = 0;
if (dl_arfcn >= 82000 && dl_arfcn < 875000)
scaling = 1;
else if (dl_arfcn >= 2016667 && dl_arfcn < 2795832)
scaling = 4;
else
AssertFatal(false, "Invalid absoluteFrequencyPointA: %d\n", dl_arfcn);
uint64_t freqpointa = from_nrarfcn(band, scs, dl_arfcn);
// offsetToPointA and kSSB are both on 15kHz SCS for FR1 and 60kHz SCS for FR2 (see 38.211 sections 7.4.3.1 and 4.4.4.2)
// SSB uses the SCS of the cell and is 20 RBs wide, so use 10
uint64_t freqssb = freqpointa + scaling * 15000 * (offsetToPointA * 12 + kssb) + 10ll * 12 * (1 << scs) * 15000;
int bw_index = get_supported_band_index(scs, band, get_dl_bw(cell_info));
int band_size_hz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, bw_index) * 1000 * 1000;
uint32_t ssb_arfcn = to_nrarfcn(band, freqssb, scs, band_size_hz);
LOG_W(RRC, "freqpointa %ld Hz/%d offsetToPointA %ld kssb %ld scs %d band %d band_size_hz %d freqssb %ld Hz/%d\n", freqpointa, dl_arfcn, offsetToPointA, kssb, scs, band, band_size_hz, freqssb, ssb_arfcn);
if (RC.nrmac) {
// debugging: let's test this is the correct ARFCN
// in the CU, we have no access to the SSB ARFCN and therefore need to
// compute it ourselves. If we are running in monolithic, though, we have
// access to the MAC structures and hence can read and compare to the
// original SSB ARFCN. If the below creates problems, it can safely be
// taken out (but the reestablishment will likely not work).
const NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
uint32_t scc_ssb_arfcn = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB;
AssertFatal(ssb_arfcn == scc_ssb_arfcn, "mismatch of SCC SSB ARFCN original %d vs. computed %d! Note: you can remove this Assert, the gNB might run but UE connection instable\n", scc_ssb_arfcn, ssb_arfcn);
}
return ssb_arfcn;
}
......@@ -85,5 +85,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
int servCellIndex,
const nr_mac_config_t *configuration,
int uid);
uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc);
typedef struct f1ap_served_cell_info_t f1ap_served_cell_info_t;
int get_dl_band(const f1ap_served_cell_info_t *cell_info);
int get_ssb_scs(const f1ap_served_cell_info_t *cell_info);
int get_dl_arfcn(const f1ap_served_cell_info_t *cell_info);
int get_dl_bw(const f1ap_served_cell_info_t *cell_info);
int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_t *mib, const NR_SIB1_t *sib1);
#endif
......@@ -250,6 +250,7 @@ typedef struct gNB_RRC_UE_s {
bool as_security_active;
byte_array_t ue_handover_prep_info_buffer;
byte_array_t ue_cap_buffer;
NR_UE_NR_Capability_t* UE_Capability_nr;
int UE_Capability_size;
......
This diff is collapsed.
This diff is collapsed.
......@@ -109,6 +109,30 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(
const size_t handoverPrepInfoSize
);
void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(
const protocol_ctxt_t *const ctxt_pP,
rrc_gNB_ue_context_t *const ue_context_pP,
uint32_t nrCellId
);
void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(
const protocol_ctxt_t *const ctxt_pP,
rrc_gNB_ue_context_t *const ue_context_pP,
uint8_t xid,
uint8_t** handoverCommand,
const size_t handoverCommandSize
);
int rrc_gNB_process_Handover_Request(MessageDef* msg_p, instance_t instance);
void process_gNB_kgnb_star(
const protocol_ctxt_t *const ctxt_pP,
rrc_gNB_ue_context_t* ue_context_pP,
uint16_t pci,
NR_ARFCN_ValueNR_t absoluteFrequencySSB
);
int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance);
void
......
......@@ -254,6 +254,20 @@ nr_rrc_du_container_t *get_du_for_ue(gNB_RRC_INST *rrc, uint32_t ue_id)
return get_du_by_assoc_id(rrc, ue_data.du_assoc_id);
}
struct nr_rrc_du_container_t* get_du_for_nr_cell_id(struct gNB_RRC_INST_s *rrc, uint64_t cellId, uint8_t* cellIdx)
{
nr_rrc_du_container_t *it = NULL;
uint8_t cell_idx = 0;
RB_FOREACH(it, rrc_du_tree, &rrc->dus) {
if (it->setup_req->cell->info.nr_cellid == cellId) {
*cellIdx = cell_idx;
return it;
}
cell_idx++;
}
return NULL;
}
nr_rrc_du_container_t *get_du_by_assoc_id(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
{
nr_rrc_du_container_t e = {.assoc_id = assoc_id};
......
......@@ -37,6 +37,7 @@ void rrc_CU_process_f1_lost_connection(struct gNB_RRC_INST_s *rrc, struct f1ap_l
struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t ue_id);
struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id);
struct nr_rrc_du_container_t* get_du_for_nr_cell_id(struct gNB_RRC_INST_s *rrc, uint64_t cellId, uint8_t* cellIdx);
void dump_du_info(const struct gNB_RRC_INST_s *rrc, FILE *f);
......
......@@ -999,7 +999,7 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
// configure lower layers to apply SRB integrity protection and ciphering
for (int i = 1; i < NR_NUM_SRB; i++) {
if (ue_rrc->perNB[gNB_index].Srb[i] == RB_ESTABLISHED)
nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, kRRCenc, kRRCint, kUPenc);
nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, kRRCenc, kRRCint, kUPenc, false);
}
} else {
LOG_I(NR_RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x", securityMode);
......
......@@ -94,6 +94,10 @@
#include "NGAP_GTP-TEID.h"
#include "NGAP_TargetNGRANNode-ToSourceNGRANNode-TransparentContainer.h"
#include "NGAP_TargetToSource-TransparentContainer.h"
#include "NGAP_SourceNGRANNode-ToTargetNGRANNode-TransparentContainer.h"
#include "NGAP_SourceToTarget-TransparentContainer.h"
#include "NGAP_HandoverRequest.h"
#include "NGAP_PDUSessionResourceSetupItemHOReq.h"
/* Checking version of ASN1C compiler */
......
......@@ -355,10 +355,15 @@ void *ngap_gNB_process_itti_msg(void *notUsed) {
case NGAP_PDUSESSION_RELEASE_RESPONSE:
ngap_gNB_pdusession_release_resp(instance, &NGAP_PDUSESSION_RELEASE_RESPONSE(received_msg));
break;
case NGAP_HANDOVER_REQUIRED:
ngap_gNB_handover_required(instance, &NGAP_HANDOVER_REQUIRED(received_msg));
break;
case NGAP_HANDOVER_REQUEST_ACKNOWLEDGE:
ngap_gNB_handover_request_acknowledge(instance, &NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(received_msg));
break;
case NGAP_HANDOVER_NOTIFY:
ngap_gNB_handover_notify(instance, &NGAP_HANDOVER_NOTIFY(received_msg));
break;
default:
NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
break;
......
......@@ -41,4 +41,9 @@ int ngap_ue_context_release_req(instance_t instance,
int ngap_gNB_handover_required(instance_t instance,
ngap_handover_required_t *handover_required_p);
int ngap_gNB_handover_request_acknowledge(instance_t instance,
ngap_handover_request_ack_t* handover_req_ack_p);
int ngap_gNB_handover_notify(instance_t instance, ngap_handover_notify_t* handover_notify_p);
#endif /* NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_ */
......@@ -98,7 +98,11 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) {
free(res.buffer);
NGAP_INFO("TODO Handover Resource Allocation initiating message\n");
break;
case NGAP_ProcedureCode_id_DownlinkRANStatusTransfer:
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
free(res.buffer);
NGAP_INFO("TODO Downlink RAN Status Transfer initiating message\n");
break;
default:
NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage->procedureCode);
......
......@@ -50,7 +50,9 @@ static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, uint8_t **buf
NGAP_ProcedureCode_id_UEContextReleaseRequest,
NGAP_ProcedureCode_id_PathSwitchRequest,
NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication,
NGAP_ProcedureCode_id_HandoverPreparation,};
NGAP_ProcedureCode_id_HandoverPreparation,
NGAP_ProcedureCode_id_HandoverNotification,
NGAP_ProcedureCode_id_DownlinkRANStatusTransfer,};
int i;
for (i = 0; i < sizeofArray(tmp); i++)
if (pdu->choice.initiatingMessage->procedureCode == tmp[i])
......@@ -74,7 +76,9 @@ static inline int ngap_gNB_encode_successfull_outcome(NGAP_NGAP_PDU_t *pdu, uint
NGAP_ProcedureCode_id_UEContextRelease,
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
NGAP_ProcedureCode_id_PDUSessionResourceModify,
NGAP_ProcedureCode_id_PDUSessionResourceRelease};
NGAP_ProcedureCode_id_PDUSessionResourceRelease,
NGAP_ProcedureCode_id_HandoverResourceAllocation
};
int i;
for (i = 0; i < sizeofArray(tmp); i++)
if (pdu->choice.successfulOutcome->procedureCode == tmp[i])
......
......@@ -680,10 +680,154 @@ static int ngap_gNB_handle_error_indication(sctp_assoc_t assoc_id, uint32_t stre
// TODO continue
return 0;
}
static int ngap_gNB_handle_downlink_ran_status_transfer(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
NGAP_INFO("This Procedure is not implemented yet! DL RAN STATUS TRANSFER\n");
return 0;
}
static int ngap_gNB_handle_handover_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
NGAP_INFO("HO LOG: Handover Request Message Has Came to the Target gNB! - NOT IMPLEMENTED\n");
uint64_t amf_ue_ngap_id;
ngap_gNB_amf_data_t *amf_desc_p = NULL;
NGAP_HandoverRequest_t *container;
NGAP_HandoverRequestIEs_t *ie;
DevAssert(pdu != NULL);
container = &pdu->choice.initiatingMessage->value.choice.HandoverRequest;
if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
NGAP_ERROR("[SCTP %u] Received Handover Request for non "
"existing AMF context\n", assoc_id);
return -1;
}
/* id-Handover Type */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_HandoverType, true);
if (ie->value.choice.HandoverType != NGAP_HandoverType_intra5gs){
NGAP_ERROR("Only Intra 5GS Handovers are supported at the moment!\n");
return -1;
}
/* id-AMF-UE-NGAP-ID */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true);
asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id);
NGAP_INFO("HO LOG: HO Request is came with AMF UE NGAP ID: %lu \n", amf_ue_ngap_id);
MessageDef * message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_HANDOVER_REQUEST);
ngap_handover_request_t * msg=&NGAP_HANDOVER_REQUEST(message_p);
memset(msg, 0, sizeof(*msg));
msg->amf_ue_ngap_id = amf_ue_ngap_id;
/* id-GUAMI */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_GUAMI, true);
TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, msg->guami.mcc,
msg->guami.mnc, msg->guami.mnc_len);
OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFRegionID, msg->guami.amf_region_id);
OCTET_STRING_TO_INT16(&ie->value.choice.GUAMI.aMFSetID, msg->guami.amf_set_id);
OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFPointer, msg->guami.amf_pointer);
/* id-UEAggregateMaximumBitRate */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, false);
if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL),
&(msg->ue_ambr.br_ul));
asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL),
&(msg->ue_ambr.br_dl));
} else {
NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate\n");
}
/* id-AllowedNSSAI */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_AllowedNSSAI, true);
NGAP_AllowedNSSAI_Item_t *allow_nssai_item_p = NULL;
AssertFatal(ie, "AllowedNSSAI not present, forging 2 NSSAI\n");
NGAP_INFO("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count);
msg->nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count;
for(int i = 0; i < ie->value.choice.AllowedNSSAI.list.count; i++) {
allow_nssai_item_p = ie->value.choice.AllowedNSSAI.list.array[i];
OCTET_STRING_TO_INT8(&allow_nssai_item_p->s_NSSAI.sST, msg->allowed_nssai[i].sst);
if(allow_nssai_item_p->s_NSSAI.sD != NULL) {
memcpy(&msg->allowed_nssai[i].sd, allow_nssai_item_p->s_NSSAI.sD, 3);
} else {
msg->allowed_nssai[i].sd = 0xffffff;
}
}
/* id-UESecurityCapabilities */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_UESecurityCapabilities, true);
msg->security_capabilities.nRencryption_algorithms =
BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRencryptionAlgorithms);
msg->security_capabilities.nRintegrity_algorithms =
BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRintegrityProtectionAlgorithms);
msg->security_capabilities.eUTRAencryption_algorithms =
BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAencryptionAlgorithms);
msg->security_capabilities.eUTRAintegrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAintegrityProtectionAlgorithms);
/* id-Security Context */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_SecurityContext, true);
memcpy(&msg->next_hop, ie->value.choice.SecurityContext.nextHopNH.buf, ie->value.choice.SecurityContext.nextHopNH.size);
msg->next_hop_chain_count = (uint8_t)ie->value.choice.SecurityContext.nextHopChainingCount;
/* id-MobilityRestrictionList*/
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_MobilityRestrictionList, false);
if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
NGAP_MobilityRestrictionList_t *mobility_rest_list_p = NULL;
mobility_rest_list_p = &ie->value.choice.MobilityRestrictionList;
msg->mobility_restriction_flag = 1;
TBCD_TO_MCC_MNC(
&mobility_rest_list_p->servingPLMN, msg->mobility_restriction.serving_plmn.mcc, msg->mobility_restriction.serving_plmn.mnc, msg->mobility_restriction.serving_plmn.mnc_digit_length);
}
/* id-Cause */
/* id-SourceToTargetTransparentContainer*/
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_SourceToTarget_TransparentContainer, true);
DevAssert(ie != NULL);
allocCopy(&(msg->sourceToTargetTransparentContainer), ie->value.choice.SourceToTarget_TransparentContainer);
/* id-PDU Session Resource Setup List HO Req*/
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListHOReq, true);
for (int pduSesIdx = 0; pduSesIdx < ie->value.choice.PDUSessionResourceSetupListHOReq.list.count; ++pduSesIdx)
{
NGAP_PDUSessionResourceSetupItemHOReq_t* item_p = ie->value.choice.PDUSessionResourceSetupListHOReq.list.array[pduSesIdx];
msg->pduSessionResourceSetupHOList[pduSesIdx].pdusession_id = item_p->pDUSessionID;
msg->pduSessionResourceSetupHOList[pduSesIdx].pdu_session_type = 0;
// S-NSSAI
OCTET_STRING_TO_INT8(&item_p->s_NSSAI.sST, msg->pduSessionResourceSetupHOList[pduSesIdx].nssai.sst);
if (item_p->s_NSSAI.sD != NULL) {
uint8_t *sd_p = (uint8_t *)&msg->pduSessionResourceSetupHOList[pduSesIdx].nssai.sd;
sd_p[0] = item_p->s_NSSAI.sD->buf[0];
sd_p[1] = item_p->s_NSSAI.sD->buf[1];
sd_p[2] = item_p->s_NSSAI.sD->buf[2];
} else {
msg->pduSessionResourceSetupHOList[pduSesIdx].nssai.sd = 0xffffff;
}
allocCopy(&msg->pduSessionResourceSetupHOList[pduSesIdx].pdusessionTransfer, item_p->handoverRequestTransfer);
}
msg->nb_of_pdusessions = ie->value.choice.PDUSessionResourceSetupListHOReq.list.count;
itti_send_msg_to_task(TASK_RRC_GNB, amf_desc_p->ngap_gNB_instance->instance, message_p);
return 0;
}
......@@ -1414,7 +1558,7 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = {
{ngap_gNB_handle_nas_downlink, 0, 0}, /* DownlinkNASTransport */
{0, 0, 0}, /* DownlinkNonUEAssociatedNRPPaTransport */
{0, 0, 0}, /* DownlinkRANConfigurationTransfer */
{0, 0, 0}, /* DownlinkRANStatusTransfer */
{ngap_gNB_handle_downlink_ran_status_transfer, 0, 0}, /* DownlinkRANStatusTransfer */
{0, 0, 0}, /* DownlinkUEAssociatedNRPPaTransport */
{ngap_gNB_handle_error_indication, 0, 0}, /* ErrorIndication */
{0, 0, 0}, /* HandoverCancel */
......
......@@ -209,7 +209,8 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t o
/* Multiply by Q */
EVAL = MUL64(EVAL,Q,c);
MAC_I = (uint32_t)(EVAL >> 32) ^ z[4];
//printf ("MAC_I:%16X\n",MAC_I);
fprintf (stdout, "MAC_I:%16X\n",MAC_I);
fflush(stdout);
MAC_I = hton_int32(MAC_I);
memcpy(out, &MAC_I, 4);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment