diff --git a/openair2/COMMON/e1ap_messages_def.h b/openair2/COMMON/e1ap_messages_def.h index ee3b1e45dfa3403412491913a93305479c56957d..70533f8add61a270294fc845fb7a84536b4a3863 100644 --- a/openair2/COMMON/e1ap_messages_def.h +++ b/openair2/COMMON/e1ap_messages_def.h @@ -29,3 +29,5 @@ MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_s MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_RESP , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_resp_t , e1ap_bearer_setup_resp) +MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_req_t , e1ap_bearer_mod_req) + diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index ae76103321548f57064418f61f15656cd973e4f5..81542cb9e5c0445c745a43e9678287c955c74fbc 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -36,10 +36,11 @@ #define E1AP_MAX_NUM_DRBS 4 #define E1AP_MAX_NUM_UP_PARAM 4 -#define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req -#define E1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_resp -#define E1AP_BEARER_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req -#define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp +#define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req +#define E1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_resp +#define E1AP_BEARER_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req +#define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp +#define E1AP_BEARER_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req typedef f1ap_net_ip_address_t e1ap_net_ip_address_t; @@ -112,6 +113,8 @@ typedef struct DRB_nGRAN_to_setup_s { long discardTimer; long reorderingTimer; long rLC_Mode; + in_addr_t tlAddress; + int teId; int numCellGroups; cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; int numQosFlow2Setup; @@ -136,6 +139,7 @@ typedef struct pdu_session_to_setup_s { typedef struct e1ap_bearer_setup_req_s { uint64_t gNB_cu_cp_ue_id; + rnti_t rnti; uint64_t cipheringAlgorithm; uint64_t integrityProtectionAlgorithm; char encryptionKey[128]; diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 6367699bfd8a7efd92ce77eacc6e27dd1d05f446..26e509b2e71d5eafe13bd784ccbc349f32dc8d90 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -186,6 +186,7 @@ typedef struct gtpv1u_gnb_create_tunnel_resp_s { int num_tunnels; teid_t gnb_NGu_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + int bearer_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; transport_layer_addr_t gnb_addr; } gtpv1u_gnb_create_tunnel_resp_t; typedef struct gtpv1u_gnb_delete_tunnel_req_s { diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 910afb3653c07e668797c05a68274cbb60e44b61..d366902b81a33df0e06a810dfc9a855c81d5a19e 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -1086,7 +1086,8 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance, BEARER CONTEXT MODIFICATION REQUEST */ -int e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { +int e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance, + e1ap_bearer_setup_req_t *req) { AssertFatal(false,"Not implemented yet\n"); return -1; } @@ -1373,6 +1374,11 @@ void *E1AP_CUCP_task(void *arg) { e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(myInstance, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); break; + case E1AP_BEARER_CONTEXT_MODIFICATION_REQ: + LOG_I(E1AP, "CUCP Task Received E1AP_BEARER_CONTEXT_MODIFICATION_REQ\n"); + e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(myInstance, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); + break; + default: LOG_E(E1AP, "Unknown message received in TASK_CUCP_E1\n"); break; diff --git a/openair2/E1AP/e1ap.h b/openair2/E1AP/e1ap.h index 965aa17acdc65923a695d650186959bc25c51f9a..6aa6f9918476833e09e101eb679f176e17a26ad6 100644 --- a/openair2/E1AP/e1ap.h +++ b/openair2/E1AP/e1ap.h @@ -30,38 +30,8 @@ #include "openair2/COMMON/e1ap_messages_types.h" #include "openair3/UTILS/conversions.h" #include "openair2/F1AP/f1ap_common.h" +#include "openair2/E1AP/e1ap_common.h" -#include <E1AP_Cause.h> -#include <E1AP_InitiatingMessage.h> -#include <E1AP_E1AP-PDU.h> -#include <E1AP_ProtocolIE-Field.h> -#include <E1AP_SupportedPLMNs-Item.h> -#include <E1AP_SuccessfulOutcome.h> -#include <E1AP_ProtocolIE-Field.h> -#include <E1AP_UnsuccessfulOutcome.h> -#include <E1AP_GNB-CU-UP-E1SetupFailure.h> -#include <E1AP_GNB-CU-UP-ConfigurationUpdate.h> -#include <E1AP_GNB-CU-UP-TNLA-To-Remove-Item.h> -#include <E1AP_CP-TNL-Information.h> -#include <E1AP_UP-Parameters-Item.h> -#include <E1AP_UP-TNL-Information.h> -#include <E1AP_PDU-Session-Resource-Setup-Item.h> -#include <E1AP_DRB-Setup-Item-EUTRAN.h> -#include <E1AP_DRB-Setup-Item-NG-RAN.h> -#include <E1AP_QoS-Flow-QoS-Parameter-Item.h> -#include <E1AP_QoS-Flow-Item.h> -#include <E1AP_DRB-Failed-List-NG-RAN.h> -#include <E1AP_DRB-Failed-Item-NG-RAN.h> -#include <E1AP_BearerContextSetupResponse.h> -#include <E1AP_BearerContextSetupRequest.h> -#include <E1AP_DRB-To-Setup-Item-EUTRAN.h> -#include <E1AP_DRB-To-Setup-Item-NG-RAN.h> -#include <E1AP_Cell-Group-Information-Item.h> -#include <E1AP_PDU-Session-Resource-To-Setup-Item.h> -#include <E1AP_GTPTunnel.h> -#include <E1AP_Non-Dynamic5QIDescriptor.h> -#include <E1AP_Dynamic5QIDescriptor.h> -#include <E1AP_T-ReorderingTimer.h> #endif diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c index 8b995bc12f631790295b6bd34bc0ea1f76c4f9db..bc0a6d58df92fcf984450b1909b583edc8c0dca6 100644 --- a/openair2/E1AP/e1ap_common.c +++ b/openair2/E1AP/e1ap_common.c @@ -51,6 +51,7 @@ void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req) { if (type == CPtype) { AssertFatal(e1ap_cp_inst[instance] == NULL, "Double call to E1 CP instance %d\n", (int)instance); e1ap_cp_inst[instance] = (e1ap_upcp_inst_t *) calloc(1, sizeof(e1ap_upcp_inst_t)); + memcpy(&e1ap_cp_inst[instance]->setupReq, req, sizeof(e1ap_setup_req_t)); } else if (type == UPtype) { AssertFatal(e1ap_up_inst[instance] == NULL, "Double call to E1 UP instance %d\n", (int)instance); e1ap_up_inst[instance] = (e1ap_upcp_inst_t *) calloc(1, sizeof(e1ap_upcp_inst_t)); diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h index 90d41e2699202376bf02915f13772d0bef375e19..26e632913f8b04af7ce78a73a1158c84bce8ff2f 100644 --- a/openair2/E1AP/e1ap_common.h +++ b/openair2/E1AP/e1ap_common.h @@ -25,6 +25,39 @@ #define E1AP_COMMON_H_ #include "openair2/E1AP/e1ap_default_values.h" #include "openair2/COMMON/e1ap_messages_types.h" + +#include <E1AP_Cause.h> +#include <E1AP_InitiatingMessage.h> +#include <E1AP_E1AP-PDU.h> +#include <E1AP_ProtocolIE-Field.h> +#include <E1AP_SupportedPLMNs-Item.h> +#include <E1AP_SuccessfulOutcome.h> +#include <E1AP_ProtocolIE-Field.h> +#include <E1AP_UnsuccessfulOutcome.h> +#include <E1AP_GNB-CU-UP-E1SetupFailure.h> +#include <E1AP_GNB-CU-UP-ConfigurationUpdate.h> +#include <E1AP_GNB-CU-UP-TNLA-To-Remove-Item.h> +#include <E1AP_CP-TNL-Information.h> +#include <E1AP_UP-Parameters-Item.h> +#include <E1AP_UP-TNL-Information.h> +#include <E1AP_PDU-Session-Resource-Setup-Item.h> +#include <E1AP_DRB-Setup-Item-EUTRAN.h> +#include <E1AP_DRB-Setup-Item-NG-RAN.h> +#include <E1AP_QoS-Flow-QoS-Parameter-Item.h> +#include <E1AP_QoS-Flow-Item.h> +#include <E1AP_DRB-Failed-List-NG-RAN.h> +#include <E1AP_DRB-Failed-Item-NG-RAN.h> +#include <E1AP_BearerContextSetupResponse.h> +#include <E1AP_BearerContextSetupRequest.h> +#include <E1AP_DRB-To-Setup-Item-EUTRAN.h> +#include <E1AP_DRB-To-Setup-Item-NG-RAN.h> +#include <E1AP_Cell-Group-Information-Item.h> +#include <E1AP_PDU-Session-Resource-To-Setup-Item.h> +#include <E1AP_GTPTunnel.h> +#include <E1AP_Non-Dynamic5QIDescriptor.h> +#include <E1AP_Dynamic5QIDescriptor.h> +#include <E1AP_T-ReorderingTimer.h> + int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length); e1ap_upcp_inst_t *getCxtE1(E1_t type, instance_t instance); diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 0b058233b52108cab4f3bbf82d02ef2f8fb79b70..54034d42f32f28c0995eb7e9286ada8d1602b723 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -700,10 +700,15 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); OCTET_STRING_TO_INT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - GtpuUpdateTunnelOutgoingTeid(getCxt(CUtype, instance)->gtpInst, + transport_layer_addr_t addr; + int sz=sizeof(drb_p->up_dl_tnl[0].tl_address); + memcpy(addr.buffer, &drb_p->up_dl_tnl[0].tl_address, sz); + addr.length = sz*8; + GtpuUpdateTunnelOutgoingPair(getCxt(CUtype, instance)->gtpInst, f1ap_ue_context_setup_resp->rnti, (ebi_t)drbs_setup_item_p->dRBID, - drb_p->up_dl_tnl[0].teid); + drb_p->up_dl_tnl[0].teid, + addr); } } @@ -1691,10 +1696,6 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); OCTET_STRING_TO_INT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - GtpuUpdateTunnelOutgoingTeid(getCxt(CUtype, instance)->gtpInst, - f1ap_ue_context_modification_resp->rnti, - (ebi_t)drbs_setupmod_item_p->dRBID, - drb_p->up_dl_tnl[0].teid); } } // SRBs_FailedToBeSetupMod_List diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index fdd23348517fc6563fb30c91483d1b70f79c799e..a9b0dfb36129b4406419edd45e6f669d88447e7a 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -468,11 +468,13 @@ typedef struct { } nr_security_configuration_t; typedef void (*nr_e1_bearer_cxt_msg_transfer_func_t)(e1ap_bearer_setup_req_t *req, instance_t instance); +typedef void (*nr_e1_ue_cxt_mod_msg_transfer_func_t)(MessageDef *msg, instance_t instance); typedef struct nr_mac_rrc_dl_if_s { /* TODO add other message types as necessary */ dl_rrc_message_transfer_func_t dl_rrc_message_transfer; nr_e1_bearer_cxt_msg_transfer_func_t nr_e1_bearer_cxt_msg_transfer; + nr_e1_ue_cxt_mod_msg_transfer_func_t nr_e1_ue_cxt_mod_msg_transfer; } nr_mac_rrc_dl_if_t; //---NR---(completely change)--------------------- diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 0eb21358319469ed39dfe50313594f7281b16870..25223f118a240f912510b61ea41f1e6b1507a552 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -225,3 +225,9 @@ void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req, void bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *req, instance_t instance); +void ue_cxt_mod_send_e1ap(MessageDef *msg, + instance_t instance); + +void ue_cxt_mod_direct(MessageDef *msg, + instance_t instance); + diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 26f7835513f00e5bdfca328176bb23a648405207..4a406bfc8a5bf0ada2a537fbad2996691e88e2c8 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -102,6 +102,7 @@ #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h" #include "openair2/F1AP/f1ap_common.h" +#include "openair2/E1AP/e1ap_common.h" #include "BIT_STRING.h" #include "assertions.h" @@ -202,24 +203,23 @@ static void rrc_gNB_mac_rrc_init(gNB_RRC_INST *rrc) { switch (rrc->node_type) { case ngran_gNB_CUCP: - rrc->cu_if.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_e1ap; + rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_e1ap; + rrc->mac_rrc.nr_e1_ue_cxt_mod_msg_transfer = ue_cxt_mod_send_e1ap; break; case ngran_gNB_CUUP: // CUUP should not have a RRC instance but we let it for now break; case ngran_gNB_CU: + case ngran_gNB: mac_rrc_dl_f1ap_init(&rrc->mac_rrc); rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_direct; + rrc->mac_rrc.nr_e1_ue_cxt_mod_msg_transfer = ue_cxt_mod_direct; break; case ngran_gNB_DU: /* silently drop this, as we currently still need the RRC at the DU. As * soon as this is not the case anymore, we can add the AssertFatal() */ //AssertFatal(1==0,"nothing to do for DU\n"); break; - case ngran_gNB: - mac_rrc_dl_direct_init(&rrc->mac_rrc); - rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_direct; - break; default: AssertFatal(0 == 1, "Unknown node type %d\n", rrc->node_type); break; @@ -3596,9 +3596,49 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch } +static void update_UL_UP_tunnel_info(e1ap_bearer_setup_req_t *req, instance_t instance, ue_id_t ue_id) { + for (int i=0; i < req->numPDUSessions; i++) { + for (int j=0; j < req->pduSession[i].numDRB2Setup; j++) { + DRB_nGRAN_to_setup_t *drb_p = req->pduSession[i].DRBnGRanList + j; + + transport_layer_addr_t newRemoteAddr; + newRemoteAddr.length = 32; // IPv4 + memcpy(newRemoteAddr.buffer, + &drb_p->tlAddress, + sizeof(in_addr_t)); + + GtpuUpdateTunnelOutgoingPair(instance, + ue_id, + (ebi_t)drb_p->id, + drb_p->teId, + newRemoteAddr); + } + } +} + +void rrc_CUUP_process_bearer_context_mod_req(e1ap_bearer_setup_req_t *req, instance_t instance) { + update_UL_UP_tunnel_info(req, instance, req->gNB_cu_cp_ue_id); + // TODO: send bearer cxt mod response +} + +void ue_cxt_mod_send_e1ap(MessageDef *msg, instance_t instance) { + int module_id = 0; + itti_send_msg_to_task(TASK_CUCP_E1, module_id, msg); +} + +void ue_cxt_mod_direct(MessageDef *msg, instance_t instance) { + e1ap_bearer_setup_req_t *req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg); + instance_t gtpInst = getCxt(CUtype, instance)->gtpInst; + + update_UL_UP_tunnel_info(req, gtpInst, req->rnti); + + int result = itti_free (ITTI_MSG_ORIGIN_ID(msg), msg); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); +} + static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, const char *msg_name, instance_t instance){ - f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); + f1ap_ue_context_setup_t *resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); protocol_ctxt_t ctxt = { .rnti = resp->rnti, .module_id = instance, @@ -3606,8 +3646,30 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, c .enb_flag = 1, .eNB_index = instance }; + gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti); + + MessageDef *msg_e1 = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_MODIFICATION_REQ); + e1ap_bearer_setup_req_t *req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_e1); + req->numPDUSessions = ue_context_p->ue_context.nb_of_pdusessions; + req->gNB_cu_cp_ue_id = ue_context_p->ue_context.gNB_ue_ngap_id; + req->rnti = ue_context_p->ue_context.rnti; + for (int i=0; i < req->numPDUSessions; i++) { + req->pduSession[i].numDRB2Setup = resp->drbs_to_be_setup_length; + for (int j=0; j < resp->drbs_to_be_setup_length; j++) { + f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j; + DRB_nGRAN_to_setup_t *drb_e1 = req->pduSession[i].DRBnGRanList + j; + + drb_e1->id = drb_f1->drb_id; + drb_e1->tlAddress = drb_f1->up_dl_tnl[0].tl_address; + drb_e1->teId = drb_f1->up_dl_tnl[0].teid; + } + } + + // send the F1 response message up to update F1-U tunnel info + rrc->cu_if.nr_e1_ue_cxt_mod_msg_transfer(msg_e1, instance); + NR_CellGroupConfig_t *cellGroupConfig = NULL; if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ @@ -4007,33 +4069,35 @@ void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_t } } -int drb_config_gtpu_create_e1(e1ap_bearer_setup_req_t *req, - gtpv1u_gnb_create_tunnel_req_t *create_tunnel_req, - gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp, - instance_t instance) { +int drb_config_N3gtpu_create_e1(e1ap_bearer_setup_req_t *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 *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, + 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; + 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 & 0xFFFF); + create_tunnel_req.num_tunnels = req->numPDUSessions; + create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF); + // Create N3 tunnel int ret = gtpv1u_create_ngu_tunnel( instance, - create_tunnel_req, + &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); + create_tunnel_req.ue_id); return ret; } @@ -4050,7 +4114,7 @@ int drb_config_gtpu_create_e1(e1ap_bearer_setup_req_t *req, &kUPint); nr_pdcp_e1_add_drbs(false, - create_tunnel_req->ue_id, + create_tunnel_req.ue_id, &DRB_configList, (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm, kUPenc, @@ -4060,46 +4124,61 @@ int drb_config_gtpu_create_e1(e1ap_bearer_setup_req_t *req, void gNB_CU_create_up_ul_tunnel(e1ap_bearer_setup_resp_t *resp, e1ap_bearer_setup_req_t *req, - instance_t instance, - ue_id_t ue_id) { + 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++) { - pdu_session_to_setup_t *pdu = req->pduSession + i; - - transport_layer_addr_t addr; - int size = sizeof(pdu->tlAddress_dl); - memcpy(addr.buffer, - &pdu->tlAddress_dl, - size); - addr.length = size * 8; - - resp->pduSession[i].tlAddress = pdu->tlAddress; - resp->pduSession[i].teId = newGtpuCreateTunnel(getCxt(CUtype, instance)->gtpInst, - ue_id, - pdu->DRBnGRanList[0].id, - pdu->DRBnGRanList[0].id, - 0xFFFF, // We will set the right value from DU answer - -1, // no qfi - addr, - pdu->tl_port_dl, - cu_f1u_data_req, - NULL); + 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; + } + } } } void rrc_gNB_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, instance_t instance) { - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; - gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; + protocol_ctxt_t ctxt={0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, req->gNB_cu_cp_ue_id, 0, 0, 0); + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp_N3={0}; // GTP tunnel for UL - drb_config_gtpu_create_e1(req, &create_tunnel_req, &create_tunnel_resp, instance); + drb_config_N3gtpu_create_e1(req, &create_tunnel_resp_N3, instance); 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); - gNB_CU_create_up_ul_tunnel(resp, req, instance, req->gNB_cu_cp_ue_id); + int remote_port = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd; + in_addr_t my_addr; + memcpy(&my_addr, + &getCxtE1(UPtype, instance)->setupReq.CUUP_e1_ip_address.ipv4_address, + sizeof(my_addr)); + gNB_CU_create_up_ul_tunnel(resp, req, instance, req->gNB_cu_cp_ue_id, remote_port, my_addr); resp->gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id; resp->numPDUSessions = req->numPDUSessions; @@ -4109,30 +4188,11 @@ void rrc_gNB_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, i pduSetup->id = pdu2Setup->sessionId; memcpy(&pduSetup->tlAddress, - &create_tunnel_resp.gnb_addr.buffer, + &create_tunnel_resp_N3.gnb_addr.buffer, sizeof(in_addr_t)); - pduSetup->teId = create_tunnel_resp.gnb_NGu_teid[i]; + pduSetup->teId = create_tunnel_resp_N3.gnb_NGu_teid[i]; 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; - - /* TODO: Set dummy values for UP Parameters for now */ - drbSetup->numUpParam = 1; - for (int k=0; k < drbSetup->numUpParam; k++) { - drbSetup->UpParamList[k].tlAddress = 0; - drbSetup->UpParamList[k].teId = 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 @@ -4143,8 +4203,7 @@ void rrc_gNB_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, i } void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, - e1ap_bearer_setup_resp_t *e1ap_resp, - e1ap_bearer_setup_req_t *e1ap_req) { + e1ap_bearer_setup_resp_t *e1ap_resp) { /*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*/ @@ -4169,19 +4228,16 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex SRBs[0].lcid = 2; /*Instruction towards the DU for DRB configuration and tunnel creation*/ - req->drbs_to_be_setup_length = e1ap_req->numPDUSessions; + req->drbs_to_be_setup_length = e1ap_resp->pduSession[0].numDRBSetup; req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)*req->drbs_to_be_setup_length); - for (int i=0; i < e1ap_req->numPDUSessions; i++) { + for (int i=0; i < e1ap_resp->pduSession[0].numDRBSetup; i++) { f1ap_drb_to_be_setup_t *DRBs = req->drbs_to_be_setup + i; - DRBs[i].drb_id = e1ap_req->pduSession[i].DRBnGRanList[0].id; + DRBs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id; DRBs[i].rlc_mode = RLC_MODE_AM; - DRBs[i].up_ul_tnl[0].tl_address = e1ap_req->pduSession[i].tlAddress; - DRBs[i].up_ul_tnl[0].port = e1ap_req->pduSession[i].tl_port; - DRBs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[i].teId; + DRBs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress; + DRBs[i].up_ul_tnl[0].port = RC.nrrrc[ctxt.module_id]->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_length = 1; - DRBs[i].up_dl_tnl[0].tl_address = e1ap_req->pduSession[i].tlAddress_dl; - DRBs[i].up_dl_tnl[0].port = e1ap_req->pduSession[i].tl_port_dl; - DRBs[i].up_dl_tnl_length = 1; } itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p); @@ -4189,8 +4245,7 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req, instance_t instance) { - 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, req->gNB_cu_cp_ue_id); + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)], req->rnti); 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); @@ -4205,22 +4260,16 @@ void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req, instance_t instan instance); if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n"); - if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)){ + if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) { rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL); } else { - for (int i=0; i < req->numPDUSessions; i++) { - pdu_session_to_setup_t *pdu = req->pduSession + i; - - pdu->tlAddress = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr); - pdu->tl_port = RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd; - pdu->tlAddress_dl = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.remote_addr); - pdu->tl_port_dl = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd; - } - e1ap_bearer_setup_resp_t resp; // Used to store teids - gNB_CU_create_up_ul_tunnel(&resp, req, instance, ue_context_p->ue_context.rnti); + 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(CUtype, instance)->gtpInst; + gNB_CU_create_up_ul_tunnel(&resp, req, gtpInst, ue_context_p->ue_context.rnti, remote_port, my_addr); - prepare_and_send_ue_context_modification_f1(ue_context_p, &resp, req); + prepare_and_send_ue_context_modification_f1(ue_context_p, &resp); } // call the code that sends UE context modification message to DU } @@ -4229,17 +4278,12 @@ void bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *req, instance_t instance // create ITTI msg and send to CUCP E1 task to send via SCTP // then in CUUP the function rrc_gNB_process_e1_bearer_context_setup_req - 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, req->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); - - MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ); + MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_SETUP_REQ); e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p); memcpy(bearer_req, req, sizeof(e1ap_bearer_setup_req_t)); free(req); - itti_send_msg_to_task (TASK_CUCP_E1, ctxt.module_id, msg_p); + itti_send_msg_to_task (TASK_CUCP_E1, instance, msg_p); } @@ -4267,20 +4311,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp ue_context_p->ue_context.setup_pdu_sessions += resp->numPDUSessions; // TODO: SV: combine e1ap_bearer_setup_req_t and e1ap_bearer_setup_resp_t and minimize assignments - e1ap_bearer_setup_req_t req; - req.numPDUSessions = resp->numPDUSessions; - for (int i=0; i < resp->numPDUSessions; i++) { - pdu_session_to_setup_t *pdu = req.pduSession + i; - - pdu->DRBnGRanList[0].id = resp->pduSession[i].DRBnGRanList[0].id; - - pdu->tlAddress = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr); - pdu->tl_port = RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd; - pdu->tlAddress_dl = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.remote_addr); - pdu->tl_port_dl = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd; - - } - prepare_and_send_ue_context_modification_f1(ue_context_p, resp, &req); + prepare_and_send_ue_context_modification_f1(ue_context_p, resp); } ///---------------------------------------------------------------------------------------------------------------/// diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index dac634c6ed07b4b6f7320279fa01f43ad1c6ea30..49dfc84c597bb1688a5c0a97e423c2de3c84a253 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -497,12 +497,14 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( return (-1); } else { PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).gNB_ue_ngap_id; ue_context_p->ue_context.amf_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).amf_ue_ngap_id; ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nas_pdu_flag; uint8_t nb_pdusessions_tosetup = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_pdusessions; if (nb_pdusessions_tosetup != 0) { + AssertFatal(rrc->node_type != ngran_gNB_CUCP, "PDU sessions in Initial context setup request not handled by E1 yet\n"); gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE) @@ -992,6 +994,7 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( e1ap_bearer_setup_req_t *bearer_req = calloc(1, sizeof(e1ap_bearer_setup_req_t)); bearer_req->gNB_cu_cp_ue_id = gNB_ue_ngap_id; + bearer_req->rnti = ue_context_p->ue_context.rnti; bearer_req->cipheringAlgorithm = ue_context_p->ue_context.ciphering_algorithm; memcpy(bearer_req->encryptionKey, ue_context_p->ue_context.kgnb, sizeof(ue_context_p->ue_context.kgnb)); bearer_req->integrityProtectionAlgorithm = ue_context_p->ue_context.integrity_algorithm; diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index a13f2b4d0c23268758f4335c4f798a1236ce276c..4d7cca38175e535239ea9f7a6a4fe33fba8e5d7e 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -546,7 +546,11 @@ instance_t gtpv1Init(openAddr_t context) { return id; } -void GtpuUpdateTunnelOutgoingTeid(instance_t instance, ue_id_t ue_id, ebi_t bearer_id, teid_t newOutgoingTeid) { +void GtpuUpdateTunnelOutgoingPair(instance_t instance, + ue_id_t ue_id, + ebi_t bearer_id, + teid_t newOutgoingTeid, + transport_layer_addr_t newRemoteAddr) { pthread_mutex_lock(&globGtp.gtp_lock); getInstRetVoid(compatInst(instance)); getRntiRetVoid(inst, ue_id); @@ -560,7 +564,36 @@ void GtpuUpdateTunnelOutgoingTeid(instance_t instance, ue_id_t ue_id, ebi_t bear } ptr2->second.teid_outgoing = newOutgoingTeid; - LOG_I(GTPU, "[%ld] Tunnel Outgoing TEID updated to %x \n", instance, ptr2->second.teid_outgoing); + + int addrs_length_in_bytes = newRemoteAddr.length / 8; + + switch (addrs_length_in_bytes) { + case 4: + memcpy(&ptr2->second.outgoing_ip_addr,newRemoteAddr.buffer,4); + break; + + case 16: + memcpy(ptr2->second.outgoing_ip6_addr.s6_addr,newRemoteAddr.buffer, + 16); + break; + + case 20: + memcpy(&ptr2->second.outgoing_ip_addr,newRemoteAddr.buffer,4); + memcpy(ptr2->second.outgoing_ip6_addr.s6_addr, + newRemoteAddr.buffer+4, + 16); + + default: + AssertFatal(false, "SGW Address size impossible"); + } + + char ip4[INET_ADDRSTRLEN]; + char ip6[INET6_ADDRSTRLEN]; + LOG_I(GTPU, "[%ld] Tunnel Outgoing TEID updated to %x, remote IPv4 to: %s, IPv6 to: %s\n", + instance, + ptr2->second.teid_outgoing, + inet_ntop(AF_INET,(void *)&ptr2->second.outgoing_ip_addr, ip4,INET_ADDRSTRLEN ), + inet_ntop(AF_INET6,(void *)ptr2->second.outgoing_ip6_addr.s6_addr, ip6, INET6_ADDRSTRLEN)); pthread_mutex_unlock(&globGtp.gtp_lock); return; } @@ -619,7 +652,7 @@ teid_t newGtpuCreateTunnel(instance_t instance, case 20: memcpy(&tmp->outgoing_ip_addr,remoteAddr.buffer,4); - memcpy(&tmp->outgoing_ip6_addr.s6_addr, + memcpy(tmp->outgoing_ip6_addr.s6_addr, remoteAddr.buffer+4, 16); diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index 3e06ef0786bd5baa21c628a5677d36a47d55c515..aa22a1990f689e1f9e5dc7aac2a5b9a98b25e33e 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -91,7 +91,13 @@ extern "C" { int port, gtpCallback callBack, gtpCallbackSDAP callBackSDAP); - void GtpuUpdateTunnelOutgoingTeid(instance_t instance, ue_id_t ue_id, ebi_t bearer_id, teid_t newOutgoingTeid); + + void GtpuUpdateTunnelOutgoingPair(instance_t instance, + ue_id_t ue_id, + ebi_t bearer_id, + teid_t newOutgoingTeid, + transport_layer_addr_t newRemoteAddr); + int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id); int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id); instance_t gtpv1Init(openAddr_t context);