diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 9656b0fe2b06160a6683f5944661b49af4c79eb4..c1e1c9964ba6cb1a2b1691ab3cffa5d1500febfe 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -121,7 +121,7 @@ typedef struct DRB_nGRAN_to_setup_s { typedef struct pdu_session_to_setup_s { long sessionId; long sessionType; - int32_t sst; + int8_t sst; long integrityProtectionIndication; long confidentialityProtectionIndication; in_addr_t tlAddress; diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 48aa19523d18098ce4bc310d95bbb007a556aeee..2318e44cfbd134b7e7d9ab5af828a3d6b3dc85ea 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -573,18 +573,19 @@ int e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, ieC6->criticality = E1AP_Criticality_reject; ieC6->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest; ieC6->value.choice.System_BearerContextSetupRequest.present = E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest; - E1AP_NG_RAN_BearerContextSetupRequest_t *msgNGRAN = calloc(1, sizeof(E1AP_NG_RAN_BearerContextSetupRequest_t)); - ieC6->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN; + E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P19_t)); + ieC6->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupRequest_t, msgNGRAN); msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List; + msgNGRAN->criticality = E1AP_Criticality_reject; msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List; E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; - for(pdu_session_to_setup_t *i=bearerCxt->pduSession; i < bearerCxt->pduSession+bearerCxt->numPDUSessions; i++) { asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Item_t, ieC6_1); ieC6_1->pDU_Session_ID = i->sessionId; ieC6_1->pDU_Session_Type = i->sessionType; - INT32_TO_OCTET_STRING(i->sst, &ieC6_1->sNSSAI.sST); + INT8_TO_OCTET_STRING(i->sst, &ieC6_1->sNSSAI.sST); ieC6_1->securityIndication.integrityProtectionIndication = i->integrityProtectionIndication; ieC6_1->securityIndication.confidentialityProtectionIndication = i->confidentialityProtectionIndication; @@ -636,7 +637,6 @@ int e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = k->pre_emptionCapability; ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = k->pre_emptionVulnerability; } - } } @@ -843,7 +843,10 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, "ie->criticality != E1AP_Criticality_ignore\n"); AssertFatal(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity, "ie->value.present != E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity\n"); - //TODO + PLMNID_TO_MCC_MNC(&ie->value.choice.PLMN_Identity, + bearerCxt->servingPLMNid.mcc, + bearerCxt->servingPLMNid.mnc, + bearerCxt->servingPLMNid.mnc_digit_length); break; case E1AP_ProtocolIE_ID_id_ActivityNotificationLevel: @@ -854,7 +857,105 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, bearerCxt->activityNotificationLevel = ie->value.choice.ActivityNotificationLevel; break; - // TODO: remaining IE handlers + case E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest: + AssertFatal(ie->criticality == E1AP_Criticality_reject, + "ie->criticality != E1AP_Criticality_reject\n"); + AssertFatal(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest, + "ie->value.present != E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest\n"); + AssertFatal(ie->value.choice.System_BearerContextSetupRequest.present == + E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest, + "ie->value.choice.System_BearerContextSetupRequest.present !=" + "E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest\n"); + AssertFatal(ie->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest, + "nG_RAN_BearerContextSetupRequest is NULL\n"); + E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P19_t *) ie->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest; + E1AP_NG_RAN_BearerContextSetupRequest_t *msgNGRAN = msgNGRAN_list->list.array[0]; + AssertFatal(msgNGRAN_list->list.count == 1, "nG_RAN_BearerContextSetupRequest supports only 1 count for now\n"); + AssertFatal(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List, + "msgNGRAN->id (%ld) != E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List\n", msgNGRAN->id); + AssertFatal(msgNGRAN->value.present = + E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List, + "msgNGRAN->value.present != E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List\n"); + + E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2SetupList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; + for (int i=0; i < pdu2SetupList->list.count; i++) { + pdu_session_to_setup_t *pdu = bearerCxt->pduSession + i; + E1AP_PDU_Session_Resource_To_Setup_Item_t *pdu2Setup = pdu2SetupList->list.array[i]; + + pdu->sessionId = pdu2Setup->pDU_Session_ID; + pdu->sessionType = pdu2Setup->pDU_Session_Type; + + OCTET_STRING_TO_INT8(&pdu2Setup->sNSSAI.sST, pdu->sst); + + pdu->integrityProtectionIndication = pdu2Setup->securityIndication.integrityProtectionIndication; + pdu->confidentialityProtectionIndication = pdu2Setup->securityIndication.confidentialityProtectionIndication; + + if (pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel) { // Optional IE + AssertFatal(pdu2Setup->nG_UL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel, + "pdu2Setup->nG_UL_UP_TNL_Information.present != E1AP_UP_TNL_Information_PR_gTPTunnel\n"); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, + pdu->tlAddress); + OCTET_STRING_TO_INT32(&pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, pdu->teId); + } + + E1AP_DRB_To_Setup_List_NG_RAN_t *drb2SetupList = &pdu2Setup->dRB_To_Setup_List_NG_RAN; + for (int j=0; j < drb2SetupList->list.count; j++) { + DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; + E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; + + drb->id = drb2Setup->dRB_ID; + + drb->defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB; + drb->sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL; + drb->sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL; + + drb->pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL; + drb->pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL; + + if (drb2Setup->pDCP_Configuration.discardTimer) { + drb->discardTimer = *drb2Setup->pDCP_Configuration.discardTimer; + } + + if (drb2Setup->pDCP_Configuration.t_ReorderingTimer) { + drb->reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering; + } + + drb->rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode; + + E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; + for (int k=0; k < cellGroupList->list.count; k++) { + E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k]; + + drb->cellGroupList[k].id = cg2Setup->cell_Group_ID; + } + + E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup; + for (int k=0; k < qos2SetupList->list.count; k++) { + qos_flow_to_setup_t *qos = drb->qosFlows + k; + E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k]; + + qos->id = qos2Setup->qoS_Flow_Identifier; + + if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == + E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + qos->fiveQI_type = non_dynamic; + qos->fiveQI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; + } else { + E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI; + qos->fiveQI_type = dynamic; + qos->qoSPriorityLevel = dynamic5QI->qoSPriorityLevel; + qos->packetDelayBudget = dynamic5QI->packetDelayBudget; + qos->packetError_scalar = dynamic5QI->packetErrorRate.pER_Scalar; + qos->packetError_exponent = dynamic5QI->packetErrorRate.pER_Exponent; + } + + qos->priorityLevel = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel; + qos->pre_emptionCapability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability; + qos->pre_emptionVulnerability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability; + } + } + } + break; default: LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); @@ -1251,6 +1352,11 @@ void *E1AP_CUUP_task(void *arg) { cuxp_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind); break; + case E1AP_BEARER_CONTEXT_SETUP_RESP: + LOG_I(E1AP, "CUUP Task Received E1AP_BEARER_CONTEXT_SETUP_RESP\n"); + e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(myInstance, &E1AP_BEARER_CONTEXT_SETUP_RESP(msg)); + break; + default: LOG_E(E1AP, "Unknown message received in TASK_CUUP_E1\n"); break; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 9e740dff2f56f1ce3d50e5e4eeb870b89288442d..147eb027e777cd982b5ff5b48900b756c6b4790d 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -3895,7 +3895,7 @@ void fill_DRB_configList(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_s ASN_SEQUENCE_ADD(&sdap_config->mappedQoS_FlowsToAdd->list, qfi); } sdap_config->mappedQoS_FlowsToRelease = NULL; - /* + // pdcp_Config ie->reestablishPDCP = NULL; ie->recoverPDCP = NULL; @@ -3917,23 +3917,22 @@ void fill_DRB_configList(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_s pdcp_config->drb->outOfOrderDelivery = NULL; pdcp_config->moreThanOneRLC = NULL; - pdcp_config->t_Reordering = calloc(1, sizeof(*drb->pdcp_config->t_Reordering)); + pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); *pdcp_config->t_Reordering = drb->reorderingTimer; pdcp_config->ext1 = NULL; - if (drb->integrityProtectionIndication == 0 || // Required - drb->integrityProtectionIndication == 1) { // Preferred + if (pdu->integrityProtectionIndication == 0 || // Required + pdu->integrityProtectionIndication == 1) { // Preferred pdcp_config->drb->integrityProtection = calloc(1, sizeof(*pdcp_config->drb->integrityProtection)); *pdcp_config->drb->integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled; } - if (drb->confidentialityProtectionIndication == 0 || // Required - drb->confidentialityProtectionIndication == 1) { // Preferred + if (pdu->confidentialityProtectionIndication == 0 || // Required + pdu->confidentialityProtectionIndication == 1) { // Preferred pdcp_config->ext1 = calloc(1, sizeof(*pdcp_config->ext1)); pdcp_config->ext1->cipheringDisabled = calloc(1, sizeof(*pdcp_config->ext1->cipheringDisabled)); *pdcp_config->ext1->cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true; } - */ } } @@ -3942,7 +3941,7 @@ int rrc_gNB_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, in gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; - NR_DRB_ToAddModList_t *DRB_configList; + NR_DRB_ToAddModList_t DRB_configList; for (int i=0; i < req->numPDUSessions; i++) { pdu_session_to_setup_t *pdu = &req->pduSession[i]; create_tunnel_req.pdusession_id[i] = pdu->sessionId; @@ -3951,28 +3950,121 @@ int rrc_gNB_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, in &pdu->tlAddress, sizeof(pdu->tlAddress)); create_tunnel_req.outgoing_teid[i] = pdu->teId; - fill_DRB_configList(DRB_configList, pdu); + fill_DRB_configList(&DRB_configList, pdu); } create_tunnel_req.num_tunnels = req->numPDUSessions; - create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF); + create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF); int ret = gtpv1u_create_ngu_tunnel( instance, &create_tunnel_req, &create_tunnel_resp); + if (ret != 0) { + LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE id %ld\n", + create_tunnel_req.ue_id); + return ret; + } - uint8_t *kRRCenc = NULL; - uint8_t *kRRCint = NULL; - /* - nr_derive_key_rrc_enc(cipheringAlgorithm, - encryptionKey, - &kRRCenc); + // Configure DRBs + uint8_t *kUPenc = NULL; + uint8_t *kUPint = NULL; - nr_derive_key_rrc_int(integrityProtectionAlgorithm, - integrityProtectionKey, - &kRRCint); - */ - return 0; + nr_derive_key_rrc_enc(req->cipheringAlgorithm, + (uint8_t *)req->encryptionKey, + &kUPenc); + + nr_derive_key_rrc_int(req->integrityProtectionAlgorithm, + (uint8_t *)req->integrityProtectionKey, + &kUPint); + + nr_pdcp_add_drbs(false, + create_tunnel_req.ue_id, + &DRB_configList, + (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm, + kUPenc, + kUPint, + NULL); + + MessageDef *message_p; + message_p = itti_alloc_new_message (TASK_RRC_GNB, instance, E1AP_BEARER_CONTEXT_SETUP_RESP); + e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(message_p); + + resp->gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id; + resp->numPDUSessions = req->numPDUSessions; + for (int i=0; i < req->numPDUSessions; i++) { + pdu_session_setup_t *pduSetup = resp->pduSession + i; + pdu_session_to_setup_t *pdu2Setup = req->pduSession + i; + + pduSetup->id = pdu2Setup->sessionId; + memcpy(&pduSetup->tlAddress, &pdu2Setup->tlAddress, sizeof(in_addr_t)); + pduSetup->teId = pdu2Setup->teId; + pduSetup->numDRBSetup = pdu2Setup->numDRB2Setup; + + for (int j=0; j < pdu2Setup->numDRB2Setup; j++) { + DRB_nGRAN_setup_t *drbSetup = pduSetup->DRBnGRanList + j; + DRB_nGRAN_to_setup_t *drb2Setup = pdu2Setup->DRBnGRanList + j; + + drbSetup->id = drb2Setup->id; + drbSetup->numUpParam = 0; + drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup; + + for (int k=0; k < drbSetup->numQosFlowSetup; k++) { + drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id; + } + } + } + // At this point we don't have a way to know the DRBs that failed to setup + // We assume all DRBs to setup have are setup successfully so we always send successful outcome in response + // TODO: Modify nr_pdcp_add_drbs() to return DRB list that failed to setup to support E1AP + + itti_send_msg_to_task(TASK_CUUP_E1, instance, message_p); + + return ret; +} + +void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) { + // Find the UE context from UE ID and send ITTI message to F1AP to send UE context modification message to DU + + uint16_t ue_initial_id = 0; // Making an invalid UE initial ID + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, resp->gNB_cu_cp_ue_id); + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + + /*Generate a UE context modification request message towards the DU to instruct the DU + *for SRB2 and DRB configuration and get the updates on master cell group config from the DU*/ + + // TODO: code repetition. very bad. And so many hard codings + MessageDef *message_p; + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ); + f1ap_ue_context_setup_t *req=&F1AP_UE_CONTEXT_MODIFICATION_REQ (message_p); + req->rnti = ue_context_p->ue_context.rnti; + req->mcc = RC.nrrrc[ctxt.module_id]->configuration.mcc[0]; + req->mnc = RC.nrrrc[ctxt.module_id]->configuration.mnc[0]; + req->mnc_digit_length = RC.nrrrc[ctxt.module_id]->configuration.mnc_digit_length[0]; + req->nr_cellid = RC.nrrrc[ctxt.module_id]->nr_cellid; + + /*Instruction towards the DU for SRB2 configuration*/ + req->srbs_to_be_setup = malloc(1*sizeof(f1ap_srb_to_be_setup_t)); + req->srbs_to_be_setup_length = 1; + f1ap_srb_to_be_setup_t *SRBs=req->srbs_to_be_setup; + SRBs[0].srb_id = 2; + SRBs[0].lcid = 2; + + /*Instruction towards the DU for DRB configuration and tunnel creation*/ + req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)); + req->drbs_to_be_setup_length = 1; + f1ap_drb_to_be_setup_t *DRBs=req->drbs_to_be_setup; + LOG_D(RRC, "Length of DRB list:%d \n", req->drbs_to_be_setup_length); + DRBs[0].drb_id = 1; + DRBs[0].rlc_mode = RLC_MODE_AM; + DRBs[0].up_ul_tnl[0].tl_address = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr); + DRBs[0].up_ul_tnl[0].port=RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd; + DRBs[0].up_ul_tnl_length = 1; + DRBs[0].up_dl_tnl[0].tl_address = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.remote_addr); + DRBs[0].up_dl_tnl[0].port=RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd; + DRBs[0].up_dl_tnl_length = 1; + + itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p); } ///---------------------------------------------------------------------------------------------------------------/// @@ -4143,6 +4235,11 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_e1_bearer_context_setup_req(&E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p), instance); break; + case E1AP_BEARER_CONTEXT_SETUP_RESP: + LOG_I(NR_RRC, "Received E1AP_BEARER_CONTEXT_SETUP_RESP for instance %d\n", (int)instance); + rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance); + break; + default: LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); break;