SDAP Initial Implementation
This commit is contained in:
@@ -1779,7 +1779,8 @@ set(NR_PDCP_SRC
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(NR_SDAP_SRC
|
set(NR_SDAP_SRC
|
||||||
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap_gnb.c
|
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap.c
|
||||||
|
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap_entity.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(L2_SRC
|
set(L2_SRC
|
||||||
|
|||||||
@@ -478,6 +478,7 @@ int logInit (void)
|
|||||||
register_log_component("NAS","log",NAS);
|
register_log_component("NAS","log",NAS);
|
||||||
register_log_component("UDP","",UDP_);
|
register_log_component("UDP","",UDP_);
|
||||||
register_log_component("GTPU","",GTPU);
|
register_log_component("GTPU","",GTPU);
|
||||||
|
register_log_component("SDAP","",SDAP);
|
||||||
register_log_component("S1AP","",S1AP);
|
register_log_component("S1AP","",S1AP);
|
||||||
register_log_component("F1AP","",F1AP);
|
register_log_component("F1AP","",F1AP);
|
||||||
register_log_component("M2AP","",M2AP);
|
register_log_component("M2AP","",M2AP);
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ typedef enum {
|
|||||||
OCM,
|
OCM,
|
||||||
UDP_,
|
UDP_,
|
||||||
GTPU,
|
GTPU,
|
||||||
|
SDAP,
|
||||||
SPGW,
|
SPGW,
|
||||||
S1AP,
|
S1AP,
|
||||||
F1AP,
|
F1AP,
|
||||||
|
|||||||
@@ -944,6 +944,27 @@ ID = LEGACY_GTPU_TRACE
|
|||||||
GROUP = ALL:LEGACY_GTPU:LEGACY_GROUP_TRACE:LEGACY
|
GROUP = ALL:LEGACY_GTPU:LEGACY_GROUP_TRACE:LEGACY
|
||||||
FORMAT = string,log
|
FORMAT = string,log
|
||||||
|
|
||||||
|
ID = LEGACY_SDAP_INFO
|
||||||
|
DESC = SDAP legacy logs - info level
|
||||||
|
GROUP = ALL:LEGACY_SDAP:LEGACY_GROUP_INFO:LEGACY
|
||||||
|
FORMAT = string,log
|
||||||
|
ID = LEGACY_SDAP_ERROR
|
||||||
|
DESC = SDAP legacy logs - error level
|
||||||
|
GROUP = ALL:LEGACY_SDAP:LEGACY_GROUP_ERROR:LEGACY
|
||||||
|
FORMAT = string,log
|
||||||
|
ID = LEGACY_SDAP_WARNING
|
||||||
|
DESC = SDAP legacy logs - warning level
|
||||||
|
GROUP = ALL:LEGACY_SDAP:LEGACY_GROUP_WARNING:LEGACY
|
||||||
|
FORMAT = string,log
|
||||||
|
ID = LEGACY_SDAP_DEBUG
|
||||||
|
DESC = SDAP legacy logs - debug level
|
||||||
|
GROUP = ALL:LEGACY_SDAP:LEGACY_GROUP_DEBUG:LEGACY
|
||||||
|
FORMAT = string,log
|
||||||
|
ID = LEGACY_SDAP_TRACE
|
||||||
|
DESC = SDAP legacy logs - trace level
|
||||||
|
GROUP = ALL:LEGACY_SDAP:LEGACY_GROUP_TRACE:LEGACY
|
||||||
|
FORMAT = string,log
|
||||||
|
|
||||||
ID = LEGACY_TMR_INFO
|
ID = LEGACY_TMR_INFO
|
||||||
DESC = TMR legacy logs - info level
|
DESC = TMR legacy logs - info level
|
||||||
GROUP = ALL:LEGACY_TMR:LEGACY_GROUP_INFO:LEGACY
|
GROUP = ALL:LEGACY_TMR:LEGACY_GROUP_INFO:LEGACY
|
||||||
|
|||||||
@@ -351,6 +351,14 @@ The following features are valid for the gNB and the 5G-NR UE.
|
|||||||
- Interfaces with RRC, RLC
|
- Interfaces with RRC, RLC
|
||||||
- Interfaces with gtp-u (data Tx/Rx over N3 and F1-U interfaces)
|
- Interfaces with gtp-u (data Tx/Rx over N3 and F1-U interfaces)
|
||||||
|
|
||||||
|
**gNB SDAP**
|
||||||
|
- Send/Receive operations according to 37.324 Rel.15
|
||||||
|
- Establishment/Handling of SDAP entities.
|
||||||
|
- Transfer of User Plane Data
|
||||||
|
- Mapping between a QoS flow and a DRB for both DL and UL
|
||||||
|
- Marking QoS flow ID in both DL and UL packets
|
||||||
|
- Reflective QoS flow to DRB mapping for UL SDAP data PDUs
|
||||||
|
|
||||||
**gNB RRC**
|
**gNB RRC**
|
||||||
- NR RRC (38.331) Rel 16 messages using new asn1c
|
- NR RRC (38.331) Rel 16 messages using new asn1c
|
||||||
- LTE RRC (36.331) also updated to Rel 15
|
- LTE RRC (36.331) also updated to Rel 15
|
||||||
@@ -400,6 +408,7 @@ The following features are valid for the gNB and the 5G-NR UE.
|
|||||||
- New gtp-u implementation supporting both N3 and F1-U interfaces according to 29.281 Rel.15
|
- New gtp-u implementation supporting both N3 and F1-U interfaces according to 29.281 Rel.15
|
||||||
- Interfaces with RRC, F1AP for tunnel creation
|
- Interfaces with RRC, F1AP for tunnel creation
|
||||||
- Interfaces with PDCP and RLC for data send/receive at the CU and DU respectively (F1-U interface)
|
- Interfaces with PDCP and RLC for data send/receive at the CU and DU respectively (F1-U interface)
|
||||||
|
- Interface with SDAP for data send/receive, capture of GTP-U Optional Header, GTP-U Extension Header and PDU Session Container.
|
||||||
|
|
||||||
# OpenAirInterface 5G-NR UE Feature Set #
|
# OpenAirInterface 5G-NR UE Feature Set #
|
||||||
|
|
||||||
@@ -502,6 +511,13 @@ The following features are valid for the gNB and the 5G-NR UE.
|
|||||||
- Radio bearer establishment/handling and association with PDCP entities
|
- Radio bearer establishment/handling and association with PDCP entities
|
||||||
- Interfaces with RRC, RLC
|
- Interfaces with RRC, RLC
|
||||||
|
|
||||||
|
**UE SDAP**
|
||||||
|
* Tx/Rx operations operations according to 37.324 Rel.15
|
||||||
|
- Establishment/Handling of SDAP entities.
|
||||||
|
- Transfer of User Plane Data
|
||||||
|
- Reflective Mapping
|
||||||
|
- RRC Signaling Mapping
|
||||||
|
|
||||||
**UE RRC**
|
**UE RRC**
|
||||||
* Integration of RRC messages and procedures supporting UE 5G SA connection according to 38.331 Rel.16
|
* Integration of RRC messages and procedures supporting UE 5G SA connection according to 38.331 Rel.16
|
||||||
- RRCSetupRequest/RRCSetup/RRCSetupComplete
|
- RRCSetupRequest/RRCSetup/RRCSetupComplete
|
||||||
|
|||||||
@@ -233,11 +233,20 @@ typedef uint8_t pdusessionid_t;
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// may be ITTI not enabled, but type instance is useful also for OTG,
|
// may be ITTI not enabled, but type instance is useful also for OTG,
|
||||||
typedef intptr_t instance_t;
|
typedef intptr_t instance_t;
|
||||||
|
|
||||||
|
typedef struct sdap_protocol_ctxt_s {
|
||||||
|
boolean_t rqi;
|
||||||
|
uint8_t qfi;
|
||||||
|
boolean_t dc;
|
||||||
|
int pdusession_id;
|
||||||
|
} sdap_protocol_ctxt_t;
|
||||||
|
|
||||||
typedef struct protocol_ctxt_s {
|
typedef struct protocol_ctxt_s {
|
||||||
module_id_t module_id; /*!< \brief Virtualized module identifier */
|
module_id_t module_id; /*!< \brief Virtualized module identifier */
|
||||||
eNB_flag_t enb_flag; /*!< \brief Flag to indicate eNB (1) or UE (0) */
|
eNB_flag_t enb_flag; /*!< \brief Flag to indicate eNB (1) or UE (0) */
|
||||||
instance_t instance; /*!< \brief ITTI or OTG module identifier */
|
instance_t instance; /*!< \brief ITTI or OTG module identifier */
|
||||||
rnti_t rnti;
|
rnti_t rnti;
|
||||||
|
sdap_protocol_ctxt_t sdap;
|
||||||
frame_t frame; /*!< \brief LTE frame number.*/
|
frame_t frame; /*!< \brief LTE frame number.*/
|
||||||
sub_frame_t subframe; /*!< \brief LTE sub frame number.*/
|
sub_frame_t subframe; /*!< \brief LTE sub frame number.*/
|
||||||
eNB_index_t eNB_index; /*!< \brief valid for UE indicating the index of connected eNB(s) */
|
eNB_index_t eNB_index; /*!< \brief valid for UE indicating the index of connected eNB(s) */
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity(
|
|||||||
ret->set_security = nr_pdcp_entity_set_security;
|
ret->set_security = nr_pdcp_entity_set_security;
|
||||||
ret->set_time = nr_pdcp_entity_set_time;
|
ret->set_time = nr_pdcp_entity_set_time;
|
||||||
|
|
||||||
ret->delete = nr_pdcp_entity_delete;
|
ret->delete_entity = nr_pdcp_entity_delete;
|
||||||
|
|
||||||
ret->deliver_sdu = deliver_sdu;
|
ret->deliver_sdu = deliver_sdu;
|
||||||
ret->deliver_sdu_data = deliver_sdu_data;
|
ret->deliver_sdu_data = deliver_sdu_data;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ typedef struct nr_pdcp_entity_t {
|
|||||||
void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size);
|
void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size);
|
||||||
void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size,
|
void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size,
|
||||||
int sdu_id);
|
int sdu_id);
|
||||||
void (*delete)(struct nr_pdcp_entity_t *entity);
|
void (*delete_entity)(struct nr_pdcp_entity_t *entity);
|
||||||
|
|
||||||
/* set_security: pass -1 to integrity_algorithm / ciphering_algorithm
|
/* set_security: pass -1 to integrity_algorithm / ciphering_algorithm
|
||||||
* to keep the current algorithm
|
* to keep the current algorithm
|
||||||
|
|||||||
@@ -36,7 +36,8 @@
|
|||||||
#include "pdcp.h"
|
#include "pdcp.h"
|
||||||
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||||
#include "openair2/SDAP/nr_sdap/nr_sdap_gnb.h"
|
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
|
||||||
|
#include "nr_pdcp_oai_api.h"
|
||||||
|
|
||||||
#define TODO do { \
|
#define TODO do { \
|
||||||
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
|
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
|
||||||
@@ -438,9 +439,13 @@ static void *enb_tun_read_thread(void *_)
|
|||||||
|
|
||||||
ctxt.rnti = rnti;
|
ctxt.rnti = rnti;
|
||||||
|
|
||||||
pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED,
|
ctxt.sdap.qfi = 7;
|
||||||
RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf,
|
ctxt.sdap.rqi = 0;
|
||||||
PDCP_TRANSMISSION_MODE_DATA, NULL, NULL);
|
ctxt.sdap.pdusession_id = 10;
|
||||||
|
|
||||||
|
sdap_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED,
|
||||||
|
RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf,
|
||||||
|
PDCP_TRANSMISSION_MODE_DATA, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -481,9 +486,13 @@ static void *ue_tun_read_thread(void *_)
|
|||||||
|
|
||||||
ctxt.rnti = rnti;
|
ctxt.rnti = rnti;
|
||||||
|
|
||||||
pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED,
|
ctxt.sdap.dc = SDAP_HDR_UL_DATA_PDU;
|
||||||
RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf,
|
ctxt.sdap.qfi = 7;
|
||||||
PDCP_TRANSMISSION_MODE_DATA, NULL, NULL);
|
ctxt.sdap.pdusession_id = 10;
|
||||||
|
|
||||||
|
sdap_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED,
|
||||||
|
RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf,
|
||||||
|
PDCP_TRANSMISSION_MODE_DATA, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -607,28 +616,13 @@ uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id)
|
|||||||
static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity,
|
static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity,
|
||||||
char *buf, int size)
|
char *buf, int size)
|
||||||
{
|
{
|
||||||
extern int nas_sock_fd[];
|
|
||||||
int len;
|
|
||||||
nr_pdcp_ue_t *ue = _ue;
|
nr_pdcp_ue_t *ue = _ue;
|
||||||
MessageDef *message_p;
|
|
||||||
uint8_t *gtpu_buffer_p;
|
|
||||||
int rb_id;
|
int rb_id;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (IS_SOFTMODEM_NOS1 || UE_NAS_USE_TUN) {
|
if (IS_SOFTMODEM_NOS1 || UE_NAS_USE_TUN) {
|
||||||
LOG_D(PDCP, "IP packet received, to be sent to TUN interface");
|
LOG_D(PDCP, "IP packet received with size %d, to be sent to SDAP interface, UE rnti: %d\n", size, ue->rnti);
|
||||||
|
sdap_data_ind(entity, ue->rnti, buf, size);
|
||||||
if(entity->has_sdapDLheader){
|
|
||||||
size -= SDAP_HDR_LENGTH;
|
|
||||||
len = write(nas_sock_fd[0], &buf[SDAP_HDR_LENGTH], size);
|
|
||||||
} else {
|
|
||||||
len = write(nas_sock_fd[0], buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len != size) {
|
|
||||||
LOG_E(PDCP, "%s:%d:%s: fatal error %d: %s\n", __FILE__, __LINE__, __FUNCTION__, errno, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
@@ -644,31 +638,9 @@ static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity,
|
|||||||
|
|
||||||
rb_found:
|
rb_found:
|
||||||
{
|
{
|
||||||
int offset=0;
|
LOG_D(PDCP, "%s() (drb %d) sending message to SDAP size %d\n", __func__, rb_id, size);
|
||||||
if (entity->has_sdap == 1 && entity->has_sdapULheader == 1)
|
sdap_data_ind(entity, ue->rnti, buf, size);
|
||||||
offset = 1; // this is the offset of the SDAP header in bytes
|
}
|
||||||
|
|
||||||
message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0,
|
|
||||||
GTPV1U_GNB_TUNNEL_DATA_REQ,
|
|
||||||
sizeof(gtpv1u_gnb_tunnel_data_req_t) + size
|
|
||||||
+ GTPU_HEADER_OVERHEAD_MAX - offset);
|
|
||||||
AssertFatal(message_p != NULL, "OUT OF MEMORY");
|
|
||||||
|
|
||||||
gtpv1u_gnb_tunnel_data_req_t *req=>PV1U_GNB_TUNNEL_DATA_REQ(message_p);
|
|
||||||
gtpu_buffer_p = (uint8_t*)(req+1);
|
|
||||||
memcpy(gtpu_buffer_p+GTPU_HEADER_OVERHEAD_MAX, buf+offset, size-offset);
|
|
||||||
req->buffer = gtpu_buffer_p;
|
|
||||||
req->length = size-offset;
|
|
||||||
req->offset = GTPU_HEADER_OVERHEAD_MAX;
|
|
||||||
req->rnti = ue->rnti;
|
|
||||||
req->pdusession_id = entity->pdusession_id;
|
|
||||||
if (offset==1) {
|
|
||||||
LOG_I(PDCP, "%s() (drb %d) SDAP header %2x\n",__func__, rb_id, buf[0]);
|
|
||||||
sdap_gnb_ul_header_handler(buf[0]); // Handler for the UL gNB SDAP Header
|
|
||||||
}
|
|
||||||
LOG_D(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size-offset);
|
|
||||||
itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,6 +939,9 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
|
|||||||
int has_sdap = 0;
|
int has_sdap = 0;
|
||||||
int has_sdapULheader=0;
|
int has_sdapULheader=0;
|
||||||
int has_sdapDLheader=0;
|
int has_sdapDLheader=0;
|
||||||
|
boolean_t is_sdap_DefaultDRB = false;
|
||||||
|
NR_QFI_t *mappedQFIs2Add = NULL;
|
||||||
|
uint8_t mappedQFIs2AddCount=0;
|
||||||
if (s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity)
|
if (s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity)
|
||||||
pdusession_id = s->cnAssociation->choice.eps_BearerIdentity;
|
pdusession_id = s->cnAssociation->choice.eps_BearerIdentity;
|
||||||
else {
|
else {
|
||||||
@@ -978,6 +953,10 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
|
|||||||
has_sdap = 1;
|
has_sdap = 1;
|
||||||
has_sdapULheader = s->cnAssociation->choice.sdap_Config->sdap_HeaderUL == NR_SDAP_Config__sdap_HeaderUL_present ? 1 : 0;
|
has_sdapULheader = s->cnAssociation->choice.sdap_Config->sdap_HeaderUL == NR_SDAP_Config__sdap_HeaderUL_present ? 1 : 0;
|
||||||
has_sdapDLheader = s->cnAssociation->choice.sdap_Config->sdap_HeaderDL == NR_SDAP_Config__sdap_HeaderDL_present ? 1 : 0;
|
has_sdapDLheader = s->cnAssociation->choice.sdap_Config->sdap_HeaderDL == NR_SDAP_Config__sdap_HeaderDL_present ? 1 : 0;
|
||||||
|
is_sdap_DefaultDRB = s->cnAssociation->choice.sdap_Config->defaultDRB == true ? 1 : 0;
|
||||||
|
mappedQFIs2Add = (NR_QFI_t*)s->cnAssociation->choice.sdap_Config->mappedQoS_FlowsToAdd->list.array[0];
|
||||||
|
mappedQFIs2AddCount = s->cnAssociation->choice.sdap_Config->mappedQoS_FlowsToAdd->list.count;
|
||||||
|
LOG_D(SDAP, "Captured mappedQoS_FlowsToAdd from RRC: %ld \n", *mappedQFIs2Add);
|
||||||
}
|
}
|
||||||
/* TODO(?): accept different UL and DL SN sizes? */
|
/* TODO(?): accept different UL and DL SN sizes? */
|
||||||
if (sn_size_ul != sn_size_dl) {
|
if (sn_size_ul != sn_size_dl) {
|
||||||
@@ -1009,6 +988,14 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
|
|||||||
nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
|
nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
|
||||||
|
|
||||||
LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||||
|
|
||||||
|
new_nr_sdap_entity(rnti,
|
||||||
|
pdusession_id,
|
||||||
|
is_sdap_DefaultDRB,
|
||||||
|
drb_id,
|
||||||
|
mappedQFIs2Add,
|
||||||
|
mappedQFIs2AddCount);
|
||||||
|
LOG_D(SDAP, "Added SDAP entity to ue rnti %x with pdusession_id %d\n", rnti, pdusession_id);
|
||||||
}
|
}
|
||||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||||
}
|
}
|
||||||
@@ -1140,7 +1127,7 @@ void nr_DRB_preconfiguration(uint16_t crnti)
|
|||||||
NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod));
|
NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod));
|
||||||
drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation));
|
drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation));
|
||||||
drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity;
|
drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity;
|
||||||
drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5;
|
drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 10;
|
||||||
drb_ToAddMod->drb_Identity = 1;
|
drb_ToAddMod->drb_Identity = 1;
|
||||||
drb_ToAddMod->reestablishPDCP = NULL;
|
drb_ToAddMod->reestablishPDCP = NULL;
|
||||||
drb_ToAddMod->recoverPDCP = NULL;
|
drb_ToAddMod->recoverPDCP = NULL;
|
||||||
@@ -1450,3 +1437,12 @@ void nr_pdcp_tick(int frame, int subframe)
|
|||||||
nr_pdcp_wakeup_timer_thread(nr_pdcp_current_time);
|
nr_pdcp_wakeup_timer_thread(nr_pdcp_current_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nr_pdcp_entity_t *nr_pdcp_find_entity_sdap(int rnti, uint8_t sdap_drb_id){
|
||||||
|
nr_pdcp_ue_t *ue;
|
||||||
|
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti);
|
||||||
|
if(ue->drb[sdap_drb_id-1])
|
||||||
|
return ue->drb[sdap_drb_id-1];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#include "openair2/COMMON/platform_types.h"
|
||||||
|
|
||||||
|
nr_pdcp_entity_t *nr_pdcp_find_entity_sdap(int rnti, uint8_t sdap_drb_id);
|
||||||
@@ -127,11 +127,11 @@ void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *_m, int rnti)
|
|||||||
|
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0; j < 2; j++)
|
||||||
if (ue->srb[j] != NULL)
|
if (ue->srb[j] != NULL)
|
||||||
ue->srb[j]->delete(ue->srb[j]);
|
ue->srb[j]->delete_entity(ue->srb[j]);
|
||||||
|
|
||||||
for (j = 0; j < 5; j++)
|
for (j = 0; j < 5; j++)
|
||||||
if (ue->drb[j] != NULL)
|
if (ue->drb[j] != NULL)
|
||||||
ue->drb[j]->delete(ue->drb[j]);
|
ue->drb[j]->delete_entity(ue->drb[j]);
|
||||||
|
|
||||||
free(ue);
|
free(ue);
|
||||||
|
|
||||||
|
|||||||
@@ -818,7 +818,6 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
|
|||||||
uint8_t buffer[RRC_BUF_SIZE];
|
uint8_t buffer[RRC_BUF_SIZE];
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
int qos_flow_index = 0;
|
int qos_flow_index = 0;
|
||||||
NR_QFI_t qfi = 0;
|
|
||||||
int pdu_sessions_done = 0;
|
int pdu_sessions_done = 0;
|
||||||
int i;
|
int i;
|
||||||
NR_CellGroupConfig_t *cellGroupConfig;
|
NR_CellGroupConfig_t *cellGroupConfig;
|
||||||
@@ -870,14 +869,15 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
|
|||||||
memset(sdap_config, 0, sizeof(NR_SDAP_Config_t));
|
memset(sdap_config, 0, sizeof(NR_SDAP_Config_t));
|
||||||
sdap_config->pdu_Session = ue_context_pP->ue_context.pduSession[i].param.pdusession_id;
|
sdap_config->pdu_Session = ue_context_pP->ue_context.pduSession[i].param.pdusession_id;
|
||||||
sdap_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present;
|
sdap_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present;
|
||||||
sdap_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent;
|
sdap_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present;
|
||||||
sdap_config->defaultDRB = TRUE;
|
sdap_config->defaultDRB = TRUE;
|
||||||
sdap_config->mappedQoS_FlowsToAdd = calloc(1, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd));
|
sdap_config->mappedQoS_FlowsToAdd = calloc(1, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd));
|
||||||
memset(sdap_config->mappedQoS_FlowsToAdd, 0, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd));
|
memset(sdap_config->mappedQoS_FlowsToAdd, 0, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd));
|
||||||
|
|
||||||
for (qos_flow_index = 0; qos_flow_index < ue_context_pP->ue_context.pduSession[i].param.nb_qos; qos_flow_index++) {
|
for (qos_flow_index = 0; qos_flow_index < ue_context_pP->ue_context.pduSession[i].param.nb_qos; qos_flow_index++) {
|
||||||
qfi = ue_context_pP->ue_context.pduSession[i].param.qos[qos_flow_index].qfi;
|
NR_QFI_t *qfi = calloc(1, sizeof(NR_QFI_t));
|
||||||
ASN_SEQUENCE_ADD(&sdap_config->mappedQoS_FlowsToAdd->list, &qfi);
|
*qfi = ue_context_pP->ue_context.pduSession[i].param.qos[qos_flow_index].qfi;
|
||||||
|
ASN_SEQUENCE_ADD(&sdap_config->mappedQoS_FlowsToAdd->list, qfi);
|
||||||
}
|
}
|
||||||
sdap_config->mappedQoS_FlowsToRelease = NULL;
|
sdap_config->mappedQoS_FlowsToRelease = NULL;
|
||||||
DRB_config->cnAssociation->choice.sdap_Config = sdap_config;
|
DRB_config->cnAssociation->choice.sdap_Config = sdap_config;
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nr_sdap.h"
|
||||||
|
|
||||||
|
boolean_t sdap_data_req(protocol_ctxt_t *ctxt_p,
|
||||||
|
const srb_flag_t srb_flag,
|
||||||
|
const rb_id_t rb_id,
|
||||||
|
const mui_t mui,
|
||||||
|
const confirm_t confirm,
|
||||||
|
const sdu_size_t sdu_buffer_size,
|
||||||
|
unsigned char *const sdu_buffer,
|
||||||
|
const pdcp_transmission_mode_t pt_mode,
|
||||||
|
const uint32_t *sourceL2Id,
|
||||||
|
const uint32_t *destinationL2Id) {
|
||||||
|
nr_sdap_entity_t *sdap_entity;
|
||||||
|
sdap_entity = nr_sdap_get_entity(ctxt_p->rnti, ctxt_p->sdap.pdusession_id);
|
||||||
|
|
||||||
|
if(sdap_entity == NULL) {
|
||||||
|
LOG_E(SDAP, "%s:%d:%s: Entity not found with ue rnti: %x and pdusession id: %d\n", __FILE__, __LINE__, __FUNCTION__, ctxt_p->rnti, ctxt_p->sdap.pdusession_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean_t ret = sdap_entity->tx_entity(sdap_entity,
|
||||||
|
ctxt_p,
|
||||||
|
srb_flag,
|
||||||
|
rb_id,
|
||||||
|
mui,
|
||||||
|
confirm,
|
||||||
|
sdu_buffer_size,
|
||||||
|
sdu_buffer,
|
||||||
|
pt_mode,
|
||||||
|
sourceL2Id,
|
||||||
|
destinationL2Id);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdap_data_ind(nr_pdcp_entity_t *pdcp_entity,
|
||||||
|
int rnti,
|
||||||
|
char *buf,
|
||||||
|
int size) {
|
||||||
|
nr_sdap_entity_t *sdap_entity;
|
||||||
|
sdap_entity = nr_sdap_get_entity(rnti, pdcp_entity->pdusession_id);
|
||||||
|
|
||||||
|
if(sdap_entity == NULL) {
|
||||||
|
LOG_E(SDAP, "%s:%d:%s: Entity not found\n", __FILE__, __LINE__, __FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdap_entity->rx_entity(sdap_entity,
|
||||||
|
pdcp_entity,
|
||||||
|
rnti,
|
||||||
|
buf,
|
||||||
|
size);
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NR_SDAP_GNB_H_
|
||||||
|
#define _NR_SDAP_GNB_H_
|
||||||
|
|
||||||
|
#include "openair2/COMMON/platform_types.h"
|
||||||
|
#include "common/utils/LOG/log.h"
|
||||||
|
#include "nr_sdap_entity.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 4.4 Functions
|
||||||
|
* Transfer of user plane data
|
||||||
|
* Downlink - gNB
|
||||||
|
* Uplink - nrUE
|
||||||
|
*/
|
||||||
|
boolean_t sdap_data_req(protocol_ctxt_t *ctxt_p,
|
||||||
|
const srb_flag_t srb_flag,
|
||||||
|
const rb_id_t rb_id,
|
||||||
|
const mui_t mui,
|
||||||
|
const confirm_t confirm,
|
||||||
|
const sdu_size_t sdu_buffer_size,
|
||||||
|
unsigned char *const sdu_buffer,
|
||||||
|
const pdcp_transmission_mode_t pt_mode,
|
||||||
|
const uint32_t *sourceL2Id,
|
||||||
|
const uint32_t *destinationL2Id
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 4.4 Functions
|
||||||
|
* Transfer of user plane data
|
||||||
|
* Uplink - gNB
|
||||||
|
* Downlink - nrUE
|
||||||
|
*/
|
||||||
|
void sdap_data_ind(nr_pdcp_entity_t *pdcp_entity,
|
||||||
|
int rnti,
|
||||||
|
char *buf,
|
||||||
|
int size
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,474 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nr_sdap_entity.h"
|
||||||
|
#include "common/utils/LOG/log.h"
|
||||||
|
#include <openair2/LAYER2/PDCP_v10.1.0/pdcp.h>
|
||||||
|
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||||
|
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
nr_sdap_entity_t *sdap_entity_llist;
|
||||||
|
} nr_sdap_entity_info;
|
||||||
|
|
||||||
|
static nr_sdap_entity_info sdap_info;
|
||||||
|
|
||||||
|
static boolean_t nr_sdap_tx_entity(nr_sdap_entity_t *entity,
|
||||||
|
protocol_ctxt_t *ctxt_p,
|
||||||
|
const srb_flag_t srb_flag,
|
||||||
|
const rb_id_t rb_id,
|
||||||
|
const mui_t mui,
|
||||||
|
const confirm_t confirm,
|
||||||
|
const sdu_size_t sdu_buffer_size,
|
||||||
|
unsigned char *const sdu_buffer,
|
||||||
|
const pdcp_transmission_mode_t pt_mode,
|
||||||
|
const uint32_t *sourceL2Id,
|
||||||
|
const uint32_t *destinationL2Id
|
||||||
|
) {
|
||||||
|
/* The offset of the SDAP header, it might be 0 if the has_sdap is not true in the pdcp entity. */
|
||||||
|
int offset=0;
|
||||||
|
boolean_t ret=false;
|
||||||
|
/*Hardcode DRB ID given from upper layer (ue/enb_tun_read_thread rb_id), it will change if we have SDAP*/
|
||||||
|
rb_id_t sdap_drb_id = rb_id;
|
||||||
|
int pdcp_ent_has_sdap = 0;
|
||||||
|
|
||||||
|
if(sdu_buffer == NULL) {
|
||||||
|
LOG_E(SDAP, "%s:%d:%s: NULL sdu_buffer \n", __FILE__, __LINE__, __FUNCTION__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sdap_buf[SDAP_MAX_PDU];
|
||||||
|
nr_pdcp_entity_t *pdcp_entity = entity->qfi2drb_map(entity, ctxt_p->sdap.qfi, rb_id);
|
||||||
|
|
||||||
|
if(pdcp_entity){
|
||||||
|
sdap_drb_id = pdcp_entity->rb_id;
|
||||||
|
pdcp_ent_has_sdap = pdcp_entity->has_sdap;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pdcp_ent_has_sdap){
|
||||||
|
ret = pdcp_data_req(ctxt_p,
|
||||||
|
srb_flag,
|
||||||
|
sdap_drb_id,
|
||||||
|
mui,
|
||||||
|
confirm,
|
||||||
|
sdu_buffer_size,
|
||||||
|
sdu_buffer,
|
||||||
|
pt_mode,
|
||||||
|
sourceL2Id,
|
||||||
|
destinationL2Id);
|
||||||
|
|
||||||
|
if(!ret)
|
||||||
|
LOG_E(SDAP, "%s:%d:%s: PDCP refused PDU\n", __FILE__, __LINE__, __FUNCTION__);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sdu_buffer_size == 0 || sdu_buffer_size > 8999) {
|
||||||
|
LOG_E(SDAP, "%s:%d:%s: NULL or 0 or exceeded sdu_buffer_size (over max PDCP SDU)\n", __FILE__, __LINE__, __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ctxt_p->enb_flag) { // gNB
|
||||||
|
offset = SDAP_HDR_LENGTH;
|
||||||
|
/*
|
||||||
|
* TS 37.324 4.4 Functions
|
||||||
|
* marking QoS flow ID in DL packets.
|
||||||
|
*
|
||||||
|
* Construct the DL SDAP data PDU.
|
||||||
|
*/
|
||||||
|
nr_sdap_dl_hdr_t sdap_hdr;
|
||||||
|
sdap_hdr.QFI = ctxt_p->sdap.qfi;
|
||||||
|
sdap_hdr.RQI = ctxt_p->sdap.rqi;
|
||||||
|
sdap_hdr.RDI = 0; // SDAP Hardcoded Value
|
||||||
|
/* Add the SDAP DL Header to the buffer */
|
||||||
|
memcpy(&sdap_buf[0], &sdap_hdr, SDAP_HDR_LENGTH);
|
||||||
|
memcpy(&sdap_buf[SDAP_HDR_LENGTH], sdu_buffer, sdu_buffer_size);
|
||||||
|
LOG_D(SDAP, "TX Entity QFI: %u \n", sdap_hdr.QFI);
|
||||||
|
LOG_D(SDAP, "TX Entity RQI: %u \n", sdap_hdr.RQI);
|
||||||
|
LOG_D(SDAP, "TX Entity RDI: %u \n", sdap_hdr.RDI);
|
||||||
|
} else { // nrUE
|
||||||
|
offset = SDAP_HDR_LENGTH;
|
||||||
|
/*
|
||||||
|
* TS 37.324 4.4 Functions
|
||||||
|
* marking QoS flow ID in UL packets.
|
||||||
|
*
|
||||||
|
* 5.2.1 Uplink
|
||||||
|
* construct the UL SDAP data PDU as specified in the subclause 6.2.2.3.
|
||||||
|
*/
|
||||||
|
nr_sdap_ul_hdr_t sdap_hdr;
|
||||||
|
sdap_hdr.QFI = ctxt_p->sdap.qfi;
|
||||||
|
sdap_hdr.R = 0;
|
||||||
|
sdap_hdr.DC = ctxt_p->sdap.dc;
|
||||||
|
/* Add the SDAP UL Header to the buffer */
|
||||||
|
memcpy(&sdap_buf[0], &sdap_hdr, SDAP_HDR_LENGTH);
|
||||||
|
memcpy(&sdap_buf[SDAP_HDR_LENGTH], sdu_buffer, sdu_buffer_size);
|
||||||
|
LOG_D(SDAP, "TX Entity QFI: %u \n", sdap_hdr.QFI);
|
||||||
|
LOG_D(SDAP, "TX Entity R: %u \n", sdap_hdr.R);
|
||||||
|
LOG_D(SDAP, "TX Entity DC: %u \n", sdap_hdr.DC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.2 Data transfer
|
||||||
|
* 5.2.1 Uplink UE side
|
||||||
|
* submit the constructed UL SDAP data PDU to the lower layers
|
||||||
|
*
|
||||||
|
* Downlink gNB side
|
||||||
|
*/
|
||||||
|
ret = pdcp_data_req(ctxt_p,
|
||||||
|
srb_flag,
|
||||||
|
sdap_drb_id,
|
||||||
|
mui,
|
||||||
|
confirm,
|
||||||
|
sdu_buffer_size+offset,
|
||||||
|
sdap_buf,
|
||||||
|
pt_mode,
|
||||||
|
sourceL2Id,
|
||||||
|
destinationL2Id);
|
||||||
|
|
||||||
|
if(!ret)
|
||||||
|
LOG_E(SDAP, "%s:%d:%s: PDCP refused PDU\n", __FILE__, __LINE__, __FUNCTION__);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nr_sdap_rx_entity(nr_sdap_entity_t *entity,
|
||||||
|
nr_pdcp_entity_t *pdcp_entity,
|
||||||
|
int rnti,
|
||||||
|
char *buf,
|
||||||
|
int size) {
|
||||||
|
/* The offset of the SDAP header, it might be 0 if the has_sdap is not true in the pdcp entity. */
|
||||||
|
int offset=0;
|
||||||
|
|
||||||
|
if(pdcp_entity->is_gnb) { // gNB
|
||||||
|
if(pdcp_entity->has_sdap && pdcp_entity->has_sdapULheader ) { // Handling the SDAP Header
|
||||||
|
offset = SDAP_HDR_LENGTH;
|
||||||
|
nr_sdap_ul_hdr_t *sdap_hdr = (nr_sdap_ul_hdr_t *)buf;
|
||||||
|
LOG_D(SDAP, "RX Entity Received QFI : %u\n", sdap_hdr->QFI);
|
||||||
|
LOG_D(SDAP, "RX Entity Received Reserved bit : %u\n", sdap_hdr->R);
|
||||||
|
LOG_D(SDAP, "RX Entity Received DC bit : %u\n", sdap_hdr->DC);
|
||||||
|
|
||||||
|
switch (sdap_hdr->DC) {
|
||||||
|
case SDAP_HDR_UL_DATA_PDU:
|
||||||
|
LOG_D(SDAP, "RX Entity Received SDAP Data PDU\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDAP_HDR_UL_CTRL_PDU:
|
||||||
|
LOG_D(SDAP, "RX Entity Received SDAP Control PDU\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pushing SDAP SDU to GTP-U Layer
|
||||||
|
MessageDef *message_p;
|
||||||
|
uint8_t *gtpu_buffer_p;
|
||||||
|
gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U, size + GTPU_HEADER_OVERHEAD_MAX - offset);
|
||||||
|
AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
|
||||||
|
memcpy(>pu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], buf+offset, size-offset);
|
||||||
|
message_p = itti_alloc_new_message(TASK_PDCP_ENB, 0 , GTPV1U_GNB_TUNNEL_DATA_REQ);
|
||||||
|
AssertFatal(message_p != NULL, "OUT OF MEMORY");
|
||||||
|
GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).buffer = gtpu_buffer_p;
|
||||||
|
GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).length = size-offset;
|
||||||
|
GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).offset = GTPU_HEADER_OVERHEAD_MAX;
|
||||||
|
GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).rnti = rnti;
|
||||||
|
GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).pdusession_id = pdcp_entity->pdusession_id;
|
||||||
|
LOG_D(SDAP, "%s() sending message to gtp size %d\n", __func__, size-offset);
|
||||||
|
itti_send_msg_to_task(TASK_VARIABLE, INSTANCE_DEFAULT, message_p);
|
||||||
|
} else { //nrUE
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.2 Data transfer
|
||||||
|
* 5.2.2 Downlink
|
||||||
|
* if the DRB from which this SDAP data PDU is received is configured by RRC with the presence of SDAP header.
|
||||||
|
*/
|
||||||
|
if(pdcp_entity->has_sdap && pdcp_entity->has_sdapDLheader) { // Handling the SDAP Header
|
||||||
|
offset = SDAP_HDR_LENGTH;
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.2 Data transfer
|
||||||
|
* 5.2.2 Downlink
|
||||||
|
* retrieve the SDAP SDU from the DL SDAP data PDU as specified in the subclause 6.2.2.2.
|
||||||
|
*/
|
||||||
|
nr_sdap_dl_hdr_t *sdap_hdr = (nr_sdap_dl_hdr_t *)buf;
|
||||||
|
LOG_D(SDAP, "RX Entity Received QFI : %u\n", sdap_hdr->QFI);
|
||||||
|
LOG_D(SDAP, "RX Entity Received RQI : %u\n", sdap_hdr->RQI);
|
||||||
|
LOG_D(SDAP, "RX Entity Received RDI : %u\n", sdap_hdr->RDI);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.2 Data transfer
|
||||||
|
* 5.2.2 Downlink
|
||||||
|
* Perform reflective QoS flow to DRB mapping as specified in the subclause 5.3.2.
|
||||||
|
*/
|
||||||
|
if(sdap_hdr->RDI == SDAP_REFLECTIVE_MAPPING) {
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.3 QoS flow to DRB Mapping
|
||||||
|
* 5.3.2 Reflective mapping
|
||||||
|
* If there is no stored QoS flow to DRB mapping rule for the QoS flow and a default DRB is configured.
|
||||||
|
*/
|
||||||
|
if(!entity->qfi2drb_table[sdap_hdr->QFI] && entity->default_drb->rb_id){
|
||||||
|
nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(sdap_hdr->QFI);
|
||||||
|
nr_pdcp_entity_t *sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, pdcp_entity, SDAP_CTRL_PDU_MAP_DEF_DRB, sdap_hdr->QFI);
|
||||||
|
entity->sdap_submit_ctrl_pdu(rnti, sdap_ctrl_pdu_drb, sdap_ctrl_pdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.3 QoS flow to DRB mapping
|
||||||
|
* 5.3.2 Reflective mapping
|
||||||
|
* if the stored QoS flow to DRB mapping rule for the QoS flow
|
||||||
|
* is different from the QoS flow to DRB mapping of the DL SDAP data PDU
|
||||||
|
* and
|
||||||
|
* the DRB according to the stored QoS flow to DRB mapping rule is configured by RRC
|
||||||
|
* with the presence of UL SDAP header
|
||||||
|
*/
|
||||||
|
if( (pdcp_entity->rb_id != entity->qfi2drb_table[sdap_hdr->QFI]->rb_id) &&
|
||||||
|
pdcp_entity->has_sdapULheader ){
|
||||||
|
nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(sdap_hdr->QFI);
|
||||||
|
nr_pdcp_entity_t *sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, pdcp_entity, SDAP_CTRL_PDU_MAP_RULE_DRB, sdap_hdr->QFI);
|
||||||
|
entity->sdap_submit_ctrl_pdu(rnti, sdap_ctrl_pdu_drb, sdap_ctrl_pdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.3 QoS flow to DRB Mapping
|
||||||
|
* 5.3.2 Reflective mapping
|
||||||
|
* store the QoS flow to DRB mapping of the DL SDAP data PDU as the QoS flow to DRB mapping rule for the UL.
|
||||||
|
*/
|
||||||
|
entity->qfi2drb_table[sdap_hdr->QFI]->rb_id = pdcp_entity->rb_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.2 Data transfer
|
||||||
|
* 5.2.2 Downlink
|
||||||
|
* perform RQI handling as specified in the subclause 5.4
|
||||||
|
*/
|
||||||
|
if(sdap_hdr->RQI == SDAP_RQI_HANDLING) {
|
||||||
|
LOG_W(SDAP, "UE - TODD 5.4\n");
|
||||||
|
}
|
||||||
|
} /* else - retrieve the SDAP SDU from the DL SDAP data PDU as specified in the subclause 6.2.2.1 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.2 Data transfer
|
||||||
|
* 5.2.2 Downlink
|
||||||
|
* deliver the retrieved SDAP SDU to the upper layer.
|
||||||
|
*/
|
||||||
|
extern int nas_sock_fd[];
|
||||||
|
int len = write(nas_sock_fd[0], &buf[offset], size-offset);
|
||||||
|
LOG_D(SDAP, "RX Entity len : %d\n", len);
|
||||||
|
LOG_D(SDAP, "RX Entity size : %d\n", size);
|
||||||
|
LOG_D(SDAP, "RX Entity offset : %d\n", offset);
|
||||||
|
|
||||||
|
if (len != size-offset)
|
||||||
|
LOG_E(SDAP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, uint8_t drb){
|
||||||
|
if(qfi < SDAP_MAX_QFI &&
|
||||||
|
qfi > SDAP_MAP_RULE_EMPTY &&
|
||||||
|
drb > 0 &&
|
||||||
|
drb <= AVLBL_DRB)
|
||||||
|
{
|
||||||
|
nr_pdcp_entity_t *pdcp_entity;
|
||||||
|
pdcp_entity = nr_pdcp_find_entity_sdap(entity->rnti, drb);
|
||||||
|
|
||||||
|
if(!pdcp_entity){
|
||||||
|
LOG_D(SDAP, "Map Update failed - PDCP Entity does not exist, should create it\n");
|
||||||
|
LOG_D(SDAP, "Map Update failed - Mapping to default DRB\n");
|
||||||
|
entity->qfi2drb_table[qfi] = entity->default_drb;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity->qfi2drb_table[qfi] = pdcp_entity;
|
||||||
|
LOG_D(SDAP, "Updated QFI to DRB Map: QFI %u -> DRB %d \n", qfi, entity->qfi2drb_table[qfi]->rb_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nr_sdap_qfi2drb_map_del(nr_sdap_entity_t *entity, uint8_t qfi){
|
||||||
|
entity->qfi2drb_table[qfi] = SDAP_NO_MAPPING_RULE;
|
||||||
|
LOG_D(SDAP, "Deleted QFI to DRB Map for QFI %u \n", qfi);
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_pdcp_entity_t *nr_sdap_qfi2drb_map(nr_sdap_entity_t *entity, uint8_t qfi, long upper_layer_rb_id){
|
||||||
|
nr_pdcp_entity_t *pdcp_entity;
|
||||||
|
|
||||||
|
pdcp_entity = entity->qfi2drb_table[qfi];
|
||||||
|
|
||||||
|
if(pdcp_entity){
|
||||||
|
return pdcp_entity;
|
||||||
|
} else if(entity->default_drb) {
|
||||||
|
LOG_D(SDAP, "Mapped QFI %u to Default DRB\n", qfi);
|
||||||
|
entity->qfi2drb_map_update(entity, qfi, entity->default_drb->rb_id);
|
||||||
|
return entity->default_drb;
|
||||||
|
} else {
|
||||||
|
/* Update map for Hardcode DRB ID given from upper layer (ue/enb_tun_read_thread rb_id)*/
|
||||||
|
entity->qfi2drb_map_update(entity, qfi, upper_layer_rb_id);
|
||||||
|
return SDAP_MAP_RULE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pdcp_entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_sdap_ul_hdr_t nr_sdap_construct_ctrl_pdu(uint8_t qfi){
|
||||||
|
nr_sdap_ul_hdr_t sdap_end_marker_hdr;
|
||||||
|
sdap_end_marker_hdr.QFI = qfi;
|
||||||
|
sdap_end_marker_hdr.R = 0;
|
||||||
|
sdap_end_marker_hdr.DC = SDAP_HDR_UL_CTRL_PDU;
|
||||||
|
LOG_D(SDAP, "Constructed Control PDU with QFI:%u R:%u DC:%u \n", sdap_end_marker_hdr.QFI,
|
||||||
|
sdap_end_marker_hdr.R,
|
||||||
|
sdap_end_marker_hdr.DC);
|
||||||
|
return sdap_end_marker_hdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_pdcp_entity_t *nr_sdap_map_ctrl_pdu(nr_sdap_entity_t *entity, nr_pdcp_entity_t *pdcp_entity, int map_type, uint8_t dl_qfi){
|
||||||
|
nr_pdcp_entity_t *drb_of_endmarker = NULL;
|
||||||
|
if(map_type == SDAP_CTRL_PDU_MAP_DEF_DRB){
|
||||||
|
drb_of_endmarker = entity->default_drb;
|
||||||
|
LOG_D(SDAP, "Mapped Control PDU to default drb\n");
|
||||||
|
}
|
||||||
|
if(map_type == SDAP_CTRL_PDU_MAP_RULE_DRB){
|
||||||
|
drb_of_endmarker = entity->qfi2drb_map(entity, dl_qfi, pdcp_entity->rb_id);
|
||||||
|
LOG_D(SDAP, "Mapped Control PDU according to the mapping rule, qfi %u \n", dl_qfi);
|
||||||
|
}
|
||||||
|
return drb_of_endmarker;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nr_sdap_submit_ctrl_pdu(int rnti, nr_pdcp_entity_t *sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu){
|
||||||
|
if(sdap_ctrl_pdu_drb){
|
||||||
|
sdap_ctrl_pdu_drb->recv_sdu(sdap_ctrl_pdu_drb, (char*)&ctrl_pdu, SDAP_HDR_LENGTH, RLC_MUI_UNDEFINED);
|
||||||
|
LOG_D(SDAP, "Sent Control PDU to PDCP Layer.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nr_sdap_ue_qfi2drb_config(nr_sdap_entity_t *existing_sdap_entity,
|
||||||
|
nr_pdcp_entity_t *pdcp_entity,
|
||||||
|
uint16_t rnti,
|
||||||
|
NR_QFI_t *mapped_qfi_2_add,
|
||||||
|
uint8_t mappedQFIs2AddCount,
|
||||||
|
uint8_t drb_identity)
|
||||||
|
{
|
||||||
|
uint8_t qfi = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < mappedQFIs2AddCount; i++){
|
||||||
|
qfi = mapped_qfi_2_add[i];
|
||||||
|
if(existing_sdap_entity->default_drb && existing_sdap_entity->qfi2drb_table[qfi] == SDAP_NO_MAPPING_RULE){
|
||||||
|
nr_sdap_ul_hdr_t sdap_ctrl_pdu = existing_sdap_entity->sdap_construct_ctrl_pdu(qfi);
|
||||||
|
nr_pdcp_entity_t *sdap_ctrl_pdu_drb = existing_sdap_entity->sdap_map_ctrl_pdu(existing_sdap_entity, pdcp_entity, SDAP_CTRL_PDU_MAP_DEF_DRB, qfi);
|
||||||
|
existing_sdap_entity->sdap_submit_ctrl_pdu(rnti, sdap_ctrl_pdu_drb, sdap_ctrl_pdu);
|
||||||
|
}
|
||||||
|
if(existing_sdap_entity->qfi2drb_table[qfi]->rb_id != drb_identity && pdcp_entity->has_sdapULheader){
|
||||||
|
nr_sdap_ul_hdr_t sdap_ctrl_pdu = existing_sdap_entity->sdap_construct_ctrl_pdu(qfi);
|
||||||
|
nr_pdcp_entity_t *sdap_ctrl_pdu_drb = existing_sdap_entity->sdap_map_ctrl_pdu(existing_sdap_entity, pdcp_entity, SDAP_CTRL_PDU_MAP_RULE_DRB, qfi);
|
||||||
|
existing_sdap_entity->sdap_submit_ctrl_pdu(rnti, sdap_ctrl_pdu_drb, sdap_ctrl_pdu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_sdap_entity_t *new_nr_sdap_entity(uint16_t rnti,
|
||||||
|
int pdusession_id,
|
||||||
|
boolean_t is_defaultDRB,
|
||||||
|
uint8_t drb_identity,
|
||||||
|
NR_QFI_t *mapped_qfi_2_add,
|
||||||
|
uint8_t mappedQFIs2AddCount)
|
||||||
|
{
|
||||||
|
if(nr_sdap_get_entity(rnti, pdusession_id)) {
|
||||||
|
LOG_E(SDAP, "SDAP Entity for UE already exists.\n");
|
||||||
|
nr_sdap_entity_t *existing_sdap_entity = nr_sdap_get_entity(rnti, pdusession_id);
|
||||||
|
nr_pdcp_entity_t *pdcp_entity = existing_sdap_entity->default_drb;
|
||||||
|
nr_sdap_ue_qfi2drb_config(existing_sdap_entity, pdcp_entity, rnti, mapped_qfi_2_add, mappedQFIs2AddCount, drb_identity);
|
||||||
|
return existing_sdap_entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_sdap_entity_t *sdap_entity;
|
||||||
|
sdap_entity = calloc(1, sizeof(nr_sdap_entity_t));
|
||||||
|
|
||||||
|
if(sdap_entity == NULL) {
|
||||||
|
LOG_E(SDAP, "SDAP Entity creation failed, out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sdap_entity->rnti = rnti;
|
||||||
|
sdap_entity->pdusession_id = pdusession_id;
|
||||||
|
|
||||||
|
sdap_entity->tx_entity = nr_sdap_tx_entity;
|
||||||
|
sdap_entity->rx_entity = nr_sdap_rx_entity;
|
||||||
|
|
||||||
|
sdap_entity->sdap_construct_ctrl_pdu = nr_sdap_construct_ctrl_pdu;
|
||||||
|
sdap_entity->sdap_map_ctrl_pdu = nr_sdap_map_ctrl_pdu;
|
||||||
|
sdap_entity->sdap_submit_ctrl_pdu = nr_sdap_submit_ctrl_pdu;
|
||||||
|
|
||||||
|
sdap_entity->qfi2drb_map_update = nr_sdap_qfi2drb_map_update;
|
||||||
|
sdap_entity->qfi2drb_map_delete = nr_sdap_qfi2drb_map_del;
|
||||||
|
sdap_entity->qfi2drb_map = nr_sdap_qfi2drb_map;
|
||||||
|
|
||||||
|
if(is_defaultDRB) {
|
||||||
|
nr_pdcp_entity_t *pdcp_entity = nr_pdcp_find_entity_sdap(sdap_entity->rnti, drb_identity);
|
||||||
|
sdap_entity->default_drb = pdcp_entity;
|
||||||
|
LOG_I(SDAP, "Default DRB for the created SDAP entity: %d \n", sdap_entity->default_drb->rb_id);
|
||||||
|
|
||||||
|
if(mappedQFIs2AddCount) {
|
||||||
|
for (int i = 0; i < mappedQFIs2AddCount; i++)
|
||||||
|
{
|
||||||
|
LOG_D(SDAP, "Mapped QFI to Add : %ld \n", mapped_qfi_2_add[i]);
|
||||||
|
sdap_entity->qfi2drb_map_update(sdap_entity, mapped_qfi_2_add[i], sdap_entity->default_drb->rb_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdap_entity->next_entity = sdap_info.sdap_entity_llist;
|
||||||
|
sdap_info.sdap_entity_llist = sdap_entity;
|
||||||
|
return sdap_entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_sdap_entity_t *nr_sdap_get_entity(uint16_t rnti, int pdusession_id) {
|
||||||
|
nr_sdap_entity_t *sdap_entity;
|
||||||
|
sdap_entity = sdap_info.sdap_entity_llist;
|
||||||
|
|
||||||
|
if(sdap_entity == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while(sdap_entity->rnti != rnti && sdap_entity->next_entity != NULL) {
|
||||||
|
sdap_entity = sdap_entity->next_entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdap_entity->rnti == rnti && sdap_entity->pdusession_id == pdusession_id)
|
||||||
|
return sdap_entity;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_nr_sdap_entity(uint16_t rnti) {
|
||||||
|
nr_sdap_entity_t *entityPtr, *entityPrev = NULL;
|
||||||
|
entityPtr = sdap_info.sdap_entity_llist;
|
||||||
|
|
||||||
|
if(entityPtr->rnti == rnti) {
|
||||||
|
sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity;
|
||||||
|
free(entityPtr);
|
||||||
|
} else {
|
||||||
|
while(entityPtr->rnti != rnti && entityPtr->next_entity != NULL) {
|
||||||
|
entityPrev = entityPtr;
|
||||||
|
entityPtr = entityPtr->next_entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entityPtr->rnti != rnti) {
|
||||||
|
entityPrev->next_entity = entityPtr->next_entity;
|
||||||
|
free(entityPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NR_SDAP_ENTITY_H_
|
||||||
|
#define _NR_SDAP_ENTITY_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "openair2/COMMON/platform_types.h"
|
||||||
|
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h"
|
||||||
|
#include "NR_RadioBearerConfig.h"
|
||||||
|
|
||||||
|
#define SDAP_BITMASK_DC (0x80)
|
||||||
|
#define SDAP_BITMASK_R (0x40)
|
||||||
|
#define SDAP_BITMASK_QFI (0x3F)
|
||||||
|
#define SDAP_BITMASK_RQI (0x40)
|
||||||
|
#define SDAP_HDR_UL_DATA_PDU (1)
|
||||||
|
#define SDAP_HDR_UL_CTRL_PDU (0)
|
||||||
|
#define SDAP_HDR_LENGTH (1)
|
||||||
|
#define SDAP_MAX_QFI (64)
|
||||||
|
#define SDAP_MAP_RULE_EMPTY (0)
|
||||||
|
#define AVLBL_DRB (5)
|
||||||
|
#define SDAP_NO_MAPPING_RULE (0)
|
||||||
|
#define SDAP_REFLECTIVE_MAPPING (1)
|
||||||
|
#define SDAP_RQI_HANDLING (1)
|
||||||
|
#define SDAP_CTRL_PDU_MAP_DEF_DRB (0)
|
||||||
|
#define SDAP_CTRL_PDU_MAP_RULE_DRB (1)
|
||||||
|
#define SDAP_MAX_PDU (9000)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The values of QoS Flow ID (QFI) and Reflective QoS Indication,
|
||||||
|
* are located in the PDU Session Container, which is conveyed by
|
||||||
|
* the GTP-U Extension Header. Inside the DL PDU SESSION INFORMATION frame.
|
||||||
|
* TS 38.415 Fig. 5.5.2.1-1
|
||||||
|
*/
|
||||||
|
typedef struct nr_sdap_dl_hdr_s {
|
||||||
|
uint8_t QFI:6;
|
||||||
|
uint8_t RQI:1;
|
||||||
|
uint8_t RDI:1;
|
||||||
|
} __attribute__((packed)) nr_sdap_dl_hdr_t;
|
||||||
|
|
||||||
|
typedef struct nr_sdap_ul_hdr_s {
|
||||||
|
uint8_t QFI:6;
|
||||||
|
uint8_t R:1;
|
||||||
|
uint8_t DC:1;
|
||||||
|
} __attribute__((packed)) nr_sdap_ul_hdr_t;
|
||||||
|
|
||||||
|
typedef struct nr_sdap_entity_s {
|
||||||
|
uint16_t rnti;
|
||||||
|
nr_pdcp_entity_t *default_drb;
|
||||||
|
int pdusession_id;
|
||||||
|
nr_pdcp_entity_t *qfi2drb_table[SDAP_MAX_QFI];
|
||||||
|
|
||||||
|
void (*qfi2drb_map_update)(struct nr_sdap_entity_s *entity, uint8_t qfi, uint8_t drb);
|
||||||
|
void (*qfi2drb_map_delete)(struct nr_sdap_entity_s *entity, uint8_t qfi);
|
||||||
|
nr_pdcp_entity_t *(*qfi2drb_map)(struct nr_sdap_entity_s *entity, uint8_t qfi, long upper_layer_rb_id);
|
||||||
|
|
||||||
|
nr_sdap_ul_hdr_t (*sdap_construct_ctrl_pdu)(uint8_t qfi);
|
||||||
|
nr_pdcp_entity_t *(*sdap_map_ctrl_pdu)(struct nr_sdap_entity_s *entity, nr_pdcp_entity_t *pdcp_entity, int map_type, uint8_t dl_qfi);
|
||||||
|
void (*sdap_submit_ctrl_pdu)(int rnti, nr_pdcp_entity_t *sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu);
|
||||||
|
|
||||||
|
|
||||||
|
boolean_t (*tx_entity)(struct nr_sdap_entity_s *entity,
|
||||||
|
protocol_ctxt_t *ctxt_p,
|
||||||
|
const srb_flag_t srb_flag,
|
||||||
|
const rb_id_t rb_id,
|
||||||
|
const mui_t mui,
|
||||||
|
const confirm_t confirm,
|
||||||
|
const sdu_size_t sdu_buffer_size,
|
||||||
|
unsigned char *const sdu_buffer,
|
||||||
|
const pdcp_transmission_mode_t pt_mode,
|
||||||
|
const uint32_t *sourceL2Id,
|
||||||
|
const uint32_t *destinationL2Id);
|
||||||
|
|
||||||
|
void (*rx_entity)(struct nr_sdap_entity_s *entity,
|
||||||
|
nr_pdcp_entity_t *pdcp_entity,
|
||||||
|
int rnti,
|
||||||
|
char *buf,
|
||||||
|
int size);
|
||||||
|
|
||||||
|
/* List of entities */
|
||||||
|
struct nr_sdap_entity_s *next_entity;
|
||||||
|
} nr_sdap_entity_t;
|
||||||
|
|
||||||
|
/* QFI to DRB Mapping Related Function */
|
||||||
|
void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, uint8_t drb);
|
||||||
|
|
||||||
|
/* QFI to DRB Mapping Related Function */
|
||||||
|
void nr_sdap_qfi2drb_map_del(nr_sdap_entity_t *entity, uint8_t qfi);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324
|
||||||
|
* 4.4 Functions
|
||||||
|
* Mapping between a QoS flow and a DRB for both DL and UL.
|
||||||
|
*
|
||||||
|
* 5.2.1 Uplink
|
||||||
|
* If there is no stored QoS flow to DRB mapping rule for the QoS flow as specified in the subclause 5.3, map the SDAP SDU to the default DRB
|
||||||
|
* else, map the SDAP SDU to the DRB according to the stored QoS flow to DRB mapping rule.
|
||||||
|
*/
|
||||||
|
nr_pdcp_entity_t *nr_sdap_qfi2drb_map(nr_sdap_entity_t *entity, uint8_t qfi, long upper_layer_rb_id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.3 QoS flow to DRB Mapping
|
||||||
|
* construct an end-marker control PDU, as specified in the subclause 6.2.3, for the QoS flow;
|
||||||
|
*/
|
||||||
|
nr_sdap_ul_hdr_t nr_sdap_construct_ctrl_pdu(uint8_t qfi);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.3 QoS flow to DRB Mapping
|
||||||
|
* map the end-marker control PDU to the
|
||||||
|
* 1.) default DRB or
|
||||||
|
* 2.) DRB according to the stored QoS flow to DRB mapping rule
|
||||||
|
*/
|
||||||
|
nr_pdcp_entity_t *nr_sdap_map_ctrl_pdu(nr_sdap_entity_t *entity, nr_pdcp_entity_t *pdcp_entity, int map_type, uint8_t dl_qfi);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.3 QoS flow to DRB Mapping
|
||||||
|
* Submit the end-marker control PDU to the lower layer.
|
||||||
|
*/
|
||||||
|
void nr_sdap_submit_ctrl_pdu(int rnti, nr_pdcp_entity_t *sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 5.3 QoS flow to DRB Mapping
|
||||||
|
* 5.3.1 Configuration Procedures
|
||||||
|
*/
|
||||||
|
void nr_sdap_ue_qfi2drb_config(nr_sdap_entity_t *existing_sdap_entity,
|
||||||
|
nr_pdcp_entity_t *pdcp_entity,
|
||||||
|
uint16_t rnti,
|
||||||
|
NR_QFI_t *mapped_qfi_2_add,
|
||||||
|
uint8_t mappedQFIs2AddCount,
|
||||||
|
uint8_t drb_identity);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS 37.324 4.4 5.1.1 SDAP entity establishment
|
||||||
|
* Establish an SDAP entity.
|
||||||
|
*/
|
||||||
|
nr_sdap_entity_t *new_nr_sdap_entity(uint16_t rnti,
|
||||||
|
int pdusession_id,
|
||||||
|
boolean_t is_defaultDRB,
|
||||||
|
uint8_t default_DRB,
|
||||||
|
NR_QFI_t *mapped_qfi_2_add,
|
||||||
|
uint8_t mappedQFIs2AddCount);
|
||||||
|
|
||||||
|
/* Entity Handling Related Functions */
|
||||||
|
nr_sdap_entity_t *nr_sdap_get_entity(uint16_t rnti, int pdusession_id);
|
||||||
|
|
||||||
|
/* Entity Handling Related Functions */
|
||||||
|
void delete_nr_sdap_entity(uint16_t rnti);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
||||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
||||||
* except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.openairinterface.org/?page_id=698
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*-------------------------------------------------------------------------------
|
|
||||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
||||||
* contact@openairinterface.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "nr_sdap_gnb.h"
|
|
||||||
#include <openair2/LAYER2/PDCP_v10.1.0/pdcp.h>
|
|
||||||
|
|
||||||
boolean_t sdap_gnb_data_req(protocol_ctxt_t *ctxt_p,
|
|
||||||
const srb_flag_t srb_flag,
|
|
||||||
const rb_id_t rb_id,
|
|
||||||
const mui_t mui,
|
|
||||||
const confirm_t confirm,
|
|
||||||
const sdu_size_t sdu_buffer_size,
|
|
||||||
unsigned char *const sdu_buffer,
|
|
||||||
const pdcp_transmission_mode_t pt_mode,
|
|
||||||
const uint32_t *sourceL2Id,
|
|
||||||
const uint32_t *destinationL2Id
|
|
||||||
) {
|
|
||||||
if(sdu_buffer == NULL) {
|
|
||||||
LOG_E(PDCP, "%s:%d:%s: SDAP Layer gNB - NULL sdu_buffer \n", __FILE__, __LINE__, __FUNCTION__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sdu_buffer_size == 0) {
|
|
||||||
LOG_E(PDCP, "%s:%d:%s: SDAP Layer gNB - NULL or 0 sdu_buffer_size \n", __FILE__, __LINE__, __FUNCTION__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *sdap_buf = (uint8_t *)malloc(sdu_buffer_size+SDAP_HDR_LENGTH);
|
|
||||||
nr_sdap_dl_hdr_t sdap_hdr;
|
|
||||||
sdap_hdr.RDI = 0; // SDAP_Hardcoded -
|
|
||||||
sdap_hdr.RQI = 0; // SDAP_Hardcoded - Should get this info from DL_PDU_SESSION_INFORMATION
|
|
||||||
sdap_hdr.QFI = 1; // SDAP_Hardcoded - Should get this info from DL_PDU_SESSION_INFORMATION
|
|
||||||
memcpy(&sdap_buf[0], &sdap_hdr, 1);
|
|
||||||
memcpy(&sdap_buf[1], sdu_buffer, sdu_buffer_size);
|
|
||||||
rb_id_t sdap_drb_id = rb_id; // SDAP_Hardcoded - Should get this info from QFI to DRB mapping table
|
|
||||||
boolean_t ret = pdcp_data_req(ctxt_p,
|
|
||||||
srb_flag,
|
|
||||||
sdap_drb_id,
|
|
||||||
mui,
|
|
||||||
confirm,
|
|
||||||
sdu_buffer_size+1,
|
|
||||||
sdap_buf,
|
|
||||||
pt_mode,
|
|
||||||
sourceL2Id,
|
|
||||||
destinationL2Id);
|
|
||||||
|
|
||||||
if(!ret) {
|
|
||||||
LOG_E(PDCP, "%s:%d:%s: SDAP Layer gNB - PDCP DL refused PDU\n", __FILE__, __LINE__, __FUNCTION__);
|
|
||||||
free(sdap_buf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(sdap_buf);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sdap_gnb_ul_header_handler(char sdap_gnb_ul_hdr) {
|
|
||||||
nr_sdap_ul_hdr_t *sdap_hdr_ul = (nr_sdap_ul_hdr_t *)&sdap_gnb_ul_hdr;
|
|
||||||
|
|
||||||
switch (sdap_hdr_ul->DC) {
|
|
||||||
case SDAP_HDR_UL_DATA_PDU:
|
|
||||||
LOG_I(PDCP, "%s:%d:%s: SDAP Layer gNB - UL Received SDAP Data PDU\n", __FILE__, __LINE__, __FUNCTION__);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDAP_HDR_UL_CTRL_PDU:
|
|
||||||
LOG_I(PDCP, "%s:%d:%s: SDAP Layer gNB - Received SDAP Control PDU\n", __FILE__, __LINE__, __FUNCTION__);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
||||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
||||||
* except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.openairinterface.org/?page_id=698
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*-------------------------------------------------------------------------------
|
|
||||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
||||||
* contact@openairinterface.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _NR_SDAP_GNB_
|
|
||||||
#define _NR_SDAP_GNB_
|
|
||||||
|
|
||||||
#include "openair2/COMMON/platform_types.h"
|
|
||||||
#include "common/utils/LOG/log.h"
|
|
||||||
|
|
||||||
#define SDAP_BITMASK_DC (0x80)
|
|
||||||
#define SDAP_BITMASK_R (0x40)
|
|
||||||
#define SDAP_BITMASK_QFI (0x3F)
|
|
||||||
#define SDAP_HDR_UL_DATA_PDU (1)
|
|
||||||
#define SDAP_HDR_UL_CTRL_PDU (0)
|
|
||||||
#define SDAP_HDR_LENGTH (1)
|
|
||||||
|
|
||||||
typedef struct nr_sdap_dl_hdr_s {
|
|
||||||
uint8_t QFI:6;
|
|
||||||
uint8_t RQI:1;
|
|
||||||
uint8_t RDI:1;
|
|
||||||
} __attribute__((packed)) nr_sdap_dl_hdr_t;
|
|
||||||
|
|
||||||
typedef struct nr_sdap_ul_hdr_s {
|
|
||||||
uint8_t QFI:6;
|
|
||||||
uint8_t R:1;
|
|
||||||
uint8_t DC:1;
|
|
||||||
} __attribute__((packed)) nr_sdap_ul_hdr_t;
|
|
||||||
|
|
||||||
boolean_t sdap_gnb_data_req(protocol_ctxt_t *ctxt_p,
|
|
||||||
const srb_flag_t srb_flag,
|
|
||||||
const rb_id_t rb_id,
|
|
||||||
const mui_t mui,
|
|
||||||
const confirm_t confirm,
|
|
||||||
const sdu_size_t sdu_buffer_size,
|
|
||||||
unsigned char *const sdu_buffer,
|
|
||||||
const pdcp_transmission_mode_t pt_mode,
|
|
||||||
const uint32_t *sourceL2Id,
|
|
||||||
const uint32_t *destinationL2Id
|
|
||||||
);
|
|
||||||
|
|
||||||
void sdap_gnb_ul_header_handler(char sdap_gnb_ul_hdr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
||||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
||||||
* except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.openairinterface.org/?page_id=698
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*-------------------------------------------------------------------------------
|
|
||||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
||||||
* contact@openairinterface.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*! \file sdap_gNB.c
|
|
||||||
* \brief sdap tasks for gNB
|
|
||||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
|
||||||
* \date 2018
|
|
||||||
* \version 1.0
|
|
||||||
*/
|
|
||||||
#define SDAP_GNB
|
|
||||||
#define SDAP_GNB_C
|
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ extern "C" {
|
|||||||
#include <openair2/COMMON/gtpv1_u_messages_types.h>
|
#include <openair2/COMMON/gtpv1_u_messages_types.h>
|
||||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||||
#include <openair2/LAYER2/PDCP_v10.1.0/pdcp.h>
|
#include <openair2/LAYER2/PDCP_v10.1.0/pdcp.h>
|
||||||
#include "openair2/SDAP/nr_sdap/nr_sdap_gnb.h"
|
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
|
||||||
//#include <openair1/PHY/phy_extern.h>
|
//#include <openair1/PHY/phy_extern.h>
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
@@ -34,8 +34,35 @@ typedef struct Gtpv1uMsgHeader {
|
|||||||
teid_t teid;
|
teid_t teid;
|
||||||
} __attribute__((packed)) Gtpv1uMsgHeaderT;
|
} __attribute__((packed)) Gtpv1uMsgHeaderT;
|
||||||
|
|
||||||
|
typedef struct Gtpv1uMsgHeaderOptFields {
|
||||||
|
uint8_t seqNum1Oct;
|
||||||
|
uint8_t seqNum2Oct;
|
||||||
|
uint8_t NPDUNum;
|
||||||
|
uint8_t NextExtHeaderType;
|
||||||
|
} __attribute__((packed)) Gtpv1uMsgHeaderOptFieldsT;
|
||||||
|
|
||||||
|
typedef struct PDUSessionContainer {
|
||||||
|
uint8_t spare:4;
|
||||||
|
uint8_t PDU_type:4;
|
||||||
|
uint8_t QFI:6;
|
||||||
|
uint8_t RQI:1;
|
||||||
|
uint8_t PPP:1;
|
||||||
|
} __attribute__((packed)) PDUSessionContainerT;
|
||||||
|
|
||||||
|
typedef struct Gtpv1uExtHeader {
|
||||||
|
uint8_t ExtHeaderLen;
|
||||||
|
PDUSessionContainerT pdusession_cntr;
|
||||||
|
//uint8_t NextExtHeaderType;
|
||||||
|
}__attribute__((packed)) Gtpv1uExtHeaderT;
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
// TS 29.281, fig 5.2.1-3
|
||||||
|
#define PDU_SESSION_CONTAINER (0x85)
|
||||||
|
// TS 29.281, 5.2.1
|
||||||
|
#define EXT_HDR_LNTH_OCTET_UNITS (4)
|
||||||
|
#define NO_MORE_EXT_HDRS (0)
|
||||||
|
|
||||||
// TS 29.060, table 7.1 defines the possible message types
|
// TS 29.060, table 7.1 defines the possible message types
|
||||||
// here are all the possible messages (3GPP R16)
|
// here are all the possible messages (3GPP R16)
|
||||||
#define GTP_ECHO_REQ (1)
|
#define GTP_ECHO_REQ (1)
|
||||||
@@ -65,6 +92,7 @@ typedef struct {
|
|||||||
rnti_t rnti;
|
rnti_t rnti;
|
||||||
ebi_t incoming_rb_id;
|
ebi_t incoming_rb_id;
|
||||||
gtpCallback callBack;
|
gtpCallback callBack;
|
||||||
|
int pdusession_id;
|
||||||
} rntiData_t;
|
} rntiData_t;
|
||||||
|
|
||||||
class gtpEndPoint {
|
class gtpEndPoint {
|
||||||
@@ -449,6 +477,8 @@ teid_t newGtpuCreateTunnel(instance_t instance, rnti_t rnti, int incoming_bearer
|
|||||||
|
|
||||||
inst->te2ue_mapping[incoming_teid].callBack=callBack;
|
inst->te2ue_mapping[incoming_teid].callBack=callBack;
|
||||||
|
|
||||||
|
inst->te2ue_mapping[incoming_teid].pdusession_id = (uint8_t)outgoing_bearer_id;
|
||||||
|
|
||||||
gtpv1u_bearer_t *tmp=&inst->ue2te_mapping[rnti].bearers[outgoing_bearer_id];
|
gtpv1u_bearer_t *tmp=&inst->ue2te_mapping[rnti].bearers[outgoing_bearer_id];
|
||||||
|
|
||||||
int addrs_length_in_bytes = remoteAddr.length / 8;
|
int addrs_length_in_bytes = remoteAddr.length / 8;
|
||||||
@@ -574,7 +604,7 @@ int gtpv1u_create_ngu_tunnel( const instance_t instance,
|
|||||||
create_tunnel_req->pdusession_id[i],
|
create_tunnel_req->pdusession_id[i],
|
||||||
create_tunnel_req->outgoing_teid[i],
|
create_tunnel_req->outgoing_teid[i],
|
||||||
create_tunnel_req->dst_addr[i], dstport,
|
create_tunnel_req->dst_addr[i], dstport,
|
||||||
sdap_gnb_data_req);
|
sdap_data_req);
|
||||||
create_tunnel_resp->status=0;
|
create_tunnel_resp->status=0;
|
||||||
create_tunnel_resp->rnti=create_tunnel_req->rnti;
|
create_tunnel_resp->rnti=create_tunnel_req->rnti;
|
||||||
create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels;
|
create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels;
|
||||||
@@ -815,10 +845,28 @@ static int Gtpv1uHandleGpdu(int h,
|
|||||||
return GTPNOK;
|
return GTPNOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset=8;
|
int offset=sizeof(Gtpv1uMsgHeaderT);
|
||||||
|
|
||||||
if( msgHdr->E || msgHdr->S ||msgHdr->PN)
|
uint8_t qfi = 0;
|
||||||
offset+=8;
|
boolean_t rqi = FALSE;
|
||||||
|
|
||||||
|
if( msgHdr->E || msgHdr->S || msgHdr->PN){
|
||||||
|
Gtpv1uMsgHeaderOptFieldsT *msgHdrOpt = (Gtpv1uMsgHeaderOptFieldsT *)(msgBuf+offset);
|
||||||
|
offset+=sizeof(Gtpv1uMsgHeaderOptFieldsT);
|
||||||
|
if( msgHdr->E && msgHdrOpt->NextExtHeaderType == PDU_SESSION_CONTAINER){
|
||||||
|
Gtpv1uExtHeaderT *msgHdrExt = (Gtpv1uExtHeaderT *)(msgBuf+offset);
|
||||||
|
offset+=msgHdrExt->ExtHeaderLen*EXT_HDR_LNTH_OCTET_UNITS;
|
||||||
|
qfi = msgHdrExt->pdusession_cntr.QFI;
|
||||||
|
rqi = msgHdrExt->pdusession_cntr.RQI;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the next extension header type of GTP extension header is set to 0
|
||||||
|
* We can not put it in the struct Gtpv1uExtHeaderT because the length is dynamic.
|
||||||
|
*/
|
||||||
|
if(*(msgBuf+offset-1) != NO_MORE_EXT_HDRS)
|
||||||
|
LOG_W(GTPU, "Warning - Next extension header is not zero, handle it \n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This context is not good for gtp
|
// This context is not good for gtp
|
||||||
// frame, ... has no meaning
|
// frame, ... has no meaning
|
||||||
@@ -828,6 +876,9 @@ static int Gtpv1uHandleGpdu(int h,
|
|||||||
ctxt.enb_flag = 1;
|
ctxt.enb_flag = 1;
|
||||||
ctxt.instance = inst->addr.originInstance;
|
ctxt.instance = inst->addr.originInstance;
|
||||||
ctxt.rnti = tunnel->second.rnti;
|
ctxt.rnti = tunnel->second.rnti;
|
||||||
|
ctxt.sdap.qfi = qfi;
|
||||||
|
ctxt.sdap.rqi = rqi;
|
||||||
|
ctxt.sdap.pdusession_id = tunnel->second.pdusession_id;
|
||||||
ctxt.frame = 0;
|
ctxt.frame = 0;
|
||||||
ctxt.subframe = 0;
|
ctxt.subframe = 0;
|
||||||
ctxt.eNB_index = 0;
|
ctxt.eNB_index = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user