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 { ...@@ -371,6 +371,8 @@ typedef struct cu_to_du_rrc_information_s {
uint32_t uE_CapabilityRAT_ContainerList_length; uint32_t uE_CapabilityRAT_ContainerList_length;
uint8_t * measConfig; uint8_t * measConfig;
uint32_t measConfig_length; uint32_t measConfig_length;
uint8_t * handoverPreparationInfo;
uint32_t handoverPreparationInfo_length;
}cu_to_du_rrc_information_t; }cu_to_du_rrc_information_t;
typedef struct du_to_cu_rrc_information_s { typedef struct du_to_cu_rrc_information_s {
......
...@@ -74,9 +74,12 @@ MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, ngap_pdu ...@@ -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_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_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_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 , 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_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_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 */ /* NGAP -> RRC messages */
MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas ) 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 ...@@ -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_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_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_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) */ /* 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) MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req)
...@@ -67,6 +67,9 @@ ...@@ -67,6 +67,9 @@
#define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind #define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind
#define NGAP_HANDOVER_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_required #define NGAP_HANDOVER_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_required
#define NGAP_HANDOVER_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_command #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_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req
#define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command
...@@ -550,6 +553,11 @@ typedef struct handover_drb_item_s { ...@@ -550,6 +553,11 @@ typedef struct handover_drb_item_s {
bool isActive; bool isActive;
} handover_drb_item_t; } 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 { typedef struct ngap_handover_required_s {
uint32_t gNB_ue_ngap_id; uint32_t gNB_ue_ngap_id;
...@@ -563,6 +571,14 @@ typedef struct ngap_handover_required_s { ...@@ -563,6 +571,14 @@ typedef struct ngap_handover_required_s {
uint32_t handoverType; // 0 for intra5gs uint32_t handoverType; // 0 for intra5gs
} ngap_handover_required_t; } 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 { typedef struct ngap_handover_command_s {
uint32_t gNB_ue_ngap_id; uint32_t gNB_ue_ngap_id;
uint64_t amf_ue_ngap_id; uint64_t amf_ue_ngap_id;
...@@ -573,6 +589,22 @@ typedef struct ngap_handover_command_s { ...@@ -573,6 +589,22 @@ typedef struct ngap_handover_command_s {
pdusession_setup_t pduSessionResourceHandoverList[NGAP_MAX_PDUSESSION]; //for data forwarding pdusession_setup_t pduSessionResourceHandoverList[NGAP_MAX_PDUSESSION]; //for data forwarding
} ngap_handover_command_t; } 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 { typedef struct ngap_ue_cap_info_ind_s {
uint32_t gNB_ue_ngap_id; uint32_t gNB_ue_ngap_id;
ngap_pdu_t ue_radio_cap; 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 ...@@ -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) { if (ra_index == NR_NB_RA_PROC_MAX) {
LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti); LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti);
return false; return false;
} }
NR_RA_t *ra = &cc->ra[ra_index]; NR_RA_t *ra = &cc->ra[ra_index];
ra->cfra = true; ra->cfra = true;
ra->rnti = rnti; ra->rnti = rnti;
...@@ -905,7 +905,7 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig ...@@ -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; return true;
} }
......
...@@ -134,12 +134,10 @@ static int nr_process_mac_pdu(instance_t module_idP, ...@@ -134,12 +134,10 @@ static int nr_process_mac_pdu(instance_t module_idP,
uint16_t mac_len=0; uint16_t mac_len=0;
uint16_t mac_subheader_len=sizeof(NR_MAC_SUBHEADER_FIXED); uint16_t mac_subheader_len=sizeof(NR_MAC_SUBHEADER_FIXED);
uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; 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); 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; unsigned char *ce_ptr;
int n_Lcg = 0; int n_Lcg = 0;
switch(rx_lcid){ switch(rx_lcid){
// MAC CE // MAC CE
/*#ifdef DEBUG_HEADER_PARSING /*#ifdef DEBUG_HEADER_PARSING
...@@ -483,12 +481,13 @@ static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) ...@@ -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; 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; bool UE_waiting_CFRA_msg3 = false;
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
const NR_RA_t *ra = &gNB_mac->common_channels[CC_id].ra[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; UE_waiting_CFRA_msg3 = true;
break; break;
} }
...@@ -506,7 +505,7 @@ void handle_nr_ul_harq(const int CC_idP, ...@@ -506,7 +505,7 @@ void handle_nr_ul_harq(const int CC_idP,
NR_SCHED_LOCK(&nrmac->sched_lock); NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti); 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) { if (!UE || UE_waiting_CFRA_msg3 == true) {
LOG_D(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti); 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, ...@@ -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; const int pusch_failure_thres = gNB_mac->pusch_failure_thres;
NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti); 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) { if (UE && UE_waiting_CFRA_msg3 == false) {
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; 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, ...@@ -684,7 +688,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
} }
} }
} else if(sduP) { } else if(sduP) {
bool no_sig = true; bool no_sig = true;
for (int k = 0; k < sdu_lenP; k++) { for (int k = 0; k < sdu_lenP; k++) {
if(sduP[k]!=0) { if(sduP[k]!=0) {
...@@ -716,13 +719,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, ...@@ -716,13 +719,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// random access pusch with TC-RNTI // random access pusch with TC-RNTI
if (ra->rnti != current_rnti) { if (ra->rnti != current_rnti) {
LOG_D(NR_MAC, LOG_E(NR_MAC,
"expected TC_RNTI %04x to match current RNTI %04x\n", "expected TC_RNTI %04x to match current RNTI %04x\n",
ra->rnti, ra->rnti,
current_rnti); current_rnti);
if( (frameP==ra->Msg3_frame) && (slotP==ra->Msg3_slot) ) { 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); 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, ...@@ -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 // re-initialize ta update variables after RA procedure completion
UE_msg3_stage->UE_sched_ctrl.ta_frame = frameP; 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", "reset RA state information for RA-RNTI 0x%04x/index %d\n",
ra->rnti, ra->rnti,
i); i);
LOG_I(NR_MAC, LOG_E(NR_MAC,
"[gNB %d][RAPROC] PUSCH with TC_RNTI 0x%04x received correctly, " "[gNB %d][RAPROC] PUSCH with TC_RNTI 0x%04x received correctly, "
"adding UE MAC Context RNTI 0x%04x\n", "adding UE MAC Context RNTI 0x%04x\n",
gnb_mod_idP, gnb_mod_idP,
...@@ -761,15 +764,21 @@ static void _nr_rx_sdu(const module_id_t 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->ta_update = timing_advance;
UE_scheduling_control->raw_rssi = rssi; UE_scheduling_control->raw_rssi = rssi;
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640; 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) { if (ra->cfra) {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti); LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti);
nr_mac_reset_ul_failure(UE_scheduling_control); nr_mac_reset_ul_failure(UE_scheduling_control);
reset_dl_harq_list(UE_scheduling_control); reset_dl_harq_list(UE_scheduling_control);
reset_ul_harq_list(UE_scheduling_control); reset_ul_harq_list(UE_scheduling_control);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); 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 { } else {
LOG_A(NR_MAC,"[RAPROC] RA-Msg3 received (sdu_lenP %d)\n",sdu_lenP); 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, ...@@ -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 // for CFRA (NSA) do not schedule retransmission of msg3
if (ra->cfra) { 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); nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
return; return;
} }
......
...@@ -24,10 +24,13 @@ ...@@ -24,10 +24,13 @@
#include "mac_proto.h" #include "mac_proto.h"
#include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/f1ap_ids.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.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 "F1AP_CauseRadioNetwork.h"
#include "uper_decoder.h" #include "uper_decoder.h"
#include "uper_encoder.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 // 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}; 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 ...@@ -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) 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]; gNB_MAC_INST *mac = RC.nrmac[0];
/* response has same type as request... */ /* response has same type as request... */
f1ap_ue_context_setup_t resp = { f1ap_ue_context_setup_t resp = {
...@@ -596,7 +754,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) ...@@ -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); 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 /* we expected a reconfiguration, and this is on DCCH. We assume this is
* the reconfiguration: nr_mac_prepare_cellgroup_update() already stored * the reconfiguration: nr_mac_prepare_cellgroup_update() already stored
* the CellGroupConfig. Below, we trigger a timer, and the CellGroupConfig * 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, ...@@ -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); 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); MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP);
msg->ittiMsgHeader.originInstance = -1; // means monolithic msg->ittiMsgHeader.originInstance = -1; // means monolithic
f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg);
......
...@@ -718,6 +718,7 @@ typedef struct { ...@@ -718,6 +718,7 @@ typedef struct {
float ul_thr_ue; float ul_thr_ue;
float dl_thr_ue; float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook; long pdsch_HARQ_ACK_Codebook;
bool isUEDoingHandover;
} NR_UE_info_t; } NR_UE_info_t;
typedef struct { typedef struct {
......
...@@ -103,7 +103,6 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, ...@@ -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; rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn;
if (entity->has_ciphering) if (entity->has_ciphering)
entity->cipher(entity->security_context, entity->cipher(entity->security_context,
buffer+header_size, size-header_size, buffer+header_size, size-header_size,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "nr_pdcp_integrity_nia1.h" #include "nr_pdcp_integrity_nia1.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
...@@ -52,6 +53,8 @@ void nr_pdcp_integrity_nia1_integrity(void *integrity_context, ...@@ -52,6 +53,8 @@ void nr_pdcp_integrity_nia1_integrity(void *integrity_context,
ctx->bearer = bearer-1; ctx->bearer = bearer-1;
ctx->direction = direction; ctx->direction = direction;
ctx->blength = length * 8; 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); stream_compute_integrity(EIA1_128_ALG_ID, ctx, out);
} }
......
...@@ -1019,7 +1019,8 @@ void nr_pdcp_config_set_security(ue_id_t ue_id, ...@@ -1019,7 +1019,8 @@ void nr_pdcp_config_set_security(ue_id_t ue_id,
const uint8_t security_modeP, const uint8_t security_modeP,
uint8_t *const kRRCenc_pP, uint8_t *const kRRCenc_pP,
uint8_t *const kRRCint_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_ue_t *ue;
nr_pdcp_entity_t *rb; nr_pdcp_entity_t *rb;
...@@ -1044,7 +1045,7 @@ void nr_pdcp_config_set_security(ue_id_t ue_id, ...@@ -1044,7 +1045,7 @@ void nr_pdcp_config_set_security(ue_id_t ue_id,
ciphering_algorithm = security_modeP & 0x0f; ciphering_algorithm = security_modeP & 0x0f;
rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP, rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP,
ciphering_algorithm, (char *)kRRCenc_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); nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
} }
......
...@@ -85,7 +85,8 @@ void nr_pdcp_config_set_security(ue_id_t ue_id, ...@@ -85,7 +85,8 @@ void nr_pdcp_config_set_security(ue_id_t ue_id,
const uint8_t security_modeP, const uint8_t security_modeP,
uint8_t *const kRRCenc_pP, uint8_t *const kRRCenc_pP,
uint8_t *const kRRCint_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, bool cu_f1u_data_req(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP, 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 ...@@ -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); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_DL_DCCH_Message, &dl_dcch_msg);
return((enc_rval.encoded+7)/8); return((enc_rval.encoded+7)/8);
} }
int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE, int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
uint8_t *buffer, uint8_t *buffer,
size_t buffer_size, size_t buffer_size,
...@@ -676,7 +676,8 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE, ...@@ -676,7 +676,8 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
NR_SecurityConfig_t *security_config, NR_SecurityConfig_t *security_config,
NR_MeasConfig_t *meas_config, NR_MeasConfig_t *meas_config,
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList, 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; asn_enc_rval_t enc_rval;
...@@ -697,6 +698,16 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE, ...@@ -697,6 +698,16 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
ie->radioBearerConfig->drb_ToReleaseList = DRB_releaseList; 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 ********************/ /******************** Meas Config ********************/
// measConfig // measConfig
ie->measConfig = meas_config; ie->measConfig = meas_config;
...@@ -709,6 +720,18 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE, ...@@ -709,6 +720,18 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
} }
if (cellGroupConfig != NULL) { 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; uint8_t *buf = NULL;
ssize_t len = uper_encode_to_new_buffer(&asn_DEF_NR_CellGroupConfig, NULL, cellGroupConfig, (void **)&buf); 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); 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, ...@@ -720,6 +743,11 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
ie->nonCriticalExtension->masterCellGroup->size = len; 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; rrcReconf->criticalExtensions.choice.rrcReconfiguration = ie;
...@@ -1312,6 +1340,114 @@ NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs) ...@@ -1312,6 +1340,114 @@ NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs)
return mc; 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) { 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}; 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 ...@@ -1325,7 +1461,8 @@ int16_t get_HandoverPreparationInformation(const gNB_RRC_UE_t* ue_p, NR_SRB_ToAd
NULL, NULL,
ue_p->measConfig, ue_p->measConfig,
NULL, NULL,
ue_p->masterCellGroup); ue_p->masterCellGroup,
false);
NR_HandoverPreparationInformation_t HoPrepInfo={0}; NR_HandoverPreparationInformation_t HoPrepInfo={0};
......
...@@ -150,7 +150,8 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE, ...@@ -150,7 +150,8 @@ int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
NR_SecurityConfig_t *security_config, NR_SecurityConfig_t *security_config,
NR_MeasConfig_t *meas_config, NR_MeasConfig_t *meas_config,
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList, 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); int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier);
struct NR_HandoverPreparationInformation; //forward declare struct NR_HandoverPreparationInformation; //forward declare
...@@ -162,6 +163,8 @@ int16_t prepare_DL_DCCH_for_HO_Command(const gNB_RRC_UE_t *UE, ...@@ -162,6 +163,8 @@ int16_t prepare_DL_DCCH_for_HO_Command(const gNB_RRC_UE_t *UE,
size_t hoCommandLength, size_t hoCommandLength,
uint8_t* buffer, uint8_t* buffer,
size_t buffer_size); 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); void free_defaultMeasConfig(NR_MeasConfig_t *mc);
uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi); uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "executables/softmodem-common.h" #include "executables/softmodem-common.h"
#include "oai_asn1.h" #include "oai_asn1.h"
#include "SIMULATION/TOOLS/sim.h" // for taus(); #include "SIMULATION/TOOLS/sim.h" // for taus();
#include "rrc_gNB_du.h"
#include "uper_decoder.h" #include "uper_decoder.h"
#include "uper_encoder.h" #include "uper_encoder.h"
...@@ -236,7 +237,7 @@ static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int curr_bwp, uin ...@@ -236,7 +237,7 @@ static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int curr_bwp, uin
return coreset; 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; uint64_t bitmap=0;
switch (scc->ssb_PositionsInBurst->present) { switch (scc->ssb_PositionsInBurst->present) {
...@@ -2974,3 +2975,71 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC ...@@ -2974,3 +2975,71 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
} }
return secondaryCellGroup; 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 ...@@ -85,5 +85,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
int servCellIndex, int servCellIndex,
const nr_mac_config_t *configuration, const nr_mac_config_t *configuration,
int uid); 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 #endif
...@@ -250,6 +250,7 @@ typedef struct gNB_RRC_UE_s { ...@@ -250,6 +250,7 @@ typedef struct gNB_RRC_UE_s {
bool as_security_active; bool as_security_active;
byte_array_t ue_handover_prep_info_buffer;
byte_array_t ue_cap_buffer; byte_array_t ue_cap_buffer;
NR_UE_NR_Capability_t* UE_Capability_nr; NR_UE_NR_Capability_t* UE_Capability_nr;
int UE_Capability_size; int UE_Capability_size;
......
...@@ -113,7 +113,6 @@ ...@@ -113,7 +113,6 @@
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
static inline uint64_t bitStr_to_uint64(const BIT_STRING_t *asn);
static const nr_neighbour_gnb_configuration_t* rrc_gNB_find_neighbour_cell_configuration_by_phyCellId(int phyCellId) static const nr_neighbour_gnb_configuration_t* rrc_gNB_find_neighbour_cell_configuration_by_phyCellId(int phyCellId)
{ {
...@@ -183,74 +182,6 @@ void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, const gNB_RR ...@@ -183,74 +182,6 @@ void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, const gNB_RR
nr_pdcp_data_req_srb(ue_p->rrc_ue_id, srb_id, rrc_gNB_mui++, size, (unsigned char *const)buffer, rrc_deliver_dl_rrc_message, &data); nr_pdcp_data_req_srb(ue_p->rrc_ue_id, srb_id, rrc_gNB_mui++, size, (unsigned char *const)buffer, rrc_deliver_dl_rrc_message, &data);
} }
static 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;
}
static 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;
}
static 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;
}
static 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;
}
static 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_D(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;
}
///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------///
...@@ -370,7 +301,7 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) ...@@ -370,7 +301,7 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish)
if (ue->Srb[i].Active) { if (ue->Srb[i].Active) {
asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb);
srb->srb_Identity = i; srb->srb_Identity = i;
if (reestablish && i == 2) { if (reestablish) {
asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true);
} }
} }
...@@ -1040,7 +971,7 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context ...@@ -1040,7 +971,7 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context
for (int srb_id = 1; srb_id < maxSRBs; srb_id++) { for (int srb_id = 1; srb_id < maxSRBs; srb_id++) {
if (ue_p->Srb[srb_id].Active) { if (ue_p->Srb[srb_id].Active) {
nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc, ue_p->as_security_active);
// TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag // TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag
nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true); nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true);
} }
...@@ -1460,6 +1391,8 @@ static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context, ...@@ -1460,6 +1391,8 @@ static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context,
NR_DRB_ToAddModList_t *DRBs = createDRBlist(&ue_context->ue_context, false); NR_DRB_ToAddModList_t *DRBs = createDRBlist(&ue_context->ue_context, false);
size_t hoPrepSize = get_HandoverPreparationInformation(&ue_context->ue_context,SRBs, DRBs, &buffer, RRC_BUF_SIZE); size_t hoPrepSize = get_HandoverPreparationInformation(&ue_context->ue_context,SRBs, DRBs, &buffer, RRC_BUF_SIZE);
DevAssert(bestNeighbourId != -1); DevAssert(bestNeighbourId != -1);
freeSRBlist(SRBs);
freeDRBlist(DRBs);
const nr_neighbour_gnb_configuration_t* neighbourConfig = rrc_gNB_find_neighbour_cell_configuration_by_phyCellId(bestNeighbourId); const nr_neighbour_gnb_configuration_t* neighbourConfig = rrc_gNB_find_neighbour_cell_configuration_by_phyCellId(bestNeighbourId);
if (neighbourConfig != NULL) { if (neighbourConfig != NULL) {
rrc_gNB_send_NGAP_HANDOVER_REQUIRED(&ctxt, ue_context, 0, neighbourConfig, &buffer, hoPrepSize); rrc_gNB_send_NGAP_HANDOVER_REQUIRED(&ctxt, ue_context, 0, neighbourConfig, &buffer, hoPrepSize);
...@@ -1723,6 +1656,11 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ ...@@ -1723,6 +1656,11 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_
case RRC_REESTABLISH_COMPLETE: case RRC_REESTABLISH_COMPLETE:
case RRC_DEDICATED_RECONF: case RRC_DEDICATED_RECONF:
/* do nothing */ /* do nothing */
if (UE->StatusRrc == NR_RRC_HO_EXECUTION) {
LOG_E(NR_RRC, "HO LOG: RRC Reconfig Complete Came for HO UE w Id: %u\n", UE->rrc_ue_id);
UE->StatusRrc = NR_RRC_RECONFIGURED;
rrc_gNB_send_NGAP_HANDOVER_NOTIFY(ctxt_pP, ue_context_p, 0);
}
break; break;
case RRC_ACTION_NONE: case RRC_ACTION_NONE:
LOG_E(RRC, "UE %d: Received RRC Reconfiguration Complete with xid %d while no transaction is ongoing\n", UE->rrc_ue_id, xid); LOG_E(RRC, "UE %d: Received RRC Reconfiguration Complete with xid %d while no transaction is ongoing\n", UE->rrc_ue_id, xid);
...@@ -2038,6 +1976,37 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f ...@@ -2038,6 +1976,37 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f
rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); rrc->cucp_cuup.bearer_context_mod(assoc_id, &req);
} }
static void get_measurement_configuration(instance_t instance, rrc_gNB_ue_context_t* ue_p) {
if (ue_p->ue_context.measConfig != NULL) {
free(ue_p->ue_context.measConfig);
ue_p->ue_context.measConfig = NULL;
}
gNB_RRC_INST *rrc = RC.nrrrc[instance];
const nr_rrc_du_container_t *du = get_du_for_ue(rrc, ue_p->ue_context.rrc_ue_id);
DevAssert(du != NULL);
f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
int scs = get_ssb_scs(cell_info);
int band = get_dl_band(cell_info);
NR_MeasConfig_t * measconfig = NULL;
if (du->mib != NULL && du->sib1 != NULL) {
uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1);
if (rrc->measurementConfiguration.enableA3 && rrc->number_of_neighbours > 0) {
LOG_D(NR_RRC, "HO LOG: Event Based Measurement is Selected!\n");
measconfig = get_EventBasedMeasConfig(ssb_arfcn, band, scs, &(rrc->measurementConfiguration), rrc->neighbourConfiguration, rrc->number_of_neighbours);
} else {
measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs);
}
}
DevAssert(measconfig != NULL);
if (measconfig != NULL)
clone_MeasConfig(measconfig, ue_p);
remove_source_gnb_measurement_configuration(ue_p);
}
static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance) static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance)
{ {
f1ap_ue_context_setup_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); f1ap_ue_context_setup_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p);
...@@ -2065,7 +2034,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance ...@@ -2065,7 +2034,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance
if (LOG_DEBUGFLAG(DEBUG_ASN1)) if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
if (resp->drbs_to_be_setup_length > 0) { if (resp->drbs_to_be_setup_length > 0 && UE->StatusRrc != NR_RRC_HO_PREPARATION) {
AssertFatal(resp->srbs_to_be_setup_length > 0 && resp->srbs_to_be_setup[0].srb_id == 2, "logic bug: we set up DRBs, so need to have both SRB1&SRB2\n"); AssertFatal(resp->srbs_to_be_setup_length > 0 && resp->srbs_to_be_setup[0].srb_id == 2, "logic bug: we set up DRBs, so need to have both SRB1&SRB2\n");
e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup);
} }
...@@ -2073,6 +2042,38 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance ...@@ -2073,6 +2042,38 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance
/* at this point, we don't have to do anything: the UE context setup request /* at this point, we don't have to do anything: the UE context setup request
* includes the Security Command, whose response will trigger the following * includes the Security Command, whose response will trigger the following
* messages (UE capability, to be specific) */ * messages (UE capability, to be specific) */
if (UE->StatusRrc == NR_RRC_HO_PREPARATION) {
if (cu_exists_f1_ue_data(UE->rrc_ue_id)) {
f1_ue_data_t prevData = cu_get_f1_ue_data(UE->rrc_ue_id);
cu_remove_f1_ue_data(UE->rrc_ue_id);
f1_ue_data_t newData = {.secondary_ue = resp->gNB_DU_ue_id, .du_assoc_id = prevData.du_assoc_id, .e1_assoc_id = prevData.e1_assoc_id};
cu_add_f1_ue_data(UE->rrc_ue_id, &newData);
LOG_I(NR_RRC, "HO LOG: CU F1AP Context is updated for the UE with CU Id : %u DU Id : %u!\n", resp->gNB_CU_ue_id, resp->gNB_DU_ue_id);
}
UE->rnti = resp->gNB_DU_ue_id;
LOG_I(NR_RRC, "HO LOG: UE Context Setup is successfully processed for HO!\n");
if (resp->drbs_to_be_setup_length > 0)
e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup);
protocol_ctxt_t ctxt = {.rntiMaybeUEid = resp->gNB_CU_ue_id, .module_id = instance, .instance = instance, .enb_flag = 1, .eNB_index = instance};
uint8_t* buffer = (uint8_t*)calloc(1,RRC_BUF_SIZE);
NR_SRB_ToAddModList_t *SRBs = createSRBlist(UE, true);
NR_DRB_ToAddModList_t *DRBs = createDRBlist(UE, true);
uint8_t xid = rrc_gNB_get_next_transaction_identifier(instance);
UE->xids[xid] = RRC_DEDICATED_RECONF;
//modify ue measurement config: remove source gNBs measurement objects
get_measurement_configuration(instance, ue_context_p);
size_t hoCommandSize = get_HandoverCommandMessage(UE, &SRBs, &DRBs, &buffer, RRC_BUF_SIZE, xid);
rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(&ctxt, ue_context_p, 0, &buffer, hoCommandSize);
}
} }
static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p) static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p)
...@@ -2156,6 +2157,7 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i ...@@ -2156,6 +2157,7 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p); rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p);
} }
} }
static void rrc_CU_process_ue_modification_required(MessageDef *msg_p) static void rrc_CU_process_ue_modification_required(MessageDef *msg_p)
...@@ -2236,6 +2238,113 @@ static pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, ...@@ -2236,6 +2238,113 @@ static pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi,
return NULL; return NULL;
} }
void rrc_gNB_ue_context_setup_request_for_handover_on_target(rrc_gNB_ue_context_t *ue_context_p, const e1ap_bearer_setup_resp_t* bearer_resp, instance_t instance)
{
gNB_RRC_INST *rrc = RC.nrrrc[0];
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
if (UE->ue_handover_prep_info_buffer.len <= 0 && UE->ue_handover_prep_info_buffer.buf == NULL) {
LOG_E(NR_RRC, "HO Prep Info Can not be NULL for UE with id %u !\n", UE->rrc_ue_id);
return;
}
f1ap_srb_to_be_setup_t srbs[2];
int nb_srb = 0;
for (int srbIdx = 1; srbIdx < maxSRBs; srbIdx++)
{
if (UE->Srb[srbIdx].Active != 1)
{
LOG_E(NR_RRC, "HO LOG: SRB : %d is not activated\n", srbIdx);
continue;
}
srbs[srbIdx - 1].srb_id = srbIdx;
srbs[srbIdx - 1].lcid = srbIdx;
nb_srb++;
}
/* Instruction towards the DU for DRB configuration and tunnel creation */
f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32
int nb_drb = 0;
for (int p = 0; p < bearer_resp->numPDUSessions; ++p) {
rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, bearer_resp->pduSession[p].id, false);
DevAssert(RRC_pduSession);
for (int i = 0; i < bearer_resp->pduSession[p].numDRBSetup; i++) {
const DRB_nGRAN_setup_t *drb_config = &bearer_resp->pduSession[p].DRBnGRanList[i];
f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
drb->drb_id = bearer_resp->pduSession[p].DRBnGRanList[i].id;
drb->rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress;
drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId;
drb->up_ul_tnl_length = 1;
drb->nssai = RRC_pduSession->param.nssai;
/* pass QoS info to MAC */
int nb_qos_flows = drb_config->numQosFlowSetup;
AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n");
drb->drb_info.flows_to_be_setup_length = nb_qos_flows;
drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t));
AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n");
for (int j = 0; j < nb_qos_flows; j++) {
drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi;
pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession);
f1ap_qos_characteristics_t *qos_char = &drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics;
if (in_qos_char->fiveQI_type == dynamic) {
qos_char->qos_type = dynamic;
qos_char->dynamic.fiveqi = in_qos_char->fiveQI;
qos_char->dynamic.qos_priority_level = in_qos_char->qos_priority;
} else {
qos_char->qos_type = non_dynamic;
qos_char->non_dynamic.fiveqi = in_qos_char->fiveQI;
qos_char->non_dynamic.qos_priority_level = in_qos_char->qos_priority;
}
}
/* the DRB QoS parameters: we just reuse the ones from the first flow */
drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params;
/* pass NSSAI info to MAC */
drb->nssai = RRC_pduSession->param.nssai;
nb_drb++;
}
}
cu_to_du_rrc_information_t cu2du = {0};
cu_to_du_rrc_information_t *cu2du_p = NULL;
cu2du.handoverPreparationInfo = UE->ue_handover_prep_info_buffer.buf;
cu2du.handoverPreparationInfo_length = UE->ue_handover_prep_info_buffer.len;
if (UE->ue_cap_buffer.len > 0 && UE->ue_cap_buffer.buf != NULL) {
cu2du.uE_CapabilityRAT_ContainerList = UE->ue_cap_buffer.buf;
cu2du.uE_CapabilityRAT_ContainerList_length = UE->ue_cap_buffer.len;
}
cu2du_p = &cu2du;
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
RETURN_IF_INVALID_ASSOC_ID(ue_data);
f1ap_ue_context_setup_t ue_context_setup_req = {
.gNB_CU_ue_id = UE->rrc_ue_id,
.plmn.mcc = rrc->configuration.mcc[0],
.plmn.mnc = rrc->configuration.mnc[0],
.plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
.nr_cellid = rrc->nr_cellid,
.servCellId = 0, /* TODO: correct value? */
.srbs_to_be_setup_length = nb_srb,
.srbs_to_be_setup = srbs,
.drbs_to_be_setup_length = nb_drb,
.drbs_to_be_setup = drbs,
.cu_to_du_rrc_information = cu2du_p,
};
LOG_I(NR_RRC, "HO LOG: UE Context Setup Request is sending to Target DU for UE ID: %u!\n", UE->rrc_ue_id);
rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &ue_context_setup_req);
}
/** /**
* @brief E1AP Bearer Context Setup Response processing on CU-CP * @brief E1AP Bearer Context Setup Response processing on CU-CP
*/ */
...@@ -2245,7 +2354,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp ...@@ -2245,7 +2354,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_cu_cp_ue_id); rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_cu_cp_ue_id);
AssertFatal(ue_context_p != NULL, "did not find UE with CU UE ID %d\n", resp->gNB_cu_cp_ue_id); AssertFatal(ue_context_p != NULL, "did not find UE with CU UE ID %d\n", resp->gNB_cu_cp_ue_id);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context; gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
// currently: we don't have "infrastructure" to save the CU-UP UE ID, so we // currently: we don't have "infrastructure" to save the CU-UP UE ID, so we
// assume (and below check) that CU-UP UE ID == CU-CP UE ID // assume (and below check) that CU-UP UE ID == CU-CP UE ID
AssertFatal(resp->gNB_cu_cp_ue_id == resp->gNB_cu_up_ue_id, AssertFatal(resp->gNB_cu_cp_ue_id == resp->gNB_cu_up_ue_id,
...@@ -2266,6 +2375,13 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp ...@@ -2266,6 +2375,13 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t); rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t);
} }
if (UE->StatusRrc == NR_RRC_HO_PREPARATION)
{
LOG_I(NR_RRC, "HO LOG: Bearer Context Setup Response has came for UE doing HO! \n");
rrc_gNB_ue_context_setup_request_for_handover_on_target(ue_context_p, resp, instance);
return;
}
/* Instruction towards the DU for DRB configuration and tunnel creation */ /* Instruction towards the DU for DRB configuration and tunnel creation */
f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32 f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32
int nb_drb = 0; int nb_drb = 0;
...@@ -2676,6 +2792,10 @@ void *rrc_gnb_task(void *args_p) { ...@@ -2676,6 +2792,10 @@ void *rrc_gnb_task(void *args_p) {
rrc_gNB_process_HandoverCommand(msg_p, instance); rrc_gNB_process_HandoverCommand(msg_p, instance);
break; break;
case NGAP_HANDOVER_REQUEST:
rrc_gNB_process_Handover_Request(msg_p, instance);
break;
default: default:
LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p);
break; break;
......
...@@ -59,6 +59,9 @@ ...@@ -59,6 +59,9 @@
#include "NR_HandoverPreparationInformation.h" #include "NR_HandoverPreparationInformation.h"
#include "NR_HandoverCommand.h" #include "NR_HandoverCommand.h"
#include "NR_HandoverCommand-IEs.h" #include "NR_HandoverCommand-IEs.h"
#include "NGAP_SourceNGRANNode-ToTargetNGRANNode-TransparentContainer.h"
#include "NGAP_NGRAN-CGI.h"
#include "NGAP_NR-CGI.h"
#include "NGAP_CauseRadioNetwork.h" #include "NGAP_CauseRadioNetwork.h"
#include "f1ap_messages_types.h" #include "f1ap_messages_types.h"
#include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/f1ap_ids.h"
...@@ -74,6 +77,8 @@ ...@@ -74,6 +77,8 @@
#include "NGAP_Dynamic5QIDescriptor.h" #include "NGAP_Dynamic5QIDescriptor.h"
#include "conversions.h" #include "conversions.h"
#include "RRC/NR/rrc_gNB_radio_bearers.h" #include "RRC/NR/rrc_gNB_radio_bearers.h"
#include "rrc_gNB_du.h"
#include "ngap_gNB_nnsf.h"
#include "uper_encoder.h" #include "uper_encoder.h"
...@@ -90,6 +95,7 @@ static const uint16_t NGAP_INTEGRITY_NIA2_MASK = 0x4000; ...@@ -90,6 +95,7 @@ static const uint16_t NGAP_INTEGRITY_NIA2_MASK = 0x4000;
static const uint16_t NGAP_INTEGRITY_NIA3_MASK = 0x2000; static const uint16_t NGAP_INTEGRITY_NIA3_MASK = 0x2000;
#define INTEGRITY_ALGORITHM_NONE NR_IntegrityProtAlgorithm_nia0 #define INTEGRITY_ALGORITHM_NONE NR_IntegrityProtAlgorithm_nia0
extern int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_t *mib, const NR_SIB1_t *sib1);
static int rrc_gNB_process_security(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *const ue_context_pP, ngap_security_capabilities_t *security_capabilities_pP); static int rrc_gNB_process_security(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *const ue_context_pP, ngap_security_capabilities_t *security_capabilities_pP);
...@@ -124,6 +130,28 @@ void process_gNB_security_key ( ...@@ -124,6 +130,28 @@ void process_gNB_security_key (
LOG_I(NR_RRC, "[gNB %d][UE %x] Saved security key %s\n", ctxt_pP->module_id, UE->rnti, ascii_buffer); LOG_I(NR_RRC, "[gNB %d][UE %x] Saved security key %s\n", ctxt_pP->module_id, UE->rnti, ascii_buffer);
} }
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
)
{
char ascii_buffer[65];
uint8_t i;
gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
nr_derive_key_ng_ran_star(pci, absoluteFrequencySSB, UE->nh, UE->kgnb);
for (i = 0; i < 32; i++) {
sprintf(&ascii_buffer[2 * i], "%02X", UE->kgnb[i]);
}
ascii_buffer[2 * i] = '\0';
LOG_I(NR_RRC, "[gNB %d][UE %x] Saved security key %s\n", ctxt_pP->module_id, UE->rnti, ascii_buffer);
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
nr_rrc_pdcp_config_security( nr_rrc_pdcp_config_security(
...@@ -150,7 +178,7 @@ nr_rrc_pdcp_config_security( ...@@ -150,7 +178,7 @@ nr_rrc_pdcp_config_security(
if ( LOG_DUMPFLAG( DEBUG_SECURITY ) ) { if ( LOG_DUMPFLAG( DEBUG_SECURITY ) ) {
if (print_keys == 1 ) { if (print_keys == 1 ) {
print_keys =0; // print_keys =0;
LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, UE->kgnb, 32, "\nKgNB:"); LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, UE->kgnb, 32, "\nKgNB:");
LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, kRRCenc, 16,"\nKRRCenc:" ); LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, kRRCenc, 16,"\nKRRCenc:" );
LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, kRRCint, 16,"\nKRRCint:" ); LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, kRRCint, 16,"\nKRRCint:" );
...@@ -159,7 +187,9 @@ nr_rrc_pdcp_config_security( ...@@ -159,7 +187,9 @@ nr_rrc_pdcp_config_security(
uint8_t security_mode = uint8_t security_mode =
enable_ciphering ? UE->ciphering_algorithm | (UE->integrity_algorithm << 4) : 0 | (UE->integrity_algorithm << 4); enable_ciphering ? UE->ciphering_algorithm | (UE->integrity_algorithm << 4) : 0 | (UE->integrity_algorithm << 4);
nr_pdcp_config_set_security(ctxt_pP->rntiMaybeUEid, DCCH, security_mode, kRRCenc, kRRCint, kUPenc);
LOG_I(NR_RRC, "HO LOG: Current Security Mode %u Integrity Algo: %d Ciphering Algo: %ld\n", security_mode, UE->integrity_algorithm, UE->ciphering_algorithm);
nr_pdcp_config_set_security(ctxt_pP->rntiMaybeUEid, DCCH, security_mode, kRRCenc, kRRCint, kUPenc, UE->as_security_active);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -1195,6 +1225,170 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in ...@@ -1195,6 +1225,170 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in
return (0); return (0);
} }
} }
static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish)
{
if (!ue->Srb[1].Active) {
LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n");
return NULL;
}
NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1);
for (int i = 0; i < maxSRBs; i++)
if (ue->Srb[i].Active) {
asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb);
srb->srb_Identity = i;
if (reestablish) {
asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true);
}
}
return list;
}
static int create_rrc_NGAP_ue_context(protocol_ctxt_t* ctxt_P, const ngap_handover_request_t* const handover_req, uint32_t gNB_ue_ngap_id)
{
struct ngap_gNB_amf_data_s * new_amf_desc_p = NULL;
ngap_gNB_instance_t * ngap_gNB_instance_p = ngap_gNB_get_instance(ctxt_P->module_id);
new_amf_desc_p = ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_p, NGAP_RRC_CAUSE_MO_SIGNALLING, handover_req->guami);
if (new_amf_desc_p) {
LOG_I(NR_RRC, "HO LOG: Chose AMF '%s' (assoc_id %d)\n",
new_amf_desc_p->amf_name,
new_amf_desc_p->assoc_id);
struct ngap_gNB_ue_context_s *ue_desc_p = calloc(1, sizeof(*ue_desc_p));
DevAssert(ue_desc_p != NULL);
/* Keep a reference to the selected AMF */
ue_desc_p->amf_ref = new_amf_desc_p;
ue_desc_p->amf_ue_ngap_id = handover_req->amf_ue_ngap_id;
ue_desc_p->gNB_ue_ngap_id = gNB_ue_ngap_id;
ue_desc_p->gNB_instance = ngap_gNB_instance_p;
ue_desc_p->ue_state = NGAP_UE_CONNECTED;
ngap_store_ue_context(ue_desc_p);
LOG_I(NR_RRC, "HO LOG: AMF found with amf setId: %d amfPointer: %d amfRegionId: %d \n",
handover_req->guami.amf_set_id, handover_req->guami.amf_pointer, handover_req->guami.amf_region_id);
return 0;
}
LOG_E(NR_RRC, "HO LOG: AMF Can not found with amf setId: %d amfPointer: %d amfRegionId: %d \n",
handover_req->guami.amf_set_id, handover_req->guami.amf_pointer, handover_req->guami.amf_region_id);
return -1;
}
int rrc_gNB_process_Handover_Request(MessageDef* msg_p, instance_t instance)
{
protocol_ctxt_t ctxt = {0};
ctxt.eNB_index = 0;
ngap_handover_request_t* handover_req = &NGAP_HANDOVER_REQUEST(msg_p);
gNB_RRC_INST* rrc = RC.nrrrc[instance];
rrc_gNB_ue_context_t * ue_context_p = NULL;
NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer_t* transparentContainer = NULL;
asn_dec_rval_t dec_rval = aper_decode_complete(NULL, &asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, (void**)&transparentContainer, handover_req->sourceToTargetTransparentContainer.buffer, handover_req->sourceToTargetTransparentContainer.length);
if (dec_rval.code != RC_OK) {
LOG_E(NR_RRC, "cannot decode Ho Request Source To Target Transparent Container for UE ID: %lu, Returning...\n", handover_req->amf_ue_ngap_id);
return -1;
}
if ( LOG_DEBUGFLAG(DEBUG_ASN1) )
xer_fprint(stdout, &asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, (const void*)transparentContainer);
uint64_t nci;
BIT_STRING_TO_NR_CELL_IDENTITY(&transparentContainer->targetCell_ID.choice.nR_CGI->nRCellIdentity, nci);
LOG_I(NR_RRC, "HO LOG: HO Request has came for NCI: %lu \n", nci);
uint8_t cellIdx = UINT8_MAX;
struct nr_rrc_du_container_t* du = get_du_for_nr_cell_id(rrc, nci, &cellIdx);
if (du == NULL || cellIdx == UINT8_MAX)
{
/* Cell Not Found! Return HO Request Failure*/
LOG_E(RRC, "received Handover Request message, but no corresponding DU found\n");
return -1;
}
const f1ap_served_cell_info_t * cell_info = &du->setup_req->cell[cellIdx].info;
uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1);
sctp_assoc_t curr_assoc_id = du->assoc_id;
ue_context_p = rrc_gNB_create_ue_context(curr_assoc_id, UINT16_MAX, rrc, UINT64_MAX, UINT32_MAX);
gNB_RRC_UE_t* UE = &(ue_context_p->ue_context);
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0);
if (create_rrc_NGAP_ue_context(&ctxt, handover_req, UE->rrc_ue_id) < 0) {
LOG_E(NR_RRC, "Can not add the ue to NGAP Context! Trigger Handover Cancel!\n");
return -1;
}
UE->StatusRrc = NR_RRC_HO_PREPARATION;
UE->amf_ue_ngap_id = handover_req->amf_ue_ngap_id;
UE->nh_ncc = handover_req->next_hop_chain_count;
UE->ue_guami.mcc = handover_req->guami.mcc;
UE->ue_guami.mnc = handover_req->guami.mnc;
UE->ue_guami.mnc_len = handover_req->guami.mnc_len;
UE->ue_guami.amf_region_id = handover_req->guami.amf_region_id;
UE->ue_guami.amf_set_id = handover_req->guami.amf_set_id;
UE->ue_guami.amf_pointer = handover_req->guami.amf_pointer;
// /* Clone Handover Preparation Information Before Parsing! */
// UE->ue_handover_prep_info_buffer.buf = (uint8_t*)calloc(1, transparentContainer->rRCContainer.size);
// memcpy(UE->ue_handover_prep_info_buffer.buf, transparentContainer->rRCContainer.buf, transparentContainer->rRCContainer.size);
// UE->ue_handover_prep_info_buffer.len = transparentContainer->rRCContainer.size;
/* Parse If Needed Later (?)*/
NR_HandoverPreparationInformation_t *hoPrepInformation = NULL;
asn_dec_rval_t hoPrep_dec_rval = uper_decode_complete(NULL,
&asn_DEF_NR_HandoverPreparationInformation,
(void **)&hoPrepInformation,
(uint8_t *)transparentContainer->rRCContainer.buf,
transparentContainer->rRCContainer.size);
AssertFatal(hoPrep_dec_rval.code == RC_OK && hoPrep_dec_rval.consumed > 0, "Handover Prep Info decode error\n");
if ( LOG_DEBUGFLAG(DEBUG_ASN1) )
xer_fprint(stdout, &asn_DEF_NR_HandoverPreparationInformation, (const void*)hoPrepInformation);
NR_HandoverPreparationInformation_IEs_t* hoPrep = hoPrepInformation->criticalExtensions.choice.c1->choice.handoverPreparationInformation;
if (UE->ue_cap_buffer.buf != NULL)
free(UE->ue_cap_buffer.buf);
const NR_UE_CapabilityRAT_ContainerList_t *ue_CapabilityRAT_ContainerList =
&(hoPrep->ue_CapabilityRAT_List);
UE->ue_cap_buffer.len = uper_encode_to_new_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList,
NULL,
ue_CapabilityRAT_ContainerList,
(void **)&UE->ue_cap_buffer.buf);
if (UE->ue_cap_buffer.len <= 0) {
LOG_E(RRC, "could not encode UE-CapabilityRAT-ContainerList, abort handling capabilities\n");
return -1;
}
UE->ue_handover_prep_info_buffer.len = uper_encode_to_new_buffer(&asn_DEF_NR_HandoverPreparationInformation,
NULL,
(const void*)hoPrepInformation,
(void **)&UE->ue_handover_prep_info_buffer.buf);
if (UE->ue_handover_prep_info_buffer.len <= 0) {
LOG_E(RRC, "Could not encode Handover Preparation Information, abort...\n");
return -1;
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_HandoverPreparationInformation, hoPrepInformation);
//PREPARE PDCP
rrc_gNB_process_security(&ctxt, ue_context_p, &handover_req->security_capabilities);
memcpy(UE->nh, handover_req->next_hop, SECURITY_KEY_LENGTH);
process_gNB_kgnb_star(&ctxt, ue_context_p, cell_info->nr_pci, ssb_arfcn);
UE->Srb[1].Active = 1;
UE->Srb[2].Active = 1;
NR_SRB_ToAddModList_t *SRBs = createSRBlist(UE, true);
nr_pdcp_add_srbs(true, UE->rrc_ue_id, SRBs, 0, NULL, NULL);
uint8_t enableCiphering = 0;
UE->as_security_active = true;
nr_rrc_pdcp_config_security(&ctxt, ue_context_p, enableCiphering);
trigger_bearer_setup(rrc, UE, handover_req->nb_of_pdusessions, handover_req->pduSessionResourceSetupHOList, handover_req->ue_ambr.br_dl);
return 0;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/* /*
...@@ -1351,6 +1545,75 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED( ...@@ -1351,6 +1545,75 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(
ue_context_pP->ue_context.StatusRrc = NR_RRC_HO_PREPARATION; ue_context_pP->ue_context.StatusRrc = NR_RRC_HO_PREPARATION;
itti_send_msg_to_task(TASK_NGAP, ctxt_pP->instance, msg_p); itti_send_msg_to_task(TASK_NGAP, ctxt_pP->instance, msg_p);
} }
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
)
{
LOG_I(NR_RRC, "HO Log: Preparing Handover Notify Structure\n");
MessageDef *msg_p;
gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
msg_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_HANDOVER_NOTIFY);
ngap_handover_notify_t* ho_notify = &NGAP_HANDOVER_NOTIFY(msg_p);
memset(ho_notify, 0, sizeof(*ho_notify));
ho_notify->gNB_ue_ngap_id = UE->rrc_ue_id;
ho_notify->amf_ue_ngap_id = UE->amf_ue_ngap_id;
ho_notify->nrCellId = nrCellId;
itti_send_msg_to_task(TASK_NGAP, ctxt_pP->instance, msg_p);
}
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
)
{
LOG_I(NR_RRC, "HO Log: Preparing Handover Command Structure\n");
MessageDef *msg_p;
gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
msg_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_HANDOVER_REQUEST_ACKNOWLEDGE);
ngap_handover_request_ack_t* ho_req_ack = &NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(msg_p);
memset(ho_req_ack, 0, sizeof(*ho_req_ack));
//Prepare RAN UE NGAP ID
ho_req_ack->gNB_ue_ngap_id = UE->rrc_ue_id;
//Prepare AMF UE NGAP ID
ho_req_ack->amf_ue_ngap_id = UE->amf_ue_ngap_id;
ho_req_ack->nb_of_pdusessions = UE->nb_of_pdusessions;
for (int pduSessionIdx = 0; pduSessionIdx < UE->nb_of_pdusessions; pduSessionIdx++)
{
rrc_pdu_session_param_t* session = &UE->pduSession[pduSessionIdx];
ho_req_ack->pdusessions[pduSessionIdx].pdusession_id = session->param.pdusession_id;
ho_req_ack->pdusessions[pduSessionIdx].pdu_session_type = session->param.pdu_session_type;
ho_req_ack->pdusessions[pduSessionIdx].gtp_teid= session->param.gNB_teid_N3;
memcpy(ho_req_ack->pdusessions[pduSessionIdx].gNB_addr.buffer, session->param.gNB_addr_N3.buffer, session->param.gNB_addr_N3.length);
ho_req_ack->pdusessions[pduSessionIdx].gNB_addr.length = session->param.gNB_addr_N3.length;
ho_req_ack->pdusessions[pduSessionIdx].nb_of_qos_flow = session->param.nb_qos;
for (int qos_flow_index = 0; qos_flow_index < ho_req_ack->pdusessions[pduSessionIdx].nb_of_qos_flow; qos_flow_index++) {
ho_req_ack->pdusessions[pduSessionIdx].associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi;
ho_req_ack->pdusessions[pduSessionIdx].associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
}
}
ho_req_ack->targetToSourceTransparentContainer.buffer = (uint8_t*)(calloc(1, handoverCommandSize));
memcpy(ho_req_ack->targetToSourceTransparentContainer.buffer, *handoverCommand, handoverCommandSize);
ho_req_ack->targetToSourceTransparentContainer.length = handoverCommandSize;
UE->StatusRrc = NR_RRC_HO_EXECUTION;
itti_send_msg_to_task(TASK_NGAP, ctxt_pP->instance, msg_p);
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE( rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(
......
...@@ -109,6 +109,30 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED( ...@@ -109,6 +109,30 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(
const size_t handoverPrepInfoSize 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); int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance);
void void
......
...@@ -254,6 +254,20 @@ nr_rrc_du_container_t *get_du_for_ue(gNB_RRC_INST *rrc, uint32_t ue_id) ...@@ -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); 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 *get_du_by_assoc_id(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
{ {
nr_rrc_du_container_t e = {.assoc_id = 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 ...@@ -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_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_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); 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, ...@@ -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 // configure lower layers to apply SRB integrity protection and ciphering
for (int i = 1; i < NR_NUM_SRB; i++) { for (int i = 1; i < NR_NUM_SRB; i++) {
if (ue_rrc->perNB[gNB_index].Srb[i] == RB_ESTABLISHED) 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 { } else {
LOG_I(NR_RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x", securityMode); LOG_I(NR_RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x", securityMode);
......
...@@ -94,6 +94,10 @@ ...@@ -94,6 +94,10 @@
#include "NGAP_GTP-TEID.h" #include "NGAP_GTP-TEID.h"
#include "NGAP_TargetNGRANNode-ToSourceNGRANNode-TransparentContainer.h" #include "NGAP_TargetNGRANNode-ToSourceNGRANNode-TransparentContainer.h"
#include "NGAP_TargetToSource-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 */ /* Checking version of ASN1C compiler */
......
...@@ -355,10 +355,15 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { ...@@ -355,10 +355,15 @@ void *ngap_gNB_process_itti_msg(void *notUsed) {
case NGAP_PDUSESSION_RELEASE_RESPONSE: case NGAP_PDUSESSION_RELEASE_RESPONSE:
ngap_gNB_pdusession_release_resp(instance, &NGAP_PDUSESSION_RELEASE_RESPONSE(received_msg)); ngap_gNB_pdusession_release_resp(instance, &NGAP_PDUSESSION_RELEASE_RESPONSE(received_msg));
break; break;
case NGAP_HANDOVER_REQUIRED: case NGAP_HANDOVER_REQUIRED:
ngap_gNB_handover_required(instance, &NGAP_HANDOVER_REQUIRED(received_msg)); ngap_gNB_handover_required(instance, &NGAP_HANDOVER_REQUIRED(received_msg));
break; 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: default:
NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
break; break;
......
...@@ -62,8 +62,23 @@ ...@@ -62,8 +62,23 @@
#include "NGAP_UEHistoryInformation.h" #include "NGAP_UEHistoryInformation.h"
#include "NGAP_LastVisitedNGRANCellInformation.h" #include "NGAP_LastVisitedNGRANCellInformation.h"
#include "NGAP_Cause.h" #include "NGAP_Cause.h"
#include "NGAP_PDUSessionResourceAdmittedList.h"
#include "NGAP_PDUSessionResourceAdmittedItem.h"
#include "NGAP_HandoverRequestAcknowledgeTransfer.h"
#include "NGAP_QosFlowItemWithDataForwarding.h"
#include "NGAP_HandoverNotify.h"
static void allocAddrCopy(BIT_STRING_t *out, transport_layer_addr_t in)
{
if (in.length) {
out->buf = malloc(in.length);
memcpy(out->buf, in.buffer, in.length);
out->size = in.length;
out->bits_unused = 0;
}
}
int ngap_ue_context_release_complete(instance_t instance, int ngap_ue_context_release_complete(instance_t instance,
ngap_ue_release_complete_t *ue_release_complete_p) ngap_ue_release_complete_t *ue_release_complete_p)
{ {
...@@ -245,6 +260,214 @@ int ngap_ue_context_release_req(instance_t instance, ...@@ -245,6 +260,214 @@ int ngap_ue_context_release_req(instance_t instance,
return 0; return 0;
} }
int ngap_gNB_handover_request_acknowledge(instance_t instance, ngap_handover_request_ack_t* handover_req_ack_p)
{
NGAP_INFO("Preparing HO Request Acknowledge Message!\n");
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
NGAP_NGAP_PDU_t pdu;
uint8_t *buffer = NULL;
uint32_t length;
/* Retrieve the NGAP gNB instance associated with Mod_id */
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
DevAssert(handover_req_ack_p != NULL);
DevAssert(ngap_gNB_instance_p != NULL);
if ((ue_context_p = ngap_get_ue_context(handover_req_ack_p->gNB_ue_ngap_id)) == NULL) {
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", handover_req_ack_p->gNB_ue_ngap_id);
return -1;
}
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
asn1cCalloc(pdu.choice.successfulOutcome, head);
head->procedureCode = NGAP_ProcedureCode_id_HandoverResourceAllocation;
head->criticality = NGAP_Criticality_reject;
head->value.present = NGAP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
NGAP_HandoverRequestAcknowledge_t *out = &head->value.choice.HandoverRequestAcknowledge;
/* mandatory */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequestAcknowledgeIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_AMF_UE_NGAP_ID;
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, handover_req_ack_p->amf_ue_ngap_id);
}
/* mandatory */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequestAcknowledgeIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_RAN_UE_NGAP_ID;
ie->value.choice.RAN_UE_NGAP_ID = (int64_t)handover_req_ack_p->gNB_ue_ngap_id;
}
/* mandatory */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequestAcknowledgeIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_TargetToSource_TransparentContainer;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_TargetToSource_TransparentContainer;
NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer_t* transparentContainer = (NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer_t*)calloc(1, sizeof(NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer_t));
//rRC Container
{
// Handover Command
transparentContainer->rRCContainer.size = handover_req_ack_p->targetToSourceTransparentContainer.length;
transparentContainer->rRCContainer.buf = (uint8_t *)malloc(handover_req_ack_p->targetToSourceTransparentContainer.length);
memcpy(transparentContainer->rRCContainer.buf, handover_req_ack_p->targetToSourceTransparentContainer.buffer ,handover_req_ack_p->targetToSourceTransparentContainer.length);
uint8_t *buf = NULL;
int encoded = aper_encode_to_new_buffer(&asn_DEF_NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer, NULL, transparentContainer, (void**)&buf);
OCTET_STRING_fromBuf(&ie->value.choice.TargetToSource_TransparentContainer, (const char *)buf,
encoded);
}
}
/* mandatory */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequestAcknowledgeIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceAdmittedList;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_PDUSessionResourceAdmittedList;
for (int pduSesIdx = 0; pduSesIdx < handover_req_ack_p->nb_of_pdusessions; pduSesIdx++)
{
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceAdmittedList.list, NGAP_PDUSessionResourceAdmittedItem_t, hoPduSesAdmittedItem);
hoPduSesAdmittedItem->pDUSessionID = handover_req_ack_p->pdusessions[pduSesIdx].pdusession_id;
/* dLQosFlowPerTNLInformation */
NGAP_HandoverRequestAcknowledgeTransfer_t hoReqTransfer = {0};
hoReqTransfer.dL_NGU_UP_TNLInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
asn1cCalloc(hoReqTransfer.dL_NGU_UP_TNLInformation.choice.gTPTunnel, tmp);
GTP_TEID_TO_ASN1(handover_req_ack_p->pdusessions[pduSesIdx].gtp_teid, &tmp->gTP_TEID);
allocAddrCopy(&tmp->transportLayerAddress, handover_req_ack_p->pdusessions[pduSesIdx].gNB_addr);
for (int j = 0; j < handover_req_ack_p->pdusessions[pduSesIdx].nb_of_qos_flow; j++)
{
asn1cSequenceAdd(hoReqTransfer.qosFlowSetupResponseList.list, NGAP_QosFlowItemWithDataForwarding_t, qosItem);
qosItem->qosFlowIdentifier = handover_req_ack_p->pdusessions[pduSesIdx].associated_qos_flows[j].qfi;
qosItem->dataForwardingAccepted = NGAP_DataForwardingAccepted_data_forwarding_accepted;
}
void *hoReqTransfer_buffer;
ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_NGAP_HandoverRequestAcknowledgeTransfer, NULL, &hoReqTransfer, &hoReqTransfer_buffer);
AssertFatal(encoded > 0, "ASN1 message encoding failed !\n");
hoPduSesAdmittedItem->handoverRequestAcknowledgeTransfer.buf = hoReqTransfer_buffer;
hoPduSesAdmittedItem->handoverRequestAcknowledgeTransfer.size = encoded;
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_HandoverRequestAcknowledgeTransfer, &hoReqTransfer);
}
}
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, (void *)&pdu);
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
/* Encode procedure has failed... */
NGAP_ERROR("Failed to encode Handover Request Acknowledge Msg\n");
return -1;
}
/* UE associated signalling -> use the allocated stream */
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance,
ue_context_p->amf_ref->assoc_id, buffer,
length, ue_context_p->tx_stream);
return 0;
}
int ngap_gNB_handover_notify(instance_t instance, ngap_handover_notify_t* handover_notify_p)
{
LOG_I(NR_RRC, "HO LOG: NGAP Handover Required Preparation!\n");
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
NGAP_NGAP_PDU_t pdu;
uint8_t *buffer = NULL;
uint32_t length;
/* Retrieve the NGAP gNB instance associated with Mod_id */
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
DevAssert(handover_notify_p != NULL);
DevAssert(ngap_gNB_instance_p != NULL);
if ((ue_context_p = ngap_get_ue_context(handover_notify_p->gNB_ue_ngap_id)) == NULL) {
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", handover_notify_p->gNB_ue_ngap_id);
return -1;
}
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu.choice.initiatingMessage, head);
head->procedureCode = NGAP_ProcedureCode_id_HandoverNotification;
head->criticality = NGAP_Criticality_ignore;
head->value.present = NGAP_InitiatingMessage__value_PR_HandoverNotify;
NGAP_HandoverNotify_t *out = &head->value.choice.HandoverNotify;
/* mandatory */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_HandoverNotifyIEs__value_PR_AMF_UE_NGAP_ID;
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id);
}
/* mandatory */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_HandoverNotifyIEs__value_PR_RAN_UE_NGAP_ID;
ie->value.choice.RAN_UE_NGAP_ID = (int64_t)ue_context_p->gNB_ue_ngap_id;
}
/* mandatory */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_UserLocationInformation;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_HandoverNotifyIEs__value_PR_UserLocationInformation;
ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR;
asn1cCalloc(ie->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p);
/* Set nRCellIdentity. default userLocationInformationNR */
MACRO_GNB_ID_TO_CELL_IDENTITY(ngap_gNB_instance_p->gNB_id,
handover_notify_p->nrCellId, // Cell ID
&userinfo_nr_p->nR_CGI.nRCellIdentity);
MCC_MNC_TO_TBCD(ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].mcc,
ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].mnc,
ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].mnc_digit_length,
&userinfo_nr_p->nR_CGI.pLMNIdentity);
// /* Set TAI */
INT24_TO_OCTET_STRING(ngap_gNB_instance_p->tac, &userinfo_nr_p->tAI.tAC);
MCC_MNC_TO_PLMNID(ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].mcc,
ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].mnc,
ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].mnc_digit_length,
&userinfo_nr_p->tAI.pLMNIdentity);
}
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
/* Encode procedure has failed... */
NGAP_ERROR("Failed to encode Handover Required Msg\n");
return -1;
}
/* UE associated signalling -> use the allocated stream */
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance,
ue_context_p->amf_ref->assoc_id, buffer,
length, ue_context_p->tx_stream);
return 0;
}
int ngap_gNB_handover_required(instance_t instance, ngap_handover_required_t* handover_required_p) int ngap_gNB_handover_required(instance_t instance, ngap_handover_required_t* handover_required_p)
{ {
......
...@@ -41,4 +41,9 @@ int ngap_ue_context_release_req(instance_t instance, ...@@ -41,4 +41,9 @@ int ngap_ue_context_release_req(instance_t instance,
int ngap_gNB_handover_required(instance_t instance, int ngap_gNB_handover_required(instance_t instance,
ngap_handover_required_t *handover_required_p); 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_ */ #endif /* NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_ */
...@@ -98,7 +98,11 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) { ...@@ -98,7 +98,11 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) {
free(res.buffer); free(res.buffer);
NGAP_INFO("TODO Handover Resource Allocation initiating message\n"); NGAP_INFO("TODO Handover Resource Allocation initiating message\n");
break; 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: default:
NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n", NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage->procedureCode); (int)pdu->choice.initiatingMessage->procedureCode);
......
...@@ -50,7 +50,9 @@ static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, uint8_t **buf ...@@ -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_UEContextReleaseRequest,
NGAP_ProcedureCode_id_PathSwitchRequest, NGAP_ProcedureCode_id_PathSwitchRequest,
NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication, NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication,
NGAP_ProcedureCode_id_HandoverPreparation,}; NGAP_ProcedureCode_id_HandoverPreparation,
NGAP_ProcedureCode_id_HandoverNotification,
NGAP_ProcedureCode_id_DownlinkRANStatusTransfer,};
int i; int i;
for (i = 0; i < sizeofArray(tmp); i++) for (i = 0; i < sizeofArray(tmp); i++)
if (pdu->choice.initiatingMessage->procedureCode == 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 ...@@ -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_UEContextRelease,
NGAP_ProcedureCode_id_PDUSessionResourceSetup, NGAP_ProcedureCode_id_PDUSessionResourceSetup,
NGAP_ProcedureCode_id_PDUSessionResourceModify, NGAP_ProcedureCode_id_PDUSessionResourceModify,
NGAP_ProcedureCode_id_PDUSessionResourceRelease}; NGAP_ProcedureCode_id_PDUSessionResourceRelease,
NGAP_ProcedureCode_id_HandoverResourceAllocation
};
int i; int i;
for (i = 0; i < sizeofArray(tmp); i++) for (i = 0; i < sizeofArray(tmp); i++)
if (pdu->choice.successfulOutcome->procedureCode == 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 ...@@ -680,10 +680,154 @@ static int ngap_gNB_handle_error_indication(sctp_assoc_t assoc_id, uint32_t stre
// TODO continue // TODO continue
return 0; 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) 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"); 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; return 0;
} }
...@@ -1414,7 +1558,7 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = { ...@@ -1414,7 +1558,7 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = {
{ngap_gNB_handle_nas_downlink, 0, 0}, /* DownlinkNASTransport */ {ngap_gNB_handle_nas_downlink, 0, 0}, /* DownlinkNASTransport */
{0, 0, 0}, /* DownlinkNonUEAssociatedNRPPaTransport */ {0, 0, 0}, /* DownlinkNonUEAssociatedNRPPaTransport */
{0, 0, 0}, /* DownlinkRANConfigurationTransfer */ {0, 0, 0}, /* DownlinkRANConfigurationTransfer */
{0, 0, 0}, /* DownlinkRANStatusTransfer */ {ngap_gNB_handle_downlink_ran_status_transfer, 0, 0}, /* DownlinkRANStatusTransfer */
{0, 0, 0}, /* DownlinkUEAssociatedNRPPaTransport */ {0, 0, 0}, /* DownlinkUEAssociatedNRPPaTransport */
{ngap_gNB_handle_error_indication, 0, 0}, /* ErrorIndication */ {ngap_gNB_handle_error_indication, 0, 0}, /* ErrorIndication */
{0, 0, 0}, /* HandoverCancel */ {0, 0, 0}, /* HandoverCancel */
......
...@@ -209,7 +209,8 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t o ...@@ -209,7 +209,8 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t o
/* Multiply by Q */ /* Multiply by Q */
EVAL = MUL64(EVAL,Q,c); EVAL = MUL64(EVAL,Q,c);
MAC_I = (uint32_t)(EVAL >> 32) ^ z[4]; 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); MAC_I = hton_int32(MAC_I);
memcpy(out, &MAC_I, 4); 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