Files
Guido Casati 0348aa08b9 Remove rb_id parameter from SDAP TX entity - QFI determines DRB mapping
- Remove rb_id parameter from nr_sdap_tx_entity() function signature
- Update tx_entity function pointer
- Remove rb_id parameter from sdap_data_req() function signature
- Remove unused rb_id variable from sdap_tun_read_thread

The rb_id parameter was redundant since SDAP determines DRB ID
from QFI mapping via entity->qfi2drb_map(entity, qfi). This
simplifies the interface.
2025-10-24 11:55:25 +02:00

221 lines
7.5 KiB
C

/*
* 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"
#include "assertions.h"
#include "utils.h"
#include <inttypes.h>
#include <pthread.h>
#include <stddef.h>
#include "nr_sdap_entity.h"
#include "common/utils/LOG/log.h"
#include "errno.h"
#include "rlc.h"
#include "tun_if.h"
#include "system.h"
static void reblock_tun_socket(int fd)
{
int f;
f = fcntl(fd, F_GETFL, 0);
f &= ~(O_NONBLOCK);
if (fcntl(fd, F_SETFL, f) == -1) {
LOG_E(PDCP, "fcntl(F_SETFL) failed on fd %d: errno %d, %s\n", fd, errno, strerror(errno));
}
}
bool sdap_data_req(protocol_ctxt_t *ctxt_p,
const ue_id_t ue_id,
const srb_flag_t srb_flag,
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,
const uint8_t qfi,
const bool rqi,
const int pdusession_id) {
nr_sdap_entity_t *sdap_entity;
sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id);
if(sdap_entity == NULL) {
LOG_E(SDAP, "%s:%d:%s: Entity not found with ue: 0x%"PRIx64" and pdusession id: %d\n", __FILE__, __LINE__, __FUNCTION__, ue_id, pdusession_id);
return 0;
}
bool ret = sdap_entity->tx_entity(sdap_entity,
ctxt_p,
srb_flag,
mui,
confirm,
sdu_buffer_size,
sdu_buffer,
pt_mode,
sourceL2Id,
destinationL2Id,
qfi,
rqi);
return ret;
}
void sdap_data_ind(int pdcp_entity,
int is_gnb,
bool has_sdap_rx,
int pdusession_id,
ue_id_t ue_id,
char *buf,
int size) {
nr_sdap_entity_t *sdap_entity;
sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id);
if (sdap_entity == NULL) {
LOG_E(SDAP, "%s:%d:%s: Entity not found for ue rnti/ue_id: %lx and pdusession id: %d\n", __FILE__, __LINE__, __FUNCTION__, ue_id, pdusession_id);
return;
}
sdap_entity->rx_entity(sdap_entity,
pdcp_entity,
is_gnb,
pdusession_id,
ue_id,
buf,
size);
}
static void *sdap_tun_read_thread(void *arg)
{
DevAssert(arg != NULL);
nr_sdap_entity_t *entity = arg;
char rx_buf[NL_MAX_PAYLOAD];
int len;
reblock_tun_socket(entity->pdusession_sock);
while (!entity->stop_thread) {
len = read(entity->pdusession_sock, &rx_buf, NL_MAX_PAYLOAD);
if (len == -1) {
if (errno == EINTR)
continue; // interrupted system call
if (errno == EBADF || errno == EINVAL) {
LOG_I(SDAP, "Socket closed, exiting TUN read thread for UE %ld, PDU session %d\n", entity->ue_id, entity->pdusession_id);
break;
}
LOG_E(PDCP, "read() failed: errno %d (%s)\n", errno, strerror(errno));
break;
}
if (len == 0) {
LOG_W(SDAP, "TUN socket returned EOF - exiting thread\n");
break;
}
LOG_D(SDAP, "read data of size %d\n", len);
protocol_ctxt_t ctxt = {.enb_flag = entity->is_gnb, .rntiMaybeUEid = entity->ue_id};
bool dc = entity->is_gnb ? false : SDAP_HDR_UL_DATA_PDU;
DevAssert(entity != NULL);
entity->tx_entity(entity,
&ctxt,
SRB_FLAG_NO,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
len,
(unsigned char *)rx_buf,
PDCP_TRANSMISSION_MODE_DATA,
NULL,
NULL,
entity->qfi,
dc);
}
return NULL;
}
void start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id_t ue_id)
{
nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, get_softmodem_params()->default_pdu_session_id);
DevAssert(entity != NULL);
DevAssert(entity->is_gnb);
char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb";
char ifname[IFNAMSIZ];
tun_generate_ifname(ifname, ifprefix, ue_id - 1);
entity->pdusession_sock = tun_alloc(ifname);
tun_config(ifname, "10.0.1.1", NULL);
threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, entity, "gnb_tun_read_thread", -1, OAI_PRIORITY_RT_LOW);
}
void start_sdap_tun_ue(ue_id_t ue_id, int pdu_session_id, int sock)
{
nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, pdu_session_id);
DevAssert(entity != NULL);
DevAssert(!entity->is_gnb);
entity->pdusession_sock = sock;
entity->stop_thread = false;
char thread_name[64];
snprintf(thread_name, sizeof(thread_name), "ue_tun_read_%ld_p%d", ue_id, pdu_session_id);
threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, entity, thread_name, -1, OAI_PRIORITY_RT_LOW);
}
void create_ue_ip_if(const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id)
{
int default_pdu = get_softmodem_params()->default_pdu_session_id;
char ifname[IFNAMSIZ];
tun_generate_ue_ifname(ifname, ue_id, pdu_session_id != default_pdu ? pdu_session_id : -1);
const int sock = tun_alloc(ifname);
tun_config(ifname, ipv4, ipv6);
if (ipv4) {
setup_ue_ipv4_route(ifname, ue_id, ipv4);
}
start_sdap_tun_ue(ue_id, pdu_session_id, sock); // interface name suffix is ue_id+1
}
void remove_ip_if(nr_sdap_entity_t *entity)
{
DevAssert(entity != NULL);
// Stop the read thread
entity->stop_thread = true;
// Close the socket: read() will get EBADF and exit
close(entity->pdusession_sock);
int ret = pthread_join(entity->pdusession_thread, NULL);
AssertFatal(ret == 0, "pthread_join() failed, errno: %d, %s\n", errno, strerror(errno));
// Bring down the IP interface
int default_pdu = get_softmodem_params()->default_pdu_session_id;
char ifname[IFNAMSIZ];
if (entity->is_gnb) {
char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb";
tun_generate_ifname(ifname, ifprefix, entity->ue_id - 1);
} else {
tun_generate_ue_ifname(ifname, entity->ue_id, entity->pdusession_id != default_pdu ? entity->pdusession_id : -1);
}
tun_destroy(ifname);
}