GTPU: CU has to send NR-U Sequence Number

This is in 3GPP TS 38.425.

Because it was not done, there was a problem of interoperability
between openair CU and srsran DU. No DL traffic was reaching the UE.

A new GTPU API function is introduced: gtpv1uSendDirectWithNRUSeqNum().
It is only used in the gNB CU, in PDCP. So it was decided to not add a
new parameter to gtpv1uSendDirect() but instead add a new API function.
This commit is contained in:
Cedric Roux
2025-08-21 09:30:41 +02:00
committed by Robert Schmidt
parent 84ce708f96
commit 807b38ddae
3 changed files with 91 additions and 11 deletions
+85 -10
View File
@@ -113,6 +113,7 @@ typedef struct gtpv1u_bearer_s {
teid_t teid_outgoing;
uint16_t seqNum;
uint8_t npduNum;
int32_t nru_sequence_number;
int outgoing_qfi;
} gtpv1u_bearer_t;
@@ -306,13 +307,14 @@ static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer,
return !GTPNOK;
}
void gtpv1uSendDirect(instance_t instance,
ue_id_t ue_id,
int bearer_id,
uint8_t *buf,
size_t len,
bool seqNumFlag,
bool npduNumFlag)
static void _gtpv1uSendDirect(instance_t instance,
ue_id_t ue_id,
int bearer_id,
uint8_t *buf,
size_t len,
bool seqNumFlag,
bool npduNumFlag,
int32_t nru_seqnum)
{
pthread_mutex_lock(&globGtp.gtp_lock);
getInstRetVoid(compatInst(instance));
@@ -347,9 +349,13 @@ void gtpv1uSendDirect(instance_t instance,
pthread_mutex_unlock(&globGtp.gtp_lock);
int extension_count = 0;
gtpu_extension_header_t ext = {};
gtpu_extension_header_t ext[2];
if (bearer.outgoing_qfi != -1) {
ext = {
/* 29.281 Figure 5.2.1-3 note 4 says PDU Session Container must come first.
* GTPU_EXT_UL_PDU_SESSION_INFORMATION is within a PDU Session Container
* so it must be put before any other extension.
*/
ext[extension_count] = {
.type = GTPU_EXT_UL_PDU_SESSION_INFORMATION,
.ul_pdu_session_information = {
.qmp = false,
@@ -364,6 +370,24 @@ void gtpv1uSendDirect(instance_t instance,
extension_count++;
}
if (nru_seqnum != -1) {
ext[extension_count] = {
.type = GTPU_EXT_DL_USER_DATA,
.dl_user_data = {
.dl_discard_blocks = false,
.dl_flush = false,
.report_polling = false,
.request_out_of_seq_report = false,
.report_delivered = false,
.user_data_existence_flag = false,
.assistance_info_report_polling_flag = false,
.retransmission_flag = false,
.nru_sequence_number = (uint32_t)nru_seqnum
}
};
extension_count++;
}
DevAssert(compatInst(instance) == bearer.sock_fd);
gtpv1uCreateAndSendMsg(&bearer,
GTP_GPDU,
@@ -371,10 +395,61 @@ void gtpv1uSendDirect(instance_t instance,
len,
seqNumFlag,
npduNumFlag,
&ext,
ext,
extension_count);
}
void gtpv1uSendDirect(instance_t instance,
ue_id_t ue_id,
int bearer_id,
uint8_t *buf,
size_t len,
bool seqNumFlag,
bool npduNumFlag)
{
_gtpv1uSendDirect(instance,
ue_id,
bearer_id,
buf,
len,
seqNumFlag,
npduNumFlag,
-1);
}
void gtpv1uSendDirectWithNRUSeqNum(instance_t instance,
ue_id_t ue_id,
int bearer_id,
uint8_t *buf,
size_t len)
{
pthread_mutex_lock(&globGtp.gtp_lock);
getInstRetVoid(compatInst(instance));
getUeRetVoid(inst, ue_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);
pthread_mutex_unlock(&globGtp.gtp_lock);
return;
}
int32_t nru_seqnum = ptr2->second.nru_sequence_number;
ptr2->second.nru_sequence_number++;
ptr2->second.nru_sequence_number &= (1 << 24) - 1;
pthread_mutex_unlock(&globGtp.gtp_lock);
_gtpv1uSendDirect(instance,
ue_id,
bearer_id,
buf,
len,
false,
false,
nru_seqnum);
}
static void fillDlDeliveryStatusReport(gtpu_extension_header_t *ext, uint32_t RLC_buffer_availability, uint32_t NR_PDCP_PDU_SN)
{
*ext = {
+5
View File
@@ -128,6 +128,11 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t;
int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *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);
void gtpv1uSendDirectWithNRUSeqNum(instance_t instance,
ue_id_t ue_id,
int bearer_id,
uint8_t *buf,
size_t len);
instance_t gtpv1Init(openAddr_t context);
void *gtpv1uTask(void *args);