diff --git a/CMakeLists.txt b/CMakeLists.txt index 53fed85709..27a7c471d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1450,12 +1450,6 @@ add_library(e1_if target_link_libraries(e1_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap SECURITY ${OPENSSL_LIBRARIES} e1ap GTPV1U) -add_library(e1_pdcp_if - ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_e1_api.c - ) - -target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) - target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc) if(E2_AGENT) target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func) @@ -2111,7 +2105,7 @@ add_executable(nr-cuup target_link_libraries(nr-cuup PRIVATE CONFIG_LIB ITTI SCTP_CLIENT - GTPV1U e1ap e1_pdcp_if f1ap SIMU_ETH + GTPV1U e1ap f1ap SIMU_ETH z sctp dl pthread shlib_loader ${T_LIB}) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 95348dcf19..d83137c328 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -95,12 +95,6 @@ void nr_rlc_add_drb(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Beare abort(); } -int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_pP, const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_p, int offset) -{ - abort(); - return 0; -} - void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp) { abort(); @@ -108,14 +102,14 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex f1ap_cudu_inst_t *getCxt(instance_t instanceP) { - abort(); - return NULL; -} - -NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) -{ - abort(); - return NULL; + // the E1 module uses F1's getCxt() to decide whether there is F1-U and if + // so, what is the GTP instance. In the CU-UP, we don't start the F1 module, + // and instead, E1 handles the GTP-U endpoint. In the following, we fake the + // instance and put the right GTP-U instance number in. + const e1ap_upcp_inst_t *e1inst = getCxtE1(instanceP); + static f1ap_cudu_inst_t fake = {0}; + fake.gtpInst = e1inst->gtpInstF1U; + return &fake; } int main(int argc, char **argv) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 6d80ac619c..8a5ede9159 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -108,6 +108,8 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB return; } +void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); } + int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { return 0; } diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 77a1d6d821..7307575bdb 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -104,6 +104,8 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB return; } +void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); } + int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { return 0; } diff --git a/openair2/E1AP/CMakeLists.txt b/openair2/E1AP/CMakeLists.txt index 01a969de7e..0384c2860b 100644 --- a/openair2/E1AP/CMakeLists.txt +++ b/openair2/E1AP/CMakeLists.txt @@ -3,5 +3,5 @@ add_subdirectory(MESSAGES) add_library(e1ap e1ap.c e1ap_common.c e1ap_api.c) target_link_libraries(e1ap PUBLIC asn1_e1ap f1ap - PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap UTIL e1_pdcp_if e1_if) + PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap UTIL e1_if) target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR}) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 459f1b4e98..45f3c4cd17 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -33,6 +33,7 @@ #include "openair2/F1AP/f1ap_common.h" #include "e1ap_default_values.h" #include "gtp_itf.h" +#include "openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h" #define E1AP_NUM_MSG_HANDLERS 14 typedef int (*e1ap_message_processing_t)(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p); @@ -684,7 +685,7 @@ void e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_bear e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__); } -static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const resp, E1AP_E1AP_PDU_t *pdu) +static void fill_BEARER_CONTEXT_SETUP_RESPONSE(const e1ap_bearer_setup_resp_t *resp, E1AP_E1AP_PDU_t *pdu) { /* Create */ /* 0. pdu Type */ @@ -750,7 +751,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List; E1AP_PDU_Session_Resource_Setup_List_t *pduSetup = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; - for (pdu_session_setup_t *i=resp->pduSession; i < resp->pduSession+resp->numPDUSessions; i++) { + for (const pdu_session_setup_t *i=resp->pduSession; i < resp->pduSession+resp->numPDUSessions; i++) { asn1cSequenceAdd(pduSetup->list, E1AP_PDU_Session_Resource_Setup_Item_t, ieC3_1); ieC3_1->pDU_Session_ID = i->id; @@ -759,11 +760,11 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); - for (DRB_nGRAN_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRBSetup; j++) { + for (const DRB_nGRAN_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRBSetup; j++) { asn1cSequenceAdd(ieC3_1->dRB_Setup_List_NG_RAN.list, E1AP_DRB_Setup_Item_NG_RAN_t, ieC3_1_1); ieC3_1_1->dRB_ID = j->id; - for (up_params_t *k=j->UpParamList; k < j->UpParamList+j->numUpParam; k++) { + for (const up_params_t *k=j->UpParamList; k < j->UpParamList+j->numUpParam; k++) { asn1cSequenceAdd(ieC3_1_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1_1); ieC3_1_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; asn1cCalloc(ieC3_1_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); @@ -771,7 +772,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); } - for (qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) { + for (const qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) { asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1); ieC3_1_1_1->qoS_Flow_Identifier = k->id; } @@ -780,7 +781,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r if (i->numDRBFailed > 0) ieC3_1->dRB_Failed_List_NG_RAN = calloc(1, sizeof(E1AP_DRB_Failed_List_NG_RAN_t)); - for (DRB_nGRAN_failed_t *j=i->DRBnGRanFailedList; j < i->DRBnGRanFailedList+i->numDRBFailed; j++) { + for (const DRB_nGRAN_failed_t *j=i->DRBnGRanFailedList; j < i->DRBnGRanFailedList+i->numDRBFailed; j++) { asn1cSequenceAdd(ieC3_1->dRB_Failed_List_NG_RAN->list, E1AP_DRB_Failed_Item_NG_RAN_t, ieC3_1_1); ieC3_1_1->dRB_ID = j->id; @@ -811,7 +812,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r } } -void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_bearer_setup_resp_t *const resp) +void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_setup_resp_t *resp) { E1AP_E1AP_PDU_t pdu = {0}; fill_BEARER_CONTEXT_SETUP_RESPONSE(resp, &pdu); @@ -996,7 +997,8 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upc e1ap_bearer_setup_req_t bearerCxt = {0}; extract_BEARER_CONTEXT_SETUP_REQUEST(pdu, &bearerCxt); - process_e1_bearer_context_setup_req(e1_inst->instance, &bearerCxt); + + e1_bearer_context_setup(&bearerCxt); return 0; } @@ -1769,6 +1771,13 @@ void *E1AP_CUUP_task(void *arg) { e1apHandleTimer(myInstance); break; + case E1AP_BEARER_CONTEXT_SETUP_RESP: { + const e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg); + const e1ap_upcp_inst_t *inst = getCxtE1(myInstance); + AssertFatal(inst != NULL, "no E1 instance found for instance %ld\n", myInstance); + e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst->cuup.assoc_id, resp); + } break; + default: LOG_E(E1AP, "Unknown message received in TASK_CUUP_E1\n"); break; diff --git a/openair2/E1AP/e1ap.h b/openair2/E1AP/e1ap.h index 8a7c6ba2df..c9d6345318 100644 --- a/openair2/E1AP/e1ap.h +++ b/openair2/E1AP/e1ap.h @@ -42,7 +42,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upc int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); -void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_bearer_setup_resp_t *const resp); +void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_setup_resp_t *resp); int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c index cf3fe14de1..816867a6ab 100644 --- a/openair2/E1AP/e1ap_api.c +++ b/openair2/E1AP/e1ap_api.c @@ -25,7 +25,6 @@ #include "e1ap_api.h" #include "nr_pdcp/nr_pdcp_entity.h" -#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h" #include "openair2/RRC/NR/cucp_cuup_if.h" #include "openair2/RRC/LTE/MESSAGES/asn1_msg.h" #include "openair3/SECU/key_nas_deriver.h" @@ -35,146 +34,6 @@ #include "e1ap_common.h" #include "e1ap.h" -struct NR_DRB_ToAddMod; -static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_setup_t *pdu) { - - for (int i=0; i < pdu->numDRB2Setup; i++) { - DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i; - asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie); - ie->drb_Identity = drb->id; - ie->cnAssociation = CALLOC(1, sizeof(*ie->cnAssociation)); - ie->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; - - // sdap_Config - asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config); - sdap_config->pdu_Session = pdu->sessionId; - sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL; - sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL; - sdap_config->defaultDRB = drb->defaultDRB; - - asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); - for (int j=0; j < drb->numQosFlow2Setup; j++) { - asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi); - *qfi = drb->qosFlows[j].fiveQI; - } - sdap_config->mappedQoS_FlowsToRelease = NULL; - - // pdcp_Config - ie->reestablishPDCP = NULL; - ie->recoverPDCP = NULL; - asn1cCalloc(ie->pdcp_Config, pdcp_config); - asn1cCalloc(pdcp_config->drb, drbCfg); - asn1cCallocOne(drbCfg->discardTimer, drb->discardTimer); - asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pDCP_SN_Size_UL); - asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pDCP_SN_Size_DL); - drbCfg->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - drbCfg->headerCompression.choice.notUsed = 0; - - drbCfg->integrityProtection = NULL; - drbCfg->statusReportRequired = NULL; - drbCfg->outOfOrderDelivery = NULL; - pdcp_config->moreThanOneRLC = NULL; - - pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); - *pdcp_config->t_Reordering = drb->reorderingTimer; - pdcp_config->ext1 = NULL; - - if (pdu->integrityProtectionIndication == 0 || // Required - pdu->integrityProtectionIndication == 1) { // Preferred - asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); - } - - if (pdu->confidentialityProtectionIndication == 2) { // Not Needed - asn1cCalloc(pdcp_config->ext1, ext1); - asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); - } - } -} - -static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req, - gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp, - instance_t instance) { - - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; - - NR_DRB_ToAddModList_t DRB_configList = {0}; - for (int i=0; i < req->numPDUSessions; i++) { - pdu_session_to_setup_t *const pdu = &req->pduSession[i]; - create_tunnel_req.pdusession_id[i] = pdu->sessionId; - create_tunnel_req.incoming_rb_id[i] = pdu->DRBnGRanList[0].id; // taking only the first DRB. TODO:change this - memcpy(&create_tunnel_req.dst_addr[i].buffer, - &pdu->tlAddress, - sizeof(uint8_t)*4); - create_tunnel_req.dst_addr[i].length = 32; // 8bits * 4bytes - create_tunnel_req.outgoing_teid[i] = pdu->teId; - fill_DRB_configList_e1(&DRB_configList, pdu); - } - create_tunnel_req.num_tunnels = req->numPDUSessions; - create_tunnel_req.ue_id = req->gNB_cu_cp_ue_id; - - // Create N3 tunnel - int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, nr_pdcp_data_req_drb, sdap_data_req); - if (ret != 0) { - LOG_E(NR_RRC, - "drb_config_N3gtpu_create=>gtpv1u_create_ngu_tunnel failed, cannot set up GTP tunnel for data transmissions of UE %ld\n", - create_tunnel_req.ue_id); - return ret; - } - - // Configure DRBs - nr_pdcp_e1_add_drbs(true, // set this to notify PDCP that his not UE - create_tunnel_req.ue_id, - &DRB_configList, - (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm, - (uint8_t *)req->encryptionKey, - (uint8_t *)req->integrityProtectionKey); - return ret; -} - -void process_e1_bearer_context_setup_req(instance_t instance, e1ap_bearer_setup_req_t *const req) -{ - e1ap_upcp_inst_t *inst = getCxtE1(instance); - AssertFatal(inst, ""); - gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp_N3={0}; - - uint32_t gNB_cu_up_ue_id = req ->gNB_cu_cp_ue_id; - LOG_I(E1AP, "adding UE with CU-CP UE ID %d and CU-UP UE ID %d\n", req->gNB_cu_cp_ue_id, gNB_cu_up_ue_id); - f1_ue_data_t ue_data = {.secondary_ue = req->gNB_cu_cp_ue_id}; - cu_add_f1_ue_data(gNB_cu_up_ue_id, &ue_data); - - // GTP tunnel for UL - drb_config_N3gtpu_create(req, &create_tunnel_resp_N3, inst->gtpInstN3); - - MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP); - e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg); - - in_addr_t my_addr; - if (inet_pton(AF_INET, inst->net_config.localAddressF1U, &my_addr) != 1) - LOG_E(E1AP, "can't use the F1-U local interface: %s\n", inst->net_config.localAddressF1U); - fill_e1ap_bearer_setup_resp(resp, req, inst->gtpInstF1U, req->gNB_cu_cp_ue_id, inst->net_config.remotePortF1U, my_addr); - - resp->gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id; - resp->gNB_cu_up_ue_id = gNB_cu_up_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; - if (inet_pton(AF_INET, inst->net_config.localAddressN3, &pduSetup->tlAddress) != 1) - LOG_E(E1AP, "can't use the N3 local interface: %s\n", inst->net_config.localAddressN3); - pduSetup->teId = create_tunnel_resp_N3.gnb_NGu_teid[i]; - pduSetup->numDRBSetup = pdu2Setup->numDRB2Setup; - - // 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 - pduSetup->numDRBFailed = 0; - } - - e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst->cuup.assoc_id, resp); -} - void CUUP_process_bearer_context_mod_req(instance_t instance, e1ap_bearer_setup_req_t *const req) { e1ap_upcp_inst_t *inst = getCxtE1(instance); diff --git a/openair2/E1AP/e1ap_api.h b/openair2/E1AP/e1ap_api.h index 1b9f219fcc..a6cbe228d1 100644 --- a/openair2/E1AP/e1ap_api.h +++ b/openair2/E1AP/e1ap_api.h @@ -28,7 +28,6 @@ #include "openair2/COMMON/e1ap_messages_types.h" #include "openair2/E1AP/e1ap_common.h" void cuup_init_n3(instance_t instance); -void process_e1_bearer_context_setup_req(instance_t, e1ap_bearer_setup_req_t *const req); void CUUP_process_bearer_context_mod_req(instance_t, e1ap_bearer_setup_req_t *const req); void CUUP_process_bearer_release_command(instance_t, e1ap_bearer_release_cmd_t *const cmd); diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 76575e65d9..29ccb6bf32 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -20,3 +20,202 @@ */ #include "cucp_cuup_handler.h" + +#include "NR_DRB-ToAddModList.h" + +#include "platform_types.h" +#include "intertask_interface.h" +#include "openair2/COMMON/e1ap_messages_types.h" +#include "openair3/ocp-gtpu/gtp_itf.h" +#include "openair2/F1AP/f1ap_ids.h" +#include "nr_pdcp_oai_api.h" +#include "cuup_cucp_if.h" +#include "common/utils/oai_asn1.h" +#include "openair2/SDAP/nr_sdap/nr_sdap.h" +#include "openair2/E1AP/e1ap_common.h" +#include "openair2/F1AP/f1ap_common.h" + +static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const pdu_session_to_setup_t *pdu) +{ + for (int i=0; i < pdu->numDRB2Setup; i++) { + const DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i; + asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie); + ie->drb_Identity = drb->id; + ie->cnAssociation = CALLOC(1, sizeof(*ie->cnAssociation)); + ie->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + + // sdap_Config + asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config); + sdap_config->pdu_Session = pdu->sessionId; + sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL; + sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL; + sdap_config->defaultDRB = drb->defaultDRB; + + asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); + for (int j=0; j < drb->numQosFlow2Setup; j++) { + asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi); + *qfi = drb->qosFlows[j].fiveQI; + } + sdap_config->mappedQoS_FlowsToRelease = NULL; + + // pdcp_Config + ie->reestablishPDCP = NULL; + ie->recoverPDCP = NULL; + asn1cCalloc(ie->pdcp_Config, pdcp_config); + asn1cCalloc(pdcp_config->drb, drbCfg); + asn1cCallocOne(drbCfg->discardTimer, drb->discardTimer); + asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pDCP_SN_Size_UL); + asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pDCP_SN_Size_DL); + drbCfg->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drbCfg->headerCompression.choice.notUsed = 0; + + drbCfg->integrityProtection = NULL; + drbCfg->statusReportRequired = NULL; + drbCfg->outOfOrderDelivery = NULL; + pdcp_config->moreThanOneRLC = NULL; + + pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); + *pdcp_config->t_Reordering = drb->reorderingTimer; + pdcp_config->ext1 = NULL; + + if (pdu->integrityProtectionIndication == 0 || // Required + pdu->integrityProtectionIndication == 1) { // Preferred + asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + } + + if (pdu->confidentialityProtectionIndication == 2) { // Not Needed + asn1cCalloc(pdcp_config->ext1, ext1); + asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); + } + } +} + +static int drb_gtpu_create(instance_t instance, + uint32_t ue_id, + int incoming_id, + int outgoing_id, + int qfi, + in_addr_t tlAddress, // only IPv4 now + teid_t outgoing_teid, + gtpCallback callBack, + gtpCallbackSDAP callBackSDAP, + gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp) +{ + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0}; + create_tunnel_req.incoming_rb_id[0] = incoming_id; + create_tunnel_req.pdusession_id[0] = outgoing_id; + memcpy(&create_tunnel_req.dst_addr[0].buffer, &tlAddress, sizeof(uint8_t) * 4); + create_tunnel_req.dst_addr[0].length = 32; + create_tunnel_req.outgoing_teid[0] = outgoing_teid; + create_tunnel_req.outgoing_qfi[0] = qfi; + create_tunnel_req.num_tunnels = 1; + create_tunnel_req.ue_id = ue_id; + + // we use gtpv1u_create_ngu_tunnel because it returns the interface + // address and port of the interface; apart from that, we also might call + // newGtpuCreateTunnel() directly + return gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, callBack, callBackSDAP); +} + +static instance_t get_n3_gtp_instance(void) +{ + const e1ap_upcp_inst_t *inst = getCxtE1(0); + AssertFatal(inst != NULL, "need to have E1 instance\n"); + return inst->gtpInstN3; +} + +static instance_t get_f1_gtp_instance(void) +{ + const f1ap_cudu_inst_t *inst = getCxt(0); + if (!inst) + return -1; // means no F1 + return inst->gtpInst; +} + +void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) +{ + /* mirror the CU-CP UE ID for CU-UP */ + uint32_t cu_up_ue_id = req->gNB_cu_cp_ue_id; + f1_ue_data_t ued = {.secondary_ue = req->gNB_cu_cp_ue_id}; + cu_add_f1_ue_data(cu_up_ue_id, &ued); + LOG_I(E1AP, "adding UE with CU-CP UE ID %d and CU-UP UE ID %d\n", req->gNB_cu_cp_ue_id, cu_up_ue_id); + + instance_t n3inst = get_n3_gtp_instance(); + instance_t f1inst = get_f1_gtp_instance(); + + e1ap_bearer_setup_resp_t resp = { + .gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id, + .gNB_cu_up_ue_id = cu_up_ue_id, + }; + resp.numPDUSessions = req->numPDUSessions; + for (int i = 0; i < resp.numPDUSessions; ++i) { + pdu_session_setup_t *resp_pdu = resp.pduSession + i; + const pdu_session_to_setup_t *req_pdu = req->pduSession + i; + resp_pdu->id = req_pdu->sessionId; + + AssertFatal(req_pdu->numDRB2Modify == 0, "DRB modification not implemented\n"); + AssertFatal(req_pdu->numDRB2Setup == 1, "can only handle one DRB per PDU session\n"); + resp_pdu->numDRBSetup = req_pdu->numDRB2Setup; + const DRB_nGRAN_to_setup_t *req_drb = &req_pdu->DRBnGRanList[0]; + DRB_nGRAN_setup_t *resp_drb = &resp_pdu->DRBnGRanList[0]; + resp_drb->id = req_drb->id; + resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup; + for (int k = 0; k < resp_drb->numQosFlowSetup; k++) + resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id; + + // GTP tunnel for N3/to core + gtpv1u_gnb_create_tunnel_resp_t resp_n3 = {0}; + int qfi = 0; // put PDU session marker + int ret = drb_gtpu_create(n3inst, + cu_up_ue_id, + req_drb->id, + req_pdu->sessionId, + qfi, + req_pdu->tlAddress, + req_pdu->teId, + nr_pdcp_data_req_drb, + sdap_data_req, + &resp_n3); + AssertFatal(ret >= 0, "Unable to create GTP Tunnel for NG-U\n"); + AssertFatal(resp_n3.num_tunnels == req->numPDUSessions, "could not create all tunnels\n"); + resp_pdu->teId = resp_n3.gnb_NGu_teid[i]; + memcpy(&resp_pdu->tlAddress, &resp_n3.gnb_addr.buffer, 4); + + // create PDCP bearers. This will also create SDAP bearers + NR_DRB_ToAddModList_t DRB_configList = {0}; + fill_DRB_configList_e1(&DRB_configList, req_pdu); + nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE + cu_up_ue_id, + &DRB_configList, + (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm, + (uint8_t *)req->encryptionKey, + (uint8_t *)req->integrityProtectionKey); + + if (f1inst >= 0) { /* we have F1(-U) */ + teid_t dummy_teid = 0xffff; // we will update later with answer from DU + in_addr_t dummy_address = {0}; // IPv4, updated later with answer from DU + gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0}; + int qfi = -1; // don't put PDU session marker in GTP + int ret = drb_gtpu_create(f1inst, + cu_up_ue_id, + req_drb->id, + req_drb->id, + qfi, + dummy_address, + dummy_teid, + cu_f1u_data_req, + NULL, + &resp_f1); + resp_drb->numUpParam = 1; + AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n"); + memcpy(&resp_drb->UpParamList[0].tlAddress, &resp_f1.gnb_addr.buffer, 4); + resp_drb->UpParamList[0].teId = resp_f1.gnb_NGu_teid[0]; + } + + // We assume all DRBs to setup have been setup successfully, so we always + // send successful outcome in response and no failed DRBs + resp_pdu->numDRBFailed = 0; + } + + get_e1_if()->bearer_setup_response(&resp); +} diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h index ea75eb366e..ec220876f5 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h @@ -26,4 +26,7 @@ void nr_pdcp_e1_if_init(bool uses_e1); +struct e1ap_bearer_setup_req_s; +void e1_bearer_context_setup(const struct e1ap_bearer_setup_req_s *req); + #endif /* CUCP_CUUP_HANDLER_H */ diff --git a/openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c b/openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c index 2741b473c0..dd87e56b5d 100644 --- a/openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c +++ b/openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c @@ -20,8 +20,18 @@ */ #include "cuup_cucp_if.h" +#include "e1ap_messages_types.h" +#include "intertask_interface.h" + +static void bearer_setup_response_direct(const e1ap_bearer_setup_resp_t *resp) +{ + MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, E1AP_BEARER_CONTEXT_SETUP_RESP); + e1ap_bearer_setup_resp_t *msg_resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg); + *msg_resp = *resp; + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); +} void cuup_cucp_init_direct(e1_if_t *iface) { - (void) iface; + iface->bearer_setup_response = bearer_setup_response_direct; } diff --git a/openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c b/openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c index 48dc148473..8db854786b 100644 --- a/openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c +++ b/openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c @@ -20,8 +20,18 @@ */ #include "cuup_cucp_if.h" +#include "intertask_interface.h" +#include "e1ap_messages_types.h" + +static void bearer_setup_response_e1ap(const e1ap_bearer_setup_resp_t *resp) +{ + MessageDef *msg_p = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP); + e1ap_bearer_setup_resp_t *bearer_resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p); + *bearer_resp = *resp; + itti_send_msg_to_task (TASK_CUUP_E1, 0, msg_p); +} void cuup_cucp_init_e1ap(e1_if_t *iface) { - (void) iface; + iface->bearer_setup_response = bearer_setup_response_e1ap; } diff --git a/openair2/LAYER2/nr_pdcp/cuup_cucp_if.h b/openair2/LAYER2/nr_pdcp/cuup_cucp_if.h index a816853958..5ec064ba03 100644 --- a/openair2/LAYER2/nr_pdcp/cuup_cucp_if.h +++ b/openair2/LAYER2/nr_pdcp/cuup_cucp_if.h @@ -24,7 +24,11 @@ #include +struct e1ap_bearer_setup_resp_s; +typedef void (*e1_bearer_setup_response_func_t)(const struct e1ap_bearer_setup_resp_s *resp); + typedef struct e1_if_t { + e1_bearer_setup_response_func_t bearer_setup_response; } e1_if_t; e1_if_t *get_e1_if(void); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c deleted file mode 100644 index c7c91a38a0..0000000000 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include "nr_pdcp_e1_api.h" - -void e1_add_drb(int is_gnb, - uint64_t ue_id, - struct NR_DRB_ToAddMod *s, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key) -{ - add_drb(is_gnb, ue_id, s, ciphering_algorithm, integrity_algorithm, ciphering_key, integrity_key); - LOG_I(PDCP, "%s:%s:%d: added DRB for UE ID %ld\n", __FILE__, __FUNCTION__, __LINE__, ue_id); -} - -void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag, - uint64_t ue_id, - NR_DRB_ToAddModList_t *const drb2add_list, - const uint8_t security_modeP, - uint8_t *const kUPenc, - uint8_t *const kUPint) { - - if (drb2add_list != NULL) { - for (int i = 0; i < drb2add_list->list.count; i++) { - e1_add_drb(enb_flag, ue_id, drb2add_list->list.array[i], - security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, - kUPenc, kUPint); - } - } else - LOG_W(PDCP, "%s with void list\n", __FUNCTION__); -} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h deleted file mode 100644 index 3c16996126..0000000000 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include "common/utils/oai_asn1.h" -#include "NR_RadioBearerConfig.h" - -#include "nr_pdcp_oai_api.h" -#include "LAYER2/nr_rlc/nr_rlc_oai_api.h" -#include -#include "openair2/SDAP/nr_sdap/nr_sdap.h" - -void e1_add_drb(int is_gnb, - uint64_t ue_id, - struct NR_DRB_ToAddMod *s, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key); - -void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag, - uint64_t ue_id, - NR_DRB_ToAddModList_t *const drb2add_list, - const uint8_t security_modeP, - uint8_t *const kUPenc, - uint8_t *const kUPint); - -void add_drb_am(int is_gnb, ue_id_t rntiMaybeUEid, struct NR_DRB_ToAddMod *s, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key); - diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index b7b9949036..eb1367c724 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -39,7 +39,6 @@ #include "openair2/F1AP/f1ap_ids.h" #include #include "openair2/SDAP/nr_sdap/nr_sdap.h" -#include "nr_pdcp_e1_api.h" #include "gnb_config.h" #include "executables/softmodem-common.h" #include "cuup_cucp_if.h" diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c index a62f576c72..8806718915 100644 --- a/openair2/RRC/NR/cucp_cuup_direct.c +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -32,7 +32,7 @@ #include "openair3/SECU/key_nas_deriver.h" #include "nr_pdcp/nr_pdcp_entity.h" -#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h" +#include "openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h" #include #include "openair3/ocp-gtpu/gtp_itf.h" #include "rrc_gNB_GTPV1U.h" @@ -42,42 +42,10 @@ extern RAN_CONTEXT_t RC; -void fill_e1ap_bearer_setup_resp(e1ap_bearer_setup_resp_t *resp, - e1ap_bearer_setup_req_t *const req, - instance_t gtpInst, - ue_id_t ue_id, - int remote_port, - in_addr_t my_addr) { - - resp->numPDUSessions = req->numPDUSessions; - transport_layer_addr_t dummy_address = {0}; - dummy_address.length = 32; // IPv4 - for (int i=0; i < req->numPDUSessions; i++) { - resp->pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup; - for (int j=0; j < req->pduSession[i].numDRB2Setup; j++) { - DRB_nGRAN_to_setup_t *drb2Setup = req->pduSession[i].DRBnGRanList + j; - DRB_nGRAN_setup_t *drbSetup = resp->pduSession[i].DRBnGRanList + j; - - drbSetup->numUpParam = 1; - drbSetup->UpParamList[0].tlAddress = my_addr; - drbSetup->UpParamList[0].teId = newGtpuCreateTunnel(gtpInst, - ue_id, - drb2Setup->id, - drb2Setup->id, - 0xFFFF, // We will set the right value from DU answer - -1, // no qfi - dummy_address, // We will set the right value from DU answer - remote_port, - cu_f1u_data_req, - NULL); - drbSetup->id = drb2Setup->id; - - drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup; - for (int k=0; k < drbSetup->numQosFlowSetup; k++) { - drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id; - } - } - } +static void cucp_cuup_bearer_context_setup_direct(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req) +{ + AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id); + e1_bearer_context_setup(req); } void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t instance, ue_id_t ue_id) { @@ -97,114 +65,6 @@ void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t insta } } -static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p, - rrc_gNB_ue_context_t *ue_context_p, - e1ap_bearer_setup_req_t *const req, - NR_DRB_ToAddModList_t *DRB_configList, - instance_t instance) -{ - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; - gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; - gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - LOG_W(NR_RRC, "recreate existing tunnels, while adding new ones\n"); - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - rrc_pdu_session_param_t *pdu = UE->pduSession + i; - create_tunnel_req.pdusession_id[i] = pdu->param.pdusession_id; - create_tunnel_req.incoming_rb_id[i] = i + 1; - create_tunnel_req.outgoing_qfi[i] = req->pduSession[i].DRBnGRanList[0].qosFlows[0].id; - memcpy(&create_tunnel_req.dst_addr[i].buffer, &pdu->param.upf_addr.buffer, sizeof(create_tunnel_req.dst_addr[0].buffer)); - create_tunnel_req.dst_addr[i].length = pdu->param.upf_addr.length; - create_tunnel_req.outgoing_teid[i] = pdu->param.gtp_teid; - } - create_tunnel_req.num_tunnels = UE->nb_of_pdusessions; - create_tunnel_req.ue_id = UE->rrc_ue_id; - int ret = gtpv1u_create_ngu_tunnel(getCxtE1(instance)->gtpInstN3, - &create_tunnel_req, - &create_tunnel_resp, - nr_pdcp_data_req_drb, - sdap_data_req); - - if (ret != 0) { - LOG_E(NR_RRC, - "drb_config_gtpu_create=>gtpv1u_create_ngu_tunnel failed, cannot set up GTP tunnel for data transmissions of UE %ld\n", - create_tunnel_req.ue_id); - return ret; - } - - nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_p, &create_tunnel_resp, 0); - - uint8_t kRRCenc[16] = {0}; - uint8_t kRRCint[16] = {0}; - uint8_t kUPenc[16] = {0}; - uint8_t kUPint[16] = {0}; - /* Derive the keys from kgnb */ - if (DRB_configList != NULL) { - nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc); - nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, kUPint); - } - - nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc); - nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint); - - /* Refresh SRBs/DRBs */ - - LOG_D(NR_RRC, "Configuring PDCP DRBs for UE %x\n", UE->rnti); - nr_pdcp_add_drbs(ctxt_p->enb_flag, - UE->rrc_ue_id, - DRB_configList, - (UE->integrity_algorithm << 4) | UE->ciphering_algorithm, - kUPenc, - kUPint); - - return ret; -} - -static void cucp_cuup_bearer_context_setup_direct(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const req) -{ - AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id); - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], req->gNB_cu_cp_ue_id); - gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - protocol_ctxt_t ctxt = {0}; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0, 0); - - e1ap_bearer_setup_resp_t resp = {0}; - resp.numPDUSessions = req->numPDUSessions; - for (int i = 0; i < resp.numPDUSessions; ++i) { - resp.pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup; - for (int j = 0; j < req->pduSession[i].numDRB2Setup; j++) { - DRB_nGRAN_to_setup_t *req_drb = req->pduSession[i].DRBnGRanList + j; - DRB_nGRAN_setup_t *resp_drb = resp.pduSession[i].DRBnGRanList + j; - resp_drb->id = req_drb->id; - resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup; - for (int k = 0; k < resp_drb->numQosFlowSetup; k++) - resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id; - } - } - - gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; - // GTP tunnel for UL - NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(UE); - int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, DRB_configList, rrc->e1_inst); - if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n"); - // the code is very badly organized, it is not possible here to call freeDRBlist() - ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList,DRB_configList ); - - // Used to store teids: if monolithic, will simply be NULL - if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) { - // intentionally empty - } else { - int remote_port = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd; - in_addr_t my_addr = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr); - instance_t gtpInst = getCxt(0)->gtpInst; - // GTP tunnel for DL - fill_e1ap_bearer_setup_resp(&resp, req, gtpInst, UE->rrc_ue_id, remote_port, my_addr); - } - // actually, we should receive the corresponding context setup response - // message at the RRC and always react to this one. So in the following, we - // just call the corresponding message handler - prepare_and_send_ue_context_modification_f1(ue_context_p, &resp); -} - static void cucp_cuup_bearer_context_mod_direct(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id); diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c index 7604cabf14..2b933e3bae 100644 --- a/openair2/RRC/NR/cucp_cuup_e1ap.c +++ b/openair2/RRC/NR/cucp_cuup_e1ap.c @@ -28,15 +28,8 @@ #include "nr_rrc_proto.h" #include "nr_rrc_extern.h" #include "cucp_cuup_if.h" -#include "openair2/COMMON/e1ap_messages_types.h" -#include "openair3/SECU/secu_defs.h" -#include -#include "common/ran_context.h" - -extern RAN_CONTEXT_t RC; - -static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const req) +static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req) { AssertFatal(assoc_id > 0, "illegal assoc_id %d\n", assoc_id); MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ); diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h index 3a3fb7948a..a298bdfe96 100644 --- a/openair2/RRC/NR/cucp_cuup_if.h +++ b/openair2/RRC/NR/cucp_cuup_if.h @@ -30,7 +30,7 @@ struct e1ap_bearer_setup_req_s; struct e1ap_bearer_setup_resp_s; -typedef void (*cucp_cuup_bearer_context_setup_func_t)(sctp_assoc_t assoc_id, struct e1ap_bearer_setup_req_s *const req); +typedef void (*cucp_cuup_bearer_context_setup_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_setup_req_s *req); struct gNB_RRC_INST_s; void cucp_cuup_message_transfer_direct_init(struct gNB_RRC_INST_s *rrc); diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 96f5b0e28b..2bbbe5ab36 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -148,8 +148,6 @@ void ue_cxt_mod_send_e1ap(MessageDef *msg, void ue_cxt_mod_direct(MessageDef *msg, instance_t instance); -NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue); - void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp); void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t rntiMaybeUEid, NR_SRB_ToAddModList_t *const srb2add_list, const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kUPint); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 7a8916181b..d744cb11c2 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -93,7 +93,6 @@ #include #include #include -#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h" #include "openair2/F1AP/f1ap_common.h" #include "openair2/F1AP/f1ap_ids.h" #include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" @@ -2317,24 +2316,42 @@ static int get_dl_mimo_layers(const f1ap_served_cell_info_t *cell_info, const NR return(1); } -void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp) +void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) { - /* 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*/ - gNB_RRC_INST *rrc = RC.nrrrc[0]; + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_cu_cp_ue_id); + AssertFatal(ue_context_p != NULL, "did not find UE with CU UE ID %d\n", resp->gNB_cu_cp_ue_id); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + // currently: we don't have "infrastructure" to save the CU-UP UE ID, so we + // assume (and below check) that CU-UP UE ID == CU-CP UE ID + AssertFatal(resp->gNB_cu_cp_ue_id == resp->gNB_cu_up_ue_id, + "cannot handle CU-UP UE ID different from CU-CP UE ID (%d vs %d)\n", + resp->gNB_cu_cp_ue_id, + resp->gNB_cu_up_ue_id); + + // save the tunnel address for the PDU sessions + for (int i=0; i < resp->numPDUSessions; i++) { + pdu_session_setup_t *e1_pdu = &resp->pduSession[i]; + rrc_pdu_session_param_t *rrc_pdu = find_pduSession(UE, e1_pdu->id, false); + if (rrc_pdu == NULL) { + LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id); + continue; + } + rrc_pdu->param.gNB_teid_N3 = e1_pdu->teId; + memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tlAddress, sizeof(uint8_t) * 4); + rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t); + } + /* Instruction towards the DU for DRB configuration and tunnel creation */ - int nb_drb = e1ap_resp->pduSession[0].numDRBSetup; + int nb_drb = resp->pduSession[0].numDRBSetup; f1ap_drb_to_be_setup_t drbs[nb_drb]; for (int i = 0; i < nb_drb; i++) { - drbs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id; + drbs[i].drb_id = resp->pduSession[0].DRBnGRanList[i].id; drbs[i].rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM; - drbs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress; + drbs[i].up_ul_tnl[0].tl_address = resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress; drbs[i].up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drbs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId; + drbs[i].up_ul_tnl[0].teid = resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId; drbs[i].up_ul_tnl_length = 1; } @@ -2348,6 +2365,7 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex srbs[0].lcid = 2; } + /* Gather UE capability if present */ cu_to_du_rrc_information_t cu2du = {0}; cu_to_du_rrc_information_t *cu2du_p = NULL; if (UE->ue_cap_buffer.len > 0 && UE->ue_cap_buffer.buf != NULL) { @@ -2374,38 +2392,6 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req); } -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 - - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], resp->gNB_cu_cp_ue_id); - AssertFatal(ue_context_p != NULL, "did not find UE with CU UE ID %d\n", resp->gNB_cu_cp_ue_id); - protocol_ctxt_t ctxt = {0}; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, resp->gNB_cu_cp_ue_id, 0, 0, 0); - - // currently: we don't have "infrastructure" to save the CU-UP UE ID, so we - // assume (and below check) that CU-UP UE ID == CU-CP UE ID - AssertFatal(resp->gNB_cu_cp_ue_id == resp->gNB_cu_up_ue_id, - "cannot handle CU-UP UE ID different from CU-CP UE ID (%d vs %d)\n", - resp->gNB_cu_cp_ue_id, - resp->gNB_cu_up_ue_id); - - gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; - create_tunnel_resp.num_tunnels = resp->numPDUSessions; - for (int i=0; i < resp->numPDUSessions; i++) { - create_tunnel_resp.pdusession_id[i] = resp->pduSession[i].id; - create_tunnel_resp.gnb_NGu_teid[i] = resp->pduSession[i].teId; - memcpy(create_tunnel_resp.gnb_addr.buffer, - &resp->pduSession[i].tlAddress, - sizeof(in_addr_t)); - create_tunnel_resp.gnb_addr.length = sizeof(in_addr_t); // IPv4 byte length - } - - nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ctxt, &create_tunnel_resp, 0); - - // TODO: SV: combine e1ap_bearer_setup_req_t and e1ap_bearer_setup_resp_t and minimize assignments - prepare_and_send_ue_context_modification_f1(ue_context_p, resp); -} - static void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id) { AssertFatal(rrc->du != NULL, "no DU connected, cannot received F1 lost connection\n"); @@ -2683,6 +2669,7 @@ void *rrc_gnb_task(void *args_p) { case E1AP_BEARER_CONTEXT_SETUP_RESP: rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance); + break; case NGAP_PAGING_IND: rrc_gNB_process_PAGING_IND(msg_p, instance); diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.c b/openair2/RRC/NR/rrc_gNB_GTPV1U.c index 3ef3e62d51..6c8627aa09 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.c +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.c @@ -75,35 +75,3 @@ int rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_ return 0; } - -int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_pP, const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, int offset) -{ - if (!create_tunnel_resp_pP) { - LOG_E(NR_RRC, "create_tunnel_resp_pP error\n"); - return -1; - } - - LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT " RX CREATE_TUNNEL_RESP num tunnels %u \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->num_tunnels); - /* we look up by CU UE ID! Do NOT change back to RNTI! */ - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[ctxt_pP->module_id], ctxt_pP->rntiMaybeUEid); - if (!ue_context_p) { - LOG_E(NR_RRC, "UE table error\n"); - return -1; - } - - for (int i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) { - ue_context_p->ue_context.pduSession[i + offset].param.gNB_teid_N3 = create_tunnel_resp_pP->gnb_NGu_teid[i]; - ue_context_p->ue_context.pduSession[i + offset].param.gNB_addr_N3 = create_tunnel_resp_pP->gnb_addr; - AssertFatal(ue_context_p->ue_context.pduSession[i + offset].param.pdusession_id == create_tunnel_resp_pP->pdusession_id[i], ""); - LOG_I(NR_RRC, - PROTOCOL_NR_RRC_CTXT_UE_FMT - " nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u) bearer UE context index %u, id %u, gtp addr len %d \n", - PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), - create_tunnel_resp_pP->gnb_NGu_teid[i], - i, - create_tunnel_resp_pP->pdusession_id[i], - create_tunnel_resp_pP->gnb_addr.length); - } - - return 0; -} diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.h b/openair2/RRC/NR/rrc_gNB_GTPV1U.h index d538127d76..d7d1013db8 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.h +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.h @@ -38,6 +38,4 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( uint8_t *inde_list ); -int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_pP, const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, int offset_in_rrc); - #endif diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 0e7f01fd8e..40d96fe527 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -378,6 +378,9 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t uint8_t nb_pdusessions_tosetup = req->nb_of_pdusessions; if (nb_pdusessions_tosetup) { AssertFatal(false, "PDU sessions in Initial context setup request not handled by E1 yet\n"); + /* this code should pass by E1: commenting here for future reference, but + * already handled in E1 for the "normal case" of a separate request for + * PDU session setup. gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0}; for (int i = 0; i < nb_pdusessions_tosetup; i++) { UE->nb_of_pdusessions++; @@ -404,6 +407,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t } nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ctxt, &create_tunnel_resp, 0); + */ } /* NAS PDU */