Commit 0ceb5fd3 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/ue_nas_simulator' into integration_2026_w13 (!3973)

Introduce UE NAS Simulator

This MR introduces a simple standalone tester for 5G UE NAS signaling and NGAP
messages. It connects to the AMF to perform NGAP and NAS encoding/decoding and
validates the UE Registration and PDU Session Establishment processes without
the overhead of a full Radio Access Network (PHY/MAC/RLC).

The motivation for this tester is as follows,
- This tester is a lightweight, deterministic tool to test the UE NAS layer
directly.
- Developers can easily inject specific NAS messages depending on the use-case.
- Developers can validate custom NAS/NGAP messages without the need to implement
complete RRC/MAC etc procedures.

Start the 5G Core network to test the UE NAS simulator. The compiling and
testing procedure is described below.
To compile:
mkdir build && cd build && cmake .. -GNinja && ninja nr-ue-nas-simulator-test

To run:
  LD_LIBRARY_PATH=. ./tests/nr-ue-nas-simulator/nr-ue-nas-simulator-test -O ../tests/nr-ue-nas-simulator/test.conf
parents 8b9eada3 03ba636b
......@@ -124,6 +124,7 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs.
- Component tests are under `tests/`. Currently, the following component tests are supported
- A simple CU-UP tester, see the corresponding [README.md](../tests/nr-cuup/README.md).
- A CU-NRPPA tester, see the corresponding [README.md](../tests/nr-cu-nrppa/README.md).
- A UE NAS tester, see the corresponding [README.md](../tests/nr-ue-nas-simulator/README.md).
- [TESTBenches.md](./TESTBenches.md) lists the CI setup and links to pipelines
- The CI setup uses a [custom framework](../ci-scripts/README.md) to run
end-to-end tests.
......
......@@ -78,6 +78,12 @@
static nr_ue_nas_t nr_ue_nas[MAX_NUM_NR_UE_INST] = {0};
nr_ue_nas_t *get_nr_ue_nas_info(uint8_t ue_inst)
{
AssertFatal(ue_inst >= 0 && ue_inst < MAX_NUM_NR_UE_INST, "Invalid UE instance\n");
return &nr_ue_nas[ue_inst];
}
#define FOREACH_STATE(TYPE_DEF) \
TYPE_DEF(NAS_SECURITY_NO_SECURITY_CONTEXT, 0) \
TYPE_DEF(NAS_SECURITY_UNPROTECTED, 1) \
......@@ -1166,6 +1172,10 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
security_header_len
+ mm_msg_encode(plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len);
if (rr.nas_data) {
free(rr.nas_data);
}
/* ciphering */
uint8_t buf[initialNasMsg->length - 7];
stream_cipher.context = nas->security_container->ciphering_context;
......
......@@ -113,5 +113,6 @@ 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, const pdu_session_config_t *pdu);
nr_ue_nas_t *get_nr_ue_nas_info(uint8_t ue_inst);
#endif /* __NR_NAS_MSG_SIM_H__*/
add_subdirectory(nr-cuup)
add_subdirectory(nr-cu-nrppa)
add_subdirectory(nr-ue-nas-simulator)
add_executable(nr-ue-nas-simulator-test nr-ue-nas-simulator.c
${OPENAIR2_DIR}/GNB_APP/gnb_config_common.c
${OPENAIR2_DIR}/GNB_APP/gnb_config_ng.c)
target_link_libraries(nr-ue-nas-simulator-test PRIVATE nr_nas nr_common lib_uicc usim_lib)
target_link_libraries(nr-ue-nas-simulator-test PRIVATE
CONFIG_LIB ITTI SCTP_CLIENT
f1ap ngap SECURITY GTPV1U
UTIL softmodem_common)
target_link_libraries(nr-ue-nas-simulator-test PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
add_dependencies(nr-ue-nas-simulator-test params_libconfig)
This is a simple standalone tester for 5G UE NAS signaling and NGAP messages. It connects to the AMF to perform NGAP and NAS encoding/decoding and validates the UE Registration and PDU Session Establishment processes without the overhead of a full Radio Access Network (PHY/MAC/RLC).
[[_TOC_]]
# Motivation
- This tester is a lightweight, deterministic tool to **test the UE NAS layer directly**.
- Developers can easily inject specific NAS messages depending on the use-case.
- Developers can validate custom NAS/NGAP messages without the need to implement complete RRC/MAC etc procedures.
# Overview
From a schematic point of view, the tester and Core Network interaction looks like this:
```
+-------+
| AMF |
+-------+
|
NGAP/NAS | (N1/N2)
|
+-------+
|tester | (nr-ue-nas-simulator-test)
+-------+
```
The tester is designed to validate the integration of NAS and NGAP messages required for a 5G Standalone (SA) UE to attach to the network. It acts as a simulated gNB and a UE, bridging NAS messages directly into NGAP payloads and connecting to the 5G Core Network's AMF.
The following messages are integrated and tested:
* **NGAP:** NG Setup Request/Response, Initial UE Message, Downlink NAS Transport, Uplink NAS Transport, Initial Context Setup Request/Response, PDU Session Resource Setup Request/Response, UE Context Release Command/Complete.
* **NAS (5GMM/5GSM):** Registration Request/Accept/Complete, Authentication Request/Response, Security Mode Command/Complete, PDU Session Establishment Request/Accept, Deregistration Request/Accept.
* **RRC (Custom):** Forwards the uplink/downlink NAS messages directly between UE and AMF.
A test scenario is fixed to these steps:
1. The 5G Core Network is deployed via Docker.
2. The tester connects to the AMF and establishes the NGAP connection (NG Setup).
3. The tester automatically triggers an Initial UE Registration Request.
4. Authentication and NAS Security Mode procedures are completed.
5. The tester requests and successfully establishes an IPv4 PDU Session.
6. The tester finally initiates deregistration request and exits succesfully.
# Usage
To run this test, you need to set up the Core Network and build the tester.
**1. Core Network Deployment**
Pull the required Docker images for the OAI 5G Core:
docker pull oaisoftwarealliance/ims:latest
docker pull oaisoftwarealliance/oai-amf:develop
docker pull oaisoftwarealliance/oai-nrf:develop
docker pull oaisoftwarealliance/oai-smf:develop
docker pull oaisoftwarealliance/oai-udr:develop
docker pull oaisoftwarealliance/oai-upf:develop
docker pull oaisoftwarealliance/oai-udm:develop
docker pull oaisoftwarealliance/oai-ausf:develop
Deploy the network using the docker compose file:
cd doc/tutorial_resources/oai-cn5g
docker compose -f docker-compose.yaml up -d
At the end of all experiments, you can also undeploy the network with:
docker compose -f docker-compose.yaml down -t 0
**2. Building the Tester**
You can build the tester as follows:
cd ~/openairinterface5g
mkdir build && cd build && cmake .. -GNinja && ninja nr-ue-nas-simulator-test
**3. Running the Tester**
Start the tester with the dedicated configuration file:
openairinterface5g/build$ LD_LIBRARY_PATH=. ./tests/nr-ue-nas-simulator/nr-ue-nas-simulator-test -O ../tests/nr-ue-nas-simulator/test.conf
# Limitations
- The tester is limited to a fixed flow: Initial Attach -> PDU Session -> Deregistration.
- The tester doesnt create a GTP tunnel after PDU session and uses a harcoded teid.
# Future Enhancements
- A real GTP tunnel can be created to test various data related functionalities like QoS.
- Simulate the actual UE RRC layer, i.e., forwarding the CellGroupConfig, have the UE apply that (without actually using it).
- Make it scriptable to test custom message implementations.
/*
* 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 "executables/softmodem-common.h"
#include "common/utils/ocp_itti/intertask_interface.h"
#include "common/ran_context.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "openair2/GNB_APP/gnb_config_common.h"
#include "openair2/GNB_APP/gnb_config_ng.h"
#include "openair2/GNB_APP/gnb_paramdef.h"
#include "openair3/SCTP/sctp_default_values.h"
#include "openair3/NAS/NR_UE/nr_nas_msg.h"
#include "executables/nr-uesoftmodem.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
RAN_CONTEXT_t RC;
THREAD_STRUCT thread_struct;
uint64_t downlink_frequency[MAX_NUM_CCs][4];
int64_t uplink_frequency_offset[MAX_NUM_CCs][4];
int oai_exit = 0;
int gnb_id = 0;
uint32_t tac = 1;
uint16_t mcc = 1;
uint16_t mnc = 1;
uint8_t mnc_len = 2;
char *gnb_ipv4_address_for_NGU = NULL;
int NB_UE_INST = 1;
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
{
LOG_E(GNB_APP, "error at %s:%d:%s: %s\n", file, line, function, s);
abort();
}
nfapi_mode_t nfapi_mod = -1;
void nfapi_setmode(nfapi_mode_t nfapi_mode)
{
nfapi_mod = nfapi_mode;
}
nfapi_mode_t nfapi_getmode(void)
{
return nfapi_mod;
}
ngran_node_t get_node_type()
{
return ngran_gNB_CUUP;
}
nrUE_params_t *get_nrUE_params(void)
{
static nrUE_params_t params = {0};
params.extra_pdu_id = -1;
return &params;
}
void create_ue_ip_if(void)
{
}
void create_ue_eth_if(void)
{
}
void set_qfi(void)
{
}
int nr_rlc_get_available_tx_space(const rnti_t rntiP, const logical_chan_id_t channel_idP)
{
abort();
return 0;
}
configmodule_interface_t *uniqCfg = NULL;
// Emulate registration request to register UE in the AMF (required for positioning)
void send_initial_ue_message(instance_t instance)
{
MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_NAS_FIRST_REQ);
NGAP_NAS_FIRST_REQ(msg_p).gNB_ue_ngap_id = 1; // Simulated UE ID
NGAP_NAS_FIRST_REQ(msg_p).plmn.mcc = mcc;
NGAP_NAS_FIRST_REQ(msg_p).plmn.mnc = mnc;
NGAP_NAS_FIRST_REQ(msg_p).plmn.mnc_digit_length = mnc_len;
NGAP_NAS_FIRST_REQ(msg_p).nr_cell_id = gnb_id;
NGAP_NAS_FIRST_REQ(msg_p).establishment_cause = NGAP_RRC_CAUSE_MO_SIGNALLING;
as_nas_info_t initialNasMsg = {0};
nr_ue_nas_t *nr_ue_nas = get_ue_nas_info(0);
generateRegistrationRequest(&initialNasMsg, nr_ue_nas, false);
NGAP_NAS_FIRST_REQ(msg_p).nas_pdu.buf = initialNasMsg.nas_data;
NGAP_NAS_FIRST_REQ(msg_p).nas_pdu.len = initialNasMsg.length;
NGAP_NAS_FIRST_REQ(msg_p).ue_identity.presenceMask = 0;
itti_send_msg_to_task(TASK_NGAP, instance, msg_p);
}
void send_uplink_nas_to_amf(instance_t instance, as_nas_info_t *nas_msg)
{
if (nas_msg->length > 0 && nas_msg->nas_data != NULL) {
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, instance, NGAP_UPLINK_NAS);
NGAP_UPLINK_NAS(msg).gNB_ue_ngap_id = 1; // Simulated UE ID
NGAP_UPLINK_NAS(msg).nas_pdu.buf = nas_msg->nas_data;
NGAP_UPLINK_NAS(msg).nas_pdu.len = nas_msg->length;
NGAP_UPLINK_NAS(msg).plmn.mcc = mcc;
NGAP_UPLINK_NAS(msg).plmn.mnc = mnc;
NGAP_UPLINK_NAS(msg).plmn.mnc_digit_length = mnc_len;
NGAP_UPLINK_NAS(msg).nr_cell_id = gnb_id;
NGAP_UPLINK_NAS(msg).tac = tac;
itti_send_msg_to_task(TASK_NGAP, instance, msg);
}
}
void *rrc_ue_task_local(void *args_p)
{
MessageDef *msg_p;
instance_t instance;
int result;
itti_mark_task_ready(TASK_RRC_NRUE);
LOG_I(NR_RRC, "Entering RRC UE task (TASK_RRC_NRUE)\n");
while (1) {
itti_receive_msg(TASK_RRC_NRUE, &msg_p);
instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(NR_RRC, " *** Exiting RRC UE thread\n");
itti_exit_task();
break;
case NAS_UPLINK_DATA_REQ:
LOG_I(NR_RRC, "Received NAS_UPLINK_DATA_REQ from NAS Library (via RRC UE Task)\n");
as_nas_info_t nas_msg;
nas_msg.nas_data = NAS_UPLINK_DATA_REQ(msg_p).nasMsg.nas_data;
nas_msg.length = NAS_UPLINK_DATA_REQ(msg_p).nasMsg.length;
send_uplink_nas_to_amf(instance, &nas_msg);
break;
case NAS_5GMM_IND:
LOG_I(NR_RRC, "Received NAS_5GMM_IND (ignored for nr_ue_nas_simulator test)\n");
break;
case NAS_KENB_REFRESH_REQ:
LOG_I(NR_RRC, "Received NAS_KENB_REFRESH_REQ (ignored for nr_ue_nas_simulator test)\n");
break;
case NAS_DETACH_REQ:
LOG_I(NR_RRC, "Received NAS_DETACH_REQ (ignored for nr_ue_nas_simulator test)\n");
break;
default:
LOG_E(NR_RRC, "RRC UE Task received unexpected message %s\n", ITTI_MSG_NAME(msg_p));
break;
}
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
msg_p = NULL;
}
return NULL;
}
void *gNB_app_task(void *args_p)
{
MessageDef *msg_p = NULL;
const char *msg_name = NULL;
instance_t instance;
int result;
/* for no gcc warnings */
(void)instance;
itti_mark_task_ready(TASK_GNB_APP);
do {
// Wait for a message
itti_receive_msg(TASK_GNB_APP, &msg_p);
msg_name = ITTI_MSG_NAME(msg_p);
instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(GNB_APP, " *** Exiting GNB_APP thread\n");
itti_exit_task();
break;
case NGAP_REGISTER_GNB_CNF:
LOG_I(GNB_APP, "[gNB %ld] Received %s: associated AMF %d\n", instance, msg_name, NGAP_REGISTER_GNB_CNF(msg_p).nb_amf);
LOG_I(GNB_APP, "Triggering NAS Registration sequence\n");
send_initial_ue_message(instance);
break;
default:
LOG_E(GNB_APP, "Received unexpected message %s\n", msg_name);
break;
}
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
} while (1);
return NULL;
}
// Forward NAS payload from the AMF directly to the NAS NRUE Task
void forward_downlink_nas_to_ue(uint8_t *pdu_buf, uint32_t pdu_len)
{
if (pdu_len > 0 && pdu_buf != NULL) {
MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NAS_DOWNLINK_DATA_IND);
NAS_DOWNLINK_DATA_IND(msg_p).UEid = 0;
NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length = pdu_len;
NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.nas_data = malloc_or_fail(pdu_len);
memcpy(NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.nas_data, pdu_buf, pdu_len);
free(pdu_buf);
LOG_I(NR_RRC, "Forwarding Downlink NAS message to real NAS Task (Length: %d)\n", pdu_len);
itti_send_msg_to_task(TASK_NAS_NRUE, 0, msg_p);
}
}
void *rrc_gnb_task(void *args_p)
{
MessageDef *msg_p;
MessageDef *msg_p_resp;
instance_t instance;
int result;
itti_mark_task_ready(TASK_RRC_GNB);
LOG_I(NR_RRC, "Entering main loop of NR_RRC message task\n");
while (1) {
// Wait for a message
itti_receive_msg(TASK_RRC_GNB, &msg_p);
const char *msg_name_p = ITTI_MSG_NAME(msg_p);
instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p);
LOG_D(NR_RRC,
"RRC GNB Task Received %s for instance %ld from task %s\n",
ITTI_MSG_NAME(msg_p),
ITTI_MSG_DESTINATION_INSTANCE(msg_p),
ITTI_MSG_ORIGIN_NAME(msg_p));
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n");
itti_exit_task();
break;
case NGAP_DOWNLINK_NAS:
LOG_I(NR_RRC, "Received NGAP_DOWNLINK_NAS\n");
forward_downlink_nas_to_ue(NGAP_DOWNLINK_NAS(msg_p).nas_pdu.buf, NGAP_DOWNLINK_NAS(msg_p).nas_pdu.len);
break;
case NGAP_INITIAL_CONTEXT_SETUP_REQ:
LOG_I(NR_RRC, "Received NGAP_INITIAL_CONTEXT_SETUP_REQ\n");
if (NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.len > 0) {
LOG_I(NR_RRC, "Processing NAS PDU in Initial Context Setup\n");
forward_downlink_nas_to_ue(NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.buf,
NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.len);
}
LOG_I(NR_RRC, "Sending NGAP_INITIAL_CONTEXT_SETUP_RESP\n");
msg_p_resp = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_INITIAL_CONTEXT_SETUP_RESP);
NGAP_INITIAL_CONTEXT_SETUP_RESP(msg_p_resp).gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).gNB_ue_ngap_id;
itti_send_msg_to_task(TASK_NGAP, instance, msg_p_resp);
break;
case NAS_UPLINK_DATA_REQ:
LOG_I(NR_RRC, "Received NAS_UPLINK_DATA_REQ from NAS Library\n");
as_nas_info_t nas_msg;
nas_msg.nas_data = NAS_UPLINK_DATA_REQ(msg_p).nasMsg.nas_data;
nas_msg.length = NAS_UPLINK_DATA_REQ(msg_p).nasMsg.length;
send_uplink_nas_to_amf(instance, &nas_msg);
break;
case NGAP_PDUSESSION_SETUP_REQ:
LOG_I(NR_RRC, "Received NGAP_PDUSESSION_SETUP_REQ\n");
for (int i = 0; i < NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup; i++) {
if (NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession[i].nas_pdu.len > 0) {
forward_downlink_nas_to_ue(NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession[i].nas_pdu.buf,
NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession[i].nas_pdu.len);
}
}
msg_p_resp = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_RESP);
NGAP_PDUSESSION_SETUP_RESP(msg_p_resp).gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id;
NGAP_PDUSESSION_SETUP_RESP(msg_p_resp).nb_of_pdusessions = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup;
for (int i = 0; i < NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup; i++) {
pdusession_setup_t *resp_item = &NGAP_PDUSESSION_SETUP_RESP(msg_p_resp).pdusessions[i];
pdusession_resource_item_t *req_item = &NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession[i];
resp_item->pdusession_id = req_item->pdusession_id;
resp_item->pdu_session_type = req_item->pdusessionTransfer.pdu_session_type;
resp_item->n3_outgoing.teid = 0x00000001 + i;
struct in_addr addr;
inet_pton(AF_INET, gnb_ipv4_address_for_NGU, &addr);
resp_item->n3_outgoing.addr.length = 4;
memcpy(resp_item->n3_outgoing.addr.buffer, &addr.s_addr, resp_item->n3_outgoing.addr.length);
resp_item->nb_of_qos_flow = req_item->pdusessionTransfer.nb_qos;
DevAssert(resp_item->nb_of_qos_flow < MAX_QOS_FLOWS);
for (int q = 0; q < resp_item->nb_of_qos_flow; q++) {
resp_item->associated_qos_flows[q].qfi = req_item->pdusessionTransfer.qos[q].qfi;
resp_item->associated_qos_flows[q].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
}
}
LOG_I(NR_RRC, "Sending NGAP_PDUSESSION_SETUP_RESP\n");
itti_send_msg_to_task(TASK_NGAP, instance, msg_p_resp);
// Initiate UE Deregistration
sleep(1);
MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_DEREGISTRATION_REQ);
NAS_DEREGISTRATION_REQ(msg).cause = AS_DETACH;
itti_send_msg_to_task(TASK_NAS_NRUE, 0, msg);
break;
case NGAP_UE_CONTEXT_RELEASE_COMMAND:
LOG_I(NR_RRC, "Received NGAP_UE_CONTEXT_RELEASE_COMMAND\n");
msg_p_resp = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE);
NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg_p_resp).gNB_ue_ngap_id = NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id;
LOG_I(NR_RRC, "Sending NGAP_UE_CONTEXT_RELEASE_COMPLETE\n");
itti_send_msg_to_task(TASK_NGAP, instance, msg_p_resp);
LOG_I(NR_RRC, "Simulator flow finished successfully!\n");
exit(EXIT_SUCCESS);
break;
default:
LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p);
break;
}
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
msg_p = NULL;
}
}
int main(int argc, char **argv)
{
// load the config file
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == NULL) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
logInit();
nas_init_nrue(NB_UE_INST);
set_softmodem_sighandler();
// Initialize ITTI tasks
itti_init(TASK_MAX, tasks_info);
int rc;
rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
AssertFatal(rc >= 0, "Create task for SCTP failed\n");
rc = itti_create_task(TASK_NGAP, ngap_gNB_task, NULL);
AssertFatal(rc >= 0, "Create task for NGAP failed\n");
rc = itti_create_task(TASK_RRC_GNB, rrc_gnb_task, NULL);
AssertFatal(rc >= 0, "Create task for RRC failed\n");
rc = itti_create_task(TASK_GNB_APP, gNB_app_task, NULL);
AssertFatal(rc >= 0, "Create task for gNB_app failed\n");
rc = itti_create_task(TASK_NAS_NRUE, nas_nrue_task, NULL);
AssertFatal(rc >= 0, "Create task for nas_nrue_task failed\n");
rc = itti_create_task(TASK_RRC_NRUE, rrc_ue_task_local, NULL);
AssertFatal(rc >= 0, "Create task for RRC_NRUE failed\n");
MessageDef *msg_p;
msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, NGAP_REGISTER_GNB_REQ);
RCconfig_NR_NG(msg_p, 0);
gnb_id = NGAP_REGISTER_GNB_REQ(msg_p).gNB_id;
tac = NGAP_REGISTER_GNB_REQ(msg_p).tac;
mcc = NGAP_REGISTER_GNB_REQ(msg_p).plmn[0].plmn.mcc;
mnc = NGAP_REGISTER_GNB_REQ(msg_p).plmn[0].plmn.mnc;
mnc_len = NGAP_REGISTER_GNB_REQ(msg_p).plmn[0].plmn.mnc_digit_length;
gnb_ipv4_address_for_NGU = NGAP_REGISTER_GNB_REQ(msg_p).gnb_ip_address.ipv4_address;
LOG_I(GNB_APP, "Sending NGAP_REGISTER_GNB_REQ to TASK_NGAP\n");
itti_send_msg_to_task(TASK_NGAP, 0, msg_p);
printf("TYPE <CTRL-C> TO TERMINATE\n");
itti_wait_tasks_end(NULL);
logClean();
printf("Bye.\n");
return 0;
}
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
nr_cellid = 12345678L;
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ({ ipv4 = "192.168.70.132"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
uicc0 = {
imsi = "001010000000001";
key = "fec86ba6eb707ed08905757b1bb44b8f";
opc = "C42449363BBAD02B66D16BC975D77CC1";
pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; });
}
log_config :
{
global_log_level ="info";
hw_log_level ="info";
phy_log_level ="info";
mac_log_level ="info";
rlc_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
ngap_log_level ="debug";
f1ap_log_level ="debug";
};
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