Commit a826af58 authored by athanassopoulos's avatar athanassopoulos

SDAP Initial Implementation

parent 5a3eeac5
......@@ -1779,7 +1779,8 @@ set(NR_PDCP_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
......
......@@ -478,6 +478,7 @@ int logInit (void)
register_log_component("NAS","log",NAS);
register_log_component("UDP","",UDP_);
register_log_component("GTPU","",GTPU);
register_log_component("SDAP","",SDAP);
register_log_component("S1AP","",S1AP);
register_log_component("F1AP","",F1AP);
register_log_component("M2AP","",M2AP);
......
......@@ -215,6 +215,7 @@ typedef enum {
OCM,
UDP_,
GTPU,
SDAP,
SPGW,
S1AP,
F1AP,
......
......@@ -944,6 +944,27 @@ ID = LEGACY_GTPU_TRACE
GROUP = ALL:LEGACY_GTPU:LEGACY_GROUP_TRACE:LEGACY
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
DESC = TMR legacy logs - info level
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 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**
- NR RRC (38.331) Rel 16 messages using new asn1c
- 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
- 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)
- 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 #
......@@ -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
- 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**
* Integration of RRC messages and procedures supporting UE 5G SA connection according to 38.331 Rel.16
- 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,
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 {
module_id_t module_id; /*!< \brief Virtualized module identifier */
eNB_flag_t enb_flag; /*!< \brief Flag to indicate eNB (1) or UE (0) */
instance_t instance; /*!< \brief ITTI or OTG module identifier */
rnti_t rnti;
sdap_protocol_ctxt_t sdap;
frame_t frame; /*!< \brief LTE 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) */
......
......@@ -368,8 +368,8 @@ nr_pdcp_entity_t *new_nr_pdcp_entity(
ret->set_security = nr_pdcp_entity_set_security;
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_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_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size,
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
* to keep the current algorithm
......
......@@ -36,7 +36,8 @@
#include "pdcp.h"
#include "LAYER2/nr_rlc/nr_rlc_oai_api.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 { \
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
......@@ -438,9 +439,13 @@ static void *enb_tun_read_thread(void *_)
ctxt.rnti = rnti;
pdcp_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);
ctxt.sdap.qfi = 7;
ctxt.sdap.rqi = 0;
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;
......@@ -481,9 +486,13 @@ static void *ue_tun_read_thread(void *_)
ctxt.rnti = rnti;
pdcp_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);
ctxt.sdap.dc = SDAP_HDR_UL_DATA_PDU;
ctxt.sdap.qfi = 7;
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;
......@@ -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,
char *buf, int size)
{
extern int nas_sock_fd[];
int len;
nr_pdcp_ue_t *ue = _ue;
MessageDef *message_p;
uint8_t *gtpu_buffer_p;
int rb_id;
int i;
if (IS_SOFTMODEM_NOS1 || UE_NAS_USE_TUN) {
LOG_D(PDCP, "IP packet received, to be sent to TUN interface");
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));
}
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);
}
else{
for (i = 0; i < 5; i++) {
......@@ -644,31 +638,9 @@ static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity,
rb_found:
{
int offset=0;
if (entity->has_sdap == 1 && entity->has_sdapULheader == 1)
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=&GTPV1U_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);
}
LOG_D(PDCP, "%s() (drb %d) sending message to SDAP size %d\n", __func__, rb_id, size);
sdap_data_ind(entity, ue->rnti, buf, size);
}
}
}
......@@ -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_sdapULheader=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)
pdusession_id = s->cnAssociation->choice.eps_BearerIdentity;
else {
......@@ -978,6 +953,10 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
has_sdap = 1;
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;
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? */
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);
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);
}
......@@ -1140,7 +1127,7 @@ void nr_DRB_preconfiguration(uint16_t crnti)
NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod));
drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation));
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->reestablishPDCP = 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_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;
}
#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++)
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++)
if (ue->drb[j] != NULL)
ue->drb[j]->delete(ue->drb[j]);
ue->drb[j]->delete_entity(ue->drb[j]);
free(ue);
......
......@@ -818,7 +818,6 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
uint8_t buffer[RRC_BUF_SIZE];
uint16_t size;
int qos_flow_index = 0;
NR_QFI_t qfi = 0;
int pdu_sessions_done = 0;
int i;
NR_CellGroupConfig_t *cellGroupConfig;
......@@ -870,14 +869,15 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
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->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->mappedQoS_FlowsToAdd = calloc(1, 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++) {
qfi = ue_context_pP->ue_context.pduSession[i].param.qos[qos_flow_index].qfi;
ASN_SEQUENCE_ADD(&sdap_config->mappedQoS_FlowsToAdd->list, &qfi);
NR_QFI_t *qfi = calloc(1, sizeof(NR_QFI_t));
*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;
DRB_config->cnAssociation->choice.sdap_Config = sdap_config;
......
......@@ -19,43 +19,55 @@
* contact@openairinterface.org
*/
#ifndef _NR_SDAP_GNB_
#define _NR_SDAP_GNB_
#include "nr_sdap.h"
#include "openair2/COMMON/platform_types.h"
#include "common/utils/LOG/log.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);
#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)
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;
}
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;
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;
}
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;
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);
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(sdap_entity == NULL) {
LOG_E(SDAP, "%s:%d:%s: Entity not found\n", __FILE__, __LINE__, __FUNCTION__);
return;
}
void sdap_gnb_ul_header_handler(char sdap_gnb_ul_hdr);
#endif
\ No newline at end of file
sdap_entity->rx_entity(sdap_entity,
pdcp_entity,
rnti,
buf,
size);
}
......@@ -19,12 +19,41 @@
* 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
#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
*/
#define SDAP_GNB
#define SDAP_GNB_C
void sdap_data_ind(nr_pdcp_entity_t *pdcp_entity,
int rnti,
char *buf,
int size
);
#endif
This diff is collapsed.
/*
* 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
/*
* 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;
}
}
\ No newline at end of file
......@@ -17,7 +17,7 @@ extern "C" {
#include <openair2/COMMON/gtpv1_u_messages_types.h>
#include <openair3/ocp-gtpu/gtp_itf.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>
#pragma pack(1)
......@@ -34,8 +34,35 @@ typedef struct Gtpv1uMsgHeader {
teid_t teid;
} __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()
// 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
// here are all the possible messages (3GPP R16)
#define GTP_ECHO_REQ (1)
......@@ -65,6 +92,7 @@ typedef struct {
rnti_t rnti;
ebi_t incoming_rb_id;
gtpCallback callBack;
int pdusession_id;
} rntiData_t;
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].pdusession_id = (uint8_t)outgoing_bearer_id;
gtpv1u_bearer_t *tmp=&inst->ue2te_mapping[rnti].bearers[outgoing_bearer_id];
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->outgoing_teid[i],
create_tunnel_req->dst_addr[i], dstport,
sdap_gnb_data_req);
sdap_data_req);
create_tunnel_resp->status=0;
create_tunnel_resp->rnti=create_tunnel_req->rnti;
create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels;
......@@ -815,10 +845,28 @@ static int Gtpv1uHandleGpdu(int h,
return GTPNOK;
}
int offset=8;
if( msgHdr->E || msgHdr->S ||msgHdr->PN)
offset+=8;
int offset=sizeof(Gtpv1uMsgHeaderT);
uint8_t qfi = 0;
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
// frame, ... has no meaning
......@@ -828,6 +876,9 @@ static int Gtpv1uHandleGpdu(int h,
ctxt.enb_flag = 1;
ctxt.instance = inst->addr.originInstance;
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.subframe = 0;
ctxt.eNB_index = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment