SDAP Initial Implementation

This commit is contained in:
athanassopoulos
2022-04-01 13:35:40 +02:00
parent 5a3eeac5e4
commit a826af5839
20 changed files with 937 additions and 243 deletions
+73
View File
@@ -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);
}
+59
View File
@@ -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
+474
View File
@@ -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(&gtpu_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);
}
}
}
+167
View File
@@ -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
-87
View File
@@ -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;
}
}
-61
View File
@@ -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
-30
View File
@@ -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