mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 05:00:31 +00:00
Compare commits
2 Commits
develop
...
N2_HO_Sour
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10629df5f9 | ||
|
|
9957f80688 |
310
ci-scripts/conf_files/gnb.sa.firecell.ban78.106prb.rfsim.conf
Normal file
310
ci-scripts/conf_files/gnb.sa.firecell.ban78.106prb.rfsim.conf
Normal file
@@ -0,0 +1,310 @@
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; sd = 0x1; }) });
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
internal_neighbour_id = 0; #For MultiCell Purposes
|
||||
neighbour_gNB_ID = 0xb00;
|
||||
neighbour_nr_cellid = 1;
|
||||
neighbour_physical_cellId = 0x001;
|
||||
neighbour_absoluteFrequencySSB = 621600 ;
|
||||
neighbour_subcarrierSpacing = 1; #30 KHz
|
||||
neighbour_mcc = 999;
|
||||
neighbour_mnc = 99;
|
||||
neighbour_mnc_length = 2;
|
||||
neighbour_tac = 1;
|
||||
},
|
||||
{ #For test : source gNB as neighbour gNB
|
||||
internal_neighbour_id = 1;
|
||||
neighbour_gNB_ID = 0xe00;
|
||||
neighbour_nr_cellid = 12345678L;
|
||||
neighbour_physical_cellId = 0;
|
||||
neighbour_absoluteFrequencySSB = 621312 ;
|
||||
neighbour_subcarrierSpacing = 1; #30 KHz
|
||||
neighbour_mcc = 001;
|
||||
neighbour_mnc = 01;
|
||||
neighbour_mnc_length = 2;
|
||||
neighbour_tac = 1;
|
||||
},
|
||||
);
|
||||
|
||||
nr_measurement_event_configuration = {
|
||||
enableA2 = 1;
|
||||
enableA3 = 1;
|
||||
thresholdA2 = 60; # 5dB
|
||||
A2_timeToTrigger = 1;
|
||||
A3_offset = 10; # 5dB
|
||||
A3_hysteresis = 0;
|
||||
A3_timeToTrigger = 1; # ms40
|
||||
};
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
do_CSIRS = 0;
|
||||
do_SRS = 0;
|
||||
|
||||
pdcch_ConfigSIB1 = (
|
||||
{
|
||||
controlResourceSetZero = 12;
|
||||
searchSpaceZero = 0;
|
||||
}
|
||||
);
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
physCellId = 0;
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||
absoluteFrequencySSB = 621312;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3600 MHz
|
||||
dl_absoluteFrequencyPointA = 620040;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 5;
|
||||
nrofDownlinkSlots = 3;
|
||||
nrofDownlinkSymbols = 8;
|
||||
nrofUplinkSlots = 1;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "192.168.70.132";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "oaicore";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "oaicore";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 300;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 0;
|
||||
ul_max_mcs = 28;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 0;
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
#sdr_addrs ="3231EEC";
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = "4043";
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="info";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
|
||||
@@ -423,6 +423,7 @@ typedef struct f1ap_ue_context_setup_s {
|
||||
ReconfigurationCompl_t ReconfigComplOutcome;
|
||||
uint8_t *rrc_container;
|
||||
int rrc_container_length;
|
||||
uint8_t* transmission_action_indicator;
|
||||
} f1ap_ue_context_setup_t, f1ap_ue_context_modif_req_t, f1ap_ue_context_modif_resp_t;
|
||||
|
||||
typedef enum F1ap_Cause_e {
|
||||
|
||||
@@ -46,6 +46,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiM
|
||||
MESSAGE_DEF(NGAP_PAGING_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_paging_log)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_release_request_log)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_release_response_log)
|
||||
MESSAGE_DEF(NGAP_HANDOVER_REQUIRED_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_handover_required_log)
|
||||
MESSAGE_DEF(NGAP_ERROR_INDICATION_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_error_indication_log)
|
||||
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_path_switch_req_log)
|
||||
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_path_switch_req_ack_log)
|
||||
@@ -72,6 +73,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_SETUP_RESP , MESSAGE_PRIORITY_MED, ngap_pdu
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, ngap_pdusession_setup_req_fail_t , ngap_pdusession_setup_request_fail)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_resp_t , ngap_pdusession_modify_resp)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdusession_release_resp_t , ngap_pdusession_release_resp)
|
||||
MESSAGE_DEF(NGAP_HANDOVER_REQUIRED , MESSAGE_PRIORITY_MED, ngap_handover_required_t , ngap_handover_required)
|
||||
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, ngap_path_switch_req_t , ngap_path_switch_req)
|
||||
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, ngap_path_switch_req_ack_t , ngap_path_switch_req_ack)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_MODIFICATION_IND , MESSAGE_PRIORITY_MED, ngap_pdusession_modification_ind_t , ngap_pdusession_modification_ind)
|
||||
@@ -85,6 +87,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQ , MESSAGE_PRIORITY_MED, ngap_pd
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_REQ , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_req_t , ngap_pdusession_modify_req )
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_COMMAND , MESSAGE_PRIORITY_MED, ngap_pdusession_release_command_t , ngap_pdusession_release_command)
|
||||
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND, MESSAGE_PRIORITY_MED, ngap_ue_release_command_t , ngap_ue_release_command)
|
||||
MESSAGE_DEF(NGAP_HANDOVER_COMMAND , MESSAGE_PRIORITY_MED, ngap_handover_command_t , ngap_handover_command)
|
||||
|
||||
/* 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)
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
#define NGAP_PDUSESSION_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_setup_req
|
||||
#define NGAP_PDUSESSION_MODIFY_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_modify_req
|
||||
#define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind
|
||||
#define NGAP_HANDOVER_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_required
|
||||
#define NGAP_HANDOVER_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_command
|
||||
|
||||
#define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req
|
||||
#define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command
|
||||
@@ -526,6 +528,51 @@ typedef struct ngap_uplink_nas_s {
|
||||
ngap_pdu_t nas_pdu;
|
||||
} ngap_uplink_nas_t;
|
||||
|
||||
typedef struct target_cell_id_s {
|
||||
ngap_plmn_identity_t plmn_identity;
|
||||
uint32_t nrCellIdentity;
|
||||
} target_cell_id_t;
|
||||
|
||||
typedef struct target_ran_node_id_s {
|
||||
uint32_t targetgNBId;
|
||||
ngap_plmn_identity_t plmn_identity; //use for both + selected TAI
|
||||
uint32_t tac; //use for both + selected TAI
|
||||
} target_ran_node_id_t;
|
||||
|
||||
typedef struct source_to_target_transparent_container_s {
|
||||
ngap_pdu_t handoverInfo;
|
||||
target_cell_id_t targetCellId;
|
||||
} source_to_target_transparent_container_t;
|
||||
|
||||
typedef struct handover_drb_item_s {
|
||||
uint8_t drbId;
|
||||
uint8_t qosFlowId;
|
||||
bool isActive;
|
||||
} handover_drb_item_t;
|
||||
|
||||
|
||||
typedef struct ngap_handover_required_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
uint64_t amf_ue_ngap_id;
|
||||
target_ran_node_id_t target_gnb_id;
|
||||
source_to_target_transparent_container_t* sourceToTargetContainer;
|
||||
uint8_t nb_of_pdusessions;
|
||||
pdusession_setup_t pdusessions[NGAP_MAX_PDUSESSION];
|
||||
handover_drb_item_t used_drbs[MAX_DRBS_PER_UE];
|
||||
uint32_t cause; //16 for Handover DEsirable For Radio Reason
|
||||
uint32_t handoverType; // 0 for intra5gs
|
||||
} ngap_handover_required_t;
|
||||
|
||||
typedef struct ngap_handover_command_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
uint64_t amf_ue_ngap_id;
|
||||
ngap_pdu_t handoverCommand;
|
||||
uint32_t cause; //16 for Handover DEsirable For Radio Reason
|
||||
uint32_t handoverType; // 0 for intra5gs
|
||||
uint8_t nb_of_pdusessions;
|
||||
pdusession_setup_t pduSessionResourceHandoverList[NGAP_MAX_PDUSESSION]; //for data forwarding
|
||||
} ngap_handover_command_t;
|
||||
|
||||
typedef struct ngap_ue_cap_info_ind_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
ngap_pdu_t ue_radio_cap;
|
||||
|
||||
@@ -1056,12 +1056,12 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte
|
||||
|
||||
/* optional */
|
||||
/* c7. TransmissionActionIndicator */
|
||||
if (0) {
|
||||
if (f1ap_ue_context_modification_req->transmission_action_indicator != NULL) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie7);
|
||||
ie7->id = F1AP_ProtocolIE_ID_id_TransmissionActionIndicator;
|
||||
ie7->criticality = F1AP_Criticality_ignore;
|
||||
ie7->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator;
|
||||
ie7->value.choice.TransmissionActionIndicator = F1AP_TransmissionActionIndicator_stop;
|
||||
ie7->value.choice.TransmissionActionIndicator = (int64_t)*f1ap_ue_context_modification_req->transmission_action_indicator;
|
||||
}
|
||||
|
||||
/* optional */
|
||||
|
||||
@@ -1074,6 +1074,20 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t
|
||||
}
|
||||
}
|
||||
|
||||
F1AP_UEContextModificationRequestIEs_t *ieTxInd;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t,
|
||||
ieTxInd,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_TransmissionActionIndicator,
|
||||
false);
|
||||
|
||||
if (ieTxInd) {
|
||||
f1ap_ue_context_modification_req->transmission_action_indicator = calloc(1, sizeof(uint8_t));
|
||||
*f1ap_ue_context_modification_req->transmission_action_indicator = ieTxInd->value.choice.TransmissionActionIndicator;
|
||||
LOG_I(NR_MAC, "HO LOG: Successfully Set TransmissionActionIndicator: %u\n", *f1ap_ue_context_modification_req->transmission_action_indicator);
|
||||
}
|
||||
|
||||
|
||||
ue_context_modification_request(f1ap_ue_context_modification_req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1607,8 +1607,46 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
||||
|
||||
char gnbpath[MAX_OPTNAME_SIZE + 8];
|
||||
sprintf(gnbpath,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
|
||||
|
||||
paramdef_t NeighbourCellParams[] = GNBNEIGHBOURCELLPARAMS_DESC;
|
||||
paramlist_def_t NeighbourCellParamList = {GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, NULL, 0};
|
||||
|
||||
|
||||
config_getlist(config_get_if(), &NeighbourCellParamList, NeighbourCellParams, sizeofArray(NeighbourCellParams), gnbpath);
|
||||
LOG_I(NR_MAC, "HO LOG: Neighbour Cell ELM NUM: %d\n", NeighbourCellParamList.numelt);
|
||||
|
||||
for (uint8_t l = 0; l < NeighbourCellParamList.numelt; ++l) {
|
||||
rrc->neighbourConfiguration[l].neighbour_gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr);
|
||||
rrc->neighbourConfiguration[l].neighbour_nrcell_id = (uint64_t) *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr);
|
||||
rrc->neighbourConfiguration[l].physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr;
|
||||
rrc->neighbourConfiguration[l].subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr;
|
||||
rrc->neighbourConfiguration[l].absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr;
|
||||
rrc->neighbourConfiguration[l].neighbour_mcc = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_MCC_IDX].uptr;
|
||||
rrc->neighbourConfiguration[l].neighbour_mnc = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_MNC_IDX].uptr;
|
||||
rrc->neighbourConfiguration[l].neighbour_mnc_digit_length = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_MNC_DIGIT_LENGTH_IDX].uptr;
|
||||
rrc->neighbourConfiguration[l].neighbour_tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr;
|
||||
}
|
||||
|
||||
rrc->number_of_neighbours = NeighbourCellParamList.numelt;
|
||||
|
||||
if (rrc->number_of_neighbours > 0) {
|
||||
paramdef_t MeasurementEventParams[] = MEASUREMENT_EVENTS_GLOBALPARAMS_DESC;
|
||||
paramlist_def_t MeasurementEventParamList = {GNB_CONFIG_STRING_MEASUREMENT_EVENTS, NULL, 0};
|
||||
config_getlist(config_get_if(), &MeasurementEventParamList, MeasurementEventParams, sizeofArray(MeasurementEventParams), gnbpath);
|
||||
|
||||
rrc->measurementConfiguration.enableA2 = (*MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A2_IDX].i64ptr);
|
||||
if (rrc->measurementConfiguration.enableA2) {
|
||||
rrc->measurementConfiguration.a2_threshold = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A2_THRESHOLD_IDX].i64ptr;
|
||||
rrc->measurementConfiguration.a2_time_to_trigger = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A2_TIME_TO_TRIGGER_IDX].i64ptr;
|
||||
}
|
||||
|
||||
rrc->measurementConfiguration.enableA3 = (*MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A3_IDX].i64ptr);
|
||||
if (rrc->measurementConfiguration.enableA3) {
|
||||
rrc->measurementConfiguration.a3_offset = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A3_OFFSET_IDX].i64ptr;
|
||||
rrc->measurementConfiguration.a3_hysteresis = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A3_HYSTERESIS_IDX].i64ptr;
|
||||
rrc->measurementConfiguration.a3_time_to_trigger = *MeasurementEventParamList.paramarray[0][MEASUREMENT_EVENTS_ENABLE_A3_TIME_TO_TRIGGER_IDX].i64ptr;
|
||||
}
|
||||
}
|
||||
|
||||
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
|
||||
|
||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
|
||||
@@ -229,6 +229,73 @@ typedef enum {
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* Neighbour Cell Configurations*/
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST "neighbour_cell_configuration"
|
||||
|
||||
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_GNB_ID "neighbour_gNB_ID"
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_NR_CELLID "neighbour_nr_cellid"
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID "neighbour_physical_cellId"
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB "neighbour_absoluteFrequencySSB"
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS "neighbour_subcarrierSpacing"
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_MOBILE_COUNTRY_CODE "neighbour_mcc"
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_MOBILE_NETWORK_CODE "neighbour_mnc"
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_MNC_DIGIT_LENGTH "neighbour_mnc_length"
|
||||
#define GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE "neighbour_tracking_area_code"
|
||||
|
||||
|
||||
|
||||
#define GNB_CONFIG_N_CELL_GNB_ID_IDX 0
|
||||
#define GNB_CONFIG_N_CELL_NR_CELLID_IDX 1
|
||||
#define GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX 2
|
||||
#define GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX 3
|
||||
#define GNB_CONFIG_N_CELL_SCS_IDX 4
|
||||
#define GNB_CONFIG_N_CELL_MCC_IDX 5
|
||||
#define GNB_CONFIG_N_CELL_MNC_IDX 6
|
||||
#define GNB_CONFIG_N_CELL_MNC_DIGIT_LENGTH_IDX 7
|
||||
#define GNB_CONFIG_N_CELL_TAC_IDX 8
|
||||
|
||||
#define GNBNEIGHBOURCELLPARAMS_DESC { \
|
||||
/* optname helpstr paramflags XXXptr def val type numelt */ \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_GNB_ID, NULL, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_NR_CELLID, NULL, 0, .u64ptr=NULL, .defint64val=1, TYPE_UINT64, 0}, \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID, "neighbour cell physical id", 0, .uptr=NULL, .defuintval=1000, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB, "neighbour cell abs freq ssb", 0, .i64ptr=NULL, .defint64val=621312, TYPE_INT64, 0}, \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS, "neighbour cell scs", 0, .uptr=NULL, .defuintval=1, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_MOBILE_COUNTRY_CODE, "mobile country code", 0, .uptr=NULL, .defuintval=1000, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_MOBILE_NETWORK_CODE, "mobile network code", 0, .uptr=NULL, .defuintval=1000, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_MNC_DIGIT_LENGTH, "length of the MNC (2 or 3)", 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
|
||||
{GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, NULL, 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
|
||||
}
|
||||
|
||||
/* Measurement Event Configurations*/
|
||||
#define GNB_CONFIG_STRING_MEASUREMENT_EVENTS "nr_measurement_event_configuration"
|
||||
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A2 "enableA2"
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A3 "enableA3"
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A2_THRESHOLD "thresholdA2"
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A2_TIME_TO_TRIGGER "A2_timeToTrigger"
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A3_OFFSET "A3_offset"
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A3_HYSTERESIS "A3_hysteresis"
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A3_TIME_TO_TRIGGER "A3_timeToTrigger"
|
||||
#define MEASUREMENT_EVENTS_GLOBALPARAMS_DESC { \
|
||||
{MEASUREMENT_EVENTS_ENABLE_A2, "enabling a2 event", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{MEASUREMENT_EVENTS_ENABLE_A3, "enabling a3 event", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{MEASUREMENT_EVENTS_ENABLE_A2_THRESHOLD, "a2 threshold", 0, .i64ptr=NULL, .defint64val=30, TYPE_INT64, 0}, \
|
||||
{MEASUREMENT_EVENTS_ENABLE_A2_TIME_TO_TRIGGER, "a2 time to trigger", 0, .i64ptr=NULL, .defint64val=1, TYPE_INT64, 0}, \
|
||||
{MEASUREMENT_EVENTS_ENABLE_A3_OFFSET, "a3 offset", 0, .i64ptr=NULL, .defint64val=10, TYPE_INT64, 0}, \
|
||||
{MEASUREMENT_EVENTS_ENABLE_A3_HYSTERESIS, "a3 hysteresis", 0, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0}, \
|
||||
{MEASUREMENT_EVENTS_ENABLE_A3_TIME_TO_TRIGGER, "a3 time to trigger", 0, .i64ptr=NULL, .defint64val=1, TYPE_INT64, 0}, \
|
||||
}
|
||||
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A2_IDX 0
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A3_IDX 1
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A2_THRESHOLD_IDX 2
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A2_TIME_TO_TRIGGER_IDX 3
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A3_OFFSET_IDX 4
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A3_HYSTERESIS_IDX 5
|
||||
#define MEASUREMENT_EVENTS_ENABLE_A3_TIME_TO_TRIGGER_IDX 6
|
||||
|
||||
/* PLMN ID configuration */
|
||||
|
||||
#define GNB_CONFIG_STRING_PLMN_LIST "plmn_list"
|
||||
|
||||
@@ -330,7 +330,8 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_fram
|
||||
const int lcid = sched_ctrl->dl_lc_ids[i];
|
||||
const uint16_t rnti = UE->rnti;
|
||||
LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid);
|
||||
if (lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
|
||||
if ((lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) ||
|
||||
(sched_ctrl->transmission_stop && sched_ctrl->rrc_processing_timer == 0)) {
|
||||
continue;
|
||||
}
|
||||
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
@@ -951,7 +952,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
* Possible improvement: take the periodicity from input file.
|
||||
* If such UE is not scheduled now, it will be by the preprocessor later.
|
||||
* If we add the CE, ta_apply will be reset */
|
||||
if (frame == (sched_ctrl->ta_frame + 10) % 1024) {
|
||||
if ((frame == (sched_ctrl->ta_frame + 10) % 1024) && (sched_ctrl->transmission_stop == false)) {
|
||||
sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
|
||||
LOG_D(NR_MAC, "[UE %04x][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE->rnti, frame, slot);
|
||||
}
|
||||
|
||||
@@ -2632,7 +2632,7 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo
|
||||
if (UE_info->sched_csirs & (1 << dl_bwp->bwp_id))
|
||||
continue;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
if (sched_ctrl->rrc_processing_timer > 0) {
|
||||
if ((sched_ctrl->rrc_processing_timer > 0) || sched_ctrl->transmission_stop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -528,7 +528,8 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot)
|
||||
sched_ctrl->sched_srs.srs_scheduled = false;
|
||||
}
|
||||
|
||||
if ((sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) || sched_ctrl->rrc_processing_timer > 0) {
|
||||
if ((sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) ||
|
||||
sched_ctrl->rrc_processing_timer > 0 || sched_ctrl->transmission_stop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,8 @@ void nr_csi_meas_reporting(int Mod_idP,
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
|
||||
if ((sched_ctrl->rrc_processing_timer > 0) || (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)) {
|
||||
if ((sched_ctrl->rrc_processing_timer > 0) || sched_ctrl->transmission_stop ||
|
||||
(sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)) {
|
||||
continue;
|
||||
}
|
||||
const NR_CSI_MeasConfig_t *csi_measconfig = UE->sc_info.csi_MeasConfig;
|
||||
@@ -1362,7 +1363,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
|
||||
if (sched_ctrl->ul_failure || sched_ctrl->rrc_processing_timer > 0)
|
||||
if (sched_ctrl->ul_failure || sched_ctrl->rrc_processing_timer > 0 || sched_ctrl->transmission_stop)
|
||||
continue;
|
||||
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
|
||||
|
||||
|
||||
@@ -1712,7 +1712,7 @@ static void pf_ul(module_id_t module_id,
|
||||
const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_pusch->frame, sched_pusch->slot, nrmac->ulsch_max_frame_inactivity);
|
||||
|
||||
LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n",UE->rnti,do_sched ? "yes" : "no");
|
||||
if ((B == 0 && !do_sched) || (sched_ctrl->rrc_processing_timer > 0)) {
|
||||
if ((B == 0 && !do_sched) || (sched_ctrl->rrc_processing_timer > 0) || sched_ctrl->transmission_stop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -465,6 +465,13 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
} else {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, new_CellGroup); // we actually don't need it
|
||||
}
|
||||
|
||||
if (req->transmission_action_indicator != NULL) {
|
||||
//TODO: After RLC Acknowledge comes for RRC Reconfiguration; then set this flag!
|
||||
// UE->UE_sched_ctrl.transmission_stop = *(req->transmission_action_indicator) ? false : true;
|
||||
LOG_I(NR_MAC, "HO LOG: Current Value of transmission indicator is %d\n", (int)UE->UE_sched_ctrl.transmission_stop);
|
||||
}
|
||||
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
|
||||
/* some sanity checks, since we use the same type for request and response */
|
||||
|
||||
@@ -645,6 +645,8 @@ typedef struct {
|
||||
|
||||
// Information about the QoS configuration for each LCID/DRB
|
||||
NR_QoS_config_t qos_config[NR_MAX_NUM_LCID - 4][NR_MAX_NUM_QFI]; // 0 -CCCH and 1- 3 SRBs(0,1,2)
|
||||
bool transmission_stop;
|
||||
|
||||
} NR_UE_sched_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
#include "NR_LogicalChannelConfig.h"
|
||||
#include "NR_PDCP-Config.h"
|
||||
#include "NR_MAC-CellGroupConfig.h"
|
||||
#include "NR_HandoverPreparationInformation.h"
|
||||
#include "NR_HandoverCommand.h"
|
||||
#include "NR_HandoverCommand-IEs.h"
|
||||
#include "NR_AS-Config.h"
|
||||
#include "NR_SecurityModeCommand.h"
|
||||
#include "NR_CipheringAlgorithm.h"
|
||||
#include "NR_RRCReconfiguration-IEs.h"
|
||||
@@ -662,6 +666,131 @@ int do_NR_RRCRelease(uint8_t *buffer, size_t buffer_size, uint8_t Transaction_id
|
||||
return((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size,
|
||||
uint8_t Transaction_id,
|
||||
NR_SRB_ToAddModList_t *SRB_configList,
|
||||
NR_DRB_ToAddModList_t *DRB_configList,
|
||||
NR_DRB_ToReleaseList_t *DRB_releaseList,
|
||||
NR_SecurityConfig_t *security_config,
|
||||
NR_MeasConfig_t *meas_config,
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
asn_enc_rval_t enc_rval;
|
||||
NR_RRCReconfiguration_IEs_t *ie;
|
||||
|
||||
NR_RRCReconfiguration_t* rrcReconf = (NR_RRCReconfiguration_t*)calloc(1, sizeof(NR_RRCReconfiguration_t));
|
||||
rrcReconf->rrc_TransactionIdentifier = Transaction_id;
|
||||
rrcReconf->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration;
|
||||
|
||||
ie = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t));
|
||||
if ((SRB_configList && SRB_configList->list.size) ||
|
||||
(DRB_configList && DRB_configList->list.size)) {
|
||||
ie->radioBearerConfig = calloc(1, sizeof(NR_RadioBearerConfig_t));
|
||||
ie->radioBearerConfig->srb_ToAddModList = SRB_configList;
|
||||
ie->radioBearerConfig->drb_ToAddModList = DRB_configList;
|
||||
ie->radioBearerConfig->securityConfig = security_config;
|
||||
ie->radioBearerConfig->srb3_ToRelease = NULL;
|
||||
ie->radioBearerConfig->drb_ToReleaseList = DRB_releaseList;
|
||||
}
|
||||
|
||||
/******************** Meas Config ********************/
|
||||
// measConfig
|
||||
ie->measConfig = meas_config;
|
||||
// lateNonCriticalExtension
|
||||
ie->lateNonCriticalExtension = NULL;
|
||||
// nonCriticalExtension
|
||||
|
||||
if (cellGroupConfig) {
|
||||
ie->nonCriticalExtension = calloc(1, sizeof(NR_RRCReconfiguration_v1530_IEs_t));
|
||||
}
|
||||
|
||||
if (cellGroupConfig != NULL) {
|
||||
uint8_t *buf = NULL;
|
||||
ssize_t len = uper_encode_to_new_buffer(&asn_DEF_NR_CellGroupConfig, NULL, cellGroupConfig, (void **)&buf);
|
||||
AssertFatal(len > 0, "ASN1 message encoding failed (%lu)!\n", len);
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig);
|
||||
}
|
||||
ie->nonCriticalExtension->masterCellGroup = calloc(1,sizeof(OCTET_STRING_t));
|
||||
ie->nonCriticalExtension->masterCellGroup->buf = buf;
|
||||
ie->nonCriticalExtension->masterCellGroup->size = len;
|
||||
}
|
||||
|
||||
rrcReconf->criticalExtensions.choice.rrcReconfiguration = ie;
|
||||
|
||||
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RRCReconfiguration,
|
||||
NULL,
|
||||
(void *)rrcReconf,
|
||||
buffer,
|
||||
buffer_size);
|
||||
|
||||
AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
// don't free what we did not allocate, so set fields with pointers to NULL
|
||||
// if memory comes from outside
|
||||
ie->measConfig = NULL;
|
||||
if (ie->radioBearerConfig) {
|
||||
ie->radioBearerConfig->srb_ToAddModList = NULL;
|
||||
ie->radioBearerConfig->drb_ToAddModList = NULL;
|
||||
ie->radioBearerConfig->securityConfig = NULL;
|
||||
ie->radioBearerConfig->srb3_ToRelease = NULL;
|
||||
ie->radioBearerConfig->drb_ToReleaseList = NULL;
|
||||
}
|
||||
if (ie->nonCriticalExtension)
|
||||
ie->nonCriticalExtension->dedicatedNAS_MessageList = NULL;
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_RRCReconfiguration, rrcReconf);
|
||||
LOG_D(NR_RRC,
|
||||
"RRCReconfiguration for UE %d: Encoded %zd bits (%zd bytes)\n",
|
||||
UE->rrc_ue_id,
|
||||
enc_rval.encoded,
|
||||
(enc_rval.encoded + 7) / 8);
|
||||
|
||||
return((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
int16_t prepare_DL_DCCH_for_HO_Command(const gNB_RRC_UE_t *UE,
|
||||
uint8_t** hoCommand,
|
||||
size_t hoCommandLength,
|
||||
uint8_t* buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
NR_DL_DCCH_Message_t dl_dcch_msg={0};
|
||||
asn_enc_rval_t enc_rval;
|
||||
dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1;
|
||||
asn1cCalloc(dl_dcch_msg.message.choice.c1, c1);// = CALLOC(1, sizeof(struct NR_DL_DCCH_MessageType__c1));
|
||||
c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
|
||||
asn1cCalloc(c1->choice.rrcReconfiguration, rrcReconf);
|
||||
|
||||
uper_decode_complete(NULL, &asn_DEF_NR_RRCReconfiguration, (void **)&rrcReconf, (const void*)*hoCommand, hoCommandLength);
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
|
||||
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message,
|
||||
NULL,
|
||||
(void *)&dl_dcch_msg,
|
||||
buffer,
|
||||
buffer_size);
|
||||
|
||||
AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_DL_DCCH_Message, &dl_dcch_msg);
|
||||
LOG_D(NR_RRC,
|
||||
"RRCReconfiguration for UE %d: Encoded %zd bits (%zd bytes)\n",
|
||||
UE->rrc_ue_id,
|
||||
enc_rval.encoded,
|
||||
(enc_rval.encoded + 7) / 8);
|
||||
|
||||
return((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int16_t do_RRCReconfiguration(const gNB_RRC_UE_t *UE,
|
||||
uint8_t *buffer,
|
||||
@@ -1183,6 +1312,205 @@ NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs)
|
||||
return mc;
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
int reconfigSize = do_HO_RRCReconfiguration(ue_p,
|
||||
rrc_reconfiguration_buffer,
|
||||
RRC_BUF_SIZE,
|
||||
0,
|
||||
SRBs,
|
||||
DRBs,
|
||||
NULL,
|
||||
NULL,
|
||||
ue_p->measConfig,
|
||||
NULL,
|
||||
ue_p->masterCellGroup);
|
||||
|
||||
|
||||
NR_HandoverPreparationInformation_t HoPrepInfo={0};
|
||||
NR_HandoverPreparationInformation_IEs_t *ie;
|
||||
asn_enc_rval_t enc_rval;
|
||||
|
||||
HoPrepInfo.criticalExtensions.present = NR_HandoverPreparationInformation__criticalExtensions_PR_c1;
|
||||
asn1cCalloc(HoPrepInfo.criticalExtensions.choice.c1, c1);
|
||||
c1->present = NR_HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation;
|
||||
|
||||
ie = calloc(1, sizeof(NR_HandoverPreparationInformation_IEs_t));
|
||||
|
||||
asn1cSequenceAdd(ie->ue_CapabilityRAT_List.list, NR_UE_CapabilityRAT_Container_t, nrContainer);
|
||||
nrContainer->rat_Type = 0; //NR
|
||||
|
||||
nrContainer->ue_CapabilityRAT_Container.size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, (void *)ue_p->UE_Capability_nr, (void **)&nrContainer->ue_CapabilityRAT_Container.buf);
|
||||
|
||||
asn1cCalloc(ie->sourceConfig, sourceConfig);
|
||||
OCTET_STRING_fromBuf(&sourceConfig->rrcReconfiguration,
|
||||
(const char *)rrc_reconfiguration_buffer, reconfigSize);
|
||||
|
||||
HoPrepInfo.criticalExtensions.choice.c1->choice.handoverPreparationInformation = ie;
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NR_HandoverPreparationInformation, (void *)&HoPrepInfo);
|
||||
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_HandoverPreparationInformation,
|
||||
NULL,
|
||||
(void *)&HoPrepInfo,
|
||||
(*buffer),
|
||||
buffer_size);
|
||||
|
||||
AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_HandoverPreparationInformation, &HoPrepInfo);
|
||||
LOG_D(NR_RRC,"HO LOG: Handover Preparation for UE %lu Encoded %zd bits (%zd bytes)\n",
|
||||
ue_p->amf_ue_ngap_id,
|
||||
enc_rval.encoded,
|
||||
(enc_rval.encoded+7)/8);
|
||||
|
||||
return((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
NR_MeasConfig_t *get_EventBasedMeasConfig(uint32_t ssb_arfcn, int band, int scs, const nr_measurement_event_configuration_t* measurementConfiguration, nr_neighbour_gnb_configuration_t* neighbourConfiguration, const int numberOfNeighbours){
|
||||
|
||||
bool intraFrequencyNeighbourExists = false;
|
||||
LOG_D(NR_RRC, "HO LOG: Supports only Intra Frequency Meas with SCS:%d ABS ARFCN: %d\n", scs, ssb_arfcn);
|
||||
for (uint8_t nCell = 0; nCell < numberOfNeighbours; nCell++){
|
||||
nr_neighbour_gnb_configuration_t* neighbourCell = &neighbourConfiguration[nCell];
|
||||
if (ssb_arfcn == neighbourCell->absoluteFrequencySSB && scs == neighbourCell->subcarrierSpacing) {
|
||||
LOG_D(NR_RRC, "HO LOG: Intra Frequency Neighbour is Found!\n");
|
||||
intraFrequencyNeighbourExists = true;
|
||||
neighbourCell->intraFrequencyNeighbour = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!intraFrequencyNeighbourExists){
|
||||
LOG_E(NR_RRC, "HO LOG: Currently Inter Frequency Measurements are not supported!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NR_MeasConfig_t *mc = calloc(1, sizeof(*mc));
|
||||
mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList));
|
||||
mc->reportConfigToAddModList = calloc(1, sizeof(*mc->reportConfigToAddModList));
|
||||
|
||||
//A3 Configuration
|
||||
NR_MeasObjectToAddMod_t *mo1 = calloc(1, sizeof(*mo1));
|
||||
mo1->measObjectId = 1;
|
||||
mo1->measObject.present = NR_MeasObjectToAddMod__measObject_PR_measObjectNR;
|
||||
NR_MeasObjectNR_t *monr1 = calloc(1, sizeof(*monr1));
|
||||
asn1cCallocOne(monr1->ssbFrequency, ssb_arfcn);
|
||||
asn1cCallocOne(monr1->ssbSubcarrierSpacing, scs);
|
||||
monr1->referenceSignalConfig.ssb_ConfigMobility = calloc(1, sizeof(*monr1->referenceSignalConfig.ssb_ConfigMobility));
|
||||
monr1->referenceSignalConfig.ssb_ConfigMobility->deriveSSB_IndexFromCell = true;
|
||||
monr1->absThreshSS_BlocksConsolidation = calloc(1, sizeof(*monr1->absThreshSS_BlocksConsolidation));
|
||||
asn1cCallocOne(monr1->absThreshSS_BlocksConsolidation->thresholdRSRP, 36);
|
||||
asn1cCallocOne(monr1->nrofSS_BlocksToAverage, 8);
|
||||
monr1->smtc1 = calloc(1, sizeof(*monr1->smtc1));
|
||||
monr1->smtc1->periodicityAndOffset.present = NR_SSB_MTC__periodicityAndOffset_PR_sf20;
|
||||
monr1->smtc1->periodicityAndOffset.choice.sf20 = 2;
|
||||
monr1->smtc1->duration = NR_SSB_MTC__duration_sf2;
|
||||
monr1->quantityConfigIndex = 1;
|
||||
monr1->ext1 = calloc(1, sizeof(*monr1->ext1));
|
||||
asn1cCallocOne(monr1->ext1->freqBandIndicatorNR, band);
|
||||
|
||||
|
||||
for (uint8_t nCell = 0; nCell < numberOfNeighbours; nCell++){
|
||||
const nr_neighbour_gnb_configuration_t* neighbourCell = &neighbourConfiguration[nCell];
|
||||
if (!neighbourCell->intraFrequencyNeighbour)
|
||||
continue;
|
||||
|
||||
LOG_D(NR_RRC, "HO LOG: Preparing Meas Config for neighbour Cell with the ID: %d\n", neighbourCell->physicalCellId);
|
||||
if (monr1->cellsToAddModList == NULL) {
|
||||
monr1->cellsToAddModList = calloc(1, sizeof(*monr1->cellsToAddModList));
|
||||
}
|
||||
|
||||
NR_CellsToAddMod_t *cell = calloc(1, sizeof(*cell));
|
||||
cell->physCellId = neighbourCell->physicalCellId;
|
||||
ASN_SEQUENCE_ADD(&monr1->cellsToAddModList->list, cell);
|
||||
}
|
||||
const int numIntraFreqNeighbours = monr1->cellsToAddModList->list.count;
|
||||
mo1->measObject.choice.measObjectNR = monr1;
|
||||
asn1cSeqAdd(&mc->measObjectToAddModList->list, mo1);
|
||||
|
||||
NR_ReportConfigToAddMod_t *rc_A3 = calloc(1, sizeof(*rc_A3));
|
||||
rc_A3->reportConfigId = 1;
|
||||
rc_A3->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
|
||||
NR_EventTriggerConfig_t *etrc_A3 = calloc(1, sizeof(*etrc_A3));
|
||||
etrc_A3->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA3;
|
||||
etrc_A3->eventId.choice.eventA3 = calloc(1, sizeof(*etrc_A3->eventId.choice.eventA3));
|
||||
etrc_A3->eventId.choice.eventA3->a3_Offset.present = NR_MeasTriggerQuantityOffset_PR_rsrp;
|
||||
etrc_A3->eventId.choice.eventA3->a3_Offset.choice.rsrp = measurementConfiguration->a3_offset;
|
||||
etrc_A3->eventId.choice.eventA3->reportOnLeave = true;
|
||||
etrc_A3->eventId.choice.eventA3->hysteresis = measurementConfiguration->a3_hysteresis;
|
||||
etrc_A3->eventId.choice.eventA3->timeToTrigger = measurementConfiguration->a3_time_to_trigger;
|
||||
etrc_A3->rsType = NR_NR_RS_Type_ssb;
|
||||
etrc_A3->reportInterval = NR_ReportInterval_ms1024;
|
||||
etrc_A3->reportAmount = NR_EventTriggerConfig__reportAmount_r4;
|
||||
etrc_A3->reportQuantityCell.rsrp = true;
|
||||
etrc_A3->reportQuantityCell.rsrq = false;
|
||||
etrc_A3->reportQuantityCell.sinr = true;
|
||||
asn1cCallocOne(etrc_A3->maxNrofRS_IndexesToReport, 4);
|
||||
etrc_A3->maxReportCells = numIntraFreqNeighbours;
|
||||
etrc_A3->includeBeamMeasurements = false;
|
||||
NR_ReportConfigNR_t *rcnr_A3 = calloc(1, sizeof(*rcnr_A3));
|
||||
rcnr_A3->reportType.present = NR_ReportConfigNR__reportType_PR_eventTriggered;
|
||||
rcnr_A3->reportType.choice.eventTriggered = etrc_A3;
|
||||
rc_A3->reportConfig.choice.reportConfigNR = rcnr_A3;
|
||||
asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A3);
|
||||
|
||||
mc->measIdToAddModList = calloc(1, sizeof(*mc->measIdToAddModList));
|
||||
NR_MeasIdToAddMod_t *measid_A3 = calloc(1, sizeof(*measid_A3));
|
||||
measid_A3->measId = 1;
|
||||
measid_A3->measObjectId = 1;
|
||||
measid_A3->reportConfigId = 1;
|
||||
asn1cSeqAdd(&mc->measIdToAddModList->list, measid_A3);
|
||||
|
||||
|
||||
// A2 Report Configuration
|
||||
if (measurementConfiguration->enableA2) {
|
||||
LOG_D(NR_RRC, "HO LOG: Preparing A2 Event Measurement Configuration!\n");
|
||||
NR_ReportConfigToAddMod_t *rc_A2 = calloc(1, sizeof(*rc_A2));
|
||||
rc_A2->reportConfigId = 2;
|
||||
rc_A2->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
|
||||
NR_EventTriggerConfig_t *etrc_A2 = calloc(1, sizeof(*etrc_A2));
|
||||
etrc_A2->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA2;
|
||||
etrc_A2->eventId.choice.eventA2 = calloc(1, sizeof(*etrc_A2->eventId.choice.eventA2));
|
||||
etrc_A2->eventId.choice.eventA2->a2_Threshold.present = NR_MeasTriggerQuantity_PR_rsrp;
|
||||
etrc_A2->eventId.choice.eventA2->a2_Threshold.choice.rsrp = measurementConfiguration->a2_threshold;
|
||||
etrc_A2->eventId.choice.eventA2->reportOnLeave = false;
|
||||
etrc_A2->eventId.choice.eventA2->hysteresis = 0;
|
||||
etrc_A2->eventId.choice.eventA2->timeToTrigger = measurementConfiguration->a2_time_to_trigger;
|
||||
etrc_A2->rsType = NR_NR_RS_Type_ssb;
|
||||
etrc_A2->reportInterval = NR_ReportInterval_ms1024;
|
||||
etrc_A2->reportAmount = NR_EventTriggerConfig__reportAmount_r4;
|
||||
etrc_A2->reportQuantityCell.rsrp = true;
|
||||
etrc_A2->reportQuantityCell.rsrq = false;
|
||||
etrc_A2->reportQuantityCell.sinr = false;
|
||||
asn1cCallocOne(etrc_A2->maxNrofRS_IndexesToReport, 4);
|
||||
etrc_A2->maxReportCells = 1;
|
||||
etrc_A2->includeBeamMeasurements = false;
|
||||
NR_ReportConfigNR_t *rcnr_A2 = calloc(1, sizeof(*rcnr_A2));
|
||||
rcnr_A2->reportType.present = NR_ReportConfigNR__reportType_PR_eventTriggered;
|
||||
rcnr_A2->reportType.choice.eventTriggered = etrc_A2;
|
||||
rc_A2->reportConfig.choice.reportConfigNR = rcnr_A2;
|
||||
asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A2);
|
||||
|
||||
|
||||
NR_MeasIdToAddMod_t *measid_A2 = calloc(1, sizeof(*measid_A2));
|
||||
measid_A2->measId = 2;
|
||||
measid_A2->measObjectId = 1;
|
||||
measid_A2->reportConfigId = 2;
|
||||
asn1cSeqAdd(&mc->measIdToAddModList->list, measid_A2);
|
||||
|
||||
}
|
||||
mc->quantityConfig = calloc(1, sizeof(*mc->quantityConfig));
|
||||
mc->quantityConfig->quantityConfigNR_List = calloc(1, sizeof(*mc->quantityConfig->quantityConfigNR_List));
|
||||
NR_QuantityConfigNR_t *qcnr3 = calloc(1, sizeof(*qcnr3));
|
||||
asn1cCallocOne(qcnr3->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6);
|
||||
asn1cCallocOne(qcnr3->quantityConfigCell.csi_RS_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6);
|
||||
asn1cSeqAdd(&mc->quantityConfig->quantityConfigNR_List->list, qcnr3);
|
||||
|
||||
return mc;
|
||||
}
|
||||
|
||||
void free_defaultMeasConfig(NR_MeasConfig_t *mc)
|
||||
{
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, mc);
|
||||
|
||||
@@ -140,9 +140,28 @@ int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
uint16_t pci,
|
||||
NR_ARFCN_ValueNR_t absoluteFrequencySSB);
|
||||
|
||||
int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier);
|
||||
int16_t do_HO_RRCReconfiguration(const gNB_RRC_UE_t *UE,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size,
|
||||
uint8_t Transaction_id,
|
||||
NR_SRB_ToAddModList_t *SRB_configList,
|
||||
NR_DRB_ToAddModList_t *DRB_configList,
|
||||
NR_DRB_ToReleaseList_t *DRB_releaseList,
|
||||
NR_SecurityConfig_t *security_config,
|
||||
NR_MeasConfig_t *meas_config,
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList,
|
||||
NR_CellGroupConfig_t *cellGroupConfig);
|
||||
|
||||
int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier);
|
||||
struct NR_HandoverPreparationInformation; //forward declare
|
||||
NR_MeasConfig_t *get_defaultMeasConfig(uint32_t absFreqSSB, int band, int scs);
|
||||
NR_MeasConfig_t *get_EventBasedMeasConfig(uint32_t ssb_arfcn, int band, int scs, const nr_measurement_event_configuration_t* measurementConfiguration, nr_neighbour_gnb_configuration_t* neighbourConfiguration, const int numberOfNeighbours);
|
||||
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 prepare_DL_DCCH_for_HO_Command(const gNB_RRC_UE_t *UE,
|
||||
uint8_t** hoCommand,
|
||||
size_t hoCommandLength,
|
||||
uint8_t* buffer,
|
||||
size_t buffer_size);
|
||||
void free_defaultMeasConfig(NR_MeasConfig_t *mc);
|
||||
uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef enum UE_STATE_NR_e {
|
||||
NR_RRC_SI_RECEIVED,
|
||||
NR_RRC_CONNECTED,
|
||||
NR_RRC_RECONFIGURED,
|
||||
NR_RRC_HO_PREPARATION,
|
||||
NR_RRC_HO_EXECUTION
|
||||
} NR_UE_STATE_t;
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
#define NR_UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!!
|
||||
#define NR_UE_INDEX_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! used to be -1
|
||||
|
||||
#define MAX_NUMBER_OF_NEIGHBOUR_GNBS 6
|
||||
|
||||
typedef enum {
|
||||
NR_RRC_OK=0,
|
||||
NR_RRC_ConnSetup_failed,
|
||||
@@ -343,6 +345,30 @@ typedef struct {
|
||||
int do_drb_integrity;
|
||||
} nr_security_configuration_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t neighbour_gNB_ID;
|
||||
uint64_t neighbour_nrcell_id;
|
||||
int physicalCellId;
|
||||
int absoluteFrequencySSB;
|
||||
int subcarrierSpacing;
|
||||
uint16_t neighbour_mcc;
|
||||
uint16_t neighbour_mnc;
|
||||
uint8_t neighbour_mnc_digit_length;
|
||||
uint32_t neighbour_tac;
|
||||
bool intraFrequencyNeighbour;
|
||||
} nr_neighbour_gnb_configuration_t;
|
||||
|
||||
typedef struct {
|
||||
int enableA2;
|
||||
int enableA3;
|
||||
int a2_threshold;
|
||||
int a2_time_to_trigger;
|
||||
int a3_offset;
|
||||
int a3_hysteresis;
|
||||
int a3_time_to_trigger;
|
||||
} nr_measurement_event_configuration_t;
|
||||
|
||||
typedef struct nr_mac_rrc_dl_if_s {
|
||||
f1_setup_response_func_t f1_setup_response;
|
||||
f1_setup_failure_func_t f1_setup_failure;
|
||||
@@ -405,6 +431,9 @@ typedef struct gNB_RRC_INST_s {
|
||||
|
||||
nr_mac_rrc_dl_if_t mac_rrc;
|
||||
cucp_cuup_if_t cucp_cuup;
|
||||
nr_neighbour_gnb_configuration_t neighbourConfiguration[MAX_NUMBER_OF_NEIGHBOUR_GNBS];
|
||||
nr_measurement_event_configuration_t measurementConfiguration;
|
||||
uint8_t number_of_neighbours;
|
||||
|
||||
RB_HEAD(rrc_du_tree, nr_rrc_du_container_t) dus; // DUs, indexed by assoc_id
|
||||
size_t num_dus;
|
||||
|
||||
@@ -58,11 +58,14 @@
|
||||
#include "NR_RRCSetup.h"
|
||||
|
||||
#include "NR_CellGroupConfig.h"
|
||||
#include "NR_MeasResultListNR.h"
|
||||
#include "NR_MeasResults.h"
|
||||
#include "NR_UL-CCCH-Message.h"
|
||||
#include "NR_RRCSetupRequest-IEs.h"
|
||||
#include "NR_RRCSetupComplete-IEs.h"
|
||||
#include "NR_RRCReestablishmentRequest-IEs.h"
|
||||
#include "NR_HandoverCommand.h"
|
||||
#include "NR_HandoverCommand-IEs.h"
|
||||
#include "NR_MIB.h"
|
||||
#include "uper_encoder.h"
|
||||
#include "uper_decoder.h"
|
||||
@@ -110,6 +113,21 @@
|
||||
|
||||
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)
|
||||
{
|
||||
const gNB_RRC_INST* rrc = RC.nrrrc[0];
|
||||
for (uint8_t neighbourId = 0; neighbourId < rrc->number_of_neighbours; ++neighbourId)
|
||||
{
|
||||
const nr_neighbour_gnb_configuration_t* configuration = &(rrc->neighbourConfiguration[neighbourId]);
|
||||
if (configuration->physicalCellId == phyCellId)
|
||||
return configuration;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mui_t rrc_gNB_mui = 0;
|
||||
|
||||
// the assoc_id might be 0 (if the DU goes offline). Below helper macro to
|
||||
@@ -510,6 +528,16 @@ static void rrc_gNB_process_RRCSetupComplete(const protocol_ctxt_t *const ctxt_p
|
||||
#endif
|
||||
}
|
||||
|
||||
static void clone_MeasConfig(const NR_MeasConfig_t *orig, rrc_gNB_ue_context_t *ue_context_pP)
|
||||
{
|
||||
uint8_t buf[16636];
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MeasConfig, NULL, orig, buf, sizeof(buf));
|
||||
AssertFatal(enc_rval.encoded > 0, "could not clone Meas Config: problem while encoding\n");
|
||||
asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_MeasConfig, (void **)&ue_context_pP->ue_context.measConfig, buf, enc_rval.encoded, 0, 0);
|
||||
AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded,
|
||||
"could not clone NR_MeasConfig_t: problem while decodung\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -555,11 +583,26 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co
|
||||
/* we cannot calculate the default measurement config without MIB&SIB1, as
|
||||
* we don't know the DU's SSB ARFCN */
|
||||
uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1);
|
||||
measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ue_p->measConfig != NULL) {
|
||||
free(ue_p->measConfig);
|
||||
ue_p->measConfig = NULL;
|
||||
}
|
||||
|
||||
if (measconfig != NULL)
|
||||
clone_MeasConfig(measconfig, ue_context_pP);
|
||||
|
||||
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false);
|
||||
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false);
|
||||
|
||||
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
int size = do_RRCReconfiguration(ue_p,
|
||||
buffer,
|
||||
@@ -683,7 +726,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
|
||||
rrc_gNB_mui,
|
||||
ctxt_pP->module_id,
|
||||
DCCH);
|
||||
|
||||
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size);
|
||||
}
|
||||
|
||||
@@ -883,6 +926,83 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size);
|
||||
}
|
||||
|
||||
typedef struct deliver_ue_ctxt_modification_data_t {
|
||||
gNB_RRC_INST *rrc;
|
||||
f1ap_ue_context_modif_req_t *modification_req;
|
||||
sctp_assoc_t assoc_id;
|
||||
} deliver_ue_ctxt_modification_data_t;
|
||||
static void rrc_deliver_ue_ctxt_modif_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
|
||||
{
|
||||
DevAssert(deliver_pdu_data != NULL);
|
||||
deliver_ue_ctxt_modification_data_t *data = deliver_pdu_data;
|
||||
data->modification_req->rrc_container = (uint8_t*)buf;
|
||||
data->modification_req->rrc_container_length = size;
|
||||
data->rrc->mac_rrc.ue_context_modification_request(data->assoc_id, data->modification_req);
|
||||
}
|
||||
|
||||
static void rrc_gNB_process_HandoverCommand(MessageDef* msg_p, instance_t instance)
|
||||
{
|
||||
LOG_E(NR_RRC, "Handover Command has came to the source gNB RRC!\n");
|
||||
uint32_t gNB_ue_ngap_id = 0;
|
||||
ngap_handover_command_t* handover_command_msg = &NGAP_HANDOVER_COMMAND(msg_p);
|
||||
gNB_ue_ngap_id = handover_command_msg->gNB_ue_ngap_id;
|
||||
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[instance];
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, gNB_ue_ngap_id);
|
||||
|
||||
|
||||
if (ue_context_p == NULL) {
|
||||
/* Can not associate this message to an UE index */
|
||||
LOG_W(NR_RRC, "[gNB %ld] In HANDOVER_COMMAND: unknown UE from gNB_ue_ngap_id (%u)\n",
|
||||
instance,
|
||||
gNB_ue_ngap_id);
|
||||
return;
|
||||
}
|
||||
const gNB_RRC_UE_t* UE = &ue_context_p->ue_context;
|
||||
|
||||
if (UE->StatusRrc != NR_RRC_HO_PREPARATION)
|
||||
{
|
||||
LOG_E(NR_RRC, "HO LOG: UE is not in HO Status!\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
NR_HandoverCommand_t* hoCommand = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
|
||||
&asn_DEF_NR_HandoverCommand,
|
||||
(void **)&hoCommand,
|
||||
(uint8_t *)handover_command_msg->handoverCommand.buffer,
|
||||
handover_command_msg->handoverCommand.length);
|
||||
if (dec_rval.code != RC_OK && dec_rval.consumed == 0) {
|
||||
LOG_E(NR_RRC, "Can not decode Handover Command!\n");
|
||||
return;
|
||||
}
|
||||
ue_context_p->ue_context.StatusRrc = NR_RRC_HO_EXECUTION;
|
||||
uint8_t* buffer = (uint8_t*)calloc(1, RRC_BUF_SIZE);
|
||||
int encoded_size = prepare_DL_DCCH_for_HO_Command(&ue_context_p->ue_context, &(hoCommand->criticalExtensions.choice.c1->choice.handoverCommand->handoverCommandMessage.buf),
|
||||
hoCommand->criticalExtensions.choice.c1->choice.handoverCommand->handoverCommandMessage.size, buffer, RRC_BUF_SIZE);
|
||||
DevAssert(encoded_size > 0);
|
||||
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_context_p->ue_context.rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
f1ap_ue_context_modif_req_t ue_context_modif_req = {
|
||||
.gNB_CU_ue_id = UE->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.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,
|
||||
};
|
||||
|
||||
ue_context_modif_req.transmission_action_indicator = (uint8_t*)malloc(sizeof(uint8_t));
|
||||
*ue_context_modif_req.transmission_action_indicator = 0;
|
||||
|
||||
deliver_ue_ctxt_modification_data_t data = {.rrc = rrc, .modification_req = &ue_context_modif_req, .assoc_id = ue_data.du_assoc_id };
|
||||
nr_pdcp_data_req_srb(UE->rrc_ue_id, DCCH, rrc_gNB_mui++, encoded_size, buffer, rrc_deliver_ue_ctxt_modif_req, &data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context_pP,
|
||||
const uint8_t *masterCellGroup_from_DU,
|
||||
@@ -1204,22 +1324,149 @@ fallback_rrc_setup:
|
||||
|
||||
static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context, NR_MeasurementReport_t *measurementReport)
|
||||
{
|
||||
LOG_D(NR_RRC, "Process Measurement Report\n");
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NR_MeasurementReport, (void *)measurementReport);
|
||||
|
||||
|
||||
DevAssert(measurementReport->criticalExtensions.present == NR_MeasurementReport__criticalExtensions_PR_measurementReport
|
||||
&& measurementReport->criticalExtensions.choice.measurementReport != NULL);
|
||||
|
||||
gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context;
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, ue_ctxt->measResults);
|
||||
ue_ctxt->measResults = NULL;
|
||||
gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context;
|
||||
NR_MeasConfig_t *meas_config = ue_ctxt->measConfig;
|
||||
if (meas_config == NULL) {
|
||||
LOG_E(NR_RRC, "%s: %i - meas_config = %p\n", __FUNCTION__, __LINE__, meas_config);
|
||||
return;
|
||||
}
|
||||
|
||||
const NR_MeasId_t id = measurementReport->criticalExtensions.choice.measurementReport->measResults.measId;
|
||||
AssertFatal(id, "unexpected MeasResult for MeasurementId %ld received\n", id);
|
||||
asn1cCallocOne(ue_ctxt->measResults, measurementReport->criticalExtensions.choice.measurementReport->measResults);
|
||||
/* we "keep" the measurement report, so set to 0 */
|
||||
free(measurementReport->criticalExtensions.choice.measurementReport);
|
||||
measurementReport->criticalExtensions.choice.measurementReport = NULL;
|
||||
NR_MeasurementReport_IEs_t *measurementReport_IEs = measurementReport->criticalExtensions.choice.measurementReport;
|
||||
const NR_MeasId_t measId = measurementReport_IEs->measResults.measId;
|
||||
|
||||
NR_MeasIdToAddMod_t *meas_id_s = NULL;
|
||||
for (int meas_idx = 0; meas_idx < meas_config->measIdToAddModList->list.count; meas_idx++) {
|
||||
if (measId == meas_config->measIdToAddModList->list.array[meas_idx]->measId) {
|
||||
meas_id_s = meas_config->measIdToAddModList->list.array[meas_idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (meas_id_s == NULL){
|
||||
LOG_E(NR_RRC, "Incoming Meas ID with id: %d Can not Found!\n", (int)measId);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_D(NR_RRC, "HO LOG: Meas Id is found: %d\n", (int)meas_id_s->measId);
|
||||
|
||||
struct NR_ReportConfigToAddMod__reportConfig *report_config = NULL;
|
||||
for (int rep_id = 0; rep_id < meas_config->reportConfigToAddModList->list.count; rep_id++) {
|
||||
if (meas_id_s->reportConfigId == meas_config->reportConfigToAddModList->list.array[rep_id]->reportConfigId) {
|
||||
report_config = &meas_config->reportConfigToAddModList->list.array[rep_id]->reportConfig;
|
||||
}
|
||||
}
|
||||
|
||||
if (report_config == NULL) {
|
||||
LOG_E(NR_RRC, "There is no related report configuration for this measId!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (report_config->choice.reportConfigNR->reportType.present == NR_ReportConfigNR__reportType_PR_periodical){
|
||||
LOG_I(NR_RRC, "Periodical Event Report! Do Nothing for now...\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, ue_ctxt->measResults);
|
||||
ue_ctxt->measResults = NULL;
|
||||
|
||||
const NR_MeasId_t id = measurementReport->criticalExtensions.choice.measurementReport->measResults.measId;
|
||||
AssertFatal(id, "unexpected MeasResult for MeasurementId %ld received\n", id);
|
||||
asn1cCallocOne(ue_ctxt->measResults, measurementReport->criticalExtensions.choice.measurementReport->measResults);
|
||||
/* we "keep" the measurement report, so set to 0 */
|
||||
free(measurementReport->criticalExtensions.choice.measurementReport);
|
||||
measurementReport->criticalExtensions.choice.measurementReport = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (report_config->choice.reportConfigNR->reportType.present != NR_ReportConfigNR__reportType_PR_eventTriggered){
|
||||
LOG_D(NR_RRC, "Incoming Report Type: %d is not supported! \n", report_config->choice.reportConfigNR->reportType.present);
|
||||
return;
|
||||
}
|
||||
|
||||
NR_EventTriggerConfig_t *event_triggered = report_config->choice.reportConfigNR->reportType.choice.eventTriggered;
|
||||
LOG_I(NR_RRC, "HO LOG: Incoming Report Id: %d\n", (int)measId);
|
||||
|
||||
|
||||
int servingCellRSRP = 0;
|
||||
int neighbourCellRSRP = 0;
|
||||
bool trigger_ho = false;
|
||||
int bestRsrp = -10000;
|
||||
int bestNeighbourId = -1;
|
||||
const int handoverMargin = 0; //This is an optimization parameter for HO like hysteresis. 0 for now.
|
||||
|
||||
switch (event_triggered->eventId.present) {
|
||||
case NR_EventTriggerConfig__eventId_PR_eventA2:
|
||||
LOG_I(NR_RRC, "\nHO LOG: Event A2 (Serving becomes worse than threshold)\n");
|
||||
break;
|
||||
|
||||
case NR_EventTriggerConfig__eventId_PR_eventA3:
|
||||
{
|
||||
LOG_I(NR_RRC, "\nHO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n");
|
||||
for (int serving_cell_idx = 0; serving_cell_idx < measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultServingMOList.list.count; serving_cell_idx++) {
|
||||
const NR_MeasResultServMO_t* meas_result_serv_MO = measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultServingMOList.list.array[serving_cell_idx];
|
||||
|
||||
if (meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell) {
|
||||
servingCellRSRP = *(meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell->rsrp) - 157;
|
||||
} else {
|
||||
servingCellRSRP = *(meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsCSI_RS_Cell->rsrp) - 157;
|
||||
}
|
||||
LOG_D(NR_RRC, "Serving Cell RSRP: %d\n", servingCellRSRP);
|
||||
}
|
||||
//Only Meas Result NR is supported at the moment
|
||||
if (measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultNeighCells == NULL)
|
||||
break;
|
||||
|
||||
if (measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultNeighCells->present != NR_MeasResults__measResultNeighCells_PR_measResultListNR)
|
||||
break;
|
||||
|
||||
for (int neigh_meas_idx = 0; neigh_meas_idx < measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultNeighCells->choice.measResultListNR->list.count; neigh_meas_idx++){
|
||||
const NR_MeasResultNR_t* meas_result_neigh_cell = (measurementReport->criticalExtensions.choice.measurementReport->measResults.measResultNeighCells->choice.measResultListNR->list.array[neigh_meas_idx]);
|
||||
const int neighbourCellId = *(meas_result_neigh_cell->physCellId);
|
||||
if (meas_result_neigh_cell->measResult.cellResults.resultsSSB_Cell) {
|
||||
neighbourCellRSRP = *(meas_result_neigh_cell->measResult.cellResults.resultsSSB_Cell->rsrp) - 157;
|
||||
} else {
|
||||
neighbourCellRSRP = *(meas_result_neigh_cell->measResult.cellResults.resultsCSI_RS_Cell->rsrp) - 157;
|
||||
}
|
||||
LOG_I(NR_RRC, "HO LOG: Measurement Report has came for the neighbour: %d with RSRP: %d\n", neighbourCellId, neighbourCellRSRP);
|
||||
if (neighbourCellRSRP > bestRsrp) {
|
||||
bestRsrp = neighbourCellRSRP;
|
||||
bestNeighbourId = neighbourCellId;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestRsrp > servingCellRSRP + handoverMargin){
|
||||
trigger_ho = true;
|
||||
LOG_I(NR_RRC, "HO LOG: Serving Cell RSRP: %d - Best Neighbor RSRP: %d ! Trigger HO\n", servingCellRSRP, bestRsrp);
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
LOG_D(NR_RRC, "NR_EventTriggerConfig__eventId_PR_NOTHING or Other event report\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (trigger_ho == true && ue_ctxt->StatusRrc != NR_RRC_HO_PREPARATION) {
|
||||
LOG_I(NR_RRC, "HO LOG: TRIGGER HANDOVER FOR PHY CELL ID: %d\n", bestNeighbourId);
|
||||
|
||||
protocol_ctxt_t ctxt = {0};
|
||||
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, 0, GNB_FLAG_YES, ue_context->ue_context.rrc_ue_id, 0, 0);
|
||||
uint8_t* buffer = (uint8_t*)calloc(1,RRC_BUF_SIZE);
|
||||
NR_SRB_ToAddModList_t *SRBs = createSRBlist(&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);
|
||||
DevAssert(bestNeighbourId != -1);
|
||||
const nr_neighbour_gnb_configuration_t* neighbourConfig = rrc_gNB_find_neighbour_cell_configuration_by_phyCellId(bestNeighbourId);
|
||||
if (neighbourConfig != NULL) {
|
||||
rrc_gNB_send_NGAP_HANDOVER_REQUIRED(&ctxt, ue_context, 0, neighbourConfig, &buffer, hoPrepSize);
|
||||
} else {
|
||||
LOG_E(NR_RRC, "HO LOG: NeighBour Cell Configuration can not be found with phyCellId: 0\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP,
|
||||
@@ -1579,6 +1826,7 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP,
|
||||
&& ul_dcch_msg->message.present == NR_UL_DCCH_MessageType_PR_c1
|
||||
&& ul_dcch_msg->message.choice.c1
|
||||
&& ul_dcch_msg->message.choice.c1->present == NR_UL_DCCH_MessageType__c1_PR_measurementReport);
|
||||
|
||||
rrc_gNB_process_MeasurementReport(ue_context_p, ul_dcch_msg->message.choice.c1->choice.measurementReport);
|
||||
break;
|
||||
|
||||
@@ -2173,6 +2421,7 @@ static const char *get_rrc_connection_status_text(NR_UE_STATE_t state)
|
||||
case NR_RRC_SI_RECEIVED: return "SI-received";
|
||||
case NR_RRC_CONNECTED: return "connected";
|
||||
case NR_RRC_RECONFIGURED: return "reconfigured";
|
||||
case NR_RRC_HO_PREPARATION: return "HO-preparation";
|
||||
case NR_RRC_HO_EXECUTION: return "HO-execution";
|
||||
default: AssertFatal(false, "illegal RRC state %d\n", state); return "illegal";
|
||||
}
|
||||
@@ -2423,6 +2672,10 @@ void *rrc_gnb_task(void *args_p) {
|
||||
rrc_gNB_process_PAGING_IND(msg_p, instance);
|
||||
break;
|
||||
|
||||
case NGAP_HANDOVER_COMMAND:
|
||||
rrc_gNB_process_HandoverCommand(msg_p, instance);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p);
|
||||
break;
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
#include "RRC/NR/MESSAGES/asn1_msg.h"
|
||||
#include "NR_UERadioAccessCapabilityInformation.h"
|
||||
#include "NR_UE-CapabilityRAT-ContainerList.h"
|
||||
#include "NR_HandoverPreparationInformation.h"
|
||||
#include "NR_HandoverCommand.h"
|
||||
#include "NR_HandoverCommand-IEs.h"
|
||||
#include "NGAP_CauseRadioNetwork.h"
|
||||
#include "f1ap_messages_types.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
@@ -1275,7 +1278,79 @@ void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(const protocol_ctxt_t *const ctxt_pP,
|
||||
itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p);
|
||||
LOG_I(NR_RRC,"Send message to ngap: NGAP_UE_CAPABILITIES_IND\n");
|
||||
}
|
||||
void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
uint8_t xid,
|
||||
const nr_neighbour_gnb_configuration_t* neighbourCellConfiguration,
|
||||
uint8_t** handoverPrepInfo,
|
||||
const size_t handoverPrepInfoSize
|
||||
)
|
||||
{
|
||||
LOG_I(NR_RRC, "HO Log: Preparing Handover Required 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_REQUIRED);
|
||||
ngap_handover_required_t* ho_required = &NGAP_HANDOVER_REQUIRED(msg_p);
|
||||
memset(ho_required, 0, sizeof(*ho_required));
|
||||
|
||||
//Prepare RAN UE NGAP ID
|
||||
ho_required->gNB_ue_ngap_id = UE->rrc_ue_id;
|
||||
|
||||
//Prepare AMF UE NGAP ID
|
||||
ho_required->amf_ue_ngap_id = UE->amf_ue_ngap_id;
|
||||
ho_required->nb_of_pdusessions = UE->nb_of_pdusessions;
|
||||
// Prepare PDU Session Items
|
||||
for (int i = 0; i < UE->nb_of_pdusessions; ++i) {
|
||||
if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE || UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false);
|
||||
if (!pduSession)
|
||||
continue;
|
||||
|
||||
ho_required->pdusessions[i].pdusession_id = pduSession->param.pdusession_id;
|
||||
ho_required->pdusessions[i].nb_of_qos_flow = pduSession->param.nb_qos;
|
||||
for (int j = 0; j < pduSession->param.nb_qos; ++j) {
|
||||
ho_required->pdusessions[i].associated_qos_flows[j].qfi = pduSession->param.qos[j].qfi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int drbItem = 0; drbItem < MAX_DRBS_PER_UE; ++drbItem) {
|
||||
if (UE->established_drbs[drbItem].status == DRB_INACTIVE)
|
||||
continue;
|
||||
|
||||
ho_required->used_drbs[drbItem].isActive = true;
|
||||
ho_required->used_drbs[drbItem].drbId = UE->established_drbs[drbItem].drb_id;
|
||||
ho_required->used_drbs[drbItem].qosFlowId = ho_required->pdusessions[drbItem].associated_qos_flows[0].qfi;
|
||||
}
|
||||
|
||||
//Prepare Source To Target Container
|
||||
ho_required->sourceToTargetContainer = (source_to_target_transparent_container_t*)calloc(1, sizeof(source_to_target_transparent_container_t));
|
||||
ho_required->sourceToTargetContainer->targetCellId.plmn_identity.mnc_digit_length = neighbourCellConfiguration->neighbour_mnc_digit_length;
|
||||
ho_required->sourceToTargetContainer->targetCellId.plmn_identity.mnc = neighbourCellConfiguration->neighbour_mnc;
|
||||
ho_required->sourceToTargetContainer->targetCellId.plmn_identity.mcc = neighbourCellConfiguration->neighbour_mcc;
|
||||
ho_required->sourceToTargetContainer->targetCellId.nrCellIdentity = neighbourCellConfiguration->neighbour_nrcell_id;
|
||||
|
||||
ho_required->sourceToTargetContainer->handoverInfo.buffer = (uint8_t*)(calloc(1, handoverPrepInfoSize));
|
||||
memcpy(ho_required->sourceToTargetContainer->handoverInfo.buffer, *handoverPrepInfo, handoverPrepInfoSize);
|
||||
ho_required->sourceToTargetContainer->handoverInfo.length = handoverPrepInfoSize;
|
||||
|
||||
//Prepare Target ID
|
||||
ho_required->target_gnb_id.plmn_identity.mnc_digit_length = neighbourCellConfiguration->neighbour_mnc_digit_length;
|
||||
ho_required->target_gnb_id.plmn_identity.mnc = neighbourCellConfiguration->neighbour_mnc;
|
||||
ho_required->target_gnb_id.plmn_identity.mcc = neighbourCellConfiguration->neighbour_mcc;
|
||||
ho_required->target_gnb_id.tac = neighbourCellConfiguration->neighbour_tac;
|
||||
ho_required->target_gnb_id.targetgNBId = neighbourCellConfiguration->neighbour_gNB_ID;
|
||||
|
||||
//Prepare Cause
|
||||
ho_required->cause = 16; //handover desirable for radio reason
|
||||
//Preapre HO Type
|
||||
ho_required->handoverType = 0; //intra5gs
|
||||
|
||||
ue_context_pP->ue_context.StatusRrc = NR_RRC_HO_PREPARATION;
|
||||
itti_send_msg_to_task(TASK_NGAP, ctxt_pP->instance, msg_p);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(
|
||||
|
||||
@@ -100,6 +100,15 @@ void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
const NR_UECapabilityInformation_t *const ue_cap_info);
|
||||
|
||||
void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
uint8_t xid,
|
||||
const nr_neighbour_gnb_configuration_t* neighbourCellConfiguration,
|
||||
uint8_t** handoverPrepInfo,
|
||||
const size_t handoverPrepInfoSize
|
||||
);
|
||||
|
||||
int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance);
|
||||
|
||||
void
|
||||
|
||||
@@ -85,6 +85,16 @@
|
||||
#include "NGAP_GTPTunnel.h"
|
||||
#include "NGAP_UE-NGAP-ID-pair.h"
|
||||
#include "NGAP_UserLocationInformationNR.h"
|
||||
#include "NGAP_HandoverCommand.h"
|
||||
#include "NGAP_HandoverCommandTransfer.h"
|
||||
#include "NGAP_PDUSessionResourceHandoverList.h"
|
||||
#include "NGAP_PDUSessionResourceHandoverItem.h"
|
||||
#include "NGAP_UPTransportLayerInformation.h"
|
||||
#include "NGAP_GTPTunnel.h"
|
||||
#include "NGAP_GTP-TEID.h"
|
||||
#include "NGAP_TargetNGRANNode-ToSourceNGRANNode-TransparentContainer.h"
|
||||
#include "NGAP_TargetToSource-TransparentContainer.h"
|
||||
|
||||
|
||||
/* Checking version of ASN1C compiler */
|
||||
#if (ASN1C_ENVIRONMENT_VERSION < ASN1C_MINIMUM_VERSION)
|
||||
|
||||
@@ -356,6 +356,9 @@ void *ngap_gNB_process_itti_msg(void *notUsed) {
|
||||
ngap_gNB_pdusession_release_resp(instance, &NGAP_PDUSESSION_RELEASE_RESPONSE(received_msg));
|
||||
break;
|
||||
|
||||
case NGAP_HANDOVER_REQUIRED:
|
||||
ngap_gNB_handover_required(instance, &NGAP_HANDOVER_REQUIRED(received_msg));
|
||||
break;
|
||||
default:
|
||||
NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
|
||||
break;
|
||||
|
||||
@@ -44,12 +44,24 @@
|
||||
#include "ngap_gNB_itti_messaging.h"
|
||||
|
||||
#include "ngap_gNB_encoder.h"
|
||||
#include "ngap_gNB_decoder.h"
|
||||
#include "ngap_gNB_nnsf.h"
|
||||
#include "ngap_gNB_ue_context.h"
|
||||
#include "ngap_gNB_nas_procedures.h"
|
||||
#include "ngap_gNB_management_procedures.h"
|
||||
#include "ngap_gNB_context_management_procedures.h"
|
||||
#include "NGAP_PDUSessionResourceItemCxtRelReq.h"
|
||||
#include "NGAP_PDUSessionResourceItemHORqd.h"
|
||||
#include "NGAP_HandoverRequiredTransfer.h"
|
||||
#include "NGAP_SourceNGRANNode-ToTargetNGRANNode-TransparentContainer.h"
|
||||
#include "NGAP_PDUSessionResourceInformationList.h"
|
||||
#include "NGAP_PDUSessionResourceInformationItem.h"
|
||||
#include "NGAP_QosFlowInformationList.h"
|
||||
#include "NGAP_QosFlowInformationItem.h"
|
||||
#include "NGAP_LastVisitedCellItem.h"
|
||||
#include "NGAP_UEHistoryInformation.h"
|
||||
#include "NGAP_LastVisitedNGRANCellInformation.h"
|
||||
#include "NGAP_Cause.h"
|
||||
|
||||
|
||||
int ngap_ue_context_release_complete(instance_t instance,
|
||||
@@ -234,3 +246,236 @@ int ngap_ue_context_release_req(instance_t instance,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ngap_gNB_handover_required(instance_t instance, ngap_handover_required_t* handover_required_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_required_p != NULL);
|
||||
DevAssert(ngap_gNB_instance_p != NULL);
|
||||
|
||||
if ((ue_context_p = ngap_get_ue_context(handover_required_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_required_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_HandoverPreparation;
|
||||
head->criticality = NGAP_Criticality_reject;
|
||||
head->value.present = NGAP_InitiatingMessage__value_PR_HandoverRequired;
|
||||
NGAP_HandoverRequired_t *out = &head->value.choice.HandoverRequired;
|
||||
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__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_HandoverRequiredIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__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_HandoverRequiredIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_HandoverType;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_HandoverType;
|
||||
ie->value.choice.HandoverType = (int64_t)handover_required_p->handoverType; //NGAP_HandoverType_intra5gs
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_Cause;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_Cause;
|
||||
ie->value.choice.Cause.present = NGAP_Cause_PR_radioNetwork;
|
||||
ie->value.choice.Cause.choice.radioNetwork = handover_required_p->cause; //NGAP_CauseRadioNetwork_handover_desirable_for_radio_reason
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_TargetID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_TargetID;
|
||||
ie->value.choice.TargetID.present = NGAP_TargetID_PR_targetRANNodeID;
|
||||
asn1cCalloc(ie->value.choice.TargetID.choice.targetRANNodeID, targetRan);
|
||||
targetRan->globalRANNodeID.present = NGAP_GlobalRANNodeID_PR_globalGNB_ID;
|
||||
asn1cCalloc(targetRan->globalRANNodeID.choice.globalGNB_ID, globalGnbId);
|
||||
|
||||
globalGnbId->gNB_ID.present = NGAP_GNB_ID_PR_gNB_ID;
|
||||
|
||||
MACRO_GNB_ID_TO_BIT_STRING(handover_required_p->target_gnb_id.targetgNBId,
|
||||
&globalGnbId->gNB_ID.choice.gNB_ID);
|
||||
|
||||
|
||||
MCC_MNC_TO_PLMNID(handover_required_p->target_gnb_id.plmn_identity.mcc,
|
||||
handover_required_p->target_gnb_id.plmn_identity.mnc,
|
||||
handover_required_p->target_gnb_id.plmn_identity.mnc_digit_length,
|
||||
&globalGnbId->pLMNIdentity);
|
||||
|
||||
/* Set TAI */
|
||||
INT24_TO_OCTET_STRING(handover_required_p->target_gnb_id.tac, &targetRan->selectedTAI.tAC);
|
||||
MCC_MNC_TO_PLMNID(handover_required_p->target_gnb_id.plmn_identity.mcc,
|
||||
handover_required_p->target_gnb_id.plmn_identity.mnc,
|
||||
handover_required_p->target_gnb_id.plmn_identity.mnc_digit_length,
|
||||
&targetRan->selectedTAI.pLMNIdentity);
|
||||
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceListHORqd;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_PDUSessionResourceListHORqd;
|
||||
for (int i = 0; i < handover_required_p->nb_of_pdusessions; ++i) {
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceListHORqd.list, NGAP_PDUSessionResourceItemHORqd_t, hoRequiredPduSession);
|
||||
hoRequiredPduSession->pDUSessionID = handover_required_p->pdusessions[i].pdusession_id;
|
||||
|
||||
NGAP_HandoverRequiredTransfer_t hoRequiredTransfer = {0};
|
||||
asn1cCalloc(hoRequiredTransfer.directForwardingPathAvailability, directFwdPathAvl);
|
||||
*directFwdPathAvl = NGAP_DirectForwardingPathAvailability_direct_path_available; //set False! (?)
|
||||
|
||||
void *hoRequiredTransferPduSessionBuf;
|
||||
ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_NGAP_HandoverRequiredTransfer, NULL, &hoRequiredTransfer, &hoRequiredTransferPduSessionBuf);
|
||||
AssertFatal(encoded > 0, "HO LOG: asn_DEF_NGAP_HandoverRequiredTransfer ASN1 message encoding failed !\n");
|
||||
hoRequiredPduSession->handoverRequiredTransfer.buf = CALLOC(1, encoded);
|
||||
hoRequiredPduSession->handoverRequiredTransfer.buf = hoRequiredTransferPduSessionBuf;
|
||||
hoRequiredPduSession->handoverRequiredTransfer.size = encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_HandoverRequiredTransfer, &hoRequiredTransfer);
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_DirectForwardingPathAvailability;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_DirectForwardingPathAvailability;
|
||||
ie->value.choice.DirectForwardingPathAvailability = NGAP_DirectForwardingPathAvailability_direct_path_available;
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_SourceToTarget_TransparentContainer;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_SourceToTarget_TransparentContainer;
|
||||
|
||||
|
||||
NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer_t* transparentContainer = (NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer_t*)calloc(1, sizeof(NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer_t));
|
||||
|
||||
//rRC Container
|
||||
{
|
||||
// Handover Prep Information
|
||||
transparentContainer->rRCContainer.size = handover_required_p->sourceToTargetContainer->handoverInfo.length;
|
||||
transparentContainer->rRCContainer.buf = (uint8_t *)malloc(handover_required_p->sourceToTargetContainer->handoverInfo.length);
|
||||
memcpy(transparentContainer->rRCContainer.buf, handover_required_p->sourceToTargetContainer->handoverInfo.buffer ,transparentContainer->rRCContainer.size);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//PDU Session Information
|
||||
{
|
||||
asn1cCalloc(transparentContainer->pDUSessionResourceInformationList, pduSessionList);
|
||||
for (uint8_t i = 0; i < handover_required_p->nb_of_pdusessions; ++i)
|
||||
{
|
||||
|
||||
|
||||
asn1cSequenceAdd(pduSessionList->list, NGAP_PDUSessionResourceInformationItem_t, pduSesResourceStp);
|
||||
pduSesResourceStp->pDUSessionID = (int64_t)handover_required_p->pdusessions[i].pdusession_id;
|
||||
|
||||
pduSesResourceStp->dRBsToQosFlowsMappingList = NULL;
|
||||
pduSesResourceStp->iE_Extensions = NULL;
|
||||
|
||||
for (int qosFlowId = 0; qosFlowId < handover_required_p->pdusessions[i].nb_of_qos_flow; ++qosFlowId) {
|
||||
asn1cSequenceAdd(pduSesResourceStp->qosFlowInformationList.list, NGAP_QosFlowInformationItem_t, qosFlowInfo);
|
||||
qosFlowInfo->qosFlowIdentifier = (int64_t)handover_required_p->pdusessions[i].associated_qos_flows[qosFlowId].qfi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NrCGI - Mandatory
|
||||
{
|
||||
transparentContainer->targetCell_ID.present = NGAP_NGRAN_CGI_PR_nR_CGI;
|
||||
asn1cCalloc(transparentContainer->targetCell_ID.choice.nR_CGI, tNrCGI);
|
||||
tNrCGI->iE_Extensions = NULL;
|
||||
MCC_MNC_TO_PLMNID(handover_required_p->target_gnb_id.plmn_identity.mcc,
|
||||
handover_required_p->target_gnb_id.plmn_identity.mnc,
|
||||
handover_required_p->target_gnb_id.plmn_identity.mnc_digit_length,
|
||||
&tNrCGI->pLMNIdentity);
|
||||
|
||||
NR_CELL_ID_TO_BIT_STRING(handover_required_p->sourceToTargetContainer->targetCellId.nrCellIdentity, &tNrCGI->nRCellIdentity);
|
||||
}
|
||||
|
||||
//UE history Information - Mandatory
|
||||
{
|
||||
asn1cSequenceAdd(transparentContainer->uEHistoryInformation.list, NGAP_LastVisitedCellItem_t, lastVisitedCell);
|
||||
lastVisitedCell->iE_Extensions = NULL;
|
||||
lastVisitedCell->lastVisitedCellInformation.present = NGAP_LastVisitedCellInformation_PR_nGRANCell;
|
||||
asn1cCalloc(lastVisitedCell->lastVisitedCellInformation.choice.nGRANCell, lastVisitedNR);
|
||||
lastVisitedNR->cellType.cellSize = NGAP_CellSize_small;
|
||||
lastVisitedNR->globalCellID.present = NGAP_NGRAN_CGI_PR_nR_CGI;
|
||||
|
||||
asn1cCalloc(lastVisitedNR->globalCellID.choice.nR_CGI, lastVisitedNrCGI);
|
||||
MCC_MNC_TO_PLMNID(handover_required_p->target_gnb_id.plmn_identity.mcc,
|
||||
handover_required_p->target_gnb_id.plmn_identity.mnc,
|
||||
handover_required_p->target_gnb_id.plmn_identity.mnc_digit_length,
|
||||
&lastVisitedNrCGI->pLMNIdentity);
|
||||
|
||||
NR_CELL_ID_TO_BIT_STRING(handover_required_p->sourceToTargetContainer->targetCellId.nrCellIdentity, &lastVisitedNrCGI->nRCellIdentity);
|
||||
|
||||
asn1cCalloc(lastVisitedNR->hOCauseValue, lastVisitedCause);
|
||||
lastVisitedCause->present = NGAP_Cause_PR_radioNetwork;
|
||||
lastVisitedCause->choice.radioNetwork = NGAP_CauseRadioNetwork_handover_desirable_for_radio_reason;
|
||||
//TODO: It is mandatory adding dummy number for now
|
||||
lastVisitedNR->timeUEStayedInCell = (int64_t)500;
|
||||
}
|
||||
|
||||
uint8_t *buf = NULL;
|
||||
int encoded = aper_encode_to_new_buffer(&asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, NULL, transparentContainer, (void**)&buf);
|
||||
AssertFatal(encoded > 0, "HO LOG: asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer ASN1 message encoding failed !\n");
|
||||
LOG_I(NR_RRC, "HO LOG Encoding Result and Length of The Transparent Container: %d!\n\n", encoded);
|
||||
|
||||
OCTET_STRING_fromBuf(&ie->value.choice.SourceToTarget_TransparentContainer, (const char *)buf,
|
||||
encoded);
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,4 +38,7 @@ int ngap_ue_context_release_complete(instance_t instance,
|
||||
int ngap_ue_context_release_req(instance_t instance,
|
||||
ngap_ue_release_req_t *ue_release_req_p);
|
||||
|
||||
int ngap_gNB_handover_required(instance_t instance,
|
||||
ngap_handover_required_t *handover_required_p);
|
||||
|
||||
#endif /* NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_ */
|
||||
|
||||
@@ -69,6 +69,12 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) {
|
||||
NGAP_INFO("PDUSESSIONSetup initiating message\n");
|
||||
break;
|
||||
|
||||
case NGAP_ProcedureCode_id_HandoverPreparation:
|
||||
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
free(res.buffer);
|
||||
NGAP_INFO("Handover Preparation initiating message\n");
|
||||
break;
|
||||
|
||||
case NGAP_ProcedureCode_id_PDUSessionResourceModify:
|
||||
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
free(res.buffer);
|
||||
@@ -87,6 +93,12 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) {
|
||||
NGAP_INFO("TODO ErrorIndication initiating message\n");
|
||||
break;
|
||||
|
||||
case NGAP_ProcedureCode_id_HandoverResourceAllocation:
|
||||
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
free(res.buffer);
|
||||
NGAP_INFO("TODO Handover Resource Allocation initiating message\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n",
|
||||
(int)pdu->choice.initiatingMessage->procedureCode);
|
||||
@@ -118,7 +130,11 @@ static int ngap_gNB_decode_successful_outcome(NGAP_NGAP_PDU_t *pdu) {
|
||||
free(res.buffer);
|
||||
break;
|
||||
|
||||
|
||||
case NGAP_ProcedureCode_id_HandoverPreparation:
|
||||
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
free(res.buffer);
|
||||
break;
|
||||
|
||||
default:
|
||||
NGAP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
|
||||
(int)pdu->choice.successfulOutcome->procedureCode);
|
||||
|
||||
@@ -49,7 +49,8 @@ static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, uint8_t **buf
|
||||
NGAP_ProcedureCode_id_NASNonDeliveryIndication,
|
||||
NGAP_ProcedureCode_id_UEContextReleaseRequest,
|
||||
NGAP_ProcedureCode_id_PathSwitchRequest,
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication};
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication,
|
||||
NGAP_ProcedureCode_id_HandoverPreparation,};
|
||||
int i;
|
||||
for (i = 0; i < sizeofArray(tmp); i++)
|
||||
if (pdu->choice.initiatingMessage->procedureCode == tmp[i])
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "ngap_gNB_trace.h"
|
||||
#include "ngap_gNB_nas_procedures.h"
|
||||
#include "ngap_gNB_management_procedures.h"
|
||||
#include "ngap_gNB_context_management_procedures.h"
|
||||
|
||||
#include "ngap_gNB_default_values.h"
|
||||
|
||||
@@ -57,6 +58,16 @@ static void allocCopy(ngap_pdu_t *out, OCTET_STRING_t in)
|
||||
out->length = in.size;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
char *ngap_direction2String(int ngap_dir) {
|
||||
static char *ngap_direction_String[] = {
|
||||
"", /* Nothing */
|
||||
@@ -670,6 +681,12 @@ static int ngap_gNB_handle_error_indication(sctp_assoc_t assoc_id, uint32_t stre
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ngap_gNB_handle_handover_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
NGAP_INFO("HO LOG: Handover Request Message Has Came to the Target gNB! - NOT IMPLEMENTED\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
int i;
|
||||
@@ -990,6 +1007,119 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ngap_gNB_handle_handover_command(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
NGAP_INFO("HO LOG: Handover Command is came to source gNB!\n");
|
||||
// NGAP_AMF_UE_NGAP_ID_t amf_ue_ngap_id;
|
||||
uint64_t amf_ue_ngap_id;
|
||||
NGAP_RAN_UE_NGAP_ID_t ran_ue_ngap_id;
|
||||
ngap_gNB_amf_data_t *amf_desc_p = NULL;
|
||||
|
||||
NGAP_HandoverCommand_t *container;
|
||||
NGAP_HandoverCommandIEs_t *ie;
|
||||
DevAssert(pdu != NULL);
|
||||
container = &pdu->choice.successfulOutcome->value.choice.HandoverCommand;
|
||||
|
||||
if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
|
||||
NGAP_ERROR("[SCTP %u] Received Handover Command for non "
|
||||
"existing AMF context\n", assoc_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* id-AMF-UE-NGAP-ID */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_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);
|
||||
|
||||
/* id-gNB-UE-NGAP-ID */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true);
|
||||
ran_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID;
|
||||
|
||||
ngap_gNB_ue_context_t *ue_desc_p = ngap_get_ue_context(ran_ue_ngap_id);
|
||||
if (!ue_desc_p) {
|
||||
NGAP_ERROR("[SCTP %u] Received HO Command Msg for non "
|
||||
"existing UE context 0x%06lx\n", assoc_id,
|
||||
ran_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ue_desc_p->rx_stream = stream;
|
||||
|
||||
if ( ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) {
|
||||
NGAP_ERROR("UE context amf_ue_ngap_id is different form that of the message (%lu != %lu)",
|
||||
(uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
MessageDef * message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_HANDOVER_COMMAND);
|
||||
ngap_handover_command_t * msg=&NGAP_HANDOVER_COMMAND(message_p);
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
msg->gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id;
|
||||
msg->amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id;
|
||||
|
||||
/* id-Handover Type */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_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;
|
||||
}
|
||||
/* PDU Session Resource Handover List */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_HandoverType, false);
|
||||
if (ie != NULL)
|
||||
{
|
||||
uint8_t numberOfDlForwardSessions = 0;
|
||||
for (int pduSesIdx = 0; pduSesIdx < ie->value.choice.PDUSessionResourceHandoverList.list.count; ++pduSesIdx)
|
||||
{
|
||||
NGAP_PDUSessionResourceHandoverItem_t* pduSessionItem = ie->value.choice.PDUSessionResourceHandoverList.list.array[pduSesIdx];
|
||||
msg->pduSessionResourceHandoverList[pduSesIdx].pdusession_id = pduSessionItem->pDUSessionID;
|
||||
NGAP_HandoverCommandTransfer_t* hoCommandTransfer = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NGAP_HandoverCommandTransfer, (void**)&hoCommandTransfer, pduSessionItem->handoverCommandTransfer.buf, pduSessionItem->handoverCommandTransfer.size);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
NGAP_ERROR("cannot decode Ho Command List for UE ID: %d, ignoring data forwarding\n", ue_desc_p->gNB_ue_ngap_id);
|
||||
continue;
|
||||
}
|
||||
if (hoCommandTransfer->dLForwardingUP_TNLInformation->present != NGAP_UPTransportLayerInformation_PR_gTPTunnel) {
|
||||
NGAP_ERROR("GTP TNL Information does not exists for UE ID: %d, ignoring data forwarding\n", ue_desc_p->gNB_ue_ngap_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
NGAP_UPTransportLayerInformation_t* upTransportLayerInfo = hoCommandTransfer->dLForwardingUP_TNLInformation;
|
||||
if (upTransportLayerInfo->present != NGAP_UPTransportLayerInformation_PR_gTPTunnel)
|
||||
{
|
||||
NGAP_ERROR("GTP TNL Information does not exists for UE ID: %d, ignoring data forwarding\n", ue_desc_p->gNB_ue_ngap_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
OCTET_STRING_TO_INT32(&(upTransportLayerInfo->choice.gTPTunnel->gTP_TEID), msg->pduSessionResourceHandoverList[pduSesIdx].gtp_teid);
|
||||
allocAddrCopy(&(upTransportLayerInfo->choice.gTPTunnel->transportLayerAddress), msg->pduSessionResourceHandoverList[pduSesIdx].gNB_addr);
|
||||
|
||||
numberOfDlForwardSessions++;
|
||||
}
|
||||
|
||||
msg->nb_of_pdusessions = numberOfDlForwardSessions;
|
||||
}
|
||||
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_TargetToSource_TransparentContainer, true);
|
||||
// ie->value.choice.TargetToSource_TransparentContainer
|
||||
NGAP_TargetToSource_TransparentContainer_t* targetToSourceTransparentContainer= &(ie->value.choice.TargetToSource_TransparentContainer);
|
||||
NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer_t* transparentContainer = NULL;
|
||||
asn_dec_rval_t dec_rval = aper_decode_complete(NULL, &asn_DEF_NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer, (void**)&transparentContainer, targetToSourceTransparentContainer->buf, targetToSourceTransparentContainer->size);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
NGAP_ERROR("cannot decode Ho Command List for UE ID: %d\n", ue_desc_p->gNB_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg->handoverCommand.buffer = (uint8_t*)calloc(1, transparentContainer->rRCContainer.size);
|
||||
msg->handoverCommand.length = transparentContainer->rRCContainer.size;
|
||||
memcpy(msg->handoverCommand.buffer, transparentContainer->rRCContainer.buf, transparentContainer->rRCContainer.size);
|
||||
|
||||
NGAP_INFO("Handover Command is parsed with a size of: %u. Sending to RRC GNB!\n", msg->handoverCommand.length);
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, amf_desc_p->ngap_gNB_instance->instance, message_p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
ngap_gNB_amf_data_t *amf_desc_p = NULL;
|
||||
@@ -1289,8 +1419,8 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = {
|
||||
{ngap_gNB_handle_error_indication, 0, 0}, /* ErrorIndication */
|
||||
{0, 0, 0}, /* HandoverCancel */
|
||||
{0, 0, 0}, /* HandoverNotification */
|
||||
{0, 0, 0}, /* HandoverPreparation */
|
||||
{0, 0, 0}, /* HandoverResourceAllocation */
|
||||
{0, ngap_gNB_handle_handover_command, 0}, /* HandoverPreparation */
|
||||
{ngap_gNB_handle_handover_request, 0, 0}, /* HandoverResourceAllocation */
|
||||
{ngap_gNB_handle_initial_context_request, 0, 0}, /* InitialContextSetup */
|
||||
{0, 0, 0}, /* InitialUEMessage */
|
||||
{0, 0, 0}, /* LocationReportingControl */
|
||||
|
||||
@@ -139,6 +139,7 @@ do { \
|
||||
(aSN)->size = 4; \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define INT32_TO_BIT_STRING(x, aSN) \
|
||||
do { \
|
||||
INT32_TO_OCTET_STRING(x, aSN); \
|
||||
@@ -601,5 +602,6 @@ do { \
|
||||
#define TAC_TO_ASN1 INT16_TO_OCTET_STRING
|
||||
#define GTP_TEID_TO_ASN1 INT32_TO_OCTET_STRING
|
||||
#define OCTET_STRING_TO_TAC OCTET_STRING_TO_INT16
|
||||
#define ASN1_TO_GTP_TEID OCTET_STRING_TO_INT32
|
||||
|
||||
#endif /* CONVERSIONS_H_ */
|
||||
|
||||
Reference in New Issue
Block a user