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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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<int, gtpv1u_bearer_t>::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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user