From a77c1d32026f4f4b8a9c0a54d8a7a0f87cf4ef84 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 29 Mar 2022 12:17:37 +0200 Subject: [PATCH] Trigger first DL Data Delivery status from DU to report the buffer availability to the CU -After that no DL traffic is getting blocked at the Accelleran CU for low values of throughput -Remaining to remove the hardcoded value of buffer availability and report the actual value from the DU. --- openair2/COMMON/gtpv1_u_messages_def.h | 3 +- openair2/COMMON/gtpv1_u_messages_types.h | 8 +++ openair2/RRC/NR/rrc_gNB.c | 15 +++++ openair3/ocp-gtpu/gtp_itf.cpp | 74 ++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/gtpv1_u_messages_def.h b/openair2/COMMON/gtpv1_u_messages_def.h index 44e9d4fbdf..e0e5db5b7f 100644 --- a/openair2/COMMON/gtpv1_u_messages_def.h +++ b/openair2/COMMON/gtpv1_u_messages_def.h @@ -27,4 +27,5 @@ MESSAGE_DEF(GTPV1U_ENB_END_MARKER_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_end MESSAGE_DEF(GTPV1U_ENB_END_MARKER_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_ind_t, Gtpv1uEndMarkerInd) MESSAGE_DEF(GTPV1U_REQ, MESSAGE_PRIORITY_MED, Gtpv1uReq, gtpv1uReq) -MESSAGE_DEF(GTPV1U_GNB_TUNNEL_DATA_REQ, MESSAGE_PRIORITY_MED, gtpv1u_gnb_tunnel_data_req_t, NRGtpv1uTunnelDataReq) +MESSAGE_DEF(GTPV1U_GNB_TUNNEL_DATA_REQ, MESSAGE_PRIORITY_MED, gtpv1u_gnb_tunnel_data_req_t, NRGtpv1uTunnelDataReq) +MESSAGE_DEF(GTPV1U_DU_BUFFER_REPORT_REQ, MESSAGE_PRIORITY_MED, gtpv1u_DU_buffer_report_req_t, NRGtpv1uBufferReportReq) diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 096f0f4697..4111b00024 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -39,6 +39,8 @@ #define GTPV1U_GNB_TUNNEL_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uTunnelDataReq +#define GTPV1U_DU_BUFFER_REPORT_REQ(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uBufferReportReq + #define GTPV1U_ALL_TUNNELS_TEID (teid_t)0xFFFFFFFF typedef struct gtpv1u_enb_create_x2u_tunnel_req_s { @@ -213,4 +215,10 @@ typedef struct gtpv1u_gnb_tunnel_data_req_s { pdusessionid_t pdusession_id; } gtpv1u_gnb_tunnel_data_req_t; +typedef struct gtpv1u_DU_buffer_report_req_s { + uint32_t buffer_availability; + rnti_t rnti; + pdusessionid_t pdusession_id; +} gtpv1u_DU_buffer_report_req_t; + #endif /* GTPV1_U_MESSAGES_TYPES_H_ */ diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index f7a53c59a4..d7ff9492a5 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -3487,6 +3487,21 @@ static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, co } else if(req->ReconfigComplOutcome == RRCreconf_success){ LOG_I(NR_RRC, "CU reporting RRC Reconfiguration success \n"); + if(ue_context_p->ue_context.DRB_configList!=NULL){ + LOG_I(NR_RRC, "Send first DDD buffer status reporting towards the CU through an ITTI message to gtp-u \n"); + uint8_t drb_id = ue_context_p->ue_context.DRB_configList->list.array[0]->drb_Identity; + rnti_t rnti = ue_context_p->ue_context.rnti; + LOG_I(NR_RRC, "Reported in DDD drb_id:%d, rnti:%d\n", drb_id, rnti); + MessageDef *msg = itti_alloc_new_message_sized(TASK_RRC_GNB, 0, GTPV1U_DU_BUFFER_REPORT_REQ, + sizeof(gtpv1u_gnb_tunnel_data_req_t)); + gtpv1u_DU_buffer_report_req_t *req=>PV1U_DU_BUFFER_REPORT_REQ(msg); + req->pdusession_id = drb_id; + req->rnti = rnti; + req->buffer_availability = 1000000; //Hardcoding to be removed and read the actual RLC buffer availability instead + extern instance_t DUuniqInstance; + itti_send_msg_to_task(TASK_GTPV1_U, DUuniqInstance, msg); + + } } /* Fill the UE context setup response ITTI message to send to F1AP */ diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index c79f7ecce2..20db486561 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -286,6 +286,74 @@ static void gtpv1uSend2(instance_t instance, gtpv1u_gnb_tunnel_data_req_t *req, buffer, length, seqNumFlag, npduNumFlag, false, tmp.seqNum, tmp.npduNum, 0, NULL, 0) ; } +static void fillDlDeliveryStatusReport(extensionHeader_t *extensionHeader, uint32_t RLC_buffer_availability, uint32_t NR_PDCP_PDU_SN){ + + extensionHeader->buffer[0] = (1+sizeof(DlDataDeliveryStatus_flagsT)+(NR_PDCP_PDU_SN>0?3:0)+(NR_PDCP_PDU_SN>0?1:0)+1)/4; + DlDataDeliveryStatus_flagsT DlDataDeliveryStatus; + DlDataDeliveryStatus.deliveredPdcpSn = 0; + DlDataDeliveryStatus.transmittedPdcpSn= NR_PDCP_PDU_SN>0?1:0; + DlDataDeliveryStatus.pduType = 1; + DlDataDeliveryStatus.drbBufferSize = htonl(RLC_buffer_availability); + memcpy(extensionHeader->buffer+1, &DlDataDeliveryStatus, sizeof(DlDataDeliveryStatus_flagsT)); + uint8_t offset = sizeof(DlDataDeliveryStatus_flagsT)+1; + + if(NR_PDCP_PDU_SN>0){ + extensionHeader->buffer[offset] = (NR_PDCP_PDU_SN >> 16) & 0xff; + extensionHeader->buffer[offset+1] = (NR_PDCP_PDU_SN >> 8) & 0xff; + extensionHeader->buffer[offset+2] = NR_PDCP_PDU_SN & 0xff; + LOG_D(GTPU, "Octets reporting NR_PDCP_PDU_SN, extensionHeader->buffer[offset]: %u, extensionHeader->buffer[offset+1]:%u, extensionHeader->buffer[offset+2]:%u \n", extensionHeader->buffer[offset], extensionHeader->buffer[offset+1],extensionHeader->buffer[offset+2]); + extensionHeader->buffer[offset+3] = 0x00; //Padding octet + offset = offset+3; + } + extensionHeader->buffer[offset] = 0x00; //No more extension headers + /*Total size of DDD_status PDU = size of mandatory part + + * 3 octets for highest transmitted/delivered PDCP SN + + * 1 octet for padding + 1 octet for next extension header type, + * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ + extensionHeader->length = 1+sizeof(DlDataDeliveryStatus_flagsT)+ + (NR_PDCP_PDU_SN>0?3:0)+ + (NR_PDCP_PDU_SN>0?1:0)+1; +} + +static void gtpv1uSendDlDeliveryStatus(instance_t instance, gtpv1u_DU_buffer_report_req_t *req){ + rnti_t rnti=req->rnti; + int rab_id=req->pdusession_id; + pthread_mutex_lock(&globGtp.gtp_lock); + auto inst=&globGtp.instances[compatInst(instance)]; + auto ptrRnti=inst->ue2te_mapping.find(rnti); + + if ( ptrRnti==inst->ue2te_mapping.end() ) { + LOG_E(GTPU, "[%ld] GTP-U gtpv1uSend failed: while getting ue rnti %x in hashtable ue_mapping\n", instance, rnti); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } + + map::iterator ptr2=ptrRnti->second.bearers.find(rab_id); + + if ( ptr2 == ptrRnti->second.bearers.end() ) { + LOG_D(GTPU,"GTP-U instance: %ld sending a packet to a non existant RNTI:RAB: %x/%x\n", instance, rnti, rab_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } + + extensionHeader_t *extensionHeader; + extensionHeader = (extensionHeader_t *) calloc(1, sizeof(extensionHeader_t)); + fillDlDeliveryStatusReport(extensionHeader, req->buffer_availability,0); + + LOG_I(GTPU,"[%ld] GTP-U sending DL Data Delivery status to RNTI:RAB:teid %x/%x/%x, oldseq %d, oldnum %d\n", + instance, rnti, rab_id,ptr2->second.teid_outgoing, ptr2->second.seqNum,ptr2->second.npduNum ); + // copy to release the mutex + gtpv1u_bearer_t tmp=ptr2->second; + pthread_mutex_unlock(&globGtp.gtp_lock); + gtpv1uCreateAndSendMsg(compatInst(instance), + tmp.outgoing_ip_addr, + tmp.outgoing_port, + GTP_GPDU, + tmp.teid_outgoing, + NULL, 0, false, false, true, 0, 0, 0x84, extensionHeader->buffer, extensionHeader->length) ; + +} + static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_tunnel_data_req_t *req) { rnti_t rnti=req->rnti; int rab_id=req->rab_id; @@ -1049,6 +1117,12 @@ void *gtpv1uTask(void *args) { } break; + case GTPV1U_DU_BUFFER_REPORT_REQ:{ + gtpv1uSendDlDeliveryStatus(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), + >PV1U_DU_BUFFER_REPORT_REQ(message_p)); + } + break; + case TERMINATE_MESSAGE: break;