Files
openairinterface5g/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp
T
Guido Casati a937eaec23 Rework RRCReconfiguration handling in RRC/ASN1
according to TS 38.331, RRCReconfiguration messages can be carried
in a container by different RRC messages, e.g. HandoverPreparationInformation,
HandoverCommand, RRCResume etc.. therefore before the introduction of new
RRCReconfiguration messages, e.g. for handover, a new design seems to be necessary
in order to improve modularity and maintainability of the code.

The goal of this commit is to make the generation of RRCReconfiguration
messages more modular by (1) preparing the RRCReconfiguration parameters
data in RRC (2) pass it to ASN1 for IEs allocation (3) encode to buffer

The following changes are introduced:
(1) introduce struct nr_rrc_reconfig_param_t to store the RRC parameters relevant
    to encode the RRCReconfiguration IEs
(2) add RRC function get_RRCReconfiguration_params to fetch nr_rrc_reconfig_param_t
    data from the UE context and
(3) pass it to the ASN1 encoder, e.g. do_RRCReconfiguration
(4) add a function build_RRCReconfiguration_IEs to allocate memory and build the
    ASN1 NR_RRCReconfiguration_IEs_t and
(5) adopt it in do_RRCReconfiguration
(4) add free_RRCReconfiguration_params for memory management of nr_rrc_reconfig_param_t data
(6) add test for rrc_reconfiguration

get_RRCReconfiguration_params:

This function prepares RRCReconfigurationParams for RRC encoding.

Motivation of this change: depending on the RRCReconfiguration
message to be encoded, the ownership of ASN1 memory allocation
should belong to the ASN1 layer, therefore this function is
preparing the nr_rrc_reconfig_param_t data to pass to the
ASN1 encoder to build the ASN1 message and encode to buffer

The function is preparing the params for the IEs that are
either mandatory or shared among different RRC messages.
Specific fields that depend on the message to be encoded are then
added afterwards in the caller. The input param to indicate
re-establishment has been split between SRBs and DRBs, since
depending on the scenario the PDCP re-establishment can vary.
This will be addressed in a later commit.

This function is also handling xid.

build_RRCReconfiguration_IE:

The long term goal is to transfer ownership of memory allocation in ASN1 encoding to
build_RRCReconfiguration_IE, then by calling ASN_STRUCT_FREE_CONTENTS_ONLY
on dl_dcch_msg, all IEs allocated in the context are freed after encoding to buffer.
In the long term, createDRBlist, createSRBlist can also be brought into the context
of build_RRCReconfiguration_IEs and free the ASN1 structure after encoding.
This improves maintability and helps preventing memory leaks.

Currently, what is not allocated in the context, is nulled and freed outside.

free_RRCReconfiguration_params:

this function frees memory allocated to build the nr_rrc_reconfig_param_t data,
including the NR_DRB_ToAddModList_t and NR_SRB_ToAddModList_t. The function
freeDRBlist has been removed since no longer necessary.

dedicated_NAS_msg_list:

dedicated_NAS_msg_list handling has also been refactored, by:

(1) fetch the NAS PDUs from the UE context in get_RRCReconfiguration_params,
which translates to (2) passing an array of dedicatedNAS-MessageList + size
to the ASN1 encoding function where (3) the ASN1 encoding logic for the
dedicated_NAS_msg_list IE has been moved

Note, 3GPP TS 38.331:
dedicatedNAS-MessageList: SEQUENCE (SIZE(1..maxDRB)) OF DedicatedNAS-Message
2025-06-09 20:43:04 +02:00

165 lines
5.0 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 <gtest/gtest.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
#include "common/ran_context.h"
#include <stdbool.h>
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include "NR_DRB-ToAddMod.h"
#include "NR_DRB-ToAddModList.h"
#include "NR_SRB-ToAddModList.h"
#include "ds/byte_array.h"
RAN_CONTEXT_t RC;
#ifdef __cplusplus
}
#endif
TEST(nr_asn1, rrc_reject)
{
unsigned char buf[1000];
EXPECT_GT(do_RRCReject(buf), 0);
}
TEST(nr_asn1, sa_capability_enquiry)
{
unsigned char buf[1000];
EXPECT_GT(do_NR_SA_UECapabilityEnquiry(buf, 0), 0);
}
TEST(nr_asn1, rrc_reconfiguration_complete_for_nsa)
{
unsigned char buf[1000];
EXPECT_GT(do_NR_RRCReconfigurationComplete_for_nsa(buf, 1000, 0), 0);
}
TEST(nr_asn1, ul_information_transfer)
{
unsigned char *buf = NULL;
unsigned char pdu[20] = {0};
EXPECT_GT(do_NR_ULInformationTransfer(&buf, 20, pdu), 0);
EXPECT_NE(buf, nullptr);
free(buf);
}
TEST(nr_asn1, rrc_reestablishment_request)
{
unsigned char buf[1000];
const uint16_t c_rnti = 1;
const uint32_t cell_id = 177;
EXPECT_GT(do_RRCReestablishmentRequest(buf, NR_ReestablishmentCause_reconfigurationFailure, cell_id, c_rnti), 0);
}
TEST(nr_asn1, rrc_reestablishment)
{
unsigned char buf[1000];
const uint8_t nh_ncc = 0;
EXPECT_GT(do_RRCReestablishment(nh_ncc, buf, 1000, 0), 0);
}
TEST(nr_asn1, paging)
{
unsigned char buf[1000];
EXPECT_GT(do_NR_Paging(0, buf, 0), 0);
}
void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params)
{
ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, params.meas_config);
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, params.drb_release_list);
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, params.drb_config_list);
ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, params.srb_config_list);
ASN_STRUCT_FREE(asn_DEF_NR_SecurityConfig, params.security_config);
for (int i = 0; i < params.num_nas_msg; i++)
FREE_AND_ZERO_BYTE_ARRAY(params.dedicated_NAS_msg_list[i]);
}
TEST(nr_asn1, rrc_reconfiguration)
{
// SRB Configuration
NR_SRB_ToAddModList_t *srb_config_list = (NR_SRB_ToAddModList_t *)calloc_or_fail(1, sizeof(*srb_config_list));
for (int i = 0; i < 4; i++) {
if (i == 1 || i == 2) {
NR_SRB_ToAddMod_t *srb = (NR_SRB_ToAddMod_t *)calloc_or_fail(1, sizeof(*srb));
ASN_SEQUENCE_ADD(&srb_config_list->list, srb);
srb->srb_Identity = i;
if (i == 1 || i == 2) {
srb->reestablishPDCP = (long *)calloc_or_fail(1, sizeof(*srb->reestablishPDCP));
*srb->reestablishPDCP = 0;
}
}
}
// DRB Configuration
NR_DRB_ToAddModList_t *drb_config_list = (NR_DRB_ToAddModList_t *)calloc_or_fail(1, sizeof(*drb_config_list));
for (int i = 0; i < 32; i++) {
if (i == 1 || i == 2) {
NR_DRB_ToAddMod_t *drb = (NR_DRB_ToAddMod_t *)calloc_or_fail(1, sizeof(*drb));
ASN_SEQUENCE_ADD(&drb_config_list->list, drb);
drb->drb_Identity = i;
drb->reestablishPDCP = (long *)calloc_or_fail(1, sizeof(*drb->reestablishPDCP));
*drb->reestablishPDCP = 0;
}
}
// nr_rrc_reconfig_param_t setup
nr_rrc_reconfig_param_t params = {};
params.srb_config_list = srb_config_list;
params.drb_config_list = drb_config_list;
params.num_nas_msg = 2;
params.masterKeyUpdate = false;
params.nextHopChainingCount = 1;
byte_array_t nas_pdu_1;
nas_pdu_1.buf = (uint8_t *)malloc_or_fail(4);
memcpy(nas_pdu_1.buf, "NAS1", 4);
nas_pdu_1.len = 4;
byte_array_t nas_pdu_2;
nas_pdu_2.buf = (uint8_t *)malloc_or_fail(4);
memcpy(nas_pdu_2.buf, "NAS2", 4);
nas_pdu_2.len = 4;
params.dedicated_NAS_msg_list[0] = nas_pdu_1;
params.dedicated_NAS_msg_list[1] = nas_pdu_2;
byte_array_t msg = do_RRCReconfiguration(&params);
EXPECT_GT(msg.len, 0);
EXPECT_NE(msg.buf, nullptr);
LOG_D(NR_RRC, "RRCReconfiguration: Encoded (%ld bytes)\n", msg.len);
free_byte_array(msg);
free_RRCReconfiguration_params(params);
}
int main(int argc, char **argv)
{
logInit();
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}