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:
committed by
Robert Schmidt
parent
84ce708f96
commit
807b38ddae
@@ -469,7 +469,7 @@ static void deliver_pdu_drb_gnb(void *deliver_pdu_data, ue_id_t ue_id, int rb_id
|
|||||||
if (NODE_IS_CU(node_type)) {
|
if (NODE_IS_CU(node_type)) {
|
||||||
LOG_D(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size);
|
LOG_D(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size);
|
||||||
extern instance_t CUuniqInstance;
|
extern instance_t CUuniqInstance;
|
||||||
gtpv1uSendDirect(CUuniqInstance, ue_id, rb_id, (uint8_t *)buf, size, false, false);
|
gtpv1uSendDirectWithNRUSeqNum(CUuniqInstance, ue_id, rb_id, (uint8_t *)buf, size);
|
||||||
} else {
|
} else {
|
||||||
uint8_t *memblock = malloc16(size);
|
uint8_t *memblock = malloc16(size);
|
||||||
memcpy(memblock, buf, size);
|
memcpy(memblock, buf, size);
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ typedef struct gtpv1u_bearer_s {
|
|||||||
teid_t teid_outgoing;
|
teid_t teid_outgoing;
|
||||||
uint16_t seqNum;
|
uint16_t seqNum;
|
||||||
uint8_t npduNum;
|
uint8_t npduNum;
|
||||||
|
int32_t nru_sequence_number;
|
||||||
int outgoing_qfi;
|
int outgoing_qfi;
|
||||||
} gtpv1u_bearer_t;
|
} gtpv1u_bearer_t;
|
||||||
|
|
||||||
@@ -306,13 +307,14 @@ static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer,
|
|||||||
return !GTPNOK;
|
return !GTPNOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gtpv1uSendDirect(instance_t instance,
|
static void _gtpv1uSendDirect(instance_t instance,
|
||||||
ue_id_t ue_id,
|
ue_id_t ue_id,
|
||||||
int bearer_id,
|
int bearer_id,
|
||||||
uint8_t *buf,
|
uint8_t *buf,
|
||||||
size_t len,
|
size_t len,
|
||||||
bool seqNumFlag,
|
bool seqNumFlag,
|
||||||
bool npduNumFlag)
|
bool npduNumFlag,
|
||||||
|
int32_t nru_seqnum)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&globGtp.gtp_lock);
|
pthread_mutex_lock(&globGtp.gtp_lock);
|
||||||
getInstRetVoid(compatInst(instance));
|
getInstRetVoid(compatInst(instance));
|
||||||
@@ -347,9 +349,13 @@ void gtpv1uSendDirect(instance_t instance,
|
|||||||
pthread_mutex_unlock(&globGtp.gtp_lock);
|
pthread_mutex_unlock(&globGtp.gtp_lock);
|
||||||
|
|
||||||
int extension_count = 0;
|
int extension_count = 0;
|
||||||
gtpu_extension_header_t ext = {};
|
gtpu_extension_header_t ext[2];
|
||||||
if (bearer.outgoing_qfi != -1) {
|
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,
|
.type = GTPU_EXT_UL_PDU_SESSION_INFORMATION,
|
||||||
.ul_pdu_session_information = {
|
.ul_pdu_session_information = {
|
||||||
.qmp = false,
|
.qmp = false,
|
||||||
@@ -364,6 +370,24 @@ void gtpv1uSendDirect(instance_t instance,
|
|||||||
extension_count++;
|
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);
|
DevAssert(compatInst(instance) == bearer.sock_fd);
|
||||||
gtpv1uCreateAndSendMsg(&bearer,
|
gtpv1uCreateAndSendMsg(&bearer,
|
||||||
GTP_GPDU,
|
GTP_GPDU,
|
||||||
@@ -371,10 +395,61 @@ void gtpv1uSendDirect(instance_t instance,
|
|||||||
len,
|
len,
|
||||||
seqNumFlag,
|
seqNumFlag,
|
||||||
npduNumFlag,
|
npduNumFlag,
|
||||||
&ext,
|
ext,
|
||||||
extension_count);
|
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)
|
static void fillDlDeliveryStatusReport(gtpu_extension_header_t *ext, uint32_t RLC_buffer_availability, uint32_t NR_PDCP_PDU_SN)
|
||||||
{
|
{
|
||||||
*ext = {
|
*ext = {
|
||||||
|
|||||||
@@ -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);
|
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 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);
|
instance_t gtpv1Init(openAddr_t context);
|
||||||
void *gtpv1uTask(void *args);
|
void *gtpv1uTask(void *args);
|
||||||
|
|||||||
Reference in New Issue
Block a user