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_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_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_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
|
#define GTPV1U_ALL_TUNNELS_TEID (teid_t)0xFFFFFFFF
|
||||||
|
|
||||||
typedef struct gtpv1u_enb_create_x2u_tunnel_req_s {
|
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;
|
pdusessionid_t pdusession_id;
|
||||||
} gtpv1u_gnb_tunnel_data_req_t;
|
} 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_ */
|
#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){
|
else if(req->ReconfigComplOutcome == RRCreconf_success){
|
||||||
LOG_I(NR_RRC, "CU reporting RRC Reconfiguration success \n");
|
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 */
|
/* 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) ;
|
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) {
|
static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_tunnel_data_req_t *req) {
|
||||||
rnti_t rnti=req->rnti;
|
rnti_t rnti=req->rnti;
|
||||||
int rab_id=req->rab_id;
|
int rab_id=req->rab_id;
|
||||||
@@ -1049,6 +1117,12 @@ void *gtpv1uTask(void *args) {
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case TERMINATE_MESSAGE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user