diff --git a/CMakeLists.txt b/CMakeLists.txt index e6147ce3fb..b80eb72986 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1474,6 +1474,7 @@ add_library(L2_UE ${MAC_SRC_UE} ) target_link_libraries(L2_UE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +target_link_libraries(L2_UE PRIVATE GTPV1U) add_library(L2_UE_LTE_NR ${L2_RRC_SRC_UE} diff --git a/doc/F1AP/F1-design.md b/doc/F1AP/F1-design.md index 627e2b4fc2..65ea6b38cf 100644 --- a/doc/F1AP/F1-design.md +++ b/doc/F1AP/F1-design.md @@ -378,15 +378,15 @@ You might also want to consult TS 38.401 regarding the message exchange. ### General In the DU in UL, RLC checks in `deliver_sdu()` if we are operating in split -mode, and either (direct) calls `pdcp_data_ind` (DRB) or (f1ap) sends an -`GTPV1U_TUNNEL_DATA_REQ` ITTI message to the GTP task. +mode, and either (direct) calls `pdcp_data_ind` (DRB) or (f1ap) sends a GTP +message through the GTP API. In the CU in UL, assuming the tunnel is in place, GTP decapsulates the packet and calls the callback `cu_f1u_data_req()`, which calls `pdcp_data_ind()` in CU. In the CU in DL, the PDCP function `deliver_pdu_drb_gnb()` either (direct) calls -into the RLC via `enqueue_rlc_data_req()`, or (f1ap) sends a -`GTPV1U_TUNNEL_DATA_REQ` ITTI message to the GTP task. +into the RLC via `enqueue_rlc_data_req()`, or (f1ap) sends a GTP message +through the GTP API. In the DU in DL, assuming the GTP-U tunnel exists, GTP decapsulates the packet and calls the reception call back `du_rlc_data_req()`, which calls diff --git a/doc/SW_archi.md b/doc/SW_archi.md index b186bea524..6ba78ad8f1 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -338,7 +338,7 @@ On the Tx side (downlink in gNB), the entry functions `nr_pdcp_data_req_drb()` a ## PDCP Rx flow -At the Rx side, `pdcp_data_ind()` serves as the entry point for receiving data from RLC. Within `pdcp_data_ind()`, the PDCP manager mutex protects access to the PDU receiving function of PDCP (`recv_pdu()` callback corresponding to `nr_pdcp_entity_recv_pdu()` for DRBs). Following this, the `deliver_sdu_drb()` function dispatches the received data to the GTP thread via an ITTI message (`GTPV1U_TUNNEL_DATA_REQ`). +At the Rx side, `pdcp_data_ind()` serves as the entry point for receiving data from RLC. Within `pdcp_data_ind()`, the PDCP manager mutex protects access to the PDU receiving function of PDCP (`recv_pdu()` callback corresponding to `nr_pdcp_entity_recv_pdu()` for DRBs). Following this, the `deliver_sdu_drb()` function dispatches the received data to the SDAP sublayer. ## PDCP security diff --git a/openair2/COMMON/gtpv1_u_messages_def.h b/openair2/COMMON/gtpv1_u_messages_def.h index 35af0c04e7..19001b883e 100644 --- a/openair2/COMMON/gtpv1_u_messages_def.h +++ b/openair2/COMMON/gtpv1_u_messages_def.h @@ -20,7 +20,6 @@ */ -MESSAGE_DEF(GTPV1U_TUNNEL_DATA_REQ, MESSAGE_PRIORITY_MED, gtpv1u_tunnel_data_req_t, Gtpv1uTunnelDataReq) MESSAGE_DEF(GTPV1U_ENB_DATA_FORWARDING_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_data_forwarding_req_t,Gtpv1uDataForwardingReq) MESSAGE_DEF(GTPV1U_ENB_DATA_FORWARDING_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_data_forwarding_ind_t,Gtpv1uDataForwardingInd) MESSAGE_DEF(GTPV1U_ENB_END_MARKER_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_req_t, Gtpv1uEndMarkerReq) diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 0a2691e643..5f12d1e9a2 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -30,7 +30,6 @@ #define NR_GTPV1U_MAX_BEARERS_PER_UE max_val_NR_DRB_Identity #define GTPV1U_ENB_TUNNEL_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uTunnelDataInd -#define GTPV1U_TUNNEL_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uTunnelDataReq #define GTPV1U_ENB_DATA_FORWARDING_REQ(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uDataForwardingReq #define GTPV1U_ENB_DATA_FORWARDING_IND(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uDataForwardingInd #define GTPV1U_ENB_END_MARKER_REQ(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uEndMarkerReq @@ -107,15 +106,6 @@ typedef struct gtpv1u_enb_delete_tunnel_resp_s { teid_t enb_S1u_teid; ///< local S1U Tunnel Endpoint Identifier to be deleted } gtpv1u_enb_delete_tunnel_resp_t; - -typedef struct gtpv1u_tunnel_data_req_s { - uint8_t *buffer; - uint32_t length; - uint32_t offset; ///< start of message offset in buffer - ue_id_t ue_id; - rb_id_t bearer_id; -} gtpv1u_tunnel_data_req_t; - typedef struct gtpv1u_enb_data_forwarding_req_s { uint8_t *buffer; uint32_t length; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 3356889bf7..e8042abd80 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -597,7 +597,6 @@ bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, uint8_t rb_offset= (srb_flagP == 0) ? DTCH -1 :0; uint16_t pdcp_uid=0; - MessageDef *message_p = NULL; uint32_t rx_hfn_for_count; int pdcp_sn_for_count; int security_ok; @@ -999,19 +998,11 @@ bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, if (LINK_ENB_PDCP_TO_GTPV1U) { if ((true == ctxt_pP->enb_flag) && (false == srb_flagP)) { - LOG_D(PDCP, "Sending packet to GTP, Calling GTPV1U_TUNNEL_DATA_REQ ue %lx rab %ld len %u\n", ctxt_pP->rntiMaybeUEid, rb_id + 4, sdu_buffer_sizeP - payload_offset); - message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0, GTPV1U_TUNNEL_DATA_REQ, - sizeof(gtpv1u_tunnel_data_req_t) + - sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX ); - AssertFatal(message_p != NULL, "OUT OF MEMORY"); - gtpv1u_tunnel_data_req_t *req=>PV1U_TUNNEL_DATA_REQ(message_p); - req->buffer = (uint8_t*)(req+1); - memcpy(req->buffer + GTPU_HEADER_OVERHEAD_MAX, sdu_buffer_pP + payload_offset, sdu_buffer_sizeP - payload_offset); - req->length = sdu_buffer_sizeP - payload_offset; - req->offset = GTPU_HEADER_OVERHEAD_MAX; - req->ue_id = ctxt_pP->rntiMaybeUEid; - req->bearer_id = rb_id + 4; - itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); + ue_id_t ue_id = ctxt_pP->rntiMaybeUEid; + uint8_t *gtp_buf = sdu_buffer_pP + payload_offset; + size_t gtp_len = sdu_buffer_sizeP - payload_offset; + LOG_D(PDCP, "Sending packet to GTP ue %lx rab %ld len %ld\n", ue_id, rb_id + 4, gtp_len); + gtpv1uSendDirect(INSTANCE_DEFAULT, ue_id, rb_id + 4, gtp_buf, gtp_len, false, false); packet_forwarded = true; } } else { diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index cb80ec99ce..7691871b33 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -718,23 +718,9 @@ static void deliver_pdu_drb_gnb(void *deliver_pdu_data, ue_id_t ue_id, int rb_id protocol_ctxt_t ctxt = { .enb_flag = 1, .rntiMaybeUEid = ue_data.secondary_ue }; if (NODE_IS_CU(node_type)) { - MessageDef *message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0, - GTPV1U_TUNNEL_DATA_REQ, - sizeof(gtpv1u_tunnel_data_req_t) - + size - + GTPU_HEADER_OVERHEAD_MAX); - AssertFatal(message_p != NULL, "OUT OF MEMORY"); - gtpv1u_tunnel_data_req_t *req=>PV1U_TUNNEL_DATA_REQ(message_p); - uint8_t *gtpu_buffer_p = (uint8_t*)(req+1); - memcpy(gtpu_buffer_p + GTPU_HEADER_OVERHEAD_MAX, buf, size); - req->buffer = gtpu_buffer_p; - req->length = size; - req->offset = GTPU_HEADER_OVERHEAD_MAX; - req->ue_id = ue_id; // use CU UE ID as GTP will use that to look up TEID - req->bearer_id = rb_id; LOG_D(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size); extern instance_t CUuniqInstance; - itti_send_msg_to_task(TASK_GTPV1_U, CUuniqInstance, message_p); + gtpv1uSendDirect(CUuniqInstance, ue_id, rb_id, (uint8_t *)buf, size, false, false); } else { uint8_t *memblock = malloc16(size); memcpy(memblock, buf, size); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 2ebd18f5e7..64a152f847 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -40,6 +40,7 @@ #include "openair2/F1AP/f1ap_du_rrc_message_transfer.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair3/ocp-gtpu/gtp_itf.h" extern RAN_CONTEXT_t RC; @@ -525,18 +526,9 @@ rb_found: itti_send_msg_to_task(TASK_DU_F1, ENB_MODULE_ID_TO_INSTANCE(0 /*ctxt_pP->module_id*/), msg); return; } else { - MessageDef *msg = itti_alloc_new_message_sized(TASK_RLC_ENB, 0, GTPV1U_TUNNEL_DATA_REQ, - sizeof(gtpv1u_tunnel_data_req_t) + size); - gtpv1u_tunnel_data_req_t *req=>PV1U_TUNNEL_DATA_REQ(msg); - req->buffer=(uint8_t*)(req+1); - memcpy(req->buffer,buf,size); - req->length=size; - req->offset = 0; - req->ue_id = ue->ue_id; - req->bearer_id=rb_id; LOG_D(RLC, "Received uplink user-plane traffic at RLC-DU to be sent to the CU, size %d \n", size); extern instance_t DUuniqInstance; - itti_send_msg_to_task(TASK_GTPV1_U, DUuniqInstance, msg); + gtpv1uSendDirect(DUuniqInstance, ue->ue_id, rb_id, (uint8_t*) buf, size, false, false); return; } } diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index bcc93c87dc..bf9eb97666 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -240,24 +240,14 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, } } + uint8_t *gtp_buf = (uint8_t *)(buf + offset); + size_t gtp_len = size - offset; + // Pushing SDAP SDU to GTP-U Layer - MessageDef *message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, - 0, - GTPV1U_TUNNEL_DATA_REQ, - sizeof(gtpv1u_tunnel_data_req_t) - + size + GTPU_HEADER_OVERHEAD_MAX - offset); - AssertFatal(message_p != NULL, "OUT OF MEMORY"); - gtpv1u_tunnel_data_req_t *req = >PV1U_TUNNEL_DATA_REQ(message_p); - uint8_t *gtpu_buffer_p = (uint8_t *) (req + 1); - memcpy(gtpu_buffer_p + GTPU_HEADER_OVERHEAD_MAX, buf + offset, size - offset); - req->buffer = gtpu_buffer_p; - req->length = size - offset; - req->offset = GTPU_HEADER_OVERHEAD_MAX; - req->ue_id = ue_id; - req->bearer_id = pdusession_id; - LOG_D(SDAP, "%s() sending message to gtp size %d\n", __func__, size-offset); + LOG_D(SDAP, "sending message to gtp size %ld\n", gtp_len); // very very dirty hack gloabl var N3GTPUInst - itti_send_msg_to_task(TASK_GTPV1_U, *N3GTPUInst, message_p); + instance_t inst = *N3GTPUInst; + gtpv1uSendDirect(inst, ue_id, pdusession_id, gtp_buf, gtp_len, false, false); } else { //nrUE /* * TS 37.324 5.2 Data transfer diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index b9ffea6531..3036565fad 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -193,7 +193,7 @@ instance_t legacyInstanceMapping=0; auto ptrUe=insT->ue2te_mapping.find(Ue); \ \ if ( ptrUe==insT->ue2te_mapping.end() ) { \ - LOG_E(GTPU, "[%ld] gtpv1uSend failed: while getting ue id %ld in hashtable ue_mapping\n", instance, ue_id); \ + LOG_E(GTPU, "[%ld] %s failed: while getting ue id %ld in hashtable ue_mapping\n", instance, __func__, ue_id); \ pthread_mutex_unlock(&globGtp.gtp_lock); \ return; \ } @@ -202,7 +202,7 @@ instance_t legacyInstanceMapping=0; auto ptrUe=insT->ue2te_mapping.find(Ue); \ \ if ( ptrUe==insT->ue2te_mapping.end() ) { \ - LOG_E(GTPU, "[%ld] gtpv1uSend failed: while getting ue id %ld in hashtable ue_mapping\n", instance, ue_id); \ + LOG_E(GTPU, "[%ld] %s failed: while getting ue id %ld in hashtable ue_mapping\n", instance, __func__, ue_id); \ pthread_mutex_unlock(&globGtp.gtp_lock); \ return GTPNOK; \ } @@ -286,38 +286,48 @@ static int gtpv1uCreateAndSendMsg(int h, return !GTPNOK; } -static void gtpv1uSend(instance_t instance, gtpv1u_tunnel_data_req_t *req, bool seqNumFlag, bool npduNumFlag) { - uint8_t *buffer=req->buffer+req->offset; - size_t length=req->length; - ue_id_t ue_id=req->ue_id; - int bearer_id=req->bearer_id; +void gtpv1uSendDirect(instance_t instance, + ue_id_t ue_id, + int bearer_id, + uint8_t *buf, + size_t len, + bool seqNumFlag, + bool npduNumFlag) +{ pthread_mutex_lock(&globGtp.gtp_lock); getInstRetVoid(compatInst(instance)); getUeRetVoid(inst, ue_id); - auto ptr2=ptrUe->second.bearers.find(bearer_id); + auto ptr2 = ptrUe->second.bearers.find(bearer_id); - if ( ptr2 == ptrUe->second.bearers.end() ) { - LOG_E(GTPU,"[%ld] GTP-U instance: sending a packet to a non existant UE:RAB: %lx/%x\n", instance, ue_id, bearer_id); + if (ptr2 == ptrUe->second.bearers.end()) { + LOG_E(GTPU, "[%ld] GTP-U instance: sending a packet to a non existant UE:RAB: %lx/%x\n", instance, ue_id, bearer_id); pthread_mutex_unlock(&globGtp.gtp_lock); return; } - LOG_D(GTPU,"[%ld] sending a packet to UE:RAB:teid %lx/%x/%x, len %lu, oldseq %d, oldnum %d\n", - instance, ue_id, bearer_id,ptr2->second.teid_outgoing,length, ptr2->second.seqNum,ptr2->second.npduNum ); + LOG_D(GTPU, + "[%ld] sending a packet to UE:RAB:teid %lx/%x/%x, len %lu, oldseq %d, oldnum %d\n", + instance, + ue_id, + bearer_id, + ptr2->second.teid_outgoing, + len, + ptr2->second.seqNum, + ptr2->second.npduNum); - if(seqNumFlag) + if (seqNumFlag) ptr2->second.seqNum++; - if(npduNumFlag) + if (npduNumFlag) ptr2->second.npduNum++; // copy to release the mutex - gtpv1u_bearer_t tmp=ptr2->second; + gtpv1u_bearer_t tmp = ptr2->second; pthread_mutex_unlock(&globGtp.gtp_lock); if (tmp.outgoing_qfi != -1) { - Gtpv1uExtHeaderT ext = { 0 }; + Gtpv1uExtHeaderT ext = {0}; ext.ExtHeaderLen = 1; // in quad bytes EXT_HDR_LNTH_OCTET_UNITS ext.pdusession_cntr.spare = 0; ext.pdusession_cntr.PDU_type = UL_PDU_SESSION_INFORMATION; @@ -331,8 +341,8 @@ static void gtpv1uSend(instance_t instance, gtpv1u_tunnel_data_req_t *req, bool tmp.outgoing_port, GTP_GPDU, tmp.teid_outgoing, - buffer, - length, + buf, + len, seqNumFlag, npduNumFlag, tmp.seqNum, @@ -341,8 +351,20 @@ static void gtpv1uSend(instance_t instance, gtpv1u_tunnel_data_req_t *req, bool (uint8_t *)&ext, sizeof(ext)); } else { - gtpv1uCreateAndSendMsg( - compatInst(instance), tmp.outgoing_ip_addr, tmp.outgoing_port, GTP_GPDU, tmp.teid_outgoing, buffer, length, seqNumFlag, npduNumFlag, tmp.seqNum, tmp.npduNum, NO_MORE_EXT_HDRS, NULL, 0); + gtpv1uCreateAndSendMsg(compatInst(instance), + tmp.outgoing_ip_addr, + tmp.outgoing_port, + GTP_GPDU, + tmp.teid_outgoing, + buf, + len, + seqNumFlag, + npduNumFlag, + tmp.seqNum, + tmp.npduNum, + NO_MORE_EXT_HDRS, + NULL, + 0); } } @@ -403,9 +425,10 @@ static void gtpv1uSendDlDeliveryStatus(instance_t instance, gtpv1u_DU_buffer_rep compatInst(instance), tmp.outgoing_ip_addr, tmp.outgoing_port, GTP_GPDU, tmp.teid_outgoing, NULL, 0, false, false, 0, 0, NR_RAN_CONTAINER, extensionHeader->buffer, extensionHeader->length); } -static void gtpv1uEndTunnel(instance_t instance, gtpv1u_tunnel_data_req_t *req) { - ue_id_t ue_id=req->ue_id; - int bearer_id=req->bearer_id; +static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *req) +{ + ue_id_t ue_id=req->rnti; + int bearer_id=req->rab_id; pthread_mutex_lock(&globGtp.gtp_lock); getInstRetVoid(compatInst(instance)); getUeRetVoid(inst, ue_id); @@ -1287,11 +1310,6 @@ void *gtpv1uTask(void *args) { switch (msgType) { // DATA TO BE SENT TO UDP - case GTPV1U_TUNNEL_DATA_REQ: { - gtpv1uSend(compatInst(myInstance), >PV1U_TUNNEL_DATA_REQ(message_p), false, false); - } - break; - case GTPV1U_DU_BUFFER_REPORT_REQ:{ gtpv1uSendDlDeliveryStatus(compatInst(myInstance), >PV1U_DU_BUFFER_REPORT_REQ(message_p)); } @@ -1305,8 +1323,8 @@ void *gtpv1uTask(void *args) { break; case GTPV1U_ENB_END_MARKER_REQ: - gtpv1uEndTunnel(compatInst(myInstance), >PV1U_TUNNEL_DATA_REQ(message_p)); - itti_free(TASK_GTPV1_U, GTPV1U_TUNNEL_DATA_REQ(message_p).buffer); + gtpv1uEndTunnel(compatInst(myInstance), >PV1U_ENB_END_MARKER_REQ(message_p)); + itti_free(TASK_GTPV1_U, GTPV1U_ENB_END_MARKER_REQ(message_p).buffer); break; case GTPV1U_ENB_DATA_FORWARDING_REQ: diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index ce806f0bfc..f3f336dc2c 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -103,6 +103,9 @@ extern "C" { int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id); 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); + + void gtpv1uSendDirect(instance_t instance, ue_id_t ue_id, int bearer_id, uint8_t *buf, size_t len, bool seqNumFlag, bool npduNumFlag); + instance_t gtpv1Init(openAddr_t context); void *gtpv1uTask(void *args);