Commit 7a7e5749 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/e1ap-msg-encdec-tests' into integration_2024_w48 (!2985)

E1AP Bearer Context Setup encoding/decoding library and unit tests

E1AP encoding/decoding library (TS 38.463) and unit test for:
- E1 Bearer Context Setup Request
- E1 Bearer Context Setup Response
parents bbc35c7a 927b1577
...@@ -27,19 +27,19 @@ ...@@ -27,19 +27,19 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/sctp.h> #include <netinet/sctp.h>
#include "common/ngran_types.h" #include "common/ngran_types.h"
#include "f1ap_messages_types.h" #include "common/platform_types.h"
#include "ngap_messages_types.h" #include "common/5g_platform_types.h"
/* Definitions according to 3GPP TS 38.463 */
#define E1AP_MAX_NUM_TRANSAC_IDS 4 #define E1AP_MAX_NUM_TRANSAC_IDS 4
#define E1AP_MAX_NUM_PLMNS 4 #define E1AP_MAX_NUM_PLMNS 4
#define E1AP_MAX_NUM_SLICES 1024 #define E1AP_MAX_NUM_SLICES 1024
#define E1AP_MAX_NUM_CELL_GROUPS 4 #define E1AP_MAX_NUM_CELL_GROUPS 4
#define E1AP_MAX_NUM_QOS_FLOWS 4 #define E1AP_MAX_NUM_QOS_FLOWS 64
#define E1AP_MAX_NUM_NGRAN_DRB 4
#define E1AP_MAX_NUM_PDU_SESSIONS 4 #define E1AP_MAX_NUM_PDU_SESSIONS 4
#define E1AP_MAX_NUM_DRBS 4 #define E1AP_MAX_NUM_DRBS 32
#define E1AP_MAX_NUM_DRBS 4
#define E1AP_MAX_NUM_UP_PARAM 4 #define E1AP_MAX_NUM_UP_PARAM 4
#define E1AP_SECURITY_KEY_SIZE 16 // keys have 128 bits length
#define E1AP_REGISTER_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_register_req #define E1AP_REGISTER_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_register_req
#define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req #define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req
...@@ -61,6 +61,17 @@ typedef enum BEARER_CONTEXT_STATUS_e { ...@@ -61,6 +61,17 @@ typedef enum BEARER_CONTEXT_STATUS_e {
BEARER_RESUME, BEARER_RESUME,
} BEARER_CONTEXT_STATUS_t; } BEARER_CONTEXT_STATUS_t;
typedef enum activity_notification_level_e {
ANL_DRB = 0,
ANL_PDU_SESSION,
ANL_UE,
} activity_notification_level_t;
typedef enum cell_group_id_e {
MCG = 0,
SCG,
} cell_group_id_t;
typedef struct PLMN_ID_s { typedef struct PLMN_ID_s {
int mcc; int mcc;
int mnc; int mnc;
...@@ -107,10 +118,6 @@ typedef struct e1ap_setup_fail_s { ...@@ -107,10 +118,6 @@ typedef struct e1ap_setup_fail_s {
long transac_id; long transac_id;
} e1ap_setup_fail_t; } e1ap_setup_fail_t;
typedef struct cell_group_s {
long id;
} cell_group_t;
typedef struct up_params_s { typedef struct up_params_s {
in_addr_t tlAddress; in_addr_t tlAddress;
long teId; long teId;
...@@ -144,22 +151,27 @@ typedef struct drb_to_setup_s { ...@@ -144,22 +151,27 @@ typedef struct drb_to_setup_s {
in_addr_t tlAddress; in_addr_t tlAddress;
long teId; long teId;
int numCellGroups; int numCellGroups;
cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; cell_group_id_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS];
} drb_to_setup_t; } drb_to_setup_t;
typedef struct qos_characteristics_s { typedef struct qos_characteristics_s {
union { union {
struct { struct {
long fiveqi; uint16_t fiveqi;
long qos_priority_level; uint8_t qos_priority_level;
} non_dynamic; } non_dynamic;
struct { struct {
long fiveqi; // -1 -> optional // Range 5QI [0 - 255]
long qos_priority_level; uint16_t fiveqi;
long packet_delay_budget; /* Range [0 - 15]
15 = "no priority," 1-14 = decreasing priority (1 highest), 0 = logical error if received */
uint8_t qos_priority_level;
// Range [0, 1023]: Upper bound for packet delay in 0.5ms units
uint16_t packet_delay_budget;
struct { struct {
long per_scalar; // PER = Scalar x 10^-k (k: 0-9)
long per_exponent; uint8_t per_scalar;
uint8_t per_exponent;
} packet_error_rate; } packet_error_rate;
} dynamic; } dynamic;
}; };
...@@ -168,8 +180,10 @@ typedef struct qos_characteristics_s { ...@@ -168,8 +180,10 @@ typedef struct qos_characteristics_s {
typedef struct ngran_allocation_retention_priority_s { typedef struct ngran_allocation_retention_priority_s {
uint16_t priority_level; uint16_t priority_level;
long preemption_capability; // Pre-emption capability on other QoS flows
long preemption_vulnerability; uint8_t preemption_capability;
// Vulnerability of the QoS flow to pre-emption of other QoS flows
uint8_t preemption_vulnerability;
} ngran_allocation_retention_priority_t; } ngran_allocation_retention_priority_t;
typedef struct qos_flow_level_qos_parameters_s { typedef struct qos_flow_level_qos_parameters_s {
...@@ -203,13 +217,31 @@ typedef struct DRB_nGRAN_to_setup_s { ...@@ -203,13 +217,31 @@ typedef struct DRB_nGRAN_to_setup_s {
/* Cell Group Information (clause 9.3.1.11) */ /* Cell Group Information (clause 9.3.1.11) */
int numCellGroups; int numCellGroups;
cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; cell_group_id_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS];
/* DRB QoS Flows Parameters (clause 9.3.1.26) */ /* DRB QoS Flows Parameters (clause 9.3.1.26) */
int numQosFlow2Setup; int numQosFlow2Setup;
qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS];
} DRB_nGRAN_to_setup_t, DRB_nGRAN_to_mod_t; } DRB_nGRAN_to_setup_t, DRB_nGRAN_to_mod_t;
typedef enum e1ap_indication_e {
SECURITY_REQUIRED = 0,
SECURITY_PREFERRED,
SECURITY_NOT_NEEDED
} e1ap_indication_t;
typedef struct security_indication_s {
e1ap_indication_t integrityProtectionIndication;
e1ap_indication_t confidentialityProtectionIndication;
// Maximum Integrity Protected Data Rate
long maxIPrate;
} security_indication_t;
typedef struct UP_TL_information_s {
in_addr_t tlAddress;
int32_t teId;
} UP_TL_information_t;
/** /**
* PDU Session Resource To Setup List (clause 9.3.3.10) * PDU Session Resource To Setup List (clause 9.3.3.10)
* PDU Session Resource To Modify List (clause 9.3.3.11) * PDU Session Resource To Modify List (clause 9.3.3.11)
...@@ -218,18 +250,12 @@ typedef struct pdu_session_to_setup_s { ...@@ -218,18 +250,12 @@ typedef struct pdu_session_to_setup_s {
long sessionId; long sessionId;
long sessionType; long sessionType;
e1ap_nssai_t nssai; e1ap_nssai_t nssai;
long integrityProtectionIndication; security_indication_t securityIndication;
long confidentialityProtectionIndication; UP_TL_information_t UP_TL_information;
in_addr_t tlAddress;
in_addr_t tlAddress_dl;
int32_t teId;
int32_t teId_dl;
int tl_port;
int tl_port_dl;
long numDRB2Setup; long numDRB2Setup;
DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS];
long numDRB2Modify; long numDRB2Modify;
DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS];
} pdu_session_to_setup_t, pdu_session_to_mod_t; } pdu_session_to_setup_t, pdu_session_to_mod_t;
/** /**
...@@ -239,15 +265,15 @@ typedef struct pdu_session_to_setup_s { ...@@ -239,15 +265,15 @@ typedef struct pdu_session_to_setup_s {
*/ */
typedef struct e1ap_bearer_setup_req_s { typedef struct e1ap_bearer_setup_req_s {
uint32_t gNB_cu_cp_ue_id; uint32_t gNB_cu_cp_ue_id;
uint32_t gNB_cu_up_ue_id; uint32_t gNB_cu_up_ue_id; // Bearer Context Modification Request only
uint64_t cipheringAlgorithm; uint64_t cipheringAlgorithm;
uint64_t integrityProtectionAlgorithm; uint64_t integrityProtectionAlgorithm;
char encryptionKey[128]; char encryptionKey[E1AP_SECURITY_KEY_SIZE];
char integrityProtectionKey[128]; char integrityProtectionKey[E1AP_SECURITY_KEY_SIZE];
long ueDlAggMaxBitRate; long ueDlAggMaxBitRate;
PLMN_ID_t servingPLMNid; PLMN_ID_t servingPLMNid;
BEARER_CONTEXT_STATUS_t bearerContextStatus; BEARER_CONTEXT_STATUS_t bearerContextStatus;
long activityNotificationLevel; activity_notification_level_t activityNotificationLevel;
int numPDUSessions; int numPDUSessions;
pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS];
int numPDUSessionsMod; int numPDUSessionsMod;
...@@ -293,16 +319,16 @@ typedef struct pdu_session_setup_s { ...@@ -293,16 +319,16 @@ typedef struct pdu_session_setup_s {
in_addr_t tlAddress; in_addr_t tlAddress;
long teId; long teId;
int numDRBSetup; int numDRBSetup;
DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS];
int numDRBFailed; int numDRBFailed;
DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_NGRAN_DRB]; DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_DRBS];
} pdu_session_setup_t; } pdu_session_setup_t;
typedef struct pdu_session_modif_s { typedef struct pdu_session_modif_s {
long id; long id;
// setup as part of PDU session modification not supported yet // setup as part of PDU session modification not supported yet
int numDRBModified; int numDRBModified;
DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_DRBS];
} pdu_session_modif_t; } pdu_session_modif_t;
typedef struct e1ap_bearer_setup_resp_s { typedef struct e1ap_bearer_setup_resp_s {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#ifndef NGAP_MESSAGES_TYPES_H_ #ifndef NGAP_MESSAGES_TYPES_H_
#define NGAP_MESSAGES_TYPES_H_ #define NGAP_MESSAGES_TYPES_H_
#include "common/5g_platform_types.h"
#include "common/platform_constants.h" #include "common/platform_constants.h"
#include "common/platform_types.h" #include "common/platform_types.h"
#include "common/5g_platform_types.h" #include "common/5g_platform_types.h"
......
add_subdirectory(MESSAGES) add_subdirectory(MESSAGES)
add_subdirectory(lib)
add_library(e1ap e1ap.c e1ap_common.c) add_library(e1ap e1ap.c e1ap_common.c)
target_link_libraries(e1ap target_link_libraries(e1ap
PUBLIC asn1_e1ap f1ap PUBLIC asn1_e1ap e1ap_lib
PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap UTIL e1_if) PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap UTIL e1_if)
target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR}) target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR})
if(ENABLE_TESTS)
add_subdirectory(tests)
endif()
This diff is collapsed.
add_library(e1ap_lib OBJECT
e1ap_bearer_context_management.c
)
target_link_libraries(e1ap_lib PRIVATE asn1_e1ap)
target_include_directories(e1ap_lib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
This diff is collapsed.
/*
* 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 E1AP_BEARER_CONTEXT_MANAGEMENT_H_
#define E1AP_BEARER_CONTEXT_MANAGEMENT_H_
#include <stdbool.h>
#include "openair2/COMMON/e1ap_messages_types.h"
#include "common/platform_types.h"
struct E1AP_E1AP_PDU;
struct E1AP_E1AP_PDU *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_req_t *msg);
bool decode_E1_bearer_context_setup_request(const struct E1AP_E1AP_PDU *pdu, e1ap_bearer_setup_req_t *out);
e1ap_bearer_setup_req_t cp_bearer_context_setup_request(const e1ap_bearer_setup_req_t *msg);
void free_e1ap_context_setup_request(e1ap_bearer_setup_req_t *msg);
bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1ap_bearer_setup_req_t *b);
struct E1AP_E1AP_PDU *encode_E1_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *msg);
bool decode_E1_bearer_context_setup_response(const struct E1AP_E1AP_PDU *pdu, e1ap_bearer_setup_resp_t *out);
void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg);
e1ap_bearer_setup_resp_t cp_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *msg);
bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e1ap_bearer_setup_resp_t *b);
#endif /* E1AP_BEARER_CONTEXT_MANAGEMENT_H_ */
/*
* 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 E1AP_LIB_COMMON_H_
#define E1AP_LIB_COMMON_H_
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "openair3/UTILS/conversions.h"
#ifdef ENABLE_TESTS
#define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__);
#else
#define PRINT_ERROR(...) // Do nothing
#endif
#define _E1_EQ_CHECK_GENERIC(condition, fmt, ...) \
do { \
if (!(condition)) { \
PRINT_ERROR("E1 Equality Check failure: %s:%d: Condition '%s' failed: " fmt " != " fmt "\n", \
__FILE__, \
__LINE__, \
#condition, \
##__VA_ARGS__); \
return false; \
} \
} while (0)
#define _E1_EQ_CHECK_LONG(A, B) _E1_EQ_CHECK_GENERIC(A == B, "%ld", A, B);
#define _E1_EQ_CHECK_INT(A, B) _E1_EQ_CHECK_GENERIC(A == B, "%d", A, B);
#define _E1_EQ_CHECK_STR(A, B) _E1_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B);
// Macro to look up IE. If mandatory and not found, macro will log an error and return false.
#define E1AP_LIB_FIND_IE(IE_TYPE, ie, container, IE_ID, mandatory) \
do { \
ie = NULL; \
for (int i = 0; i < (container)->protocolIEs.list.count; ++i) { \
IE_TYPE *current_ie = (container)->protocolIEs.list.array[i]; \
if (current_ie->id == (IE_ID)) { \
ie = current_ie; \
break; \
} \
} \
if (mandatory && ie == NULL) { \
fprintf(stderr, "%s(): Mandatory element not found: ID" #IE_ID " with type " #IE_TYPE "\n", __func__); \
return false; \
} \
} while (0)
#endif /* E1AP_LIB_COMMON_H_ */
/*
* 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 E1AP_LIB_INCLUDES_H_
#define E1AP_LIB_INCLUDES_H_
#include "E1AP_E1AP-PDU.h"
#include "E1AP_ProcedureCode.h"
#include "E1AP_SuccessfulOutcome.h"
#include "E1AP_InitiatingMessage.h"
#include "E1AP_ProtocolIE-ID.h"
#include "E1AP_ProtocolIE-Field.h"
#include "E1AP_UP-TNL-Information.h"
#include "E1AP_DefaultDRB.h"
#include "E1AP_QoS-Characteristics.h"
#include "E1AP_PDU-Session-Resource-To-Setup-Item.h"
#include "E1AP_GTPTunnel.h"
#include "E1AP_DRB-To-Setup-Item-NG-RAN.h"
#include "E1AP_T-ReorderingTimer.h"
#include "E1AP_QoS-Flow-QoS-Parameter-Item.h"
#include "E1AP_Cell-Group-Information-Item.h"
#include "E1AP_Dynamic5QIDescriptor.h"
#include "E1AP_Non-Dynamic5QIDescriptor.h"
// E1 Bearer Context Setup Request
#include "E1AP_BearerContextSetupRequest.h"
#include "E1AP_GNB-CU-CP-E1SetupRequest.h"
#include "E1AP_GNB-CU-UP-E1SetupRequest.h"
#include "E1AP_System-BearerContextSetupRequest.h"
#include "E1AP_MaximumIPdatarate.h"
#include "E1AP_PDU-Session-Type.h"
// E1 Bearer Context Setup Response
#include "E1AP_PDU-Session-Resource-Setup-Item.h"
#include "E1AP_DRB-Setup-Item-NG-RAN.h"
#include "E1AP_UP-Parameters-Item.h"
#include "E1AP_QoS-Flow-Item.h"
#include "E1AP_DRB-Failed-List-NG-RAN.h"
#include "E1AP_DRB-Failed-Item-NG-RAN.h"
#endif /* E1AP_LIB_INCLUDES_H_ */
add_executable(e1ap_lib_test e1ap_lib_test.c)
add_dependencies(tests e1ap_lib_test)
add_test(NAME e1ap_lib_test COMMAND e1ap_lib_test)
target_link_libraries(e1ap_lib_test PRIVATE e1ap_lib)
target_link_libraries(e1ap_lib_test PRIVATE asn1_e1ap)
target_include_directories(e1ap_lib_test PRIVATE
${CMAKE_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
)
/*
* 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 e1ap_lib_test.c
* \brief Unit tests for E1AP libraries
* \author Guido Casati
* \date 2024
* \version 0.1
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include "E1AP/lib/e1ap_bearer_context_management.h"
#include "E1AP/lib/e1ap_lib_includes.h"
#include "common/utils/assertions.h"
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
{
printf("detected error at %s:%d:%s: %s\n", file, line, function, s);
abort();
}
static E1AP_E1AP_PDU_t *e1ap_encode_decode(const E1AP_E1AP_PDU_t *enc_pdu)
{
// xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, enc_pdu);
DevAssert(enc_pdu != NULL);
char errbuf[2048];
size_t errlen = sizeof(errbuf);
int ret = asn_check_constraints(&asn_DEF_E1AP_E1AP_PDU, enc_pdu, errbuf, &errlen);
AssertFatal(ret == 0, "asn_check_constraints() failed: %s\n", errbuf);
uint8_t msgbuf[16384];
asn_enc_rval_t enc = aper_encode_to_buffer(&asn_DEF_E1AP_E1AP_PDU, NULL, enc_pdu, msgbuf, sizeof(msgbuf));
AssertFatal(enc.encoded > 0, "aper_encode_to_buffer() failed\n");
E1AP_E1AP_PDU_t *dec_pdu = NULL;
asn_codec_ctx_t st = {.max_stack_size = 100 * 1000};
asn_dec_rval_t dec = aper_decode(&st, &asn_DEF_E1AP_E1AP_PDU, (void **)&dec_pdu, msgbuf, enc.encoded, 0, 0);
AssertFatal(dec.code == RC_OK, "aper_decode() failed\n");
// xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, dec_pdu);
return dec_pdu;
}
static void e1ap_msg_free(E1AP_E1AP_PDU_t *pdu)
{
ASN_STRUCT_FREE(asn_DEF_E1AP_E1AP_PDU, pdu);
}
/**
* @brief Test E1AP Bearer Context Setup Request encoding/decoding
*/
static void test_bearer_context_setup_request(void)
{
bearer_context_pdcp_config_t pdcp = {
.discardTimer = E1AP_DiscardTimer_ms10,
.pDCP_Reestablishment = E1AP_PDCP_Reestablishment_true,
.pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_12,
.pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_12,
.reorderingTimer = 10,
.rLC_Mode = E1AP_RLC_Mode_rlc_am,
};
bearer_context_sdap_config_t sdap = {
.defaultDRB = 1,
.sDAP_Header_DL = true,
.sDAP_Header_UL = true,
};
qos_flow_to_setup_t qos = {
.qfi = 1,
.qos_params.alloc_reten_priority.preemption_capability = E1AP_Pre_emptionCapability_shall_not_trigger_pre_emption,
.qos_params.alloc_reten_priority.preemption_vulnerability = E1AP_Pre_emptionVulnerability_not_pre_emptable,
.qos_params.alloc_reten_priority.priority_level = E1AP_PriorityLevel_highest,
.qos_params.qos_characteristics.non_dynamic.fiveqi = 9,
};
security_indication_t security = {
.confidentialityProtectionIndication = E1AP_ConfidentialityProtectionIndication_required,
.integrityProtectionIndication = E1AP_IntegrityProtectionIndication_required,
.maxIPrate = E1AP_MaxIPrate_max_UErate,
};
// Step 1: Initialize the E1AP Bearer Context Setup Request
e1ap_bearer_setup_req_t orig = {
.gNB_cu_cp_ue_id = 1234,
.cipheringAlgorithm = 0x01,
.integrityProtectionAlgorithm = 0x01,
.ueDlAggMaxBitRate = 1000000000,
.bearerContextStatus = 0,
.servingPLMNid.mcc = 001,
.servingPLMNid.mnc = 01,
.servingPLMNid.mnc_digit_length = 0x02,
.activityNotificationLevel = ANL_PDU_SESSION,
.numPDUSessions = 1,
.pduSession[0].sessionId = 1,
.pduSession[0].sessionType = E1AP_PDU_Session_Type_ipv4,
.pduSession[0].nssai.sd = 0x01,
.pduSession[0].nssai.sst = 0x01,
.pduSession[0].securityIndication = security,
.pduSession[0].numDRB2Setup = 1,
.pduSession[0].UP_TL_information.tlAddress = 167772161,
.pduSession[0].UP_TL_information.teId = 0x12345,
.pduSession[0].DRBnGRanList[0].id = 1,
.pduSession[0].DRBnGRanList[0].sdap_config = sdap,
.pduSession[0].DRBnGRanList[0].pdcp_config = pdcp,
.pduSession[0].DRBnGRanList[0].id = 1,
.pduSession[0].DRBnGRanList[0].numCellGroups = 1,
.pduSession[0].DRBnGRanList[0].cellGroupList[0] = MCG,
.pduSession[0].DRBnGRanList[0].numQosFlow2Setup = 1,
.pduSession[0].DRBnGRanList[0].qosFlows[0] = qos,
};
memset(orig.encryptionKey, 0xAB, sizeof(orig.encryptionKey));
memset(orig.integrityProtectionKey, 0xCD, sizeof(orig.integrityProtectionKey));
// E1AP encode the original message
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_request(&orig);
// E1AP decode the encoded message
E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc);
// Free the E1AP encoded message
e1ap_msg_free(enc);
// E1 message decode
e1ap_bearer_setup_req_t decoded = {0};
bool ret = decode_E1_bearer_context_setup_request(dec, &decoded);
AssertFatal(ret, "decode_E1_bearer_context_setup_request(): could not decode message\n");
// Free the E1AP decoded message
e1ap_msg_free(dec);
// Equality check original/decoded
ret = eq_bearer_context_setup_request(&orig, &decoded);
AssertFatal(ret, "eq_bearer_context_setup_request(): decoded message doesn't match\n");
// Free the memory for the decoded message
free_e1ap_context_setup_request(&decoded);
// Deep copy and equality check of the original message
e1ap_bearer_setup_req_t cp = cp_bearer_context_setup_request(&orig);
ret = eq_bearer_context_setup_request(&orig, &cp);
AssertFatal(ret, "eq_bearer_context_setup_request(): copied message doesn't match\n");
// Free the copied message and original
free_e1ap_context_setup_request(&cp);
free_e1ap_context_setup_request(&orig);
}
/**
* @brief Test E1AP Bearer Context Setup Response encoding/decoding
*/
static void test_bearer_context_setup_response(void)
{
// Step 1: Initialize the E1AP Bearer Context Setup Response
e1ap_bearer_setup_resp_t orig = {
.gNB_cu_cp_ue_id = 1234,
.gNB_cu_up_ue_id = 5678,
.numPDUSessions = 1,
.pduSession[0].id = 1,
.pduSession[0].tlAddress = 167772161,
.pduSession[0].teId = 0x12345,
.pduSession[0].numDRBSetup = 1,
.pduSession[0].numDRBFailed = 0,
.pduSession[0].DRBnGRanList[0].id = 1,
.pduSession[0].DRBnGRanList[0].numUpParam = 1,
.pduSession[0].DRBnGRanList[0].numQosFlowSetup = 1,
.pduSession[0].DRBnGRanList[0].qosFlows[0].qfi = 1,
.pduSession[0].DRBnGRanList[0].UpParamList[0].cell_group_id = MCG,
.pduSession[0].DRBnGRanList[0].UpParamList[0].teId = 0x34345,
.pduSession[0].DRBnGRanList[0].UpParamList[0].tlAddress = 167772161,
};
// E1AP encode the original message
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_response(&orig);
// E1AP decode the encoded message
E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc);
// Free the E1AP encoded message
e1ap_msg_free(enc);
// E1 message decode
e1ap_bearer_setup_resp_t decoded = {0};
bool ret = decode_E1_bearer_context_setup_response(dec, &decoded);
AssertFatal(ret, "decode_E1_bearer_context_setup_response(): could not decode message\n");
// Free the E1AP decoded message
e1ap_msg_free(dec);
// Equality check original/decoded
ret = eq_bearer_context_setup_response(&orig, &decoded);
AssertFatal(ret, "eq_bearer_context_setup_response(): decoded message doesn't match\n");
// Free the memory for the decoded message
free_e1ap_context_setup_response(&decoded);
// Deep copy and equality check of the original message
e1ap_bearer_setup_resp_t cp = cp_bearer_context_setup_response(&orig);
ret = eq_bearer_context_setup_response(&orig, &cp);
AssertFatal(ret, "eq_bearer_context_setup_response(): copied message doesn't match\n");
// Free the copied message and original
free_e1ap_context_setup_response(&cp);
free_e1ap_context_setup_response(&orig);
}
int main()
{
// E1 Bearer Context Setup
test_bearer_context_setup_request();
test_bearer_context_setup_response();
return 0;
}
...@@ -88,11 +88,12 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const ...@@ -88,11 +88,12 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const
pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering));
*pdcp_config->t_Reordering = drb->pdcp_config.reorderingTimer; *pdcp_config->t_Reordering = drb->pdcp_config.reorderingTimer;
pdcp_config->ext1 = NULL; pdcp_config->ext1 = NULL;
if (pdu->integrityProtectionIndication == 0 || // Required const security_indication_t *sec = &pdu->securityIndication;
pdu->integrityProtectionIndication == 1) { // Preferred if (sec->integrityProtectionIndication == SECURITY_REQUIRED ||
asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); sec->integrityProtectionIndication == SECURITY_PREFERRED) {
asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled);
} }
if (pdu->confidentialityProtectionIndication == 2) { // Not Needed if (sec->confidentialityProtectionIndication == SECURITY_NOT_NEEDED) {
asn1cCalloc(pdcp_config->ext1, ext1); asn1cCalloc(pdcp_config->ext1, ext1);
asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true);
} }
...@@ -188,8 +189,8 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) ...@@ -188,8 +189,8 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
req_drb->id, req_drb->id,
req_pdu->sessionId, req_pdu->sessionId,
qfi, qfi,
req_pdu->tlAddress, req_pdu->UP_TL_information.tlAddress,
req_pdu->teId, req_pdu->UP_TL_information.teId,
nr_pdcp_data_req_drb, nr_pdcp_data_req_drb,
sdap_data_req, sdap_data_req,
&resp_n3); &resp_n3);
......
...@@ -94,6 +94,7 @@ ...@@ -94,6 +94,7 @@
#include "utils.h" #include "utils.h"
#include "x2ap_messages_types.h" #include "x2ap_messages_types.h"
#include "xer_encoder.h" #include "xer_encoder.h"
#include "E1AP/lib/e1ap_bearer_context_management.h"
#ifdef E2_AGENT #ifdef E2_AGENT
#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h"
...@@ -2595,6 +2596,7 @@ void *rrc_gnb_task(void *args_p) { ...@@ -2595,6 +2596,7 @@ void *rrc_gnb_task(void *args_p) {
case E1AP_BEARER_CONTEXT_SETUP_RESP: case E1AP_BEARER_CONTEXT_SETUP_RESP:
rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance); rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance);
free_e1ap_context_setup_response(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p));
break; break;
case E1AP_BEARER_CONTEXT_MODIFICATION_RESP: case E1AP_BEARER_CONTEXT_MODIFICATION_RESP:
......
...@@ -349,11 +349,13 @@ void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession ...@@ -349,11 +349,13 @@ void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
if (cuup_nssai.sst == 0) if (cuup_nssai.sst == 0)
cuup_nssai = pdu->nssai; /* for CU-UP selection below */ cuup_nssai = pdu->nssai; /* for CU-UP selection below */
pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed; security_indication_t *sec = &pdu->securityIndication;
sec->integrityProtectionIndication = rrc->security.do_drb_integrity ? SECURITY_REQUIRED
pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed; : SECURITY_NOT_NEEDED;
pdu->teId = session->gtp_teid; sec->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? SECURITY_REQUIRED
memcpy(&pdu->tlAddress, session->upf_addr.buffer, 4); // Fixme: dirty IPv4 target : SECURITY_NOT_NEEDED;
pdu->UP_TL_information.teId = session->gtp_teid;
memcpy(&pdu->UP_TL_information.tlAddress, session->upf_addr.buffer, sizeof(in_addr_t));
/* we assume for the moment one DRB per PDU session. Activate the bearer, /* we assume for the moment one DRB per PDU session. Activate the bearer,
* and configure in RRC. */ * and configure in RRC. */
...@@ -380,9 +382,10 @@ void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession ...@@ -380,9 +382,10 @@ void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
drb->numCellGroups = 1; // assume one cell group associated with a DRB drb->numCellGroups = 1; // assume one cell group associated with a DRB
// Set all Cell Group IDs to MCG
for (int k=0; k < drb->numCellGroups; k++) { for (int k=0; k < drb->numCellGroups; k++) {
cell_group_t *cellGroup = drb->cellGroupList + k; cell_group_id_t *cellGroup = drb->cellGroupList + k;
cellGroup->id = 0; // MCG *cellGroup = MCG;
} }
drb->numQosFlow2Setup = session->nb_qos; drb->numQosFlow2Setup = session->nb_qos;
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24)) ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24))
# define hton_int16(x) \ # define hton_int16(x) \
(((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8))
# define ntoh_int32_buf(bUF) \ # define ntoh_int32_buf(bUF) \
((*((uint8_t*)bUF)) << 24) | ((*((uint8_t*)bUF + 1)) << 16) | ((*((uint8_t*)bUF + 2)) << 8) \ ((*((uint8_t*)bUF)) << 24) | ((*((uint8_t*)bUF + 1)) << 16) | ((*((uint8_t*)bUF + 2)) << 8) \
...@@ -285,19 +285,6 @@ do { \ ...@@ -285,19 +285,6 @@ do { \
BUFFER_TO_UINT32((aSN)->buf, x); \ BUFFER_TO_UINT32((aSN)->buf, x); \
} while (0) } while (0)
#define BIT_STRING_TO_INT32(aSN, x) \
do { \
DevCheck((aSN)->bits_unused == 0, (aSN)->bits_unused, 0, 0); \
OCTET_STRING_TO_INT32(aSN, x); \
} while(0)
#define BIT_STRING_TO_CELL_IDENTITY(aSN, vALUE) \
do { \
DevCheck((aSN)->bits_unused == 4, (aSN)->bits_unused, 4, 0); \
vALUE = ((aSN)->buf[0] << 20) | ((aSN)->buf[1] << 12) | \
((aSN)->buf[2] << 4) | (aSN)->buf[3]; \
} while(0)
#define BIT_STRING_TO_NR_CELL_IDENTITY(aSN, vALUE) \ #define BIT_STRING_TO_NR_CELL_IDENTITY(aSN, vALUE) \
do { \ do { \
DevCheck((aSN)->bits_unused == 4, (aSN)->bits_unused, 4, 0); \ DevCheck((aSN)->bits_unused == 4, (aSN)->bits_unused, 4, 0); \
...@@ -315,14 +302,6 @@ do { \ ...@@ -315,14 +302,6 @@ do { \
#define MCC_MNC_DIGIT(vALUE) \ #define MCC_MNC_DIGIT(vALUE) \
((vALUE) % 10) ((vALUE) % 10)
#define MCC_TO_BUFFER(mCC, bUFFER) \
do { \
DevAssert(bUFFER != NULL); \
(bUFFER)[0] = MCC_HUNDREDS(mCC); \
(bUFFER)[1] = MCC_MNC_DECIMAL(mCC); \
(bUFFER)[2] = MCC_MNC_DIGIT(mCC); \
} while(0)
#define MCC_MNC_TO_PLMNID(mCC, mNC, mNCdIGITlENGTH, oCTETsTRING) \ #define MCC_MNC_TO_PLMNID(mCC, mNC, mNCdIGITlENGTH, oCTETsTRING) \
do { \ do { \
(oCTETsTRING)->buf = calloc(3, sizeof(uint8_t)); \ (oCTETsTRING)->buf = calloc(3, sizeof(uint8_t)); \
...@@ -459,14 +438,6 @@ do { \ ...@@ -459,14 +438,6 @@ do { \
(bITsTRING)->bits_unused = 4; \ (bITsTRING)->bits_unused = 4; \
} while(0) } while(0)
/*
#define INT16_TO_3_BYTE_BUFFER(x, buf) \
do { \
(buf)[0] = 0x00; \
(buf)[1] = (x) >> 8; \
(buf)[2] = (x); \
} while(0)
*/
#define NR_FIVEGS_TAC_ID_TO_BIT_STRING(x, aSN) \ #define NR_FIVEGS_TAC_ID_TO_BIT_STRING(x, aSN) \
do { \ do { \
...@@ -497,20 +468,6 @@ do { \ ...@@ -497,20 +468,6 @@ do { \
(bITsTRING)->bits_unused = 0; \ (bITsTRING)->bits_unused = 0; \
} while(0) } while(0)
#define BIT_STRING_TO_MaskedIMEISV(bITsTRING, mACRO) \
do { \
DevCheck((bITsTRING)->size == 8, (bITsTRING)->size, 8, 0); \
DevCheck((bITsTRING)->bits_unused == 0, (bITsTRING)->bits_unused, 0, 0); \
mACRO = ((bITsTRING)->buf[0] << 56) + \
((bITsTRING)->buf[1] << 48) + \
((bITsTRING)->buf[2] << 40) + \
((bITsTRING)->buf[3] << 32) + \
((bITsTRING)->buf[4] << 24) + \
((bITsTRING)->buf[5] << 16) + \
((bITsTRING)->buf[6] << 8) + \
((bITsTRING)->buf[7]); \
} while (0)
/* TS 36.413 v10.9.0 section 9.2.1.37: /* TS 36.413 v10.9.0 section 9.2.1.37:
* Macro eNB ID: * Macro eNB ID:
* Equal to the 20 leftmost bits of the Cell * Equal to the 20 leftmost bits of the Cell
......
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