Merge remote-tracking branch 'origin/add-support-eth-pdu-sess' into integration_2026_w05 (!3769)

Add Ethernet PDU session support and make PDU session request configurable

This MR adds support for Ethernet PDU sessions, and makes PDU sessions
configurable: per-PDU session ID, type (IPv4/IPv4v6/IPv6/Ethernet [1]),
DNN, NSSAI.

Concretely, it adds a new configuration file section pdu_sessions below
uicc0 that looks like this if everything is specified (default values
are shown):

    uicc0:
      [...]
      pdu_sessions:
        - id: 1
          type: "IPv4"
          nssai_sst: 1
          nssai_sd: 0xffffff
          dnn: "oai"

It is possible to list multiple PDU sessions (add new line   - id: 2 to
request a second PDU session). It is backwards-compatible to the current
PDU session configuration (uicc0.dnn/nssai_sst/etc), the idea being that
either legacy or new configuration could be used, but (1) if
pdu_sessions exist, it will overwrite the legacy configuration, and (2)
multiple PDU sessions, and type, can only be configured using the new
config. The old parameters --extra-pdu-id and --default-pdu-id are not
accepted anymore. Documentation has been added to the UE tutorial.

It is possible to test an Ethernet PDU session [1]. It is possible to
test the PDU session inside the UE by verifying it has an TAP interface
oaitap_ue1, and ARPing the data network (arping has been added to
oai-nr-ue container for that purpose):

    ip addr add 192.168.72.140/26 dev oaitap_ue1  # same subnet as data network!
    ip link set dev oaitap_ue1 up
    arping -c 20 -I oaitap_ue1 192.168.72.135     # will send ARP request in Ethernet frame to get IP address of data network

[1] See description MR !3769 for more information. On the UE side, only
the type has to be changed to "Ethernet".
This commit is contained in:
Robert Schmidt
2026-01-29 07:52:48 +01:00
49 changed files with 483 additions and 190 deletions
@@ -23,7 +23,6 @@
#include <arpa/inet.h>
#include "PduSessionEstablishmentAccept.h"
#include "common/utils/LOG/log.h"
#include "common/utils/tun_if.h"
#include "fgs_nas_utils.h"
/**
@@ -49,6 +49,8 @@ typedef enum { FOREACH_IEI(TO_ENUM) } pduSessionEstablishment_IEI_t;
#define PDU_SESSION_TYPE_IPV4 0b001
#define PDU_SESSION_TYPE_IPV6 0b010
#define PDU_SESSION_TYPE_IPV4V6 0b011
#define PDU_SESSION_TYPE_UNSTRUCT 0b100
#define PDU_SESSION_TYPE_ETHER 0b101
#define IPv4_ADDRESS_LENGTH 4 // length of the IPv4 address associated with a PDU session
#define IPv6_INTERFACE_ID_LENGTH 8 // interface identifier for the IPv6 link local address
#define SMF_IPv6_LLA_LENGTH 16
+74 -39
View File
@@ -56,7 +56,6 @@
#include "aka_functions.h"
#include "assertions.h"
#include "common/utils/ds/byte_array.h"
#include "common/utils/tun_if.h"
#include "commonDef.h"
#include "intertask_interface.h"
#include "kdf.h"
@@ -1473,7 +1472,10 @@ static int capture_ipv6_addr(const uint8_t *addr, char *ip, size_t len)
* @brief Process PDU Session Address in PDU Session Establishment Accept message
* and configure the tun interface
*/
static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg, int instance_id, int pdu_session_id)
static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg,
int instance_id,
int pdu_session_id,
bool is_default)
{
uint8_t *addr = msg->pdu_addr_ie.pdu_addr_oct;
@@ -1481,13 +1483,13 @@ static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg
case PDU_SESSION_TYPE_IPV4: {
char ip[20];
capture_ipv4_addr(&addr[0], ip, sizeof(ip));
create_ue_ip_if(ip, NULL, instance_id, pdu_session_id);
create_ue_ip_if(ip, NULL, instance_id, pdu_session_id, is_default);
} break;
case PDU_SESSION_TYPE_IPV6: {
char ipv6[40];
capture_ipv6_addr(addr, ipv6, sizeof(ipv6));
create_ue_ip_if(NULL, ipv6, instance_id, pdu_session_id);
create_ue_ip_if(NULL, ipv6, instance_id, pdu_session_id, is_default);
} break;
case PDU_SESSION_TYPE_IPV4V6: {
@@ -1495,7 +1497,7 @@ static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg
capture_ipv6_addr(addr, ipv6, sizeof(ipv6));
char ipv4[20];
capture_ipv4_addr(&addr[IPv6_INTERFACE_ID_LENGTH], ipv4, sizeof(ipv4));
create_ue_ip_if(ipv4, ipv6, instance_id, pdu_session_id);
create_ue_ip_if(ipv4, ipv6, instance_id, pdu_session_id, is_default);
} break;
default:
@@ -1507,7 +1509,7 @@ static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg
/**
* @brief Handle PDU Session Establishment Accept and process decoded message
*/
static void handle_pdu_session_accept(uint8_t *pdu_buffer, uint32_t msg_length, int instance)
static void handle_pdu_session_accept(const nr_ue_nas_t *nas, uint8_t *pdu_buffer, uint32_t msg_length, int instance)
{
pdu_session_establishment_accept_msg_t msg = {0};
int size = 0;
@@ -1545,22 +1547,42 @@ static void handle_pdu_session_accept(uint8_t *pdu_buffer, uint32_t msg_length,
size += decoded;
// decode PDU Session Establishment Accept
if (!decode_pdu_session_establishment_accept_msg(&msg, pdu_buffer + size, msg_length))
if (!decode_pdu_session_establishment_accept_msg(&msg, pdu_buffer + size, msg_length)) {
LOG_E(NAS, "decode_pdu_session_establishment_accept_msg failure\n");
return;
}
int idx;
for (idx = 0; idx < nas->uicc->n_pdu_sessions; ++idx) {
const pdu_session_config_t *pdu = &nas->uicc->pdu_sessions[idx];
if (pdu->id == sm_header.pdu_session_id && pdu->type == msg.pdu_type)
break;
}
if (idx == nas->uicc->n_pdu_sessions) {
LOG_E(NAS,
"PDU session establishment accept for ID %d type %d not in list of configured PDU sessions, abort transaction\n",
sm_header.pdu_session_id,
msg.pdu_type);
return;
}
// process PDU Session: pass ID -1 to not append PDU ID to interface
bool is_default = idx == 0;
if (msg.pdu_type == PDU_SESSION_TYPE_ETHER) {
create_ue_eth_if(instance, sm_header.pdu_session_id, is_default);
} else if (msg.pdu_addr_ie.pdu_length) {
process_pdu_session_addr(&msg, instance, sm_header.pdu_session_id, is_default);
} else {
LOG_W(NAS, "Unhandled PDU session type %d, ignoring PDU session ID %d\n", msg.pdu_type, sm_header.pdu_session_id);
}
// process PDU Session
if (msg.pdu_addr_ie.pdu_length)
process_pdu_session_addr(&msg, instance, sm_header.pdu_session_id);
else
LOG_W(NAS, "Optional PDU Address IE was not provided\n");
set_qfi(msg.qos_rules.rule->qfi, sm_header.pdu_session_id, instance);
}
/**
* @brief Handle DL NAS Transport and process piggybacked 5GSM messages
*/
void handleDownlinkNASTransport(uint8_t * pdu_buffer, int pdu_length, int instance)
void handleDownlinkNASTransport(const nr_ue_nas_t *nas, uint8_t * pdu_buffer, int pdu_length, int instance)
{
if (pdu_length < 17) {
LOG_E(NAS, "Received DL NAS Transport message too short (%d)\n", pdu_length);
@@ -1569,7 +1591,7 @@ void handleDownlinkNASTransport(uint8_t * pdu_buffer, int pdu_length, int instan
uint8_t msg_type = *(pdu_buffer + 16);
if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) {
LOG_A(NAS, "Received PDU Session Establishment Accept in DL NAS Transport\n");
handle_pdu_session_accept(pdu_buffer, pdu_length, instance);
handle_pdu_session_accept(nas, pdu_buffer, pdu_length, instance);
} else {
LOG_E(NAS, "Received unexpected message in DLinformationTransfer %d\n", msg_type);
}
@@ -1688,19 +1710,16 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
const bool has_nssai_sd = pdu_req->sd != 0xffffff; // 0xffffff means "no SD", TS 23.003
const size_t nssai_len = has_nssai_sd ? 4 : 1;
mm_msg->snssai.length = nssai_len;
// Fixme: it seems there are a lot of memory errors in this: this value was on the stack,
// but pushed in a itti message to another thread
// this kind of error seems in many places in 5G NAS
mm_msg->snssai.value = calloc(1, nssai_len);
mm_msg->snssai.value[0] = pdu_req->sst;
if (has_nssai_sd)
INT24_TO_BUFFER(pdu_req->sd, &mm_msg->snssai.value[1]);
size += 1 + 1 + nssai_len;
int dnnSize = strlen(nas->uicc->dnnStr);
int dnnSize = strlen(pdu_req->dnn);
mm_msg->dnn.value = calloc(1, dnnSize + 1);
mm_msg->dnn.length = dnnSize + 1;
mm_msg->dnn.value[0] = dnnSize;
memcpy(mm_msg->dnn.value + 1, nas->uicc->dnnStr, dnnSize);
memcpy(mm_msg->dnn.value + 1, pdu_req->dnn, dnnSize);
size += (1 + 1 + dnnSize + 1);
// encode the message
@@ -1772,24 +1791,33 @@ static void send_nas_5gmm_ind(instance_t instance, const Guti5GSMobileIdentity_t
itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg);
}
void request_pdusession(nr_ue_nas_t *nas, int pdusession_id)
void request_pdusession(nr_ue_nas_t *nas, const pdu_session_config_t *pdu)
{
int t = pdu->type;
AssertFatal(t == PDU_SESSION_TYPE_IPV4 || t == PDU_SESSION_TYPE_IPV6 || t == PDU_SESSION_TYPE_IPV4V6
|| t == PDU_SESSION_TYPE_UNSTRUCT || t == PDU_SESSION_TYPE_ETHER,
"illegal PDU session type %d\n",
t);
AssertFatal(t != PDU_SESSION_TYPE_UNSTRUCT, "unstructured PDU sessions not handled yet\n");
MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ);
NAS_PDU_SESSION_REQ(message_p).pdusession_id = pdusession_id;
NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91; // 0x91 = IPv4, 0x92 = IPv6, 0x93 = IPv4v6
NAS_PDU_SESSION_REQ(message_p).sst = nas->uicc->nssai_sst;
NAS_PDU_SESSION_REQ(message_p).sd = nas->uicc->nssai_sd;
nas_pdu_session_req_t *pdu_req = &NAS_PDU_SESSION_REQ(message_p);
pdu_req->pdusession_id = pdu->id;
// 24.501: joint PDU session type IEI (0x9-, Table 8.3.1.1.1) and type (9.11.4.11)
pdu_req->pdusession_type = 0x90 | t;
pdu_req->sst = pdu->nssai.sst;
pdu_req->sd = pdu->nssai.sd;
snprintf(pdu_req->dnn, sizeof(pdu_req->dnn), "%s", pdu->dnn);
itti_send_msg_to_task(TASK_NAS_NRUE, nas->UE_id, message_p);
}
static int get_user_nssai_idx(const nr_nas_msg_snssai_t allowed_nssai[NAS_MAX_NUMBER_SLICES], const nr_ue_nas_t *nas)
static int get_user_nssai_idx(nssai_t ch_nssai, const nr_nas_msg_snssai_t allowed_nssai[NAS_MAX_NUMBER_SLICES])
{
for (int i = 0; i < NAS_MAX_NUMBER_SLICES; i++) {
const nr_nas_msg_snssai_t *nssai = allowed_nssai + i;
/* If it was received in Registration Accept, check the SD
in the stored Allowed N-SSAI, else, consider the SD valid */
bool sd_match = !nssai->sd || (nas->uicc->nssai_sd == *nssai->sd);
if ((nas->uicc->nssai_sst == nssai->sst) && sd_match)
bool sd_match = !nssai->sd || (ch_nssai.sd == *nssai->sd);
if ((ch_nssai.sst == nssai->sst) && sd_match)
return i;
}
return -1;
@@ -1864,12 +1892,18 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff
send_nas_uplink_data_req(nas, &initialNasMsg);
LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n");
}
if (get_user_nssai_idx(msg.nas_allowed_nssai, nas) < 0) {
LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n");
} else {
request_pdusession(nas, get_softmodem_params()->default_pdu_session_id);
if (get_nrUE_params()->extra_pdu_id != -1) {
request_pdusession(nas, get_nrUE_params()->extra_pdu_id);
if (nas->uicc->n_pdu_sessions == 0)
LOG_W(SIM, "no PDU sessions to request configured\n");
for (const pdu_session_config_t *pdu = nas->uicc->pdu_sessions; pdu < nas->uicc->pdu_sessions + nas->uicc->n_pdu_sessions; ++pdu) {
if (get_user_nssai_idx(pdu->nssai, msg.nas_allowed_nssai) < 0) {
LOG_E(NAS,
"PDU session ID %d NSSAI %d.%d: mismatch for allowed NSSAI. Couldn't request PDU session.\n",
pdu->id,
pdu->nssai.sst,
pdu->nssai.sd);
} else {
LOG_I(NAS, "requested PDU session ID %d type %d NSSAI %d.%d DNN %s\n", pdu->id, pdu->type, pdu->nssai.sst, pdu->nssai.sd, pdu->dnn);
request_pdusession(nas, pdu);
}
}
// Free local message after processing
@@ -2017,7 +2051,7 @@ void *nas_nrue(void *args_p)
if (msg_type == FGS_REGISTRATION_ACCEPT) {
handle_registration_accept(nas, ba.buf, ba.len);
} else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) {
handle_pdu_session_accept(ba.buf, ba.len, nas->UE_id);
handle_pdu_session_accept(nas, ba.buf, ba.len, nas->UE_id);
}
// Free NAS buffer memory after use (coming from RRC)
@@ -2103,7 +2137,7 @@ void *nas_nrue(void *args_p)
handle_security_mode_command(nas, &initialNasMsg, pdu_buffer, pdu_length);
break;
case FGS_DOWNLINK_NAS_TRANSPORT:
handleDownlinkNASTransport(pdu_buffer, pdu_length, nas->UE_id);
handleDownlinkNASTransport(nas, pdu_buffer, pdu_length, nas->UE_id);
break;
case FGS_REGISTRATION_ACCEPT:
handle_registration_accept(nas, pdu_buffer, pdu_length);
@@ -2114,7 +2148,7 @@ void *nas_nrue(void *args_p)
nas->fiveGMM_state = FGS_DEREGISTERED;
break;
case FGS_PDU_SESSION_ESTABLISHMENT_ACC:
handle_pdu_session_accept(pdu_buffer, pdu_length, nas->UE_id);
handle_pdu_session_accept(nas, pdu_buffer, pdu_length, nas->UE_id);
break;
case FGS_PDU_SESSION_ESTABLISHMENT_REJ:
LOG_E(NAS, "Received PDU Session Establishment reject\n");
@@ -2159,10 +2193,11 @@ void *nas_nrue(void *args_p)
} break;
case NAS_INIT_NOS1_IF: {
const int pdu_session_id = get_softmodem_params()->default_pdu_session_id;
const int pdu_session_id = DEFAULT_NOS1_PDU_ID;
const char *ip = "10.0.1.2";
const int qfi = 7;
create_ue_ip_if(ip, NULL, nas->UE_id, pdu_session_id);
const bool is_default = true;
create_ue_ip_if(ip, NULL, nas->UE_id, pdu_session_id, is_default);
set_qfi(qfi, pdu_session_id, nas->UE_id);
break;
}
+2 -1
View File
@@ -32,6 +32,7 @@
#define __NR_NAS_MSG_SIM_H__
#include <common/utils/assertions.h>
#include "common/5g_platform_types.h"
#include <openair3/UICC/usim_interface.h>
#include <stdbool.h>
#include <stdint.h>
@@ -113,6 +114,6 @@ void *nas_nrue_task(void *args_p);
void *nas_nrue(void *args_p);
void nas_init_nrue(int num_ues);
void nr_ue_create_ip_if(const char *ifnameprefix, const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id);
void request_pdusession(nr_ue_nas_t *nas, int pdusession_id);
void request_pdusession(nr_ue_nas_t *nas, const pdu_session_config_t *pdu);
#endif /* __NR_NAS_MSG_SIM_H__*/
+1 -1
View File
@@ -45,7 +45,7 @@ Description Defines functions used to handle EPS bearer contexts.
#include "esm_ebr.h"
#include "esm_ebr_context.h"
#include "common/utils/tun_if.h"
#include "common/utils/tuntap_if.h"
#include "emm_sap.h"
#include "system.h"
+1 -1
View File
@@ -1,3 +1,3 @@
add_library(lib_uicc OBJECT usim_interface.c)
add_library(lib_uicc OBJECT usim_interface.c pdu_session.c)
target_include_directories(lib_uicc PRIVATE .)
target_link_libraries(lib_uicc PRIVATE log_headers)
+116
View File
@@ -0,0 +1,116 @@
/*
* 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 <assert.h>
#include "pdu_session.h"
// we can't include the file for PDU session type defines, as it pulls in too
// much. However, we only use it for mapping types to integers, which are
// standard defined, so it should be ok.
//#include "openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h"
#include "common/utils/utils.h"
#include "common/config/config_paramdesc.h"
#include "common/config/config_userapi.h"
// clang-format off
// Note: Default PDU session ID 0 does not exist and will be replaced with PDU
// session index if not set to a parameter > 0!
#define PDU_SESS_PARAMS_DESC { \
{"id", "PDU session ID\n", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{"type", "PDU session type\n", 0, .strptr=NULL, .defstrval="IPv4", TYPE_STRING, 0}, \
{"nssai_sst", "NSSAI slice type\n", 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
{"nssai_sd", "NSSAI slice differentiator\n", 0, .uptr=NULL, .defintval=0xffffff, TYPE_UINT32, 0}, \
{"dnn", "PDU session DNN (APN)\n", 0, .strptr=NULL, .defstrval="oai", TYPE_STRING, 0}, \
}
#define PDU_SESS_PARAMS_CHECK { \
{.s2 = {config_check_intrange, {0, 255}}}, \
{.s3a = {config_checkstr_assign_integer, \
{"IPv4", "IPv6", "IPv4v6", "Ethernet"}, \
{1 /*PDU_SESSION_TYPE_IPV4*/, \
2 /*PDU_SESSION_TYPE_IPV6*/, \
3 /*PDU_SESSION_TYPE_IPV4V6*/, \
5 /*PDU_SESSION_TYPE_ETHER*/}, \
4}}, \
{.s2 = {config_check_intrange, {1, 4}}}, \
{.s2 = {config_check_intrange, {1, 0xffffff}}}, \
{.s4 = {config_check_dnn}}, \
}
// clang-format on
static int config_check_dnn(configmodule_interface_t *cfg, paramdef_t *param)
{
const char *dnn = *param->strptr;
int dnn_len = strlen(dnn);
if (dnn_len > 102) {
printf("DNN '%s' exceeds max len of 102 (is %d) (TS 24.501 §9.11.2.1A)\n", dnn, dnn_len);
return -1;
}
// check for valid characters in the APN (TS 23.003 §9.1)
// we don't enforce all conditions
const char *allowed = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789.-";
while (*dnn) {
if (!strchr(allowed, *dnn)) {
printf("character '%c' in DNN '%s' is not allowed (TS 23.003 §9.1)\n", *dnn, *param->strptr);
return -1;
}
dnn++;
}
return 0;
}
int get_pdu_session_configs(const char *uiccName, pdu_session_config_t *configs, int max_len)
{
paramdef_t pdu_sess_params[] = PDU_SESS_PARAMS_DESC;
const int npsp = sizeofArray(pdu_sess_params);
paramlist_def_t pdu_sess_list = {"pdu_sessions"};
checkedparam_t pdu_sess_params_check[] = PDU_SESS_PARAMS_CHECK;
static_assert(sizeofArray(pdu_sess_params) == sizeofArray(pdu_sess_params_check),
"param_def_t array and corresponding checkedparam_t array should have the same size");
for (int i = 0; i < sizeofArray(pdu_sess_params); ++i)
pdu_sess_params[i].chkPptr = &pdu_sess_params_check[i];
int ret = config_getlist(config_get_if(), &pdu_sess_list, pdu_sess_params, sizeofArray(pdu_sess_params), uiccName);
if (ret < 0) {
// couldn't load configuration from pdu_sessions, caller has to handle
return -1;
}
int num = pdu_sess_list.numelt;
AssertFatal(num <= max_len, "cannot handle more than %d PDU sessions\n", max_len);
for (int i = 0; i < num; ++i) {
pdu_session_config_t *pdu = configs + i;
paramdef_t *p = pdu_sess_list.paramarray[i];
int id = *gpd(p, npsp, "id")->iptr;
pdu->id = id > 0 ? id : i + 1; // if not user-specified ID, use PDU session index
pdu->type = config_get_processedint(config_get_if(), (paramdef_t *)gpd(p, npsp, "type"));
pdu->nssai.sst = *gpd(p, npsp, "nssai_sst")->iptr;
pdu->nssai.sd = *gpd(p, npsp, "nssai_sd")->iptr;
pdu->dnn = strdup(*gpd(p, npsp, "dnn")->strptr);
}
return num;
}
+36
View File
@@ -0,0 +1,36 @@
/*
* 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 PDU_SESSION_H_
#define PDU_SESSION_H_
#include "common/5g_platform_types.h"
typedef struct {
int id;
int type;
nssai_t nssai;
char *dnn; // [103]?
} pdu_session_config_t;
int get_pdu_session_configs(const char *uiccName, pdu_session_config_t *configs, int max_len);
#endif /* PDU_SESSION_H_ */
+32 -4
View File
@@ -22,6 +22,7 @@
*/
#include <ctype.h>
#include "common/platform_constants.h"
#include <openair3/UICC/usim_interface.h>
#include <openair3/NAS/COMMON/milenage.h>
extern uint16_t NB_UE_INST;
@@ -76,10 +77,7 @@ uicc_t *init_uicc(char *sectionName) {
// key, OPc, sqn, amf don't need to be read from the true USIM
int ret = config_get(config_get_if(), uicc_params, sizeofArray(uicc_params), sectionName);
AssertFatal(ret >= 0, "configuration couldn't be performed for uicc name: %s", sectionName);
LOG_I(SIM,
"UICC simulation: IMSI=%s, IMEISV=%s, Ki=%s, OPc=%s, DNN=%s, SST=0x%02x, SD=0x%06x\n",
uicc->imsiStr, uicc->imeisvStr, uicc->keyStr, uicc->opcStr,
uicc->dnnStr, uicc->nssai_sst, uicc->nssai_sd);
LOG_I(SIM, "UICC simulation: IMSI=%s, IMEISV=%s, Ki=%s, OPc=%s\n", uicc->imsiStr, uicc->imeisvStr, uicc->keyStr, uicc->opcStr);
to_hex(uicc->keyStr,uicc->key, sizeof(uicc->key) );
to_hex(uicc->opcStr,uicc->opc, sizeof(uicc->opc) );
to_hex(uicc->sqnStr,uicc->sqn, sizeof(uicc->sqn) );
@@ -112,6 +110,36 @@ uicc_t * checkUicc(int Mod_id) {
char uiccName[64];
sprintf(uiccName,"uicc%d", Mod_id);
uiccArray[Mod_id]=(void*)init_uicc(uiccName);
uicc_t *uicc = uiccArray[Mod_id];
uicc->n_pdu_sessions = get_pdu_session_configs(uiccName, uicc->pdu_sessions, sizeof(uicc->pdu_sessions));
if (uicc->n_pdu_sessions > 0) {
LOG_I(SIM, "overriding potential %s.dnn/nssai_sst/nssai_sd from %s.pdu_sessions\n", uiccName, uiccName);
} else if (uicc->n_pdu_sessions < 0) {
// we could not load from "new" pdu_sessions list, so read from "legacy"
// config
LOG_W(SIM,
"loading PDU session parameters from legacy UICC configuration. Please update to use %s.pdu_sessions instead to make this warning disappear\n",
uiccName);
sleep(3);
uicc->n_pdu_sessions = 1;
pdu_session_config_t *pdu = &uicc->pdu_sessions[0];
AssertFatal(uicc->dnnStr != NULL, "no default DNN, cannot create\n");
pdu->id = DEFAULT_NOS1_PDU_ID; // any default would do
pdu->dnn = strdup(uicc->dnnStr);
pdu->nssai.sst = uicc->nssai_sst;
pdu->nssai.sd = uicc->nssai_sd;
pdu->type = 1; /* = PDU_SESSION_TYPE_IPV4 */
} // else: uicc->n_pdu_sessions == 0 => don't request a PDU session
for (int i = 0; i < uicc->n_pdu_sessions; ++i) {
const pdu_session_config_t *pdu = &uicc->pdu_sessions[i];
LOG_I(SIM,
"will request PDU session ID %d, type %d, DNN %s, NSSAI %d.%6x\n",
pdu->id,
pdu->type,
pdu->dnn,
pdu->nssai.sst,
pdu->nssai.sd);
}
}
return (uicc_t*) uiccArray[Mod_id];
}
+3
View File
@@ -34,6 +34,7 @@
#include <common/utils/load_module_shlib.h>
#include <common/config/config_userapi.h>
#include "common_lib.h"
#include "pdu_session.h"
/* 3GPP glossary
RES RESponse
@@ -53,6 +54,8 @@ typedef struct {
char *dnnStr;
int nssai_sst;
int nssai_sd;
pdu_session_config_t pdu_sessions[256];
int n_pdu_sessions;
uint8_t key[16];
uint8_t opc[16];
uint8_t amf[2];