Merge remote-tracking branch 'origin/nr-paging-cu' into integration_2026_w08 (!3893)
NR Paging on CU
Implements the NR paging path on the CU:
- NGAP Paging is decoded and passed to RRC
- RRC builds F1AP Paging, and distributes it to DUs via F1 callback
Changes:
- Refactor and extend F1AP Paging encode/decode libraries
* add missing enc/dec/eq/cp functions
* add unit test
* IEs: CN UE 5G-S-TMSI, RAN UE I-RNTI; optional DRX/priority/origin)
- Refactor CU callback CU_send_Paging
- Refactor DU handler DU_handle_Paging
- Refactor old F1 callback for Paging indication, extend it and align
with existing F1 callbacks in stack
- Refactor and extend NGAP Paging encode/decode lib
* add missing enc/dec/eq/cp functions
* add unit test
* Fixes NGAP paging to accept Paging only on SCTP stream 0 per TS
38.412
- Includes supporting refactors (PDU session split, shared 5G-S-TMSI
helpers, NGAP/F1AP cleanups)
Testing
- NGAP and F1AP Paging lib unit tests (enc/dec)
- Stream-0 fix validated with Open5GS AMF
This MR does not address the DU changes besides the F1 handler. F1AP
Paging does not have an RRC container to pass the PCCH message to the
DU, and F1 DL RRC Message Transfer does not apply to PCCH. PCCH-Message
shall be built at DU per TS 38.331 §5.3.2, with padding as per §8.5 and
delivered as RLC SDU per §8.2. For each cell in Paging Cell List that
belongs to this DU, queue for MAC. MAC schedules at PF/PO per TS 38.304
§7.
Refs:
- F1AP 3GPP TS 38.473 version 16.21.0 Release 16
- NGAP 3GPP TS 38.413 version 16.17.0 Release 16
This commit is contained in:
@@ -434,7 +434,9 @@ add_library(ngap
|
||||
${NGAP_DIR}/ngap_gNB_handlers.c
|
||||
${NGAP_DIR}/ngap_gNB_itti_messaging.c
|
||||
${NGAP_DIR}/ngap_gNB_management_procedures.c
|
||||
${NGAP_DIR}/ngap_gNB_paging.c
|
||||
${NGAP_DIR}/ngap_gNB_nas_procedures.c
|
||||
${NGAP_DIR}/ngap_gNB_pdu_session_management.c
|
||||
${NGAP_DIR}/ngap_gNB_nnsf.c
|
||||
${NGAP_DIR}/ngap_gNB_overload.c
|
||||
${NGAP_DIR}/ngap_gNB_trace.c
|
||||
@@ -442,6 +444,9 @@ add_library(ngap
|
||||
)
|
||||
target_link_libraries(ngap PUBLIC asn1_ngap)
|
||||
target_link_libraries(ngap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
if(ENABLE_TESTS)
|
||||
target_compile_definitions(ngap PRIVATE ENABLE_TESTS)
|
||||
endif()
|
||||
|
||||
#M2AP
|
||||
##############
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 EQ_CHECK_H_
|
||||
#define EQ_CHECK_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Layers may override PRINT_ERROR() before including this header to preserve
|
||||
* custom logging style (for example by mapping it to a local PRINT_ERROR()).
|
||||
*/
|
||||
|
||||
#ifndef PRINT_ERROR
|
||||
#ifdef ENABLE_TESTS
|
||||
#define PRINT_ERROR(fmt, ...) fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define PRINT_ERROR(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EQ_CHECK_FAIL
|
||||
#define EQ_CHECK_FAIL() return false
|
||||
#endif
|
||||
|
||||
#define EQ_CHECK_GENERIC(condition, fmt, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
PRINT_ERROR("Equality condition '%s' failed: " fmt " != " fmt "\n", #condition, ##__VA_ARGS__); \
|
||||
EQ_CHECK_FAIL(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _EQ_CHECK_LONG(A, B) EQ_CHECK_GENERIC((A) == (B), "%ld", (A), (B))
|
||||
#define _EQ_CHECK_INT(A, B) EQ_CHECK_GENERIC((A) == (B), "%d", (A), (B))
|
||||
#define _EQ_CHECK_UINT32(A, B) EQ_CHECK_GENERIC((A) == (B), "%u", (A), (B))
|
||||
#define _EQ_CHECK_UINT64(A, B) EQ_CHECK_GENERIC((A) == (B), "%" PRIu64, (uint64_t)(A), (uint64_t)(B))
|
||||
#define _EQ_CHECK_STR(A, B) EQ_CHECK_GENERIC(strcmp((A), (B)) == 0, "'%s'", (A), (B))
|
||||
|
||||
#define _EQ_CHECK_OPTIONAL_IE(A, B, FIELD, EQ_MACRO) \
|
||||
do { \
|
||||
EQ_CHECK_GENERIC((((A)->FIELD) != NULL) == (((B)->FIELD) != NULL), "%d", ((A)->FIELD) != NULL, ((B)->FIELD) != NULL); \
|
||||
if ((A)->FIELD && (B)->FIELD) \
|
||||
EQ_MACRO(*(A)->FIELD, *(B)->FIELD); \
|
||||
} while (0)
|
||||
|
||||
#define _EQ_CHECK_OPTIONAL_PTR(A, B, FIELD) \
|
||||
do { \
|
||||
if ((((A)->FIELD) != NULL) != (((B)->FIELD) != NULL)) { \
|
||||
PRINT_ERROR("%s:%d: optional IE '%s' not allocated: %p, %p\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#FIELD, \
|
||||
(void *)(A)->FIELD, \
|
||||
(void *)(B)->FIELD); \
|
||||
EQ_CHECK_FAIL(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* EQ_CHECK_H_ */
|
||||
@@ -1463,6 +1463,18 @@ uint64_t nr_construct_5g_s_tmsi(uint16_t amf_set_id, uint8_t amf_pointer, uint32
|
||||
return ((uint64_t)amf_set_id << 38) | ((uint64_t)amf_pointer << 32) | m_tmsi;
|
||||
}
|
||||
|
||||
/** @brief Extract 5G-S-TMSI-Part1 from full 5G-S-TMSI
|
||||
* @param fiveg_s_tmsi Full 5G-S-TMSI (48 bits)
|
||||
* @return 5G-S-TMSI-Part1 (rightmost 39 bits)
|
||||
* @note 5G-S-TMSI-Part1 is the rightmost 39 bits of the full 5G-S-TMSI:
|
||||
* - Bits 32-37: AMF Pointer (6 bits)
|
||||
* - Bits 0-31: 5G-TMSI (32 bits)
|
||||
* @ref 3GPP TS 23.003 */
|
||||
uint64_t nr_extract_5g_s_tmsi_part1(const uint64_t fiveg_s_tmsi)
|
||||
{
|
||||
return fiveg_s_tmsi & ((1ULL << 39) - 1);
|
||||
}
|
||||
|
||||
/** @brief Construct 5G-S-TMSI-Part1 from 5G-S-TMSI components
|
||||
* @param amf_set_id AMF Set ID (10 bits)
|
||||
* @param amf_pointer AMF Pointer (6 bits)
|
||||
@@ -1476,5 +1488,48 @@ uint64_t nr_construct_5g_s_tmsi_part1(uint16_t amf_set_id, uint8_t amf_pointer,
|
||||
{
|
||||
// Construct full 5G-S-TMSI and extract Part1: rightmost 39 bits
|
||||
uint64_t full_s_tmsi = nr_construct_5g_s_tmsi(amf_set_id, amf_pointer, m_tmsi);
|
||||
return full_s_tmsi & ((1ULL << 39) - 1);
|
||||
return nr_extract_5g_s_tmsi_part1(full_s_tmsi);
|
||||
}
|
||||
|
||||
/** @brief Extract 5G-S-TMSI-Part2 from full 5G-S-TMSI
|
||||
* @param fiveg_s_tmsi Full 5G-S-TMSI (48 bits)
|
||||
* @return 5G-S-TMSI-Part2 (leftmost 9 bits)
|
||||
* @note 5G-S-TMSI-Part2 is the leftmost 9 bits of the full 5G-S-TMSI:
|
||||
* - Bits 39-47: AMF Set ID (9 bits)
|
||||
* @ref 3GPP TS 23.003 */
|
||||
uint16_t nr_extract_5g_s_tmsi_part2(const uint64_t fiveg_s_tmsi)
|
||||
{
|
||||
return (fiveg_s_tmsi >> 39) & ((1ULL << 9) - 1);
|
||||
}
|
||||
|
||||
/** @brief Build full 5G-S-TMSI from Part1 and Part2
|
||||
* @param part1 5G-S-TMSI-Part1 (rightmost 39 bits)
|
||||
* @param part2 5G-S-TMSI-Part2 (leftmost 9 bits)
|
||||
* @return Full 5G-S-TMSI (48 bits)
|
||||
* @note Combines Part2 (leftmost 9 bits) and Part1 (rightmost 39 bits)
|
||||
* @ref 3GPP TS 23.003 */
|
||||
uint64_t nr_build_full_5g_s_tmsi(const uint64_t part1, const uint16_t part2)
|
||||
{
|
||||
return ((uint64_t)part2 << 39) | part1;
|
||||
}
|
||||
|
||||
/** @brief Deconstruct full 5G-S-TMSI into its components
|
||||
* @param fiveg_s_tmsi Full 5G-S-TMSI (48 bits)
|
||||
* @param[out] amf_set_id Pointer to store AMF Set ID (10 bits)
|
||||
* @param[out] amf_pointer Pointer to store AMF Pointer (6 bits)
|
||||
* @param[out] m_tmsi Pointer to store 5G-TMSI (32 bits)
|
||||
* @note The 5G-S-TMSI is deconstructed from a 48-bit value:
|
||||
* - Bits 38-47: AMF Set ID (10 bits)
|
||||
* - Bits 32-37: AMF Pointer (6 bits)
|
||||
* - Bits 0-31: 5G-TMSI (32 bits)
|
||||
* @ref 3GPP TS 23.003 */
|
||||
void nr_deconstruct_5g_s_tmsi(const uint64_t fiveg_s_tmsi, uint16_t *amf_set_id, uint8_t *amf_pointer, uint32_t *m_tmsi)
|
||||
{
|
||||
DevAssert(amf_set_id != NULL);
|
||||
DevAssert(amf_pointer != NULL);
|
||||
DevAssert(m_tmsi != NULL);
|
||||
|
||||
*amf_set_id = fiveg_s_tmsi >> 38;
|
||||
*amf_pointer = (fiveg_s_tmsi >> 32) & 0x3F;
|
||||
*m_tmsi = fiveg_s_tmsi;
|
||||
}
|
||||
|
||||
@@ -360,6 +360,18 @@ uint64_t nr_construct_5g_s_tmsi(uint16_t amf_set_id, uint8_t amf_pointer, uint32
|
||||
/** @brief Construct 5G-S-TMSI-Part1 from 5G-S-TMSI components */
|
||||
uint64_t nr_construct_5g_s_tmsi_part1(uint16_t amf_set_id, uint8_t amf_pointer, uint32_t m_tmsi);
|
||||
|
||||
/** @brief Extract 5G-S-TMSI-Part1 from full 5G-S-TMSI */
|
||||
uint64_t nr_extract_5g_s_tmsi_part1(const uint64_t fiveg_s_tmsi);
|
||||
|
||||
/** @brief Extract 5G-S-TMSI-Part2 from full 5G-S-TMSI */
|
||||
uint16_t nr_extract_5g_s_tmsi_part2(const uint64_t fiveg_s_tmsi);
|
||||
|
||||
/** @brief Build full 5G-S-TMSI from Part1 and Part2 */
|
||||
uint64_t nr_build_full_5g_s_tmsi(const uint64_t part1, const uint16_t part2);
|
||||
|
||||
/** @brief Deconstruct full 5G-S-TMSI into its components */
|
||||
void nr_deconstruct_5g_s_tmsi(const uint64_t fiveg_s_tmsi, uint16_t *amf_set_id, uint8_t *amf_pointer, uint32_t *m_tmsi);
|
||||
|
||||
#define CEILIDIV(a,b) ((a+b-1)/b)
|
||||
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
|
||||
#define BOUNDED_EVAL(a, b, c) (min(c, max(a, b)))
|
||||
|
||||
@@ -109,6 +109,15 @@ int hex_char_to_hex_value (char c);
|
||||
// Converts an hexadecimal ASCII coded string into its value.**
|
||||
int hex_string_to_hex_value (uint8_t *hex_value, const char *hex_string, int size);
|
||||
|
||||
/* Map task id to printable name. */
|
||||
typedef struct {
|
||||
int id;
|
||||
char text[256];
|
||||
} text_info_t;
|
||||
|
||||
#define TO_TEXT(LabEl, nUmID) {nUmID, #LabEl},
|
||||
#define TO_ENUM(LabEl, nUmID) LabEl = nUmID,
|
||||
|
||||
char *itoa(int i);
|
||||
|
||||
#define STRINGIFY(S) #S
|
||||
|
||||
@@ -64,4 +64,4 @@ MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse)
|
||||
|
||||
/* CU -> DU*/
|
||||
MESSAGE_DEF(F1AP_PAGING_IND, MESSAGE_PRIORITY_MED, f1ap_paging_ind_t, f1ap_paging_ind)
|
||||
MESSAGE_DEF(F1AP_PAGING, MESSAGE_PRIORITY_MED, f1ap_paging_t, f1ap_paging)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/sctp.h>
|
||||
#include <stdbool.h>
|
||||
#include "common/5g_platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
@@ -67,7 +68,7 @@
|
||||
#define F1AP_UE_CONTEXT_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_cmd
|
||||
#define F1AP_UE_CONTEXT_RELEASE_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_complete
|
||||
|
||||
#define F1AP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.f1ap_paging_ind
|
||||
#define F1AP_PAGING(mSGpTR) (mSGpTR)->ittiMsg.f1ap_paging
|
||||
|
||||
/* Length of the transport layer address string
|
||||
* 160 bits / 8 bits by char.
|
||||
@@ -631,14 +632,67 @@ typedef struct f1ap_ue_context_rel_cplt_t {
|
||||
uint32_t gNB_DU_ue_id;
|
||||
} f1ap_ue_context_rel_cplt_t;
|
||||
|
||||
typedef struct f1ap_paging_ind_s {
|
||||
uint16_t ueidentityindexvalue;
|
||||
uint64_t fiveg_s_tmsi;
|
||||
uint8_t fiveg_s_tmsi_length;
|
||||
typedef struct f1ap_paging_cell_item_s {
|
||||
plmn_id_t plmn;
|
||||
uint64_t nr_cellid;
|
||||
uint8_t paging_drx;
|
||||
} f1ap_paging_ind_t;
|
||||
} f1ap_paging_cell_item_t;
|
||||
|
||||
typedef enum f1ap_paging_identity_type_e {
|
||||
F1AP_PAGING_IDENTITY_RAN_UE, // RAN UE Paging Identity (I-RNTI)
|
||||
F1AP_PAGING_IDENTITY_CN_UE // CN UE Paging Identity (5G-S-TMSI)
|
||||
} f1ap_paging_identity_type_t;
|
||||
|
||||
typedef union f1ap_paging_identity_u {
|
||||
// RAN UE Paging Identity (I-RNTI)
|
||||
uint64_t ran_ue_paging_identity;
|
||||
// CN UE Paging Identity (5G-S-TMSI)
|
||||
uint64_t cn_ue_paging_identity;
|
||||
} f1ap_paging_identity_t;
|
||||
|
||||
/** @brief Paging DRX (9.3.1.40 TS 38.473)
|
||||
* This IE indicates the Paging DRX as defined in
|
||||
* TS 38.304. Unit in radio frames.*/
|
||||
typedef enum f1ap_paging_drx_e {
|
||||
F1AP_PAGING_DRX_32 = 0,
|
||||
F1AP_PAGING_DRX_64 = 1,
|
||||
F1AP_PAGING_DRX_128 = 2,
|
||||
F1AP_PAGING_DRX_256 = 3
|
||||
} f1ap_paging_drx_t;
|
||||
|
||||
/** @brief Paging Priority (9.3.1.41 TS 38.473)
|
||||
* Lower value codepoint indicates higher priority.
|
||||
* codepoint indicates higher priority.*/
|
||||
typedef enum f1ap_paging_priority_e {
|
||||
F1AP_PAGING_PRIO_LEVEL1 = 0,
|
||||
F1AP_PAGING_PRIO_LEVEL2 = 1,
|
||||
F1AP_PAGING_PRIO_LEVEL3 = 2,
|
||||
F1AP_PAGING_PRIO_LEVEL4 = 3,
|
||||
F1AP_PAGING_PRIO_LEVEL5 = 4,
|
||||
F1AP_PAGING_PRIO_LEVEL6 = 5,
|
||||
F1AP_PAGING_PRIO_LEVEL7 = 6,
|
||||
F1AP_PAGING_PRIO_LEVEL8 = 7
|
||||
} f1ap_paging_priority_t;
|
||||
|
||||
typedef bool f1ap_paging_origin_t;
|
||||
#define F1AP_PAGING_ORIGIN_NON_3GPP true
|
||||
|
||||
/* 9.2.6.1 Paging (3GPP TS 38.473) */
|
||||
typedef struct {
|
||||
// UE Identity Index value (mandatory)
|
||||
uint16_t ue_identity_index_value;
|
||||
// Paging Identity (mandatory)
|
||||
f1ap_paging_identity_type_t identity_type;
|
||||
f1ap_paging_identity_t identity;
|
||||
// Paging DRX: 0 (32), 1 (64), 2 (128), 3 (256) (optional)
|
||||
f1ap_paging_drx_t *drx;
|
||||
// Paging priority (optional)
|
||||
f1ap_paging_priority_t *priority;
|
||||
// Paging origin (optional)
|
||||
f1ap_paging_origin_t *origin;
|
||||
// Paging Cell List (mandatory); max 512 cells
|
||||
uint16_t n_cells;
|
||||
f1ap_paging_cell_item_t *cells;
|
||||
} f1ap_paging_t;
|
||||
|
||||
typedef struct f1ap_lost_connection_t {
|
||||
int dummy;
|
||||
|
||||
@@ -47,8 +47,6 @@ MESSAGE_DEF(NGAP_PAGING_LOG , MESSAGE_PRIORITY_MED, IttiMsgText
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_release_request_log)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_release_response_log)
|
||||
MESSAGE_DEF(NGAP_ERROR_INDICATION_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_error_indication_log)
|
||||
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_path_switch_req_log)
|
||||
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_path_switch_req_ack_log)
|
||||
|
||||
/* gNB application layer -> NGAP messages */
|
||||
MESSAGE_DEF(NGAP_REGISTER_GNB_REQ , MESSAGE_PRIORITY_MED, ngap_register_gnb_req_t , ngap_register_gnb_req)
|
||||
@@ -65,8 +63,6 @@ MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, ngap_initial_
|
||||
MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_FAIL, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_fail_t, ngap_initial_context_setup_fail)
|
||||
MESSAGE_DEF(NGAP_NAS_NON_DELIVERY_IND , MESSAGE_PRIORITY_MED, ngap_nas_non_delivery_ind_t , ngap_nas_non_delivery_ind)
|
||||
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, ngap_ue_release_complete_t , ngap_ue_release_complete)
|
||||
MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_resp_t , ngap_ue_ctxt_modification_resp)
|
||||
MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_fail_t , ngap_ue_ctxt_modification_fail)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_SETUP_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_setup_resp_t , ngap_pdusession_setup_resp)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_resp_t , ngap_pdusession_modify_resp)
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdusession_release_resp_t , ngap_pdusession_release_resp)
|
||||
@@ -81,7 +77,6 @@ MESSAGE_DEF(NGAP_DL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_t
|
||||
/* NGAP -> RRC messages */
|
||||
MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas )
|
||||
MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, ngap_initial_context_setup_req_t , ngap_initial_context_setup_req )
|
||||
MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_req_t , ngap_ue_ctxt_modification_req)
|
||||
MESSAGE_DEF(NGAP_PAGING_IND , MESSAGE_PRIORITY_MED, ngap_paging_ind_t , ngap_paging_ind )
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQ , MESSAGE_PRIORITY_MED, ngap_pdusession_setup_req_t , ngap_pdusession_setup_req )
|
||||
MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_REQ , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_req_t , ngap_pdusession_modify_req )
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
#include "common/5g_platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
#include "common/platform_types.h"
|
||||
#include "common/5g_platform_types.h"
|
||||
#include "s1ap_messages_types.h"
|
||||
#include "ds/byte_array.h"
|
||||
#include "utils.h"
|
||||
|
||||
// Defines to access message fields.
|
||||
#define NGAP_REGISTER_GNB_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_register_gnb_req
|
||||
@@ -58,7 +58,6 @@
|
||||
|
||||
#define NGAP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_nas
|
||||
#define NGAP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_req
|
||||
#define NGAP_UE_CTXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_req
|
||||
#define NGAP_UE_CONTEXT_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_command
|
||||
#define NGAP_UE_CONTEXT_RELEASE_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_complete
|
||||
#define NGAP_PDUSESSION_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_setup_req
|
||||
@@ -89,39 +88,46 @@
|
||||
|
||||
#define NGAP_MAX_NB_AMF_IP_ADDRESS 10
|
||||
|
||||
#define NGAP_MAX_NO_TAI_PAGING 16 // 9.2.4.1 3GPP TS 38.413
|
||||
|
||||
/* Security key length used within gNB
|
||||
* Even if only 16 bytes will be effectively used,
|
||||
* the key length is 32 bytes (256 bits)
|
||||
*/
|
||||
#define SECURITY_KEY_LENGTH 32
|
||||
|
||||
typedef enum ngap_paging_drx_e {
|
||||
NGAP_PAGING_DRX_32 = 0x0,
|
||||
NGAP_PAGING_DRX_64 = 0x1,
|
||||
NGAP_PAGING_DRX_128 = 0x2,
|
||||
NGAP_PAGING_DRX_256 = 0x3
|
||||
} ngap_paging_drx_t;
|
||||
#define NGAP_MAX_NO_TAI_PAGING 16 // 9.2.4.1 3GPP TS 38.413
|
||||
|
||||
/* Lower value codepoint
|
||||
* indicates higher priority.
|
||||
*/
|
||||
typedef enum ngap_paging_priority_s {
|
||||
NGAP_PAGING_PRIO_LEVEL1 = 0,
|
||||
NGAP_PAGING_PRIO_LEVEL2 = 1,
|
||||
NGAP_PAGING_PRIO_LEVEL3 = 2,
|
||||
NGAP_PAGING_PRIO_LEVEL4 = 3,
|
||||
NGAP_PAGING_PRIO_LEVEL5 = 4,
|
||||
NGAP_PAGING_PRIO_LEVEL6 = 5,
|
||||
NGAP_PAGING_PRIO_LEVEL7 = 6,
|
||||
NGAP_PAGING_PRIO_LEVEL8 = 7
|
||||
} ngap_paging_priority_t;
|
||||
/* Paging DRX values (3GPP TS 38.413) */
|
||||
#define FOREACH_PAGING_DRX(DRX_DEF) \
|
||||
DRX_DEF(NGAP_PAGING_DRX_32, 0x0) \
|
||||
DRX_DEF(NGAP_PAGING_DRX_64, 0x1) \
|
||||
DRX_DEF(NGAP_PAGING_DRX_128, 0x2) \
|
||||
DRX_DEF(NGAP_PAGING_DRX_256, 0x3)
|
||||
|
||||
typedef enum ngap_cn_domain_s {
|
||||
NGAP_CN_DOMAIN_PS = 1,
|
||||
NGAP_CN_DOMAIN_CS = 2
|
||||
} ngap_cn_domain_t;
|
||||
/* Lower value codepoint indicates higher priority (3GPP TS 38.413) */
|
||||
#define FOREACH_PAGING_PRIORITY(PRIO_DEF) \
|
||||
PRIO_DEF(NGAP_PAGING_PRIO_LEVEL1, 0) \
|
||||
PRIO_DEF(NGAP_PAGING_PRIO_LEVEL2, 1) \
|
||||
PRIO_DEF(NGAP_PAGING_PRIO_LEVEL3, 2) \
|
||||
PRIO_DEF(NGAP_PAGING_PRIO_LEVEL4, 3) \
|
||||
PRIO_DEF(NGAP_PAGING_PRIO_LEVEL5, 4) \
|
||||
PRIO_DEF(NGAP_PAGING_PRIO_LEVEL6, 5) \
|
||||
PRIO_DEF(NGAP_PAGING_PRIO_LEVEL7, 6) \
|
||||
PRIO_DEF(NGAP_PAGING_PRIO_LEVEL8, 7)
|
||||
|
||||
/* Paging Origin (9.3.3.22 of 3GPP TS 38.413) */
|
||||
#define FOREACH_PAGING_ORIGIN(ORIGIN_DEF) ORIGIN_DEF(NGAP_PAGING_ORIGIN_NON_3GPP, 0)
|
||||
|
||||
static const text_info_t paging_drx_text[] = {FOREACH_PAGING_DRX(TO_TEXT)};
|
||||
|
||||
static const text_info_t paging_prio_text[] = {FOREACH_PAGING_PRIORITY(TO_TEXT)};
|
||||
|
||||
static const text_info_t paging_origin_text[] = {FOREACH_PAGING_ORIGIN(TO_TEXT)};
|
||||
|
||||
typedef enum { FOREACH_PAGING_DRX(TO_ENUM) } ngap_paging_drx_t;
|
||||
|
||||
typedef enum { FOREACH_PAGING_PRIORITY(TO_ENUM) } ngap_paging_priority_t;
|
||||
|
||||
typedef enum { FOREACH_PAGING_ORIGIN(TO_ENUM) } ngap_paging_origin_t;
|
||||
|
||||
typedef struct ngap_net_ip_address_s {
|
||||
unsigned ipv4:1;
|
||||
@@ -144,25 +150,26 @@ typedef struct ngap_security_capabilities_s {
|
||||
uint16_t eUTRAintegrity_algorithms;
|
||||
} ngap_security_capabilities_t;
|
||||
|
||||
/* Provides the establishment cause for the RRC connection request as provided
|
||||
* by the upper layers. W.r.t. the cause value names: highPriorityAccess
|
||||
* concerns AC11..AC15, ‘mt Estands for ‘Mobile Terminating Eand ‘mo Efor
|
||||
* 'Mobile Originating'. Defined in TS 36.331.
|
||||
*/
|
||||
typedef enum ngap_rrc_establishment_cause_e {
|
||||
NGAP_RRC_CAUSE_EMERGENCY = 0x0,
|
||||
NGAP_RRC_CAUSE_HIGH_PRIO_ACCESS = 0x1,
|
||||
NGAP_RRC_CAUSE_MT_ACCESS = 0x2,
|
||||
NGAP_RRC_CAUSE_MO_SIGNALLING = 0x3,
|
||||
NGAP_RRC_CAUSE_MO_DATA = 0x4,
|
||||
NGAP_RRC_CAUSE_MO_VOICECALL = 0x5,
|
||||
NGAP_RRC_CAUSE_MO_VIDEOCALL = 0x6,
|
||||
NGAP_RRC_CAUSE_MO_SMS = 0x7,
|
||||
NGAP_RRC_CAUSE_MPS_PRIORITY_ACCESS = 0x8,
|
||||
NGAP_RRC_CAUSE_MCS_PRIORITY_ACCESS = 0x9,
|
||||
NGAP_RRC_CAUSE_NOTAVAILABLE = 0x10,
|
||||
NGAP_RRC_CAUSE_LAST
|
||||
} ngap_rrc_establishment_cause_t;
|
||||
/** @brief RRC Establishment Cause (9.3.1.111 of 3GPP TS 38.413)
|
||||
* Indicates the reason for RRC Connection Establishment/Resume as received from the UE.
|
||||
* The notAvailable value is used when re-establishing/resuming an RRC connection and the
|
||||
* cause value from the UE does not map to any other value. */
|
||||
#define FOREACH_RRC_ESTABLISHMENT_CAUSE(CAUSE_DEF) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_EMERGENCY, 0) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_HIGH_PRIO_ACCESS, 1) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MT_ACCESS, 2) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MO_SIGNALLING, 3) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MO_DATA, 4) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MO_VOICECALL, 5) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MO_VIDEOCALL, 6) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MO_SMS, 7) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MPS_PRIORITY_ACCESS, 8) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MCS_PRIORITY_ACCESS, 9) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_NOTAVAILABLE, 10) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_MO_EXCEPTION_DATA, 11) \
|
||||
CAUSE_DEF(NGAP_RRC_CAUSE_LAST, 12)
|
||||
|
||||
typedef enum { FOREACH_RRC_ESTABLISHMENT_CAUSE(TO_ENUM) } ngap_rrc_establishment_cause_t;
|
||||
|
||||
typedef struct fiveg_s_tmsi_s {
|
||||
uint16_t amf_set_id;
|
||||
@@ -170,10 +177,6 @@ typedef struct fiveg_s_tmsi_s {
|
||||
uint32_t m_tmsi;
|
||||
} fiveg_s_tmsi_t;
|
||||
|
||||
typedef struct ngap_ue_paging_identity_s {
|
||||
fiveg_s_tmsi_t s_tmsi;
|
||||
} ngap_ue_paging_identity_t;
|
||||
|
||||
typedef enum ngap_ue_identities_presenceMask_e {
|
||||
NGAP_UE_IDENTITIES_FiveG_s_tmsi = 1 << 1,
|
||||
NGAP_UE_IDENTITIES_guami = 1 << 2,
|
||||
@@ -243,15 +246,16 @@ typedef struct pdusession_modify_s {
|
||||
qos_flow_addmod_response_item_t qos[MAX_QOS_FLOWS];
|
||||
} pdusession_modify_t;
|
||||
|
||||
/* Cause (9.3.1.2 of 3GPP TS 38.413) */
|
||||
typedef enum ngap_cause_group_e {
|
||||
NGAP_CAUSE_NOTHING, /* No components present */
|
||||
NGAP_CAUSE_RADIO_NETWORK,
|
||||
NGAP_CAUSE_TRANSPORT,
|
||||
NGAP_CAUSE_NAS,
|
||||
NGAP_CAUSE_PROTOCOL,
|
||||
NGAP_CAUSE_MISC,
|
||||
} ngap_cause_group_t;
|
||||
/* Cause Group (9.3.1.2 of 3GPP TS 38.413) */
|
||||
#define FOREACH_CAUSE_GROUP(CAUSE_DEF) \
|
||||
CAUSE_DEF(NGAP_CAUSE_NOTHING, 0) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK, 1) \
|
||||
CAUSE_DEF(NGAP_CAUSE_TRANSPORT, 2) \
|
||||
CAUSE_DEF(NGAP_CAUSE_NAS, 3) \
|
||||
CAUSE_DEF(NGAP_CAUSE_PROTOCOL, 4) \
|
||||
CAUSE_DEF(NGAP_CAUSE_MISC, 5)
|
||||
|
||||
typedef enum { FOREACH_CAUSE_GROUP(TO_ENUM) } ngap_cause_group_t;
|
||||
|
||||
/* Cause (9.3.1.2 of 3GPP TS 38.413) */
|
||||
typedef struct ngap_cause_s {
|
||||
@@ -259,73 +263,74 @@ typedef struct ngap_cause_s {
|
||||
uint8_t value;
|
||||
} ngap_cause_t;
|
||||
|
||||
typedef enum ngap_Cause_radio_network_e {
|
||||
NGAP_CAUSE_RADIO_NETWORK_UNSPECIFIED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_TXNRELOCOVERALL_EXPIRY,
|
||||
NGAP_CAUSE_RADIO_NETWORK_SUCCESSFUL_HANDOVER,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_5GC_GENERATED_REASON,
|
||||
NGAP_CAUSE_RADIO_NETWORK_HANDOVER_CANCELLED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_PARTIAL_HANDOVER,
|
||||
NGAP_CAUSE_RADIO_NETWORK_HO_FAILURE_IN_TARGET_5GC_NGRAN_NODE_OR_TARGET_SYSTEM,
|
||||
NGAP_CAUSE_RADIO_NETWORK_HO_TARGET_NOT_ALLOWED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_TNGRELOCOVERALL_EXPIRY,
|
||||
NGAP_CAUSE_RADIO_NETWORK_TNGRELOCPREP_EXPIRY,
|
||||
NGAP_CAUSE_RADIO_NETWORK_CELL_NOT_AVAILABLE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_TARGETID,
|
||||
NGAP_CAUSE_RADIO_NETWORK_NO_RADIO_RESOURCES_AVAILABLE_IN_TARGET_CELL,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_LOCAL_UE_NGAP_ID,
|
||||
NGAP_CAUSE_RADIO_NETWORK_INCONSISTENT_REMOTE_UE_NGAP_ID,
|
||||
NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON,
|
||||
NGAP_CAUSE_RADIO_NETWORK_TIME_CRITICAL_HANDOVER,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RESOURCE_OPTIMISATION_HANDOVER,
|
||||
NGAP_CAUSE_RADIO_NETWORK_REDUCE_LOAD_IN_SERVING_CELL,
|
||||
NGAP_CAUSE_RADIO_NETWORK_USER_INACTIVITY,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RADIO_RESOURCES_NOT_AVAILABLE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_INVALID_QOS_COMBINATION,
|
||||
NGAP_CAUSE_RADIO_NETWORK_FAILURE_IN_RADIO_INTERFACE_PROCEDURE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_INTERACTION_WITH_OTHER_PROCEDURE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_QOS_FLOW_ID,
|
||||
NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES,
|
||||
NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_QOS_FLOW_ID_INSTANCES,
|
||||
NGAP_CAUSE_RADIO_NETWORK_ENCRYPTION_AND_OR_INTEGRITY_PROTECTION_ALGORITHMS_NOT_SUPPORTED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_NG_INTRA_SYSTEM_HANDOVER_TRIGGERED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_NG_INTER_SYSTEM_HANDOVER_TRIGGERED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_XN_HANDOVER_TRIGGERED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_NOT_SUPPORTED_5QI_VALUE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UE_CONTEXT_TRANSFER,
|
||||
NGAP_CAUSE_RADIO_NETWORK_IMS_VOICE_EPS_FALLBACK_OR_RAT_FALLBACK_TRIGGERED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UP_INTEGRITY_PROTECTION_NOT_POSSIBLE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UP_CONFIDENTIALITY_PROTECTION_NOT_POSSIBLE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_SLICE_NOT_SUPPORTED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UE_IN_RRC_INACTIVE_STATE_NOT_REACHABLE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_REDIRECTION,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_UE_MAX_INTEGRITY_PROTECTED_DATA_RATE_REASON,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_CN_DETECTED_MOBILITY,
|
||||
NGAP_CAUSE_RADIO_NETWORK_N26_INTERFACE_NOT_AVAILABLE,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_PRE_EMPTION,
|
||||
NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_LOCATION_REPORTING_REFERENCE_ID_INSTANCES,
|
||||
NGAP_CAUSE_RADIO_NETWORK_RSN_NOT_AVAILABLE_FOR_THE_UP,
|
||||
NGAP_CAUSE_RADIO_NETWORK_NPN_ACCESS_DENIED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_CAG_ONLY_ACCESS_DENIED,
|
||||
NGAP_CAUSE_RADIO_NETWORK_INSUFFICIENT_UE_CAPABILITIES
|
||||
} ngap_cause_radio_network_t;
|
||||
/* Radio Network Cause (9.3.1.2 of 3GPP TS 38.413) */
|
||||
#define FOREACH_CAUSE_RADIO_NETWORK(CAUSE_DEF) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UNSPECIFIED, 0) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_TXNRELOCOVERALL_EXPIRY, 1) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_SUCCESSFUL_HANDOVER, 2) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON, 3) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_5GC_GENERATED_REASON, 4) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_HANDOVER_CANCELLED, 5) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_PARTIAL_HANDOVER, 6) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_HO_FAILURE_IN_TARGET_5GC_NGRAN_NODE_OR_TARGET_SYSTEM, 7) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_HO_TARGET_NOT_ALLOWED, 8) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_TNGRELOCOVERALL_EXPIRY, 9) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_TNGRELOCPREP_EXPIRY, 10) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_CELL_NOT_AVAILABLE, 11) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_TARGETID, 12) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_NO_RADIO_RESOURCES_AVAILABLE_IN_TARGET_CELL, 13) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_LOCAL_UE_NGAP_ID, 14) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_INCONSISTENT_REMOTE_UE_NGAP_ID, 15) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON, 16) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_TIME_CRITICAL_HANDOVER, 17) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RESOURCE_OPTIMISATION_HANDOVER, 18) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_REDUCE_LOAD_IN_SERVING_CELL, 19) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_USER_INACTIVITY, 20) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST, 21) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RADIO_RESOURCES_NOT_AVAILABLE, 22) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_INVALID_QOS_COMBINATION, 23) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_FAILURE_IN_RADIO_INTERFACE_PROCEDURE, 24) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_INTERACTION_WITH_OTHER_PROCEDURE, 25) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID, 26) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_QOS_FLOW_ID, 27) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES, 28) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_QOS_FLOW_ID_INSTANCES, 29) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_ENCRYPTION_AND_OR_INTEGRITY_PROTECTION_ALGORITHMS_NOT_SUPPORTED, 30) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_NG_INTRA_SYSTEM_HANDOVER_TRIGGERED, 31) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_NG_INTER_SYSTEM_HANDOVER_TRIGGERED, 32) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_XN_HANDOVER_TRIGGERED, 33) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_NOT_SUPPORTED_5QI_VALUE, 34) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UE_CONTEXT_TRANSFER, 35) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_IMS_VOICE_EPS_FALLBACK_OR_RAT_FALLBACK_TRIGGERED, 36) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UP_INTEGRITY_PROTECTION_NOT_POSSIBLE, 37) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UP_CONFIDENTIALITY_PROTECTION_NOT_POSSIBLE, 38) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_SLICE_NOT_SUPPORTED, 39) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UE_IN_RRC_INACTIVE_STATE_NOT_REACHABLE, 40) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_REDIRECTION, 41) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE, 42) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_UE_MAX_INTEGRITY_PROTECTED_DATA_RATE_REASON, 43) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_CN_DETECTED_MOBILITY, 44) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_N26_INTERFACE_NOT_AVAILABLE, 45) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_PRE_EMPTION, 46) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_LOCATION_REPORTING_REFERENCE_ID_INSTANCES, 47) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_RSN_NOT_AVAILABLE_FOR_THE_UP, 48) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_NPN_ACCESS_DENIED, 49) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_CAG_ONLY_ACCESS_DENIED, 50) \
|
||||
CAUSE_DEF(NGAP_CAUSE_RADIO_NETWORK_INSUFFICIENT_UE_CAPABILITIES, 51)
|
||||
|
||||
/**
|
||||
* NGAP protocol cause values as per 9.3.1.2 `Cause` section in 3GPP TS 38.413.
|
||||
*/
|
||||
typedef enum ngap_cause_protocol_e {
|
||||
NGAP_CAUSE_PROTOCOL_TRANSFER_SYNTAX_ERROR,
|
||||
NGAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_REJECT,
|
||||
NGAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_IGNORE,
|
||||
NGAP_CAUSE_PROTOCOL_MSG_NOT_COMPATIBLE_WITH_RECEIVER_STATE,
|
||||
NGAP_CAUSE_PROTOCOL_SEMANTIC_ERROR,
|
||||
NGAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_FCM,
|
||||
NGAP_CAUSE_PROTOCOL_UNSPECIFIED
|
||||
} ngap_cause_protocol_t;
|
||||
typedef enum { FOREACH_CAUSE_RADIO_NETWORK(TO_ENUM) } ngap_cause_radio_network_t;
|
||||
|
||||
/** NGAP protocol cause values (9.3.1.2 of 3GPP TS 38.413) */
|
||||
#define FOREACH_CAUSE_PROTOCOL(CAUSE_DEF) \
|
||||
CAUSE_DEF(NGAP_CAUSE_PROTOCOL_TRANSFER_SYNTAX_ERROR, 0) \
|
||||
CAUSE_DEF(NGAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_REJECT, 1) \
|
||||
CAUSE_DEF(NGAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_IGNORE, 2) \
|
||||
CAUSE_DEF(NGAP_CAUSE_PROTOCOL_MSG_NOT_COMPATIBLE_WITH_RECEIVER_STATE, 3) \
|
||||
CAUSE_DEF(NGAP_CAUSE_PROTOCOL_SEMANTIC_ERROR, 4) \
|
||||
CAUSE_DEF(NGAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_FCM, 5) \
|
||||
CAUSE_DEF(NGAP_CAUSE_PROTOCOL_UNSPECIFIED, 6)
|
||||
|
||||
typedef enum { FOREACH_CAUSE_PROTOCOL(TO_ENUM) } ngap_cause_protocol_t;
|
||||
|
||||
typedef struct pdusession_failed_s {
|
||||
/* Unique pdusession_id for the UE. */
|
||||
@@ -352,7 +357,11 @@ typedef struct {
|
||||
} ngap_plmn_t;
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
// gNB application layer -> NGAP messages
|
||||
|
||||
/** @brief NG SETUP REQUEST message (9.2.6.1 of 3GPP TS 38.413)
|
||||
* This message is sent by the NG-RAN node to transfer application layer information
|
||||
* for an NG-C interface instance.
|
||||
* Direction: NG-RAN node -> AMF */
|
||||
typedef struct ngap_register_gnb_req_s {
|
||||
/* Unique gNB_id to identify the gNB within EPC.
|
||||
* For macro gNB ids this field should be 20 bits long.
|
||||
@@ -790,29 +799,6 @@ typedef struct ngap_initial_context_setup_req_s {
|
||||
byte_array_t nas_pdu;
|
||||
} ngap_initial_context_setup_req_t;
|
||||
|
||||
|
||||
typedef struct ngap_paging_ind_s {
|
||||
/* UE paging identity */
|
||||
ngap_ue_paging_identity_t ue_paging_identity;
|
||||
|
||||
/* Indicates origin of paging */
|
||||
ngap_cn_domain_t cn_domain;
|
||||
|
||||
/* PLMN_identity in TAI of Paging*/
|
||||
plmn_id_t plmn_identity[NGAP_MAX_NO_TAI_PAGING];
|
||||
|
||||
/* TAC in TAIList of Paging*/
|
||||
int16_t tac[NGAP_MAX_NO_TAI_PAGING];
|
||||
|
||||
/* size of TAIList*/
|
||||
int16_t tai_size;
|
||||
|
||||
/* Optional fields */
|
||||
ngap_paging_drx_t paging_drx;
|
||||
|
||||
ngap_paging_priority_t paging_priority;
|
||||
} ngap_paging_ind_t;
|
||||
|
||||
typedef struct ngap_pdusession_setup_req_s {
|
||||
/* UE id for initial connection to NGAP */
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
@@ -939,6 +925,45 @@ typedef struct ngap_pdusession_release_resp_s {
|
||||
pdusession_release_t pdusession_release[NGAP_MAX_PDU_SESSION];
|
||||
} ngap_pdusession_release_resp_t;
|
||||
|
||||
/** NG PAGING PROCEDURES (9.2.4. of 3GPP TS 38.413) */
|
||||
|
||||
typedef struct {
|
||||
plmn_id_t plmn;
|
||||
uint16_t tac;
|
||||
} nr_tai_t;
|
||||
|
||||
typedef struct ngap_ue_paging_identity_s {
|
||||
fiveg_s_tmsi_t s_tmsi;
|
||||
} ngap_ue_paging_identity_t;
|
||||
|
||||
/** 9.3.1.72 Paging Attempt Information (3GPP TS 38.413) */
|
||||
typedef struct {
|
||||
/* Paging Attempt Count */
|
||||
uint8_t paging_attempt_count;
|
||||
/* Intended Number of Paging Attempts */
|
||||
uint8_t intended_paging_attempts;
|
||||
} ngap_paging_attempt_info_t;
|
||||
|
||||
/** 9.2.4.1 3GPP TS 38.413 */
|
||||
typedef struct {
|
||||
/* UE paging identity */
|
||||
ngap_ue_paging_identity_t ue_paging_identity;
|
||||
|
||||
/* TAI List for Paging */
|
||||
nr_tai_t tai_list[NGAP_MAX_NO_TAI_PAGING];
|
||||
int16_t n_tai;
|
||||
|
||||
/* Optional fields */
|
||||
ngap_paging_drx_t *paging_drx;
|
||||
ngap_paging_priority_t *paging_priority;
|
||||
/* UE Radio Capability for Paging (optional) */
|
||||
byte_array_t *ue_radio_capability;
|
||||
/* Paging Origin (optional) */
|
||||
ngap_paging_origin_t *origin;
|
||||
/* Assistance Data for Paging (optional) */
|
||||
ngap_paging_attempt_info_t *paging_attempt_info;
|
||||
} ngap_paging_ind_t;
|
||||
|
||||
/** 9.2.3.14 Uplink RAN Status Transfer (3GPP TS 38.413)
|
||||
* COUNT value used for both UL and DL PDCP SN + HFN (12-bit or 18-bit SN) */
|
||||
|
||||
|
||||
@@ -10,7 +10,3 @@ target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR})
|
||||
if(ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
target_compile_definitions(e1ap PRIVATE E1AP_LOG_ERRORS)
|
||||
endif()
|
||||
|
||||
@@ -9,3 +9,7 @@ target_include_directories(e1ap_lib PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
target_compile_definitions(e1ap_lib PRIVATE ENABLE_TESTS)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -96,12 +96,12 @@ static bool e1_decode_security_info(security_information_t *out, const E1AP_Secu
|
||||
|
||||
// User Plane Security Keys (M) (9.3.1.32)
|
||||
// Encryption Key (M)
|
||||
_E1_EQ_CHECK_INT((int)in->uPSecuritykey.encryptionKey.size, E1AP_SECURITY_KEY_SIZE);
|
||||
_EQ_CHECK_INT((int)in->uPSecuritykey.encryptionKey.size, E1AP_SECURITY_KEY_SIZE);
|
||||
memcpy(out->encryptionKey, in->uPSecuritykey.encryptionKey.buf, in->uPSecuritykey.encryptionKey.size);
|
||||
// Integrity Protection Key (O)
|
||||
if (in->uPSecuritykey.integrityProtectionKey) {
|
||||
E1AP_IntegrityProtectionKey_t *ipKey = in->uPSecuritykey.integrityProtectionKey;
|
||||
_E1_EQ_CHECK_INT((int)ipKey->size, E1AP_SECURITY_KEY_SIZE);
|
||||
_EQ_CHECK_INT((int)ipKey->size, E1AP_SECURITY_KEY_SIZE);
|
||||
memcpy(out->integrityProtectionKey, ipKey->buf, E1AP_SECURITY_KEY_SIZE);
|
||||
} else {
|
||||
memset(out->integrityProtectionKey, 0, E1AP_SECURITY_KEY_SIZE);
|
||||
@@ -132,7 +132,7 @@ static bool e1_decode_up_tnl_info(UP_TL_information_t *out, const E1AP_UP_TNL_In
|
||||
// GTP Tunnel
|
||||
struct E1AP_GTPTunnel *gTPTunnel = in->choice.gTPTunnel;
|
||||
AssertFatal(gTPTunnel != NULL, "item->nG_UL_UP_TNL_Information.choice.gTPTunnel is a mandatory IE");
|
||||
_E1_EQ_CHECK_INT(in->present, E1AP_UP_TNL_Information_PR_gTPTunnel);
|
||||
_EQ_CHECK_INT(in->present, E1AP_UP_TNL_Information_PR_gTPTunnel);
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, out->tlAddress);
|
||||
// GTP-TEID
|
||||
OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, out->teId);
|
||||
@@ -178,12 +178,12 @@ static bool e1_decode_pdcp_config(bearer_context_pdcp_config_t *out, const E1AP_
|
||||
*/
|
||||
static bool eq_pdcp_config(const bearer_context_pdcp_config_t *a, const bearer_context_pdcp_config_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->pDCP_SN_Size_UL, b->pDCP_SN_Size_UL);
|
||||
_E1_EQ_CHECK_LONG(a->pDCP_SN_Size_DL, b->pDCP_SN_Size_DL);
|
||||
_E1_EQ_CHECK_LONG(a->rLC_Mode, b->rLC_Mode);
|
||||
_E1_EQ_CHECK_LONG(a->reorderingTimer, b->reorderingTimer);
|
||||
_E1_EQ_CHECK_LONG(a->discardTimer, b->discardTimer);
|
||||
_E1_EQ_CHECK_INT(a->pDCP_Reestablishment, b->pDCP_Reestablishment);
|
||||
_EQ_CHECK_LONG(a->pDCP_SN_Size_UL, b->pDCP_SN_Size_UL);
|
||||
_EQ_CHECK_LONG(a->pDCP_SN_Size_DL, b->pDCP_SN_Size_DL);
|
||||
_EQ_CHECK_LONG(a->rLC_Mode, b->rLC_Mode);
|
||||
_EQ_CHECK_LONG(a->reorderingTimer, b->reorderingTimer);
|
||||
_EQ_CHECK_LONG(a->discardTimer, b->discardTimer);
|
||||
_EQ_CHECK_INT(a->pDCP_Reestablishment, b->pDCP_Reestablishment);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -211,9 +211,9 @@ static bool e1_decode_sdap_config(bearer_context_sdap_config_t *out, const E1AP_
|
||||
*/
|
||||
static bool eq_sdap_config(const bearer_context_sdap_config_t *a, const bearer_context_sdap_config_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->defaultDRB, b->defaultDRB);
|
||||
_E1_EQ_CHECK_INT(a->sDAP_Header_UL, b->sDAP_Header_UL);
|
||||
_E1_EQ_CHECK_INT(a->sDAP_Header_DL, b->sDAP_Header_DL);
|
||||
_EQ_CHECK_LONG(a->defaultDRB, b->defaultDRB);
|
||||
_EQ_CHECK_INT(a->sDAP_Header_UL, b->sDAP_Header_UL);
|
||||
_EQ_CHECK_INT(a->sDAP_Header_DL, b->sDAP_Header_DL);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -285,22 +285,22 @@ bool e1_decode_qos_flow_to_setup(qos_flow_to_setup_t *out, const E1AP_QoS_Flow_Q
|
||||
*/
|
||||
static bool eq_qos_flow(const qos_flow_to_setup_t *a, const qos_flow_to_setup_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->qfi, b->qfi);
|
||||
_EQ_CHECK_LONG(a->qfi, b->qfi);
|
||||
const ngran_allocation_retention_priority_t *arp_a = &a->qos_params.alloc_reten_priority;
|
||||
const ngran_allocation_retention_priority_t *arp_b = &b->qos_params.alloc_reten_priority;
|
||||
_E1_EQ_CHECK_INT(arp_a->preemption_capability, arp_b->preemption_capability);
|
||||
_E1_EQ_CHECK_INT(arp_a->preemption_vulnerability, arp_b->preemption_vulnerability);
|
||||
_E1_EQ_CHECK_INT(arp_a->priority_level, arp_b->priority_level);
|
||||
_EQ_CHECK_INT(arp_a->preemption_capability, arp_b->preemption_capability);
|
||||
_EQ_CHECK_INT(arp_a->preemption_vulnerability, arp_b->preemption_vulnerability);
|
||||
_EQ_CHECK_INT(arp_a->priority_level, arp_b->priority_level);
|
||||
const qos_characteristics_t *qos_a = &a->qos_params.qos_characteristics;
|
||||
const qos_characteristics_t *qos_b = &b->qos_params.qos_characteristics;
|
||||
_E1_EQ_CHECK_INT(qos_a->qos_type, qos_b->qos_type);
|
||||
_E1_EQ_CHECK_INT(qos_a->dynamic.fiveqi, qos_b->dynamic.fiveqi);
|
||||
_E1_EQ_CHECK_INT(qos_a->dynamic.packet_delay_budget, qos_b->dynamic.packet_delay_budget);
|
||||
_E1_EQ_CHECK_INT(qos_a->dynamic.packet_error_rate.per_exponent, qos_b->dynamic.packet_error_rate.per_exponent);
|
||||
_E1_EQ_CHECK_INT(qos_a->dynamic.packet_error_rate.per_scalar, qos_b->dynamic.packet_error_rate.per_scalar);
|
||||
_E1_EQ_CHECK_INT(qos_a->dynamic.qos_priority_level, qos_b->dynamic.qos_priority_level);
|
||||
_E1_EQ_CHECK_INT(qos_a->non_dynamic.fiveqi, qos_b->non_dynamic.fiveqi);
|
||||
_E1_EQ_CHECK_INT(qos_a->non_dynamic.qos_priority_level, qos_b->non_dynamic.qos_priority_level);
|
||||
_EQ_CHECK_INT(qos_a->qos_type, qos_b->qos_type);
|
||||
_EQ_CHECK_INT(qos_a->dynamic.fiveqi, qos_b->dynamic.fiveqi);
|
||||
_EQ_CHECK_INT(qos_a->dynamic.packet_delay_budget, qos_b->dynamic.packet_delay_budget);
|
||||
_EQ_CHECK_INT(qos_a->dynamic.packet_error_rate.per_exponent, qos_b->dynamic.packet_error_rate.per_exponent);
|
||||
_EQ_CHECK_INT(qos_a->dynamic.packet_error_rate.per_scalar, qos_b->dynamic.packet_error_rate.per_scalar);
|
||||
_EQ_CHECK_INT(qos_a->dynamic.qos_priority_level, qos_b->dynamic.qos_priority_level);
|
||||
_EQ_CHECK_INT(qos_a->non_dynamic.fiveqi, qos_b->non_dynamic.fiveqi);
|
||||
_EQ_CHECK_INT(qos_a->non_dynamic.qos_priority_level, qos_b->non_dynamic.qos_priority_level);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -386,10 +386,10 @@ static e1_pdcp_status_info_t decode_pdcp_status_info(const E1AP_PDCP_SN_Status_I
|
||||
|
||||
static bool eq_pdcp_info(const e1_pdcp_status_info_t *a, const e1_pdcp_status_info_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(a->dl_count.hfn, b->dl_count.hfn);
|
||||
_E1_EQ_CHECK_INT(a->dl_count.sn, b->dl_count.sn);
|
||||
_E1_EQ_CHECK_INT(a->ul_count.hfn, b->ul_count.hfn);
|
||||
_E1_EQ_CHECK_INT(a->ul_count.sn, b->ul_count.sn);
|
||||
_EQ_CHECK_INT(a->dl_count.hfn, b->dl_count.hfn);
|
||||
_EQ_CHECK_INT(a->dl_count.sn, b->dl_count.sn);
|
||||
_EQ_CHECK_INT(a->ul_count.hfn, b->ul_count.hfn);
|
||||
_EQ_CHECK_INT(a->ul_count.sn, b->ul_count.sn);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -398,12 +398,12 @@ static bool eq_pdcp_info(const e1_pdcp_status_info_t *a, const e1_pdcp_status_in
|
||||
*/
|
||||
static bool eq_drb_to_setup(const DRB_nGRAN_to_setup_t *a, const DRB_nGRAN_to_setup_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->id, b->id);
|
||||
_E1_EQ_CHECK_INT(a->numCellGroups, b->numCellGroups);
|
||||
_EQ_CHECK_LONG(a->id, b->id);
|
||||
_EQ_CHECK_INT(a->numCellGroups, b->numCellGroups);
|
||||
for (int i = 0; i < a->numCellGroups; i++) {
|
||||
_E1_EQ_CHECK_INT(a->cellGroupList[i], b->cellGroupList[i]);
|
||||
_EQ_CHECK_INT(a->cellGroupList[i], b->cellGroupList[i]);
|
||||
}
|
||||
_E1_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup);
|
||||
_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup);
|
||||
for (int i = 0; i < a->numQosFlow2Setup; i++) {
|
||||
if (!eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]))
|
||||
return false;
|
||||
@@ -474,13 +474,13 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A
|
||||
PRINT_ERROR("Missing mandatory IE item->nG_UL_UP_TNL_Information.choice.gTPTunnel\n");
|
||||
return false;
|
||||
}
|
||||
_E1_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel);
|
||||
_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel);
|
||||
CHECK_E1AP_DEC(e1_decode_up_tnl_info(&out->UP_TL_information, &item->nG_UL_UP_TNL_Information));
|
||||
/* DRB To Setup List ( > 1 item ) */
|
||||
E1AP_DRB_To_Setup_List_NG_RAN_t *drb2SetupList = &item->dRB_To_Setup_List_NG_RAN;
|
||||
_E1_EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0);
|
||||
EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0);
|
||||
out->numDRB2Setup = drb2SetupList->list.count;
|
||||
_E1_EQ_CHECK_INT(out->numDRB2Setup, 1); // can only handle one DRB per PDU session
|
||||
_EQ_CHECK_INT(out->numDRB2Setup, 1); // can only handle one DRB per PDU session
|
||||
for (int j = 0; j < drb2SetupList->list.count; j++) {
|
||||
DRB_nGRAN_to_setup_t *drb = out->DRBnGRanList + j;
|
||||
E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j];
|
||||
@@ -492,7 +492,7 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A
|
||||
CHECK_E1AP_DEC(e1_decode_pdcp_config(&drb->pdcp_config, &drb2Setup->pDCP_Configuration));
|
||||
// Cell Group Information (M)
|
||||
E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information;
|
||||
_E1_EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0);
|
||||
EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0);
|
||||
drb->numCellGroups = cellGroupList->list.count;
|
||||
for (int k = 0; k < cellGroupList->list.count; k++) {
|
||||
E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k];
|
||||
@@ -542,8 +542,8 @@ void free_pdu_session_to_setup_item(const pdu_session_to_setup_t *msg)
|
||||
/** @brief Equality check for UP Transport Layer Information (3GPP TS 38.463 9.3.2.1)*/
|
||||
static bool eq_up_tl_info(const UP_TL_information_t *a, const UP_TL_information_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(a->tlAddress, b->tlAddress);
|
||||
_E1_EQ_CHECK_INT(a->teId, b->teId);
|
||||
_EQ_CHECK_INT(a->tlAddress, b->tlAddress);
|
||||
_EQ_CHECK_INT(a->teId, b->teId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -552,17 +552,17 @@ static bool eq_up_tl_info(const UP_TL_information_t *a, const UP_TL_information_
|
||||
*/
|
||||
static bool eq_pdu_session_item(const pdu_session_to_setup_t *a, const pdu_session_to_setup_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->sessionId, b->sessionId);
|
||||
_E1_EQ_CHECK_LONG(a->sessionType, b->sessionType);
|
||||
_EQ_CHECK_LONG(a->sessionId, b->sessionId);
|
||||
_EQ_CHECK_LONG(a->sessionType, b->sessionType);
|
||||
eq_up_tl_info(&a->UP_TL_information, &b->UP_TL_information);
|
||||
_E1_EQ_CHECK_INT(a->numDRB2Setup, b->numDRB2Setup);
|
||||
_EQ_CHECK_INT(a->numDRB2Setup, b->numDRB2Setup);
|
||||
for (int i = 0; i < a->numDRB2Setup; i++)
|
||||
if (!eq_drb_to_setup(&a->DRBnGRanList[i], &b->DRBnGRanList[i]))
|
||||
return false;
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer);
|
||||
if (a->inactivityTimer && b->inactivityTimer)
|
||||
_E1_EQ_CHECK_INT(*a->inactivityTimer, *b->inactivityTimer);
|
||||
_E1_EQ_CHECK_OPTIONAL_IE(a, b, dlAggregateMaxBitRate, _E1_EQ_CHECK_LONG);
|
||||
_EQ_CHECK_INT(*a->inactivityTimer, *b->inactivityTimer);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, dlAggregateMaxBitRate, _EQ_CHECK_LONG);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -660,9 +660,9 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
|
||||
DevAssert(pdu != NULL);
|
||||
|
||||
// Check message type
|
||||
_E1_EQ_CHECK_INT(pdu->present,E1AP_E1AP_PDU_PR_initiatingMessage);
|
||||
_E1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup);
|
||||
_E1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_initiatingMessage);
|
||||
_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup);
|
||||
_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest);
|
||||
|
||||
const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest;
|
||||
E1AP_BearerContextSetupRequestIEs_t *ie;
|
||||
@@ -681,22 +681,22 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
|
||||
AssertFatal(ie != NULL, "in->protocolIEs.list.array[i] shall not be null");
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_SecurityInformation:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation);
|
||||
CHECK_E1AP_DEC(e1_decode_security_info(&out->secInfo, &ie->value.choice.SecurityInformation));
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_BitRate);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_BitRate);
|
||||
asn_INTEGER2long(&ie->value.choice.BitRate, &out->ueDlAggMaxBitRate);
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_Serving_PLMN:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity);
|
||||
PLMNID_TO_MCC_MNC(&ie->value.choice.PLMN_Identity,
|
||||
out->servingPLMNid.mcc,
|
||||
out->servingPLMNid.mnc,
|
||||
@@ -704,7 +704,7 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest);
|
||||
E1AP_System_BearerContextSetupRequest_t *System_BearerContextSetupRequest =
|
||||
&ie->value.choice.System_BearerContextSetupRequest;
|
||||
switch (System_BearerContextSetupRequest->present) {
|
||||
@@ -717,8 +717,8 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
|
||||
break;
|
||||
case E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest:
|
||||
// Handle nG-RAN Bearer Context Setup Request
|
||||
_E1_EQ_CHECK_INT(System_BearerContextSetupRequest->present,
|
||||
E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest);
|
||||
_EQ_CHECK_INT(System_BearerContextSetupRequest->present,
|
||||
E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest);
|
||||
AssertFatal(System_BearerContextSetupRequest->choice.nG_RAN_BearerContextSetupRequest != NULL,
|
||||
"System_BearerContextSetupRequest->choice.nG_RAN_BearerContextSetupRequest shall not be null");
|
||||
break;
|
||||
@@ -731,10 +731,9 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
|
||||
(E1AP_ProtocolIE_Container_4932P19_t *)System_BearerContextSetupRequest->choice.nG_RAN_BearerContextSetupRequest;
|
||||
E1AP_NG_RAN_BearerContextSetupRequest_t *msgNGRAN = msgNGRAN_list->list.array[0];
|
||||
// NG-RAN
|
||||
_E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1); // only one RAN is expected
|
||||
_E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List);
|
||||
_E1_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List);
|
||||
_EQ_CHECK_INT(msgNGRAN_list->list.count, 1); // only one RAN is expected
|
||||
_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List);
|
||||
_EQ_CHECK_INT(msgNGRAN->value.present, E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List);
|
||||
// PDU Session Resource To Setup List (9.3.3.2 of 3GPP TS 38.463)
|
||||
E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2SetupList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List;
|
||||
out->numPDUSessions = pdu2SetupList->list.count;
|
||||
@@ -791,18 +790,18 @@ e1ap_bearer_setup_req_t cp_bearer_context_setup_request(const e1ap_bearer_setup_
|
||||
bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1ap_bearer_setup_req_t *b)
|
||||
{
|
||||
// Primitive data types
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_E1_EQ_CHECK_LONG(a->secInfo.cipheringAlgorithm, b->secInfo.cipheringAlgorithm);
|
||||
_E1_EQ_CHECK_LONG(a->secInfo.integrityProtectionAlgorithm, b->secInfo.integrityProtectionAlgorithm);
|
||||
_E1_EQ_CHECK_LONG(a->ueDlAggMaxBitRate, b->ueDlAggMaxBitRate);
|
||||
_E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions);
|
||||
_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_EQ_CHECK_LONG(a->secInfo.cipheringAlgorithm, b->secInfo.cipheringAlgorithm);
|
||||
_EQ_CHECK_LONG(a->secInfo.integrityProtectionAlgorithm, b->secInfo.integrityProtectionAlgorithm);
|
||||
_EQ_CHECK_LONG(a->ueDlAggMaxBitRate, b->ueDlAggMaxBitRate);
|
||||
_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions);
|
||||
// PLMN
|
||||
_E1_EQ_CHECK_INT(a->servingPLMNid.mcc, b->servingPLMNid.mcc);
|
||||
_E1_EQ_CHECK_INT(a->servingPLMNid.mnc, b->servingPLMNid.mnc);
|
||||
_E1_EQ_CHECK_INT(a->servingPLMNid.mnc_digit_length, b->servingPLMNid.mnc_digit_length);
|
||||
_EQ_CHECK_INT(a->servingPLMNid.mcc, b->servingPLMNid.mcc);
|
||||
_EQ_CHECK_INT(a->servingPLMNid.mnc, b->servingPLMNid.mnc);
|
||||
_EQ_CHECK_INT(a->servingPLMNid.mnc_digit_length, b->servingPLMNid.mnc_digit_length);
|
||||
// Security Keys
|
||||
_E1_EQ_CHECK_STR(a->secInfo.encryptionKey, b->secInfo.encryptionKey);
|
||||
_E1_EQ_CHECK_STR(a->secInfo.integrityProtectionKey, b->secInfo.integrityProtectionKey);
|
||||
_EQ_CHECK_STR(a->secInfo.encryptionKey, b->secInfo.encryptionKey);
|
||||
_EQ_CHECK_STR(a->secInfo.integrityProtectionKey, b->secInfo.integrityProtectionKey);
|
||||
// PDU Sessions
|
||||
if (a->numPDUSessions != b->numPDUSessions)
|
||||
return false;
|
||||
@@ -810,10 +809,10 @@ bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1a
|
||||
if (!eq_pdu_session_item(&a->pduSession[i], &b->pduSession[i]))
|
||||
return false;
|
||||
// Check optional IEs
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimerUE);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimerUE);
|
||||
if (a->inactivityTimerUE && b->inactivityTimerUE)
|
||||
_E1_EQ_CHECK_INT(*a->inactivityTimerUE, *b->inactivityTimerUE);
|
||||
_E1_EQ_CHECK_OPTIONAL_IE(a, b, ueDlMaxIPBitRate, _E1_EQ_CHECK_LONG);
|
||||
_EQ_CHECK_INT(*a->inactivityTimerUE, *b->inactivityTimerUE);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, ueDlMaxIPBitRate, _EQ_CHECK_LONG);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -969,9 +968,9 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_response(const e1ap_bearer_setup
|
||||
bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_resp_t *out)
|
||||
{
|
||||
// Check message type
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
_E1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup);
|
||||
_E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup);
|
||||
_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse);
|
||||
|
||||
const E1AP_BearerContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse;
|
||||
E1AP_BearerContextSetupResponseIEs_t *ie;
|
||||
@@ -985,27 +984,27 @@ bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_be
|
||||
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
||||
out->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse);
|
||||
switch (ie->value.choice.System_BearerContextSetupResponse.present) {
|
||||
case E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse: {
|
||||
E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list =
|
||||
(E1AP_ProtocolIE_Container_4932P22_t *)
|
||||
ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse;
|
||||
_E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1);
|
||||
_EQ_CHECK_INT(msgNGRAN_list->list.count, 1);
|
||||
E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0];
|
||||
_E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List);
|
||||
_E1_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List);
|
||||
_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List);
|
||||
_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List);
|
||||
E1AP_PDU_Session_Resource_Setup_List_t *pduSetupList = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List;
|
||||
out->numPDUSessions = pduSetupList->list.count;
|
||||
for (int i = 0; i < pduSetupList->list.count; i++) {
|
||||
@@ -1069,34 +1068,34 @@ e1ap_bearer_setup_resp_t cp_bearer_context_setup_response(const e1ap_bearer_setu
|
||||
bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e1ap_bearer_setup_resp_t *b)
|
||||
{
|
||||
// Check basic members
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions);
|
||||
_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions);
|
||||
// Check PDU Sessions Setup
|
||||
if (a->numPDUSessions != b->numPDUSessions)
|
||||
return false;
|
||||
for (int i = 0; i < a->numPDUSessions; i++) {
|
||||
const pdu_session_setup_t *ps_a = &a->pduSession[i];
|
||||
const pdu_session_setup_t *ps_b = &b->pduSession[i];
|
||||
_E1_EQ_CHECK_LONG(ps_a->id, ps_b->id);
|
||||
_EQ_CHECK_LONG(ps_a->id, ps_b->id);
|
||||
eq_up_tl_info(&ps_a->tl_info, &ps_b->tl_info);
|
||||
_E1_EQ_CHECK_INT(ps_a->numDRBSetup, ps_b->numDRBSetup);
|
||||
_E1_EQ_CHECK_INT(ps_a->numDRBFailed, ps_b->numDRBFailed);
|
||||
_EQ_CHECK_INT(ps_a->numDRBSetup, ps_b->numDRBSetup);
|
||||
_EQ_CHECK_INT(ps_a->numDRBFailed, ps_b->numDRBFailed);
|
||||
// Check DRB Setup
|
||||
for (int j = 0; j < ps_a->numDRBSetup; j++) {
|
||||
const DRB_nGRAN_setup_t *drb_a = &ps_a->DRBnGRanList[j];
|
||||
const DRB_nGRAN_setup_t *drb_b = &ps_b->DRBnGRanList[j];
|
||||
_E1_EQ_CHECK_LONG(drb_a->id, drb_b->id);
|
||||
_E1_EQ_CHECK_INT(drb_a->numUpParam, drb_b->numUpParam);
|
||||
_E1_EQ_CHECK_INT(drb_a->numQosFlowSetup, drb_b->numQosFlowSetup);
|
||||
_EQ_CHECK_LONG(drb_a->id, drb_b->id);
|
||||
_EQ_CHECK_INT(drb_a->numUpParam, drb_b->numUpParam);
|
||||
_EQ_CHECK_INT(drb_a->numQosFlowSetup, drb_b->numQosFlowSetup);
|
||||
}
|
||||
// Check DRB Failed
|
||||
for (int j = 0; j < ps_a->numDRBFailed; j++) {
|
||||
const DRB_nGRAN_failed_t *drbf_a = &ps_a->DRBnGRanFailedList[j];
|
||||
const DRB_nGRAN_failed_t *drbf_b = &ps_b->DRBnGRanFailedList[j];
|
||||
_E1_EQ_CHECK_LONG(drbf_a->id, drbf_b->id);
|
||||
_E1_EQ_CHECK_INT(drbf_a->cause.type, drbf_b->cause.type);
|
||||
_E1_EQ_CHECK_INT(drbf_a->cause.value, drbf_b->cause.value);
|
||||
_EQ_CHECK_LONG(drbf_a->id, drbf_b->id);
|
||||
_EQ_CHECK_INT(drbf_a->cause.type, drbf_b->cause.type);
|
||||
_EQ_CHECK_INT(drbf_a->cause.value, drbf_b->cause.value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1163,10 +1162,10 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_failure(const e1ap_bearer_contex
|
||||
bool decode_E1_bearer_context_setup_failure(e1ap_bearer_context_setup_failure_t *out, const E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_unsuccessfulOutcome);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_unsuccessfulOutcome);
|
||||
E1AP_UnsuccessfulOutcome_t *type = pdu->choice.unsuccessfulOutcome;
|
||||
_E1_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup);
|
||||
_E1_EQ_CHECK_INT(type->value.present, E1AP_UnsuccessfulOutcome__value_PR_BearerContextSetupFailure);
|
||||
_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup);
|
||||
_EQ_CHECK_INT(type->value.present, E1AP_UnsuccessfulOutcome__value_PR_BearerContextSetupFailure);
|
||||
const E1AP_BearerContextSetupFailure_t *in = &type->value.choice.BearerContextSetupFailure;
|
||||
|
||||
// Check mandatory IEs first
|
||||
@@ -1210,10 +1209,10 @@ e1ap_bearer_context_setup_failure_t cp_bearer_context_setup_failure(const e1ap_b
|
||||
/** @brief Bearer Context Setup Failure equality check */
|
||||
bool eq_bearer_context_setup_failure(const e1ap_bearer_context_setup_failure_t *a, const e1ap_bearer_context_setup_failure_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_E1_EQ_CHECK_OPTIONAL_IE(a, b, gNB_cu_up_ue_id, _E1_EQ_CHECK_INT);
|
||||
_E1_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_E1_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, gNB_cu_up_ue_id, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1271,10 +1270,10 @@ E1AP_E1AP_PDU_t *encode_e1_bearer_context_release_command(const e1ap_bearer_rele
|
||||
bool decode_e1_bearer_context_release_command(e1ap_bearer_release_cmd_t *out, const E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_initiatingMessage);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_initiatingMessage);
|
||||
E1AP_InitiatingMessage_t *type = pdu->choice.initiatingMessage;
|
||||
_E1_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextRelease);
|
||||
_E1_EQ_CHECK_INT(type->value.present, E1AP_InitiatingMessage__value_PR_BearerContextReleaseCommand);
|
||||
_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextRelease);
|
||||
_EQ_CHECK_INT(type->value.present, E1AP_InitiatingMessage__value_PR_BearerContextReleaseCommand);
|
||||
const E1AP_BearerContextReleaseCommand_t *in = &type->value.choice.BearerContextReleaseCommand;
|
||||
|
||||
// Check mandatory IEs
|
||||
@@ -1297,7 +1296,7 @@ bool decode_e1_bearer_context_release_command(e1ap_bearer_release_cmd_t *out, co
|
||||
out->cause = e1_decode_cause_ie(&ie->value.choice.Cause);
|
||||
break;
|
||||
default:
|
||||
PRINT_ERROR("%s decoding failure: IE %ld is invalid\n", __func__, ie->id)
|
||||
PRINT_ERROR("%s decoding failure: IE %ld is invalid\n", __func__, ie->id);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -1308,10 +1307,10 @@ bool decode_e1_bearer_context_release_command(e1ap_bearer_release_cmd_t *out, co
|
||||
/** @brief Bearer Context Release Command equality check */
|
||||
bool eq_bearer_context_release_command(const e1ap_bearer_release_cmd_t *a, const e1ap_bearer_release_cmd_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_E1_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1366,10 +1365,10 @@ E1AP_E1AP_PDU_t *encode_e1_bearer_context_release_complete(const e1ap_bearer_rel
|
||||
bool decode_e1_bearer_context_release_complete(e1ap_bearer_release_cplt_t *out, const E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
E1AP_SuccessfulOutcome_t *type = pdu->choice.successfulOutcome;
|
||||
_E1_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextRelease);
|
||||
_E1_EQ_CHECK_INT(type->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextReleaseComplete);
|
||||
_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextRelease);
|
||||
_EQ_CHECK_INT(type->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextReleaseComplete);
|
||||
const E1AP_BearerContextReleaseComplete_t *in = &type->value.choice.BearerContextReleaseComplete;
|
||||
|
||||
// Check mandatory IEs
|
||||
@@ -1388,7 +1387,7 @@ bool decode_e1_bearer_context_release_complete(e1ap_bearer_release_cplt_t *out,
|
||||
out->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
|
||||
break;
|
||||
default:
|
||||
PRINT_ERROR("%s decoding failure: IE %ld is not handled or invalid\n", __func__, ie->id)
|
||||
PRINT_ERROR("%s decoding failure: IE %ld is not handled or invalid\n", __func__, ie->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1398,8 +1397,8 @@ bool decode_e1_bearer_context_release_complete(e1ap_bearer_release_cplt_t *out,
|
||||
/** @brief Bearer Context Release Complete equality check */
|
||||
bool eq_bearer_context_release_complete(const e1ap_bearer_release_cplt_t *a, const e1ap_bearer_release_cplt_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1669,13 +1668,13 @@ static bool e1_decode_pdu_session_to_setup_mod_item(pdu_session_to_setup_t *out,
|
||||
// Security Indication (M)
|
||||
CHECK_E1AP_DEC(e1_decode_security_indication(&out->securityIndication, &item->securityIndication));
|
||||
/* NG UL UP Transport Layer Information (M) */
|
||||
_E1_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel);
|
||||
_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel);
|
||||
CHECK_E1AP_DEC(e1_decode_up_tnl_info(&out->UP_TL_information, &item->nG_UL_UP_TNL_Information));
|
||||
/* DRB To Setup List ( > 1 item ) */
|
||||
const E1AP_DRB_To_Setup_Mod_List_NG_RAN_t *drb2SetupList = &item->dRB_To_Setup_Mod_List_NG_RAN;
|
||||
_E1_EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0);
|
||||
EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0);
|
||||
out->numDRB2Setup = drb2SetupList->list.count;
|
||||
_E1_EQ_CHECK_INT(out->numDRB2Setup, 1); // can only handle one DRB per PDU session
|
||||
_EQ_CHECK_INT(out->numDRB2Setup, 1); // can only handle one DRB per PDU session
|
||||
for (int j = 0; j < drb2SetupList->list.count; j++) {
|
||||
DRB_nGRAN_to_setup_t *drb = out->DRBnGRanList + j;
|
||||
const E1AP_DRB_To_Setup_Mod_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j];
|
||||
@@ -1687,7 +1686,7 @@ static bool e1_decode_pdu_session_to_setup_mod_item(pdu_session_to_setup_t *out,
|
||||
CHECK_E1AP_DEC(e1_decode_pdcp_config(&drb->pdcp_config, &drb2Setup->pDCP_Configuration));
|
||||
// Cell Group Information (M)
|
||||
const E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information;
|
||||
_E1_EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0);
|
||||
EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0);
|
||||
drb->numCellGroups = cellGroupList->list.count;
|
||||
for (int k = 0; k < cellGroupList->list.count; k++) {
|
||||
const E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k];
|
||||
@@ -1774,10 +1773,10 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
// Validate message type
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_initiatingMessage);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_initiatingMessage);
|
||||
const E1AP_InitiatingMessage_t *im = pdu->choice.initiatingMessage;
|
||||
_E1_EQ_CHECK_LONG(im->procedureCode, E1AP_ProcedureCode_id_bearerContextModification);
|
||||
_E1_EQ_CHECK_INT(im->value.present, E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest);
|
||||
_EQ_CHECK_LONG(im->procedureCode, E1AP_ProcedureCode_id_bearerContextModification);
|
||||
_EQ_CHECK_INT(im->value.present, E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest);
|
||||
|
||||
const E1AP_BearerContextModificationRequest_t *in = &im->value.choice.BearerContextModificationRequest;
|
||||
E1AP_BearerContextModificationRequestIEs_t *ie = NULL;
|
||||
@@ -1794,12 +1793,12 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
||||
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
||||
out->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
@@ -1819,7 +1818,7 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_BearerContextStatusChange:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange);
|
||||
if (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) {
|
||||
out->bearerContextStatus = malloc_or_fail(sizeof(*out->bearerContextStatus));
|
||||
*out->bearerContextStatus = BEARER_SUSPEND;
|
||||
@@ -1836,8 +1835,8 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest: {
|
||||
_E1_EQ_CHECK_INT(ie->value.present,
|
||||
E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest);
|
||||
_EQ_CHECK_INT(ie->value.present,
|
||||
E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest);
|
||||
E1AP_System_BearerContextModificationRequest_t *modReq = &ie->value.choice.System_BearerContextModificationRequest;
|
||||
DevAssert(ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest != NULL);
|
||||
// System IE can contain either UTRAN or NG-RAN
|
||||
@@ -1860,9 +1859,9 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
||||
E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = msgNGRAN_list->list.array[i];
|
||||
switch (msgNGRAN->id) {
|
||||
case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List:
|
||||
_E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List);
|
||||
_E1_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Setup_Mod_List);
|
||||
_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List);
|
||||
_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Setup_Mod_List);
|
||||
E1AP_PDU_Session_Resource_To_Setup_Mod_List_t *setupList =
|
||||
&msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_Mod_List;
|
||||
// PDU Session Resource To Modify List
|
||||
@@ -1876,8 +1875,8 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List:
|
||||
/* PDU Session Resource To Modify List (see 9.3.3.11 of TS 38.463) */
|
||||
_E1_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List);
|
||||
_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List);
|
||||
E1AP_PDU_Session_Resource_To_Modify_List_t *modList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List;
|
||||
out->numPDUSessionsMod = modList->list.count;
|
||||
// Loop through all PDU sessions
|
||||
@@ -1887,8 +1886,8 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Remove_List:
|
||||
/* PDU Session Resource To Remove List (see 9.3.3.12 of TS 38.463) */
|
||||
_E1_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Remove_List);
|
||||
_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Remove_List);
|
||||
E1AP_PDU_Session_Resource_To_Remove_List_t *remList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Remove_List;
|
||||
out->numPDUSessionsRem = remList->list.count;
|
||||
// Loop through all PDU sessions to remove
|
||||
@@ -1980,9 +1979,9 @@ e1ap_bearer_mod_req_t cp_bearer_context_mod_request(const e1ap_bearer_mod_req_t
|
||||
/** @brief Equality check for Security Indication IE (3GPP TS 38.463 9.3.1.23) */
|
||||
static bool eq_security_ind(security_indication_t *a, security_indication_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(a->confidentialityProtectionIndication, b->confidentialityProtectionIndication);
|
||||
_E1_EQ_CHECK_INT(a->integrityProtectionIndication, b->integrityProtectionIndication);
|
||||
_E1_EQ_CHECK_LONG(a->maxIPrate, b->maxIPrate);
|
||||
_EQ_CHECK_INT(a->confidentialityProtectionIndication, b->confidentialityProtectionIndication);
|
||||
_EQ_CHECK_INT(a->integrityProtectionIndication, b->integrityProtectionIndication);
|
||||
_EQ_CHECK_LONG(a->maxIPrate, b->maxIPrate);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1991,29 +1990,29 @@ static bool eq_security_ind(security_indication_t *a, security_indication_t *b)
|
||||
*/
|
||||
static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->id, b->id);
|
||||
_E1_EQ_CHECK_INT(a->numQosFlowsMod, b->numQosFlowsMod);
|
||||
_EQ_CHECK_LONG(a->id, b->id);
|
||||
_EQ_CHECK_INT(a->numQosFlowsMod, b->numQosFlowsMod);
|
||||
for (int i = 0; i < a->numQosFlowsMod; i++) {
|
||||
if (!eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]))
|
||||
return false;
|
||||
}
|
||||
_E1_EQ_CHECK_INT(a->numDlUpParam, b->numDlUpParam);
|
||||
_EQ_CHECK_INT(a->numDlUpParam, b->numDlUpParam);
|
||||
for (int i = 0; i < a->numDlUpParam; i++) {
|
||||
_E1_EQ_CHECK_INT(a->DlUpParamList[i].cell_group_id, b->DlUpParamList[i].cell_group_id);
|
||||
_EQ_CHECK_INT(a->DlUpParamList[i].cell_group_id, b->DlUpParamList[i].cell_group_id);
|
||||
if (!eq_up_tl_info(&a->DlUpParamList[i].tl_info, &b->DlUpParamList[i].tl_info))
|
||||
return false;
|
||||
}
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, pdcp_config);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, pdcp_config);
|
||||
if (a->pdcp_config && b->pdcp_config) {
|
||||
if (!eq_pdcp_config(a->pdcp_config, b->pdcp_config))
|
||||
return false;
|
||||
}
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, sdap_config);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, sdap_config);
|
||||
if (a->sdap_config && b->sdap_config) {
|
||||
if (!eq_sdap_config(a->sdap_config, b->sdap_config))
|
||||
return false;
|
||||
}
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, pdcp_status);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, pdcp_status);
|
||||
if (a->pdcp_status && b->pdcp_status) {
|
||||
if (!eq_pdcp_info(a->pdcp_status, b->pdcp_status))
|
||||
return false;
|
||||
@@ -2024,26 +2023,26 @@ static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t
|
||||
/** @brief Equality check for PDU session item to modify */
|
||||
static bool eq_pdu_session_to_mod_item(const pdu_session_to_mod_t *a, const pdu_session_to_mod_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->sessionId, b->sessionId);
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, UP_TL_information);
|
||||
_EQ_CHECK_LONG(a->sessionId, b->sessionId);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, UP_TL_information);
|
||||
if (a->UP_TL_information && b->UP_TL_information) {
|
||||
if (!eq_up_tl_info(a->UP_TL_information, b->UP_TL_information))
|
||||
return false;
|
||||
}
|
||||
_E1_EQ_CHECK_INT(a->numDRB2Setup, b->numDRB2Setup);
|
||||
_EQ_CHECK_INT(a->numDRB2Setup, b->numDRB2Setup);
|
||||
for (int i = 0; i < a->numDRB2Setup; i++) {
|
||||
if (!eq_drb_to_setup(&a->DRBnGRanList[i], &b->DRBnGRanList[i]))
|
||||
return false;
|
||||
}
|
||||
_E1_EQ_CHECK_LONG(a->numDRB2Modify, b->numDRB2Modify);
|
||||
_EQ_CHECK_LONG(a->numDRB2Modify, b->numDRB2Modify);
|
||||
for (int i = 0; i < a->numDRB2Modify; i++) {
|
||||
if (!eq_drb_to_mod(&a->DRBnGRanModList[i], &b->DRBnGRanModList[i]))
|
||||
return false;
|
||||
}
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, securityIndication);
|
||||
_E1_EQ_CHECK_INT(a->n_drb_to_remove, b->n_drb_to_remove);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, securityIndication);
|
||||
_EQ_CHECK_INT(a->n_drb_to_remove, b->n_drb_to_remove);
|
||||
for (int r = 0; r < a->n_drb_to_remove; r++) {
|
||||
_E1_EQ_CHECK_LONG(a->drbs_to_remove[r].id, b->drbs_to_remove[r].id);
|
||||
_EQ_CHECK_LONG(a->drbs_to_remove[r].id, b->drbs_to_remove[r].id);
|
||||
}
|
||||
if (a->securityIndication && b->securityIndication) {
|
||||
if (!eq_security_ind(a->securityIndication, b->securityIndication))
|
||||
@@ -2058,24 +2057,24 @@ static bool eq_pdu_session_to_mod_item(const pdu_session_to_mod_t *a, const pdu_
|
||||
bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_bearer_mod_req_t *b)
|
||||
{
|
||||
// basic members
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions);
|
||||
_E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod);
|
||||
_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions);
|
||||
_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod);
|
||||
// Security Info
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, secInfo);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, secInfo);
|
||||
if (a->secInfo && b->secInfo) {
|
||||
_E1_EQ_CHECK_LONG(a->secInfo->cipheringAlgorithm, b->secInfo->cipheringAlgorithm);
|
||||
_E1_EQ_CHECK_LONG(a->secInfo->integrityProtectionAlgorithm, b->secInfo->integrityProtectionAlgorithm);
|
||||
_E1_EQ_CHECK_STR(a->secInfo->encryptionKey, b->secInfo->encryptionKey);
|
||||
_E1_EQ_CHECK_STR(a->secInfo->integrityProtectionKey, b->secInfo->integrityProtectionKey);
|
||||
_EQ_CHECK_LONG(a->secInfo->cipheringAlgorithm, b->secInfo->cipheringAlgorithm);
|
||||
_EQ_CHECK_LONG(a->secInfo->integrityProtectionAlgorithm, b->secInfo->integrityProtectionAlgorithm);
|
||||
_EQ_CHECK_STR(a->secInfo->encryptionKey, b->secInfo->encryptionKey);
|
||||
_EQ_CHECK_STR(a->secInfo->integrityProtectionKey, b->secInfo->integrityProtectionKey);
|
||||
}
|
||||
// Bearer Context Status (O)
|
||||
_E1_EQ_CHECK_OPTIONAL_IE(a, b, bearerContextStatus, _E1_EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, bearerContextStatus, _EQ_CHECK_INT);
|
||||
// Inactivity Timer (O)
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer);
|
||||
if (a->inactivityTimer && b->inactivityTimer)
|
||||
_E1_EQ_CHECK_INT(*a->inactivityTimer, *b->inactivityTimer);
|
||||
_EQ_CHECK_INT(*a->inactivityTimer, *b->inactivityTimer);
|
||||
// Activity Notification Level (O)
|
||||
// PDU Sessions
|
||||
if (a->numPDUSessions != b->numPDUSessions)
|
||||
@@ -2092,13 +2091,13 @@ bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_be
|
||||
return false;
|
||||
}
|
||||
// PDU Sessions to Remove
|
||||
_E1_EQ_CHECK_INT(a->numPDUSessionsRem, b->numPDUSessionsRem);
|
||||
_EQ_CHECK_INT(a->numPDUSessionsRem, b->numPDUSessionsRem);
|
||||
for (int i = 0; i < a->numPDUSessionsRem; i++) {
|
||||
const pdu_session_to_remove_t *pduRemA = &a->pduSessionRem[i];
|
||||
const pdu_session_to_remove_t *pduRemB = &b->pduSessionRem[i];
|
||||
_E1_EQ_CHECK_LONG(pduRemA->sessionId, pduRemB->sessionId);
|
||||
_E1_EQ_CHECK_INT(pduRemA->cause.type, pduRemB->cause.type);
|
||||
_E1_EQ_CHECK_INT(pduRemA->cause.value, pduRemB->cause.value);
|
||||
_EQ_CHECK_LONG(pduRemA->sessionId, pduRemB->sessionId);
|
||||
_EQ_CHECK_INT(pduRemA->cause.type, pduRemB->cause.type);
|
||||
_EQ_CHECK_INT(pduRemA->cause.value, pduRemB->cause.value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2324,10 +2323,10 @@ static qos_flow_failed_t decode_qos_flow_failed_item(const E1AP_QoS_Flow_Failed_
|
||||
bool decode_E1_bearer_context_mod_response(e1ap_bearer_modif_resp_t *out, const E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
E1AP_SuccessfulOutcome_t *type = pdu->choice.successfulOutcome;
|
||||
_E1_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextModification);
|
||||
_E1_EQ_CHECK_INT(type->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse);
|
||||
_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextModification);
|
||||
_EQ_CHECK_INT(type->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse);
|
||||
const E1AP_BearerContextModificationResponse_t *in = &type->value.choice.BearerContextModificationResponse;
|
||||
// Check mandatory IEs first
|
||||
E1AP_BearerContextModificationResponseIEs_t *ie;
|
||||
@@ -2339,28 +2338,30 @@ bool decode_E1_bearer_context_mod_response(e1ap_bearer_modif_resp_t *out, const
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID:
|
||||
// gNB-CU-CP UE E1AP ID (M)
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
|
||||
out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID:
|
||||
// gNB-CU-UP UE E1AP ID (M)
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
|
||||
out->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse:
|
||||
// CHOICE System (O)
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse);
|
||||
_EQ_CHECK_INT(ie->value.present,
|
||||
E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse);
|
||||
// NG-RAN System
|
||||
E1AP_System_BearerContextModificationResponse_t *system = &ie->value.choice.System_BearerContextModificationResponse;
|
||||
_E1_EQ_CHECK_INT(system->present, E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse);
|
||||
_EQ_CHECK_INT(system->present, E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse);
|
||||
// NG-RAN List
|
||||
E1AP_ProtocolIE_Container_4932P29_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P29_t *)system->choice.nG_RAN_BearerContextModificationResponse;
|
||||
_E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1);
|
||||
_EQ_CHECK_INT(msgNGRAN_list->list.count, 1);
|
||||
E1AP_NG_RAN_BearerContextModificationResponse_t *msgNGRAN = msgNGRAN_list->list.array[0];
|
||||
_E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List);
|
||||
_E1_EQ_CHECK_INT(msgNGRAN->value.present, E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List);
|
||||
_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List);
|
||||
_EQ_CHECK_INT(msgNGRAN->value.present,
|
||||
E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List);
|
||||
// PDU Session Resource Modified list (O)
|
||||
E1AP_PDU_Session_Resource_Modified_List_t *list = &msgNGRAN->value.choice.PDU_Session_Resource_Modified_List;
|
||||
out->numPDUSessionsMod = list->list.count;
|
||||
@@ -2501,36 +2502,36 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a
|
||||
if (!a || !b) return false; // Null-check both inputs
|
||||
|
||||
// Basic members
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod);
|
||||
_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod);
|
||||
|
||||
// PDU Session Modified List
|
||||
for (int i = 0; i < a->numPDUSessionsMod; i++) {
|
||||
const pdu_session_modif_t *pduA = &a->pduSessionMod[i];
|
||||
const pdu_session_modif_t *pduB = &b->pduSessionMod[i];
|
||||
|
||||
_E1_EQ_CHECK_LONG(pduA->id, pduB->id);
|
||||
_E1_EQ_CHECK_OPTIONAL_IE(pduA, pduB, confidentialityProtectionIndication, _E1_EQ_CHECK_INT);
|
||||
_E1_EQ_CHECK_OPTIONAL_IE(pduA, pduB, integrityProtectionIndication, _E1_EQ_CHECK_INT);
|
||||
_EQ_CHECK_LONG(pduA->id, pduB->id);
|
||||
_EQ_CHECK_OPTIONAL_IE(pduA, pduB, confidentialityProtectionIndication, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(pduA, pduB, integrityProtectionIndication, _EQ_CHECK_INT);
|
||||
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(pduA, pduB, ng_DL_UP_TL_info);
|
||||
_EQ_CHECK_OPTIONAL_PTR(pduA, pduB, ng_DL_UP_TL_info);
|
||||
if (pduA->ng_DL_UP_TL_info && pduB->ng_DL_UP_TL_info) {
|
||||
if (!eq_up_tl_info(pduA->ng_DL_UP_TL_info, pduB->ng_DL_UP_TL_info))
|
||||
return false;
|
||||
}
|
||||
|
||||
// DRB Modified List
|
||||
_E1_EQ_CHECK_INT(pduA->numDRBModified, pduB->numDRBModified);
|
||||
_EQ_CHECK_INT(pduA->numDRBModified, pduB->numDRBModified);
|
||||
for (int j = 0; j < pduA->numDRBModified; j++) {
|
||||
const DRB_nGRAN_modified_t *drbModA = &pduA->DRBnGRanModList[j];
|
||||
const DRB_nGRAN_modified_t *drbModB = &pduB->DRBnGRanModList[j];
|
||||
_E1_EQ_CHECK_LONG(drbModA->id, drbModB->id);
|
||||
_E1_EQ_CHECK_INT(drbModA->numQosFlowSetup, drbModB->numQosFlowSetup);
|
||||
_EQ_CHECK_LONG(drbModA->id, drbModB->id);
|
||||
_EQ_CHECK_INT(drbModA->numQosFlowSetup, drbModB->numQosFlowSetup);
|
||||
for (int j = 0; j < drbModA->numQosFlowSetup; j++) {
|
||||
_E1_EQ_CHECK_LONG(drbModA->qosFlows[j].qfi, drbModB->qosFlows[j].qfi);
|
||||
_EQ_CHECK_LONG(drbModA->qosFlows[j].qfi, drbModB->qosFlows[j].qfi);
|
||||
}
|
||||
_E1_EQ_CHECK_OPTIONAL_PTR(drbModA, drbModB, pdcp_status);
|
||||
_EQ_CHECK_OPTIONAL_PTR(drbModA, drbModB, pdcp_status);
|
||||
if (drbModA->pdcp_status && drbModB->pdcp_status) {
|
||||
if (!eq_pdcp_info(drbModA->pdcp_status, drbModB->pdcp_status))
|
||||
return false;
|
||||
@@ -2538,32 +2539,32 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a
|
||||
}
|
||||
|
||||
// DRB Failed to Modify List
|
||||
_E1_EQ_CHECK_INT(pduA->numDRBFailedToMod, pduB->numDRBFailedToMod);
|
||||
_EQ_CHECK_INT(pduA->numDRBFailedToMod, pduB->numDRBFailedToMod);
|
||||
for (int j = 0; j < pduA->numDRBFailedToMod; j++) {
|
||||
_E1_EQ_CHECK_LONG(pduA->DRBnGRanFailedModList[j].id, pduB->DRBnGRanFailedModList[j].id);
|
||||
_E1_EQ_CHECK_INT(pduA->DRBnGRanFailedModList[j].cause.value, pduB->DRBnGRanFailedModList[j].cause.value);
|
||||
_E1_EQ_CHECK_INT(pduA->DRBnGRanFailedModList[j].cause.type, pduB->DRBnGRanFailedModList[j].cause.type);
|
||||
_EQ_CHECK_LONG(pduA->DRBnGRanFailedModList[j].id, pduB->DRBnGRanFailedModList[j].id);
|
||||
_EQ_CHECK_INT(pduA->DRBnGRanFailedModList[j].cause.value, pduB->DRBnGRanFailedModList[j].cause.value);
|
||||
_EQ_CHECK_INT(pduA->DRBnGRanFailedModList[j].cause.type, pduB->DRBnGRanFailedModList[j].cause.type);
|
||||
}
|
||||
|
||||
// DRB Setup List
|
||||
_E1_EQ_CHECK_INT(pduA->numDRBSetup, pduB->numDRBSetup);
|
||||
_EQ_CHECK_INT(pduA->numDRBSetup, pduB->numDRBSetup);
|
||||
for (int j = 0; j < pduA->numDRBSetup; j++) {
|
||||
const DRB_nGRAN_setup_t *drbSetupA = &pduA->DRBnGRanSetupList[j];
|
||||
const DRB_nGRAN_setup_t *drbSetupB = &pduB->DRBnGRanSetupList[j];
|
||||
|
||||
_E1_EQ_CHECK_LONG(drbSetupA->id, drbSetupB->id);
|
||||
_E1_EQ_CHECK_INT(drbSetupA->numQosFlowSetup, drbSetupB->numQosFlowSetup);
|
||||
_EQ_CHECK_LONG(drbSetupA->id, drbSetupB->id);
|
||||
_EQ_CHECK_INT(drbSetupA->numQosFlowSetup, drbSetupB->numQosFlowSetup);
|
||||
for (int j = 0; j < drbSetupA->numQosFlowSetup; j++) {
|
||||
_E1_EQ_CHECK_LONG(drbSetupA->qosFlows[j].qfi, drbSetupB->qosFlows[j].qfi);
|
||||
_EQ_CHECK_LONG(drbSetupA->qosFlows[j].qfi, drbSetupB->qosFlows[j].qfi);
|
||||
}
|
||||
}
|
||||
|
||||
// DRB Failed to Setup List
|
||||
_E1_EQ_CHECK_INT(pduA->numDRBFailed, pduB->numDRBFailed);
|
||||
_EQ_CHECK_INT(pduA->numDRBFailed, pduB->numDRBFailed);
|
||||
for (int j = 0; j < pduA->numDRBFailed; j++) {
|
||||
_E1_EQ_CHECK_LONG(pduA->DRBnGRanFailedList[j].id, pduB->DRBnGRanFailedList[j].id);
|
||||
_E1_EQ_CHECK_INT(pduA->DRBnGRanFailedList[j].cause.value, pduB->DRBnGRanFailedList[j].cause.value);
|
||||
_E1_EQ_CHECK_INT(pduA->DRBnGRanFailedList[j].cause.type, pduB->DRBnGRanFailedList[j].cause.type);
|
||||
_EQ_CHECK_LONG(pduA->DRBnGRanFailedList[j].id, pduB->DRBnGRanFailedList[j].id);
|
||||
_EQ_CHECK_INT(pduA->DRBnGRanFailedList[j].cause.value, pduB->DRBnGRanFailedList[j].cause.value);
|
||||
_EQ_CHECK_INT(pduA->DRBnGRanFailedList[j].cause.type, pduB->DRBnGRanFailedList[j].cause.type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2627,10 +2628,10 @@ struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_failure(const e1ap_bearer_con
|
||||
bool decode_E1_bearer_context_mod_failure(e1ap_bearer_context_mod_failure_t *out, const E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_unsuccessfulOutcome);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_unsuccessfulOutcome);
|
||||
E1AP_UnsuccessfulOutcome_t *type = pdu->choice.unsuccessfulOutcome;
|
||||
_E1_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextModification);
|
||||
_E1_EQ_CHECK_INT(type->value.present, E1AP_UnsuccessfulOutcome__value_PR_BearerContextModificationFailure);
|
||||
_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextModification);
|
||||
_EQ_CHECK_INT(type->value.present, E1AP_UnsuccessfulOutcome__value_PR_BearerContextModificationFailure);
|
||||
const E1AP_BearerContextModificationFailure_t *in = &type->value.choice.BearerContextModificationFailure;
|
||||
// Check mandatory IEs first
|
||||
E1AP_BearerContextModificationFailureIEs_t *ie;
|
||||
@@ -2671,10 +2672,10 @@ bool eq_E1_bearer_context_mod_failure(const e1ap_bearer_context_mod_failure_t *a
|
||||
{
|
||||
if (!a || !b)
|
||||
return false; // Null-check both inputs
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_E1_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_E1_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
|
||||
_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -179,15 +179,15 @@ bool decode_e1ap_cuup_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_req_t
|
||||
AssertFatal(ie != NULL, "in->protocolIEs.list.array[i] shall not be null");
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_TransactionID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID);
|
||||
out->transac_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID);
|
||||
asn_INTEGER2ulong(&ie->value.choice.GNB_CU_UP_ID, &out->gNB_cu_up_id);
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_Name);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_Name);
|
||||
// gNB-CU-UP Name (O)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name, false);
|
||||
if (ie != NULL) {
|
||||
@@ -196,12 +196,12 @@ bool decode_e1ap_cuup_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_req_t
|
||||
}
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_CNSupport:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport);
|
||||
_E1_EQ_CHECK_INT(ie->value.choice.CNSupport, E1AP_CNSupport_c_5gc); // only 5GC CN Support supported
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport);
|
||||
_EQ_CHECK_LONG((long)ie->value.choice.CNSupport, (long)E1AP_CNSupport_c_5gc); // only 5GC CN Support supported
|
||||
out->cn_support = ie->value.choice.CNSupport;
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_SupportedPLMNs:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List);
|
||||
out->supported_plmns = ie->value.choice.SupportedPLMNs_List.list.count;
|
||||
|
||||
for (int i = 0; i < out->supported_plmns; i++) {
|
||||
@@ -275,19 +275,19 @@ void free_e1ap_cuup_setup_request(e1ap_setup_req_t *msg)
|
||||
*/
|
||||
bool eq_e1ap_cuup_setup_request(const e1ap_setup_req_t *a, const e1ap_setup_req_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(a->transac_id, b->transac_id);
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_up_id, b->gNB_cu_up_id);
|
||||
_EQ_CHECK_UINT64(a->transac_id, b->transac_id);
|
||||
_EQ_CHECK_UINT64(a->gNB_cu_up_id, b->gNB_cu_up_id);
|
||||
if (a->gNB_cu_up_name && b->gNB_cu_up_name)
|
||||
_E1_EQ_CHECK_STR(a->gNB_cu_up_name, b->gNB_cu_up_name)
|
||||
_E1_EQ_CHECK_INT(a->supported_plmns, b->supported_plmns);
|
||||
_EQ_CHECK_STR(a->gNB_cu_up_name, b->gNB_cu_up_name);
|
||||
_EQ_CHECK_INT(a->supported_plmns, b->supported_plmns);
|
||||
for (int i = 0; i < a->supported_plmns; i++) {
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].id.mcc, b->plmn[i].id.mcc);
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].id.mnc, b->plmn[i].id.mnc);
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].id.mnc_digit_length, b->plmn[i].id.mnc_digit_length);
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].supported_slices, b->plmn[i].supported_slices);
|
||||
_EQ_CHECK_INT(a->plmn[i].id.mcc, b->plmn[i].id.mcc);
|
||||
_EQ_CHECK_INT(a->plmn[i].id.mnc, b->plmn[i].id.mnc);
|
||||
_EQ_CHECK_INT(a->plmn[i].id.mnc_digit_length, b->plmn[i].id.mnc_digit_length);
|
||||
_EQ_CHECK_INT(a->plmn[i].supported_slices, b->plmn[i].supported_slices);
|
||||
for (int s = 0; s < a->plmn[i].supported_slices; ++s) {
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].slice[s].sst, b->plmn[i].slice[s].sst);
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].slice[s].sd, b->plmn[i].slice[s].sd);
|
||||
_EQ_CHECK_INT(a->plmn[i].slice[s].sst, b->plmn[i].slice[s].sst);
|
||||
_EQ_CHECK_INT(a->plmn[i].slice[s].sd, b->plmn[i].slice[s].sd);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -372,9 +372,9 @@ E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_response(const e1ap_setup_resp_t *msg)
|
||||
*/
|
||||
bool decode_e1ap_cuup_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_resp_t *out)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
_E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->procedureCode, E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup);
|
||||
_E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup);
|
||||
_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse);
|
||||
const E1AP_GNB_CU_UP_E1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse;
|
||||
E1AP_GNB_CU_UP_E1SetupResponseIEs_t *ie;
|
||||
// Transaction ID (M)
|
||||
@@ -391,7 +391,7 @@ bool decode_e1ap_cuup_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_resp
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_Name:
|
||||
// gNB-CU-CP Name (O)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_CP_Name, false);
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_GNB_CU_CP_Name);
|
||||
_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_GNB_CU_CP_Name);
|
||||
if (ie != NULL) {
|
||||
out->gNB_cu_cp_name = calloc_or_fail(ie->value.choice.GNB_CU_CP_Name.size + 1, sizeof(char));
|
||||
memcpy(out->gNB_cu_cp_name, ie->value.choice.GNB_CU_CP_Name.buf, ie->value.choice.GNB_CU_CP_Name.size);
|
||||
@@ -474,30 +474,30 @@ void free_e1ap_cuup_setup_response(e1ap_setup_resp_t *msg)
|
||||
*/
|
||||
bool eq_e1ap_cuup_setup_response(const e1ap_setup_resp_t *a, const e1ap_setup_resp_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->transac_id, b->transac_id);
|
||||
_EQ_CHECK_LONG(a->transac_id, b->transac_id);
|
||||
if ((a->gNB_cu_cp_name && !b->gNB_cu_cp_name) || (!a->gNB_cu_cp_name && b->gNB_cu_cp_name))
|
||||
return false;
|
||||
if (a->gNB_cu_cp_name && b->gNB_cu_cp_name)
|
||||
_E1_EQ_CHECK_STR(a->gNB_cu_cp_name, b->gNB_cu_cp_name);
|
||||
_EQ_CHECK_STR(a->gNB_cu_cp_name, b->gNB_cu_cp_name);
|
||||
if ((a->tnla_info && !b->tnla_info) || (!a->tnla_info && b->tnla_info))
|
||||
return false;
|
||||
if (a->tnla_info && b->tnla_info) {
|
||||
_E1_EQ_CHECK_INT(a->tnla_info->num_addresses_to_add, b->tnla_info->num_addresses_to_add);
|
||||
_E1_EQ_CHECK_INT(a->tnla_info->num_addresses_to_remove, b->tnla_info->num_addresses_to_remove);
|
||||
_EQ_CHECK_INT(a->tnla_info->num_addresses_to_add, b->tnla_info->num_addresses_to_add);
|
||||
_EQ_CHECK_INT(a->tnla_info->num_addresses_to_remove, b->tnla_info->num_addresses_to_remove);
|
||||
for (int i = 0; i < a->tnla_info->num_addresses_to_add; i++) {
|
||||
tnl_address_info_item_t *a_to_add = &a->tnla_info->addresses_to_add[i];
|
||||
tnl_address_info_item_t *b_to_add = &b->tnla_info->addresses_to_add[i];
|
||||
_E1_EQ_CHECK_LONG(a_to_add->ipsec_tl_address, b_to_add->ipsec_tl_address);
|
||||
_EQ_CHECK_UINT32(a_to_add->ipsec_tl_address, b_to_add->ipsec_tl_address);
|
||||
for (int j = 0; j < a_to_add->num_gtp_tl_addresses; j++) {
|
||||
_E1_EQ_CHECK_LONG(a_to_add->gtp_tl_addresses[j], b_to_add->gtp_tl_addresses[j]);
|
||||
_EQ_CHECK_UINT32(a_to_add->gtp_tl_addresses[j], b_to_add->gtp_tl_addresses[j]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < a->tnla_info->num_addresses_to_remove; i++) {
|
||||
tnl_address_info_item_t *a_to_rem = &a->tnla_info->addresses_to_remove[i];
|
||||
tnl_address_info_item_t *b_to_rem = &b->tnla_info->addresses_to_remove[i];
|
||||
_E1_EQ_CHECK_LONG(a_to_rem->ipsec_tl_address, b_to_rem->ipsec_tl_address);
|
||||
_EQ_CHECK_UINT32(a_to_rem->ipsec_tl_address, b_to_rem->ipsec_tl_address);
|
||||
for (int j = 0; j < a_to_rem->num_gtp_tl_addresses; j++) {
|
||||
_E1_EQ_CHECK_LONG(a_to_rem->gtp_tl_addresses[j], b_to_rem->gtp_tl_addresses[j]);
|
||||
_EQ_CHECK_UINT32(a_to_rem->gtp_tl_addresses[j], b_to_rem->gtp_tl_addresses[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -558,8 +558,8 @@ E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *msg)
|
||||
*/
|
||||
bool decode_e1ap_cuup_setup_failure(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_fail_t *out)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_unsuccessfulOutcome);
|
||||
_E1_EQ_CHECK_INT(pdu->choice.unsuccessfulOutcome->procedureCode, E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup);
|
||||
_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_unsuccessfulOutcome);
|
||||
_EQ_CHECK_LONG(pdu->choice.unsuccessfulOutcome->procedureCode, E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup);
|
||||
const E1AP_GNB_CU_UP_E1SetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure;
|
||||
E1AP_GNB_CU_UP_E1SetupFailureIEs_t *ie;
|
||||
// Check mandatory IEs first
|
||||
@@ -647,25 +647,25 @@ void free_e1ap_cuup_setup_failure(e1ap_setup_fail_t *msg)
|
||||
*/
|
||||
bool eq_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *a, const e1ap_setup_fail_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->transac_id, b->transac_id);
|
||||
_E1_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_E1_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
_EQ_CHECK_LONG(a->transac_id, b->transac_id);
|
||||
_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
if (a->time_to_wait && b->time_to_wait)
|
||||
_E1_EQ_CHECK_LONG(*a->time_to_wait, *b->time_to_wait);
|
||||
_EQ_CHECK_LONG(*a->time_to_wait, *b->time_to_wait);
|
||||
if (a->crit_diag && b->crit_diag) {
|
||||
if (a->crit_diag->procedure_code && b->crit_diag->procedure_code)
|
||||
_E1_EQ_CHECK_LONG(*(a->crit_diag->procedure_code), *(b->crit_diag->procedure_code));
|
||||
_EQ_CHECK_INT(*(a->crit_diag->procedure_code), *(b->crit_diag->procedure_code));
|
||||
if (a->crit_diag->triggering_msg && b->crit_diag->triggering_msg)
|
||||
_E1_EQ_CHECK_LONG(*(a->crit_diag->triggering_msg), *(b->crit_diag->triggering_msg));
|
||||
_EQ_CHECK_UINT32(*(a->crit_diag->triggering_msg), *(b->crit_diag->triggering_msg));
|
||||
if (a->crit_diag->procedure_criticality && b->crit_diag->procedure_criticality)
|
||||
_E1_EQ_CHECK_LONG(*(a->crit_diag->procedure_criticality), *(b->crit_diag->procedure_criticality));
|
||||
_E1_EQ_CHECK_INT(a->crit_diag->num_errors, b->crit_diag->num_errors);
|
||||
_EQ_CHECK_UINT32(*(a->crit_diag->procedure_criticality), *(b->crit_diag->procedure_criticality));
|
||||
_EQ_CHECK_INT(a->crit_diag->num_errors, b->crit_diag->num_errors);
|
||||
for (int i = 0; i < a->crit_diag->num_errors; i++) {
|
||||
const criticality_diagnostics_ie_t *a_err = &a->crit_diag->errors[i];
|
||||
const criticality_diagnostics_ie_t *b_err = &b->crit_diag->errors[i];
|
||||
_E1_EQ_CHECK_INT(a_err->ie_id, b_err->ie_id);
|
||||
_E1_EQ_CHECK_INT(a_err->error_type, b_err->error_type);
|
||||
_E1_EQ_CHECK_INT(a_err->criticality, b_err->criticality);
|
||||
_EQ_CHECK_INT(a_err->ie_id, b_err->ie_id);
|
||||
_EQ_CHECK_INT(a_err->error_type, b_err->error_type);
|
||||
_EQ_CHECK_INT(a_err->criticality, b_err->criticality);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -27,12 +27,7 @@
|
||||
#include <stdio.h>
|
||||
#include "openair3/UTILS/conversions.h"
|
||||
#include "e1ap_messages_types.h"
|
||||
|
||||
#ifdef E1AP_LOG_ERRORS
|
||||
#define PRINT_ERROR(fmt, ...) fprintf(stderr, "[%s] " fmt, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define PRINT_ERROR(...) // Do nothing
|
||||
#endif
|
||||
#include "common/utils/eq_check.h"
|
||||
|
||||
#define CHECK_E1AP_DEC(exp) \
|
||||
do { \
|
||||
@@ -42,22 +37,6 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#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 { \
|
||||
@@ -84,29 +63,6 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _E1_EQ_CHECK_OPTIONAL_IE(a, b, field, EQ_MACRO) \
|
||||
do { \
|
||||
if (((a)->field && !(b)->field) || (!(a)->field && (b)->field)) { \
|
||||
return false; /* One of the two is not allocated */ \
|
||||
} \
|
||||
if ((a)->field && (b)->field) { \
|
||||
EQ_MACRO(*(a)->field, *(b)->field) \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _E1_EQ_CHECK_OPTIONAL_PTR(a, b, field) \
|
||||
do { \
|
||||
if (((a)->field && !(b)->field) || (!(a)->field && (b)->field)) { \
|
||||
PRINT_ERROR("%s:%d: optional IE '%s' not allocated: %p, %p\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#field, \
|
||||
(void *)(a)->field, \
|
||||
(void *)(b)->field); \
|
||||
return false; /* One of the two is not allocated */ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct E1AP_Cause;
|
||||
struct E1AP_Cause e1_encode_cause_ie(const e1ap_cause_t *cause);
|
||||
e1ap_cause_t e1_decode_cause_ie(const struct E1AP_Cause *ie);
|
||||
|
||||
@@ -34,87 +34,26 @@
|
||||
#include "f1ap_encoder.h"
|
||||
#include "f1ap_itti_messaging.h"
|
||||
#include "f1ap_cu_paging.h"
|
||||
#include "lib/f1ap_paging.h"
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
|
||||
extern f1ap_setup_req_t *f1ap_du_data_from_du;
|
||||
|
||||
int CU_send_Paging(sctp_assoc_t assoc_id, f1ap_paging_ind_t *paging)
|
||||
int CU_send_Paging(sctp_assoc_t assoc_id, const f1ap_paging_t *paging)
|
||||
{
|
||||
F1AP_F1AP_PDU_t pdu = {0};
|
||||
|
||||
pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu.choice.initiatingMessage, msg);
|
||||
msg->procedureCode = F1AP_ProcedureCode_id_Paging;
|
||||
msg->criticality = F1AP_Criticality_reject;
|
||||
msg->value.present = F1AP_InitiatingMessage__value_PR_Paging;
|
||||
|
||||
/* mandatory */
|
||||
/* UEIdentityIndexValue */
|
||||
{
|
||||
asn1cSequenceAdd(msg->value.choice.Paging.protocolIEs.list,
|
||||
F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_UEIdentityIndexValue;
|
||||
ie->criticality = F1AP_Criticality_reject;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_UEIdentityIndexValue;
|
||||
ie->value.choice.UEIdentityIndexValue.present =
|
||||
F1AP_UEIdentityIndexValue_PR_indexLength10;
|
||||
UEIDENTITYINDEX_TO_BIT_STRING(
|
||||
paging->ueidentityindexvalue,
|
||||
&ie->value.choice.UEIdentityIndexValue.choice.indexLength10);
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
/* PagingIdentity */
|
||||
{
|
||||
asn1cSequenceAdd(msg->value.choice.Paging.protocolIEs.list,
|
||||
F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_PagingIdentity;
|
||||
ie->criticality = F1AP_Criticality_reject;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_PagingIdentity;
|
||||
ie->value.choice.PagingIdentity.present =
|
||||
F1AP_PagingIdentity_PR_cNUEPagingIdentity;
|
||||
asn1cCalloc(ie->value.choice.PagingIdentity.choice.cNUEPagingIdentity, id);
|
||||
id->present = F1AP_CNUEPagingIdentity_PR_fiveG_S_TMSI;
|
||||
FIVEG_S_TMSI_TO_BIT_STRING(paging->fiveg_s_tmsi, &id->choice.fiveG_S_TMSI);
|
||||
}
|
||||
|
||||
/* optional */
|
||||
/* PagingDRX */
|
||||
{
|
||||
asn1cSequenceAdd(msg->value.choice.Paging.protocolIEs.list,
|
||||
F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_PagingDRX;
|
||||
ie->criticality = F1AP_Criticality_ignore;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_PagingDRX;
|
||||
ie->value.choice.PagingDRX = paging->paging_drx;
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
/* PagingCell_list */
|
||||
{
|
||||
asn1cSequenceAdd(msg->value.choice.Paging.protocolIEs.list,
|
||||
F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_PagingCell_List;
|
||||
ie->criticality = F1AP_Criticality_reject;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_PagingCell_list;
|
||||
asn1cSequenceAdd(ie->value.choice.PagingCell_list,
|
||||
F1AP_PagingCell_ItemIEs_t, itemies);
|
||||
itemies->id = F1AP_ProtocolIE_ID_id_PagingCell_Item;
|
||||
itemies->criticality = F1AP_Criticality_reject;
|
||||
itemies->value.present = F1AP_PagingCell_ItemIEs__value_PR_PagingCell_Item;
|
||||
F1AP_NRCGI_t *nRCGI = &itemies->value.choice.PagingCell_Item.nRCGI;
|
||||
MCC_MNC_TO_PLMNID(paging->plmn.mcc, paging->plmn.mnc, paging->plmn.mnc_digit_length, &nRCGI->pLMN_Identity);
|
||||
NR_CELL_ID_TO_BIT_STRING(paging->nr_cellid, &nRCGI->nRCellIdentity);
|
||||
}
|
||||
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
/* encode */
|
||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(F1AP, "Failed to encode F1 Paging failure\n");
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_F1AP_F1AP_PDU, &pdu);
|
||||
F1AP_F1AP_PDU_t *pdu = encode_f1ap_paging(paging);
|
||||
if (pdu == NULL) {
|
||||
LOG_E(F1AP, "Failed to encode F1 Paging\n");
|
||||
return -1;
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_F1AP_F1AP_PDU, &pdu);
|
||||
f1ap_itti_send_sctp_data_req(assoc_id, buffer, len);
|
||||
|
||||
byte_array_t ba = {0};
|
||||
/* encode */
|
||||
if (f1ap_encode_pdu(pdu, &ba.buf, (uint32_t *)&ba.len) < 0) {
|
||||
LOG_E(F1AP, "Failed to encode F1 Paging PDU\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu);
|
||||
return -1;
|
||||
}
|
||||
ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu);
|
||||
/* Ownership of ba.buf is transferred to SCTP task; do not free here. */
|
||||
f1ap_itti_send_sctp_data_req(assoc_id, ba.buf, ba.len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,5 +32,5 @@
|
||||
|
||||
#ifndef F1AP_CU_PAGING_H_
|
||||
#define F1AP_CU_PAGING_H_
|
||||
int CU_send_Paging(sctp_assoc_t assoc_id, f1ap_paging_ind_t *paging);
|
||||
int CU_send_Paging(sctp_assoc_t assoc_id, const f1ap_paging_t *paging);
|
||||
#endif /* F1AP_DU_PAGING_H_ */
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "lib/f1ap_interface_management.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
#include "f1ap_cu_paging.h"
|
||||
#include "lib/f1ap_paging.h"
|
||||
#include "f1ap_cu_task.h"
|
||||
#include "openair2/RRC/NR/nr_rrc_defs.h"
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
@@ -202,9 +203,9 @@ void *F1AP_CU_task(void *arg) {
|
||||
free_ue_context_rel_cmd(&F1AP_UE_CONTEXT_RELEASE_CMD(received_msg));
|
||||
break;
|
||||
|
||||
case F1AP_PAGING_IND:
|
||||
CU_send_Paging(assoc_id,
|
||||
&F1AP_PAGING_IND(received_msg));
|
||||
case F1AP_PAGING:
|
||||
CU_send_Paging(assoc_id, &F1AP_PAGING(received_msg));
|
||||
free_f1ap_paging(&F1AP_PAGING(received_msg));
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_MODIFICATION_CONFIRM:
|
||||
|
||||
@@ -19,75 +19,37 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file f1ap_du_interface_management.h
|
||||
* \brief f1ap interface management for DU
|
||||
* \author EURECOM/NTUST
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include "f1ap_common.h"
|
||||
#include "f1ap_du_paging.h"
|
||||
#include "lib/f1ap_paging.h"
|
||||
#include "conversions.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "openair2/RRC/LTE/rrc_proto.h"
|
||||
|
||||
/* @brief Handle F1AP Paging message at DU */
|
||||
int DU_handle_Paging(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
F1AP_Paging_t *paging;
|
||||
F1AP_PagingIEs_t *ie;
|
||||
long tmsi;
|
||||
uint8_t pagingdrx;
|
||||
uint8_t *fiveg_tmsi_buf = NULL;
|
||||
f1ap_paging_t decoded = {0};
|
||||
|
||||
DevAssert(pdu);
|
||||
(void)instance;
|
||||
(void)assoc_id;
|
||||
(void)stream;
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
|
||||
xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, pdu);
|
||||
}
|
||||
|
||||
paging = &pdu->choice.initiatingMessage->value.choice.Paging;
|
||||
// get UEIdentityIndexValue
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_PagingIEs_t, ie, paging,
|
||||
F1AP_ProtocolIE_ID_id_UEIdentityIndexValue, true);
|
||||
|
||||
LOG_D(F1AP, "indexLength10 %d\n", BIT_STRING_to_uint32(&ie->value.choice.UEIdentityIndexValue.choice.indexLength10));
|
||||
|
||||
// get PagingIdentity
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_PagingIEs_t, ie, paging,
|
||||
F1AP_ProtocolIE_ID_id_PagingIdentity, true);
|
||||
|
||||
if(ie != NULL){
|
||||
fiveg_tmsi_buf = ie->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.buf;
|
||||
|
||||
tmsi = ((long)fiveg_tmsi_buf[0] << 40) +
|
||||
((long)fiveg_tmsi_buf[1] << 32) +
|
||||
(fiveg_tmsi_buf[2] << 24) +
|
||||
(fiveg_tmsi_buf[3] << 16) +
|
||||
(fiveg_tmsi_buf[4] << 8) +
|
||||
fiveg_tmsi_buf[5];
|
||||
|
||||
LOG_D(F1AP, "tmsi %ld\n", tmsi);
|
||||
if (!decode_f1ap_paging(&decoded, pdu)) {
|
||||
LOG_E(F1AP, "Failed to decode F1AP Paging\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get PagingDRX
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_PagingIEs_t, ie, paging,
|
||||
F1AP_ProtocolIE_ID_id_PagingDRX, true);
|
||||
|
||||
if(ie != NULL) {
|
||||
pagingdrx = (uint8_t)ie->value.choice.PagingDRX;
|
||||
}
|
||||
|
||||
LOG_D(F1AP, "pagingdrx %u\n", pagingdrx);
|
||||
|
||||
// get PagingCell_List
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_PagingIEs_t, ie, paging,
|
||||
F1AP_ProtocolIE_ID_id_PagingCell_List, true);
|
||||
|
||||
AssertFatal(false, "not implemented\n");
|
||||
/** @todo Build PCCH-Message (Paging) at DU per TS 38.331 §5.3.2; apply
|
||||
* RRC padding per §8.5; deliver as RLC SDU per §8.2. For each
|
||||
* cell in Paging Cell List that belongs to this DU, queue for MAC; MAC schedules
|
||||
* at PF/PO per TS 38.304 §7. */
|
||||
|
||||
free_f1ap_paging(&decoded);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -19,20 +19,10 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file f1ap_du_interface_management.h
|
||||
* \brief f1ap interface management for DU
|
||||
* \author EURECOM/NTUST
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#ifndef F1AP_DU_PAGING_H_
|
||||
#define F1AP_DU_PAGING_H_
|
||||
|
||||
/* Paging (gNB-CU initiated) */
|
||||
int DU_handle_Paging(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
#endif /* F1AP_DU_PAGING_H_ */
|
||||
|
||||
@@ -4,6 +4,7 @@ add_library(f1ap_lib OBJECT
|
||||
f1ap_interface_management.c
|
||||
f1ap_ue_context.c
|
||||
f1ap_positioning.c
|
||||
f1ap_paging.c
|
||||
)
|
||||
target_link_libraries(f1ap_lib PRIVATE asn1_f1ap ds)
|
||||
target_include_directories(f1ap_lib PUBLIC
|
||||
|
||||
@@ -69,11 +69,11 @@ bool eq_f1ap_ue_to_reset(const f1ap_ue_to_reset_t *a, const f1ap_ue_to_reset_t *
|
||||
if ((!a->gNB_CU_ue_id) ^ (!b->gNB_CU_ue_id))
|
||||
return false;
|
||||
if (a->gNB_CU_ue_id)
|
||||
_F1_EQ_CHECK_INT(*a->gNB_CU_ue_id, *b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(*a->gNB_CU_ue_id, *b->gNB_CU_ue_id);
|
||||
if ((!a->gNB_DU_ue_id) ^ (!b->gNB_DU_ue_id))
|
||||
return false;
|
||||
if (a->gNB_DU_ue_id)
|
||||
_F1_EQ_CHECK_INT(*a->gNB_DU_ue_id, *b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(*a->gNB_DU_ue_id, *b->gNB_DU_ue_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -148,10 +148,10 @@ F1AP_F1AP_PDU_t *encode_f1ap_reset(const f1ap_reset_t *msg)
|
||||
/* @brief decode F1 Reset (9.2.1.1 in TS 38.473) */
|
||||
bool decode_f1ap_reset(const F1AP_F1AP_PDU_t *pdu, f1ap_reset_t *out)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL");
|
||||
_F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_Reset);
|
||||
_F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_Reset);
|
||||
_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_Reset);
|
||||
_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_Reset);
|
||||
|
||||
/* Check presence of mandatory IEs */
|
||||
F1AP_Reset_t *in = &pdu->choice.initiatingMessage->value.choice.Reset;
|
||||
@@ -167,12 +167,12 @@ bool decode_f1ap_reset(const F1AP_F1AP_PDU_t *pdu, f1ap_reset_t *out)
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_TransactionID:
|
||||
// (M) Transaction ID
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_ResetIEs__value_PR_TransactionID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_ResetIEs__value_PR_TransactionID);
|
||||
out->transaction_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_Cause:
|
||||
// (M) Cause
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_ResetIEs__value_PR_Cause);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_ResetIEs__value_PR_Cause);
|
||||
if (!decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)) {
|
||||
PRINT_ERROR("could not decode F1AP Cause\n");
|
||||
return false;
|
||||
@@ -180,7 +180,7 @@ bool decode_f1ap_reset(const F1AP_F1AP_PDU_t *pdu, f1ap_reset_t *out)
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_ResetType:
|
||||
// (M) Reset type
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_ResetIEs__value_PR_ResetType);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_ResetIEs__value_PR_ResetType);
|
||||
if (ie->value.choice.ResetType.present == F1AP_ResetType_PR_f1_Interface) {
|
||||
out->reset_type = F1AP_RESET_ALL;
|
||||
} else if (ie->value.choice.ResetType.present == F1AP_ResetType_PR_partOfF1_Interface) {
|
||||
@@ -192,9 +192,9 @@ bool decode_f1ap_reset(const F1AP_F1AP_PDU_t *pdu, f1ap_reset_t *out)
|
||||
for (int i = 0; i < out->num_ue_to_reset; ++i) {
|
||||
const F1AP_UE_associatedLogicalF1_ConnectionItemRes_t *it_res =
|
||||
(const F1AP_UE_associatedLogicalF1_ConnectionItemRes_t *)con_list->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(it_res->id, F1AP_ProtocolIE_ID_id_UE_associatedLogicalF1_ConnectionItem);
|
||||
_F1_EQ_CHECK_INT(it_res->value.present,
|
||||
F1AP_UE_associatedLogicalF1_ConnectionItemRes__value_PR_UE_associatedLogicalF1_ConnectionItem);
|
||||
_EQ_CHECK_LONG(it_res->id, F1AP_ProtocolIE_ID_id_UE_associatedLogicalF1_ConnectionItem);
|
||||
_EQ_CHECK_INT(it_res->value.present,
|
||||
F1AP_UE_associatedLogicalF1_ConnectionItemRes__value_PR_UE_associatedLogicalF1_ConnectionItem);
|
||||
out->ue_to_reset[i] = decode_f1ap_ue_to_reset(&it_res->value.choice.UE_associatedLogicalF1_ConnectionItem);
|
||||
}
|
||||
} else {
|
||||
@@ -220,12 +220,12 @@ void free_f1ap_reset(f1ap_reset_t *msg)
|
||||
|
||||
bool eq_f1ap_reset(const f1ap_reset_t *a, const f1ap_reset_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_F1_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_F1_EQ_CHECK_LONG(a->cause_value, b->cause_value);
|
||||
_F1_EQ_CHECK_INT(a->reset_type, b->reset_type);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_EQ_CHECK_LONG(a->cause_value, b->cause_value);
|
||||
_EQ_CHECK_INT(a->reset_type, b->reset_type);
|
||||
if (a->reset_type == F1AP_RESET_PART_OF_F1_INTERFACE) {
|
||||
_F1_EQ_CHECK_INT(a->num_ue_to_reset, b->num_ue_to_reset);
|
||||
_EQ_CHECK_INT(a->num_ue_to_reset, b->num_ue_to_reset);
|
||||
for (int i = 0; i < a->num_ue_to_reset; ++i)
|
||||
if (!eq_f1ap_ue_to_reset(&a->ue_to_reset[i], &b->ue_to_reset[i]))
|
||||
return false;
|
||||
@@ -295,10 +295,10 @@ struct F1AP_F1AP_PDU *encode_f1ap_reset_ack(const f1ap_reset_ack_t *msg)
|
||||
/* @brief decode F1 Reset Ack (9.2.1.2 in TS 38.473) */
|
||||
bool decode_f1ap_reset_ack(const struct F1AP_F1AP_PDU *pdu, f1ap_reset_ack_t *out)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome);
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome);
|
||||
AssertError(pdu->choice.successfulOutcome != NULL, return false, "pdu->choice.initiatingMessage is NULL");
|
||||
_F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_Reset);
|
||||
_F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, F1AP_SuccessfulOutcome__value_PR_ResetAcknowledge);
|
||||
_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_Reset);
|
||||
_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, F1AP_SuccessfulOutcome__value_PR_ResetAcknowledge);
|
||||
|
||||
/* Check presence of mandatory IEs */
|
||||
F1AP_ResetAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.ResetAcknowledge;
|
||||
@@ -312,11 +312,11 @@ bool decode_f1ap_reset_ack(const struct F1AP_F1AP_PDU *pdu, f1ap_reset_ack_t *ou
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_TransactionID:
|
||||
// (M) Transaction ID
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_ResetAcknowledgeIEs__value_PR_TransactionID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_ResetAcknowledgeIEs__value_PR_TransactionID);
|
||||
out->transaction_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_UE_associatedLogicalF1_ConnectionListResAck:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_ResetAcknowledgeIEs__value_PR_UE_associatedLogicalF1_ConnectionListResAck);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_ResetAcknowledgeIEs__value_PR_UE_associatedLogicalF1_ConnectionListResAck);
|
||||
{
|
||||
const F1AP_UE_associatedLogicalF1_ConnectionListResAck_t *conn_list = &ie->value.choice.UE_associatedLogicalF1_ConnectionListResAck;
|
||||
AssertError(conn_list->list.count > 0, return false, "no UEs for partially reset F1 interface\n");
|
||||
@@ -324,8 +324,9 @@ bool decode_f1ap_reset_ack(const struct F1AP_F1AP_PDU *pdu, f1ap_reset_ack_t *ou
|
||||
out->ue_to_reset = calloc_or_fail(out->num_ue_to_reset, sizeof(*out->ue_to_reset));
|
||||
for (int i = 0; i < out->num_ue_to_reset; ++i) {
|
||||
const F1AP_UE_associatedLogicalF1_ConnectionItemResAck_t *it_res = (const F1AP_UE_associatedLogicalF1_ConnectionItemResAck_t *)conn_list->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(it_res->id, F1AP_ProtocolIE_ID_id_UE_associatedLogicalF1_ConnectionItem);
|
||||
_F1_EQ_CHECK_INT(it_res->value.present, F1AP_UE_associatedLogicalF1_ConnectionItemResAck__value_PR_UE_associatedLogicalF1_ConnectionItem);
|
||||
_EQ_CHECK_LONG(it_res->id, F1AP_ProtocolIE_ID_id_UE_associatedLogicalF1_ConnectionItem);
|
||||
_EQ_CHECK_INT(it_res->value.present,
|
||||
F1AP_UE_associatedLogicalF1_ConnectionItemResAck__value_PR_UE_associatedLogicalF1_ConnectionItem);
|
||||
out->ue_to_reset[i] = decode_f1ap_ue_to_reset(&it_res->value.choice.UE_associatedLogicalF1_ConnectionItem);
|
||||
}
|
||||
}
|
||||
@@ -347,8 +348,8 @@ void free_f1ap_reset_ack(f1ap_reset_ack_t *msg)
|
||||
|
||||
bool eq_f1ap_reset_ack(const f1ap_reset_ack_t *a, const f1ap_reset_ack_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_F1_EQ_CHECK_INT(a->num_ue_to_reset, b->num_ue_to_reset);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_INT(a->num_ue_to_reset, b->num_ue_to_reset);
|
||||
for (int i = 0; i < a->num_ue_to_reset; ++i) {
|
||||
if (!eq_f1ap_ue_to_reset(&a->ue_to_reset[i], &b->ue_to_reset[i]))
|
||||
return false;
|
||||
@@ -806,10 +807,10 @@ F1AP_F1AP_PDU_t *encode_f1ap_setup_request(const f1ap_setup_req_t *msg)
|
||||
bool decode_f1ap_setup_request(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_req_t *out)
|
||||
{
|
||||
/* Check presence of message type */
|
||||
_F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL");
|
||||
_F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_F1Setup);
|
||||
_F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_F1SetupRequest);
|
||||
_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_F1Setup);
|
||||
_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_F1SetupRequest);
|
||||
/* Check presence of mandatory IEs */
|
||||
F1AP_F1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.F1SetupRequest;
|
||||
F1AP_F1SetupRequestIEs_t *ie;
|
||||
@@ -823,13 +824,13 @@ bool decode_f1ap_setup_request(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_req_t *out
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_TransactionID:
|
||||
// Transaction ID (M)
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupRequestIEs__value_PR_TransactionID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupRequestIEs__value_PR_TransactionID);
|
||||
AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1");
|
||||
out->transaction_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_ID:
|
||||
// gNB-DU ID (M)
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupRequestIEs__value_PR_GNB_DU_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupRequestIEs__value_PR_GNB_DU_ID);
|
||||
asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, &out->gNB_DU_id);
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_Name: {
|
||||
@@ -971,19 +972,19 @@ f1ap_setup_req_t cp_f1ap_setup_request(const f1ap_setup_req_t *msg)
|
||||
*/
|
||||
bool eq_f1ap_setup_request(const f1ap_setup_req_t *a, const f1ap_setup_req_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_LONG(a->gNB_DU_id, b->gNB_DU_id);
|
||||
_F1_EQ_CHECK_STR(a->gNB_DU_name, b->gNB_DU_name);
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_F1_EQ_CHECK_INT(a->num_cells_available, b->num_cells_available);
|
||||
_EQ_CHECK_LONG(a->gNB_DU_id, b->gNB_DU_id);
|
||||
_EQ_CHECK_STR(a->gNB_DU_name, b->gNB_DU_name);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_INT(a->num_cells_available, b->num_cells_available);
|
||||
for (int i = 0; i < a->num_cells_available && i < F1AP_MAX_NB_CELLS; i++) {
|
||||
if (!eq_f1ap_cell_info(&a->cell[i].info, &b->cell[i].info))
|
||||
return false;
|
||||
if (!eq_f1ap_sys_info(a->cell[i].sys_info, b->cell[i].sys_info))
|
||||
return false;
|
||||
}
|
||||
_F1_EQ_CHECK_LONG(sizeofArray(a->rrc_ver), sizeofArray(b->rrc_ver));
|
||||
_EQ_CHECK_LONG(sizeofArray(a->rrc_ver), sizeofArray(b->rrc_ver));
|
||||
for (int i = 0; i < sizeofArray(a->rrc_ver); i++) {
|
||||
_F1_EQ_CHECK_INT(a->rrc_ver[i], b->rrc_ver[i]);
|
||||
_EQ_CHECK_INT(a->rrc_ver[i], b->rrc_ver[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1087,9 +1088,9 @@ F1AP_F1AP_PDU_t *encode_f1ap_setup_response(const f1ap_setup_resp_t *msg)
|
||||
bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *out)
|
||||
{
|
||||
/* Check presence of message type */
|
||||
_F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome);
|
||||
_F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_F1Setup);
|
||||
_F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, F1AP_SuccessfulOutcome__value_PR_F1SetupResponse);
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome);
|
||||
_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_F1Setup);
|
||||
_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, F1AP_SuccessfulOutcome__value_PR_F1SetupResponse);
|
||||
/* Check presence of mandatory IEs */
|
||||
F1AP_F1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse;
|
||||
F1AP_F1SetupResponseIEs_t *ie;
|
||||
@@ -1101,14 +1102,14 @@ bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *o
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_TransactionID:
|
||||
// Transaction ID (M)
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_TransactionID);
|
||||
AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1");
|
||||
out->transaction_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_TransactionID);
|
||||
AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1");
|
||||
out->transaction_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
|
||||
case F1AP_ProtocolIE_ID_id_gNB_CU_Name: {
|
||||
// gNB-CU Name (O)
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name);
|
||||
const F1AP_GNB_CU_Name_t *cu_name = &ie->value.choice.GNB_CU_Name;
|
||||
out->gNB_CU_name = calloc_or_fail(cu_name->size + 1, sizeof(*out->gNB_CU_name));
|
||||
strncpy(out->gNB_CU_name, (char *)cu_name->buf, cu_name->size);
|
||||
@@ -1116,18 +1117,18 @@ bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *o
|
||||
|
||||
case F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version:
|
||||
// gNB-CU RRC version (M)
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_RRC_Version);
|
||||
// RRC Version: "This IE is not used in this release."
|
||||
if (ie->value.choice.RRC_Version.iE_Extensions) {
|
||||
F1AP_ProtocolExtensionContainer_11023P233_t *ext =
|
||||
(F1AP_ProtocolExtensionContainer_11023P233_t *)ie->value.choice.RRC_Version.iE_Extensions;
|
||||
if (ext->list.count > 0) {
|
||||
F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0];
|
||||
OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_;
|
||||
for (int i = 0; i < sizeofArray(out->rrc_ver); i++)
|
||||
out->rrc_ver[i] = os->buf[i];
|
||||
}
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_RRC_Version);
|
||||
// RRC Version: "This IE is not used in this release."
|
||||
if (ie->value.choice.RRC_Version.iE_Extensions) {
|
||||
F1AP_ProtocolExtensionContainer_11023P233_t *ext =
|
||||
(F1AP_ProtocolExtensionContainer_11023P233_t *)ie->value.choice.RRC_Version.iE_Extensions;
|
||||
if (ext->list.count > 0) {
|
||||
F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0];
|
||||
OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_;
|
||||
for (int i = 0; i < sizeofArray(out->rrc_ver); i++)
|
||||
out->rrc_ver[i] = os->buf[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: {
|
||||
@@ -1161,17 +1162,17 @@ bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *o
|
||||
*/
|
||||
bool eq_f1ap_setup_response(const f1ap_setup_resp_t *a, const f1ap_setup_resp_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_STR(a->gNB_CU_name, b->gNB_CU_name);
|
||||
_F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate);
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_STR(a->gNB_CU_name, b->gNB_CU_name);
|
||||
_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
if (a->num_cells_to_activate) {
|
||||
for (int i = 0; i < a->num_cells_to_activate && i < F1AP_MAX_NB_CELLS; i++) {
|
||||
const served_cells_to_activate_t *a_cell = &a->cells_to_activate[i];
|
||||
const served_cells_to_activate_t *b_cell = &b->cells_to_activate[i];
|
||||
_F1_EQ_CHECK_LONG(a_cell->nr_cellid, b_cell->nr_cellid);
|
||||
_F1_EQ_CHECK_INT(a_cell->nrpci, b_cell->nrpci);
|
||||
_F1_EQ_CHECK_INT(a_cell->num_SI, b_cell->num_SI);
|
||||
_F1_EQ_CHECK_LONG(a_cell->nr_cellid, b_cell->nr_cellid);
|
||||
_EQ_CHECK_LONG(a_cell->nr_cellid, b_cell->nr_cellid);
|
||||
_EQ_CHECK_INT(a_cell->nrpci, b_cell->nrpci);
|
||||
_EQ_CHECK_INT(a_cell->num_SI, b_cell->num_SI);
|
||||
_EQ_CHECK_LONG(a_cell->nr_cellid, b_cell->nr_cellid);
|
||||
if (!eq_f1ap_plmn(&a_cell->plmn, &b_cell->plmn))
|
||||
return false;
|
||||
if (sizeofArray(a->cells_to_activate[i].SI_msg) != sizeofArray(b->cells_to_activate[i].SI_msg))
|
||||
@@ -1179,15 +1180,15 @@ bool eq_f1ap_setup_response(const f1ap_setup_resp_t *a, const f1ap_setup_resp_t
|
||||
for (int j = 0; j < b->cells_to_activate[i].num_SI; j++) {
|
||||
const f1ap_sib_msg_t *a_SI_msg = &a->cells_to_activate[i].SI_msg[j];
|
||||
const f1ap_sib_msg_t *b_SI_msg = &b->cells_to_activate[i].SI_msg[j];
|
||||
_F1_EQ_CHECK_INT(*a_SI_msg->SI_container, *b_SI_msg->SI_container);
|
||||
_F1_EQ_CHECK_INT(a_SI_msg->SI_container_length, b_SI_msg->SI_container_length);
|
||||
_F1_EQ_CHECK_INT(a_SI_msg->SI_type, b_SI_msg->SI_type);
|
||||
_EQ_CHECK_INT(*a_SI_msg->SI_container, *b_SI_msg->SI_container);
|
||||
_EQ_CHECK_INT(a_SI_msg->SI_container_length, b_SI_msg->SI_container_length);
|
||||
_EQ_CHECK_INT(a_SI_msg->SI_type, b_SI_msg->SI_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
_F1_EQ_CHECK_LONG(sizeofArray(a->rrc_ver), sizeofArray(b->rrc_ver));
|
||||
_EQ_CHECK_LONG(sizeofArray(a->rrc_ver), sizeofArray(b->rrc_ver));
|
||||
for (int i = 0; i < sizeofArray(a->rrc_ver); i++) {
|
||||
_F1_EQ_CHECK_INT(a->rrc_ver[i], b->rrc_ver[i]);
|
||||
_EQ_CHECK_INT(a->rrc_ver[i], b->rrc_ver[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1340,7 +1341,7 @@ bool decode_f1ap_setup_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_failure_t
|
||||
*/
|
||||
bool eq_f1ap_setup_failure(const f1ap_setup_failure_t *a, const f1ap_setup_failure_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1501,9 +1502,9 @@ F1AP_F1AP_PDU_t *encode_f1ap_du_configuration_update(const f1ap_gnb_du_configura
|
||||
bool decode_f1ap_du_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_du_configuration_update_t *out)
|
||||
{
|
||||
/* Check presence of message type */
|
||||
_F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
_F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_gNBDUConfigurationUpdate);
|
||||
_F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate);
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_gNBDUConfigurationUpdate);
|
||||
_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate);
|
||||
/* Check presence of mandatory IEs */
|
||||
F1AP_GNBDUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate;
|
||||
F1AP_GNBDUConfigurationUpdateIEs_t *ie;
|
||||
@@ -1638,10 +1639,10 @@ bool eq_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *a
|
||||
if ((a->gNB_DU_ID != NULL) ^ (b->gNB_DU_ID != NULL))
|
||||
return false;
|
||||
if (a->gNB_DU_ID != NULL && b->gNB_DU_ID != NULL)
|
||||
_F1_EQ_CHECK_LONG(*a->gNB_DU_ID, *b->gNB_DU_ID);
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_LONG(*a->gNB_DU_ID, *b->gNB_DU_ID);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
/* to add */
|
||||
_F1_EQ_CHECK_INT(a->num_cells_to_add, b->num_cells_to_add);
|
||||
_EQ_CHECK_INT(a->num_cells_to_add, b->num_cells_to_add);
|
||||
for (int i = 0; i < a->num_cells_to_add && i < F1AP_MAX_NB_CELLS; i++) {
|
||||
if (!eq_f1ap_cell_info(&a->cell_to_add[i].info, &b->cell_to_add[i].info))
|
||||
return false;
|
||||
@@ -1649,32 +1650,32 @@ bool eq_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *a
|
||||
return false;
|
||||
}
|
||||
/* to delete */
|
||||
_F1_EQ_CHECK_INT(a->num_cells_to_delete, b->num_cells_to_delete);
|
||||
_EQ_CHECK_INT(a->num_cells_to_delete, b->num_cells_to_delete);
|
||||
for (int i = 0; i < a->num_cells_to_delete && i < F1AP_MAX_NB_CELLS; i++) {
|
||||
_F1_EQ_CHECK_LONG(a->cell_to_delete[i].nr_cellid, b->cell_to_delete[i].nr_cellid);
|
||||
_EQ_CHECK_LONG(a->cell_to_delete[i].nr_cellid, b->cell_to_delete[i].nr_cellid);
|
||||
if (!eq_f1ap_plmn(&a->cell_to_delete[i].plmn, &b->cell_to_delete[i].plmn))
|
||||
return false;
|
||||
}
|
||||
/* to modify */
|
||||
_F1_EQ_CHECK_INT(a->num_cells_to_modify, b->num_cells_to_modify);
|
||||
_EQ_CHECK_INT(a->num_cells_to_modify, b->num_cells_to_modify);
|
||||
for (int i = 0; i < a->num_cells_to_modify && i < F1AP_MAX_NB_CELLS; i++) {
|
||||
if (!eq_f1ap_plmn(&a->cell_to_modify[i].old_plmn, &b->cell_to_modify[i].old_plmn))
|
||||
return false;
|
||||
_F1_EQ_CHECK_LONG(a->cell_to_modify[i].old_nr_cellid, b->cell_to_modify[i].old_nr_cellid);
|
||||
_EQ_CHECK_LONG(a->cell_to_modify[i].old_nr_cellid, b->cell_to_modify[i].old_nr_cellid);
|
||||
if (!eq_f1ap_cell_info(&a->cell_to_modify[i].info, &b->cell_to_modify[i].info))
|
||||
return false;
|
||||
if (!eq_f1ap_sys_info(a->cell_to_modify[i].sys_info, b->cell_to_modify[i].sys_info))
|
||||
return false;
|
||||
}
|
||||
/* cell status */
|
||||
_F1_EQ_CHECK_INT(a->num_status, b->num_status);
|
||||
_EQ_CHECK_INT(a->num_status, b->num_status);
|
||||
for (int i = 0; i < a->num_status && i < F1AP_MAX_NB_CELLS; ++i) {
|
||||
const f1ap_cell_status_t *astatus = &a->status[i];
|
||||
const f1ap_cell_status_t *bstatus = &b->status[i];
|
||||
if (!eq_f1ap_plmn(&astatus->plmn, &bstatus->plmn))
|
||||
return false;
|
||||
_F1_EQ_CHECK_LONG(astatus->nr_cellid, bstatus->nr_cellid);
|
||||
_F1_EQ_CHECK_INT(astatus->service_state, bstatus->service_state);
|
||||
_EQ_CHECK_LONG(astatus->nr_cellid, bstatus->nr_cellid);
|
||||
_EQ_CHECK_INT(astatus->service_state, bstatus->service_state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1770,10 +1771,10 @@ F1AP_F1AP_PDU_t *encode_f1ap_cu_configuration_update(const f1ap_gnb_cu_configura
|
||||
bool decode_f1ap_cu_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_cu_configuration_update_t *out)
|
||||
{
|
||||
/* Check presence of message type */
|
||||
_F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL");
|
||||
_F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_gNBCUConfigurationUpdate);
|
||||
_F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate);
|
||||
_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_gNBCUConfigurationUpdate);
|
||||
_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate);
|
||||
/* Check presence of mandatory IEs */
|
||||
F1AP_GNBCUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate;
|
||||
F1AP_GNBCUConfigurationUpdateIEs_t *ie;
|
||||
@@ -1783,13 +1784,13 @@ bool decode_f1ap_cu_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_cu
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_TransactionID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID);
|
||||
AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1");
|
||||
out->transaction_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: {
|
||||
/* Cells to be Activated List (O) */
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List);
|
||||
/* Cells to be Activated List Item (count >= 1) */
|
||||
F1AP_Cells_to_be_Activated_List_t *Cells_to_be_Activated_List = &ie->value.choice.Cells_to_be_Activated_List;
|
||||
out->num_cells_to_activate = Cells_to_be_Activated_List->list.count;
|
||||
@@ -1823,21 +1824,21 @@ void free_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t
|
||||
*/
|
||||
bool eq_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *a, const f1ap_gnb_cu_configuration_update_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
/* to activate */
|
||||
_F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate);
|
||||
_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate);
|
||||
for (int i = 0; i < a->num_cells_to_activate && i < F1AP_MAX_NB_CELLS; i++) {
|
||||
_F1_EQ_CHECK_LONG(a->cells_to_activate[i].nr_cellid, b->cells_to_activate[i].nr_cellid);
|
||||
_F1_EQ_CHECK_INT(a->cells_to_activate[i].nrpci, b->cells_to_activate[i].nrpci);
|
||||
_EQ_CHECK_LONG(a->cells_to_activate[i].nr_cellid, b->cells_to_activate[i].nr_cellid);
|
||||
_EQ_CHECK_INT(a->cells_to_activate[i].nrpci, b->cells_to_activate[i].nrpci);
|
||||
if (!eq_f1ap_plmn(&a->cells_to_activate[i].plmn, &b->cells_to_activate[i].plmn))
|
||||
return false;
|
||||
_F1_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI);
|
||||
_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI);
|
||||
for (int s = 0; s < a->cells_to_activate[i].num_SI; s++) {
|
||||
f1ap_sib_msg_t *a_sib_msg = &a->cells_to_activate[i].SI_msg[s];
|
||||
f1ap_sib_msg_t *b_sib_msg = &b->cells_to_activate[i].SI_msg[s];
|
||||
_F1_EQ_CHECK_INT(*a_sib_msg->SI_container, *b_sib_msg->SI_container);
|
||||
_F1_EQ_CHECK_INT(a_sib_msg->SI_container_length, b_sib_msg->SI_container_length);
|
||||
_F1_EQ_CHECK_INT(a_sib_msg->SI_type, b_sib_msg->SI_type);
|
||||
_EQ_CHECK_INT(*a_sib_msg->SI_container, *b_sib_msg->SI_container);
|
||||
_EQ_CHECK_INT(a_sib_msg->SI_container_length, b_sib_msg->SI_container_length);
|
||||
_EQ_CHECK_INT(a_sib_msg->SI_type, b_sib_msg->SI_type);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1925,11 +1926,10 @@ bool decode_f1ap_cu_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu,
|
||||
f1ap_gnb_cu_configuration_update_acknowledge_t *out)
|
||||
{
|
||||
/* Message type */
|
||||
_F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome);
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome);
|
||||
AssertError(pdu->choice.successfulOutcome != NULL, return false, "pdu->choice.successfulOutcome is NULL");
|
||||
_F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_gNBCUConfigurationUpdate);
|
||||
_F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present,
|
||||
F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge);
|
||||
_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_gNBCUConfigurationUpdate);
|
||||
_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge);
|
||||
/* payload */
|
||||
F1AP_GNBCUConfigurationUpdateAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.GNBCUConfigurationUpdateAcknowledge;
|
||||
F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t *ie;
|
||||
@@ -1940,14 +1940,13 @@ bool decode_f1ap_cu_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu,
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_TransactionID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID);
|
||||
AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1");
|
||||
out->transaction_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_Cells_Failed_to_be_Activated_List: {
|
||||
/* Decode Cells Failed to be Activated List */
|
||||
_F1_EQ_CHECK_INT(ie->value.present,
|
||||
F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_Failed_to_be_Activated_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_Failed_to_be_Activated_List);
|
||||
F1AP_Cells_Failed_to_be_Activated_List_t *cell_fail_list = &ie->value.choice.Cells_Failed_to_be_Activated_List;
|
||||
out->num_cells_failed_to_be_activated = cell_fail_list->list.count;
|
||||
out->cells_failed_to_be_activated =
|
||||
@@ -1996,36 +1995,36 @@ bool eq_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration
|
||||
const f1ap_gnb_cu_configuration_update_acknowledge_t *b)
|
||||
{
|
||||
// Transaction ID
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
// number of cells failed to be activated
|
||||
_F1_EQ_CHECK_INT(a->num_cells_failed_to_be_activated, b->num_cells_failed_to_be_activated);
|
||||
_EQ_CHECK_INT(a->num_cells_failed_to_be_activated, b->num_cells_failed_to_be_activated);
|
||||
for (int i = 0; i < a->num_cells_failed_to_be_activated && i < F1AP_MAX_NB_CELLS; i++) {
|
||||
if (!eq_f1ap_plmn(&a->cells_failed_to_be_activated[i].plmn, &b->cells_failed_to_be_activated[i].plmn))
|
||||
return false;
|
||||
_F1_EQ_CHECK_LONG(a->cells_failed_to_be_activated[i].nr_cellid, b->cells_failed_to_be_activated[i].nr_cellid);
|
||||
_F1_EQ_CHECK_INT(a->cells_failed_to_be_activated[i].cause, b->cells_failed_to_be_activated[i].cause);
|
||||
_EQ_CHECK_LONG(a->cells_failed_to_be_activated[i].nr_cellid, b->cells_failed_to_be_activated[i].nr_cellid);
|
||||
_EQ_CHECK_INT(a->cells_failed_to_be_activated[i].cause, b->cells_failed_to_be_activated[i].cause);
|
||||
}
|
||||
// TNL Associations to setup
|
||||
_F1_EQ_CHECK_INT(a->noofTNLAssociations_to_setup, b->noofTNLAssociations_to_setup);
|
||||
_EQ_CHECK_INT(a->noofTNLAssociations_to_setup, b->noofTNLAssociations_to_setup);
|
||||
for (int i = 0; i < a->noofTNLAssociations_to_setup && i < F1AP_MAX_NO_OF_TNL_ASSOCIATIONS; i++) {
|
||||
// Explicit comparison of TNL Association fields
|
||||
_F1_EQ_CHECK_INT(a->tnlAssociations_to_setup[i].tl_address, b->tnlAssociations_to_setup[i].tl_address);
|
||||
_F1_EQ_CHECK_INT(a->tnlAssociations_to_setup[i].port, b->tnlAssociations_to_setup[i].port);
|
||||
_EQ_CHECK_INT(a->tnlAssociations_to_setup[i].tl_address, b->tnlAssociations_to_setup[i].tl_address);
|
||||
_EQ_CHECK_INT(a->tnlAssociations_to_setup[i].port, b->tnlAssociations_to_setup[i].port);
|
||||
}
|
||||
// TNL Associations failed to setup
|
||||
_F1_EQ_CHECK_INT(a->noofTNLAssociations_failed, b->noofTNLAssociations_failed);
|
||||
_EQ_CHECK_INT(a->noofTNLAssociations_failed, b->noofTNLAssociations_failed);
|
||||
for (int i = 0; i < a->noofTNLAssociations_failed && i < F1AP_MAX_NO_OF_TNL_ASSOCIATIONS; i++) {
|
||||
// Explicit comparison of TNL Association fields
|
||||
_F1_EQ_CHECK_INT(a->tnlAssociations_failed[i].tl_address, b->tnlAssociations_failed[i].tl_address);
|
||||
_F1_EQ_CHECK_INT(a->tnlAssociations_failed[i].port, b->tnlAssociations_failed[i].port);
|
||||
_EQ_CHECK_INT(a->tnlAssociations_failed[i].tl_address, b->tnlAssociations_failed[i].tl_address);
|
||||
_EQ_CHECK_INT(a->tnlAssociations_failed[i].port, b->tnlAssociations_failed[i].port);
|
||||
}
|
||||
// Dedicated SI Delivery Needed UE List
|
||||
_F1_EQ_CHECK_INT(a->noofDedicatedSIDeliveryNeededUEs, b->noofDedicatedSIDeliveryNeededUEs);
|
||||
_EQ_CHECK_INT(a->noofDedicatedSIDeliveryNeededUEs, b->noofDedicatedSIDeliveryNeededUEs);
|
||||
for (int i = 0; i < a->noofDedicatedSIDeliveryNeededUEs && i < F1AP_MAX_NO_UE_ID; i++) {
|
||||
_F1_EQ_CHECK_INT(a->dedicatedSIDeliveryNeededUEs[i].gNB_CU_ue_id, b->dedicatedSIDeliveryNeededUEs[i].gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->dedicatedSIDeliveryNeededUEs[i].gNB_CU_ue_id, b->dedicatedSIDeliveryNeededUEs[i].gNB_CU_ue_id);
|
||||
if (!eq_f1ap_plmn(&a->dedicatedSIDeliveryNeededUEs[i].ue_plmn, &b->dedicatedSIDeliveryNeededUEs[i].ue_plmn))
|
||||
return false;
|
||||
_F1_EQ_CHECK_LONG(a->dedicatedSIDeliveryNeededUEs[i].ue_nr_cellid, b->dedicatedSIDeliveryNeededUEs[i].ue_nr_cellid);
|
||||
_EQ_CHECK_LONG(a->dedicatedSIDeliveryNeededUEs[i].ue_nr_cellid, b->dedicatedSIDeliveryNeededUEs[i].ue_nr_cellid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2115,11 +2114,10 @@ bool decode_f1ap_du_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu,
|
||||
f1ap_gnb_du_configuration_update_acknowledge_t *out)
|
||||
{
|
||||
/* message type */
|
||||
_F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome);
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome);
|
||||
AssertError(pdu->choice.successfulOutcome != NULL, return false, "pdu->choice.successfulOutcome is NULL");
|
||||
_F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_gNBDUConfigurationUpdate);
|
||||
_F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present,
|
||||
F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge);
|
||||
_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_gNBDUConfigurationUpdate);
|
||||
_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge);
|
||||
F1AP_GNBDUConfigurationUpdateAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.GNBDUConfigurationUpdateAcknowledge;
|
||||
F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t *ie;
|
||||
/* Check mandatory IEs */
|
||||
@@ -2129,13 +2127,13 @@ bool decode_f1ap_du_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu,
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_TransactionID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID);
|
||||
AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1");
|
||||
out->transaction_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: {
|
||||
/* Decode Cells Failed to be Activated List */
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_to_be_Activated_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_to_be_Activated_List);
|
||||
F1AP_Cells_to_be_Activated_List_t *list = &ie->value.choice.Cells_to_be_Activated_List;
|
||||
out->num_cells_to_activate = list->list.count;
|
||||
out->cells_to_activate = calloc_or_fail(out->num_cells_to_activate, sizeof(*out->cells_to_activate));
|
||||
@@ -2161,21 +2159,20 @@ bool eq_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration
|
||||
const f1ap_gnb_du_configuration_update_acknowledge_t *b)
|
||||
{
|
||||
// Transaction ID
|
||||
_F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_LONG(a->transaction_id, b->transaction_id);
|
||||
// number of cells to activate
|
||||
_F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate);
|
||||
_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate);
|
||||
// loop over cells to activate
|
||||
for (int i = 0; i < a->num_cells_to_activate && i < F1AP_MAX_NB_CELLS; i++) {
|
||||
_F1_EQ_CHECK_LONG(a->cells_to_activate[i].nr_cellid, b->cells_to_activate[i].nr_cellid);
|
||||
_F1_EQ_CHECK_INT(a->cells_to_activate[i].nrpci, b->cells_to_activate[i].nrpci);
|
||||
_EQ_CHECK_LONG(a->cells_to_activate[i].nr_cellid, b->cells_to_activate[i].nr_cellid);
|
||||
_EQ_CHECK_INT(a->cells_to_activate[i].nrpci, b->cells_to_activate[i].nrpci);
|
||||
if (!eq_f1ap_plmn(&a->cells_to_activate[i].plmn, &b->cells_to_activate[i].plmn))
|
||||
return false;
|
||||
_F1_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI);
|
||||
_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI);
|
||||
for (int s = 0; s < a->cells_to_activate[i].num_SI; s++) {
|
||||
_F1_EQ_CHECK_INT(*a->cells_to_activate[i].SI_msg[s].SI_container, *b->cells_to_activate[i].SI_msg[s].SI_container);
|
||||
_F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_container_length,
|
||||
b->cells_to_activate[i].SI_msg[s].SI_container_length);
|
||||
_F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_type, b->cells_to_activate[i].SI_msg[s].SI_type);
|
||||
_EQ_CHECK_INT(*a->cells_to_activate[i].SI_msg[s].SI_container, *b->cells_to_activate[i].SI_msg[s].SI_container);
|
||||
_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_container_length, b->cells_to_activate[i].SI_msg[s].SI_container_length);
|
||||
_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_type, b->cells_to_activate[i].SI_msg[s].SI_type);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -29,40 +29,40 @@
|
||||
|
||||
bool eq_f1ap_plmn(const plmn_id_t *a, const plmn_id_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->mcc, b->mcc);
|
||||
_F1_EQ_CHECK_INT(a->mnc, b->mnc);
|
||||
_F1_EQ_CHECK_INT(a->mnc_digit_length, b->mnc_digit_length);
|
||||
_EQ_CHECK_INT(a->mcc, b->mcc);
|
||||
_EQ_CHECK_INT(a->mnc, b->mnc);
|
||||
_EQ_CHECK_INT(a->mnc_digit_length, b->mnc_digit_length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eq_f1ap_freq_info(const f1ap_nr_frequency_info_t *a, const f1ap_nr_frequency_info_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->arfcn, b->arfcn);
|
||||
_F1_EQ_CHECK_INT(a->band, b->band);
|
||||
_EQ_CHECK_INT(a->arfcn, b->arfcn);
|
||||
_EQ_CHECK_INT(a->band, b->band);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eq_f1ap_tx_bandwidth(const f1ap_transmission_bandwidth_t *a, const f1ap_transmission_bandwidth_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->nrb, b->nrb);
|
||||
_F1_EQ_CHECK_INT(a->scs, b->scs);
|
||||
_EQ_CHECK_INT(a->nrb, b->nrb);
|
||||
_EQ_CHECK_INT(a->scs, b->scs);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eq_f1ap_cell_info(const f1ap_served_cell_info_t *a, const f1ap_served_cell_info_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid);
|
||||
_F1_EQ_CHECK_INT(a->nr_pci, b->nr_pci);
|
||||
_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid);
|
||||
_EQ_CHECK_INT(a->nr_pci, b->nr_pci);
|
||||
if ((!a->tac) ^ (!b->tac))
|
||||
return false;
|
||||
if (a->tac)
|
||||
_F1_EQ_CHECK_INT(*a->tac, *b->tac);
|
||||
_F1_EQ_CHECK_INT(a->num_ssi, b->num_ssi);
|
||||
_EQ_CHECK_INT(*a->tac, *b->tac);
|
||||
_EQ_CHECK_INT(a->num_ssi, b->num_ssi);
|
||||
for (int i = 0; i < a->num_ssi; ++i) {
|
||||
_F1_EQ_CHECK_INT(a->nssai[i].sst, b->nssai[i].sst);
|
||||
_F1_EQ_CHECK_INT(a->nssai[i].sd, b->nssai[i].sd);
|
||||
_EQ_CHECK_INT(a->nssai[i].sst, b->nssai[i].sst);
|
||||
_EQ_CHECK_INT(a->nssai[i].sd, b->nssai[i].sd);
|
||||
}
|
||||
_F1_EQ_CHECK_INT(a->mode, b->mode);
|
||||
_EQ_CHECK_INT(a->mode, b->mode);
|
||||
if (a->mode == F1AP_MODE_TDD) {
|
||||
/* TDD */
|
||||
if (!eq_f1ap_tx_bandwidth(&a->tdd.tbw, &b->tdd.tbw))
|
||||
@@ -80,8 +80,8 @@ bool eq_f1ap_cell_info(const f1ap_served_cell_info_t *a, const f1ap_served_cell_
|
||||
if (!eq_f1ap_freq_info(&a->fdd.ul_freqinfo, &b->fdd.ul_freqinfo))
|
||||
return false;
|
||||
}
|
||||
_F1_EQ_CHECK_INT(a->measurement_timing_config_len, b->measurement_timing_config_len);
|
||||
_F1_EQ_CHECK_INT(*a->measurement_timing_config, *b->measurement_timing_config);
|
||||
_EQ_CHECK_INT(a->measurement_timing_config_len, b->measurement_timing_config_len);
|
||||
_EQ_CHECK_INT(*a->measurement_timing_config, *b->measurement_timing_config);
|
||||
if (!eq_f1ap_plmn(&a->plmn, &b->plmn))
|
||||
return false;
|
||||
return true;
|
||||
@@ -97,13 +97,13 @@ bool eq_f1ap_sys_info(const f1ap_gnb_du_system_info_t *a, const f1ap_gnb_du_syst
|
||||
return false;
|
||||
|
||||
/* MIB */
|
||||
_F1_EQ_CHECK_INT(a->mib_length, b->mib_length);
|
||||
_EQ_CHECK_INT(a->mib_length, b->mib_length);
|
||||
for (int i = 0; i < a->mib_length; i++)
|
||||
_F1_EQ_CHECK_INT(a->mib[i], b->mib[i]);
|
||||
_EQ_CHECK_INT(a->mib[i], b->mib[i]);
|
||||
/* SIB1 */
|
||||
_F1_EQ_CHECK_INT(a->sib1_length, b->sib1_length);
|
||||
_EQ_CHECK_INT(a->sib1_length, b->sib1_length);
|
||||
for (int i = 0; i < a->sib1_length; i++)
|
||||
_F1_EQ_CHECK_INT(a->sib1[i], b->sib1[i]);
|
||||
_EQ_CHECK_INT(a->sib1[i], b->sib1[i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,24 +32,7 @@
|
||||
#include "F1AP_Cause.h"
|
||||
#include "F1AP_SNSSAI.h"
|
||||
#include "f1ap_messages_types.h"
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
#define PRINT_ERROR(fmt, ...) fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define PRINT_ERROR(...) // Do nothing
|
||||
#endif
|
||||
|
||||
#define _F1_EQ_CHECK_GENERIC(condition, fmt, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
PRINT_ERROR("Equality condition '%s' failed: " fmt " != " fmt "\n", #condition, ##__VA_ARGS__); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _F1_EQ_CHECK_LONG(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%ld", A, B);
|
||||
#define _F1_EQ_CHECK_INT(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%d", A, B);
|
||||
#define _F1_EQ_CHECK_STR(A, B) _F1_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B);
|
||||
#include "common/utils/eq_check.h"
|
||||
|
||||
#define _F1_CHECK_EXP(EXP) \
|
||||
do { \
|
||||
@@ -59,13 +42,6 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _F1_EQ_CHECK_OPTIONAL_IE(A, B, FIELD, EQ_MACRO) \
|
||||
do { \
|
||||
_F1_CHECK_EXP(((A)->FIELD && (B)->FIELD) || (!(A)->FIELD && !(B)->FIELD)); \
|
||||
if ((A)->FIELD && (B)->FIELD) \
|
||||
EQ_MACRO(*(A)->FIELD, *(B)->FIELD); \
|
||||
} while (0)
|
||||
|
||||
/* macro to look up IE. If mandatory and not found, macro will print
|
||||
* descriptive debug message to stderr and force exit in calling function */
|
||||
#define F1AP_LIB_FIND_IE(IE_TYPE, ie, IE_LIST, IE_ID, mandatory) \
|
||||
|
||||
@@ -90,5 +90,9 @@
|
||||
#include "F1AP_UL-RTOA-Measurement.h"
|
||||
#include "F1AP_GNB-RxTxTimeDiff.h"
|
||||
#include "F1AP_LCS-to-GCS-TranslationAoA.h"
|
||||
#include "F1AP_CNUEPagingIdentity.h"
|
||||
#include "F1AP_RANUEPagingIdentity.h"
|
||||
#include "F1AP_PagingIdentity.h"
|
||||
#include "F1AP_Paging.h"
|
||||
|
||||
#endif /* F1AP_LIB_INCLUDES_H_ */
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "common/utils/assertions.h"
|
||||
#include "openair3/UTILS/conversions.h"
|
||||
#include "common/utils/oai_asn1.h"
|
||||
#include "common/utils/utils.h"
|
||||
|
||||
#include "f1ap_paging.h"
|
||||
#include "f1ap_lib_common.h"
|
||||
#include "f1ap_lib_includes.h"
|
||||
#include "f1ap_messages_types.h"
|
||||
|
||||
/** @brief encode to F1AP_PagingDRX_t */
|
||||
static F1AP_PagingDRX_t encode_f1_paging_drx(const f1ap_paging_drx_t drx)
|
||||
{
|
||||
switch (drx) {
|
||||
case F1AP_PAGING_DRX_32:
|
||||
return F1AP_PagingDRX_v32;
|
||||
case F1AP_PAGING_DRX_64:
|
||||
return F1AP_PagingDRX_v64;
|
||||
case F1AP_PAGING_DRX_128:
|
||||
return F1AP_PagingDRX_v128;
|
||||
case F1AP_PAGING_DRX_256:
|
||||
return F1AP_PagingDRX_v256;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Unknown Paging DRX: %u\n", drx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief decode from F1AP_PagingDRX_t */
|
||||
static f1ap_paging_drx_t decode_f1_paging_drx(const F1AP_PagingDRX_t drx)
|
||||
{
|
||||
switch (drx) {
|
||||
case F1AP_PagingDRX_v32:
|
||||
return F1AP_PAGING_DRX_32;
|
||||
case F1AP_PagingDRX_v64:
|
||||
return F1AP_PAGING_DRX_64;
|
||||
case F1AP_PagingDRX_v128:
|
||||
return F1AP_PAGING_DRX_128;
|
||||
case F1AP_PagingDRX_v256:
|
||||
return F1AP_PAGING_DRX_256;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Unknown Paging DRX: %ld\n", drx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief encode F1 Paging (9.2.6 Paging 3GPP TS 38.473) */
|
||||
F1AP_F1AP_PDU_t *encode_f1ap_paging(const f1ap_paging_t *msg)
|
||||
{
|
||||
DevAssert(msg);
|
||||
F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
|
||||
|
||||
pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu->choice.initiatingMessage, initMsg);
|
||||
initMsg->procedureCode = F1AP_ProcedureCode_id_Paging;
|
||||
initMsg->criticality = F1AP_Criticality_reject;
|
||||
initMsg->value.present = F1AP_InitiatingMessage__value_PR_Paging;
|
||||
F1AP_Paging_t *paging = &initMsg->value.choice.Paging;
|
||||
|
||||
/* UEIdentityIndexValue (Mandatory) 10 bits */
|
||||
{
|
||||
AssertFatal(msg->ue_identity_index_value <= 1023,
|
||||
"UE Identity Index Value exceeds 10 bits: %d\n",
|
||||
msg->ue_identity_index_value);
|
||||
asn1cSequenceAdd(paging->protocolIEs.list, F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_UEIdentityIndexValue;
|
||||
ie->criticality = F1AP_Criticality_reject;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_UEIdentityIndexValue;
|
||||
F1AP_UEIdentityIndexValue_t *ue_identity_index = &ie->value.choice.UEIdentityIndexValue;
|
||||
ue_identity_index->present = F1AP_UEIdentityIndexValue_PR_indexLength10;
|
||||
UEIDENTITYINDEX_TO_BIT_STRING(msg->ue_identity_index_value, &ue_identity_index->choice.indexLength10);
|
||||
}
|
||||
|
||||
/* PagingIdentity (Mandatory) */
|
||||
{
|
||||
asn1cSequenceAdd(paging->protocolIEs.list, F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_PagingIdentity;
|
||||
ie->criticality = F1AP_Criticality_reject;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_PagingIdentity;
|
||||
|
||||
F1AP_PagingIdentity_t *paging_identity = &ie->value.choice.PagingIdentity;
|
||||
const f1ap_paging_identity_t *paging_id = &msg->identity;
|
||||
|
||||
if (msg->identity_type == F1AP_PAGING_IDENTITY_CN_UE) {
|
||||
// CN UE Paging Identity (5G-S-TMSI)
|
||||
paging_identity->present = F1AP_PagingIdentity_PR_cNUEPagingIdentity;
|
||||
asn1cCalloc(paging_identity->choice.cNUEPagingIdentity, id);
|
||||
id->present = F1AP_CNUEPagingIdentity_PR_fiveG_S_TMSI;
|
||||
FIVEG_S_TMSI_TO_BIT_STRING(paging_id->cn_ue_paging_identity, &id->choice.fiveG_S_TMSI);
|
||||
} else {
|
||||
// RAN UE Paging Identity (I-RNTI)
|
||||
paging_identity->present = F1AP_PagingIdentity_PR_rANUEPagingIdentity;
|
||||
asn1cCalloc(paging_identity->choice.rANUEPagingIdentity, ran_id);
|
||||
// I-RNTI is 40 bits, stored in 5 bytes
|
||||
IRNTI_TO_BIT_STRING(paging_id->ran_ue_paging_identity, &ran_id->iRNTI);
|
||||
}
|
||||
}
|
||||
|
||||
/* Paging Priority (Optional) */
|
||||
if (msg->priority != NULL) {
|
||||
AssertFatal(*msg->priority >= F1AP_PAGING_PRIO_LEVEL1 && *msg->priority <= F1AP_PAGING_PRIO_LEVEL8,
|
||||
"Unknown Paging Priority: %d\n",
|
||||
*msg->priority);
|
||||
asn1cSequenceAdd(paging->protocolIEs.list, F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_PagingPriority;
|
||||
ie->criticality = F1AP_Criticality_ignore;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_PagingPriority;
|
||||
ie->value.choice.PagingPriority = (F1AP_PagingPriority_t)*msg->priority;
|
||||
}
|
||||
|
||||
/* Paging Origin (Optional) */
|
||||
if (msg->origin != NULL) {
|
||||
AssertFatal(*msg->origin == F1AP_PAGING_ORIGIN_NON_3GPP, "Unknown Paging Origin: %d\n", *msg->origin);
|
||||
asn1cSequenceAdd(paging->protocolIEs.list, F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_PagingOrigin;
|
||||
ie->criticality = F1AP_Criticality_ignore;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_PagingOrigin;
|
||||
ie->value.choice.PagingOrigin = F1AP_PagingOrigin_non_3gpp;
|
||||
}
|
||||
|
||||
/* PagingDRX (Optional) */
|
||||
if (msg->drx != NULL) {
|
||||
asn1cSequenceAdd(paging->protocolIEs.list, F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_PagingDRX;
|
||||
ie->criticality = F1AP_Criticality_ignore;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_PagingDRX;
|
||||
ie->value.choice.PagingDRX = encode_f1_paging_drx(*msg->drx);
|
||||
}
|
||||
|
||||
/* PagingCell_list (Mandatory) */
|
||||
{
|
||||
AssertFatal(msg->n_cells > 0 && msg->n_cells <= F1AP_MAX_NB_CELLS,
|
||||
"invalid n_cells %u (must be 1..%d)\n",
|
||||
msg->n_cells,
|
||||
F1AP_MAX_NB_CELLS);
|
||||
DevAssert(msg->cells != NULL);
|
||||
asn1cSequenceAdd(paging->protocolIEs.list, F1AP_PagingIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_PagingCell_List;
|
||||
ie->criticality = F1AP_Criticality_reject;
|
||||
ie->value.present = F1AP_PagingIEs__value_PR_PagingCell_list;
|
||||
|
||||
// Add all cells in the paging cell list
|
||||
for (uint16_t cell_idx = 0; cell_idx < msg->n_cells; cell_idx++) {
|
||||
asn1cSequenceAdd(ie->value.choice.PagingCell_list, F1AP_PagingCell_ItemIEs_t, item);
|
||||
item->id = F1AP_ProtocolIE_ID_id_PagingCell_Item;
|
||||
item->criticality = F1AP_Criticality_reject;
|
||||
item->value.present = F1AP_PagingCell_ItemIEs__value_PR_PagingCell_Item;
|
||||
// NRCGI (Mandatory)
|
||||
F1AP_NRCGI_t *nRCGI = &item->value.choice.PagingCell_Item.nRCGI;
|
||||
const f1ap_paging_cell_item_t *cell = &msg->cells[cell_idx];
|
||||
MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &nRCGI->pLMN_Identity);
|
||||
NR_CELL_ID_TO_BIT_STRING(cell->nr_cellid, &nRCGI->nRCellIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/** @brief decode F1 Paging (9.2.6 Paging 3GPP TS 38.473) */
|
||||
bool decode_f1ap_paging(f1ap_paging_t *out, const F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(out);
|
||||
DevAssert(pdu);
|
||||
DevAssert(pdu->choice.initiatingMessage);
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage);
|
||||
_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_Paging);
|
||||
_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_Paging);
|
||||
|
||||
/* Check presence of mandatory IEs */
|
||||
const F1AP_Paging_t *in = &pdu->choice.initiatingMessage->value.choice.Paging;
|
||||
F1AP_PagingIEs_t *ie;
|
||||
F1AP_LIB_FIND_IE(F1AP_PagingIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_UEIdentityIndexValue, true);
|
||||
F1AP_LIB_FIND_IE(F1AP_PagingIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_PagingIdentity, true);
|
||||
F1AP_LIB_FIND_IE(F1AP_PagingIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_PagingCell_List, true);
|
||||
|
||||
/* Loop over all IEs */
|
||||
for (int i = 0; i < in->protocolIEs.list.count; i++) {
|
||||
DevAssert(in->protocolIEs.list.array[i] != NULL);
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_UEIdentityIndexValue:
|
||||
// (M) UE Identity Index Value
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_PagingIEs__value_PR_UEIdentityIndexValue);
|
||||
out->ue_identity_index_value = BIT_STRING_to_uint32(&ie->value.choice.UEIdentityIndexValue.choice.indexLength10);
|
||||
break;
|
||||
|
||||
case F1AP_ProtocolIE_ID_id_PagingIdentity:
|
||||
// (M) Paging Identity
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_PagingIEs__value_PR_PagingIdentity);
|
||||
if (ie->value.choice.PagingIdentity.present == F1AP_PagingIdentity_PR_cNUEPagingIdentity) {
|
||||
// CN UE Paging Identity (5G-S-TMSI)
|
||||
out->identity_type = F1AP_PAGING_IDENTITY_CN_UE;
|
||||
BIT_STRING_t *fiveg_tmsi = &ie->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI;
|
||||
out->identity.cn_ue_paging_identity = BIT_STRING_to_uint64(fiveg_tmsi);
|
||||
} else if (ie->value.choice.PagingIdentity.present == F1AP_PagingIdentity_PR_rANUEPagingIdentity) {
|
||||
// RAN UE Paging Identity (I-RNTI)
|
||||
out->identity_type = F1AP_PAGING_IDENTITY_RAN_UE;
|
||||
BIT_STRING_t *irnti = &ie->value.choice.PagingIdentity.choice.rANUEPagingIdentity->iRNTI;
|
||||
out->identity.ran_ue_paging_identity = BIT_STRING_to_uint64(irnti);
|
||||
} else {
|
||||
PRINT_ERROR("Unknown PagingIdentity type: %d\n", ie->value.choice.PagingIdentity.present);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case F1AP_ProtocolIE_ID_id_PagingDRX:
|
||||
// (O) Paging DRX
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_PagingIEs__value_PR_PagingDRX);
|
||||
out->drx = malloc_or_fail(sizeof(*out->drx));
|
||||
*out->drx = decode_f1_paging_drx(ie->value.choice.PagingDRX);
|
||||
break;
|
||||
|
||||
case F1AP_ProtocolIE_ID_id_PagingPriority:
|
||||
// (O) Paging Priority
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_PagingIEs__value_PR_PagingPriority);
|
||||
AssertFatal(ie->value.choice.PagingPriority >= F1AP_PagingPriority_priolevel1
|
||||
&& ie->value.choice.PagingPriority <= F1AP_PagingPriority_priolevel8,
|
||||
"Unknown Paging Priority: %ld\n",
|
||||
ie->value.choice.PagingPriority);
|
||||
out->priority = malloc_or_fail(sizeof(*out->priority));
|
||||
*out->priority = (f1ap_paging_priority_t)ie->value.choice.PagingPriority;
|
||||
break;
|
||||
|
||||
case F1AP_ProtocolIE_ID_id_PagingOrigin:
|
||||
// (O) Paging Origin
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_PagingIEs__value_PR_PagingOrigin);
|
||||
AssertFatal(ie->value.choice.PagingOrigin == F1AP_PagingOrigin_non_3gpp,
|
||||
"Unknown Paging Origin: %ld\n",
|
||||
ie->value.choice.PagingOrigin);
|
||||
out->origin = malloc_or_fail(sizeof(*out->origin));
|
||||
*out->origin = F1AP_PAGING_ORIGIN_NON_3GPP;
|
||||
break;
|
||||
|
||||
case F1AP_ProtocolIE_ID_id_PagingCell_List:
|
||||
// (M) Paging Cell List (max 512 cells)
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_PagingIEs__value_PR_PagingCell_list);
|
||||
out->n_cells = ie->value.choice.PagingCell_list.list.count;
|
||||
AssertError(out->n_cells > 0, return false, "at least 1 cell must be present");
|
||||
AssertError(out->n_cells <= F1AP_MAX_NB_CELLS, return false, "too many cells");
|
||||
out->cells = calloc_or_fail(out->n_cells, sizeof(*out->cells));
|
||||
for (int j = 0; j < out->n_cells; j++) {
|
||||
F1AP_PagingCell_ItemIEs_t *cell_item = (F1AP_PagingCell_ItemIEs_t *)ie->value.choice.PagingCell_list.list.array[j];
|
||||
DevAssert(cell_item);
|
||||
F1AP_NRCGI_t *nRCGI = &cell_item->value.choice.PagingCell_Item.nRCGI;
|
||||
f1ap_paging_cell_item_t *cell = &out->cells[j];
|
||||
PLMNID_TO_MCC_MNC(&nRCGI->pLMN_Identity, cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length);
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&nRCGI->nRCellIdentity, cell->nr_cellid);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief free F1 Paging */
|
||||
void free_f1ap_paging(f1ap_paging_t *msg)
|
||||
{
|
||||
DevAssert(msg);
|
||||
free(msg->drx);
|
||||
free(msg->priority);
|
||||
free(msg->origin);
|
||||
free(msg->cells);
|
||||
}
|
||||
|
||||
/** @brief Equality check for two F1 Paging */
|
||||
bool eq_f1ap_paging(const f1ap_paging_t *a, const f1ap_paging_t *b)
|
||||
{
|
||||
DevAssert(a);
|
||||
DevAssert(b);
|
||||
_EQ_CHECK_INT(a->ue_identity_index_value, b->ue_identity_index_value);
|
||||
_EQ_CHECK_INT(a->identity_type, b->identity_type);
|
||||
if (a->identity_type == F1AP_PAGING_IDENTITY_CN_UE) {
|
||||
_EQ_CHECK_LONG(a->identity.cn_ue_paging_identity, b->identity.cn_ue_paging_identity);
|
||||
} else {
|
||||
_EQ_CHECK_LONG(a->identity.ran_ue_paging_identity, b->identity.ran_ue_paging_identity);
|
||||
}
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, drx, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, priority, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, origin, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_INT(a->n_cells, b->n_cells);
|
||||
if ((a->n_cells > 0 && (a->cells == NULL || b->cells == NULL)))
|
||||
return false;
|
||||
for (int i = 0; i < a->n_cells; i++) {
|
||||
if (!eq_f1ap_plmn(&a->cells[i].plmn, &b->cells[i].plmn))
|
||||
return false;
|
||||
_EQ_CHECK_LONG(a->cells[i].nr_cellid, b->cells[i].nr_cellid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief deep copy F1 Paging */
|
||||
f1ap_paging_t cp_f1ap_paging(const f1ap_paging_t *orig)
|
||||
{
|
||||
DevAssert(orig);
|
||||
f1ap_paging_t cp = {0};
|
||||
cp.ue_identity_index_value = orig->ue_identity_index_value;
|
||||
cp.identity_type = orig->identity_type;
|
||||
cp.identity = orig->identity;
|
||||
if (orig->drx != NULL) {
|
||||
cp.drx = malloc_or_fail(sizeof(*cp.drx));
|
||||
*cp.drx = *orig->drx;
|
||||
}
|
||||
if (orig->priority != NULL) {
|
||||
cp.priority = malloc_or_fail(sizeof(*cp.priority));
|
||||
*cp.priority = *orig->priority;
|
||||
}
|
||||
if (orig->origin != NULL) {
|
||||
cp.origin = malloc_or_fail(sizeof(*cp.origin));
|
||||
*cp.origin = *orig->origin;
|
||||
}
|
||||
cp.n_cells = orig->n_cells;
|
||||
if (cp.n_cells > 0) {
|
||||
DevAssert(orig->cells != NULL);
|
||||
cp.cells = calloc_or_fail(cp.n_cells, sizeof(*cp.cells));
|
||||
for (int i = 0; i < cp.n_cells; i++) {
|
||||
cp.cells[i] = orig->cells[i];
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 F1AP_PAGING_H_
|
||||
#define F1AP_PAGING_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "f1ap_messages_types.h"
|
||||
|
||||
struct F1AP_F1AP_PDU;
|
||||
|
||||
/* F1 Paging */
|
||||
struct F1AP_F1AP_PDU *encode_f1ap_paging(const f1ap_paging_t *msg);
|
||||
bool decode_f1ap_paging(f1ap_paging_t *out, const struct F1AP_F1AP_PDU *pdu);
|
||||
void free_f1ap_paging(f1ap_paging_t *msg);
|
||||
bool eq_f1ap_paging(const f1ap_paging_t *a, const f1ap_paging_t *b);
|
||||
f1ap_paging_t cp_f1ap_paging(const f1ap_paging_t *orig);
|
||||
|
||||
#endif /* F1AP_PAGING_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -172,19 +172,19 @@ f1ap_initial_ul_rrc_message_t cp_initial_ul_rrc_message_transfer(const f1ap_init
|
||||
*/
|
||||
bool eq_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *a, const f1ap_initial_ul_rrc_message_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
if (!eq_f1ap_plmn(&a->plmn, &b->plmn))
|
||||
return false;
|
||||
_F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid);
|
||||
_F1_EQ_CHECK_INT(a->crnti, b->crnti);
|
||||
_F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length);
|
||||
_F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid);
|
||||
_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid);
|
||||
_EQ_CHECK_INT(a->crnti, b->crnti);
|
||||
_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length);
|
||||
_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid);
|
||||
if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0)
|
||||
return false;
|
||||
_F1_EQ_CHECK_INT(a->du2cu_rrc_container_length, b->du2cu_rrc_container_length);
|
||||
_EQ_CHECK_INT(a->du2cu_rrc_container_length, b->du2cu_rrc_container_length);
|
||||
if (memcmp(a->du2cu_rrc_container, b->du2cu_rrc_container, a->du2cu_rrc_container_length) != 0)
|
||||
return false;
|
||||
_F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id);
|
||||
_EQ_CHECK_INT(a->transaction_id, b->transaction_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -300,10 +300,10 @@ f1ap_ul_rrc_message_t cp_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *ms
|
||||
*/
|
||||
bool eq_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *a, const f1ap_ul_rrc_message_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0)
|
||||
return false;
|
||||
return true;
|
||||
@@ -456,16 +456,16 @@ f1ap_dl_rrc_message_t cp_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *ms
|
||||
*/
|
||||
bool eq_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *a, const f1ap_dl_rrc_message_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
if (!(a->old_gNB_DU_ue_id == NULL && b->old_gNB_DU_ue_id == NULL))
|
||||
_F1_EQ_CHECK_INT(*a->old_gNB_DU_ue_id, *b->old_gNB_DU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->srb_id, b->srb_id);
|
||||
_F1_EQ_CHECK_INT(a->execute_duplication, b->execute_duplication);
|
||||
_F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length);
|
||||
_EQ_CHECK_INT(*a->old_gNB_DU_ue_id, *b->old_gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->srb_id, b->srb_id);
|
||||
_EQ_CHECK_INT(a->execute_duplication, b->execute_duplication);
|
||||
_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length);
|
||||
if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
+159
-159
@@ -144,11 +144,11 @@ static bool eq_ba(const byte_array_t a, const byte_array_t b)
|
||||
|
||||
static bool eq_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *a, const f1ap_cu_to_du_rrc_info_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, cg_configinfo, eq_ba);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, ue_cap, eq_ba);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_config, eq_ba);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_timing_config, eq_ba);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, ho_prep_info, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, cg_configinfo, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, ue_cap, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, meas_config, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, meas_timing_config, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, ho_prep_info, eq_ba);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ static f1ap_du_to_cu_rrc_info_t cp_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_inf
|
||||
static bool eq_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *a, const f1ap_du_to_cu_rrc_info_t *b)
|
||||
{
|
||||
_F1_CHECK_EXP(eq_byte_array(&a->cell_group_config, &b->cell_group_config));
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_gap_config, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, meas_gap_config, eq_ba);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -257,8 +257,8 @@ static bool decode_srbs_to_setup(const F1AP_SRBs_ToBeSetup_List_t *f1ap, int *n,
|
||||
f1ap_srb_to_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_SRBs_ToBeSetup_ItemIEs_t *itie = (F1AP_SRBs_ToBeSetup_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item);
|
||||
srbs[i].id = itie->value.choice.SRBs_ToBeSetup_Item.sRBID;
|
||||
}
|
||||
|
||||
@@ -279,8 +279,8 @@ static bool decode_srbs_to_setupmod(const F1AP_SRBs_ToBeSetupMod_List_t *f1ap, i
|
||||
f1ap_srb_to_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_SRBs_ToBeSetupMod_ItemIEs_t *itie = (F1AP_SRBs_ToBeSetupMod_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item);
|
||||
srbs[i].id = itie->value.choice.SRBs_ToBeSetupMod_Item.sRBID;
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ static f1ap_srb_to_setup_t cp_srb_to_setup(const f1ap_srb_to_setup_t *orig)
|
||||
|
||||
static bool eq_srb_to_setup(const f1ap_srb_to_setup_t *a, const f1ap_srb_to_setup_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->id, b->id);
|
||||
_EQ_CHECK_INT(a->id, b->id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -347,8 +347,8 @@ static bool decode_srbs_setup(const F1AP_SRBs_Setup_List_t *f1ap, int *n, f1ap_s
|
||||
f1ap_srb_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_SRBs_Setup_ItemIEs_t *itie = (F1AP_SRBs_Setup_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_Setup_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_Setup_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item);
|
||||
const F1AP_SRBs_Setup_Item_t *it = &itie->value.choice.SRBs_Setup_Item;
|
||||
srbs[i].id = it->sRBID;
|
||||
srbs[i].lcid = it->lCID;
|
||||
@@ -367,8 +367,8 @@ static bool decode_srbs_setupmod(const F1AP_SRBs_SetupMod_List_t *f1ap, int *n,
|
||||
f1ap_srb_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_SRBs_SetupMod_ItemIEs_t *itie = (F1AP_SRBs_SetupMod_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item);
|
||||
const F1AP_SRBs_SetupMod_Item_t *it = &itie->value.choice.SRBs_SetupMod_Item;
|
||||
srbs[i].id = it->sRBID;
|
||||
srbs[i].lcid = it->lCID;
|
||||
@@ -384,8 +384,8 @@ static f1ap_srb_setup_t cp_srb_setup(const f1ap_srb_setup_t *orig)
|
||||
|
||||
static bool eq_srb_setup(const f1ap_srb_setup_t *a, const f1ap_srb_setup_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->id, b->id);
|
||||
_F1_EQ_CHECK_INT(a->lcid, b->lcid);
|
||||
_EQ_CHECK_INT(a->id, b->id);
|
||||
_EQ_CHECK_INT(a->lcid, b->lcid);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ static bool decode_qos_flow_param(const F1AP_QoSFlowLevelQoSParameters_t *f1ap,
|
||||
const F1AP_NonDynamic5QIDescriptor_t *nondyn = f1ap->qoS_Characteristics.choice.non_Dynamic_5QI;
|
||||
out->nondyn.fiveQI = nondyn->fiveQI;
|
||||
} else {
|
||||
_F1_EQ_CHECK_INT(f1ap->qoS_Characteristics.present, F1AP_QoS_Characteristics_PR_dynamic_5QI);
|
||||
_EQ_CHECK_INT(f1ap->qoS_Characteristics.present, F1AP_QoS_Characteristics_PR_dynamic_5QI);
|
||||
const F1AP_Dynamic5QIDescriptor_t *d = f1ap->qoS_Characteristics.choice.dynamic_5QI;
|
||||
out->qos_type = DYNAMIC;
|
||||
out->dyn.prio = d->qoSPriorityLevel;
|
||||
@@ -488,23 +488,23 @@ static f1ap_qos_flow_param_t cp_qos_flow_param(const f1ap_qos_flow_param_t *orig
|
||||
|
||||
static bool eq_qos_flow_param(const f1ap_qos_flow_param_t *a, const f1ap_qos_flow_param_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->qos_type, b->qos_type);
|
||||
_EQ_CHECK_INT(a->qos_type, b->qos_type);
|
||||
if (a->qos_type == NON_DYNAMIC) {
|
||||
_F1_EQ_CHECK_INT(a->nondyn.fiveQI, b->nondyn.fiveQI);
|
||||
_EQ_CHECK_INT(a->nondyn.fiveQI, b->nondyn.fiveQI);
|
||||
} else {
|
||||
DevAssert(a->qos_type == DYNAMIC);
|
||||
DevAssert(b->qos_type == DYNAMIC);
|
||||
const f1ap_dynamic_5qi_t *adyn = &a->dyn, *bdyn = &b->dyn;
|
||||
_F1_EQ_CHECK_INT(adyn->prio, bdyn->prio);
|
||||
_F1_EQ_CHECK_INT(adyn->pdb, bdyn->pdb);
|
||||
_F1_EQ_CHECK_INT(adyn->per.scalar, bdyn->per.scalar);
|
||||
_F1_EQ_CHECK_INT(adyn->per.exponent, bdyn->per.exponent);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, delay_critical, _F1_EQ_CHECK_INT);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, avg_win, _F1_EQ_CHECK_INT);
|
||||
_EQ_CHECK_INT(adyn->prio, bdyn->prio);
|
||||
_EQ_CHECK_INT(adyn->pdb, bdyn->pdb);
|
||||
_EQ_CHECK_INT(adyn->per.scalar, bdyn->per.scalar);
|
||||
_EQ_CHECK_INT(adyn->per.exponent, bdyn->per.exponent);
|
||||
_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, delay_critical, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, avg_win, _EQ_CHECK_INT);
|
||||
}
|
||||
_F1_EQ_CHECK_INT(a->arp.prio, b->arp.prio);
|
||||
_F1_EQ_CHECK_INT(a->arp.preempt_cap, b->arp.preempt_cap);
|
||||
_F1_EQ_CHECK_INT(a->arp.preempt_vuln, b->arp.preempt_vuln);
|
||||
_EQ_CHECK_INT(a->arp.prio, b->arp.prio);
|
||||
_EQ_CHECK_INT(a->arp.preempt_cap, b->arp.preempt_cap);
|
||||
_EQ_CHECK_INT(a->arp.preempt_vuln, b->arp.preempt_vuln);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -569,11 +569,11 @@ static f1ap_drb_info_nr_t cp_drb_info_nr(const f1ap_drb_info_nr_t *orig)
|
||||
static bool eq_drb_info_nr(const f1ap_drb_info_nr_t *a, const f1ap_drb_info_nr_t *b)
|
||||
{
|
||||
_F1_CHECK_EXP(eq_qos_flow_param(&a->drb_qos, &b->drb_qos));
|
||||
_F1_EQ_CHECK_INT(a->nssai.sst, b->nssai.sst);
|
||||
_F1_EQ_CHECK_INT(a->nssai.sd, b->nssai.sd);
|
||||
_F1_EQ_CHECK_INT(a->flows_len, b->flows_len);
|
||||
_EQ_CHECK_INT(a->nssai.sst, b->nssai.sst);
|
||||
_EQ_CHECK_INT(a->nssai.sd, b->nssai.sd);
|
||||
_EQ_CHECK_INT(a->flows_len, b->flows_len);
|
||||
for (int i = 0; i < a->flows_len; ++i) {
|
||||
_F1_EQ_CHECK_INT(a->flows[i].qfi, b->flows[i].qfi);
|
||||
_EQ_CHECK_INT(a->flows[i].qfi, b->flows[i].qfi);
|
||||
_F1_CHECK_EXP(eq_qos_flow_param(&a->flows[i].param, &b->flows[i].param));
|
||||
}
|
||||
return true;
|
||||
@@ -629,7 +629,7 @@ static F1AP_UPTransportLayerInformation_t encode_up_tnl(const f1ap_up_tnl_t *tnl
|
||||
|
||||
static bool decode_up_tnl(const F1AP_UPTransportLayerInformation_t *tnl_info, f1ap_up_tnl_t *out)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(tnl_info->present, F1AP_UPTransportLayerInformation_PR_gTPTunnel);
|
||||
_EQ_CHECK_INT(tnl_info->present, F1AP_UPTransportLayerInformation_PR_gTPTunnel);
|
||||
const F1AP_GTPTunnel_t *gtp_tnl = tnl_info->choice.gTPTunnel;
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(>p_tnl->transportLayerAddress, out->tl_address);
|
||||
OCTET_STRING_TO_UINT32(>p_tnl->gTP_TEID, out->teid);
|
||||
@@ -649,7 +649,7 @@ static bool eq_up_tnl(const f1ap_up_tnl_t *a, const f1ap_up_tnl_t *b)
|
||||
PRINT_ERROR("tl_address mismatch\n");
|
||||
return false;
|
||||
}
|
||||
_F1_EQ_CHECK_INT(a->teid, b->teid);
|
||||
_EQ_CHECK_INT(a->teid, b->teid);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -780,22 +780,22 @@ static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n,
|
||||
f1ap_drb_to_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_DRBs_ToBeSetup_ItemIEs_t *itie = (const F1AP_DRBs_ToBeSetup_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item);
|
||||
const F1AP_DRBs_ToBeSetup_Item_t *it = &itie->value.choice.DRBs_ToBeSetup_Item;
|
||||
|
||||
f1ap_drb_to_setup_t *drb = &drbs[i];
|
||||
drb->id = it->dRBID;
|
||||
|
||||
_F1_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension);
|
||||
_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension);
|
||||
const F1AP_QoSInformation_ExtIEs_t *qos_ext = (F1AP_QoSInformation_ExtIEs_t *)it->qoSInformation.choice.choice_extension;
|
||||
_F1_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information);
|
||||
_F1_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information);
|
||||
_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information);
|
||||
_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information);
|
||||
drb->qos_choice = F1AP_QOS_CHOICE_NR;
|
||||
_F1_CHECK_EXP(decode_drb_info_nr(&qos_ext->value.choice.DRB_Information, &drb->nr));
|
||||
|
||||
drb->up_ul_tnl_len = it->uLUPTNLInformation_ToBeSetup_List.list.count;
|
||||
_F1_EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1);
|
||||
EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1);
|
||||
for (int j = 0; j < drb->up_ul_tnl_len; ++j) {
|
||||
const F1AP_ULUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->uLUPTNLInformation_ToBeSetup_List.list.array[j];
|
||||
_F1_CHECK_EXP(decode_up_tnl(&it_tnl->uLUPTNLInformation, &drb->up_ul_tnl[j]));
|
||||
@@ -813,11 +813,11 @@ static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n,
|
||||
AssertError(ie != NULL, return false, "ext->list.array[j] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_DLPDCPSNLength:
|
||||
_F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength);
|
||||
_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength);
|
||||
_F1_MALLOC(drb->dl_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength);
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_ULPDCPSNLength:
|
||||
_F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength_1);
|
||||
_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength_1);
|
||||
_F1_MALLOC(drb->ul_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength_1);
|
||||
break;
|
||||
default:
|
||||
@@ -845,22 +845,22 @@ static bool decode_drbs_to_setupmod(const F1AP_DRBs_ToBeSetupMod_List_t *f1ap, i
|
||||
f1ap_drb_to_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_DRBs_ToBeSetupMod_ItemIEs_t *itie = (const F1AP_DRBs_ToBeSetupMod_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item);
|
||||
const F1AP_DRBs_ToBeSetupMod_Item_t *it = &itie->value.choice.DRBs_ToBeSetupMod_Item;
|
||||
|
||||
f1ap_drb_to_setup_t *drb = &drbs[i];
|
||||
drb->id = it->dRBID;
|
||||
|
||||
_F1_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension);
|
||||
_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension);
|
||||
const F1AP_QoSInformation_ExtIEs_t *qos_ext = (F1AP_QoSInformation_ExtIEs_t *)it->qoSInformation.choice.choice_extension;
|
||||
_F1_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information);
|
||||
_F1_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information);
|
||||
_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information);
|
||||
_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information);
|
||||
drb->qos_choice = F1AP_QOS_CHOICE_NR;
|
||||
_F1_CHECK_EXP(decode_drb_info_nr(&qos_ext->value.choice.DRB_Information, &drb->nr));
|
||||
|
||||
drb->up_ul_tnl_len = it->uLUPTNLInformation_ToBeSetup_List.list.count;
|
||||
_F1_EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1);
|
||||
EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1);
|
||||
for (int j = 0; j < drb->up_ul_tnl_len; ++j) {
|
||||
const F1AP_ULUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->uLUPTNLInformation_ToBeSetup_List.list.array[j];
|
||||
_F1_CHECK_EXP(decode_up_tnl(&it_tnl->uLUPTNLInformation, &drb->up_ul_tnl[j]));
|
||||
@@ -878,11 +878,11 @@ static bool decode_drbs_to_setupmod(const F1AP_DRBs_ToBeSetupMod_List_t *f1ap, i
|
||||
AssertError(ie != NULL, return false, "ext->list.array[j] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_DLPDCPSNLength:
|
||||
_F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength);
|
||||
_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength);
|
||||
_F1_MALLOC(drb->dl_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength);
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_ULPDCPSNLength:
|
||||
_F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength_1);
|
||||
_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength_1);
|
||||
_F1_MALLOC(drb->ul_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength_1);
|
||||
break;
|
||||
default:
|
||||
@@ -922,18 +922,18 @@ static f1ap_drb_to_setup_t cp_drb_to_setup(const f1ap_drb_to_setup_t *orig)
|
||||
|
||||
static bool eq_drb_to_setup(const f1ap_drb_to_setup_t *a, const f1ap_drb_to_setup_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->id, b->id);
|
||||
_F1_EQ_CHECK_INT(a->qos_choice, b->qos_choice);
|
||||
_EQ_CHECK_INT(a->id, b->id);
|
||||
_EQ_CHECK_INT(a->qos_choice, b->qos_choice);
|
||||
AssertFatal(a->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n");
|
||||
if (a->qos_choice == F1AP_QOS_CHOICE_NR)
|
||||
eq_drb_info_nr(&a->nr, &b->nr);
|
||||
_F1_EQ_CHECK_INT(a->up_ul_tnl_len, b->up_ul_tnl_len);
|
||||
_EQ_CHECK_INT(a->up_ul_tnl_len, b->up_ul_tnl_len);
|
||||
for (int i = 0; i < a->up_ul_tnl_len; ++i) {
|
||||
_F1_CHECK_EXP(eq_up_tnl(&a->up_ul_tnl[i], &b->up_ul_tnl[i]));
|
||||
}
|
||||
_F1_EQ_CHECK_INT(a->rlc_mode, b->rlc_mode);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, dl_pdcp_sn_len, _F1_EQ_CHECK_INT);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, ul_pdcp_sn_len, _F1_EQ_CHECK_INT);
|
||||
_EQ_CHECK_INT(a->rlc_mode, b->rlc_mode);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, dl_pdcp_sn_len, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, ul_pdcp_sn_len, _EQ_CHECK_INT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1004,8 +1004,8 @@ static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_d
|
||||
f1ap_drb_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_DRBs_Setup_ItemIEs_t *itie = (const F1AP_DRBs_Setup_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_Setup_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_Setup_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item);
|
||||
const F1AP_DRBs_Setup_Item_t *it = &itie->value.choice.DRBs_Setup_Item;
|
||||
|
||||
f1ap_drb_setup_t *drb = &drbs[i];
|
||||
@@ -1014,7 +1014,7 @@ static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_d
|
||||
_F1_MALLOC(drb->lcid, *it->lCID);
|
||||
|
||||
drb->up_dl_tnl_len = it->dLUPTNLInformation_ToBeSetup_List.list.count;
|
||||
_F1_EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1);
|
||||
EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1);
|
||||
for (int j = 0; j < drb->up_dl_tnl_len; ++j) {
|
||||
F1AP_DLUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->dLUPTNLInformation_ToBeSetup_List.list.array[j];
|
||||
_F1_CHECK_EXP(decode_up_tnl(&it_tnl->dLUPTNLInformation, &drb->up_dl_tnl[j]));
|
||||
@@ -1035,8 +1035,8 @@ static bool decode_drbs_setupmod(const F1AP_DRBs_SetupMod_List_t *f1ap, int *n,
|
||||
f1ap_drb_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_DRBs_SetupMod_ItemIEs_t *itie = (const F1AP_DRBs_SetupMod_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item);
|
||||
const F1AP_DRBs_SetupMod_Item_t *it = &itie->value.choice.DRBs_SetupMod_Item;
|
||||
|
||||
f1ap_drb_setup_t *drb = &drbs[i];
|
||||
@@ -1045,7 +1045,7 @@ static bool decode_drbs_setupmod(const F1AP_DRBs_SetupMod_List_t *f1ap, int *n,
|
||||
_F1_MALLOC(drb->lcid, *it->lCID);
|
||||
|
||||
drb->up_dl_tnl_len = it->dLUPTNLInformation_ToBeSetup_List.list.count;
|
||||
_F1_EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1);
|
||||
EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1);
|
||||
for (int j = 0; j < drb->up_dl_tnl_len; ++j) {
|
||||
F1AP_DLUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->dLUPTNLInformation_ToBeSetup_List.list.array[j];
|
||||
_F1_CHECK_EXP(decode_up_tnl(&it_tnl->dLUPTNLInformation, &drb->up_dl_tnl[j]));
|
||||
@@ -1070,9 +1070,9 @@ static f1ap_drb_setup_t cp_drb_setup(const f1ap_drb_setup_t *orig)
|
||||
|
||||
static bool eq_drb_setup(const f1ap_drb_setup_t *a, const f1ap_drb_setup_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->id, b->id);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, lcid, _F1_EQ_CHECK_INT);
|
||||
_F1_EQ_CHECK_INT(a->up_dl_tnl_len, b->up_dl_tnl_len);
|
||||
_EQ_CHECK_INT(a->id, b->id);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, lcid, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_INT(a->up_dl_tnl_len, b->up_dl_tnl_len);
|
||||
for (int i = 0; i < a->up_dl_tnl_len; ++i)
|
||||
_F1_CHECK_EXP(eq_up_tnl(&a->up_dl_tnl[i], &b->up_dl_tnl[i]));
|
||||
return true;
|
||||
@@ -1107,8 +1107,8 @@ static bool decode_drbs_to_release(const F1AP_DRBs_ToBeReleased_List_t *f1ap, in
|
||||
f1ap_drb_to_release_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const F1AP_DRBs_ToBeReleased_ItemIEs_t *itie = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)f1ap->list.array[i];
|
||||
_F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item);
|
||||
_F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item);
|
||||
_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item);
|
||||
_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item);
|
||||
drbs[i].id = itie->value.choice.DRBs_ToBeReleased_Item.dRBID;
|
||||
}
|
||||
|
||||
@@ -1125,7 +1125,7 @@ static f1ap_drb_to_release_t cp_drb_to_release(const f1ap_drb_to_release_t *orig
|
||||
|
||||
static bool eq_drb_to_release(const f1ap_drb_to_release_t *a, const f1ap_drb_to_release_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->id, b->id);
|
||||
_EQ_CHECK_INT(a->id, b->id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1249,33 +1249,33 @@ bool decode_ue_context_setup_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_set
|
||||
AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
_F1_MALLOC(out->gNB_DU_ue_id, ie->value.choice.GNB_DU_UE_F1AP_ID);
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_SpCell_ID: {
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_NRCGI);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_NRCGI);
|
||||
const F1AP_NRCGI_t *nrcgi = &ie->value.choice.NRCGI;
|
||||
PLMNID_TO_MCC_MNC(&nrcgi->pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length);
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&nrcgi->nRCellIdentity, out->nr_cellid);
|
||||
} break;
|
||||
case F1AP_ProtocolIE_ID_id_ServCellIndex:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex);
|
||||
out->servCellIndex = ie->value.choice.ServCellIndex;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_CUtoDURRCInformation:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation);
|
||||
_F1_CHECK_EXP(decode_cu_to_du_rrc_info(&out->cu_to_du_rrc_info, &ie->value.choice.CUtoDURRCInformation));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List);
|
||||
_F1_CHECK_EXP(decode_srbs_to_setup(&ie->value.choice.SRBs_ToBeSetup_List, &out->srbs_len, &out->srbs));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List);
|
||||
{
|
||||
// gNB-DU UE Aggregate Maximum Bit Rate Uplink is C-ifDRBSetup
|
||||
// below, check that gNB-DU UE AMBR UL IE is present if we have DRB
|
||||
@@ -1287,7 +1287,7 @@ bool decode_ue_context_setup_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_set
|
||||
_F1_CHECK_EXP(decode_drbs_to_setup(&ie->value.choice.DRBs_ToBeSetup_List, &out->drbs_len, &out->drbs));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_RRCContainer:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer);
|
||||
out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container));
|
||||
{
|
||||
OCTET_STRING_t *os = &ie->value.choice.RRCContainer;
|
||||
@@ -1295,7 +1295,7 @@ bool decode_ue_context_setup_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_set
|
||||
}
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_BitRate);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_BitRate);
|
||||
out->gnb_du_ue_agg_mbr_ul = malloc_or_fail(sizeof(*out->gnb_du_ue_agg_mbr_ul));
|
||||
asn_INTEGER2uint64(&ie->value.choice.BitRate, out->gnb_du_ue_agg_mbr_ul);
|
||||
break;
|
||||
@@ -1346,26 +1346,26 @@ f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_
|
||||
*/
|
||||
bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, gNB_DU_ue_id, _F1_EQ_CHECK_INT);
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, gNB_DU_ue_id, _EQ_CHECK_INT);
|
||||
_F1_CHECK_EXP(eq_f1ap_plmn(&a->plmn, &b->plmn));
|
||||
_F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid);
|
||||
_F1_EQ_CHECK_INT(a->servCellIndex, b->servCellIndex);
|
||||
_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid);
|
||||
_EQ_CHECK_INT(a->servCellIndex, b->servCellIndex);
|
||||
_F1_CHECK_EXP(eq_cu_to_du_rrc_info(&a->cu_to_du_rrc_info, &b->cu_to_du_rrc_info));
|
||||
|
||||
_F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len);
|
||||
_EQ_CHECK_INT(a->srbs_len, b->srbs_len);
|
||||
_F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs));
|
||||
for (int i = 0; i < a->srbs_len; ++i)
|
||||
_F1_CHECK_EXP(eq_srb_to_setup(&a->srbs[i], &b->srbs[i]));
|
||||
|
||||
_F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len);
|
||||
_EQ_CHECK_INT(a->drbs_len, b->drbs_len);
|
||||
_F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs));
|
||||
for (int i = 0; i < a->drbs_len; ++i)
|
||||
_F1_CHECK_EXP(eq_drb_to_setup(&a->drbs[i], &b->drbs[i]));
|
||||
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba);
|
||||
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, gnb_du_ue_agg_mbr_ul, _F1_EQ_CHECK_LONG);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, gnb_du_ue_agg_mbr_ul, _EQ_CHECK_LONG);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1472,27 +1472,27 @@ bool decode_ue_context_setup_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_conte
|
||||
AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_DUtoCURRCInformation:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation);
|
||||
_F1_CHECK_EXP(decode_du_to_cu_rrc_info(&out->du_to_cu_rrc_info, &ie->value.choice.DUtoCURRCInformation));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_C_RNTI:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI);
|
||||
_F1_MALLOC(out->crnti, ie->value.choice.C_RNTI);
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_DRBs_Setup_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List);
|
||||
_F1_CHECK_EXP(decode_drbs_setup(&ie->value.choice.DRBs_Setup_List, &out->drbs_len, &out->drbs));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_SRBs_Setup_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List);
|
||||
_F1_CHECK_EXP(decode_srbs_setup(&ie->value.choice.SRBs_Setup_List, &out->srbs_len, &out->srbs));
|
||||
break;
|
||||
default:
|
||||
@@ -1541,17 +1541,17 @@ f1ap_ue_context_setup_resp_t cp_ue_context_setup_resp(const f1ap_ue_context_setu
|
||||
*/
|
||||
bool eq_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *a, const f1ap_ue_context_setup_resp_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_F1_CHECK_EXP(eq_du_to_cu_rrc_info(&a->du_to_cu_rrc_info, &b->du_to_cu_rrc_info));
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, crnti, _F1_EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, crnti, _EQ_CHECK_INT);
|
||||
|
||||
_F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len);
|
||||
_EQ_CHECK_INT(a->drbs_len, b->drbs_len);
|
||||
_F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs));
|
||||
for (int i = 0; i < a->drbs_len; ++i)
|
||||
_F1_CHECK_EXP(eq_drb_setup(&a->drbs[i], &b->drbs[i]));
|
||||
|
||||
_F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len);
|
||||
_EQ_CHECK_INT(a->srbs_len, b->srbs_len);
|
||||
_F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs));
|
||||
for (int i = 0; i < a->srbs_len; ++i)
|
||||
_F1_CHECK_EXP(eq_srb_setup(&a->srbs[i], &b->srbs[i]));
|
||||
@@ -1735,15 +1735,15 @@ bool decode_ue_context_mod_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_mod_r
|
||||
AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_SpCell_ID: {
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_NRCGI);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_NRCGI);
|
||||
const F1AP_NRCGI_t *nrcgi = &ie->value.choice.NRCGI;
|
||||
out->plmn = malloc_or_fail(sizeof(*out->plmn));
|
||||
PLMNID_TO_MCC_MNC(&nrcgi->pLMN_Identity, out->plmn->mcc, out->plmn->mnc, out->plmn->mnc_digit_length);
|
||||
@@ -1751,16 +1751,16 @@ bool decode_ue_context_mod_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_mod_r
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&nrcgi->nRCellIdentity, *out->nr_cellid);
|
||||
} break;
|
||||
case F1AP_ProtocolIE_ID_id_ServCellIndex:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex);
|
||||
_F1_MALLOC(out->servCellIndex, ie->value.choice.ServCellIndex);
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_CUtoDURRCInformation:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation);
|
||||
out->cu_to_du_rrc_info = calloc(1, sizeof(*out->cu_to_du_rrc_info));
|
||||
_F1_CHECK_EXP(decode_cu_to_du_rrc_info(out->cu_to_du_rrc_info, &ie->value.choice.CUtoDURRCInformation));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_TransmissionActionIndicator:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator);
|
||||
{
|
||||
TransmActionInd_t v = ie->value.choice.TransmissionActionIndicator == F1AP_TransmissionActionIndicator_stop
|
||||
? TransmActionInd_STOP
|
||||
@@ -1769,7 +1769,7 @@ bool decode_ue_context_mod_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_mod_r
|
||||
}
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator);
|
||||
{
|
||||
ReconfigurationCompl_t v =
|
||||
ie->value.choice.RRCReconfigurationCompleteIndicator == F1AP_RRCReconfigurationCompleteIndicator_true
|
||||
@@ -1779,7 +1779,7 @@ bool decode_ue_context_mod_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_mod_r
|
||||
}
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_RRCContainer:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer);
|
||||
out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container));
|
||||
{
|
||||
OCTET_STRING_t *os = &ie->value.choice.RRCContainer;
|
||||
@@ -1787,26 +1787,26 @@ bool decode_ue_context_mod_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_mod_r
|
||||
}
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_GNB_DUConfigurationQuery:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_DUConfigurationQuery);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_DUConfigurationQuery);
|
||||
{
|
||||
bool v = ie->value.choice.GNB_DUConfigurationQuery == F1AP_GNB_DUConfigurationQuery_true;
|
||||
_F1_MALLOC(out->gNB_DU_Configuration_Query, v);
|
||||
}
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List);
|
||||
_F1_CHECK_EXP(decode_srbs_to_setupmod(&ie->value.choice.SRBs_ToBeSetupMod_List, &out->srbs_len, &out->srbs));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List);
|
||||
_F1_CHECK_EXP(decode_drbs_to_setupmod(&ie->value.choice.DRBs_ToBeSetupMod_List, &out->drbs_len, &out->drbs));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List);
|
||||
_F1_CHECK_EXP(decode_drbs_to_release(&ie->value.choice.DRBs_ToBeReleased_List, &out->drbs_rel_len, &out->drbs_rel));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_LowerLayerPresenceStatusChange:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_LowerLayerPresenceStatusChange);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_LowerLayerPresenceStatusChange);
|
||||
{
|
||||
lower_layer_status_t v = ie->value.choice.LowerLayerPresenceStatusChange == F1AP_LowerLayerPresenceStatusChange_suspend_lower_layers
|
||||
? LOWER_LAYERS_SUSPEND : LOWER_LAYERS_RESUME;
|
||||
@@ -1888,35 +1888,35 @@ f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t
|
||||
*/
|
||||
bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_F1_CHECK_EXP((a->plmn && b->plmn) || (!a->plmn && !b->plmn));
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, plmn);
|
||||
_F1_CHECK_EXP(!a->plmn || eq_f1ap_plmn(a->plmn, b->plmn));
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, nr_cellid, _F1_EQ_CHECK_LONG);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, servCellIndex, _F1_EQ_CHECK_INT);
|
||||
_F1_CHECK_EXP((a->cu_to_du_rrc_info && b->cu_to_du_rrc_info) || (!a->cu_to_du_rrc_info && !b->cu_to_du_rrc_info));
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, nr_cellid, _EQ_CHECK_LONG);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, servCellIndex, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, cu_to_du_rrc_info);
|
||||
_F1_CHECK_EXP(!a->cu_to_du_rrc_info || eq_cu_to_du_rrc_info(a->cu_to_du_rrc_info, b->cu_to_du_rrc_info));
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, transm_action_ind, _F1_EQ_CHECK_INT);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, reconfig_compl, _F1_EQ_CHECK_INT);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, transm_action_ind, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, reconfig_compl, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba);
|
||||
|
||||
_F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len);
|
||||
_EQ_CHECK_INT(a->srbs_len, b->srbs_len);
|
||||
_F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs));
|
||||
for (int i = 0; i < a->srbs_len; ++i)
|
||||
_F1_CHECK_EXP(eq_srb_to_setup(&a->srbs[i], &b->srbs[i]));
|
||||
|
||||
_F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len);
|
||||
_EQ_CHECK_INT(a->drbs_len, b->drbs_len);
|
||||
_F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs));
|
||||
for (int i = 0; i < a->drbs_len; ++i)
|
||||
_F1_CHECK_EXP(eq_drb_to_setup(&a->drbs[i], &b->drbs[i]));
|
||||
|
||||
_F1_EQ_CHECK_INT(a->drbs_rel_len, b->drbs_rel_len);
|
||||
_EQ_CHECK_INT(a->drbs_rel_len, b->drbs_rel_len);
|
||||
_F1_CHECK_EXP(a->drbs_rel_len == 0 || (a->drbs_rel_len && b->drbs_rel_len));
|
||||
for (int i = 0; i < a->drbs_rel_len; ++i)
|
||||
_F1_CHECK_EXP(eq_drb_to_release(&a->drbs_rel[i], &b->drbs_rel[i]));
|
||||
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, status, _F1_EQ_CHECK_INT);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, gNB_DU_Configuration_Query, _F1_EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, status, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, gNB_DU_Configuration_Query, _EQ_CHECK_INT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2024,24 +2024,24 @@ bool decode_ue_context_mod_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context
|
||||
AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_DUtoCURRCInformation:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation);
|
||||
out->du_to_cu_rrc_info = calloc(1, sizeof(*out->du_to_cu_rrc_info));
|
||||
_F1_CHECK_EXP(decode_du_to_cu_rrc_info(out->du_to_cu_rrc_info, &ie->value.choice.DUtoCURRCInformation));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List);
|
||||
_F1_CHECK_EXP(decode_drbs_setupmod(&ie->value.choice.DRBs_SetupMod_List, &out->drbs_len, &out->drbs));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List);
|
||||
_F1_CHECK_EXP(decode_srbs_setupmod(&ie->value.choice.SRBs_SetupMod_List, &out->srbs_len, &out->srbs));
|
||||
break;
|
||||
default:
|
||||
@@ -2097,17 +2097,17 @@ f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp
|
||||
*/
|
||||
bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
//_F1_EQ_CHECK_OPTIONAL_IE(a, b, du_to_cu_rrc_info, eq_du_to_cu_rrc_info);
|
||||
_F1_CHECK_EXP((a->du_to_cu_rrc_info && b->du_to_cu_rrc_info) || (!a->du_to_cu_rrc_info && !b->du_to_cu_rrc_info));
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
//_EQ_CHECK_OPTIONAL_IE(a, b, du_to_cu_rrc_info, eq_du_to_cu_rrc_info);
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, du_to_cu_rrc_info);
|
||||
_F1_CHECK_EXP(!a->du_to_cu_rrc_info || eq_du_to_cu_rrc_info(a->du_to_cu_rrc_info, b->du_to_cu_rrc_info));
|
||||
|
||||
_F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs));
|
||||
for (int i = 0; i < a->drbs_len; ++i)
|
||||
_F1_CHECK_EXP(eq_drb_setup(&a->drbs[i], &b->drbs[i]));
|
||||
|
||||
_F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len);
|
||||
_EQ_CHECK_INT(a->srbs_len, b->srbs_len);
|
||||
_F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs));
|
||||
for (int i = 0; i < a->srbs_len; ++i)
|
||||
_F1_CHECK_EXP(eq_srb_setup(&a->srbs[i], &b->srbs[i]));
|
||||
@@ -2189,15 +2189,15 @@ bool decode_ue_context_rel_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_
|
||||
AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_Cause:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_Cause);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_Cause);
|
||||
_F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value));
|
||||
break;
|
||||
default:
|
||||
@@ -2228,10 +2228,10 @@ f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t
|
||||
*/
|
||||
bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_F1_EQ_CHECK_LONG(a->cause_value, b->cause_value);
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_EQ_CHECK_LONG(a->cause_value, b->cause_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2327,27 +2327,27 @@ bool decode_ue_context_rel_cmd(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_
|
||||
AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_Cause:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_Cause);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_Cause);
|
||||
_F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value));
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_RRCContainer:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer);
|
||||
out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container));
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer);
|
||||
out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container));
|
||||
{
|
||||
OCTET_STRING_t *os = &ie->value.choice.RRCContainer;
|
||||
*out->rrc_container = create_byte_array(os->size, os->buf);
|
||||
}
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_SRBID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_SRBID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_SRBID);
|
||||
{
|
||||
// SRB-ID
|
||||
F1AP_UEContextReleaseCommandIEs_t *check_ie;
|
||||
@@ -2356,7 +2356,7 @@ bool decode_ue_context_rel_cmd(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_
|
||||
_F1_MALLOC(out->srb_id, ie->value.choice.SRBID);
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID_1);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID_1);
|
||||
_F1_MALLOC(out->old_gNB_DU_ue_id, ie->value.choice.GNB_DU_UE_F1AP_ID_1);
|
||||
break;
|
||||
default:
|
||||
@@ -2394,13 +2394,13 @@ f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t
|
||||
*/
|
||||
bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_F1_EQ_CHECK_LONG(a->cause_value, b->cause_value);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, srb_id, _F1_EQ_CHECK_INT);
|
||||
_F1_EQ_CHECK_OPTIONAL_IE(a, b, old_gNB_DU_ue_id, _F1_EQ_CHECK_INT);
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_EQ_CHECK_LONG(a->cause_value, b->cause_value);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, srb_id, _EQ_CHECK_INT);
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, old_gNB_DU_ue_id, _EQ_CHECK_INT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2464,11 +2464,11 @@ bool decode_ue_context_rel_cplt(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context
|
||||
AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL");
|
||||
switch (ie->id) {
|
||||
case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID);
|
||||
out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
break;
|
||||
case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
|
||||
_F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID);
|
||||
out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
break;
|
||||
default:
|
||||
@@ -2497,8 +2497,8 @@ f1ap_ue_context_rel_cplt_t cp_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt
|
||||
*/
|
||||
bool eq_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *a, const f1ap_ue_context_rel_cplt_t *b)
|
||||
{
|
||||
_F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id);
|
||||
_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "lib/f1ap_interface_management.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
#include "lib/f1ap_positioning.h"
|
||||
#include "lib/f1ap_paging.h"
|
||||
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||
{
|
||||
@@ -2383,6 +2384,79 @@ static void test_f1ap_positioning_measurement_update()
|
||||
printf("%s() successful\n", __func__);
|
||||
}
|
||||
|
||||
/** @brief Test F1 Paging encode/decode roundtrip and copy operations */
|
||||
static void test_f1ap_paging_rt(f1ap_paging_t *orig)
|
||||
{
|
||||
F1AP_F1AP_PDU_t *f1enc = encode_f1ap_paging(orig);
|
||||
F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc);
|
||||
f1ap_msg_free(f1enc);
|
||||
|
||||
f1ap_paging_t decoded = {0};
|
||||
bool ret = decode_f1ap_paging(&decoded, f1dec);
|
||||
AssertFatal(ret, "decode_f1ap_paging(): could not decode message\n");
|
||||
f1ap_msg_free(f1dec);
|
||||
|
||||
ret = eq_f1ap_paging(orig, &decoded);
|
||||
AssertFatal(ret, "eq_f1ap_paging(): decoded message doesn't match\n");
|
||||
free_f1ap_paging(&decoded);
|
||||
|
||||
f1ap_paging_t cp = cp_f1ap_paging(orig);
|
||||
ret = eq_f1ap_paging(orig, &cp);
|
||||
AssertFatal(ret, "eq_f1ap_paging(): copied message doesn't match\n");
|
||||
free_f1ap_paging(&cp);
|
||||
}
|
||||
|
||||
/** @brief Test F1 Paging encoding/decoding */
|
||||
static void test_f1ap_paging(void)
|
||||
{
|
||||
// Test with CN UE Paging Identity (5G-S-TMSI)
|
||||
{
|
||||
f1ap_paging_t orig = {0};
|
||||
orig.ue_identity_index_value = 123;
|
||||
orig.identity_type = F1AP_PAGING_IDENTITY_CN_UE;
|
||||
orig.identity.cn_ue_paging_identity = 0x1234567890AB;
|
||||
orig.drx = malloc_or_fail(sizeof(*orig.drx));
|
||||
*orig.drx = F1AP_PAGING_DRX_32;
|
||||
orig.n_cells = 2;
|
||||
orig.cells = calloc_or_fail(orig.n_cells, sizeof(*orig.cells));
|
||||
orig.cells[0].plmn.mcc = 208;
|
||||
orig.cells[0].plmn.mnc = 95;
|
||||
orig.cells[0].plmn.mnc_digit_length = 2;
|
||||
orig.cells[0].nr_cellid = 123456;
|
||||
orig.cells[1].plmn.mcc = 208;
|
||||
orig.cells[1].plmn.mnc = 93;
|
||||
orig.cells[1].plmn.mnc_digit_length = 2;
|
||||
orig.cells[1].nr_cellid = 789012;
|
||||
|
||||
test_f1ap_paging_rt(&orig);
|
||||
free_f1ap_paging(&orig);
|
||||
}
|
||||
|
||||
// Test with RAN UE Paging Identity (I-RNTI)
|
||||
{
|
||||
f1ap_paging_t orig = {0};
|
||||
orig.ue_identity_index_value = 456;
|
||||
orig.identity_type = F1AP_PAGING_IDENTITY_RAN_UE;
|
||||
orig.identity.ran_ue_paging_identity = 0x1234567890;
|
||||
orig.drx = NULL;
|
||||
orig.priority = malloc_or_fail(sizeof(*orig.priority));
|
||||
*orig.priority = F1AP_PAGING_PRIO_LEVEL3;
|
||||
orig.origin = malloc_or_fail(sizeof(*orig.origin));
|
||||
*orig.origin = F1AP_PAGING_ORIGIN_NON_3GPP;
|
||||
orig.n_cells = 1;
|
||||
orig.cells = calloc_or_fail(orig.n_cells, sizeof(*orig.cells));
|
||||
orig.cells[0].plmn.mcc = 1;
|
||||
orig.cells[0].plmn.mnc = 1;
|
||||
orig.cells[0].plmn.mnc_digit_length = 2;
|
||||
orig.cells[0].nr_cellid = 987654;
|
||||
|
||||
test_f1ap_paging_rt(&orig);
|
||||
free_f1ap_paging(&orig);
|
||||
}
|
||||
|
||||
printf("%s() successful\n", __func__);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_initial_ul_rrc_message_transfer();
|
||||
@@ -2427,5 +2501,6 @@ int main()
|
||||
test_f1ap_positioning_measurement_abort();
|
||||
test_f1ap_positioning_measurement_failure_indication();
|
||||
test_f1ap_positioning_measurement_update();
|
||||
test_f1ap_paging();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -716,7 +716,7 @@ int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_
|
||||
str->buf[3] = rv[3];
|
||||
str->buf[4] = rv[4] & 0xfe;
|
||||
} else {
|
||||
uint64_t fiveG_S_TMSI_part1 = fiveG_S_TMSI & ((1ULL << 39) - 1);
|
||||
uint64_t fiveG_S_TMSI_part1 = nr_extract_5g_s_tmsi_part1(fiveG_S_TMSI);
|
||||
/** set the ue-Identity to ng-5G-S-TMSI-Part1
|
||||
* ng-5G-S-TMSI-Part1: the rightmost 39 bits of 5G-S-TMSI
|
||||
* BIT STRING (SIZE (39)) - 3GPP TS 38.331 */
|
||||
@@ -840,7 +840,7 @@ int do_RRCSetupComplete(uint8_t *buffer,
|
||||
str->size = 2;
|
||||
str->bits_unused = 7;
|
||||
str->buf = calloc_or_fail(str->size, sizeof(str->buf[0]));
|
||||
uint16_t fiveG_s_tmsi_part2 = (fiveG_s_tmsi >> 39) & ((1ULL << 9) - 1);
|
||||
uint16_t fiveG_s_tmsi_part2 = nr_extract_5g_s_tmsi_part2(fiveG_s_tmsi);
|
||||
str->buf[0] = (fiveG_s_tmsi_part2 >> (8 - str->bits_unused)) & 0xFF;
|
||||
str->buf[1] = (fiveG_s_tmsi_part2 << str->bits_unused) & 0xFF;
|
||||
LOG_D(NR_RRC, "5G-S-TMSI part 2 %d in RRCSetupComplete (5G-S-TMSI %ld)\n", fiveG_s_tmsi_part2, fiveG_s_tmsi);
|
||||
|
||||
@@ -2,7 +2,7 @@ add_executable(test_asn1_msg
|
||||
test_asn1_msg.cpp
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_rlc/asn1_utils.c)
|
||||
target_link_libraries(test_asn1_msg PRIVATE nr_rrc SECURITY minimal_lib GTest::gtest UTIL)
|
||||
target_link_libraries(test_asn1_msg PRIVATE nr_rrc SECURITY minimal_lib GTest::gtest UTIL nr_common)
|
||||
add_dependencies(tests test_asn1_msg)
|
||||
add_test(NAME test_asn1_msg
|
||||
COMMAND ./test_asn1_msg)
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef void (*ue_context_modification_refuse_func_t)(sctp_assoc_t assoc_id, con
|
||||
typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd);
|
||||
|
||||
typedef void (*dl_rrc_message_transfer_func_t)(sctp_assoc_t assoc_id, const f1ap_dl_rrc_message_t *dl_rrc);
|
||||
typedef void (*f1_paging_transfer_func_t)(sctp_assoc_t assoc_id, const f1ap_paging_t *paging);
|
||||
|
||||
struct nr_mac_rrc_dl_if_s;
|
||||
void mac_rrc_dl_direct_init(struct nr_mac_rrc_dl_if_s *mac_rrc);
|
||||
|
||||
@@ -94,6 +94,16 @@ static void dl_rrc_message_transfer_direct(sctp_assoc_t assoc_id, const f1ap_dl_
|
||||
dl_rrc_message_transfer(dl_rrc);
|
||||
}
|
||||
|
||||
static void f1_paging_transfer_direct(sctp_assoc_t assoc_id, const f1ap_paging_t *paging)
|
||||
{
|
||||
AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id);
|
||||
/** @todo Build PCCH-Message (Paging) at DU per TS 38.331 §5.3.2; apply
|
||||
* RRC padding per §8.5; deliver as RLC SDU per §8.2. For each
|
||||
* cell in Paging Cell List that belongs to this DU, queue for MAC;
|
||||
* MAC schedules at PF/PO per TS 38.304 §7. */
|
||||
(void)paging;
|
||||
}
|
||||
|
||||
void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc)
|
||||
{
|
||||
mac_rrc->f1_reset = f1_reset_cu_initiated_direct;
|
||||
@@ -107,4 +117,5 @@ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc)
|
||||
mac_rrc->ue_context_modification_refuse = ue_context_modification_refuse_direct;
|
||||
mac_rrc->ue_context_release_command = ue_context_release_command_direct;
|
||||
mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_direct;
|
||||
mac_rrc->paging_transfer = f1_paging_transfer_direct;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "intertask_interface.h"
|
||||
#include "mac_rrc_dl.h"
|
||||
#include "nr_rrc_defs.h"
|
||||
#include "lib/f1ap_paging.h"
|
||||
#include "lib/f1ap_rrc_message_transfer.h"
|
||||
#include "lib/f1ap_interface_management.h"
|
||||
#include "lib/f1ap_ue_context.h"
|
||||
@@ -138,6 +139,15 @@ static void dl_rrc_message_transfer_f1ap(sctp_assoc_t assoc_id, const f1ap_dl_rr
|
||||
itti_send_msg_to_task (TASK_CU_F1, 0, message_p);
|
||||
}
|
||||
|
||||
static void paging_f1ap(sctp_assoc_t assoc_id, const f1ap_paging_t *paging)
|
||||
{
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_PAGING);
|
||||
message_p->ittiMsgHeader.originInstance = assoc_id;
|
||||
f1ap_paging_t *msg = &F1AP_PAGING(message_p);
|
||||
*msg = cp_f1ap_paging(paging);
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, message_p);
|
||||
}
|
||||
|
||||
void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc)
|
||||
{
|
||||
mac_rrc->f1_reset = f1_reset_cu_initiated_f1ap;
|
||||
@@ -151,4 +161,5 @@ void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc)
|
||||
mac_rrc->ue_context_modification_refuse = ue_context_modification_refuse_f1ap;
|
||||
mac_rrc->ue_context_release_command = ue_context_release_command_f1ap;
|
||||
mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_f1ap;
|
||||
mac_rrc->paging_transfer = paging_f1ap;
|
||||
}
|
||||
|
||||
@@ -362,6 +362,7 @@ typedef struct nr_mac_rrc_dl_if_s {
|
||||
ue_context_modification_refuse_func_t ue_context_modification_refuse;
|
||||
ue_context_release_command_func_t ue_context_release_command;
|
||||
dl_rrc_message_transfer_func_t dl_rrc_message_transfer;
|
||||
f1_paging_transfer_func_t paging_transfer;
|
||||
} nr_mac_rrc_dl_if_t;
|
||||
|
||||
typedef struct cucp_cuup_if_s {
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "common/openairinterface5g_limits.h"
|
||||
#include "common/platform_constants.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "common_lib.h"
|
||||
#include "constr_SEQUENCE.h"
|
||||
#include "constr_TYPE.h"
|
||||
@@ -2077,7 +2078,7 @@ static void handle_rrcSetupComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const N
|
||||
uint16_t stmsi_part2 = BIT_STRING_to_uint16(part2);
|
||||
LOG_I(RRC, "s_tmsi part2 %d (%02x %02x)\n", stmsi_part2, part2->buf[0], part2->buf[1]);
|
||||
// Part2 is leftmost 9, Part1 is rightmost 39 bits of 5G-S-TMSI
|
||||
fiveg_s_TMSI = ((uint64_t) stmsi_part2) << 39 | UE->ng_5G_S_TMSI_Part1;
|
||||
fiveg_s_TMSI = nr_build_full_5g_s_tmsi(UE->ng_5G_S_TMSI_Part1, stmsi_part2);
|
||||
} else {
|
||||
LOG_W(RRC, "UE %d received 5G-S-TMSI-Part2, but no 5G-S-TMSI-Part1 present, won't send 5G-S-TMSI to core\n", UE->rrc_ue_id);
|
||||
UE->Initialue_identity_5g_s_TMSI.presence = false;
|
||||
@@ -2094,9 +2095,10 @@ static void handle_rrcSetupComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const N
|
||||
}
|
||||
|
||||
if (UE->Initialue_identity_5g_s_TMSI.presence) {
|
||||
uint16_t amf_set_id = fiveg_s_TMSI >> 38;
|
||||
uint8_t amf_pointer = (fiveg_s_TMSI >> 32) & 0x3F;
|
||||
uint32_t fiveg_tmsi = (uint32_t) fiveg_s_TMSI;
|
||||
uint16_t amf_set_id;
|
||||
uint8_t amf_pointer;
|
||||
uint32_t fiveg_tmsi;
|
||||
nr_deconstruct_5g_s_tmsi(fiveg_s_TMSI, &amf_set_id, &amf_pointer, &fiveg_tmsi);
|
||||
LOG_I(NR_RRC,
|
||||
"5g_s_TMSI: 0x%lX, amf_set_id: 0x%X (%d), amf_pointer: 0x%X (%d), 5g TMSI: 0x%X \n",
|
||||
fiveg_s_TMSI,
|
||||
@@ -3525,7 +3527,7 @@ void *rrc_gnb_task(void *args_p) {
|
||||
break;
|
||||
|
||||
case NGAP_PAGING_IND:
|
||||
rrc_gNB_process_PAGING_IND(msg_p, instance);
|
||||
rrc_gNB_process_PAGING_IND(RC.nrrrc[instance], instance, &NGAP_PAGING_IND(msg_p));
|
||||
break;
|
||||
|
||||
case NGAP_HANDOVER_REQUEST:
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#include "nr_pdcp/nr_pdcp_oai_api.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "openair2/F1AP/lib/f1ap_paging.h"
|
||||
#include "openair3/SECU/key_nas_deriver.h"
|
||||
#include "rrc_messages_types.h"
|
||||
#include "s1ap_messages_types.h"
|
||||
@@ -1629,56 +1630,67 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_comm
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rrc_gNB_process_PAGING_IND(MessageDef *msg_p, instance_t instance)
|
||||
/** @brief Handle NGAP Paging Indication from the AMF.
|
||||
* For each TAI in the message, matches (PLMN + TAC) against the gNB configuration; on match,
|
||||
* builds an F1AP Paging message and distributes it to all DUs that serve cells in that PLMN. */
|
||||
int rrc_gNB_process_PAGING_IND(gNB_RRC_INST *rrc, const instance_t instance, const ngap_paging_ind_t *msg)
|
||||
{
|
||||
ngap_paging_ind_t *msg = &NGAP_PAGING_IND(msg_p);
|
||||
for (uint16_t tai_size = 0; tai_size < msg->tai_size; tai_size++) {
|
||||
plmn_id_t *p = &msg->plmn_identity[tai_size];
|
||||
LOG_I(NR_RRC,
|
||||
"[gNB %ld] TAI List for Paging: MCC=%03d, MNC=%0*d, TAC=%d\n",
|
||||
DevAssert(rrc);
|
||||
DevAssert(msg);
|
||||
|
||||
// Construct 5G-S-TMSI from paging identity components
|
||||
const fiveg_s_tmsi_t *s_tmsi = &msg->ue_paging_identity.s_tmsi;
|
||||
const uint64_t fiveg_s_tmsi = nr_construct_5g_s_tmsi(s_tmsi->amf_set_id, s_tmsi->amf_pointer, s_tmsi->m_tmsi);
|
||||
const nr_rrc_config_t *req = &rrc->configuration;
|
||||
DevAssert(req->num_plmn > 0);
|
||||
|
||||
LOG_D(NR_RRC, "[gNB %ld] Processing NGAP Paging Indication for %d TAIs\n", instance, msg->n_tai);
|
||||
|
||||
// Paging Attempt Information (TS 38.413 §9.3.1.72, TS 38.300 §9.2.5)
|
||||
// AMF provides attempt count and intended attempts for paging optimization (area expansion, retransmission logic).
|
||||
if (msg->paging_attempt_info != NULL) {
|
||||
LOG_D(NR_RRC,
|
||||
"[gNB %ld] Paging Attempt Count: %u, Intended Number of Attempts: %u\n",
|
||||
instance,
|
||||
p->mcc,
|
||||
p->mnc_digit_length,
|
||||
p->mnc,
|
||||
msg->tac[tai_size]);
|
||||
nr_rrc_config_t *req = &RC.nrrrc[instance]->configuration;
|
||||
for (uint8_t j = 0; j < req->num_plmn; j++) {
|
||||
plmn_id_t *req_plmn = &req->plmn[j];
|
||||
if (req_plmn->mcc == p->mcc && req_plmn->mnc == p->mnc && req->tac == msg->tac[tai_size]) {
|
||||
for (uint8_t CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
AssertFatal(false, "to be implemented properly\n");
|
||||
if (NODE_IS_CU(RC.nrrrc[instance]->node_type)) {
|
||||
MessageDef *m = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_PAGING_IND);
|
||||
F1AP_PAGING_IND(m).plmn = *req_plmn;
|
||||
// Construct 5G-S-TMSI-Part1 from paging identity to find UE
|
||||
const fiveg_s_tmsi_t *s_tmsi = &msg->ue_paging_identity.s_tmsi;
|
||||
uint64_t s_tmsi_part1 = nr_construct_5g_s_tmsi_part1(s_tmsi->amf_set_id, s_tmsi->amf_pointer, s_tmsi->m_tmsi);
|
||||
// Try to find UE by 5G-S-TMSI-Part1
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_ue_context_5g_s_tmsi_exist(RC.nrrrc[instance], s_tmsi_part1);
|
||||
if (ue_context_p == NULL) {
|
||||
LOG_W(NR_RRC, "UE not found by paging identity\n");
|
||||
return -1;
|
||||
}
|
||||
// UE found: use its associated cell
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
nr_rrc_cell_container_t *cell = rrc_get_pcell_for_ue(RC.nrrrc[instance], UE);
|
||||
if (cell == NULL) {
|
||||
LOG_W(NR_RRC, "UE %d (rnti %04x) found by paging identity but has no valid cell\n", UE->rrc_ue_id, UE->rnti);
|
||||
return -1;
|
||||
}
|
||||
F1AP_PAGING_IND(m).nr_cellid = cell->info.cell_id;
|
||||
F1AP_PAGING_IND(m).ueidentityindexvalue = (uint16_t)(msg->ue_paging_identity.s_tmsi.m_tmsi % 1024);
|
||||
F1AP_PAGING_IND(m).fiveg_s_tmsi = msg->ue_paging_identity.s_tmsi.m_tmsi;
|
||||
F1AP_PAGING_IND(m).paging_drx = msg->paging_drx;
|
||||
LOG_E(F1AP, "ueidentityindexvalue %u fiveg_s_tmsi %ld paging_drx %u\n", F1AP_PAGING_IND (m).ueidentityindexvalue, F1AP_PAGING_IND (m).fiveg_s_tmsi, F1AP_PAGING_IND (m).paging_drx);
|
||||
itti_send_msg_to_task(TASK_CU_F1, instance, m);
|
||||
} else {
|
||||
//rrc_gNB_generate_pcch_msg(NGAP_PAGING_IND(msg_p).ue_paging_identity.s_tmsi.m_tmsi,(uint8_t)NGAP_PAGING_IND(msg_p).paging_drx, instance, CC_id);
|
||||
} // end of nodetype check
|
||||
} // end of cc loop
|
||||
} // end of mcc mnc check
|
||||
} // end of num_plmn
|
||||
} // end of tai size
|
||||
msg->paging_attempt_info->paging_attempt_count,
|
||||
msg->paging_attempt_info->intended_paging_attempts);
|
||||
}
|
||||
|
||||
if (msg->n_tai > NGAP_MAX_NO_TAI_PAGING) {
|
||||
LOG_E(NR_RRC,
|
||||
"[gNB %ld] Paging message error: n_tai (%d) exceeds NGAP_MAX_NO_TAI_PAGING (%d)\n",
|
||||
instance,
|
||||
msg->n_tai,
|
||||
NGAP_MAX_NO_TAI_PAGING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Build F1AP paging message once for all TAIs
|
||||
f1ap_paging_t f1ap_msg = {0};
|
||||
f1ap_msg.ue_identity_index_value = s_tmsi->m_tmsi % 1024;
|
||||
f1ap_msg.identity_type = F1AP_PAGING_IDENTITY_CN_UE;
|
||||
f1ap_msg.identity.cn_ue_paging_identity = fiveg_s_tmsi;
|
||||
if (msg->paging_drx != NULL) {
|
||||
/* Mapping 1:1 between NGAP and F1AP Paging DRX */
|
||||
f1ap_msg.drx = malloc_or_fail(sizeof(*f1ap_msg.drx));
|
||||
*f1ap_msg.drx = (f1ap_paging_drx_t)*msg->paging_drx;
|
||||
}
|
||||
if (msg->paging_priority != NULL) {
|
||||
/* Mapping 1:1 between NGAP and F1AP Paging Priority */
|
||||
f1ap_msg.priority = malloc_or_fail(sizeof(*f1ap_msg.priority));
|
||||
*f1ap_msg.priority = (f1ap_paging_priority_t)*msg->paging_priority;
|
||||
}
|
||||
if (msg->origin != NULL) {
|
||||
/* Mapping 1:1 between NGAP and F1AP Paging Origin */
|
||||
f1ap_msg.origin = malloc_or_fail(sizeof(*f1ap_msg.origin));
|
||||
*f1ap_msg.origin = (f1ap_paging_origin_t)*msg->origin;
|
||||
}
|
||||
|
||||
// For each DU, collect cells matching any AMF TAI (PLMN+TAC) and send
|
||||
// one Paging with that cell list.
|
||||
rrc_send_paging_to_dus(rrc, msg->tai_list, msg->n_tai, &f1ap_msg);
|
||||
|
||||
free_f1ap_paging(&f1ap_msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE
|
||||
|
||||
void nr_rrc_pdcp_config_security(gNB_RRC_UE_t *UE, bool enable_ciphering);
|
||||
|
||||
int rrc_gNB_process_PAGING_IND(MessageDef *msg_p, instance_t instance);
|
||||
int rrc_gNB_process_PAGING_IND(gNB_RRC_INST *rrc, const instance_t instance, const ngap_paging_ind_t *msg);
|
||||
|
||||
void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc,
|
||||
gNB_RRC_UE_t *UE,
|
||||
|
||||
@@ -820,3 +820,71 @@ void trigger_f1_reset(gNB_RRC_INST *rrc, sctp_assoc_t du_assoc_id)
|
||||
};
|
||||
rrc->mac_rrc.f1_reset(du_assoc_id, &reset);
|
||||
}
|
||||
|
||||
/** @brief Distribute paging to DUs serving cells matching any of the requested TAIs.
|
||||
* Loops DUs once, collects matching cells per DU, sends one message per DU.
|
||||
* Each cell is added at most once per DU (cells are unique by cell_id within a DU).
|
||||
* Per 3GPP TS 23.003, TAI is uniquely identified by (PLMN, TAC) combination.
|
||||
* @param rrc RRC instance
|
||||
* @param tais Array of TAIs (PLMN + TAC) to match against
|
||||
* @param n_tai Number of TAIs in the array (must be > 0)
|
||||
* @param msg Pre-filled F1AP paging message */
|
||||
void rrc_send_paging_to_dus(gNB_RRC_INST *rrc, const nr_tai_t tais[], uint8_t n_tai, f1ap_paging_t *msg)
|
||||
{
|
||||
DevAssert(msg && !msg->cells);
|
||||
DevAssert(n_tai > 0);
|
||||
|
||||
nr_rrc_du_container_t *du = NULL;
|
||||
// Loop over DUs once, for each DU, collects matching cells
|
||||
RB_FOREACH (du, rrc_du_tree, &rrc->dus) {
|
||||
RETURN_IF_INVALID_ASSOC_ID(du->assoc_id);
|
||||
|
||||
// Stack-allocated cell list for this DU iteration
|
||||
f1ap_paging_cell_item_t cells[F1AP_MAX_NB_CELLS] = {0};
|
||||
msg->cells = cells;
|
||||
msg->n_cells = 0;
|
||||
|
||||
// For each cell in this DU, check if it matches any of the matching TAIs
|
||||
FOR_EACH_SEQ_ARR (nr_rrc_cell_container_t **, cell, &du->cells) {
|
||||
if (msg->n_cells >= F1AP_MAX_NB_CELLS) {
|
||||
LOG_W(F1AP,
|
||||
"[gNB] Paging: DU assoc_id %d has more than %d matching cells, skipping next cells\n",
|
||||
du->assoc_id,
|
||||
F1AP_MAX_NB_CELLS);
|
||||
break;
|
||||
}
|
||||
|
||||
const nr_rrc_cell_info_t *info = &(*cell)->info;
|
||||
const plmn_id_t *cell_plmn = &info->plmn;
|
||||
const uint16_t cell_tac = info->tac;
|
||||
// Check if this cell's TAI (PLMN + TAC) matches any of the matching TAIs
|
||||
for (uint8_t j = 0; j < n_tai; j++) {
|
||||
const nr_tai_t *req_tai = &tais[j];
|
||||
const plmn_id_t *req_plmn = &req_tai->plmn;
|
||||
const uint16_t req_tac = req_tai->tac;
|
||||
if (cell_plmn->mcc == req_plmn->mcc && cell_plmn->mnc == req_plmn->mnc
|
||||
&& cell_plmn->mnc_digit_length == req_plmn->mnc_digit_length && cell_tac == req_tac) {
|
||||
f1ap_paging_cell_item_t *paging_cell = &msg->cells[msg->n_cells++];
|
||||
paging_cell->plmn = *cell_plmn;
|
||||
paging_cell->nr_cellid = info->cell_id;
|
||||
break; // Found match, no need to check other TAIs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip DUs with no matching cells
|
||||
if (msg->n_cells == 0)
|
||||
continue;
|
||||
DevAssert(msg->n_cells <= F1AP_MAX_NB_CELLS);
|
||||
LOG_I(F1AP,
|
||||
"[gNB] Paging transfer to DU assoc_id %d: ue_identity_index_value=%u, paging_identity=%lu, n_cells=%u\n",
|
||||
du->assoc_id,
|
||||
msg->ue_identity_index_value,
|
||||
msg->identity.cn_ue_paging_identity,
|
||||
msg->n_cells);
|
||||
// Send one message to the DU with all matching cells
|
||||
rrc->mac_rrc.paging_transfer(du->assoc_id, msg);
|
||||
}
|
||||
|
||||
msg->cells = NULL; // Stack allocation, no need to free
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@ struct nr_rrc_cell_container_t;
|
||||
struct f1ap_gnb_du_configuration_update_s;
|
||||
struct f1ap_served_cell_info_t;
|
||||
|
||||
#include "f1ap_messages_types.h"
|
||||
#include "ngap_messages_types.h"
|
||||
|
||||
void rrc_gNB_process_f1_setup_req(struct f1ap_setup_req_s *req, sctp_assoc_t assoc_id);
|
||||
void rrc_CU_process_f1_lost_connection(struct gNB_RRC_INST_s *rrc, struct f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id);
|
||||
void rrc_gNB_process_f1_du_configuration_update(struct f1ap_gnb_du_configuration_update_s *conf_up, sctp_assoc_t assoc_id);
|
||||
@@ -58,4 +61,6 @@ struct nr_rrc_du_container_t *find_target_du(struct gNB_RRC_INST_s *rrc, sctp_as
|
||||
|
||||
void trigger_f1_reset(struct gNB_RRC_INST_s *rrc, sctp_assoc_t du_assoc_id);
|
||||
|
||||
void rrc_send_paging_to_dus(struct gNB_RRC_INST_s *rrc, const nr_tai_t tais[], uint8_t n_tai, f1ap_paging_t *f1ap_msg);
|
||||
|
||||
#endif /* RRC_GNB_DU_H_ */
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <stdint.h>
|
||||
#include "OctetString.h"
|
||||
#include "fgs_nas_utils.h"
|
||||
#include "common/utils/utils.h" // text_info_t, TO_ENUM, TO_TEXT
|
||||
|
||||
#ifndef FGS_MOBILE_IDENTITY_H_
|
||||
#define FGS_MOBILE_IDENTITY_H_
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <stdint.h>
|
||||
#include "FGSNASSecurityModeReject.h"
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
#include "fgmm_lib.h"
|
||||
|
||||
int encode_fgs_security_mode_reject(byte_array_t *buffer, const fgs_security_mode_reject_msg *msg)
|
||||
@@ -45,6 +46,6 @@ int decode_fgs_security_mode_reject(fgs_security_mode_reject_msg *msg, const byt
|
||||
|
||||
bool eq_sec_mode_reject(const fgs_security_mode_reject_msg *a, const fgs_security_mode_reject_msg *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_EQ_CHECK_INT(a->cause, b->cause);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "conversions.h"
|
||||
#include "RegistrationAccept.h"
|
||||
#include "fgs_nas_utils.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "ds/byte_array.h"
|
||||
#include "fgmm_lib.h"
|
||||
@@ -47,7 +48,7 @@
|
||||
static int decode_fgs_registration_result(registration_accept_msg *out, const byte_array_t buffer)
|
||||
{
|
||||
if (buffer.len < FGS_REGISTRATION_RESULT_LEN) {
|
||||
PRINT_NAS_ERROR("5GS registration result decoding failure: invalid buffer length\n");
|
||||
PRINT_ERROR("5GS registration result decoding failure: invalid buffer length\n");
|
||||
return -1;
|
||||
}
|
||||
out->result = buffer.buf[1] & 0x7; // skip length of contents octet
|
||||
@@ -58,7 +59,7 @@ static int decode_fgs_registration_result(registration_accept_msg *out, const by
|
||||
static int encode_fgs_registration_result(byte_array_t buffer, const registration_accept_msg *out)
|
||||
{
|
||||
if (buffer.len < FGS_REGISTRATION_RESULT_LEN) {
|
||||
PRINT_NAS_ERROR("5GS registration result encoding failure: invalid buffer length\n");
|
||||
PRINT_ERROR("5GS registration result encoding failure: invalid buffer length\n");
|
||||
return -1;
|
||||
}
|
||||
uint8_t *buf = buffer.buf;
|
||||
@@ -125,7 +126,7 @@ static int decode_nssai_ie(nr_nas_msg_snssai_t *nssai, uint8_t *num_slices, uint
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINT_NAS_ERROR("Unknown length in Allowed S-NSSAI list item\n");
|
||||
PRINT_ERROR("Unknown length in Allowed S-NSSAI list item\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -139,7 +140,7 @@ size_t decode_registration_accept(registration_accept_msg *registration_accept,
|
||||
byte_array_t ba = buffer; // local copy of buffer
|
||||
|
||||
if (ba.len < REGISTRATION_ACCEPT_MIN_LEN) {
|
||||
PRINT_NAS_ERROR("Registration Accept decoding failed: invalid buffer length\n");
|
||||
PRINT_ERROR("Registration Accept decoding failed: invalid buffer length\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -152,7 +153,7 @@ size_t decode_registration_accept(registration_accept_msg *registration_accept,
|
||||
if (ba.len > 0 && ba.buf[0] == IEI_5G_GUTI) {
|
||||
registration_accept->guti = calloc_or_fail(1, sizeof(*registration_accept->guti));
|
||||
if ((dec = decode_5gs_mobile_identity(registration_accept->guti, IEI_5G_GUTI, ba.buf, ba.len)) < 0) {
|
||||
PRINT_NAS_ERROR("Failed to decode 5GS Mobile Identity in Registration Accept\n");
|
||||
PRINT_ERROR("Failed to decode 5GS Mobile Identity in Registration Accept\n");
|
||||
return -1;
|
||||
}
|
||||
UPDATE_BYTE_ARRAY(ba, dec);
|
||||
@@ -182,7 +183,7 @@ size_t decode_registration_accept(registration_accept_msg *registration_accept,
|
||||
}
|
||||
}
|
||||
if(ba.len != 0) {
|
||||
PRINT_NAS_ERROR("Failed to decode registration accept: ba.len = %ld\n", ba.len);
|
||||
PRINT_ERROR("Failed to decode registration accept: ba.len = %ld\n", ba.len);
|
||||
return -1;
|
||||
}
|
||||
return buffer.len;
|
||||
@@ -209,22 +210,22 @@ int encode_registration_accept(const registration_accept_msg *registration_accep
|
||||
|
||||
bool eq_snssai(const nr_nas_msg_snssai_t *a, const nr_nas_msg_snssai_t *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_INT(a->sst, b->sst);
|
||||
_EQ_CHECK_INT(a->sst, b->sst);
|
||||
|
||||
if ((a->hplmn_sst && !b->hplmn_sst) || (!a->hplmn_sst && b->hplmn_sst))
|
||||
return false;
|
||||
if (a->hplmn_sst && b->hplmn_sst)
|
||||
_NAS_EQ_CHECK_INT(*a->hplmn_sst, *b->hplmn_sst);
|
||||
_EQ_CHECK_INT(*a->hplmn_sst, *b->hplmn_sst);
|
||||
|
||||
if ((a->sd && !b->sd) || (!a->sd && b->sd))
|
||||
return false;
|
||||
if (a->sd && b->sd)
|
||||
_NAS_EQ_CHECK_INT(*a->sd, *b->sd);
|
||||
_EQ_CHECK_INT(*a->sd, *b->sd);
|
||||
|
||||
if ((a->hplmn_sd && !b->hplmn_sd) || (!a->hplmn_sd && b->hplmn_sd))
|
||||
return false;
|
||||
if (a->hplmn_sd && b->hplmn_sd)
|
||||
_NAS_EQ_CHECK_INT(*a->hplmn_sd, *b->hplmn_sd);
|
||||
_EQ_CHECK_INT(*a->hplmn_sd, *b->hplmn_sd);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -233,48 +234,48 @@ bool eq_snssai(const nr_nas_msg_snssai_t *a, const nr_nas_msg_snssai_t *b)
|
||||
bool eq_fgmm_registration_accept(const registration_accept_msg *a, const registration_accept_msg *b)
|
||||
{
|
||||
if (!a || !b) {
|
||||
PRINT_NAS_ERROR("Null pointer in registration_accept_msg_eq\n");
|
||||
PRINT_ERROR("Null pointer in registration_accept_msg_eq\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5GS registration result (mandatory)
|
||||
_NAS_EQ_CHECK_INT(a->result, b->result);
|
||||
_NAS_EQ_CHECK_INT(a->sms_allowed, b->sms_allowed);
|
||||
_EQ_CHECK_INT(a->result, b->result);
|
||||
_EQ_CHECK_INT(a->sms_allowed, b->sms_allowed);
|
||||
|
||||
// GUTI (optional)
|
||||
if (a->guti && b->guti) {
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.spare, b->guti->guti.spare);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.oddeven, b->guti->guti.oddeven);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.typeofidentity, b->guti->guti.typeofidentity);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.mccdigit2, b->guti->guti.mccdigit2);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.mccdigit1, b->guti->guti.mccdigit1);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.mncdigit3, b->guti->guti.mncdigit3);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.mccdigit3, b->guti->guti.mccdigit3);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.mncdigit2, b->guti->guti.mncdigit2);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.mncdigit1, b->guti->guti.mncdigit1);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.amfregionid, b->guti->guti.amfregionid);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.amfsetid, b->guti->guti.amfsetid);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.amfpointer, b->guti->guti.amfpointer);
|
||||
_NAS_EQ_CHECK_INT(a->guti->guti.tmsi, b->guti->guti.tmsi);
|
||||
_EQ_CHECK_INT(a->guti->guti.spare, b->guti->guti.spare);
|
||||
_EQ_CHECK_INT(a->guti->guti.oddeven, b->guti->guti.oddeven);
|
||||
_EQ_CHECK_INT(a->guti->guti.typeofidentity, b->guti->guti.typeofidentity);
|
||||
_EQ_CHECK_INT(a->guti->guti.mccdigit2, b->guti->guti.mccdigit2);
|
||||
_EQ_CHECK_INT(a->guti->guti.mccdigit1, b->guti->guti.mccdigit1);
|
||||
_EQ_CHECK_INT(a->guti->guti.mncdigit3, b->guti->guti.mncdigit3);
|
||||
_EQ_CHECK_INT(a->guti->guti.mccdigit3, b->guti->guti.mccdigit3);
|
||||
_EQ_CHECK_INT(a->guti->guti.mncdigit2, b->guti->guti.mncdigit2);
|
||||
_EQ_CHECK_INT(a->guti->guti.mncdigit1, b->guti->guti.mncdigit1);
|
||||
_EQ_CHECK_INT(a->guti->guti.amfregionid, b->guti->guti.amfregionid);
|
||||
_EQ_CHECK_INT(a->guti->guti.amfsetid, b->guti->guti.amfsetid);
|
||||
_EQ_CHECK_INT(a->guti->guti.amfpointer, b->guti->guti.amfpointer);
|
||||
_EQ_CHECK_INT(a->guti->guti.tmsi, b->guti->guti.tmsi);
|
||||
} else if ((a->guti && !b->guti) || (!a->guti && b->guti)) {
|
||||
PRINT_NAS_ERROR("NAS Equality Check failure: One of the two GUTIs is NULL\n");
|
||||
PRINT_ERROR("NAS Equality Check failure: One of the two GUTIs is NULL\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
_NAS_EQ_CHECK_INT(a->num_allowed_slices, b->num_allowed_slices);
|
||||
_NAS_EQ_CHECK_INT(a->num_configured_slices, b->num_configured_slices);
|
||||
_EQ_CHECK_INT(a->num_allowed_slices, b->num_allowed_slices);
|
||||
_EQ_CHECK_INT(a->num_configured_slices, b->num_configured_slices);
|
||||
|
||||
// Configured NSSAI (optional)
|
||||
for (int i = 0; i < a->num_configured_slices; i++) {
|
||||
if (!eq_snssai(&a->config_nssai[i], &b->config_nssai[i])) {
|
||||
PRINT_NAS_ERROR("NAS Equality Check failure: Configured NSSAI\n");
|
||||
PRINT_ERROR("NAS Equality Check failure: Configured NSSAI\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Allowed NSSAI (optional)
|
||||
for (int i = 0; i < a->num_allowed_slices; i++) {
|
||||
if (!eq_snssai(&a->nas_allowed_nssai[i], &b->nas_allowed_nssai[i])) {
|
||||
PRINT_NAS_ERROR("NAS Equality Check failure: Allowed NSSAI\n");
|
||||
PRINT_ERROR("NAS Equality Check failure: Allowed NSSAI\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdlib.h> // For malloc and free
|
||||
#include "fgmm_lib.h"
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
#include "common/utils/utils.h"
|
||||
|
||||
#define MIN_AUTH_FAILURE_LEN 1
|
||||
@@ -35,7 +36,7 @@
|
||||
int encode_fgmm_auth_failure(byte_array_t *buffer, const fgmm_auth_failure_t *msg)
|
||||
{
|
||||
if (buffer->len < MIN_AUTH_FAILURE_LEN) {
|
||||
PRINT_NAS_ERROR("Missing mandatory IE in Authentication Failure");
|
||||
PRINT_ERROR("Missing mandatory IE in Authentication Failure");
|
||||
return -1; // missing mandatory IE
|
||||
}
|
||||
// 5GMM cause (Mandatory)
|
||||
@@ -44,11 +45,11 @@ int encode_fgmm_auth_failure(byte_array_t *buffer, const fgmm_auth_failure_t *ms
|
||||
if (msg->cause == Synch_failure) {
|
||||
// Authentication failure parameter shall be present with cause Synch Failure
|
||||
if (msg->authentication_failure_param.len == 0) {
|
||||
PRINT_NAS_ERROR("Authentication Failure Cause is synch failure but Authentication Failure Parameter is not available");
|
||||
PRINT_ERROR("Authentication Failure Cause is synch failure but Authentication Failure Parameter is not available");
|
||||
return -1;
|
||||
}
|
||||
if (buffer->len - encoded < msg->authentication_failure_param.len + 2) {
|
||||
PRINT_NAS_ERROR("Invalid buffer for encoding of Authentication Failure Parameter");
|
||||
PRINT_ERROR("Invalid buffer for encoding of Authentication Failure Parameter");
|
||||
return -1;
|
||||
}
|
||||
// Encode the IEI
|
||||
@@ -76,7 +77,7 @@ int decode_fgmm_auth_failure(fgmm_auth_failure_t *msg, const byte_array_t *buffe
|
||||
if (iei == AUTH_FAIL_PARAM_IEI) {
|
||||
msg->authentication_failure_param.len = ba.buf[decoded++];
|
||||
if (msg->authentication_failure_param.len > AUTH_FAILURE_PARAM_LEN - 2) { // maximum length of contents is 14 octets
|
||||
PRINT_NAS_ERROR("Length of Authentication Failure Parameter contents is too large");
|
||||
PRINT_ERROR("Length of Authentication Failure Parameter contents is too large");
|
||||
return -1;
|
||||
}
|
||||
msg->authentication_failure_param.buf = malloc_or_fail(msg->authentication_failure_param.len);
|
||||
@@ -90,7 +91,7 @@ int decode_fgmm_auth_failure(fgmm_auth_failure_t *msg, const byte_array_t *buffe
|
||||
|
||||
bool eq_fgmm_auth_failure(const fgmm_auth_failure_t *a, const fgmm_auth_failure_t *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_EQ_CHECK_INT(a->cause, b->cause);
|
||||
eq_byte_array(&a->authentication_failure_param, &b->authentication_failure_param);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <arpa/inet.h> // For htons and ntohs
|
||||
#include <stdlib.h> // For malloc and free
|
||||
#include "fgmm_lib.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
|
||||
#define MIN_AUTH_REJECT_LEN 3
|
||||
|
||||
@@ -55,13 +56,13 @@ int decode_fgmm_auth_reject(fgmm_auth_reject_msg_t *msg, const byte_array_t *buf
|
||||
if (iei == IEI_EAPMSG) {
|
||||
return (decoded + decode_eap_msg_ie(&msg->eap_msg, &ba));
|
||||
}
|
||||
PRINT_NAS_ERROR("Expected EAP MSG but it is not present");
|
||||
PRINT_ERROR("Expected EAP MSG but it is not present");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool eq_auth_reject(fgmm_auth_reject_msg_t *a, fgmm_auth_reject_msg_t *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_LONG(a->eap_msg.len, b->eap_msg.len);
|
||||
_EQ_CHECK_LONG(a->eap_msg.len, b->eap_msg.len);
|
||||
if (a->eap_msg.len > 0) {
|
||||
return !memcmp(a->eap_msg.buf, b->eap_msg.buf, a->eap_msg.len);
|
||||
}
|
||||
|
||||
@@ -22,11 +22,12 @@
|
||||
#include "fgmm_identity_request.h"
|
||||
#include <string.h>
|
||||
#include "FGSMobileIdentity.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
|
||||
int decode_fgs_identity_request(fgs_identity_request_msg_t *msg, const byte_array_t *buffer)
|
||||
{
|
||||
if (buffer->len < 1) {
|
||||
PRINT_NAS_ERROR("Failed to decode NAS Identity Request: invalid buffer length %ld\n", buffer->len);
|
||||
PRINT_ERROR("Failed to decode NAS Identity Request: invalid buffer length %ld\n", buffer->len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <arpa/inet.h> // For htons and ntohs
|
||||
#include <stdlib.h> // For malloc and free
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
|
||||
#define IEI_LEN 1
|
||||
#define GPRS_TIMER_LENGTH 3 // octets
|
||||
@@ -41,7 +42,7 @@
|
||||
int encode_pdu_session_ie(byte_array_t *buffer, nas_service_IEI_t iei, const uint8_t *psi)
|
||||
{
|
||||
if (buffer->len < MIN_PDU_SESSION_CONTENTS_LEN + 2) {
|
||||
PRINT_NAS_ERROR("%s failed: buffer is too small", __func__);
|
||||
PRINT_ERROR("%s failed: buffer is too small", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -83,14 +84,14 @@ int decode_pdu_session_ie(uint8_t *psi, const byte_array_t *buffer)
|
||||
uint8_t *buf = buffer->buf;
|
||||
|
||||
if (buffer->len < MIN_PDU_SESSION_CONTENTS_LEN + 2) {
|
||||
PRINT_NAS_ERROR("%s failed: buffer length is too small", __func__);
|
||||
PRINT_ERROR("%s failed: buffer length is too small", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// start decoding from length IE (IEI is decoded in the caller)
|
||||
uint8_t pdu_session_status_len = buf[decoded++];
|
||||
if (pdu_session_status_len > MAX_PDU_SESSION_CONTENTS_LEN) {
|
||||
PRINT_NAS_ERROR("decoded length is out of bound for PDU Session Status/Reactivation result\n");
|
||||
PRINT_ERROR("decoded length is out of bound for PDU Session Status/Reactivation result\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -116,7 +117,7 @@ int decode_pdu_session_ie(uint8_t *psi, const byte_array_t *buffer)
|
||||
int encode_gprs_timer_ie(byte_array_t *buffer, nas_service_IEI_t iei, const gprs_timer_t *timer)
|
||||
{
|
||||
if (buffer->len < GPRS_TIMER_LENGTH) {
|
||||
PRINT_NAS_ERROR("Buffer length is too short to encode the GPRS Timer IE\n");
|
||||
PRINT_ERROR("Buffer length is too short to encode the GPRS Timer IE\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -150,8 +151,8 @@ int decode_gprs_timer_ie(gprs_timer_t *timer, const byte_array_t *buffer)
|
||||
/** @brief Equality check for GPRS Timer */
|
||||
bool eq_gprs_timer(const gprs_timer_t *a, const gprs_timer_t *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_INT(a->value, b->value);
|
||||
_NAS_EQ_CHECK_INT(a->unit, b->unit);
|
||||
_EQ_CHECK_INT(a->value, b->value);
|
||||
_EQ_CHECK_INT(a->unit, b->unit);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -162,13 +163,13 @@ int encode_eap_msg_ie(byte_array_t *buffer, const byte_array_t *msg)
|
||||
|
||||
// Sanity check on buffer length
|
||||
if (buffer->len < MIN_EAP_MSG_LEN) {
|
||||
PRINT_NAS_ERROR("Invalid buffer length %ld", buffer->len);
|
||||
PRINT_ERROR("Invalid buffer length %ld", buffer->len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Sanity check on input length
|
||||
if (msg->len < MIN_EAP_CONTENTS_LEN || msg->len > MAX_EAP_CONTENTS_LEN) {
|
||||
PRINT_NAS_ERROR("Invalid EAP message length %ld", msg->len);
|
||||
PRINT_ERROR("Invalid EAP message length %ld", msg->len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -196,7 +197,7 @@ int decode_eap_msg_ie(byte_array_t *eap_msg, const byte_array_t *buffer)
|
||||
|
||||
// Check buffer length validity
|
||||
if (buffer->len < min_len_to_decode) {
|
||||
PRINT_NAS_ERROR("Invalid buffer for decoding EAP message IE");
|
||||
PRINT_ERROR("Invalid buffer for decoding EAP message IE");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -206,13 +207,13 @@ int decode_eap_msg_ie(byte_array_t *eap_msg, const byte_array_t *buffer)
|
||||
|
||||
// Check payload length validity
|
||||
if (eap_msg->len < MIN_EAP_CONTENTS_LEN || eap_msg->len > MAX_EAP_CONTENTS_LEN) {
|
||||
PRINT_NAS_ERROR("Invalid EAP message length %ld", eap_msg->len);
|
||||
PRINT_ERROR("Invalid EAP message length %ld", eap_msg->len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check for buffer overflow
|
||||
if (buffer->len < decoded + eap_msg->len) {
|
||||
PRINT_NAS_ERROR("Buffer too short for EAP message: %ld < %ld", buffer->len, decoded + eap_msg->len);
|
||||
PRINT_ERROR("Buffer too short for EAP message: %ld < %ld", buffer->len, decoded + eap_msg->len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <stdbool.h>
|
||||
#include "fgs_nas_utils.h"
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "common/utils/utils.h"
|
||||
|
||||
/* The following defines are valide for
|
||||
both PDU Session Status and PDU session Reactivation Result IEs */
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdlib.h> // For malloc and free
|
||||
#include "common/utils/utils.h" // For malloc_or_fail
|
||||
#include "common/utils/ds/byte_array.h" // For byte_array_t
|
||||
#include "common/utils/eq_check.h"
|
||||
#include "fgmm_lib.h"
|
||||
|
||||
/** @brief Encode Service Accept (8.2.17 of 3GPP TS 24.501) */
|
||||
@@ -53,7 +54,7 @@ int encode_fgs_service_accept(byte_array_t *buffer, const fgs_service_accept_msg
|
||||
// encode length of PDU session reactivation result error cause
|
||||
uint16_t error_len = msg->num_errors * sizeof(msg->cause[0]);
|
||||
if (error_len > MAX_NUM_PDU_ERRORS) {
|
||||
PRINT_NAS_ERROR("encoded length is out of bound (IEI_PDU_SESSION_REACT_RESULT_ERROR_CAUSE)\n");
|
||||
PRINT_ERROR("encoded length is out of bound (IEI_PDU_SESSION_REACT_RESULT_ERROR_CAUSE)\n");
|
||||
return -1;
|
||||
}
|
||||
uint16_t n_len = htons(error_len);
|
||||
@@ -115,7 +116,7 @@ int decode_fgs_service_accept(fgs_service_accept_msg_t *msg, const byte_array_t
|
||||
uint16_t error_len = ntohs(tmp);
|
||||
decoded += sizeof(error_len);
|
||||
if (error_len > MAX_NUM_PDU_ERRORS * sizeof(msg->cause[0])) {
|
||||
PRINT_NAS_ERROR("IEI_PDU_SESSION_REACT_RESULT_ERROR_CAUSE: decoded length is out of bound\n");
|
||||
PRINT_ERROR("IEI_PDU_SESSION_REACT_RESULT_ERROR_CAUSE: decoded length is out of bound\n");
|
||||
return -1;
|
||||
}
|
||||
// Decode each PDU Session ID and Cause
|
||||
@@ -137,7 +138,7 @@ int decode_fgs_service_accept(fgs_service_accept_msg_t *msg, const byte_array_t
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINT_NAS_ERROR("Unkwown or invalid IEI %d\n", iei);
|
||||
PRINT_ERROR("Unkwown or invalid IEI %d\n", iei);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -150,26 +151,26 @@ int decode_fgs_service_accept(fgs_service_accept_msg_t *msg, const byte_array_t
|
||||
*/
|
||||
bool eq_service_accept(const fgs_service_accept_msg_t *a, const fgs_service_accept_msg_t *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_INT(a->has_psi_status, b->has_psi_status);
|
||||
_EQ_CHECK_INT(a->has_psi_status, b->has_psi_status);
|
||||
if (a->has_psi_status && b->has_psi_status) {
|
||||
for (int i = 0; i < MAX_NUM_PSI; i++)
|
||||
_NAS_EQ_CHECK_INT(a->psi_status[i], b->psi_status[i]);
|
||||
_EQ_CHECK_INT(a->psi_status[i], b->psi_status[i]);
|
||||
}
|
||||
_NAS_EQ_CHECK_INT(a->has_psi_res, b->has_psi_res);
|
||||
_EQ_CHECK_INT(a->has_psi_res, b->has_psi_res);
|
||||
if (a->has_psi_res && b->has_psi_res) {
|
||||
for (int i = 0; i < MAX_NUM_PSI; i++)
|
||||
_NAS_EQ_CHECK_INT(a->psi_res[i], b->psi_res[i]);
|
||||
_EQ_CHECK_INT(a->psi_res[i], b->psi_res[i]);
|
||||
}
|
||||
_NAS_EQ_CHECK_INT(a->num_errors, b->num_errors);
|
||||
_EQ_CHECK_INT(a->num_errors, b->num_errors);
|
||||
if (a->num_errors && b->num_errors) {
|
||||
for (int i = 0; i < a->num_errors; i++) {
|
||||
_NAS_EQ_CHECK_INT(a->cause[i].cause, b->cause[i].cause);
|
||||
_NAS_EQ_CHECK_INT(a->cause[i].pdu_session_id, b->cause[i].pdu_session_id);
|
||||
_EQ_CHECK_INT(a->cause[i].cause, b->cause[i].cause);
|
||||
_EQ_CHECK_INT(a->cause[i].pdu_session_id, b->cause[i].pdu_session_id);
|
||||
}
|
||||
}
|
||||
if (a->t3448 != NULL || b->t3448 != NULL) {
|
||||
if (a->t3448 == NULL || b->t3448 == NULL) {
|
||||
PRINT_NAS_ERROR("t3448 equality check failed\n");
|
||||
PRINT_ERROR("t3448 equality check failed\n");
|
||||
return false;
|
||||
}
|
||||
if (!eq_gprs_timer(a->t3448, b->t3448))
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdlib.h> // For malloc and free
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
#include "fgmm_lib.h"
|
||||
|
||||
#define SERVICE_REJECT_MIN_LEN 1 // 1 octet
|
||||
@@ -33,7 +34,7 @@
|
||||
int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg_t *msg)
|
||||
{
|
||||
if (buffer->len < SERVICE_REJECT_MIN_LEN) {
|
||||
PRINT_NAS_ERROR("Failed to encode Service Reject: missing Cause IE!\n");
|
||||
PRINT_ERROR("Failed to encode Service Reject: missing Cause IE!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -71,7 +72,7 @@ int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg
|
||||
int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t *buffer)
|
||||
{
|
||||
if (buffer->len < SERVICE_REJECT_MIN_LEN) {
|
||||
PRINT_NAS_ERROR("Nothing to decode: missing Cause IE!\n");
|
||||
PRINT_ERROR("Nothing to decode: missing Cause IE!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -112,11 +113,11 @@ int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t
|
||||
int cag_len = cag_list_len + 2; // encoded content + 2 octets for the length IE
|
||||
decoded += cag_len;
|
||||
UPDATE_BYTE_ARRAY(ba, cag_len);
|
||||
PRINT_NAS_ERROR("CAG information list IE in NAS Service Reject is not handled\n");
|
||||
PRINT_ERROR("CAG information list IE in NAS Service Reject is not handled\n");
|
||||
} break;
|
||||
|
||||
default:
|
||||
PRINT_NAS_ERROR("Uknown or invalid NAS Service Reject IEI %d\n", iei);
|
||||
PRINT_ERROR("Uknown or invalid NAS Service Reject IEI %d\n", iei);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -127,15 +128,15 @@ int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t
|
||||
/** @brief Equality check for Service Reject (enc/dec) */
|
||||
bool eq_service_reject(const fgs_service_reject_msg_t *a, const fgs_service_reject_msg_t *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_NAS_EQ_CHECK_INT(a->has_psi_status, b->has_psi_status);
|
||||
_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_EQ_CHECK_INT(a->has_psi_status, b->has_psi_status);
|
||||
if (a->has_psi_status && b->has_psi_status) {
|
||||
for (int i = 0; i < MAX_NUM_PSI; i++)
|
||||
_NAS_EQ_CHECK_INT(a->psi_status[i], b->psi_status[i]);
|
||||
_EQ_CHECK_INT(a->psi_status[i], b->psi_status[i]);
|
||||
}
|
||||
if (a->t3448 != NULL || b->t3448 != NULL) {
|
||||
if (a->t3448 == NULL || b->t3448 == NULL) {
|
||||
PRINT_NAS_ERROR("t3448 equality check failed\n");
|
||||
PRINT_ERROR("t3448 equality check failed\n");
|
||||
return false;
|
||||
}
|
||||
if (!eq_gprs_timer(a->t3448, b->t3448))
|
||||
@@ -143,7 +144,7 @@ bool eq_service_reject(const fgs_service_reject_msg_t *a, const fgs_service_reje
|
||||
}
|
||||
if (a->t3446 != NULL || b->t3446 != NULL) {
|
||||
if (a->t3446 == NULL || b->t3446 == NULL) {
|
||||
PRINT_NAS_ERROR("t3448 equality check failed\n");
|
||||
PRINT_ERROR("t3448 equality check failed\n");
|
||||
return false;
|
||||
}
|
||||
if (!eq_gprs_timer(a->t3446, b->t3446))
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <arpa/inet.h>
|
||||
#include "PduSessionEstablishmentAccept.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/utils.h" // text_info_t, TO_ENUM, TO_TEXT
|
||||
#include "fgs_nas_utils.h"
|
||||
|
||||
/**
|
||||
@@ -205,7 +206,7 @@ int decode_pdu_session_establishment_accept_msg(pdu_session_establishment_accept
|
||||
}
|
||||
|
||||
default:
|
||||
PRINT_NAS_ERROR("Unknown IEI %d\n", psea_iei);
|
||||
PRINT_ERROR("Unknown IEI %d\n", psea_iei);
|
||||
curPtr = buffer + msg_length; // we force stop processing
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "fgs_nas_utils.h"
|
||||
#include "common/utils/utils.h" // text_info_t, TO_ENUM, TO_TEXT
|
||||
|
||||
/* PDU Session Establish Accept Optional IE Identifiers - TS 24.501 Table 8.3.2.1.1 */
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ add_subdirectory(5GMM/IES)
|
||||
add_subdirectory(5GSM/MSG)
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
target_compile_definitions(fgs_5gmm_lib PRIVATE ENABLE_TESTS)
|
||||
target_compile_definitions(fgs_5gmm_ies_lib PRIVATE ENABLE_TESTS)
|
||||
target_compile_definitions(fgs_5gsm_lib PRIVATE ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
add_library(fgs_lib fgs_nas_lib.c)
|
||||
@@ -16,3 +19,7 @@ target_link_libraries(fgs_lib PUBLIC
|
||||
)
|
||||
|
||||
target_include_directories(fgs_lib PUBLIC . 5GMM/MSG 5GMM/IES)
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
target_compile_definitions(fgs_lib PRIVATE ENABLE_TESTS)
|
||||
endif()
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "NR_NAS_defs.h"
|
||||
#include "nas_log.h"
|
||||
#include "TLVEncoder.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
#include "fgs_nas_utils.h"
|
||||
|
||||
int _nas_mm_msg_encode_header(const fgmm_msg_header_t *header, uint8_t *buffer, uint32_t len)
|
||||
@@ -56,7 +57,7 @@ int mm_msg_encode(const fgmm_nas_message_plain_t *p, uint8_t *buffer, uint32_t l
|
||||
int enc_header = _nas_mm_msg_encode_header(&p->header, buffer, len);
|
||||
|
||||
if (enc_header < 0) {
|
||||
PRINT_NAS_ERROR("Failed to encode 5GMM message header\n");
|
||||
PRINT_ERROR("Failed to encode 5GMM message header\n");
|
||||
return enc_header;
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ int mm_msg_encode(const fgmm_nas_message_plain_t *p, uint8_t *buffer, uint32_t l
|
||||
}
|
||||
|
||||
if (enc_msg < 0) {
|
||||
PRINT_NAS_ERROR("Failed to encode 5GMM message\n");
|
||||
PRINT_ERROR("Failed to encode 5GMM message\n");
|
||||
return enc_msg;
|
||||
}
|
||||
|
||||
@@ -116,7 +117,7 @@ int nas_protected_security_header_encode(uint8_t *buffer, const fgs_nas_message_
|
||||
int size = 0;
|
||||
|
||||
if (length < sizeof(fgs_nas_message_security_header_t)) {
|
||||
PRINT_NAS_ERROR("Could not encode the NAS security header\n");
|
||||
PRINT_ERROR("Could not encode the NAS security header\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -140,7 +141,7 @@ int nas_protected_security_header_encode(uint8_t *buffer, const fgs_nas_message_
|
||||
uint8_t decode_5gmm_msg_header(fgmm_msg_header_t *mm_header, const uint8_t *buffer, uint32_t len)
|
||||
{
|
||||
if (len < sizeof(fgmm_msg_header_t)) {
|
||||
PRINT_NAS_ERROR("Failed to decode plain 5GMM header: buffer length too short\n");
|
||||
PRINT_ERROR("Failed to decode plain 5GMM header: buffer length too short\n");
|
||||
return -1;
|
||||
}
|
||||
mm_header->ex_protocol_discriminator = *buffer++;
|
||||
@@ -155,7 +156,7 @@ uint8_t decode_5gmm_msg_header(fgmm_msg_header_t *mm_header, const uint8_t *buff
|
||||
uint8_t decode_5gsm_msg_header(fgsm_msg_header_t *sm_header, const uint8_t *buffer, uint32_t len)
|
||||
{
|
||||
if (len < sizeof(fgsm_msg_header_t)) {
|
||||
PRINT_NAS_ERROR("Failed to decode plain 5GSM header: buffer length too short\n");
|
||||
PRINT_ERROR("Failed to decode plain 5GSM header: buffer length too short\n");
|
||||
return -1;
|
||||
}
|
||||
sm_header->ex_protocol_discriminator = *buffer++;
|
||||
@@ -172,7 +173,7 @@ int decode_5gs_security_protected_header(fgs_nas_message_security_header_t *head
|
||||
{
|
||||
int decoded = 0;
|
||||
if (len < sizeof(fgs_nas_message_security_header_t)) {
|
||||
PRINT_NAS_ERROR("Failed to decode security protected 5GS header: buffer length too short\n");
|
||||
PRINT_ERROR("Failed to decode security protected 5GS header: buffer length too short\n");
|
||||
return -1;
|
||||
}
|
||||
header->protocol_discriminator = *buf++;
|
||||
|
||||
@@ -26,33 +26,8 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h> // For memcpy
|
||||
#include <stdio.h>
|
||||
|
||||
#define PRINT_NAS_ERROR(...) fprintf(stderr, ##__VA_ARGS__)
|
||||
|
||||
#define _NAS_EQ_CHECK_GENERIC(condition, fmt, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
PRINT_NAS_ERROR("NAS Equality Check failure: %s:%d: Condition '%s' failed: " fmt " != " fmt "\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#condition, \
|
||||
##__VA_ARGS__); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _NAS_EQ_CHECK_LONG(A, B) _NAS_EQ_CHECK_GENERIC(A == B, "%ld", A, B);
|
||||
#define _NAS_EQ_CHECK_INT(A, B) _NAS_EQ_CHECK_GENERIC(A == B, "%d", A, B);
|
||||
#define _NAS_EQ_CHECK_STR(A, B) _NAS_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B);
|
||||
|
||||
/* Map task id to printable name. */
|
||||
typedef struct {
|
||||
int id;
|
||||
char text[256];
|
||||
} text_info_t;
|
||||
|
||||
#define TO_TEXT(LabEl, nUmID) {nUmID, #LabEl},
|
||||
#define TO_ENUM(LabEl, nUmID ) LabEl = nUmID,
|
||||
#include "utils.h" // text_info_t, TO_ENUM, TO_TEXT
|
||||
#include "common/utils/eq_check.h"
|
||||
|
||||
#define GET_SHORT(input, size) ({ \
|
||||
uint16_t tmp16; \
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
add_subdirectory(MESSAGES)
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
@@ -27,9 +27,30 @@
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "conversions.h"
|
||||
#include "ngap_common.h"
|
||||
#include "ngap_msg_includes.h"
|
||||
|
||||
void tnl_to_bitstring(BIT_STRING_t *out, const transport_layer_addr_t in)
|
||||
{
|
||||
if (in.length) {
|
||||
out->buf = malloc_or_fail(in.length);
|
||||
memcpy(out->buf, in.buffer, in.length);
|
||||
out->size = in.length;
|
||||
out->bits_unused = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void bitstring_to_tnl(transport_layer_addr_t *out, const BIT_STRING_t in)
|
||||
{
|
||||
if (in.size) {
|
||||
memcpy(out->buffer, in.buf, in.size);
|
||||
out->length = in.size;
|
||||
}
|
||||
}
|
||||
|
||||
void encode_ngap_cause(NGAP_Cause_t *out, const ngap_cause_t *in)
|
||||
{
|
||||
@@ -271,3 +292,54 @@ bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRIN
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief PDU Session Resource Setup Response Transfer encoding (9.3.4.2 3GPP TS 38.413) */
|
||||
byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusession_setup_t *pdusession)
|
||||
{
|
||||
NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0};
|
||||
byte_array_t out = {0};
|
||||
|
||||
// DL QoS Flow per TNL Information (Mandatory)
|
||||
NGAP_QosFlowPerTNLInformation_t *dLQosFlowPerTNLInformation = &pdusessionTransfer.dLQosFlowPerTNLInformation;
|
||||
|
||||
// UP Transport Layer Information (Mandatory)
|
||||
dLQosFlowPerTNLInformation->uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
|
||||
asn1cCalloc(dLQosFlowPerTNLInformation->uPTransportLayerInformation.choice.gTPTunnel, gtp);
|
||||
GTP_TEID_TO_ASN1(pdusession->n3_outgoing.teid, >p->gTP_TEID);
|
||||
tnl_to_bitstring(>p->transportLayerAddress, pdusession->n3_outgoing.addr);
|
||||
char ip_str[INET_ADDRSTRLEN] = {0};
|
||||
inet_ntop(AF_INET, gtp->transportLayerAddress.buf, ip_str, sizeof(ip_str));
|
||||
NGAP_DEBUG("Encoded PDU Session Transfer (%d): TEID=0x%08x, Addr=%s\n",
|
||||
pdusession->pdusession_id,
|
||||
pdusession->n3_outgoing.teid,
|
||||
ip_str);
|
||||
|
||||
// Associated QoS Flow List (Mandatory)
|
||||
for (int j = 0; j < pdusession->nb_of_qos_flow; j++) {
|
||||
asn1cSequenceAdd(dLQosFlowPerTNLInformation->associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, qos_item);
|
||||
// QoS Flow Identifier (Mandatory)
|
||||
qos_item->qosFlowIdentifier = pdusession->associated_qos_flows[j].qfi;
|
||||
}
|
||||
|
||||
// Encode
|
||||
asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL,
|
||||
ATS_ALIGNED_CANONICAL_PER,
|
||||
&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer,
|
||||
&pdusessionTransfer);
|
||||
AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer);
|
||||
out.buf = res.buffer;
|
||||
out.len = res.result.encoded;
|
||||
return out;
|
||||
}
|
||||
|
||||
bool eq_ngap_plmn(const plmn_id_t *a, const plmn_id_t *b)
|
||||
{
|
||||
if (a == NULL || b == NULL) {
|
||||
return false;
|
||||
}
|
||||
_EQ_CHECK_INT(a->mcc, b->mcc);
|
||||
_EQ_CHECK_INT(a->mnc, b->mnc);
|
||||
_EQ_CHECK_INT(a->mnc_digit_length, b->mnc_digit_length);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,49 +36,19 @@
|
||||
#ifndef NGAP_COMMON_H_
|
||||
#define NGAP_COMMON_H_
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include <stdbool.h>
|
||||
#include "oai_asn1.h"
|
||||
#include "ngap_utils.h"
|
||||
#include "ngap_msg_includes.h"
|
||||
#include "openair2/COMMON/ngap_messages_types.h"
|
||||
#include "ngap_messages_types.h"
|
||||
|
||||
/* Checking version of ASN1C compiler */
|
||||
#if (ASN1C_ENVIRONMENT_VERSION < ASN1C_MINIMUM_VERSION)
|
||||
# error "You are compiling ngap with the wrong version of ASN1C"
|
||||
#endif
|
||||
|
||||
# include "common/utils/LOG/log.h"
|
||||
# include "ngap_gNB_default_values.h"
|
||||
# define NGAP_ERROR(x, args...) LOG_E(NGAP, x, ##args)
|
||||
# define NGAP_WARN(x, args...) LOG_W(NGAP, x, ##args)
|
||||
# define NGAP_TRAF(x, args...) LOG_I(NGAP, x, ##args)
|
||||
# define NGAP_INFO(x, args...) LOG_I(NGAP, x, ##args)
|
||||
# define NGAP_DEBUG(x, args...) LOG_D(NGAP, x, ##args)
|
||||
|
||||
#define NGAP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \
|
||||
do { \
|
||||
IE_TYPE **ptr; \
|
||||
ie = NULL; \
|
||||
for (ptr = container->protocolIEs.list.array; ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; ptr++) { \
|
||||
if ((*ptr)->id == IE_ID) { \
|
||||
ie = *ptr; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (ie == NULL) { \
|
||||
if (mandatory) { \
|
||||
AssertFatal(NGAP, "NGAP_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \
|
||||
} else { \
|
||||
NGAP_DEBUG("NGAP_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \
|
||||
} \
|
||||
} \
|
||||
} while (0); \
|
||||
if (mandatory && !ie) \
|
||||
return -1
|
||||
|
||||
/** \brief Function callback prototype.
|
||||
**/
|
||||
typedef int (*ngap_message_decoded_callback)(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu);
|
||||
|
||||
void tnl_to_bitstring(BIT_STRING_t *out, const transport_layer_addr_t in);
|
||||
void bitstring_to_tnl(transport_layer_addr_t *out, const BIT_STRING_t in);
|
||||
void encode_ngap_cause(NGAP_Cause_t *out, const ngap_cause_t *in);
|
||||
nr_guami_t decode_ngap_guami(const NGAP_GUAMI_t *in);
|
||||
ngap_cause_t decode_ngap_cause(const NGAP_Cause_t *in);
|
||||
@@ -91,7 +61,9 @@ void encode_ngap_nr_cgi(NGAP_NR_CGI_t *out, const plmn_id_t *plmn, const uint32_
|
||||
pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params);
|
||||
void *decode_pdusession_transfer(const asn_TYPE_descriptor_t *td, const OCTET_STRING_t buf);
|
||||
bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRING_t in);
|
||||
byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusession_setup_t *pdusession);
|
||||
|
||||
bool eq_ngap_plmn(const plmn_id_t *a, const plmn_id_t *b);
|
||||
|
||||
/** @}*/
|
||||
|
||||
#endif /* NGAP_COMMON_H_ */
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "ngap_messages_types.h"
|
||||
#include "ngap_gNB_mobility_management.h"
|
||||
#include "ngap_gNB_ue_context.h"
|
||||
#include "ngap_gNB_pdu_session_management.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "openair3/SECU/kdf.h"
|
||||
#include "queue.h"
|
||||
|
||||
@@ -47,7 +47,9 @@
|
||||
#include "ngap_gNB_nnsf.h"
|
||||
#include "ngap_gNB_management_procedures.h"
|
||||
#include "ngap_gNB_mobility_management.h"
|
||||
#include "ngap_gNB_pdu_session_management.h"
|
||||
#include "ngap_gNB_nas_procedures.h"
|
||||
#include "ngap_gNB_paging.h"
|
||||
#include "ngap_gNB_trace.h"
|
||||
#include "ngap_gNB_ue_context.h"
|
||||
#include "ngap_messages_types.h"
|
||||
@@ -1096,21 +1098,28 @@ static int ngap_gNB_handle_handover_cancel_ack(sctp_assoc_t assoc_id, uint32_t s
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle NGAP Paging message from AMF
|
||||
* @param assoc_id SCTP association ID
|
||||
* @param stream SCTP stream ID (must be 0 for paging per TS 38.412 Clause 7)
|
||||
* @param pdu NGAP PDU containing Paging message
|
||||
* @return 0 on success, -1 on failure */
|
||||
static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
ngap_gNB_amf_data_t *amf_desc_p = NULL;
|
||||
ngap_gNB_instance_t *ngap_gNB_instance = NULL;
|
||||
NGAP_Paging_t *container;
|
||||
NGAP_PagingIEs_t *ie;
|
||||
DevAssert(pdu != NULL);
|
||||
container = &pdu->choice.initiatingMessage->value.choice.Paging;
|
||||
// received Paging Message from AMF
|
||||
NGAP_DEBUG("[SCTP %u] Received Paging Message From AMF\n",assoc_id);
|
||||
|
||||
/* Paging procedure -> stream != 0 */
|
||||
if (stream == 0) {
|
||||
LOG_W(NGAP,"[SCTP %d] Received Paging procedure on stream (%d)\n",
|
||||
assoc_id, stream);
|
||||
/* Per 3GPP TS 38.412 Clause 7 (Transport layer):
|
||||
* Paging is classified as "non-UE-associated signalling" because:
|
||||
* - UE is in RRC_IDLE or RRC_INACTIVE state
|
||||
* - No active UE context exists in the RAN
|
||||
* - Paging targets UE by 5G-S-TMSI, not by RAN-UE-NGAP-ID
|
||||
* Non-UE-associated signalling MUST use stream 0 (or a reserved stream pair) */
|
||||
if (stream != 0) {
|
||||
LOG_W(NGAP,"[SCTP %d] Received Paging procedure on stream != 0 (expected stream 0 per TS 38.412)\n", assoc_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1129,67 +1138,20 @@ static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_N
|
||||
}
|
||||
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PAGING_IND);
|
||||
ngap_paging_ind_t * msg=&NGAP_PAGING_IND(message_p);
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
ngap_paging_ind_t *msg = &NGAP_PAGING_IND(message_p);
|
||||
|
||||
/* convert NGAP_PagingIEs_t to ngap_paging_ind_t */
|
||||
/* id-UEIdentityIndexValue : convert UE Identity Index value */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UEPagingIdentity, true);
|
||||
|
||||
struct NGAP_FiveG_S_TMSI *fiveG_S_TMSI = ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI;
|
||||
OCTET_STRING_TO_INT16(&fiveG_S_TMSI->aMFSetID, msg->ue_paging_identity.s_tmsi.amf_set_id);
|
||||
OCTET_STRING_TO_INT8(&fiveG_S_TMSI->aMFPointer, msg->ue_paging_identity.s_tmsi.amf_pointer);
|
||||
OCTET_STRING_TO_INT32(&fiveG_S_TMSI->fiveG_TMSI, msg->ue_paging_identity.s_tmsi.m_tmsi);
|
||||
|
||||
NGAP_DEBUG("[SCTP %u] Received Paging Identity amf_set_id %d, amf_pointer %d, m_tmsi %d\n",
|
||||
assoc_id,
|
||||
msg->ue_paging_identity.s_tmsi.amf_set_id,
|
||||
msg->ue_paging_identity.s_tmsi.amf_pointer,
|
||||
msg->ue_paging_identity.s_tmsi.m_tmsi);
|
||||
|
||||
msg->paging_drx = NGAP_PAGING_DRX_256;
|
||||
/* id-pagingDRX */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PagingDRX, false);
|
||||
|
||||
/* optional */
|
||||
if (ie) {
|
||||
msg->paging_drx = ie->value.choice.PagingDRX;
|
||||
} else {
|
||||
msg->paging_drx = NGAP_PAGING_DRX_256;
|
||||
/* Decode NGAP Paging message */
|
||||
if (!decode_ng_paging(msg, pdu)) {
|
||||
NGAP_ERROR("[SCTP %u] Failed to decode NGAP Paging message\n", assoc_id);
|
||||
free_ng_paging(msg);
|
||||
itti_free(TASK_NGAP, message_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* id-TAIList */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container,
|
||||
NGAP_ProtocolIE_ID_id_TAIListForPaging, true);
|
||||
/* send message to RRC */
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, ngap_gNB_instance->instance, message_p);
|
||||
|
||||
NGAP_INFO("[SCTP %u] Received Paging taiList For Paging: count %d\n", assoc_id, ie->value.choice.TAIListForPaging.list.count);
|
||||
|
||||
for (int i = 0; i < ie->value.choice.TAIListForPaging.list.count; i++) {
|
||||
NGAP_TAIListForPagingItem_t *item_p;
|
||||
item_p = (NGAP_TAIListForPagingItem_t *)ie->value.choice.TAIListForPaging.list.array[i];
|
||||
TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNIdentity), msg->plmn_identity[i].mcc, msg->plmn_identity[i].mnc, msg->plmn_identity[i].mnc_digit_length);
|
||||
OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), msg->tac[i]);
|
||||
msg->tai_size++;
|
||||
plmn_id_t *p = &msg->plmn_identity[i];
|
||||
LOG_D(NGAP,
|
||||
"[SCTP %u] PLMN in TAI list for Paging: MCC=%03d, MNC=%0*d, TAC=%d\n",
|
||||
assoc_id,
|
||||
p->mcc,
|
||||
p->mnc_digit_length,
|
||||
p->mnc,
|
||||
msg->tac[i]);
|
||||
}
|
||||
|
||||
//paging parameter values
|
||||
NGAP_DEBUG("[SCTP %u] Received Paging parameters: Paging Identity amf_set_id %d amf_pointer %d m_tmsi %d paging_drx %d paging_priority %d\n",assoc_id,
|
||||
msg->ue_paging_identity.s_tmsi.amf_set_id,
|
||||
msg->ue_paging_identity.s_tmsi.amf_pointer,
|
||||
msg->ue_paging_identity.s_tmsi.m_tmsi,
|
||||
msg->paging_drx, msg->paging_priority);
|
||||
/* send message to RRC */
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, ngap_gNB_instance->instance, message_p);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool decodePDUSessionResourceModify(pdusession_transfer_t *out, const OCTET_STRING_t in)
|
||||
@@ -1528,6 +1490,8 @@ static int ngap_gNB_handle_dl_ran_status_transfer(sctp_assoc_t assoc_id, uint32_
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef int (*ngap_message_decoded_callback)(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu);
|
||||
|
||||
/* Handlers matrix. Only gNB related procedure present here */
|
||||
const ngap_message_decoded_callback ngap_messages_callback[][3] = {
|
||||
{0, 0, 0}, /* AMFConfigurationUpdate */
|
||||
|
||||
@@ -191,20 +191,3 @@ void ngap_gNB_remove_amf_desc(ngap_gNB_instance_t * instance)
|
||||
}
|
||||
}
|
||||
|
||||
void tnl_to_bitstring(BIT_STRING_t *out, const transport_layer_addr_t in)
|
||||
{
|
||||
if (in.length) {
|
||||
out->buf = malloc_or_fail(in.length);
|
||||
memcpy(out->buf, in.buffer, in.length);
|
||||
out->size = in.length;
|
||||
out->bits_unused = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void bitstring_to_tnl(transport_layer_addr_t *out, const BIT_STRING_t in)
|
||||
{
|
||||
if (in.size) {
|
||||
memcpy(out->buffer, in.buf, in.size);
|
||||
out->length = in.size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,4 @@ uint16_t ngap_gNB_fetch_add_global_cnx_id(void);
|
||||
|
||||
void ngap_gNB_prepare_internal_data(void);
|
||||
|
||||
void tnl_to_bitstring(BIT_STRING_t *out, const transport_layer_addr_t in);
|
||||
|
||||
void bitstring_to_tnl(transport_layer_addr_t *out, const BIT_STRING_t in);
|
||||
|
||||
#endif /* NGAP_GNB_MANAGEMENT_PROCEDURES_H_ */
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "ngap_gNB_management_procedures.h"
|
||||
#include "ngap_gNB_encoder.h"
|
||||
#include "ngap_gNB_itti_messaging.h"
|
||||
#include "NR_HandoverPreparationInformation.h"
|
||||
#include "conversions.h"
|
||||
|
||||
/** @brief UE Mobility Management: encode Handover Required
|
||||
|
||||
@@ -558,64 +558,6 @@ int ngap_gNB_nas_non_delivery_ind(instance_t instance,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief PDU Session Resource Setup Response Transfer encoding (9.3.4.2 3GPP TS 38.413) */
|
||||
static byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusession_setup_t *pdusession)
|
||||
{
|
||||
NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0};
|
||||
byte_array_t out = {0};
|
||||
|
||||
// DL QoS Flow per TNL Information (Mandatory)
|
||||
NGAP_QosFlowPerTNLInformation_t *dLQosFlowPerTNLInformation = &pdusessionTransfer.dLQosFlowPerTNLInformation;
|
||||
|
||||
// UP Transport Layer Information (Mandatory)
|
||||
dLQosFlowPerTNLInformation->uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
|
||||
asn1cCalloc(dLQosFlowPerTNLInformation->uPTransportLayerInformation.choice.gTPTunnel, gtp);
|
||||
GTP_TEID_TO_ASN1(pdusession->n3_outgoing.teid, >p->gTP_TEID);
|
||||
tnl_to_bitstring(>p->transportLayerAddress, pdusession->n3_outgoing.addr);
|
||||
char ip_str[INET_ADDRSTRLEN] = {0};
|
||||
inet_ntop(AF_INET, gtp->transportLayerAddress.buf, ip_str, sizeof(ip_str));
|
||||
NGAP_DEBUG("Encoded PDU Session Transfer (%d): TEID=0x%08x, Addr=%s\n",
|
||||
pdusession->pdusession_id,
|
||||
pdusession->n3_outgoing.teid,
|
||||
ip_str);
|
||||
|
||||
// Associated QoS Flow List (Mandatory)
|
||||
for (int j = 0; j < pdusession->nb_of_qos_flow; j++) {
|
||||
asn1cSequenceAdd(dLQosFlowPerTNLInformation->associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, qos_item);
|
||||
// QoS Flow Identifier (Mandatory)
|
||||
qos_item->qosFlowIdentifier = pdusession->associated_qos_flows[j].qfi;
|
||||
}
|
||||
|
||||
// Encode
|
||||
asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL,
|
||||
ATS_ALIGNED_CANONICAL_PER,
|
||||
&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer,
|
||||
&pdusessionTransfer);
|
||||
AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer);
|
||||
out.buf = res.buffer;
|
||||
out.len = res.result.encoded;
|
||||
return out;
|
||||
}
|
||||
|
||||
/** @brief PDU Session Resource Release Response Transfer encoding (9.3.4.21 3GPP TS 38.413)
|
||||
* The transfer structure contains only an optional Secondary RAT Usage Information IE.
|
||||
* Since we don't use secondary RAT (MR-DC), we encode an empty structure. */
|
||||
static byte_array_t encode_ngap_pdusession_release_response_transfer(void)
|
||||
{
|
||||
NGAP_PDUSessionResourceReleaseResponseTransfer_t pdusessionTransfer = {0};
|
||||
|
||||
// Encode
|
||||
asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL,
|
||||
ATS_ALIGNED_CANONICAL_PER,
|
||||
&asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer,
|
||||
&pdusessionTransfer);
|
||||
AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, &pdusessionTransfer);
|
||||
byte_array_t out = {.buf = res.buffer, .len = res.result.encoded};
|
||||
return out;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p)
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -909,354 +851,3 @@ int ngap_gNB_ue_capabilities(instance_t instance, ngap_ue_cap_info_ind_t *ue_cap
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_resp_t *pdusession_setup_resp_p)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
|
||||
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
|
||||
NGAP_NGAP_PDU_t pdu = {0};
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t length;
|
||||
|
||||
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||
DevAssert(pdusession_setup_resp_p != NULL);
|
||||
DevAssert(ngap_gNB_instance_p != NULL);
|
||||
|
||||
if ((ue_context_p = ngap_get_ue_context(pdusession_setup_resp_p->gNB_ue_ngap_id)) == NULL) {
|
||||
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_setup_resp_p->gNB_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Uplink NAS transport can occur either during an ngap connected state
|
||||
* or during initial attach (for example: NAS authentication).
|
||||
*/
|
||||
if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) {
|
||||
NGAP_WARN(
|
||||
"You are attempting to send NAS data over non-connected "
|
||||
"gNB ue ngap id: %08x, current state: %d\n",
|
||||
pdusession_setup_resp_p->gNB_ue_ngap_id,
|
||||
ue_context_p->ue_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Prepare the NGAP message to encode */
|
||||
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu.choice.successfulOutcome, successfulOutcome);
|
||||
successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceSetup;
|
||||
successfulOutcome->criticality = NGAP_Criticality_reject;
|
||||
successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceSetupResponse;
|
||||
NGAP_PDUSessionResourceSetupResponse_t *out = &successfulOutcome->value.choice.PDUSessionResourceSetupResponse;
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id);
|
||||
}
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
ie->value.choice.RAN_UE_NGAP_ID = pdusession_setup_resp_p->gNB_ue_ngap_id;
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (pdusession_setup_resp_p->nb_of_pdusessions > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie3);
|
||||
ie3->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSURes;
|
||||
ie3->criticality = NGAP_Criticality_ignore;
|
||||
ie3->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceSetupListSURes;
|
||||
|
||||
for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions; i++) {
|
||||
pdusession_setup_t *pdusession = pdusession_setup_resp_p->pdusessions + i;
|
||||
asn1cSequenceAdd(ie3->value.choice.PDUSessionResourceSetupListSURes.list, NGAP_PDUSessionResourceSetupItemSURes_t, item);
|
||||
/* pDUSessionID */
|
||||
item->pDUSessionID = pdusession->pdusession_id;
|
||||
|
||||
// PDU Session Resource Setup Response Transfer (Mandatory)
|
||||
byte_array_t ba = encode_ngap_pdusession_setup_response_transfer(pdusession);
|
||||
item->pDUSessionResourceSetupResponseTransfer.buf = ba.buf;
|
||||
item->pDUSessionResourceSetupResponseTransfer.size = ba.len;
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (pdusession_setup_resp_p->nb_of_pdusessions_failed > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListSURes;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes;
|
||||
|
||||
for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) {
|
||||
pdusession_failed_t *pdusession_failed = pdusession_setup_resp_p->pdusessions_failed + i;
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToSetupListSURes.list, NGAP_PDUSessionResourceFailedToSetupItemSURes_t, item);
|
||||
NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t pdusessionUnTransfer_p = {0};
|
||||
|
||||
/* pDUSessionID */
|
||||
item->pDUSessionID = pdusession_failed->pdusession_id;
|
||||
|
||||
/* cause */
|
||||
encode_ngap_cause(&pdusessionUnTransfer_p.cause, &pdusession_failed->cause);
|
||||
NGAP_INFO("pdusession setup response: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
|
||||
asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, &pdusessionUnTransfer_p);
|
||||
item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer;
|
||||
item->pDUSessionResourceSetupUnsuccessfulTransfer.size = res.result.encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, &pdusessionUnTransfer_p);
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_CriticalityDiagnostics;
|
||||
// ie->value.choice.CriticalityDiagnostics = ;
|
||||
}
|
||||
|
||||
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||
NGAP_ERROR("Failed to encode uplink transport\n");
|
||||
/* Encode procedure has failed... */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* UE associated signalling -> use the allocated stream */
|
||||
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_resp_t *pdusession_modify_resp_p)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
|
||||
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t length;
|
||||
|
||||
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||
DevAssert(pdusession_modify_resp_p != NULL);
|
||||
DevAssert(ngap_gNB_instance_p != NULL);
|
||||
|
||||
if ((ue_context_p = ngap_get_ue_context(pdusession_modify_resp_p->gNB_ue_ngap_id)) == NULL) {
|
||||
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_modify_resp_p->gNB_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Uplink NAS transport can occur either during an ngap connected state
|
||||
* or during initial attach (for example: NAS authentication).
|
||||
*/
|
||||
if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) {
|
||||
NGAP_WARN(
|
||||
"You are attempting to send NAS data over non-connected "
|
||||
"gNB ue ngap id: %08x, current state: %d\n",
|
||||
pdusession_modify_resp_p->gNB_ue_ngap_id,
|
||||
ue_context_p->ue_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Prepare the NGAP message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu.choice.successfulOutcome, head);
|
||||
head->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceModify;
|
||||
head->criticality = NGAP_Criticality_reject;
|
||||
head->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceModifyResponse;
|
||||
NGAP_PDUSessionResourceModifyResponse_t *out = &head->value.choice.PDUSessionResourceModifyResponse;
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t));
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, pdusession_modify_resp_p->amf_ue_ngap_id);
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
}
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
ie->value.choice.RAN_UE_NGAP_ID = pdusession_modify_resp_p->gNB_ue_ngap_id;
|
||||
}
|
||||
|
||||
/* PDUSessionResourceModifyListModRes optional */
|
||||
if (pdusession_modify_resp_p->nb_of_pdusessions > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModRes;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceModifyListModRes;
|
||||
|
||||
for (int i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions; i++) {
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceModifyListModRes.list, NGAP_PDUSessionResourceModifyItemModRes_t, item);
|
||||
item->pDUSessionID = pdusession_modify_resp_p->pdusessions[i].pdusession_id;
|
||||
|
||||
NGAP_PDUSessionResourceModifyResponseTransfer_t transfer = {0};
|
||||
asn1cCalloc(transfer.qosFlowAddOrModifyResponseList, tmp);
|
||||
|
||||
for (int qos_flow_index = 0; qos_flow_index < pdusession_modify_resp_p->pdusessions[i].nb_of_qos_flow; qos_flow_index++) {
|
||||
asn1cSequenceAdd(tmp->list, NGAP_QosFlowAddOrModifyResponseItem_t, qos);
|
||||
qos->qosFlowIdentifier = pdusession_modify_resp_p->pdusessions[i].qos[qos_flow_index].qfi;
|
||||
}
|
||||
asn_encode_to_new_buffer_result_t res = {0};
|
||||
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, &transfer);
|
||||
item->pDUSessionResourceModifyResponseTransfer.buf = res.buffer;
|
||||
item->pDUSessionResourceModifyResponseTransfer.size = res.result.encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, &transfer);
|
||||
|
||||
NGAP_DEBUG("pdusession_modify_resp: modified pdusession ID %ld\n", item->pDUSessionID);
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (pdusession_modify_resp_p->nb_of_pdusessions_failed > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToModifyListModRes;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceFailedToModifyListModRes;
|
||||
|
||||
for (int i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions_failed; i++) {
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToModifyListModRes.list, NGAP_PDUSessionResourceFailedToModifyItemModRes_t, item);
|
||||
item->pDUSessionID = pdusession_modify_resp_p->pdusessions_failed[i].pdusession_id;
|
||||
|
||||
NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t pdusessionTransfer = {0};
|
||||
|
||||
// NGAP cause
|
||||
encode_ngap_cause(&pdusessionTransfer.cause, &pdusession_modify_resp_p->pdusessions_failed[i].cause);
|
||||
|
||||
asn_encode_to_new_buffer_result_t res = {0};
|
||||
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, &pdusessionTransfer);
|
||||
item->pDUSessionResourceModifyUnsuccessfulTransfer.buf = res.buffer;
|
||||
item->pDUSessionResourceModifyUnsuccessfulTransfer.size = res.result.encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, &pdusessionTransfer);
|
||||
|
||||
NGAP_INFO("pdusession_modify_resp: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_CriticalityDiagnostics;
|
||||
// ie->value.choice.CriticalityDiagnostics = ;
|
||||
}
|
||||
|
||||
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||
NGAP_ERROR("Failed to encode uplink transport\n");
|
||||
/* Encode procedure has failed... */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* UE associated signalling -> use the allocated stream */
|
||||
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream);
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_release_resp_t *pdusession_release_resp_p)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
|
||||
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t length;
|
||||
int i;
|
||||
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||
DevAssert(pdusession_release_resp_p != NULL);
|
||||
DevAssert(ngap_gNB_instance_p != NULL);
|
||||
|
||||
if ((ue_context_p = ngap_get_ue_context(pdusession_release_resp_p->gNB_ue_ngap_id)) == NULL) {
|
||||
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_release_resp_p->gNB_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Prepare the NGAP message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu.choice.successfulOutcome, head);
|
||||
head->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceRelease;
|
||||
head->criticality = NGAP_Criticality_reject;
|
||||
head->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceReleaseResponse;
|
||||
NGAP_PDUSessionResourceReleaseResponse_t *out = &head->value.choice.PDUSessionResourceReleaseResponse;
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id);
|
||||
}
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id;
|
||||
}
|
||||
|
||||
/* PDU Session Resource Released List (mandatory) */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes;
|
||||
|
||||
for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) {
|
||||
NGAP_PDUSessionResourceReleasedListRelRes_t *list = &ie->value.choice.PDUSessionResourceReleasedListRelRes;
|
||||
asn1cSequenceAdd(list->list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item);
|
||||
pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i];
|
||||
/* PDU Session ID (mandatory) */
|
||||
item->pDUSessionID = r->pdusession_id;
|
||||
/* PDU Session Resource Release Response Transfer (mandatory) */
|
||||
// Empty transfer is valid since Secondary RAT Usage Information is optional and not used
|
||||
byte_array_t transfer = encode_ngap_pdusession_release_response_transfer();
|
||||
OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)transfer.buf, transfer.len);
|
||||
free_byte_array(transfer);
|
||||
NGAP_DEBUG("PDU Session Resource Release Response: pdusession ID %ld\n", item->pDUSessionID);
|
||||
}
|
||||
}
|
||||
|
||||
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||
NGAP_ERROR("Failed to encode release response\n");
|
||||
/* Encode procedure has failed... */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* UE associated signalling -> use the allocated stream */
|
||||
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream);
|
||||
NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d \n",
|
||||
pdusession_release_resp_p->gNB_ue_ngap_id,
|
||||
(uint64_t)ue_context_p->amf_ue_ngap_id,
|
||||
pdusession_release_resp_p->nb_of_pdusessions_released);
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,13 +54,4 @@ int ngap_gNB_initial_ctxt_fail(instance_t instance, ngap_initial_context_setup_f
|
||||
int ngap_gNB_ue_capabilities(instance_t instance,
|
||||
ngap_ue_cap_info_ind_t *ue_cap_info_ind_p);
|
||||
|
||||
int ngap_gNB_pdusession_setup_resp(instance_t instance,
|
||||
ngap_pdusession_setup_resp_t *pdusession_setup_resp_p);
|
||||
|
||||
int ngap_gNB_pdusession_modify_resp(instance_t instance,
|
||||
ngap_pdusession_modify_resp_t *pdusession_modify_resp_p);
|
||||
|
||||
int ngap_gNB_pdusession_release_resp(instance_t instance,
|
||||
ngap_pdusession_release_resp_t *pdusession_release_resp_p);
|
||||
|
||||
#endif /* NGAP_GNB_NAS_PROCEDURES_H_ */
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* 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 Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "assertions.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "conversions.h"
|
||||
#include "ngap_common.h"
|
||||
#include "ngap_gNB_paging.h"
|
||||
#include "ngap_msg_includes.h"
|
||||
#include "oai_asn1.h"
|
||||
|
||||
/* Paging Attempt range (TS 38.413 §9.3.1.72) */
|
||||
#define NGAP_PAGING_ATTEMPT_MIN 1
|
||||
#define NGAP_PAGING_ATTEMPT_MAX 16
|
||||
|
||||
/** @brief Return text label at index in text_info array */
|
||||
static const char *text_info_at(int index, const text_info_t *info_array, size_t array_size)
|
||||
{
|
||||
DevAssert(index >= 0 && index < array_size);
|
||||
return info_array[index].text;
|
||||
}
|
||||
|
||||
/** @brief Encode NGAP Paging message (9.2.4.1 of 3GPP TS 38.413)
|
||||
* @param msg Pointer to paging indication structure to encode
|
||||
* @return Pointer to allocated NGAP_NGAP_PDU_t */
|
||||
NGAP_NGAP_PDU_t *encode_ng_paging(const ngap_paging_ind_t *msg)
|
||||
{
|
||||
DevAssert(msg != NULL);
|
||||
|
||||
NGAP_NGAP_PDU_t *pdu = calloc_or_fail(1, sizeof(NGAP_NGAP_PDU_t));
|
||||
|
||||
pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu->choice.initiatingMessage, head);
|
||||
head->procedureCode = NGAP_ProcedureCode_id_Paging;
|
||||
head->criticality = NGAP_Criticality_ignore;
|
||||
head->value.present = NGAP_InitiatingMessage__value_PR_Paging;
|
||||
NGAP_Paging_t *container = &head->value.choice.Paging;
|
||||
|
||||
// UE Paging Identity (M)
|
||||
asn1cSequenceAdd(container->protocolIEs.list, NGAP_PagingIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_UEPagingIdentity;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_PagingIEs__value_PR_UEPagingIdentity;
|
||||
ie->value.choice.UEPagingIdentity.present = NGAP_UEPagingIdentity_PR_fiveG_S_TMSI;
|
||||
asn1cCalloc(ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI, fiveg_s_tmsi);
|
||||
const fiveg_s_tmsi_t *s_tmsi = &msg->ue_paging_identity.s_tmsi;
|
||||
AMF_SETID_TO_BIT_STRING(s_tmsi->amf_set_id, &fiveg_s_tmsi->aMFSetID);
|
||||
AMF_POINTER_TO_BIT_STRING(s_tmsi->amf_pointer, &fiveg_s_tmsi->aMFPointer);
|
||||
M_TMSI_TO_OCTET_STRING(s_tmsi->m_tmsi, &fiveg_s_tmsi->fiveG_TMSI);
|
||||
|
||||
// TAI List for Paging (M)
|
||||
asn1cSequenceAdd(container->protocolIEs.list, NGAP_PagingIEs_t, ie1);
|
||||
ie1->id = NGAP_ProtocolIE_ID_id_TAIListForPaging;
|
||||
ie1->criticality = NGAP_Criticality_reject;
|
||||
ie1->value.present = NGAP_PagingIEs__value_PR_TAIListForPaging;
|
||||
|
||||
for (int i = 0; i < msg->n_tai; i++) {
|
||||
asn1cSequenceAdd(ie1->value.choice.TAIListForPaging.list, NGAP_TAIListForPagingItem_t, item);
|
||||
NGAP_TAI_t *tai = &item->tAI;
|
||||
const plmn_id_t *plmn = &msg->tai_list[i].plmn;
|
||||
MCC_MNC_TO_TBCD(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &tai->pLMNIdentity);
|
||||
INT24_TO_OCTET_STRING(msg->tai_list[i].tac, &tai->tAC);
|
||||
}
|
||||
|
||||
// Paging DRX (O)
|
||||
if (msg->paging_drx != NULL) {
|
||||
asn1cSequenceAdd(container->protocolIEs.list, NGAP_PagingIEs_t, ie2);
|
||||
ie2->id = NGAP_ProtocolIE_ID_id_PagingDRX;
|
||||
ie2->criticality = NGAP_Criticality_ignore;
|
||||
ie2->value.present = NGAP_PagingIEs__value_PR_PagingDRX;
|
||||
ie2->value.choice.PagingDRX = *msg->paging_drx;
|
||||
}
|
||||
|
||||
// Paging Priority (O)
|
||||
if (msg->paging_priority != NULL) {
|
||||
asn1cSequenceAdd(container->protocolIEs.list, NGAP_PagingIEs_t, ie3);
|
||||
ie3->id = NGAP_ProtocolIE_ID_id_PagingPriority;
|
||||
ie3->criticality = NGAP_Criticality_ignore;
|
||||
ie3->value.present = NGAP_PagingIEs__value_PR_PagingPriority;
|
||||
ie3->value.choice.PagingPriority = *msg->paging_priority;
|
||||
}
|
||||
|
||||
// UERadioCapabilityForPaging (O)
|
||||
if (msg->ue_radio_capability != NULL && msg->ue_radio_capability->buf != NULL) {
|
||||
const byte_array_t *ue_radio_cap_ba = msg->ue_radio_capability;
|
||||
asn1cSequenceAdd(container->protocolIEs.list, NGAP_PagingIEs_t, ie4);
|
||||
ie4->id = NGAP_ProtocolIE_ID_id_UERadioCapabilityForPaging;
|
||||
ie4->criticality = NGAP_Criticality_ignore;
|
||||
ie4->value.present = NGAP_PagingIEs__value_PR_UERadioCapabilityForPaging;
|
||||
NGAP_UERadioCapabilityForPaging_t *ue_radio_cap = &ie4->value.choice.UERadioCapabilityForPaging;
|
||||
// UERadioCapabilityForPaging is a SEQUENCE with optional OCTET_STRING fields (Encode as NR)
|
||||
asn1cCalloc(ue_radio_cap->uERadioCapabilityForPagingOfNR, nr_field);
|
||||
OCTET_STRING_fromBuf(nr_field, (const char *)ue_radio_cap_ba->buf, ue_radio_cap_ba->len);
|
||||
}
|
||||
|
||||
// PagingOrigin (O)
|
||||
if (msg->origin != NULL) {
|
||||
asn1cSequenceAdd(container->protocolIEs.list, NGAP_PagingIEs_t, ie5);
|
||||
ie5->id = NGAP_ProtocolIE_ID_id_PagingOrigin;
|
||||
ie5->criticality = NGAP_Criticality_ignore;
|
||||
ie5->value.present = NGAP_PagingIEs__value_PR_PagingOrigin;
|
||||
ie5->value.choice.PagingOrigin = *msg->origin;
|
||||
}
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/** @brief Free memory allocated for NGAP paging indication
|
||||
* @param msg Pointer to paging indication structure to free */
|
||||
void free_ng_paging(ngap_paging_ind_t *msg)
|
||||
{
|
||||
DevAssert(msg != NULL);
|
||||
free(msg->paging_drx);
|
||||
free(msg->paging_priority);
|
||||
if (msg->ue_radio_capability != NULL) {
|
||||
free_byte_array(*msg->ue_radio_capability);
|
||||
free(msg->ue_radio_capability);
|
||||
}
|
||||
free(msg->origin);
|
||||
free(msg->paging_attempt_info);
|
||||
}
|
||||
|
||||
/** @brief Decode NGAP Paging message (9.2.4.1 of 3GPP TS 38.413)
|
||||
* @param out Pointer to output structure to fill
|
||||
* @param pdu Pointer to NGAP PDU containing the Paging message
|
||||
* @return true on success, false on failure */
|
||||
bool decode_ng_paging(ngap_paging_ind_t *out, const NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
DevAssert(out != NULL);
|
||||
|
||||
if (pdu->present != NGAP_NGAP_PDU_PR_initiatingMessage) {
|
||||
NGAP_ERROR("Invalid PDU present value for Paging message\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const NGAP_Paging_t *container = &pdu->choice.initiatingMessage->value.choice.Paging;
|
||||
NGAP_PagingIEs_t *ie;
|
||||
fiveg_s_tmsi_t *s_tmsi = &out->ue_paging_identity.s_tmsi;
|
||||
|
||||
// Reset output structure
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
// UE Paging Identity (M)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UEPagingIdentity, true);
|
||||
|
||||
if (ie->value.choice.UEPagingIdentity.present == NGAP_UEPagingIdentity_PR_fiveG_S_TMSI) {
|
||||
const struct NGAP_FiveG_S_TMSI *fiveG_S_TMSI = ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI;
|
||||
s_tmsi->amf_set_id = BIT_STRING_to_uint16(&fiveG_S_TMSI->aMFSetID);
|
||||
s_tmsi->amf_pointer = BIT_STRING_to_uint8(&fiveG_S_TMSI->aMFPointer);
|
||||
OCTET_STRING_TO_INT32(&fiveG_S_TMSI->fiveG_TMSI, s_tmsi->m_tmsi);
|
||||
} else {
|
||||
NGAP_ERROR("Unsupported UE Paging Identity type\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TAI List for Paging (M)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_TAIListForPaging, true);
|
||||
|
||||
// Validate TAI list count
|
||||
int tai_count = ie->value.choice.TAIListForPaging.list.count;
|
||||
if (tai_count > NGAP_MAX_NO_TAI_PAGING) {
|
||||
NGAP_ERROR("Invalid TAI list count: %d (must be <= %d)\n", tai_count, NGAP_MAX_NO_TAI_PAGING);
|
||||
return false;
|
||||
}
|
||||
|
||||
out->n_tai = 0;
|
||||
for (int i = 0; i < tai_count; i++) {
|
||||
const NGAP_TAIListForPagingItem_t *item_p = ie->value.choice.TAIListForPaging.list.array[i];
|
||||
DevAssert(item_p != NULL);
|
||||
const NGAP_TAI_t *tai = &item_p->tAI;
|
||||
nr_tai_t *tai_out = &out->tai_list[i];
|
||||
TBCD_TO_MCC_MNC(&tai->pLMNIdentity, tai_out->plmn.mcc, tai_out->plmn.mnc, tai_out->plmn.mnc_digit_length);
|
||||
OCTET_STRING_TO_INT24(&tai->tAC, tai_out->tac);
|
||||
NGAP_DEBUG("TAI[%d] for paging: MCC=%03d, MNC=%0*d, TAC=%d\n",
|
||||
i,
|
||||
tai_out->plmn.mcc,
|
||||
tai_out->plmn.mnc_digit_length,
|
||||
tai_out->plmn.mnc,
|
||||
tai_out->tac);
|
||||
out->n_tai++;
|
||||
}
|
||||
|
||||
// Paging DRX (O)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PagingDRX, false);
|
||||
if (ie != NULL) {
|
||||
out->paging_drx = malloc_or_fail(sizeof(ngap_paging_drx_t));
|
||||
*out->paging_drx = ie->value.choice.PagingDRX;
|
||||
const char *s = text_info_at(*out->paging_drx, paging_drx_text, sizeofArray(paging_drx_text));
|
||||
NGAP_DEBUG("Decoded Paging DRX: %s", s);
|
||||
}
|
||||
|
||||
// Paging Priority (O)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PagingPriority, false);
|
||||
if (ie != NULL) {
|
||||
out->paging_priority = malloc_or_fail(sizeof(ngap_paging_priority_t));
|
||||
*out->paging_priority = ie->value.choice.PagingPriority;
|
||||
const char *s = text_info_at(*out->paging_priority, paging_prio_text, sizeofArray(paging_prio_text));
|
||||
NGAP_DEBUG("Decoded Paging Priority: %s", s);
|
||||
}
|
||||
|
||||
// UERadioCapabilityForPaging (O)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UERadioCapabilityForPaging, false);
|
||||
if (ie != NULL) {
|
||||
const NGAP_UERadioCapabilityForPaging_t *ue_radio_cap = &ie->value.choice.UERadioCapabilityForPaging;
|
||||
const OCTET_STRING_t *nr_field = ue_radio_cap->uERadioCapabilityForPagingOfNR;
|
||||
const OCTET_STRING_t *eutra_field = ue_radio_cap->uERadioCapabilityForPagingOfEUTRA;
|
||||
if (nr_field != NULL) {
|
||||
out->ue_radio_capability = malloc_or_fail(sizeof(byte_array_t));
|
||||
*out->ue_radio_capability = create_byte_array(nr_field->size, nr_field->buf);
|
||||
NGAP_DEBUG("Decoded UERadioCapabilityForPaging (NR): %zu bytes\n", nr_field->size);
|
||||
} else if (eutra_field != NULL) {
|
||||
out->ue_radio_capability = malloc_or_fail(sizeof(byte_array_t));
|
||||
*out->ue_radio_capability = create_byte_array(eutra_field->size, eutra_field->buf);
|
||||
NGAP_DEBUG("Decoded UERadioCapabilityForPaging (EUTRA): %zu bytes\n", eutra_field->size);
|
||||
} else {
|
||||
NGAP_WARN("UERadioCapabilityForPaging present but both NR and EUTRA fields are NULL\n");
|
||||
}
|
||||
}
|
||||
|
||||
// PagingOrigin (O)
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PagingOrigin, false);
|
||||
if (ie != NULL) {
|
||||
// PagingOrigin shall be transferred to UE according to TS 38.331 and TS 36.331
|
||||
out->origin = calloc_or_fail(1, sizeof(*out->origin));
|
||||
*out->origin = ie->value.choice.PagingOrigin;
|
||||
}
|
||||
|
||||
// AssistanceDataForPaging (O) - contains PagingAttemptInformation
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AssistanceDataForPaging, false);
|
||||
if (ie != NULL) {
|
||||
const NGAP_AssistanceDataForPaging_t *assistance_data = &ie->value.choice.AssistanceDataForPaging;
|
||||
|
||||
// Extract PagingAttemptInformation if present (TS 38.413 §9.3.1.72)
|
||||
if (assistance_data->pagingAttemptInformation != NULL) {
|
||||
const NGAP_PagingAttemptInformation_t *paging_attempt_info = assistance_data->pagingAttemptInformation;
|
||||
out->paging_attempt_info = calloc_or_fail(1, sizeof(ngap_paging_attempt_info_t));
|
||||
|
||||
// Paging Attempt Count (mandatory)
|
||||
uint8_t attempt_count = paging_attempt_info->pagingAttemptCount;
|
||||
DevAssert(attempt_count >= NGAP_PAGING_ATTEMPT_MIN && attempt_count <= NGAP_PAGING_ATTEMPT_MAX);
|
||||
out->paging_attempt_info->paging_attempt_count = attempt_count;
|
||||
NGAP_DEBUG("Decoded Paging Attempt Count: %u\n", out->paging_attempt_info->paging_attempt_count);
|
||||
|
||||
// Intended Number of Paging Attempts (mandatory)
|
||||
uint8_t intended_attempts = paging_attempt_info->intendedNumberOfPagingAttempts;
|
||||
DevAssert(intended_attempts >= NGAP_PAGING_ATTEMPT_MIN && intended_attempts <= NGAP_PAGING_ATTEMPT_MAX);
|
||||
out->paging_attempt_info->intended_paging_attempts = intended_attempts;
|
||||
NGAP_DEBUG("Decoded Intended Number of Paging Attempts: %u\n", out->paging_attempt_info->intended_paging_attempts);
|
||||
}
|
||||
}
|
||||
|
||||
NGAP_DEBUG("Decoded Paging: m_tmsi=0x%08x, TAI=%d", s_tmsi->m_tmsi, out->n_tai);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief Check equality of two NGAP paging indication structures
|
||||
* @param a First structure
|
||||
* @param b Second structure
|
||||
* @return true if equal, false otherwise */
|
||||
bool eq_ng_paging(const ngap_paging_ind_t *a, const ngap_paging_ind_t *b)
|
||||
{
|
||||
if (a == NULL || b == NULL) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
// UE Paging Identity
|
||||
const fiveg_s_tmsi_t *a_tmsi = &a->ue_paging_identity.s_tmsi;
|
||||
const fiveg_s_tmsi_t *b_tmsi = &b->ue_paging_identity.s_tmsi;
|
||||
_EQ_CHECK_INT(a_tmsi->amf_set_id, b_tmsi->amf_set_id);
|
||||
_EQ_CHECK_INT(a_tmsi->amf_pointer, b_tmsi->amf_pointer);
|
||||
_EQ_CHECK_UINT32(a_tmsi->m_tmsi, b_tmsi->m_tmsi);
|
||||
|
||||
// TAI List
|
||||
_EQ_CHECK_INT(a->n_tai, b->n_tai);
|
||||
for (int i = 0; i < a->n_tai; i++) {
|
||||
if (!eq_ngap_plmn(&a->tai_list[i].plmn, &b->tai_list[i].plmn)) {
|
||||
return false;
|
||||
}
|
||||
_EQ_CHECK_INT(a->tai_list[i].tac, b->tai_list[i].tac);
|
||||
}
|
||||
|
||||
// Paging DRX (optional)
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, paging_drx, _EQ_CHECK_INT);
|
||||
|
||||
// Paging Priority (optional)
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, paging_priority, _EQ_CHECK_INT);
|
||||
|
||||
// UERadioCapabilityForPaging (optional)
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, ue_radio_capability);
|
||||
if (a->ue_radio_capability != NULL && b->ue_radio_capability != NULL) {
|
||||
if (!eq_byte_array(a->ue_radio_capability, b->ue_radio_capability)) {
|
||||
NGAP_ERROR("Equality condition 'eq_byte_array' failed: byte array contents differ\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// PagingOrigin (optional)
|
||||
_EQ_CHECK_OPTIONAL_IE(a, b, origin, _EQ_CHECK_INT);
|
||||
|
||||
// Assistance Data for Paging (optional)
|
||||
_EQ_CHECK_OPTIONAL_PTR(a, b, paging_attempt_info);
|
||||
if (a->paging_attempt_info != NULL && b->paging_attempt_info != NULL) {
|
||||
_EQ_CHECK_INT(a->paging_attempt_info->paging_attempt_count, b->paging_attempt_info->paging_attempt_count);
|
||||
_EQ_CHECK_INT(a->paging_attempt_info->intended_paging_attempts, b->paging_attempt_info->intended_paging_attempts);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef NGAP_GNB_PAGING_H_
|
||||
#define NGAP_GNB_PAGING_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "ngap_messages_types.h"
|
||||
|
||||
/** @brief Encode NGAP Paging message (9.2.4.1 of 3GPP TS 38.413)
|
||||
* @param msg Pointer to paging indication structure to encode
|
||||
* @return Pointer to allocated NGAP_NGAP_PDU_t, or NULL on failure */
|
||||
NGAP_NGAP_PDU_t *encode_ng_paging(const ngap_paging_ind_t *msg);
|
||||
|
||||
/** @brief Decode NGAP Paging message (9.2.4.1 of 3GPP TS 38.413)
|
||||
* @param out Pointer to output structure to fill
|
||||
* @param pdu Pointer to NGAP PDU containing the Paging message
|
||||
* @return true on success, false on failure */
|
||||
bool decode_ng_paging(ngap_paging_ind_t *out, const NGAP_NGAP_PDU_t *pdu);
|
||||
|
||||
/** @brief Free memory allocated for NGAP paging indication
|
||||
* @param msg Pointer to paging indication structure to free */
|
||||
void free_ng_paging(ngap_paging_ind_t *msg);
|
||||
|
||||
/** @brief Check equality of two NGAP paging indication structures
|
||||
* @param a First structure
|
||||
* @param b Second structure
|
||||
* @return true if equal, false otherwise */
|
||||
bool eq_ng_paging(const ngap_paging_ind_t *a, const ngap_paging_ind_t *b);
|
||||
|
||||
#endif /* NGAP_GNB_PAGING_H_ */
|
||||
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* 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 "ngap_gNB_pdu_session_management.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "INTEGER.h"
|
||||
#include "ngap_msg_includes.h"
|
||||
#include "OCTET_STRING.h"
|
||||
#include "asn_application.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "ngap_common.h"
|
||||
#include "ngap_gNB_encoder.h"
|
||||
#include "ngap_gNB_itti_messaging.h"
|
||||
#include "ngap_gNB_ue_context.h"
|
||||
#include "ngap_gNB_management_procedures.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "ds/byte_array.h"
|
||||
|
||||
int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_resp_t *pdusession_setup_resp_p)
|
||||
{
|
||||
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
|
||||
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
|
||||
NGAP_NGAP_PDU_t pdu = {0};
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t length;
|
||||
|
||||
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||
DevAssert(pdusession_setup_resp_p != NULL);
|
||||
DevAssert(ngap_gNB_instance_p != NULL);
|
||||
|
||||
if ((ue_context_p = ngap_get_ue_context(pdusession_setup_resp_p->gNB_ue_ngap_id)) == NULL) {
|
||||
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_setup_resp_p->gNB_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Uplink NAS transport can occur either during an ngap connected state
|
||||
* or during initial attach (for example: NAS authentication).
|
||||
*/
|
||||
if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) {
|
||||
NGAP_WARN(
|
||||
"You are attempting to send NAS data over non-connected "
|
||||
"gNB ue ngap id: %08x, current state: %d\n",
|
||||
pdusession_setup_resp_p->gNB_ue_ngap_id,
|
||||
ue_context_p->ue_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Prepare the NGAP message to encode */
|
||||
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu.choice.successfulOutcome, successfulOutcome);
|
||||
successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceSetup;
|
||||
successfulOutcome->criticality = NGAP_Criticality_reject;
|
||||
successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceSetupResponse;
|
||||
NGAP_PDUSessionResourceSetupResponse_t *out = &successfulOutcome->value.choice.PDUSessionResourceSetupResponse;
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id);
|
||||
}
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
ie->value.choice.RAN_UE_NGAP_ID = pdusession_setup_resp_p->gNB_ue_ngap_id;
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (pdusession_setup_resp_p->nb_of_pdusessions > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie3);
|
||||
ie3->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSURes;
|
||||
ie3->criticality = NGAP_Criticality_ignore;
|
||||
ie3->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceSetupListSURes;
|
||||
|
||||
for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions; i++) {
|
||||
pdusession_setup_t *pdusession = pdusession_setup_resp_p->pdusessions + i;
|
||||
asn1cSequenceAdd(ie3->value.choice.PDUSessionResourceSetupListSURes.list, NGAP_PDUSessionResourceSetupItemSURes_t, item);
|
||||
/* pDUSessionID */
|
||||
item->pDUSessionID = pdusession->pdusession_id;
|
||||
|
||||
// PDU Session Resource Setup Response Transfer (Mandatory)
|
||||
byte_array_t ba = encode_ngap_pdusession_setup_response_transfer(pdusession);
|
||||
item->pDUSessionResourceSetupResponseTransfer.buf = ba.buf;
|
||||
item->pDUSessionResourceSetupResponseTransfer.size = ba.len;
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (pdusession_setup_resp_p->nb_of_pdusessions_failed > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListSURes;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes;
|
||||
|
||||
for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) {
|
||||
pdusession_failed_t *pdusession_failed = pdusession_setup_resp_p->pdusessions_failed + i;
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToSetupListSURes.list,
|
||||
NGAP_PDUSessionResourceFailedToSetupItemSURes_t,
|
||||
item);
|
||||
NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t pdusessionUnTransfer_p = {0};
|
||||
|
||||
/* pDUSessionID */
|
||||
item->pDUSessionID = pdusession_failed->pdusession_id;
|
||||
|
||||
/* cause */
|
||||
encode_ngap_cause(&pdusessionUnTransfer_p.cause, &pdusession_failed->cause);
|
||||
NGAP_INFO("pdusession setup response: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
|
||||
asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL,
|
||||
ATS_ALIGNED_CANONICAL_PER,
|
||||
&asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer,
|
||||
&pdusessionUnTransfer_p);
|
||||
item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer;
|
||||
item->pDUSessionResourceSetupUnsuccessfulTransfer.size = res.result.encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, &pdusessionUnTransfer_p);
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceSetupResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_CriticalityDiagnostics;
|
||||
}
|
||||
|
||||
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||
NGAP_ERROR("Failed to encode uplink transport\n");
|
||||
/* Encode procedure has failed... */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* UE associated signalling -> use the allocated stream */
|
||||
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance,
|
||||
ue_context_p->amf_ref->assoc_id,
|
||||
buffer,
|
||||
length,
|
||||
ue_context_p->tx_stream);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_resp_t *pdusession_modify_resp_p)
|
||||
{
|
||||
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
|
||||
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t length;
|
||||
|
||||
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||
DevAssert(pdusession_modify_resp_p != NULL);
|
||||
DevAssert(ngap_gNB_instance_p != NULL);
|
||||
|
||||
if ((ue_context_p = ngap_get_ue_context(pdusession_modify_resp_p->gNB_ue_ngap_id)) == NULL) {
|
||||
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_modify_resp_p->gNB_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Uplink NAS transport can occur either during an ngap connected state
|
||||
* or during initial attach (for example: NAS authentication).
|
||||
*/
|
||||
if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) {
|
||||
NGAP_WARN(
|
||||
"You are attempting to send NAS data over non-connected "
|
||||
"gNB ue ngap id: %08x, current state: %d\n",
|
||||
pdusession_modify_resp_p->gNB_ue_ngap_id,
|
||||
ue_context_p->ue_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Prepare the NGAP message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu.choice.successfulOutcome, head);
|
||||
head->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceModify;
|
||||
head->criticality = NGAP_Criticality_reject;
|
||||
head->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceModifyResponse;
|
||||
NGAP_PDUSessionResourceModifyResponse_t *out = &head->value.choice.PDUSessionResourceModifyResponse;
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t));
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, pdusession_modify_resp_p->amf_ue_ngap_id);
|
||||
asn1cSeqAdd(&out->protocolIEs.list, ie);
|
||||
}
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
ie->value.choice.RAN_UE_NGAP_ID = pdusession_modify_resp_p->gNB_ue_ngap_id;
|
||||
}
|
||||
|
||||
/* PDUSessionResourceModifyListModRes optional */
|
||||
if (pdusession_modify_resp_p->nb_of_pdusessions > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModRes;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceModifyListModRes;
|
||||
|
||||
for (int i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions; i++) {
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceModifyListModRes.list, NGAP_PDUSessionResourceModifyItemModRes_t, item);
|
||||
item->pDUSessionID = pdusession_modify_resp_p->pdusessions[i].pdusession_id;
|
||||
|
||||
NGAP_PDUSessionResourceModifyResponseTransfer_t transfer = {0};
|
||||
asn1cCalloc(transfer.qosFlowAddOrModifyResponseList, tmp);
|
||||
|
||||
for (int qos_flow_index = 0; qos_flow_index < pdusession_modify_resp_p->pdusessions[i].nb_of_qos_flow; qos_flow_index++) {
|
||||
asn1cSequenceAdd(tmp->list, NGAP_QosFlowAddOrModifyResponseItem_t, qos);
|
||||
qos->qosFlowIdentifier = pdusession_modify_resp_p->pdusessions[i].qos[qos_flow_index].qfi;
|
||||
}
|
||||
asn_encode_to_new_buffer_result_t res = {0};
|
||||
res = asn_encode_to_new_buffer(NULL,
|
||||
ATS_ALIGNED_CANONICAL_PER,
|
||||
&asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer,
|
||||
&transfer);
|
||||
item->pDUSessionResourceModifyResponseTransfer.buf = res.buffer;
|
||||
item->pDUSessionResourceModifyResponseTransfer.size = res.result.encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, &transfer);
|
||||
|
||||
NGAP_DEBUG("pdusession_modify_resp: modified pdusession ID %ld\n", item->pDUSessionID);
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (pdusession_modify_resp_p->nb_of_pdusessions_failed > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToModifyListModRes;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceFailedToModifyListModRes;
|
||||
|
||||
for (int i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions_failed; i++) {
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToModifyListModRes.list,
|
||||
NGAP_PDUSessionResourceFailedToModifyItemModRes_t,
|
||||
item);
|
||||
item->pDUSessionID = pdusession_modify_resp_p->pdusessions_failed[i].pdusession_id;
|
||||
|
||||
NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t pdusessionTransfer = {0};
|
||||
|
||||
// NGAP cause
|
||||
encode_ngap_cause(&pdusessionTransfer.cause, &pdusession_modify_resp_p->pdusessions_failed[i].cause);
|
||||
|
||||
asn_encode_to_new_buffer_result_t res = {0};
|
||||
NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t *pdusessionTransfer_p = NULL;
|
||||
res = asn_encode_to_new_buffer(NULL,
|
||||
ATS_ALIGNED_CANONICAL_PER,
|
||||
&asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer,
|
||||
&pdusessionTransfer);
|
||||
item->pDUSessionResourceModifyUnsuccessfulTransfer.buf = res.buffer;
|
||||
item->pDUSessionResourceModifyUnsuccessfulTransfer.size = res.result.encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, pdusessionTransfer_p);
|
||||
|
||||
NGAP_INFO("pdusession_modify_resp: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
}
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceModifyResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_CriticalityDiagnostics;
|
||||
}
|
||||
|
||||
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||
NGAP_ERROR("Failed to encode uplink transport\n");
|
||||
/* Encode procedure has failed... */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* UE associated signalling -> use the allocated stream */
|
||||
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance,
|
||||
ue_context_p->amf_ref->assoc_id,
|
||||
buffer,
|
||||
length,
|
||||
ue_context_p->tx_stream);
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief PDU Session Resource Release Response Transfer encoding (9.3.4.21 3GPP TS 38.413)
|
||||
* The transfer structure contains only an optional Secondary RAT Usage Information IE.
|
||||
* Since we don't use secondary RAT (MR-DC), we encode an empty structure. */
|
||||
static byte_array_t encode_ngap_pdusession_release_response_transfer(void)
|
||||
{
|
||||
NGAP_PDUSessionResourceReleaseResponseTransfer_t pdusessionTransfer = {0};
|
||||
|
||||
// Encode
|
||||
asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL,
|
||||
ATS_ALIGNED_CANONICAL_PER,
|
||||
&asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer,
|
||||
&pdusessionTransfer);
|
||||
AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, &pdusessionTransfer);
|
||||
byte_array_t out = {.buf = res.buffer, .len = res.result.encoded};
|
||||
return out;
|
||||
}
|
||||
|
||||
int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_release_resp_t *pdusession_release_resp_p)
|
||||
{
|
||||
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
|
||||
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t length;
|
||||
int i;
|
||||
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||
DevAssert(pdusession_release_resp_p != NULL);
|
||||
DevAssert(ngap_gNB_instance_p != NULL);
|
||||
|
||||
if ((ue_context_p = ngap_get_ue_context(pdusession_release_resp_p->gNB_ue_ngap_id)) == NULL) {
|
||||
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", pdusession_release_resp_p->gNB_ue_ngap_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Prepare the NGAP message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu.choice.successfulOutcome, head);
|
||||
head->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceRelease;
|
||||
head->criticality = NGAP_Criticality_reject;
|
||||
head->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceReleaseResponse;
|
||||
NGAP_PDUSessionResourceReleaseResponse_t *out = &head->value.choice.PDUSessionResourceReleaseResponse;
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id);
|
||||
}
|
||||
/* mandatory */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id;
|
||||
}
|
||||
|
||||
/* PDU Session Resource Released List (mandatory) */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes;
|
||||
|
||||
for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) {
|
||||
NGAP_PDUSessionResourceReleasedListRelRes_t *list = &ie->value.choice.PDUSessionResourceReleasedListRelRes;
|
||||
asn1cSequenceAdd(list->list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item);
|
||||
pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i];
|
||||
/* PDU Session ID (mandatory) */
|
||||
item->pDUSessionID = r->pdusession_id;
|
||||
/* PDU Session Resource Release Response Transfer (mandatory) */
|
||||
// Empty transfer is valid since Secondary RAT Usage Information is optional and not used
|
||||
byte_array_t transfer = encode_ngap_pdusession_release_response_transfer();
|
||||
OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)transfer.buf, transfer.len);
|
||||
free_byte_array(transfer);
|
||||
NGAP_DEBUG("PDU Session Resource Release Response: pdusession ID %ld\n", item->pDUSessionID);
|
||||
}
|
||||
}
|
||||
|
||||
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||
NGAP_ERROR("Failed to encode release response\n");
|
||||
/* Encode procedure has failed... */
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* UE associated signalling -> use the allocated stream */
|
||||
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance,
|
||||
ue_context_p->amf_ref->assoc_id,
|
||||
buffer,
|
||||
length,
|
||||
ue_context_p->tx_stream);
|
||||
NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d \n",
|
||||
pdusession_release_resp_p->gNB_ue_ngap_id,
|
||||
(uint64_t)ue_context_p->amf_ue_ngap_id,
|
||||
pdusession_release_resp_p->nb_of_pdusessions_released);
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu);
|
||||
return 0;
|
||||
}
|
||||
@@ -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 NGAP_GNB_PDU_SESSION_MANAGEMENT_H_
|
||||
#define NGAP_GNB_PDU_SESSION_MANAGEMENT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "assertions.h"
|
||||
#include "ngap_messages_types.h"
|
||||
#include "ngap_msg_includes.h"
|
||||
|
||||
int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_resp_t *pdusession_setup_resp_p);
|
||||
|
||||
int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_resp_t *pdusession_modify_resp_p);
|
||||
|
||||
int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_release_resp_t *pdusession_release_resp_p);
|
||||
|
||||
#endif /* NGAP_GNB_PDU_SESSION_MANAGEMENT_H_ */
|
||||
@@ -41,6 +41,12 @@
|
||||
#include "NGAP_GTPTunnel.h"
|
||||
#include "NGAP_InitiatingMessage.h"
|
||||
#include "NGAP_NGAP-PDU.h"
|
||||
#include "NGAP_Paging.h"
|
||||
#include "NGAP_AssistanceDataForPaging.h"
|
||||
#include "NGAP_PagingAttemptInformation.h"
|
||||
#include "NGAP_FiveG-S-TMSI.h"
|
||||
#include "NGAP_TAI.h"
|
||||
#include "NGAP_UEPagingIdentity.h"
|
||||
#include "NGAP_PDUSessionResourceFailedToModifyItemModRes.h"
|
||||
#include "NGAP_PDUSessionResourceFailedToSetupItemCxtRes.h"
|
||||
#include "NGAP_PDUSessionResourceFailedToSetupItemSURes.h"
|
||||
@@ -102,7 +108,6 @@
|
||||
#include "NGAP_PDUSessionResourceAdmittedItem.h"
|
||||
#include "NGAP_HandoverRequestAcknowledgeTransfer.h"
|
||||
#include "NGAP_QosFlowItemWithDataForwarding.h"
|
||||
#include "NR_HandoverPreparationInformation.h"
|
||||
#include "NGAP_HandoverNotify.h"
|
||||
#include "NGAP_DRBsSubjectToStatusTransferItem.h"
|
||||
#include "NGAP_DRBStatusUL.h"
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef NGAP_UTILS_H_
|
||||
#define NGAP_UTILS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "assertions.h"
|
||||
#include "common/utils/eq_check.h"
|
||||
|
||||
#define NGAP_UE_ID_FMT "0x%06" PRIX32
|
||||
|
||||
#define NGAP_ERROR(x, args...) LOG_E(NGAP, x, ##args)
|
||||
#define NGAP_WARN(x, args...) LOG_W(NGAP, x, ##args)
|
||||
#define NGAP_TRAF(x, args...) LOG_I(NGAP, x, ##args)
|
||||
#define NGAP_INFO(x, args...) LOG_I(NGAP, x, ##args)
|
||||
#define NGAP_DEBUG(x, args...) LOG_D(NGAP, x, ##args)
|
||||
|
||||
#define NGAP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \
|
||||
do { \
|
||||
IE_TYPE **ptr; \
|
||||
ie = NULL; \
|
||||
for (ptr = container->protocolIEs.list.array; ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \
|
||||
ptr++) { \
|
||||
if ((*ptr)->id == IE_ID) { \
|
||||
ie = *ptr; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (ie == NULL) { \
|
||||
if (mandatory) { \
|
||||
AssertFatal(NGAP, "NGAP_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \
|
||||
} else { \
|
||||
NGAP_DEBUG("NGAP_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \
|
||||
} \
|
||||
} \
|
||||
} while (0); \
|
||||
if (mandatory && !ie) \
|
||||
return -1
|
||||
|
||||
#endif /* NGAP_UTILS_H_ */
|
||||
@@ -0,0 +1,6 @@
|
||||
add_executable(ngap_lib_test ngap_lib_test.c)
|
||||
add_dependencies(tests ngap_lib_test)
|
||||
add_test(NAME ngap_lib_test COMMAND ngap_lib_test)
|
||||
target_link_libraries(ngap_lib_test PRIVATE ngap asn1_ngap asn1_lte_rrc_hdrs UTIL ds)
|
||||
target_include_directories(ngap_lib_test PRIVATE ${CMAKE_SOURCE_DIR})
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // abort
|
||||
#include <stdint.h> // uint*_t
|
||||
#include <stdio.h> // printf
|
||||
#include <stdbool.h> // bool
|
||||
|
||||
#include "common/utils/assertions.h" // AssertFatal, DevAssert
|
||||
#include "common/utils/utils.h" // malloc_or_fail, calloc_or_fail
|
||||
#include "common/utils/ds/byte_array.h" // create_byte_array
|
||||
#include "conversions.h" // TBCD_TO_MCC_MNC, OCTET_STRING_TO_INT*
|
||||
#include "ngap_common.h" // NGAP_ERROR, NGAP_DEBUG, ngap_messages_types.h
|
||||
#include "ngap_gNB_paging.h" // encode_ng_paging, decode_ng_paging, free_ng_paging
|
||||
#include "ngap_msg_includes.h" // NGAP_NGAP_PDU_t, NGAP_Paging_t, etc.
|
||||
#include "oai_asn1.h" // ASN_STRUCT_FREE, asn_DEF_NGAP_NGAP_PDU
|
||||
#include "config/config_load_configmodule.h" // configmodule_interface_t
|
||||
#include "common/utils/LOG/log.h" // log_init
|
||||
|
||||
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 NGAP_NGAP_PDU_t *ngap_encode_decode(const NGAP_NGAP_PDU_t *enc_pdu)
|
||||
{
|
||||
DevAssert(enc_pdu != NULL);
|
||||
char errbuf[1024];
|
||||
size_t errlen = sizeof(errbuf);
|
||||
int ret = asn_check_constraints(&asn_DEF_NGAP_NGAP_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_NGAP_NGAP_PDU, NULL, enc_pdu, msgbuf, sizeof(msgbuf));
|
||||
AssertFatal(enc.encoded > 0, "aper_encode_to_buffer() failed\n");
|
||||
|
||||
NGAP_NGAP_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_NGAP_NGAP_PDU, (void **)&dec_pdu, msgbuf, enc.encoded, 0, 0);
|
||||
AssertFatal(dec.code == RC_OK, "aper_decode() failed\n");
|
||||
|
||||
return dec_pdu;
|
||||
}
|
||||
|
||||
static void ngap_msg_free(NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
}
|
||||
|
||||
/** @brief Test NGAP Paging encoding/decoding roundtrip */
|
||||
static void test_ngap_paging_encode_decode(void)
|
||||
{
|
||||
// Create test paging indication
|
||||
ngap_paging_ind_t orig = {0};
|
||||
orig.ue_paging_identity.s_tmsi.amf_set_id = 123; // Valid range: 0-1023 (10 bits)
|
||||
orig.ue_paging_identity.s_tmsi.amf_pointer = 45; // Valid range: 0-63 (6 bits)
|
||||
orig.ue_paging_identity.s_tmsi.m_tmsi = 0x12345678;
|
||||
orig.n_tai = 2;
|
||||
orig.tai_list[0].plmn.mcc = 208;
|
||||
orig.tai_list[0].plmn.mnc = 95;
|
||||
orig.tai_list[0].plmn.mnc_digit_length = 2;
|
||||
orig.tai_list[0].tac = 12345;
|
||||
orig.tai_list[1].plmn.mcc = 001;
|
||||
orig.tai_list[1].plmn.mnc = 01;
|
||||
orig.tai_list[1].plmn.mnc_digit_length = 2;
|
||||
orig.tai_list[1].tac = 23456;
|
||||
orig.paging_drx = malloc_or_fail(sizeof(ngap_paging_drx_t));
|
||||
*orig.paging_drx = NGAP_PAGING_DRX_128;
|
||||
orig.paging_priority = malloc_or_fail(sizeof(ngap_paging_priority_t));
|
||||
*orig.paging_priority = NGAP_PAGING_PRIO_LEVEL2;
|
||||
uint8_t ue_cap_data[] = {0x01, 0x02, 0x03, 0x04};
|
||||
orig.ue_radio_capability = malloc_or_fail(sizeof(byte_array_t));
|
||||
*orig.ue_radio_capability = create_byte_array(sizeof(ue_cap_data), ue_cap_data);
|
||||
orig.origin = calloc_or_fail(1, sizeof(*orig.origin));
|
||||
*orig.origin = NGAP_PAGING_ORIGIN_NON_3GPP;
|
||||
|
||||
// Encode
|
||||
NGAP_NGAP_PDU_t *enc_pdu = encode_ng_paging(&orig);
|
||||
AssertFatal(enc_pdu != NULL, "encode_ng_paging(): failed to encode message\n");
|
||||
LOG_A(NGAP, "encoded: m_tmsi=0x%x, n_tai=%d\n", orig.ue_paging_identity.s_tmsi.m_tmsi, orig.n_tai);
|
||||
|
||||
// Encode/decode roundtrip
|
||||
NGAP_NGAP_PDU_t *dec_pdu = ngap_encode_decode(enc_pdu);
|
||||
ngap_msg_free(enc_pdu);
|
||||
|
||||
// Decode
|
||||
ngap_paging_ind_t decoded = {0};
|
||||
bool decode_ret = decode_ng_paging(&decoded, dec_pdu);
|
||||
AssertFatal(decode_ret, "decode_ng_paging(): could not decode message\n");
|
||||
ngap_msg_free(dec_pdu);
|
||||
LOG_A(NGAP, "decoded: m_tmsi=0x%x, n_tai=%d\n", decoded.ue_paging_identity.s_tmsi.m_tmsi, decoded.n_tai);
|
||||
|
||||
// Verify decoded values using equality function
|
||||
bool eq_ret = eq_ng_paging(&orig, &decoded);
|
||||
AssertFatal(eq_ret, "eq_ng_paging(): decoded message doesn't match original\n");
|
||||
LOG_A(NGAP, "eq_ng_paging(): decoded message matches original\n");
|
||||
|
||||
free_ng_paging(&decoded);
|
||||
free_ng_paging(&orig);
|
||||
}
|
||||
|
||||
// Stub for uniqCfg required by logging/config system
|
||||
configmodule_interface_t *uniqCfg = NULL;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Initialize logging system
|
||||
logInit();
|
||||
set_log(NGAP, OAILOG_INFO);
|
||||
|
||||
test_ngap_paging_encode_decode();
|
||||
LOG_A(NGAP, "All NGAP paging tests passed!\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -548,6 +548,18 @@ do { \
|
||||
(bITsTRING)->bits_unused = 0; \
|
||||
} while(0)
|
||||
|
||||
#define IRNTI_TO_BIT_STRING(mACRO, bITsTRING) \
|
||||
do { \
|
||||
(bITsTRING)->buf = calloc(5, sizeof(uint8_t)); \
|
||||
(bITsTRING)->buf[0] = ((mACRO) >> 32) & 0xff; \
|
||||
(bITsTRING)->buf[1] = ((mACRO) >> 24) & 0xff; \
|
||||
(bITsTRING)->buf[2] = ((mACRO) >> 16) & 0xff; \
|
||||
(bITsTRING)->buf[3] = ((mACRO) >> 8) & 0xff; \
|
||||
(bITsTRING)->buf[4] = ((mACRO) & 0xff); \
|
||||
(bITsTRING)->size = 5; \
|
||||
(bITsTRING)->bits_unused = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Used to format an uint32_t containing an ipv4 address */
|
||||
#define IPV4_ADDR "%u.%u.%u.%u"
|
||||
#define IPV4_ADDR_FORMAT(aDDRESS) \
|
||||
|
||||
Reference in New Issue
Block a user