Use F1 UE context setup/modif Request in stack
Use the new, tested F1 UE context setup request and modification requests in the stack. We have to do both at once, because there are some functions that are used by handlers for both messages, notably - handle_ue_context_drbs_setup() - handle_ue_context_srbs_setup() (+ and some functions called by those two). For instance, the first uses the (new/old) type f1ap_drb_to_be_setup_t/f1ap_drb_to_setup_t which is shared. The alternative would be to duplicate the functionality temporarily, and I want to avoid unnecessary code churn.
This commit is contained in:
@@ -56,9 +56,9 @@ MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue
|
||||
/* RRC -> F1AP messages */
|
||||
MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message )
|
||||
//MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req )
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_req)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_req_t, f1ap_ue_context_setup_req)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_req_t, f1ap_ue_context_modification_req)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_req_t, f1ap_ue_context_mod_req)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_confirm_t, f1ap_ue_context_modification_confirm)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse)
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message
|
||||
#define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req
|
||||
#define F1AP_UE_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_resp
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_req
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_mod_req
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_required
|
||||
@@ -645,7 +645,7 @@ typedef struct f1ap_ue_context_setup_s {
|
||||
uint8_t *rrc_container;
|
||||
int rrc_container_length;
|
||||
TransmActionInd_t *transm_action_ind;
|
||||
} f1ap_ue_context_setup_t, f1ap_ue_context_modif_req_t, f1ap_ue_context_modif_resp_t;
|
||||
} f1ap_ue_context_setup_t, f1ap_ue_context_modif_resp_t;
|
||||
|
||||
typedef enum F1ap_Cause_e {
|
||||
F1AP_CAUSE_NOTHING, /* No components present */
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "f1ap_cu_ue_context_management.h"
|
||||
#include "lib/f1ap_rrc_message_transfer.h"
|
||||
#include "lib/f1ap_interface_management.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
#include "f1ap_cu_paging.h"
|
||||
#include "f1ap_cu_task.h"
|
||||
#include "openair2/RRC/NR/nr_rrc_defs.h"
|
||||
@@ -186,13 +187,13 @@ void *F1AP_CU_task(void *arg) {
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_SETUP_REQ: // from rrc
|
||||
CU_send_UE_CONTEXT_SETUP_REQUEST(assoc_id,
|
||||
&F1AP_UE_CONTEXT_SETUP_REQ(received_msg));
|
||||
CU_send_UE_CONTEXT_SETUP_REQUEST(assoc_id, &F1AP_UE_CONTEXT_SETUP_REQ(received_msg));
|
||||
free_ue_context_setup_req(&F1AP_UE_CONTEXT_SETUP_REQ(received_msg));
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_MODIFICATION_REQ:
|
||||
CU_send_UE_CONTEXT_MODIFICATION_REQUEST(assoc_id,
|
||||
&F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg));
|
||||
CU_send_UE_CONTEXT_MODIFICATION_REQUEST(assoc_id, &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg));
|
||||
free_ue_context_mod_req(&F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg));
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,8 +36,7 @@
|
||||
/*
|
||||
* UE Context Setup
|
||||
*/
|
||||
int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id,
|
||||
f1ap_ue_context_setup_t *f1ap_ue_context_setup_req);
|
||||
int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req);
|
||||
|
||||
int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
@@ -59,7 +58,7 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t asso
|
||||
/*
|
||||
* UE Context Modification (gNB-CU initiated)
|
||||
*/
|
||||
int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req);
|
||||
int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req);
|
||||
int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "f1ap_du_rrc_message_transfer.h"
|
||||
#include "lib/f1ap_rrc_message_transfer.h"
|
||||
#include "lib/f1ap_interface_management.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
#include "f1ap_du_task.h"
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
|
||||
|
||||
@@ -34,295 +34,24 @@
|
||||
#include "f1ap_encoder.h"
|
||||
#include "f1ap_itti_messaging.h"
|
||||
#include "f1ap_du_ue_context_management.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h"
|
||||
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
|
||||
static void f1ap_read_drb_qos_param(const F1AP_QoSFlowLevelQoSParameters_t *asn1_qos, f1ap_qos_flow_level_qos_parameters_t *drb_qos)
|
||||
{
|
||||
f1ap_qos_characteristics_t *drb_qos_char = &drb_qos->qos_characteristics;
|
||||
const F1AP_QoS_Characteristics_t *dRB_QoS_Char = &asn1_qos->qoS_Characteristics;
|
||||
|
||||
if (dRB_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
|
||||
drb_qos_char->qos_type = NON_DYNAMIC;
|
||||
drb_qos_char->non_dynamic.fiveqi = dRB_QoS_Char->choice.non_Dynamic_5QI->fiveQI;
|
||||
drb_qos_char->non_dynamic.qos_priority_level = (dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL)
|
||||
? *dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel
|
||||
: -1;
|
||||
} else {
|
||||
drb_qos_char->qos_type = DYNAMIC;
|
||||
drb_qos_char->dynamic.fiveqi =
|
||||
(dRB_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *dRB_QoS_Char->choice.dynamic_5QI->fiveQI : -1;
|
||||
drb_qos_char->dynamic.qos_priority_level = dRB_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel;
|
||||
drb_qos_char->dynamic.packet_delay_budget = dRB_QoS_Char->choice.dynamic_5QI->packetDelayBudget;
|
||||
drb_qos_char->dynamic.packet_error_rate.per_scalar = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar;
|
||||
drb_qos_char->dynamic.packet_error_rate.per_exponent = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent;
|
||||
}
|
||||
|
||||
/* nGRANallocationRetentionPriority */
|
||||
drb_qos->alloc_reten_priority.priority_level = asn1_qos->nGRANallocationRetentionPriority.priorityLevel;
|
||||
drb_qos->alloc_reten_priority.preemption_vulnerability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability;
|
||||
drb_qos->alloc_reten_priority.preemption_capability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability;
|
||||
}
|
||||
|
||||
static void f1ap_read_flows_mapped(const F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, f1ap_flows_mapped_to_drb_t *flows_mapped, int n)
|
||||
{
|
||||
for (int k = 0; k < n; k++) {
|
||||
f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb = flows_mapped + k;
|
||||
const F1AP_Flows_Mapped_To_DRB_Item_t *flows_Mapped_To_Drb = asn1_flows_mapped->list.array[0] + k;
|
||||
|
||||
flows_mapped_to_drb->qfi = flows_Mapped_To_Drb->qoSFlowIdentifier;
|
||||
|
||||
/* QoS-Flow-Level-QoS-Parameters */
|
||||
{
|
||||
f1ap_qos_flow_level_qos_parameters_t *flow_qos = &flows_mapped_to_drb->qos_params;
|
||||
const F1AP_QoSFlowLevelQoSParameters_t *Flow_QoS = &flows_Mapped_To_Drb->qoSFlowLevelQoSParameters;
|
||||
|
||||
/* QoS Characteristics*/
|
||||
f1ap_qos_characteristics_t *flow_qos_char = &flow_qos->qos_characteristics;
|
||||
const F1AP_QoS_Characteristics_t *Flow_QoS_Char = &Flow_QoS->qoS_Characteristics;
|
||||
|
||||
if (Flow_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
|
||||
flow_qos_char->qos_type = NON_DYNAMIC;
|
||||
flow_qos_char->non_dynamic.fiveqi = Flow_QoS_Char->choice.non_Dynamic_5QI->fiveQI;
|
||||
flow_qos_char->non_dynamic.qos_priority_level = (Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL)
|
||||
? *Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel
|
||||
: -1;
|
||||
} else {
|
||||
flow_qos_char->qos_type = DYNAMIC;
|
||||
flow_qos_char->dynamic.fiveqi =
|
||||
(Flow_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *Flow_QoS_Char->choice.dynamic_5QI->fiveQI : -1;
|
||||
flow_qos_char->dynamic.qos_priority_level = Flow_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel;
|
||||
flow_qos_char->dynamic.packet_delay_budget = Flow_QoS_Char->choice.dynamic_5QI->packetDelayBudget;
|
||||
flow_qos_char->dynamic.packet_error_rate.per_scalar = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar;
|
||||
flow_qos_char->dynamic.packet_error_rate.per_exponent = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent;
|
||||
}
|
||||
|
||||
/* nGRANallocationRetentionPriority */
|
||||
flow_qos->alloc_reten_priority.priority_level = Flow_QoS->nGRANallocationRetentionPriority.priorityLevel;
|
||||
flow_qos->alloc_reten_priority.preemption_vulnerability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
|
||||
flow_qos->alloc_reten_priority.preemption_capability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void f1ap_read_drb_nssai(const F1AP_SNSSAI_t *asn1_nssai, nssai_t *nssai)
|
||||
{
|
||||
OCTET_STRING_TO_INT8(&asn1_nssai->sST, nssai->sst);
|
||||
nssai->sd = 0xffffff;
|
||||
if (asn1_nssai->sD != NULL) {
|
||||
BUFFER_TO_INT24(asn1_nssai->sD->buf, nssai->sd);
|
||||
}
|
||||
}
|
||||
|
||||
int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
F1AP_UEContextSetupRequest_t *container;
|
||||
int i;
|
||||
DevAssert(pdu);
|
||||
f1ap_ue_context_setup_t ue_context_setup = {0};
|
||||
f1ap_ue_context_setup_t *f1ap_ue_context_setup_req = &ue_context_setup;
|
||||
container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest;
|
||||
/* GNB_CU_UE_F1AP_ID */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieCU;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCU, container,
|
||||
F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
|
||||
f1ap_ue_context_setup_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
/* optional */
|
||||
/* GNB_DU_UE_F1AP_ID */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieDU_UE;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDU_UE, container,
|
||||
F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, false);
|
||||
// this should be optional. At present, the DU uses the RNTI, and hence, this
|
||||
// value cannot exceed 0xffff (or something below, whatever is a valid
|
||||
// C-RNTI). So we use a value > 0xffff to mark optionality
|
||||
f1ap_ue_context_setup_req->gNB_DU_ue_id = -1; // 0xffffffff
|
||||
if (ieDU_UE != NULL)
|
||||
f1ap_ue_context_setup_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
|
||||
/* SpCell_ID */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieNet;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieNet, container,
|
||||
F1AP_ProtocolIE_ID_id_SpCell_ID, true);
|
||||
PLMNID_TO_MCC_MNC(&ieNet->value.choice.NRCGI.pLMN_Identity,
|
||||
f1ap_ue_context_setup_req->plmn.mcc,
|
||||
f1ap_ue_context_setup_req->plmn.mnc,
|
||||
f1ap_ue_context_setup_req->plmn.mnc_digit_length);
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&ieNet->value.choice.NRCGI.nRCellIdentity, f1ap_ue_context_setup_req->nr_cellid);
|
||||
/* ServCellIndex */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieCell;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCell, container,
|
||||
F1AP_ProtocolIE_ID_id_ServCellIndex, true);
|
||||
f1ap_ue_context_setup_req->servCellIndex = ieCell->value.choice.ServCellIndex;
|
||||
/* optional */
|
||||
/* CellULConfigured */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieULCell;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieULCell, container,
|
||||
F1AP_ProtocolIE_ID_id_SpCellULConfigured, false); // SpCellULConfigured
|
||||
|
||||
if (ieULCell) {
|
||||
/* correct here */
|
||||
f1ap_ue_context_setup_req->cellULConfigured = malloc(sizeof(uint32_t));
|
||||
|
||||
if (f1ap_ue_context_setup_req->cellULConfigured)
|
||||
*f1ap_ue_context_setup_req->cellULConfigured = ieULCell->value.choice.CellULConfigured;
|
||||
} else {
|
||||
f1ap_ue_context_setup_req->cellULConfigured = NULL;
|
||||
f1ap_ue_context_setup_req_t req = {0};
|
||||
if (!decode_ue_context_setup_req(pdu, &req)) {
|
||||
LOG_E(F1AP, "cannot decode F1 UE Context Setup Request\n");
|
||||
free_ue_context_setup_req(&req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
F1AP_UEContextSetupRequestIEs_t *ieCuRrcInfo;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCuRrcInfo, container,
|
||||
F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, false);
|
||||
if(ieCuRrcInfo!=NULL){
|
||||
f1ap_ue_context_setup_req->cu_to_du_rrc_information = (cu_to_du_rrc_information_t *)calloc(1,sizeof(cu_to_du_rrc_information_t));
|
||||
cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_setup_req->cu_to_du_rrc_information;
|
||||
const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCuRrcInfo->value.choice.CUtoDURRCInformation;
|
||||
if (cu2duie->cG_ConfigInfo != NULL) {
|
||||
cu2du->cG_ConfigInfo = malloc_or_fail(cu2duie->cG_ConfigInfo->size);
|
||||
cu2du->cG_ConfigInfo_length = cu2duie->cG_ConfigInfo->size;
|
||||
memcpy(cu2du->cG_ConfigInfo, cu2duie->cG_ConfigInfo->buf, cu2du->cG_ConfigInfo_length);
|
||||
}
|
||||
if(cu2duie->uE_CapabilityRAT_ContainerList!=NULL){
|
||||
cu2du->uE_CapabilityRAT_ContainerList = calloc(1, cu2duie->uE_CapabilityRAT_ContainerList->size);
|
||||
memcpy(cu2du->uE_CapabilityRAT_ContainerList,
|
||||
cu2duie->uE_CapabilityRAT_ContainerList->buf,
|
||||
cu2duie->uE_CapabilityRAT_ContainerList->size);
|
||||
cu2du->uE_CapabilityRAT_ContainerList_length = cu2duie->uE_CapabilityRAT_ContainerList->size;
|
||||
LOG_D(F1AP, "Size f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length: %d \n", f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length);
|
||||
}
|
||||
if (cu2duie->iE_Extensions != NULL) {
|
||||
const F1AP_ProtocolExtensionContainer_10696P60_t *ext = (const F1AP_ProtocolExtensionContainer_10696P60_t *)cu2duie->iE_Extensions;
|
||||
for (int i = 0; i < ext->list.count; ++i) {
|
||||
const F1AP_CUtoDURRCInformation_ExtIEs_t *cu2du_info = ext->list.array[i];
|
||||
switch (cu2du_info->id) {
|
||||
case F1AP_ProtocolIE_ID_id_HandoverPreparationInformation:
|
||||
DevAssert(cu2du_info->extensionValue.present == F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation);
|
||||
const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info->extensionValue.choice.MeasurementTimingConfiguration;
|
||||
cu2du->handoverPreparationInfo = calloc_or_fail(1, hopi->size);
|
||||
memcpy(cu2du->handoverPreparationInfo, hopi->buf, hopi->size);
|
||||
cu2du->handoverPreparationInfo_length = hopi->size;
|
||||
break;
|
||||
default:
|
||||
LOG_W(F1AP, "unsupported CUtoDURRCInformation_ExtIE %ld encountered, ignoring\n", cu2du_info->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ue_context_setup_request(&req);
|
||||
free_ue_context_setup_req(&req);
|
||||
|
||||
/* DRB */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieDrb;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDrb, container,
|
||||
F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List, false);
|
||||
|
||||
if(ieDrb!=NULL) {
|
||||
f1ap_ue_context_setup_req->drbs_to_be_setup_length = ieDrb->value.choice.DRBs_ToBeSetup_List.list.count;
|
||||
f1ap_ue_context_setup_req->drbs_to_be_setup = calloc(f1ap_ue_context_setup_req->drbs_to_be_setup_length,
|
||||
sizeof(f1ap_drb_to_be_setup_t));
|
||||
AssertFatal(f1ap_ue_context_setup_req->drbs_to_be_setup,
|
||||
"could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n");
|
||||
|
||||
for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; ++i) {
|
||||
f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_req->drbs_to_be_setup[i];
|
||||
F1AP_DRBs_ToBeSetup_Item_t *drbs_tobesetup_item_p =
|
||||
&((F1AP_DRBs_ToBeSetup_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeSetup_List.list.array[i])->value.choice.DRBs_ToBeSetup_Item;
|
||||
drb_p->drb_id = drbs_tobesetup_item_p->dRBID;
|
||||
/* TODO in the following, assume only one UP UL TNL is present.
|
||||
* this matches/assumes OAI CU implementation, can be up to 2! */
|
||||
drb_p->up_ul_tnl_length = 1;
|
||||
AssertFatal(drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0,
|
||||
"no UL UP TNL Information in DRBs to be Setup list\n");
|
||||
F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0];
|
||||
F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel;
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address);
|
||||
OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
|
||||
// 3GPP assumes GTP-U is on port 2152, but OAI is configurable
|
||||
drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport;
|
||||
|
||||
switch (drbs_tobesetup_item_p->rLCMode) {
|
||||
case F1AP_RLCMode_rlc_am:
|
||||
drb_p->rlc_mode = F1AP_RLC_MODE_AM;
|
||||
break;
|
||||
case F1AP_RLCMode_rlc_um_bidirectional:
|
||||
drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR;
|
||||
break;
|
||||
default:
|
||||
LOG_W(F1AP, "unsupported RLC Mode %ld received: setting UM bidir\n", drbs_tobesetup_item_p->rLCMode);
|
||||
drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) {
|
||||
AssertFatal(false, "Decode of eUTRANQoS is not implemented yet");
|
||||
} // EUTRAN QoS Information
|
||||
else {
|
||||
/* 12.1.2 DRB_Information */
|
||||
if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) {
|
||||
F1AP_QoSInformation_ExtIEs_t *ie =
|
||||
(F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetup_item_p->qoSInformation.choice.choice_extension;
|
||||
if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject
|
||||
&& ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) {
|
||||
|
||||
const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information;
|
||||
f1ap_drb_information_t *drb_info = &drb_p->drb_info;
|
||||
|
||||
/* QoS-Flow-Level-QoS-Parameters */
|
||||
/* QoS Characteristics*/
|
||||
f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos);
|
||||
|
||||
// 12.1.2.4 flows_Mapped_To_DRB_List
|
||||
drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count;
|
||||
drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t));
|
||||
AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n");
|
||||
f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length);
|
||||
|
||||
/* S-NSSAI */
|
||||
f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SRB */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieSrb;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieSrb, container,
|
||||
F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List, false);
|
||||
|
||||
if(ieSrb != NULL) {
|
||||
f1ap_ue_context_setup_req->srbs_to_be_setup_length = ieSrb->value.choice.SRBs_ToBeSetup_List.list.count;
|
||||
f1ap_ue_context_setup_req->srbs_to_be_setup = calloc(f1ap_ue_context_setup_req->srbs_to_be_setup_length,
|
||||
sizeof(f1ap_srb_to_be_setup_t));
|
||||
AssertFatal(f1ap_ue_context_setup_req->srbs_to_be_setup,
|
||||
"could not allocate memory for f1ap_ue_context_setup_req->srbs_to_be_setup\n");
|
||||
|
||||
for (i = 0; i < f1ap_ue_context_setup_req->srbs_to_be_setup_length; ++i) {
|
||||
f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_setup_req->srbs_to_be_setup[i];
|
||||
F1AP_SRBs_ToBeSetup_Item_t *srbs_tobesetup_item_p;
|
||||
srbs_tobesetup_item_p = &((F1AP_SRBs_ToBeSetup_ItemIEs_t *)ieSrb->value.choice.SRBs_ToBeSetup_List.list.array[i])->value.choice.SRBs_ToBeSetup_Item;
|
||||
srb_p->srb_id = srbs_tobesetup_item_p->sRBID;
|
||||
}
|
||||
}
|
||||
|
||||
/* RRCContainer */
|
||||
F1AP_UEContextSetupRequestIEs_t *ieRRC;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieRRC, container,
|
||||
F1AP_ProtocolIE_ID_id_RRCContainer, false);
|
||||
|
||||
if (ieRRC) {
|
||||
/* correct here */
|
||||
if ( ieRRC->value.choice.RRCContainer.size ) {
|
||||
f1ap_ue_context_setup_req->rrc_container = malloc(ieRRC->value.choice.RRCContainer.size);
|
||||
memcpy(f1ap_ue_context_setup_req->rrc_container,
|
||||
ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size);
|
||||
f1ap_ue_context_setup_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size;
|
||||
} else {
|
||||
LOG_E(F1AP, " RRCContainer in UEContextSetupRequestIEs size id 0\n");
|
||||
}
|
||||
}
|
||||
|
||||
ue_context_setup_request(f1ap_ue_context_setup_req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -893,214 +622,16 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_r
|
||||
|
||||
int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
F1AP_UEContextModificationRequest_t *container;
|
||||
int i;
|
||||
f1ap_ue_context_modif_req_t ue_context_modification = {0};
|
||||
f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req = &ue_context_modification;
|
||||
container = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequest;
|
||||
|
||||
/* mandatory */
|
||||
/* GNB_CU_UE_F1AP_ID */
|
||||
F1AP_UEContextModificationRequestIEs_t *ieCU;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieCU, container,
|
||||
F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
|
||||
f1ap_ue_context_modification_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
|
||||
/* mandatory */
|
||||
/* GNB_DU_UE_F1AP_ID */
|
||||
F1AP_UEContextModificationRequestIEs_t *ieDU_UE;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDU_UE, container,
|
||||
F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true);
|
||||
f1ap_ue_context_modification_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
|
||||
/* SRB */
|
||||
F1AP_UEContextModificationRequestIEs_t *ieSrb;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieSrb, container,
|
||||
F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List, false);
|
||||
|
||||
F1AP_UEContextModificationRequestIEs_t *ieTxInd;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t,
|
||||
ieTxInd,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_TransmissionActionIndicator,
|
||||
false);
|
||||
|
||||
if (ieTxInd != NULL) {
|
||||
f1ap_ue_context_modification_req->transm_action_ind = calloc_or_fail(1, sizeof(*f1ap_ue_context_modification_req->transm_action_ind));
|
||||
*f1ap_ue_context_modification_req->transm_action_ind = ieTxInd->value.choice.TransmissionActionIndicator;
|
||||
// Stop is guaranteed to be 0, by restart might be different from 1
|
||||
static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART,
|
||||
"mismatch of ASN.1 and internal representation\n");
|
||||
f1ap_ue_context_mod_req_t req = {0};
|
||||
if (!decode_ue_context_mod_req(pdu, &req)) {
|
||||
LOG_E(F1AP, "cannot decode F1 UE Context Modification Request\n");
|
||||
free_ue_context_mod_req(&req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ieSrb != NULL) {
|
||||
f1ap_ue_context_modification_req->srbs_to_be_setup_length = ieSrb->value.choice.SRBs_ToBeSetupMod_List.list.count;
|
||||
f1ap_ue_context_modification_req->srbs_to_be_setup = calloc(f1ap_ue_context_modification_req->srbs_to_be_setup_length,
|
||||
sizeof(f1ap_srb_to_be_setup_t));
|
||||
AssertFatal(f1ap_ue_context_modification_req->srbs_to_be_setup,
|
||||
"could not allocate memory for f1ap_ue_context_setup_req->srbs_to_be_setup\n");
|
||||
ue_context_modification_request(&req);
|
||||
free_ue_context_mod_req(&req);
|
||||
|
||||
for (i = 0; i < f1ap_ue_context_modification_req->srbs_to_be_setup_length; ++i) {
|
||||
f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_modification_req->srbs_to_be_setup[i];
|
||||
F1AP_SRBs_ToBeSetupMod_Item_t *srbs_tobesetupmod_item_p;
|
||||
srbs_tobesetupmod_item_p = &((F1AP_SRBs_ToBeSetupMod_ItemIEs_t *)ieSrb->value.choice.SRBs_ToBeSetupMod_List.list.array[i])->value.choice.SRBs_ToBeSetupMod_Item;
|
||||
srb_p->srb_id = srbs_tobesetupmod_item_p->sRBID;
|
||||
}
|
||||
}
|
||||
|
||||
/* DRB */
|
||||
F1AP_UEContextModificationRequestIEs_t *ieDrb;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container,
|
||||
F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List, false);
|
||||
|
||||
if(ieDrb!=NULL) {
|
||||
f1ap_ue_context_modification_req->drbs_to_be_setup_length = ieDrb->value.choice.DRBs_ToBeSetupMod_List.list.count;
|
||||
f1ap_ue_context_modification_req->drbs_to_be_setup = calloc(f1ap_ue_context_modification_req->drbs_to_be_setup_length,
|
||||
sizeof(f1ap_drb_to_be_setup_t));
|
||||
AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_setup,
|
||||
"could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n");
|
||||
|
||||
for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_setup_length; ++i) {
|
||||
f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_modification_req->drbs_to_be_setup[i];
|
||||
F1AP_DRBs_ToBeSetupMod_Item_t *drbs_tobesetupmod_item_p =
|
||||
&((F1AP_DRBs_ToBeSetupMod_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeSetupMod_List.list.array[i])->value.choice.DRBs_ToBeSetupMod_Item;
|
||||
drb_p->drb_id = drbs_tobesetupmod_item_p->dRBID;
|
||||
/* TODO in the following, assume only one UP UL TNL is present.
|
||||
* this matches/assumes OAI CU implementation, can be up to 2! */
|
||||
drb_p->up_ul_tnl_length = 1;
|
||||
AssertFatal(drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0,
|
||||
"no UL UP TNL Information in DRBs to be Setup list\n");
|
||||
F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0];
|
||||
F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel;
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address);
|
||||
OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
|
||||
// 3GPP assumes GTP-U is on port 2152, but OAI is configurable
|
||||
drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport;
|
||||
|
||||
switch (drbs_tobesetupmod_item_p->rLCMode) {
|
||||
case F1AP_RLCMode_rlc_am:
|
||||
drb_p->rlc_mode = F1AP_RLC_MODE_AM;
|
||||
break;
|
||||
case F1AP_RLCMode_rlc_um_bidirectional:
|
||||
drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR;
|
||||
break;
|
||||
default:
|
||||
LOG_W(F1AP, "unsupported RLC Mode %ld received: setting UM bidir\n", drbs_tobesetupmod_item_p->rLCMode);
|
||||
drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (drbs_tobesetupmod_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) {
|
||||
AssertFatal(false, "Decode of eUTRANQoS is not implemented yet");
|
||||
} // EUTRAN QoS Information
|
||||
else {
|
||||
/* 12.1.2 DRB_Information */
|
||||
if (drbs_tobesetupmod_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) {
|
||||
F1AP_QoSInformation_ExtIEs_t *ie =
|
||||
(F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetupmod_item_p->qoSInformation.choice.choice_extension;
|
||||
if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject
|
||||
&& ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) {
|
||||
|
||||
const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information;
|
||||
f1ap_drb_information_t *drb_info = &drb_p->drb_info;
|
||||
|
||||
/* QoS-Flow-Level-QoS-Parameters */
|
||||
/* QoS Characteristics*/
|
||||
f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos);
|
||||
|
||||
// 12.1.2.4 flows_Mapped_To_DRB_List
|
||||
drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count;
|
||||
drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t));
|
||||
AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n");
|
||||
f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length);
|
||||
|
||||
/* S-NSSAI */
|
||||
f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container,
|
||||
F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List, false);
|
||||
if (ieDrb != NULL) {
|
||||
f1ap_ue_context_modification_req->drbs_to_be_released_length = ieDrb->value.choice.DRBs_ToBeReleased_List.list.count;
|
||||
f1ap_ue_context_modification_req->drbs_to_be_released =
|
||||
calloc(f1ap_ue_context_modification_req->drbs_to_be_released_length, sizeof(f1ap_drb_to_be_released_t));
|
||||
AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_released,
|
||||
"could not allocate memory for f1ap_ue_context_released_req->drbs_to_be_released\n");
|
||||
for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; ++i) {
|
||||
F1AP_DRBs_ToBeReleased_ItemIEs_t *tbrel = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeReleased_List.list.array[i];
|
||||
DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item);
|
||||
DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item);
|
||||
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID;
|
||||
}
|
||||
}
|
||||
|
||||
/* RRC Reconfiguration Complete indicator */
|
||||
F1AP_UEContextModificationRequestIEs_t *ieReconf;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieReconf, container,
|
||||
F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator, false);
|
||||
|
||||
if(ieReconf) {
|
||||
switch(ieReconf->value.choice.RRCReconfigurationCompleteIndicator){
|
||||
case F1AP_RRCReconfigurationCompleteIndicator_true:
|
||||
f1ap_ue_context_modification_req->ReconfigComplOutcome = RRCreconf_success;
|
||||
break;
|
||||
|
||||
case F1AP_RRCReconfigurationCompleteIndicator_failure:
|
||||
f1ap_ue_context_modification_req->ReconfigComplOutcome = RRCreconf_failure;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* RRCContainer */
|
||||
F1AP_UEContextModificationRequestIEs_t *ieRRC;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieRRC, container,
|
||||
F1AP_ProtocolIE_ID_id_RRCContainer, false);
|
||||
|
||||
if (ieRRC) {
|
||||
/* correct here */
|
||||
if ( ieRRC->value.choice.RRCContainer.size ) {
|
||||
f1ap_ue_context_modification_req->rrc_container = malloc(ieRRC->value.choice.RRCContainer.size);
|
||||
memcpy(f1ap_ue_context_modification_req->rrc_container,
|
||||
ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size);
|
||||
f1ap_ue_context_modification_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size;
|
||||
} else {
|
||||
LOG_E(F1AP, " RRCContainer in UEContextModificationRequestIEs size id 0\n");
|
||||
}
|
||||
} else {
|
||||
LOG_D(F1AP, "can't find RRCContainer in UEContextModificationRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer);
|
||||
}
|
||||
|
||||
/* CU2DU Information */
|
||||
F1AP_UEContextModificationRequestIEs_t *ieCU2DU = NULL;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t,
|
||||
ieCU2DU,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_CUtoDURRCInformation,
|
||||
false);
|
||||
if (ieCU2DU != NULL) {
|
||||
f1ap_ue_context_modification_req->cu_to_du_rrc_information =
|
||||
calloc(1, sizeof(*f1ap_ue_context_modification_req->cu_to_du_rrc_information));
|
||||
AssertFatal(f1ap_ue_context_modification_req->cu_to_du_rrc_information != NULL, "out of memory\n");
|
||||
cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_modification_req->cu_to_du_rrc_information;
|
||||
const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCU2DU->value.choice.CUtoDURRCInformation;
|
||||
if (cu2duie->cG_ConfigInfo != NULL)
|
||||
LOG_W(F1AP, "UE RNTI %04x: ignoring cg_ConfigInfo, not implemented\n", f1ap_ue_context_modification_req->gNB_DU_ue_id);
|
||||
if (cu2duie->measConfig != NULL)
|
||||
LOG_W(F1AP, "UE RNTI %04x: ignoring measConfig, not implemented\n", f1ap_ue_context_modification_req->gNB_DU_ue_id);
|
||||
if (cu2duie->uE_CapabilityRAT_ContainerList != NULL) {
|
||||
F1AP_UE_CapabilityRAT_ContainerList_t *uecap = cu2duie->uE_CapabilityRAT_ContainerList;
|
||||
cu2du->uE_CapabilityRAT_ContainerList = calloc(uecap->size, sizeof(*cu2du->uE_CapabilityRAT_ContainerList));
|
||||
AssertFatal(cu2du->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n");
|
||||
cu2du->uE_CapabilityRAT_ContainerList_length = uecap->size;
|
||||
memcpy(cu2du->uE_CapabilityRAT_ContainerList, uecap->buf, uecap->size);
|
||||
}
|
||||
}
|
||||
|
||||
ue_context_modification_request(f1ap_ue_context_modification_req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
#include "lib/f1ap_rrc_message_transfer.h"
|
||||
#include "lib/f1ap_interface_management.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
@@ -222,18 +223,18 @@ void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_upd
|
||||
LOG_I(MAC, "received gNB-DU configuration update acknowledge\n");
|
||||
}
|
||||
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb,
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_setup_t *srb,
|
||||
const nr_rlc_configuration_t *rlc_config)
|
||||
{
|
||||
long priority = srb->srb_id == 2 ? 3 : 1; // see 38.331 sec 9.2.1
|
||||
long priority = srb->id == 2 ? 3 : 1; // see 38.331 sec 9.2.1
|
||||
e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucket =
|
||||
NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5;
|
||||
return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->srb_id), priority, bucket, rlc_config);
|
||||
return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->id), priority, bucket, rlc_config);
|
||||
}
|
||||
|
||||
static int handle_ue_context_srbs_setup(NR_UE_info_t *UE,
|
||||
int srbs_len,
|
||||
const f1ap_srb_to_be_setup_t *req_srbs,
|
||||
const f1ap_srb_to_setup_t *req_srbs,
|
||||
f1ap_srb_to_be_setup_t **resp_srbs,
|
||||
NR_CellGroupConfig_t *cellGroupConfig,
|
||||
const nr_rlc_configuration_t *rlc_config)
|
||||
@@ -243,15 +244,15 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE,
|
||||
*resp_srbs = calloc(srbs_len, sizeof(**resp_srbs));
|
||||
AssertFatal(*resp_srbs != NULL, "out of memory\n");
|
||||
for (int i = 0; i < srbs_len; i++) {
|
||||
const f1ap_srb_to_be_setup_t *srb = &req_srbs[i];
|
||||
const f1ap_srb_to_setup_t *srb = &req_srbs[i];
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb, rlc_config);
|
||||
nr_rlc_add_srb(UE->rnti, srb->srb_id, rlc_BearerConfig);
|
||||
nr_rlc_add_srb(UE->rnti, srb->id, rlc_BearerConfig);
|
||||
|
||||
int priority = rlc_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority;
|
||||
nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority};
|
||||
nr_mac_add_lcid(&UE->UE_sched_ctrl, &c);
|
||||
|
||||
(*resp_srbs)[i].srb_id = srb->srb_id;
|
||||
(*resp_srbs)[i].srb_id = srb->id;
|
||||
(*resp_srbs)[i].lcid = c.lcid;
|
||||
|
||||
if (rlc_BearerConfig->logicalChannelIdentity == 1) {
|
||||
@@ -268,12 +269,12 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE,
|
||||
return srbs_len;
|
||||
}
|
||||
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb,
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_setup_t *drb,
|
||||
const nr_rlc_configuration_t *rlc_config)
|
||||
{
|
||||
const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == F1AP_RLC_MODE_AM ? NR_RLC_Config_PR_am : NR_RLC_Config_PR_um_Bi_Directional;
|
||||
long priority = 13; // hardcoded for the moment
|
||||
return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->drb_id), drb->drb_id, rlc_conf, priority, rlc_config);
|
||||
return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->id), drb->id, rlc_conf, priority, rlc_config);
|
||||
}
|
||||
|
||||
static int get_non_dynamic_priority(int fiveqi)
|
||||
@@ -285,20 +286,20 @@ static int get_non_dynamic_priority(int fiveqi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char)
|
||||
static NR_QoS_config_t get_qos_config(const f1ap_qos_flow_param_t *qos)
|
||||
{
|
||||
NR_QoS_config_t qos_c = {0};
|
||||
switch (qos_char->qos_type) {
|
||||
switch (qos->qos_type) {
|
||||
case DYNAMIC:
|
||||
qos_c.priority = qos_char->dynamic.qos_priority_level;
|
||||
qos_c.fiveQI = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0;
|
||||
qos_c.priority = qos->dyn.prio;
|
||||
qos_c.fiveQI = 0; // does not exist for non-dynamic
|
||||
break;
|
||||
case NON_DYNAMIC:
|
||||
qos_c.fiveQI = qos_char->non_dynamic.fiveqi;
|
||||
qos_c.priority = get_non_dynamic_priority(qos_char->non_dynamic.fiveqi);
|
||||
qos_c.fiveQI = qos->nondyn.fiveQI;
|
||||
qos_c.priority = get_non_dynamic_priority(qos_c.fiveQI);
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "illegal QoS type %d\n", qos_char->qos_type);
|
||||
AssertFatal(false, "illegal QoS type %d\n", qos->qos_type);
|
||||
break;
|
||||
}
|
||||
return qos_c;
|
||||
@@ -306,7 +307,7 @@ static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char
|
||||
|
||||
static int handle_ue_context_drbs_setup(NR_UE_info_t *UE,
|
||||
int drbs_len,
|
||||
const f1ap_drb_to_be_setup_t *req_drbs,
|
||||
const f1ap_drb_to_setup_t *req_drbs,
|
||||
f1ap_drb_to_be_setup_t **resp_drbs,
|
||||
NR_CellGroupConfig_t *cellGroupConfig,
|
||||
const nr_rlc_configuration_t *rlc_config)
|
||||
@@ -319,32 +320,34 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE,
|
||||
*resp_drbs = calloc(drbs_len, sizeof(**resp_drbs));
|
||||
AssertFatal(*resp_drbs != NULL, "out of memory\n");
|
||||
for (int i = 0; i < drbs_len; i++) {
|
||||
const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
|
||||
const f1ap_drb_to_setup_t *drb = &req_drbs[i];
|
||||
AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS supported\n");
|
||||
f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i];
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb, rlc_config);
|
||||
nr_rlc_add_drb(UE->rnti, drb->drb_id, rlc_BearerConfig);
|
||||
nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig);
|
||||
|
||||
nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nssai};
|
||||
nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nr.nssai};
|
||||
int prio = 100;
|
||||
for (int q = 0; q < drb->drb_info.flows_to_be_setup_length; ++q) {
|
||||
c.qos_config[q] = get_qos_config(&drb->drb_info.flows_mapped_to_drb[q].qos_params.qos_characteristics);
|
||||
for (int q = 0; q < drb->nr.flows_len; ++q) {
|
||||
c.qos_config[q] = get_qos_config(&drb->nr.flows[q].param);
|
||||
prio = min(prio, c.qos_config[q].priority);
|
||||
}
|
||||
c.priority = prio;
|
||||
nr_mac_add_lcid(&UE->UE_sched_ctrl, &c);
|
||||
|
||||
*resp_drb = *drb;
|
||||
resp_drb->drb_id = drb->id;
|
||||
// TODO lcid
|
||||
// just put same number of tunnels in DL as in UL
|
||||
DevAssert(drb->up_ul_tnl_length == 1);
|
||||
resp_drb->up_dl_tnl_length = drb->up_ul_tnl_length;
|
||||
DevAssert(drb->up_ul_tnl_len == 1);
|
||||
resp_drb->up_dl_tnl_length = drb->up_ul_tnl_len;
|
||||
|
||||
if (f1inst >= 0) { // we actually use F1-U
|
||||
int qfi = -1; // don't put PDU session marker in GTP
|
||||
gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0};
|
||||
int ret = drb_gtpu_create(f1inst,
|
||||
UE->rnti,
|
||||
drb->drb_id,
|
||||
drb->drb_id,
|
||||
drb->id,
|
||||
drb->id,
|
||||
qfi,
|
||||
drb->up_ul_tnl[0].tl_address,
|
||||
drb->up_ul_tnl[0].teid,
|
||||
@@ -366,7 +369,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE,
|
||||
|
||||
static int handle_ue_context_drbs_release(NR_UE_info_t *UE,
|
||||
int drbs_len,
|
||||
const f1ap_drb_to_be_released_t *req_drbs,
|
||||
const f1ap_drb_to_release_t *req_drbs,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
{
|
||||
DevAssert(req_drbs != NULL && cellGroupConfig != NULL);
|
||||
@@ -378,9 +381,9 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE,
|
||||
/* Note: the actual GTP tunnels are already removed in the F1AP message
|
||||
* decoding */
|
||||
for (int i = 0; i < drbs_len; i++) {
|
||||
const f1ap_drb_to_be_released_t *drb = &req_drbs[i];
|
||||
const f1ap_drb_to_release_t *drb = &req_drbs[i];
|
||||
|
||||
long lcid = get_lcid_from_drbid(drb->rb_id);
|
||||
long lcid = get_lcid_from_drbid(drb->id);
|
||||
int idx = 0;
|
||||
while (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
|
||||
const NR_RLC_BearerConfig_t *bc = cellGroupConfig->rlc_BearerToAddModList->list.array[idx];
|
||||
@@ -392,7 +395,7 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE,
|
||||
nr_mac_remove_lcid(&UE->UE_sched_ctrl, lcid);
|
||||
nr_rlc_release_entity(UE->rnti, lcid);
|
||||
if (f1inst >= 0)
|
||||
newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->rb_id);
|
||||
newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->id);
|
||||
asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1);
|
||||
long *plcid = malloc(sizeof(*plcid));
|
||||
AssertFatal(plcid, "out of memory\n");
|
||||
@@ -600,34 +603,30 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
|
||||
return UE;
|
||||
}
|
||||
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req)
|
||||
{
|
||||
const bool is_SA = IS_SA_MODE(get_softmodem_params());
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
/* response has same type as request... */
|
||||
|
||||
/* TODO: update response */
|
||||
f1ap_ue_context_setup_t resp = {
|
||||
.gNB_CU_ue_id = req->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = req->gNB_DU_ue_id,
|
||||
};
|
||||
|
||||
/* gNB-DU UE ID is optional. As of now, the F1AP module fills -1 (on uint, so
|
||||
* 0xffffffff), but the DU uses the RNTI, so check if it's a legal RNTI in
|
||||
* which case we consider; if not, assume no DU UE ID given */
|
||||
bool ue_id_provided = resp.gNB_DU_ue_id > 0 && resp.gNB_DU_ue_id < 0xffff;
|
||||
bool ue_id_provided = req->gNB_DU_ue_id != NULL;
|
||||
|
||||
NR_UE_NR_Capability_t *ue_cap = NULL;
|
||||
const f1ap_cu_to_du_rrc_info_t *cu2du = &req->cu_to_du_rrc_info;
|
||||
NR_CG_ConfigInfo_t *cg_configinfo = NULL;
|
||||
if (req->cu_to_du_rrc_information != NULL) {
|
||||
const cu_to_du_rrc_information_t *cu2du = req->cu_to_du_rrc_information;
|
||||
if (cu2du->cG_ConfigInfo != NULL)
|
||||
cg_configinfo = get_cg_config_info(cu2du->cG_ConfigInfo, cu2du->cG_ConfigInfo_length);
|
||||
if (cu2du->handoverPreparationInfo != NULL) {
|
||||
ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->handoverPreparationInfo, cu2du->handoverPreparationInfo_length);
|
||||
} else if (cu2du->uE_CapabilityRAT_ContainerList != NULL) {
|
||||
ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, cu2du->uE_CapabilityRAT_ContainerList, cu2du->uE_CapabilityRAT_ContainerList_length);
|
||||
}
|
||||
AssertFatal(cu2du->measConfig == NULL, "MeasConfig not handled\n");
|
||||
if (cu2du->cg_configinfo != NULL)
|
||||
cg_configinfo = get_cg_config_info(cu2du->cg_configinfo->buf, cu2du->cg_configinfo->len);
|
||||
NR_UE_NR_Capability_t *ue_cap = NULL;
|
||||
if (cu2du->ho_prep_info != NULL) {
|
||||
ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->ho_prep_info->buf, cu2du->ho_prep_info->len);
|
||||
} else if (cu2du->ue_cap != NULL) {
|
||||
ue_cap = get_ue_nr_cap(*req->gNB_DU_ue_id, cu2du->ue_cap->buf, cu2du->ue_cap->len);
|
||||
}
|
||||
AssertFatal(cu2du->meas_config == NULL, "MeasConfig not handled\n");
|
||||
|
||||
/* 38.473: "For DC operation, the CG-ConfigInfo IE shall be included in the CU
|
||||
* to DU RRC Information IE at the gNB acting as secondary node" As of now,
|
||||
* we only handle NSA => we check we have CG-ConfigInfo if not SA or have SA
|
||||
@@ -643,25 +642,26 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
resp.crnti = &UE->rnti;
|
||||
} else {
|
||||
DevAssert(is_SA);
|
||||
UE = find_nr_UE(&mac->UE_info, req->gNB_DU_ue_id);
|
||||
UE = find_nr_UE(&mac->UE_info, *req->gNB_DU_ue_id);
|
||||
}
|
||||
AssertFatal(UE, "no UE found or could not be created, but UE Context Setup Failed not implemented\n");
|
||||
resp.gNB_DU_ue_id = UE->rnti;
|
||||
|
||||
NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup);
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0) {
|
||||
if (req->srbs_len > 0) {
|
||||
resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE,
|
||||
req->srbs_to_be_setup_length,
|
||||
req->srbs_to_be_setup,
|
||||
req->srbs_len,
|
||||
req->srbs,
|
||||
&resp.srbs_to_be_setup,
|
||||
new_CellGroup,
|
||||
&mac->rlc_config);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
if (req->drbs_len > 0) {
|
||||
resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE,
|
||||
req->drbs_to_be_setup_length,
|
||||
req->drbs_to_be_setup,
|
||||
req->drbs_len,
|
||||
req->drbs,
|
||||
&resp.drbs_to_be_setup,
|
||||
new_CellGroup,
|
||||
&mac->rlc_config);
|
||||
@@ -669,7 +669,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
|
||||
if (req->rrc_container != NULL) {
|
||||
logical_chan_id_t id = 1;
|
||||
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length);
|
||||
nr_rlc_srb_recv_sdu(UE->rnti, id, req->rrc_container->buf, req->rrc_container->len);
|
||||
}
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
@@ -722,7 +722,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
free(resp.du_to_cu_rrc_information);
|
||||
}
|
||||
|
||||
void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req)
|
||||
{
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
f1ap_ue_context_modif_resp_t resp = {
|
||||
@@ -731,12 +731,13 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
};
|
||||
|
||||
NR_UE_NR_Capability_t *ue_cap = NULL;
|
||||
if (req->cu_to_du_rrc_information != NULL) {
|
||||
AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
|
||||
ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id,
|
||||
req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList,
|
||||
req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length);
|
||||
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n");
|
||||
if (req->cu_to_du_rrc_info != NULL) {
|
||||
AssertFatal(req->cu_to_du_rrc_info->cg_configinfo == NULL, "CG-ConfigInfo not handled\n");
|
||||
if (req->cu_to_du_rrc_info->ue_cap) {
|
||||
byte_array_t *b = req->cu_to_du_rrc_info->ue_cap;
|
||||
ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, b->buf, b->len);
|
||||
}
|
||||
AssertFatal(req->cu_to_du_rrc_info->meas_config == NULL, "MeasConfig not handled\n");
|
||||
}
|
||||
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
@@ -749,39 +750,38 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
|
||||
NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup);
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0) {
|
||||
if (req->srbs_len > 0) {
|
||||
resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE,
|
||||
req->srbs_to_be_setup_length,
|
||||
req->srbs_to_be_setup,
|
||||
req->srbs_len,
|
||||
req->srbs,
|
||||
&resp.srbs_to_be_setup,
|
||||
new_CellGroup,
|
||||
&mac->rlc_config);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
if (req->drbs_len > 0) {
|
||||
resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE,
|
||||
req->drbs_to_be_setup_length,
|
||||
req->drbs_to_be_setup,
|
||||
req->drbs_len,
|
||||
req->drbs,
|
||||
&resp.drbs_to_be_setup,
|
||||
new_CellGroup,
|
||||
&mac->rlc_config);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_released_length > 0) {
|
||||
resp.drbs_to_be_released_length =
|
||||
handle_ue_context_drbs_release(UE, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup);
|
||||
if (req->drbs_rel_len > 0) {
|
||||
resp.drbs_to_be_released_length = handle_ue_context_drbs_release(UE, req->drbs_rel_len, req->drbs_rel, new_CellGroup);
|
||||
}
|
||||
|
||||
if (req->rrc_container != NULL) {
|
||||
logical_chan_id_t id = 1;
|
||||
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length);
|
||||
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container->buf, req->rrc_container->len);
|
||||
}
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) {
|
||||
if (req->reconfig_compl && *req->reconfig_compl != RRCreconf_success) {
|
||||
LOG_E(NR_MAC,
|
||||
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
|
||||
} else if (req->ReconfigComplOutcome == RRCreconf_success) {
|
||||
} else if (req->reconfig_compl) {
|
||||
LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n");
|
||||
if (UE->reconfigSpCellConfig) {
|
||||
// in case of reestablishment, the spCellConfig had to be released
|
||||
@@ -807,8 +807,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
|
||||
}
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0
|
||||
|| ue_cap != NULL) {
|
||||
if (req->srbs_len > 0 || req->drbs_len > 0 || req->drbs_rel_len > 0 || ue_cap != NULL) {
|
||||
resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t));
|
||||
AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024);
|
||||
|
||||
@@ -32,8 +32,8 @@ void f1_setup_response(const f1ap_setup_resp_t *resp);
|
||||
void f1_setup_failure(const f1ap_setup_failure_t *failure);
|
||||
void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack);
|
||||
NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig);
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_t *req);
|
||||
void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req);
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req);
|
||||
void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req);
|
||||
void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm);
|
||||
void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse);
|
||||
void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd);
|
||||
|
||||
@@ -33,8 +33,8 @@ typedef void (*f1_setup_failure_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_
|
||||
typedef void (*gnb_du_configuration_update_ack_func_t)(sctp_assoc_t assoc_id,
|
||||
const f1ap_gnb_du_configuration_update_acknowledge_t *ack);
|
||||
|
||||
typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req);
|
||||
typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req);
|
||||
typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req);
|
||||
typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req);
|
||||
typedef void (*ue_context_modification_confirm_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_confirm_t *confirm);
|
||||
typedef void (*ue_context_modification_refuse_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_refuse_t *refuse);
|
||||
typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd);
|
||||
|
||||
@@ -58,13 +58,13 @@ static void gnb_du_configuration_update_ack_direct(sctp_assoc_t assoc_id, const
|
||||
gnb_du_configuration_update_acknowledge(ack);
|
||||
}
|
||||
|
||||
static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req)
|
||||
static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req)
|
||||
{
|
||||
AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id);
|
||||
ue_context_setup_request(req);
|
||||
}
|
||||
|
||||
static void ue_context_modification_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req)
|
||||
static void ue_context_modification_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req)
|
||||
{
|
||||
AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id);
|
||||
ue_context_modification_request(req);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "nr_rrc_defs.h"
|
||||
#include "lib/f1ap_rrc_message_transfer.h"
|
||||
#include "lib/f1ap_interface_management.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
|
||||
static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset)
|
||||
{
|
||||
@@ -75,116 +76,19 @@ static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req)
|
||||
static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ);
|
||||
msg->ittiMsgHeader.originInstance = assoc_id;
|
||||
f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg);
|
||||
*f1ap_msg = *req;
|
||||
if (req->cu_to_du_rrc_information != NULL) {
|
||||
f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information));
|
||||
AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n");
|
||||
const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information;
|
||||
if (req->cu_to_du_rrc_information->cG_ConfigInfo != NULL) {
|
||||
cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information;
|
||||
du2cu_new->cG_ConfigInfo_length = du2cu_req->cG_ConfigInfo_length;
|
||||
du2cu_new->cG_ConfigInfo = malloc_or_fail(du2cu_new->cG_ConfigInfo_length);
|
||||
memcpy(du2cu_new->cG_ConfigInfo, du2cu_req->cG_ConfigInfo, du2cu_new->cG_ConfigInfo_length);
|
||||
}
|
||||
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n");
|
||||
if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) {
|
||||
cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information;
|
||||
DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0);
|
||||
du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length;
|
||||
du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length);
|
||||
AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n");
|
||||
memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length);
|
||||
}
|
||||
if (req->cu_to_du_rrc_information->handoverPreparationInfo != NULL) {
|
||||
cu_to_du_rrc_information_t *du2cu_new = f1ap_msg->cu_to_du_rrc_information;
|
||||
DevAssert(du2cu_req->handoverPreparationInfo_length > 0);
|
||||
du2cu_new->handoverPreparationInfo_length = du2cu_req->handoverPreparationInfo_length;
|
||||
du2cu_new->handoverPreparationInfo = malloc_or_fail(du2cu_new->handoverPreparationInfo_length);
|
||||
memcpy(du2cu_new->handoverPreparationInfo, du2cu_req->handoverPreparationInfo, du2cu_new->handoverPreparationInfo_length);
|
||||
}
|
||||
}
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
int n = req->drbs_to_be_setup_length;
|
||||
f1ap_msg->drbs_to_be_setup_length = n;
|
||||
f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n");
|
||||
memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
}
|
||||
if (req->srbs_to_be_setup_length > 0) {
|
||||
int n = req->srbs_to_be_setup_length;
|
||||
f1ap_msg->srbs_to_be_setup_length = n;
|
||||
f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup));
|
||||
AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n");
|
||||
memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup));
|
||||
}
|
||||
if (req->rrc_container_length > 0) {
|
||||
f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container));
|
||||
AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n");
|
||||
f1ap_msg->rrc_container_length = req->rrc_container_length;
|
||||
memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length);
|
||||
}
|
||||
F1AP_UE_CONTEXT_SETUP_REQ(msg) = cp_ue_context_setup_req(req);
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_modification_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req)
|
||||
static void ue_context_modification_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ);
|
||||
msg->ittiMsgHeader.originInstance = assoc_id;
|
||||
f1ap_ue_context_modif_req_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQ(msg);
|
||||
*f1ap_msg = *req;
|
||||
if (req->cu_to_du_rrc_information != NULL) {
|
||||
f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information));
|
||||
AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n");
|
||||
AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL && req->cu_to_du_rrc_information->cG_ConfigInfo_length == 0, "cg_ConfigInfo not implemented\n");
|
||||
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n");
|
||||
if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) {
|
||||
const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information;
|
||||
cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information;
|
||||
DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0);
|
||||
du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length;
|
||||
du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length);
|
||||
AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n");
|
||||
memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length);
|
||||
}
|
||||
}
|
||||
AssertFatal(req->drbs_to_be_modified_length == 0, "drbs_to_be_modified not supported yet\n");
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
int n = req->drbs_to_be_setup_length;
|
||||
f1ap_msg->drbs_to_be_setup_length = n;
|
||||
f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n");
|
||||
memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
}
|
||||
if (req->srbs_to_be_setup_length > 0) {
|
||||
int n = req->srbs_to_be_setup_length;
|
||||
f1ap_msg->srbs_to_be_setup_length = n;
|
||||
f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup));
|
||||
AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n");
|
||||
memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup));
|
||||
}
|
||||
if (req->drbs_to_be_released_length > 0) {
|
||||
int n = req->drbs_to_be_released_length;
|
||||
f1ap_msg->drbs_to_be_released_length = n;
|
||||
f1ap_msg->drbs_to_be_released = calloc(n, sizeof(*f1ap_msg->drbs_to_be_released));
|
||||
AssertFatal(f1ap_msg->drbs_to_be_released != NULL, "out of memory\n");
|
||||
memcpy(f1ap_msg->drbs_to_be_released, req->drbs_to_be_released, n * sizeof(*f1ap_msg->drbs_to_be_released));
|
||||
}
|
||||
if (req->rrc_container_length > 0) {
|
||||
f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container));
|
||||
AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n");
|
||||
f1ap_msg->rrc_container_length = req->rrc_container_length;
|
||||
memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length);
|
||||
}
|
||||
if (req->transm_action_ind != NULL) {
|
||||
f1ap_msg->transm_action_ind = malloc(sizeof *f1ap_msg->transm_action_ind);
|
||||
AssertFatal(f1ap_msg->transm_action_ind != NULL, "out of memory\n");
|
||||
*f1ap_msg->transm_action_ind = *req->transm_action_ind;
|
||||
}
|
||||
F1AP_UE_CONTEXT_MODIFICATION_REQ(msg) = cp_ue_context_mod_req(req);
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,14 +107,14 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint3
|
||||
void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
int n_drbs,
|
||||
const f1ap_drb_to_be_setup_t *drbs);
|
||||
const f1ap_drb_to_setup_t *drbs);
|
||||
|
||||
void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
int n_drbs,
|
||||
const f1ap_drb_to_be_setup_t *drbs,
|
||||
const f1ap_drb_to_setup_t *drbs,
|
||||
int n_rel_drbs,
|
||||
const f1ap_drb_to_be_released_t *rel_drbs);
|
||||
const f1ap_drb_to_release_t *rel_drbs);
|
||||
|
||||
void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params);
|
||||
|
||||
@@ -123,6 +123,6 @@ byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t *
|
||||
nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish);
|
||||
|
||||
pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession);
|
||||
f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param);
|
||||
f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param);
|
||||
void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration);
|
||||
#endif
|
||||
|
||||
+83
-61
@@ -80,6 +80,7 @@
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h"
|
||||
#include "openair2/F1AP/lib/f1ap_interface_management.h"
|
||||
#include "openair2/F1AP/lib/f1ap_ue_context.h"
|
||||
#include "rrc_gNB_NGAP.h"
|
||||
#include "rrc_gNB_du.h"
|
||||
#include "rrc_gNB_mobility.h"
|
||||
@@ -1774,12 +1775,14 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U
|
||||
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_ue_context_modif_req_t ue_context_modif_req = {
|
||||
ReconfigurationCompl_t rc = RRCreconf_success;
|
||||
f1ap_ue_context_mod_req_t req = {
|
||||
.gNB_CU_ue_id = UE->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.ReconfigComplOutcome = RRCreconf_success,
|
||||
.reconfig_compl = &rc,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req);
|
||||
rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &req);
|
||||
/* nothing to be freed */
|
||||
}
|
||||
|
||||
static void rrc_gNB_generate_UECapabilityEnquiry(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue)
|
||||
@@ -2364,18 +2367,26 @@ pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu
|
||||
}
|
||||
|
||||
/* \bref return F1AP QoS characteristics based on Qos flow parameters */
|
||||
f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param)
|
||||
f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param)
|
||||
{
|
||||
f1ap_qos_characteristics_t qos_char = {0};
|
||||
f1ap_qos_flow_param_t qos_char = {0};
|
||||
if (qos_param->fiveQI_type == DYNAMIC) {
|
||||
qos_char.qos_type = DYNAMIC;
|
||||
qos_char.dynamic.fiveqi = qos_param->fiveQI;
|
||||
qos_char.dynamic.qos_priority_level = qos_param->qos_priority;
|
||||
qos_char.dyn.prio = qos_param->qos_priority;
|
||||
qos_char.dyn.pdb = 100; // TODO
|
||||
qos_char.dyn.per.scalar = 10; // TODO
|
||||
qos_char.dyn.per.exponent = 100; // TODO
|
||||
} else {
|
||||
qos_char.qos_type = NON_DYNAMIC;
|
||||
qos_char.non_dynamic.fiveqi = qos_param->fiveQI;
|
||||
qos_char.non_dynamic.qos_priority_level = qos_param->qos_priority;
|
||||
qos_char.nondyn.fiveQI = qos_param->fiveQI;
|
||||
}
|
||||
const ngap_allocation_retention_priority_t *a = &qos_param->allocation_retention_priority;
|
||||
qos_char.arp.prio = a->priority_level;
|
||||
qos_char.arp.preempt_cap = a->pre_emp_capability == NGAP_PRE_EMPTION_CAPABILITY_MAY_TRIGGER_PREEMPTION
|
||||
? MAY_TRIGGER_PREEMPTION
|
||||
: SHALL_NOT_TRIGGER_PREEMPTION;
|
||||
qos_char.arp.preempt_vuln =
|
||||
a->pre_emp_vulnerability == NGAP_PRE_EMPTION_VULNERABILITY_PREEMPTABLE ? PREEMPTABLE : NOT_PREEMPTABLE;
|
||||
return qos_char;
|
||||
}
|
||||
|
||||
@@ -2385,38 +2396,52 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc,
|
||||
gNB_RRC_UE_t *UE,
|
||||
const pdu_session_setup_t *pduSession,
|
||||
int numPduSession,
|
||||
f1ap_drb_to_be_setup_t drbs[32])
|
||||
f1ap_drb_to_setup_t drbs[32])
|
||||
{
|
||||
int nb_drb = 0;
|
||||
for (int p = 0; p < numPduSession; ++p) {
|
||||
rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, pduSession[p].id, false);
|
||||
DevAssert(RRC_pduSession);
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession(UE, pduSession[p].id, false);
|
||||
DevAssert(pdu);
|
||||
for (int i = 0; i < pduSession[p].numDRBSetup; i++) {
|
||||
const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i];
|
||||
f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
|
||||
drb->drb_id = pduSession[p].DRBnGRanList[i].id;
|
||||
drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM;
|
||||
drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress;
|
||||
drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
|
||||
drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId;
|
||||
drb->up_ul_tnl_length = 1;
|
||||
drb_t *rrc_drb = get_drb(UE, pduSession[p].DRBnGRanList[i].id);
|
||||
DevAssert(rrc_drb);
|
||||
|
||||
f1ap_drb_to_setup_t *drb = &drbs[nb_drb];
|
||||
drb->id = rrc_drb->drb_id;
|
||||
|
||||
drb->qos_choice = F1AP_QOS_CHOICE_NR;
|
||||
|
||||
/* pass QoS info to MAC */
|
||||
int nb_qos_flows = drb_config->numQosFlowSetup;
|
||||
AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n");
|
||||
drb->drb_info.flows_to_be_setup_length = nb_qos_flows;
|
||||
drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t));
|
||||
AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n");
|
||||
drb->nr.flows_len = nb_qos_flows;
|
||||
drb->nr.flows = calloc_or_fail(nb_qos_flows, sizeof(*drb->nr.flows));
|
||||
for (int j = 0; j < nb_qos_flows; j++) {
|
||||
drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi;
|
||||
pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession);
|
||||
drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char);
|
||||
int qfi = drb_config->qosFlows[j].qfi;
|
||||
/* find the QoS characteristics stored at RRC based on QFI returned
|
||||
* from E1. We expect this to correspond to a QFI we passed to E1
|
||||
* previously, so we expect it to exist. */
|
||||
pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu);
|
||||
DevAssert(qos_param);
|
||||
f1ap_drb_flows_mapped_t *flow = &drb->nr.flows[j];
|
||||
flow->qfi = qfi;
|
||||
flow->param = get_qos_char_from_qos_flow_param(qos_param);
|
||||
}
|
||||
/* the DRB QoS parameters: we just reuse the ones from the first flow */
|
||||
drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params;
|
||||
drb->nr.drb_qos = drb->nr.flows[0].param;
|
||||
|
||||
/* pass NSSAI info to MAC */
|
||||
drb->nssai = RRC_pduSession->param.nssai;
|
||||
drb->nr.nssai = pdu->param.nssai;
|
||||
|
||||
drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress;
|
||||
drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId;
|
||||
drb->up_ul_tnl_len = 1;
|
||||
drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM;
|
||||
drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len));
|
||||
*drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;
|
||||
drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len));
|
||||
*drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;
|
||||
|
||||
nb_drb++;
|
||||
}
|
||||
@@ -2463,7 +2488,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
|
||||
}
|
||||
|
||||
/* Instruction towards the DU for DRB configuration and tunnel creation */
|
||||
f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32
|
||||
f1ap_drb_to_setup_t drbs[32]; // maximum DRB can be 32
|
||||
int nb_drb = fill_drb_to_be_setup_from_e1_resp(rrc, UE, resp->pduSession, resp->numPDUSessions, drbs);
|
||||
|
||||
if (!UE->f1_ue_context_active)
|
||||
@@ -3001,7 +3026,7 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint
|
||||
void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
int n_drbs,
|
||||
const f1ap_drb_to_be_setup_t *drbs)
|
||||
const f1ap_drb_to_setup_t *drbs)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
@@ -3009,47 +3034,51 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc,
|
||||
|
||||
AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n");
|
||||
|
||||
cu_to_du_rrc_information_t cu2du = {0};
|
||||
cu_to_du_rrc_information_t *cu2du_p = NULL;
|
||||
f1ap_cu_to_du_rrc_info_t cu2du = {0};
|
||||
if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) {
|
||||
cu2du_p = &cu2du;
|
||||
cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf;
|
||||
cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len;
|
||||
cu2du.ue_cap = &ue_p->ue_cap_buffer;
|
||||
}
|
||||
|
||||
int nb_srb = 1;
|
||||
f1ap_srb_to_be_setup_t srbs[1] = {{.srb_id = 2, .lcid = 2}};
|
||||
f1ap_srb_to_setup_t srbs[1] = {{.id = 2, }};
|
||||
activate_srb(ue_p, 2);
|
||||
|
||||
/* gNB-DU UE Aggregate Maximum Bit Rate Uplink is C- ifDRBSetup */
|
||||
uint64_t agg_mbr = 1000000000 /* bps */, *agg_mbr_p = NULL;
|
||||
if (n_drbs > 0)
|
||||
agg_mbr_p = &agg_mbr;
|
||||
|
||||
/* the callback will fill the UE context setup request and forward it */
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_ue_context_setup_t ue_context_setup_req = {
|
||||
f1ap_ue_context_setup_req_t ue_context_setup_req = {
|
||||
.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.gNB_DU_ue_id = &ue_data.secondary_ue,
|
||||
.plmn.mcc = rrc->configuration.plmn[0].mcc,
|
||||
.plmn.mnc = rrc->configuration.plmn[0].mnc,
|
||||
.plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length,
|
||||
.nr_cellid = rrc->nr_cellid,
|
||||
.servCellId = 0, /* TODO: correct value? */
|
||||
.srbs_to_be_setup_length = nb_srb,
|
||||
.srbs_to_be_setup = srbs,
|
||||
.drbs_to_be_setup_length = n_drbs,
|
||||
.drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs,
|
||||
.cu_to_du_rrc_information = cu2du_p,
|
||||
.servCellIndex = 0, /* TODO: correct value? */
|
||||
.srbs_len = nb_srb,
|
||||
.srbs = srbs,
|
||||
.drbs_len = n_drbs,
|
||||
.drbs = (f1ap_drb_to_setup_t *) drbs, // cast to avoid warning on const
|
||||
.cu_to_du_rrc_info = cu2du,
|
||||
.gnb_du_ue_agg_mbr_ul = agg_mbr_p,
|
||||
};
|
||||
|
||||
rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &ue_context_setup_req);
|
||||
LOG_I(RRC, "UE %d trigger UE context setup request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs);
|
||||
// nothing to free for ue_context_setup_req
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
int n_drbs,
|
||||
const f1ap_drb_to_be_setup_t *drbs,
|
||||
const f1ap_drb_to_setup_t *drbs,
|
||||
int n_rel_drbs,
|
||||
const f1ap_drb_to_be_released_t *rel_drbs)
|
||||
const f1ap_drb_to_release_t *rel_drbs)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
@@ -3058,30 +3087,23 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc,
|
||||
|
||||
AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n");
|
||||
|
||||
cu_to_du_rrc_information_t cu2du = {0};
|
||||
cu_to_du_rrc_information_t *cu2du_p = NULL;
|
||||
f1ap_cu_to_du_rrc_info_t cu2du = {0};
|
||||
if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) {
|
||||
cu2du_p = &cu2du;
|
||||
cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf;
|
||||
cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len;
|
||||
cu2du.ue_cap = &ue_p->ue_cap_buffer;
|
||||
}
|
||||
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_ue_context_modif_req_t ue_context_modif_req = {
|
||||
f1ap_ue_context_mod_req_t ue_context_modif_req = {
|
||||
.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.plmn.mcc = rrc->configuration.plmn[0].mcc,
|
||||
.plmn.mnc = rrc->configuration.plmn[0].mnc,
|
||||
.plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length,
|
||||
.nr_cellid = rrc->nr_cellid,
|
||||
.servCellId = 0, /* TODO: correct value? */
|
||||
.drbs_to_be_setup_length = n_drbs,
|
||||
.drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs,
|
||||
.drbs_to_be_released_length = n_rel_drbs,
|
||||
.drbs_to_be_released = (f1ap_drb_to_be_released_t *)rel_drbs,
|
||||
.cu_to_du_rrc_information = cu2du_p,
|
||||
.drbs_len = n_drbs,
|
||||
.drbs = (f1ap_drb_to_setup_t *)drbs,
|
||||
.drbs_rel_len = n_rel_drbs,
|
||||
.drbs_rel = (f1ap_drb_to_release_t *)rel_drbs,
|
||||
.cu_to_du_rrc_info = &cu2du,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req);
|
||||
LOG_I(RRC, "UE %d trigger UE context modification request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs);
|
||||
// nothing to free
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "rrc_gNB_UE_context.h"
|
||||
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "openair2/F1AP/lib/f1ap_ue_context.h"
|
||||
#include "MESSAGES/asn1_msg.h"
|
||||
#include "nr_pdcp/nr_pdcp_oai_api.h"
|
||||
#include "openair3/SECU/key_nas_deriver.h"
|
||||
@@ -61,7 +62,7 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx)
|
||||
free(ho_ctx);
|
||||
}
|
||||
|
||||
static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE])
|
||||
static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE])
|
||||
{
|
||||
int nb_drb = 0;
|
||||
for (int i = 0; i < MAX_DRBS_PER_UE; ++i) {
|
||||
@@ -69,34 +70,38 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_
|
||||
if (rrc_drb->status == DRB_INACTIVE)
|
||||
continue;
|
||||
|
||||
f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
|
||||
f1ap_drb_to_setup_t *drb = &drbs[nb_drb];
|
||||
nb_drb++;
|
||||
drb->drb_id = rrc_drb->drb_id;
|
||||
drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM;
|
||||
memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4);
|
||||
drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
|
||||
drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid;
|
||||
drb->up_ul_tnl_length = 1;
|
||||
|
||||
/* fetch an existing PDU session for this DRB */
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, drb->drb_id);
|
||||
AssertFatal(pdu != NULL, "no PDU session for DRB ID %ld\n", drb->drb_id);
|
||||
drb->nssai = pdu->param.nssai;
|
||||
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id);
|
||||
AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id);
|
||||
// for the moment, we only support one QoS flow. Put a reminder in case
|
||||
// this changes
|
||||
AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n");
|
||||
drb->drb_info.flows_to_be_setup_length = 1;
|
||||
drb->drb_info.flows_mapped_to_drb = calloc_or_fail(1, sizeof(drb->drb_info.flows_mapped_to_drb[0]));
|
||||
AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n");
|
||||
int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0];
|
||||
DevAssert(qfi > 0);
|
||||
drb->drb_info.flows_mapped_to_drb[0].qfi = qfi;
|
||||
pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(qfi, pdu);
|
||||
drb->drb_info.flows_mapped_to_drb[0].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char);
|
||||
pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu);
|
||||
|
||||
drb->id = rrc_drb->drb_id;
|
||||
|
||||
drb->qos_choice = F1AP_QOS_CHOICE_NR;
|
||||
drb->nr.nssai = pdu->param.nssai;
|
||||
drb->nr.flows_len = 1;
|
||||
drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows));
|
||||
DevAssert(qfi > 0);
|
||||
drb->nr.flows[0].qfi = qfi;
|
||||
drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(qos_param);
|
||||
/* the DRB QoS parameters: we just reuse the ones from the first flow */
|
||||
drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params;
|
||||
drb->nr.drb_qos = drb->nr.flows[0].param;
|
||||
|
||||
memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4);
|
||||
drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid;
|
||||
drb->up_ul_tnl_len = 1;
|
||||
|
||||
drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM;
|
||||
drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len));
|
||||
*drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;
|
||||
drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len));
|
||||
*drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;;
|
||||
}
|
||||
return nb_drb;
|
||||
}
|
||||
@@ -168,32 +173,38 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc,
|
||||
target_du->assoc_id,
|
||||
target_du->setup_req->cell[0].info.nr_pci);
|
||||
|
||||
cu_to_du_rrc_information_t cu2du = {
|
||||
.handoverPreparationInfo = ho_prep_info->buf,
|
||||
.handoverPreparationInfo_length = ho_prep_info->len,
|
||||
};
|
||||
|
||||
f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE] = {0};
|
||||
f1ap_drb_to_setup_t *drbs = calloc_or_fail(MAX_DRBS_PER_UE, sizeof(*drbs));
|
||||
int nb_drb = fill_drb_to_be_setup(rrc, ue, drbs);
|
||||
|
||||
f1ap_srb_to_be_setup_t srbs[2] = {{.srb_id = 1, .lcid = 1}, {.srb_id = 2, .lcid = 2}};
|
||||
int nb_srb = 2;
|
||||
f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs));
|
||||
srbs[0].id = 1;
|
||||
srbs[1].id = 2;
|
||||
|
||||
byte_array_t *hpi = malloc_or_fail(sizeof(*hpi));
|
||||
*hpi = copy_byte_array(*ho_prep_info);
|
||||
|
||||
uint64_t *ue_agg_mbr = malloc_or_fail(sizeof(*ue_agg_mbr));
|
||||
*ue_agg_mbr = 1000000000 /*bps*/;
|
||||
|
||||
f1ap_served_cell_info_t *cell_info = &target_du->setup_req->cell[0].info;
|
||||
RETURN_IF_INVALID_ASSOC_ID(target_du->assoc_id);
|
||||
f1ap_ue_context_setup_t ue_context_setup_req = {
|
||||
f1ap_ue_context_setup_req_t ue_context_setup_req = {
|
||||
.gNB_CU_ue_id = ue->rrc_ue_id,
|
||||
.gNB_DU_ue_id = 0, /* TODO: this should be optional! */
|
||||
.plmn.mcc = cell_info->plmn.mcc,
|
||||
.plmn.mnc = cell_info->plmn.mnc,
|
||||
.plmn.mnc_digit_length = cell_info->plmn.mnc_digit_length,
|
||||
.nr_cellid = cell_info->nr_cellid,
|
||||
.servCellId = 0, // TODO: correct value?
|
||||
.srbs_to_be_setup_length = 2,
|
||||
.srbs_to_be_setup = srbs,
|
||||
.drbs_to_be_setup_length = nb_drb,
|
||||
.drbs_to_be_setup = drbs,
|
||||
.cu_to_du_rrc_information = &cu2du,
|
||||
.servCellIndex = 0, // TODO: correct value?
|
||||
.srbs_len = nb_srb,
|
||||
.srbs = srbs,
|
||||
.drbs_len = nb_drb,
|
||||
.drbs = drbs,
|
||||
.cu_to_du_rrc_info.ho_prep_info = hpi,
|
||||
.gnb_du_ue_agg_mbr_ul = ue_agg_mbr,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_setup_request(target_du->assoc_id, &ue_context_setup_req);
|
||||
free_ue_context_setup_req(&ue_context_setup_req);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -214,15 +225,15 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, int nr_cgi, uint8_t *ho_prep_info,
|
||||
|
||||
typedef struct deliver_ue_ctxt_modification_data_t {
|
||||
gNB_RRC_INST *rrc;
|
||||
f1ap_ue_context_modif_req_t *modification_req;
|
||||
f1ap_ue_context_mod_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;
|
||||
byte_array_t ba = {.buf = (uint8_t *) buf, .len = size};
|
||||
data->modification_req->rrc_container = &ba;
|
||||
data->rrc->mac_rrc.ue_context_modification_request(data->assoc_id, data->modification_req);
|
||||
}
|
||||
static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *rrc_reconf, int rrc_reconf_len)
|
||||
@@ -231,12 +242,9 @@ static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_
|
||||
|
||||
TransmActionInd_t transmission_action_indicator = TransmActionInd_STOP;
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_ue_context_modif_req_t ue_context_modif_req = {
|
||||
f1ap_ue_context_mod_req_t ue_context_modif_req = {
|
||||
.gNB_CU_ue_id = ue->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.plmn = rrc->configuration.plmn[0],
|
||||
.nr_cellid = rrc->nr_cellid, // TODO target cell ID
|
||||
.servCellId = 0, // TODO: correct value?
|
||||
.transm_action_ind = &transmission_action_indicator,
|
||||
};
|
||||
deliver_ue_ctxt_modification_data_t data = {.rrc = rrc,
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "xer_decoder.h"
|
||||
#include "xer_encoder.h"
|
||||
#include "f1ap_common.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
|
||||
// In case of phy-test and do-ra mode, read UE capabilities directly from file
|
||||
// and put it into a CG-ConfigInfo field
|
||||
@@ -137,18 +138,16 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_
|
||||
nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0};
|
||||
|
||||
uint8_t tmp[1024];
|
||||
uint8_t *cgci_buf = NULL;
|
||||
uint32_t cgci_len = 0;
|
||||
byte_array_t cgci = {0};
|
||||
if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) {
|
||||
DevAssert(m == NULL);
|
||||
UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master, &rrc->pdcp_config);
|
||||
cgci_len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp);
|
||||
DevAssert(cgci_len > 0);
|
||||
cgci_buf = tmp;
|
||||
int len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp);
|
||||
DevAssert(len > 0);
|
||||
cgci = create_byte_array(len, tmp);
|
||||
} else {
|
||||
DevAssert(m != NULL);
|
||||
cgci_buf = m->rrc_buffer;
|
||||
cgci_len = m->rrc_buffer_size;
|
||||
cgci = create_byte_array(m->rrc_buffer_size, m->rrc_buffer);
|
||||
|
||||
/* TODO: handle more than one bearer */
|
||||
if (m->nb_e_rabs_tobeadded != 1) {
|
||||
@@ -272,25 +271,24 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_
|
||||
UE->rb_config->drb_ToAddModList,
|
||||
&security_parameters);
|
||||
|
||||
cu_to_du_rrc_information_t cu2du = {
|
||||
.cG_ConfigInfo = cgci_buf,
|
||||
.cG_ConfigInfo_length = cgci_len,
|
||||
};
|
||||
/* assumption: only a single bearer, see above */
|
||||
NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList;
|
||||
AssertFatal(rb_list->list.count == 1, "can only handle one bearer for NSA/phy-test/do-ra, but has %d\n", rb_list->list.count);
|
||||
int drb_id = rb_list->list.array[0]->drb_Identity;
|
||||
f1ap_flows_mapped_to_drb_t *flow = calloc(1, sizeof(f1ap_flows_mapped_to_drb_t));
|
||||
flow->qos_params.qos_characteristics.qos_type = NON_DYNAMIC;
|
||||
flow->qfi = flow->qos_params.qos_characteristics.non_dynamic.fiveqi = 9;
|
||||
f1ap_drb_to_be_setup_t drbs = {
|
||||
.drb_id = drb_id,
|
||||
.rlc_mode = F1AP_RLC_MODE_UM_BIDIR, // hardcoded keep it backwards compatible for now
|
||||
// rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM,
|
||||
.up_ul_tnl_length = 1,
|
||||
.drb_info.flows_to_be_setup_length = 1,
|
||||
.drb_info.flows_mapped_to_drb = flow,
|
||||
};
|
||||
f1ap_drb_to_setup_t *drb = calloc_or_fail(1, sizeof(*drb));
|
||||
drb->id = drb_id;
|
||||
// hardcoded keep it backwards compatible for now
|
||||
// rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM,
|
||||
drb->rlc_mode = F1AP_RLC_MODE_UM_BIDIR;
|
||||
drb->up_ul_tnl_len = 1;
|
||||
drb->qos_choice = F1AP_QOS_CHOICE_NR; // we don't have EUTRAN yet, "approximate" it
|
||||
drb->nr.flows_len = 1;
|
||||
f1ap_drb_flows_mapped_t *flow = drb->nr.flows = calloc_or_fail(drb->nr.flows_len, sizeof(*flow));
|
||||
flow->qfi = 9;
|
||||
flow->param.qos_type = NON_DYNAMIC;
|
||||
flow->param.nondyn.fiveQI = 9;
|
||||
flow->param.arp.prio = 5;
|
||||
|
||||
// Note: E1 support for NSA/phy-test/do-ra not implemented yet
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
if (f1inst >= 0) {
|
||||
@@ -305,25 +303,30 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_
|
||||
gtpv1u_gnb_create_tunnel_resp_t resp = {0};
|
||||
int ret = gtpv1u_create_ngu_tunnel(f1inst, &req, &resp, NULL, NULL);
|
||||
AssertFatal(ret == 0, "gtpv1u_create_ngu_tunnel failed: ret %d\n", ret);
|
||||
drbs.up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
|
||||
memcpy(&drbs.up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4);
|
||||
drbs.up_ul_tnl[0].teid = resp.gnb_NGu_teid[0];
|
||||
memcpy(&drb->up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4);
|
||||
drb->up_ul_tnl[0].teid = resp.gnb_NGu_teid[0];
|
||||
drb->up_ul_tnl_len = 1;
|
||||
}
|
||||
f1ap_ue_context_setup_t req = {
|
||||
uint64_t *ue_agg_mbr_ul = malloc_or_fail(sizeof(*ue_agg_mbr_ul));
|
||||
*ue_agg_mbr_ul = 1000000000;
|
||||
byte_array_t *cg_configinfo = malloc_or_fail(sizeof(*cg_configinfo));
|
||||
*cg_configinfo = cgci;
|
||||
f1ap_ue_context_setup_req_t req = {
|
||||
.gNB_CU_ue_id = UE->rrc_ue_id,
|
||||
.gNB_DU_ue_id = 0xffffffff, /* not known yet */
|
||||
.plmn.mcc = rrc->configuration.plmn[0].mcc,
|
||||
.plmn.mnc = rrc->configuration.plmn[0].mnc,
|
||||
.plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length,
|
||||
.nr_cellid = rrc->nr_cellid,
|
||||
.servCellId = 0,
|
||||
.drbs_to_be_setup_length = 1,
|
||||
.drbs_to_be_setup = &drbs,
|
||||
.cu_to_du_rrc_information = &cu2du,
|
||||
.servCellIndex = 0,
|
||||
.drbs_len = 1,
|
||||
.drbs = drb,
|
||||
.cu_to_du_rrc_info.cg_configinfo = cg_configinfo,
|
||||
.gnb_du_ue_agg_mbr_ul = ue_agg_mbr_ul,
|
||||
};
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &req);
|
||||
free_ue_context_setup_req(&req);
|
||||
}
|
||||
|
||||
static NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup)
|
||||
|
||||
Reference in New Issue
Block a user