Merge remote-tracking branch 'origin/cleanup-pdu-session' into integration_2025_w26 (!3435)

Cleanup PDU Session Handling in RRC/NGAP

Currently, NGAP and RRC share the same structures and responsibilities when
handling PDU Session information: this creates tight coupling, redundancy, and
makes the code harder to maintain.

- NGAP should be responsible only for: Protocol-specific encoding/decoding
(3GPP TS 38.413)
- RRC should own: PDU Session handling and storage in the UE context

This MR is the first step in a broader refactoring of the PDU Session handling
code across NGAP and RRC layers, with the goal of splitting responsibilities
cleanly between both modules.

- Unified gtpu_tunnel_t for tunnel endpoint config (formerly f1u_tunnel_t)
- Refactored and relocated PDU Session struct definitions for better separation
  between NGAP and RRC
  - Moved pdusession_t for PDU Session handling out of NGAP, now defined and
    managed by RRC only
  - Defined 3GPP TS 38.413 message-specific structs in NGAP module
  - NGAP now decodes NGAP PDU Session Resource Setup/Modify IEs and transfers
    decoded data to RRC via ITTI
  - Add helper functions to copy from NGAP message to pdusession_t
- Introduced new encoders/decoders/helpers in NGAP for handling PDU Session
  Resource Setup/Modify procedures (e.g. decode_pdusession_transfer)
  - Migrated to NGAP and removed duplicated logic for QoS information decoding
    (fill_qos)
- Improved logging of GTP tunnel info
- Merged redundant functions (f1u_dl_gtp_update and f1u_ul_gtp_update)
- Removed unused code and obsolete types
- do free_func in seq_arr_erase_it on the provided range and updated unit test
- Other fixes and simplifications (e.g. simplified and clarified naming of
  tunnel/session parameters and structs)

This cleanup improves code readability, has a high code churn (the deletions are
~159.7% of the insertions) and prepares for better modularity before the
refactoring of PDU Session handling in RRC/NGAP.
This commit is contained in:
Jaroslava Fiedlerova
2025-06-23 15:55:57 +02:00
20 changed files with 370 additions and 570 deletions

View File

@@ -45,6 +45,14 @@ typedef struct nr_guami_s {
uint8_t amf_pointer;
} nr_guami_t;
typedef enum {
PDUSessionType_ipv4 = 0,
PDUSessionType_ipv6 = 1,
PDUSessionType_ipv4v6 = 2,
PDUSessionType_ethernet = 3,
PDUSessionType_unstructured = 4
} pdu_session_type_t;
typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t;
#endif

View File

@@ -218,25 +218,27 @@ typedef struct nr_lcid_rb_t {
} nr_lcid_rb_t;
typedef struct transport_layer_addr_s {
/**
* Transport Layer Address as a bitstring:
* - 32 bits for IPv4 (RFC 791),
* - 128 bits for IPv6 (RFC 2460),
* - 160 bits for both IPv4 and IPv6, with IPv4 in the first 32 bits.
* The S1AP/NGAP layer forwards this address (bitstring<1..160>)
* to S1-U/NG-U without interpreting it.
*/
/** Transport Layer Address in bytes:
* - 4 bytes for IPv4 (RFC 791), 16 bytes for IPv6 (RFC 2460),
* - 20 bytes for both IPv4 and IPv6, with IPv4 in the first 4 bytes. */
uint8_t length;
/// Buffer: address in network byte order
uint8_t buffer[20];
} transport_layer_addr_t;
/** @brief GTP tunnel configuration */
typedef struct {
// Tunnel endpoint identifier
uint32_t teid;
// Transport layer address
transport_layer_addr_t addr;
} gtpu_tunnel_t;
//-----------------------------------------------------------------------------
// GTPV1U TYPES
//-----------------------------------------------------------------------------
typedef uint32_t teid_t; // tunnel endpoint identifier
typedef uint8_t ebi_t; // eps bearer id
typedef uint8_t pdusessionid_t;
//-----------------------------------------------------------------------------
//

View File

@@ -123,11 +123,10 @@ void seq_arr_erase_it(seq_arr_t* arr, void* start_it, void* end_it, void (*free_
return;
if (free_func != NULL) {
void* start_it = seq_arr_front(arr);
void* end_it = seq_arr_end(arr);
while (start_it != end_it) {
free_func(start_it);
start_it = seq_arr_next(arr, start_it);
void* it = start_it;
while (it != end_it) {
free_func(it);
it = seq_arr_next(arr, it);
}
}

View File

@@ -36,6 +36,13 @@ static int compar(const void* m0, const void* m1)
return 1;
}
static int free_func_call_count = 0;
static void dummy_free_func(void* it)
{
++free_func_call_count;
}
int main()
{
seq_arr_t arr = {0};
@@ -83,6 +90,19 @@ int main()
void* it = bsearch(&key, base, nmemb, size, compar);
assert(seq_arr_dist(&arr, seq_arr_front(&arr), it) == 4);
// Regression test: erase a partial range only
// Erase 92, 93, 94 (i.e., indices 1 to 3)
int* start = seq_arr_at(&arr, 1);
int* end = seq_arr_at(&arr, 4);
seq_arr_erase_it(&arr, start, end, dummy_free_func);
// Now values should be: [91, 95, 96, 97, 98, 99]
assert(free_func_call_count == 3);
assert(seq_arr_size(&arr) == 6);
assert(*(int*)seq_arr_at(&arr, 0) == 91);
assert(*(int*)seq_arr_at(&arr, 1) == 95);
assert(*(int*)seq_arr_at(&arr, 5) == 99);
// Free data structure
seq_arr_free(&arr, NULL);

View File

@@ -163,7 +163,7 @@ typedef struct gtpv1u_gnb_create_tunnel_req_s {
int num_tunnels;
teid_t outgoing_teid[NR_GTPV1U_MAX_BEARERS_PER_UE];
int outgoing_qfi[NR_GTPV1U_MAX_BEARERS_PER_UE];
pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE];
int pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE];
ebi_t incoming_rb_id[NR_GTPV1U_MAX_BEARERS_PER_UE];
transport_layer_addr_t dst_addr[NR_GTPV1U_MAX_BEARERS_PER_UE];
} gtpv1u_gnb_create_tunnel_req_t;
@@ -173,13 +173,13 @@ typedef struct gtpv1u_gnb_create_tunnel_resp_s {
ue_id_t ue_id;
int num_tunnels;
teid_t gnb_NGu_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier
pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE];
int pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE];
transport_layer_addr_t gnb_addr;
} gtpv1u_gnb_create_tunnel_resp_t;
typedef struct gtpv1u_gnb_delete_tunnel_req_s {
ue_id_t ue_id;
uint8_t num_pdusession;
pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE];
int pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE];
} gtpv1u_gnb_delete_tunnel_req_t;
typedef struct gtpv1u_gnb_delete_tunnel_resp_s {
@@ -192,7 +192,7 @@ typedef struct gtpv1u_gnb_delete_tunnel_resp_s {
typedef struct gtpv1u_DU_buffer_report_req_s {
uint32_t buffer_availability;
ue_id_t ue_id;
pdusessionid_t pdusession_id;
int pdusession_id;
} gtpv1u_DU_buffer_report_req_t;
#endif /* GTPV1_U_MESSAGES_TYPES_H_ */

View File

@@ -71,9 +71,6 @@ MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_
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)
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, ngap_path_switch_req_t , ngap_path_switch_req)
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, ngap_path_switch_req_ack_t , ngap_path_switch_req_ack)
MESSAGE_DEF(NGAP_PDUSESSION_MODIFICATION_IND , MESSAGE_PRIORITY_MED, ngap_pdusession_modification_ind_t , ngap_pdusession_modification_ind)
/* NGAP -> RRC messages */
MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas )

View File

@@ -231,36 +231,6 @@ typedef struct ngap_mobility_restriction_s{
ngap_plmn_identity_t serving_plmn;
}ngap_mobility_restriction_t;
typedef enum pdu_session_type_e {
PDUSessionType_ipv4 = 0,
PDUSessionType_ipv6 = 1,
PDUSessionType_ipv4v6 = 2,
PDUSessionType_ethernet = 3,
PDUSessionType_unstructured = 4
}pdu_session_type_t;
typedef struct pdusession_s {
/* Unique pdusession_id for the UE. */
int pdusession_id;
byte_array_t nas_pdu;
byte_array_t pdusessionTransfer;
uint8_t nb_qos;
/* Quality of service for this pdusession */
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
/* The transport layer address for the IP packets */
pdu_session_type_t pdu_session_type;
transport_layer_addr_t upf_addr;
/* Outgoing (UL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gtp_teid;
/* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gNB_teid_N3;
transport_layer_addr_t gNB_addr_N3;
/* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t UPF_teid_N3;
transport_layer_addr_t UPF_addr_N3;
nssai_t nssai;
} pdusession_t;
typedef enum pdusession_qosflow_mapping_ind_e{
QOSFLOW_MAPPING_INDICATION_UL = 0,
QOSFLOW_MAPPING_INDICATION_DL = 1,
@@ -278,10 +248,9 @@ typedef struct pdusession_setup_s {
/* The transport layer address for the IP packets */
uint8_t pdu_session_type;
transport_layer_addr_t gNB_addr;
/* Incoming NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gtp_teid;
// NG-U (N3) Tunnel Endpoint on the RAN side
gtpu_tunnel_t n3_outgoing;
/* qos flow list number */
uint8_t nb_of_qos_flow;
@@ -290,18 +259,6 @@ typedef struct pdusession_setup_s {
pdusession_associate_qosflow_t associated_qos_flows[QOSFLOW_MAX_VALUE];
} pdusession_setup_t;
typedef struct pdusession_tobeswitched_s {
/* Unique pdusession_id for the UE. */
uint8_t pdusession_id;
/* The transport layer address for the IP packets */
uint8_t pdu_session_type;
transport_layer_addr_t upf_addr;
/* S-GW Tunnel endpoint identifier */
uint32_t gtp_teid;
} pdusession_tobeswitched_t;
typedef struct qos_flow_tobe_modified_s {
uint8_t qfi; // 0~63
} qos_flow_tobe_modified_t;
@@ -580,6 +537,22 @@ typedef struct ngap_downlink_nas_s {
byte_array_t nas_pdu;
} ngap_downlink_nas_t;
/* PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */
typedef struct {
uint8_t nb_qos;
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
pdu_session_type_t pdu_session_type;
// UPF endpoint of the NG-U (N3) transport bearer
gtpu_tunnel_t n3_incoming;
} pdusession_transfer_t;
/* PDU Session Resource Setup/Modify Request Item */
typedef struct {
int pdusession_id;
byte_array_t nas_pdu;
nssai_t nssai;
pdusession_transfer_t pdusessionTransfer;
} pdusession_resource_item_t;
typedef struct ngap_initial_context_setup_req_s {
/* UE id for initial connection to NGAP */
@@ -605,8 +578,8 @@ typedef struct ngap_initial_context_setup_req_s {
/* Number of pdusession to be setup in the list */
uint8_t nb_of_pdusessions;
/* list of pdusession to be setup by RRC layers */
pdusession_t pdusession_param[NGAP_MAX_PDU_SESSION];
// PDU Session Resource Setup Request List
pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION];
/* Mobility Restriction List */
uint8_t mobility_restriction_flag;
@@ -640,13 +613,6 @@ typedef struct ngap_paging_ind_s {
ngap_paging_priority_t paging_priority;
} ngap_paging_ind_t;
typedef struct {
/* Unique pdusession_id for the UE. */
int pdusession_id;
byte_array_t nas_pdu;
byte_array_t pdusessionTransfer;
} pdusession_setup_req_t;
typedef struct ngap_pdusession_setup_req_s {
/* UE id for initial connection to NGAP */
uint32_t gNB_ue_ngap_id;
@@ -661,8 +627,8 @@ typedef struct ngap_pdusession_setup_req_s {
/* Number of pdusession to be setup in the list */
uint8_t nb_pdusessions_tosetup;
/* E RAB setup request */
pdusession_t pdusession_setup_params[NGAP_MAX_PDU_SESSION];
// PDU Session Resource Setup Request List
pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION];
/* UE Aggregated Max Bitrates */
ngap_ambr_t ueAggMaxBitRate;
@@ -682,78 +648,6 @@ typedef struct ngap_pdusession_setup_resp_s {
pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION];
} ngap_pdusession_setup_resp_t;
typedef struct ngap_path_switch_req_s {
uint32_t gNB_ue_ngap_id;
/* Number of pdusession setup-ed in the list */
uint8_t nb_of_pdusessions;
/* list of pdusession setup-ed by RRC layers */
pdusession_setup_t pdusessions_tobeswitched[NGAP_MAX_PDU_SESSION];
/* AMF UE id */
uint64_t amf_ue_ngap_id;
nr_guami_t ue_guami;
uint16_t ue_initial_id;
/* Security algorithms */
ngap_security_capabilities_t security_capabilities;
} ngap_path_switch_req_t;
typedef struct ngap_path_switch_req_ack_s {
/* UE id for initial connection to NGAP */
uint16_t ue_initial_id;
uint32_t gNB_ue_ngap_id;
/* AMF UE id */
uint64_t amf_ue_ngap_id;
/* UE aggregate maximum bitrate */
ngap_ambr_t ue_ambr;
/* Number of pdusession setup-ed in the list */
uint8_t nb_pdusessions_tobeswitched;
/* list of pdusession to be switched by RRC layers */
pdusession_tobeswitched_t pdusessions_tobeswitched[NGAP_MAX_PDU_SESSION];
/* Number of pdusessions to be released by RRC */
uint8_t nb_pdusessions_tobereleased;
/* list of pdusessions to be released */
pdusession_failed_t pdusessions_tobereleased[NGAP_MAX_PDU_SESSION];
/* Security key */
int next_hop_chain_count;
uint8_t next_security_key[SECURITY_KEY_LENGTH];
} ngap_path_switch_req_ack_t;
typedef struct ngap_pdusession_modification_ind_s {
uint32_t gNB_ue_ngap_id;
/* AMF UE id */
uint64_t amf_ue_ngap_id;
/* Number of pdusession setup-ed in the list */
uint8_t nb_of_pdusessions_tobemodified;
uint8_t nb_of_pdusessions_nottobemodified;
/* list of pdusession setup-ed by RRC layers */
pdusession_setup_t pdusessions_tobemodified[NGAP_MAX_PDU_SESSION];
pdusession_setup_t pdusessions_nottobemodified[NGAP_MAX_PDU_SESSION];
uint16_t ue_initial_id;
} ngap_pdusession_modification_ind_t;
// NGAP --> RRC messages
typedef struct ngap_ue_release_command_s {
@@ -789,8 +683,8 @@ typedef struct ngap_pdusession_modify_req_s {
/* Number of pdusession to be modify in the list */
uint8_t nb_pdusessions_tomodify;
/* pdu session modify request */
pdusession_t pdusession_modify_params[NGAP_MAX_PDU_SESSION];
// PDU Session Resource Modify Request List
pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION];
} ngap_pdusession_modify_req_t;
typedef struct ngap_pdusession_modify_resp_s {

View File

@@ -65,8 +65,8 @@ bool read_gtp_sm(void * data)
int nb_pdu_session = ue_context_p->ue_context.nb_of_pdusessions;
if (nb_pdu_session > 0) {
int nb_pdu_idx = nb_pdu_session - 1;
gtp->msg.ngut[i].teidgnb = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.gNB_teid_N3;
gtp->msg.ngut[i].teidupf = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.UPF_teid_N3;
gtp->msg.ngut[i].teidgnb = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_outgoing.teid;
gtp->msg.ngut[i].teidupf = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_incoming.teid;
// TODO: one PDU session has multiple QoS Flow
int nb_qos_flow = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.nb_qos;
if (nb_qos_flow > 0) {

View File

@@ -99,6 +99,22 @@ typedef enum pdu_session_satus_e {
PDU_SESSION_STATUS_RELEASED
} pdu_session_status_t;
typedef struct pdusession_s {
/* Unique pdusession_id for the UE. */
int pdusession_id;
byte_array_t nas_pdu;
uint8_t nb_qos;
/* Quality of service for this pdusession */
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
/* The transport layer address for the IP packets */
pdu_session_type_t pdu_session_type;
// NG-RAN endpoint of the NG-U (N3) transport bearer
gtpu_tunnel_t n3_outgoing;
// UPF endpoint of the NG-U (N3) transport bearer
gtpu_tunnel_t n3_incoming;
nssai_t nssai;
} pdusession_t;
typedef struct pdu_session_param_s {
pdusession_t param;
pdu_session_status_t status;
@@ -106,16 +122,6 @@ typedef struct pdu_session_param_s {
ngap_cause_t cause;
} rrc_pdu_session_param_t;
/**
* @brief F1-U tunnel configuration
*/
typedef struct f1u_tunnel_s {
/* F1-U Tunnel Endpoint Identifier (on DU side) */
uint32_t teid;
/* Downlink F1-U Transport Layer (on DU side) */
transport_layer_addr_t addr;
} f1u_tunnel_t;
typedef struct drb_s {
int status;
int drb_id;
@@ -145,9 +151,9 @@ typedef struct drb_s {
} ext1;
} pdcp_config;
// F1-U Downlink Tunnel Config (on DU side)
f1u_tunnel_t du_tunnel_config;
gtpu_tunnel_t du_tunnel_config;
// F1-U Uplink Tunnel Config (on CU-UP side)
f1u_tunnel_t cuup_tunnel_config;
gtpu_tunnel_t cuup_tunnel_config;
} drb_t;
typedef enum {

View File

@@ -2004,14 +2004,13 @@ static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_to_b
drb_e1->DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid;
}
/**
* @brief Store F1-U DL TL and TEID in RRC
*/
static void f1u_dl_gtp_update(f1u_tunnel_t *f1u, const f1ap_up_tnl_t *p)
static gtpu_tunnel_t f1u_gtp_update(uint32_t teid, const in_addr_t addr)
{
f1u->teid = p->teid;
memcpy(&f1u->addr.buffer, &p->tl_address, sizeof(uint8_t) * 4);
f1u->addr.length = sizeof(in_addr_t);
gtpu_tunnel_t out = {0};
out.teid = teid;
memcpy(&out.addr.buffer, &addr, 4);
out.addr.length = sizeof(addr);
return out;
}
/**
@@ -2024,20 +2023,10 @@ static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_R
AssertFatal(drb_f1->up_dl_tnl_length == 1, "can handle only one UP param\n");
AssertFatal(drb_f1->drb_id < MAX_DRBS_PER_UE, "illegal DRB ID %ld\n", drb_f1->drb_id);
drb_t *drb = get_drb(ue, drb_f1->drb_id);
f1u_dl_gtp_update(&drb->du_tunnel_config, &drb_f1->up_dl_tnl[0]);
drb->du_tunnel_config = f1u_gtp_update(drb_f1->up_dl_tnl[0].teid, drb_f1->up_dl_tnl[0].tl_address);
}
}
/*
* @brief Store F1-U UL TEID and address in RRC
*/
static void f1u_ul_gtp_update(f1u_tunnel_t *f1u, const up_params_t *p)
{
f1u->teid = p->tl_info.teId;
memcpy(&f1u->addr.buffer, &p->tl_info.tlAddress, sizeof(uint8_t) * 4);
f1u->addr.length = sizeof(in_addr_t);
}
/* \brief use list of DRBs and send the corresponding bearer update message via
* E1 to the CU of this UE. Also updates TEID info internally */
static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs)
@@ -2460,9 +2449,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id);
continue;
}
rrc_pdu->param.gNB_teid_N3 = e1_pdu->tl_info.teId;
memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tl_info.tlAddress, sizeof(uint8_t) * 4);
rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t);
rrc_pdu->param.n3_outgoing = f1u_gtp_update(e1_pdu->tl_info.teId, e1_pdu->tl_info.tlAddress);
// save the tunnel address for the DRBs
for (int i = 0; i < e1_pdu->numDRBSetup; i++) {
@@ -2470,7 +2457,8 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
// numUpParam only relevant in F1, but not monolithic
AssertFatal(drb_config->numUpParam <= 1, "can only up to one UP param\n");
drb_t *drb = get_drb(UE, drb_config->id);
f1u_ul_gtp_update(&drb->cuup_tunnel_config, &drb_config->UpParamList[0]);
UP_TL_information_t *tl_info = &drb_config->UpParamList[0].tl_info;
drb->cuup_tunnel_config = f1u_gtp_update(tl_info->teId, tl_info->tlAddress);
}
}

View File

@@ -36,6 +36,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include "E1AP_ConfidentialityProtectionIndication.h"
#include "E1AP_IntegrityProtectionIndication.h"
#include "NGAP_CauseRadioNetwork.h"
@@ -161,6 +162,20 @@ static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn)
return guami;
}
/** @brief Copy NGAP PDU Session Resource item to RRC pdusession_t struct */
static void cp_pdusession_resource_item_to_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src)
{
dst->pdusession_id = src->pdusession_id;
dst->nas_pdu = src->nas_pdu;
dst->nb_qos = src->pdusessionTransfer.nb_qos;
for (uint8_t i = 0; i < src->pdusessionTransfer.nb_qos && i < QOSFLOW_MAX_VALUE; ++i) {
dst->qos[i] = src->pdusessionTransfer.qos[i];
}
dst->pdu_session_type = src->pdusessionTransfer.pdu_session_type;
dst->n3_incoming = src->pdusessionTransfer.n3_incoming;
dst->nssai = src->nssai;
}
/**
* @brief Prepare the Initial UE Message (Uplink NAS) to be forwarded to the AMF over N2
* extracts NAS PDU, Selected PLMN and Registered AMF from the RRCSetupComplete
@@ -225,114 +240,6 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, message_p);
}
static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session)
{
DevAssert(qos->list.count > 0);
DevAssert(qos->list.count <= NGAP_maxnoofQosFlows);
for (int qosIdx = 0; qosIdx < qos->list.count; qosIdx++) {
NGAP_QosFlowSetupRequestItem_t *qosFlowItem_p = qos->list.array[qosIdx];
// Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics;
AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx);
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = NON_DYNAMIC;
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
} else {
AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = DYNAMIC;
session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI);
}
ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority;
NGAP_AllocationAndRetentionPriority_t *tmp2 = &qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority;
tmp->priority_level = tmp2->priorityLevelARP;
tmp->pre_emp_capability = tmp2->pre_emptionCapability;
tmp->pre_emp_vulnerability = tmp2->pre_emptionVulnerability;
}
session->nb_qos = qos->list.count;
}
static int decodePDUSessionResourceSetup(pdusession_t *session)
{
NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL;
asn_codec_ctx_t st = {.max_stack_size = 100 * 1000};
asn_dec_rval_t dec_rval = aper_decode(&st,
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
(void **)&pdusessionTransfer,
session->pdusessionTransfer.buf,
session->pdusessionTransfer.len,
0,
0);
if (dec_rval.code != RC_OK) {
LOG_E(NR_RRC, "can not decode PDUSessionResourceSetupRequestTransfer\n");
return -1;
}
for (int i = 0; i < pdusessionTransfer->protocolIEs.list.count; i++) {
NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[i];
switch (pdusessionTransfer_ies->id) {
/* optional PDUSessionAggregateMaximumBitRate */
case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate:
break;
/* mandatory UL-NGU-UP-TNLInformation */
case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation: {
NGAP_GTPTunnel_t *gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel;
/* Set the transport layer address */
memcpy(session->upf_addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size);
session->upf_addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused;
/* GTP tunnel endpoint ID */
OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, session->gtp_teid);
}
break;
/* optional AdditionalUL-NGU-UP-TNLInformation */
case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation:
break;
/* optional DataForwardingNotPossible */
case NGAP_ProtocolIE_ID_id_DataForwardingNotPossible:
break;
/* mandatory PDUSessionType */
case NGAP_ProtocolIE_ID_id_PDUSessionType:
session->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType;
break;
/* optional SecurityIndication */
case NGAP_ProtocolIE_ID_id_SecurityIndication:
break;
/* optional NetworkInstance */
case NGAP_ProtocolIE_ID_id_NetworkInstance:
break;
/* mandatory QosFlowSetupRequestList */
case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList:
fill_qos(&pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList, session);
break;
/* optional CommonNetworkInstance */
case NGAP_ProtocolIE_ID_id_CommonNetworkInstance:
break;
default:
LOG_E(NR_RRC, "could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id);
return -1;
}
}
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, pdusessionTransfer);
return 0;
}
/**
* @brief Triggers bearer setup for the specified UE.
*
@@ -360,13 +267,7 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
for (int i = 0; i < n; i++) {
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, sessions[i].pdusession_id, true);
pdusession_t *session = &pduSession->param;
session->pdusession_id = sessions[i].pdusession_id;
LOG_I(NR_RRC, "Adding pdusession %d, total nb of sessions %d\n", session->pdusession_id, UE->nb_of_pdusessions);
session->pdu_session_type = sessions[i].pdu_session_type;
session->nas_pdu = sessions[i].nas_pdu;
session->pdusessionTransfer = sessions[i].pdusessionTransfer;
session->nssai = sessions[i].nssai;
decodePDUSessionResourceSetup(session);
cp_pdusession(session, &sessions[i]);
bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id;
security_information_t *secInfo = &bearer_req.secInfo;
secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0;
@@ -386,8 +287,12 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
: SECURITY_NOT_NEEDED;
sec->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? SECURITY_REQUIRED
: SECURITY_NOT_NEEDED;
pdu->UP_TL_information.teId = session->gtp_teid;
memcpy(&pdu->UP_TL_information.tlAddress, session->upf_addr.buffer, sizeof(in_addr_t));
gtpu_tunnel_t *n3_incoming = &session->n3_incoming;
pdu->UP_TL_information.teId = n3_incoming->teid;
memcpy(&pdu->UP_TL_information.tlAddress, n3_incoming->addr.buffer, sizeof(in_addr_t));
char ip_str[INET_ADDRSTRLEN] = {0};
inet_ntop(AF_INET, n3_incoming->addr.buffer, ip_str, sizeof(ip_str));
LOG_I(NR_RRC, "Bearer Context Setup: PDU Session ID=%d, incoming TEID=0x%08x, Addr=%s\n", session->pdusession_id, n3_incoming->teid, ip_str);
/* we assume for the moment one DRB per PDU session. Activate the bearer,
* and configure in RRC. */
@@ -480,7 +385,7 @@ static void send_ngap_initial_context_setup_resp_fail(instance_t instance,
resp->gNB_ue_ngap_id = msg->gNB_ue_ngap_id;
for (int i = 0; i < msg->nb_of_pdusessions; i++) {
fill_pdu_session_resource_failed_to_setup_item(&resp->pdusessions_failed[i], msg->pdusession_param[i].pdusession_id, cause);
fill_pdu_session_resource_failed_to_setup_item(&resp->pdusessions_failed[i], msg->pdusession[i].pdusession_id, cause);
}
resp->nb_of_pdusessions = 0;
resp->nb_of_pdusessions_failed = msg->nb_of_pdusessions;
@@ -519,10 +424,9 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
/* if there are PDU sessions to setup, store them to be created once
* security (and UE capabilities) are received */
UE->n_initial_pdu = req->nb_of_pdusessions;
UE->initial_pdus = calloc(UE->n_initial_pdu, sizeof(*UE->initial_pdus));
AssertFatal(UE->initial_pdus != NULL, "out of memory\n");
UE->initial_pdus = calloc_or_fail(UE->n_initial_pdu, sizeof(*UE->initial_pdus));
for (int i = 0; i < UE->n_initial_pdu; ++i)
UE->initial_pdus[i] = req->pdusession_param[i];
cp_pdusession_resource_item_to_pdusession(&UE->initial_pdus[i], &req->pdusession[i]);
}
/* security */
@@ -567,6 +471,15 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
return 0;
}
static gtpu_tunnel_t cp_gtp_tunnel(const gtpu_tunnel_t in)
{
gtpu_tunnel_t out = {0};
out.teid = in.teid;
out.addr.length = in.addr.length;
memcpy(out.addr.buffer, in.addr.buffer, out.addr.length);
return out;
}
void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE)
{
MessageDef *msg_p = NULL;
@@ -582,11 +495,7 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_
if (session->status == PDU_SESSION_STATUS_DONE) {
pdu_sessions_done++;
resp->pdusessions[pdusession].pdusession_id = session->param.pdusession_id;
resp->pdusessions[pdusession].gtp_teid = session->param.gNB_teid_N3;
memcpy(resp->pdusessions[pdusession].gNB_addr.buffer,
session->param.gNB_addr_N3.buffer,
sizeof(resp->pdusessions[pdusession].gNB_addr.buffer));
resp->pdusessions[pdusession].gNB_addr.length = 4; // Fixme: IPv4 hard coded here
resp->pdusessions[pdusession].n3_outgoing = cp_gtp_tunnel(session->param.n3_outgoing);
resp->pdusessions[pdusession].nb_of_qos_flow = session->param.nb_qos;
for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) {
resp->pdusessions[pdusession].associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi;
@@ -777,25 +686,18 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
pdusession_setup_t *tmp = &resp->pdusessions[pdu_sessions_done];
tmp->pdusession_id = session->param.pdusession_id;
tmp->nb_of_qos_flow = session->param.nb_qos;
tmp->gtp_teid = session->param.gNB_teid_N3;
tmp->n3_outgoing = cp_gtp_tunnel(session->param.n3_outgoing);
tmp->pdu_session_type = session->param.pdu_session_type;
tmp->gNB_addr.length = session->param.gNB_addr_N3.length;
memcpy(tmp->gNB_addr.buffer, session->param.gNB_addr_N3.buffer, tmp->gNB_addr.length);
for (int qos_flow_index = 0; qos_flow_index < tmp->nb_of_qos_flow; qos_flow_index++) {
tmp->associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi;
tmp->associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
}
session->status = PDU_SESSION_STATUS_ESTABLISHED;
LOG_I(NR_RRC,
"msg index %d, pdu_sessions index %d, status %d, xid %d): nb_of_pdusessions %d, pdusession_id %d, teid: %u \n ",
pdu_sessions_done,
pdusession,
session->status,
xid,
UE->nb_of_pdusessions,
tmp->pdusession_id,
tmp->gtp_teid);
char ip_str[INET_ADDRSTRLEN] = {0};
inet_ntop(AF_INET, tmp->n3_outgoing.addr.buffer, ip_str, sizeof(ip_str));
LOG_I(NR_RRC, "PDU Session Setup Response: ID=%d, outgoing TEID=0x%08x, Addr=%s\n", tmp->pdusession_id, tmp->n3_outgoing.teid, ip_str);
pdu_sessions_done++;
} else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) {
session->status = PDU_SESSION_STATUS_FAILED;
@@ -807,10 +709,6 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
}
resp->nb_of_pdusessions = pdu_sessions_done;
resp->nb_of_pdusessions_failed = pdu_sessions_failed;
// } else {
// LOG_D(NR_RRC,"xid does not corresponds (context pdu_sessions index %d, status %d, xid %d/%d) \n ",
// pdusession, UE->pdusession[pdusession].status, xid, UE->pdusession[pdusession].xid);
// }
}
if ((pdu_sessions_done > 0 || pdu_sessions_failed)) {
@@ -860,9 +758,7 @@ static void send_ngap_pdu_session_setup_resp_fail(instance_t instance, ngap_pdus
resp->nb_of_pdusessions_failed = msg->nb_pdusessions_tosetup;
resp->nb_of_pdusessions = 0;
for (int i = 0; i < resp->nb_of_pdusessions_failed; ++i) {
fill_pdu_session_resource_failed_to_setup_item(&resp->pdusessions_failed[i],
msg->pdusession_setup_params[i].pdusession_id,
cause);
fill_pdu_session_resource_failed_to_setup_item(&resp->pdusessions_failed[i], msg->pdusession[i].pdusession_id, cause);
}
itti_send_msg_to_task(TASK_NGAP, instance, msg_resp);
}
@@ -908,7 +804,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
// At least one because marking one as existing, and setting up another, that
// might be more work than is worth it. See 8.2.1.4 in 38.413
for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) {
const pdusession_t *p = &msg->pdusession_setup_params[i];
const pdusession_resource_item_t *p = &msg->pdusession[i];
rrc_pdu_session_param_t *exist = find_pduSession(UE, p->pdusession_id, false /* don't create */);
if (exist) {
LOG_E(NR_RRC, "UE %d: already has existing PDU session %d rejecting PDU Session Resource Setup Request\n", UE->rrc_ue_id, p->pdusession_id);
@@ -941,7 +837,11 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
return;
}
if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession_setup_params, msg->ueAggMaxBitRate.br_dl)) {
pdusession_t to_setup[NGAP_MAX_PDU_SESSION] = {0};
for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i)
cp_pdusession_resource_item_to_pdusession(&to_setup[i], &msg->pdusession[i]);
if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, msg->ueAggMaxBitRate.br_dl)) {
// Reject PDU Session Resource setup if there's no CU-UP associated
LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id);
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE};
@@ -952,104 +852,6 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
}
}
static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *session)
{
// we need to duplicate the function fill_qos because all data types are slightly different
DevAssert(qos->list.count > 0);
DevAssert(qos->list.count <= NGAP_maxnoofQosFlows);
for (int qosIdx = 0; qosIdx < qos->list.count; qosIdx++) {
NGAP_QosFlowAddOrModifyRequestItem_t *qosFlowItem_p = qos->list.array[qosIdx];
// Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics;
AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx);
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = NON_DYNAMIC;
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
} else {
AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = DYNAMIC;
session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI);
}
ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority;
NGAP_AllocationAndRetentionPriority_t *tmp2 = &qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority;
tmp->priority_level = tmp2->priorityLevelARP;
tmp->pre_emp_capability = tmp2->pre_emptionCapability;
tmp->pre_emp_vulnerability = tmp2->pre_emptionVulnerability;
}
session->nb_qos = qos->list.count;
}
static void decodePDUSessionResourceModify(pdusession_t *param, const byte_array_t pdu)
{
NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer = NULL;
asn_dec_rval_t dec_rval = aper_decode(NULL,
&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,
(void **)&pdusessionTransfer,
pdu.buf,
pdu.len,
0,
0);
if (dec_rval.code != RC_OK) {
LOG_E(NR_RRC, "could not decode PDUSessionResourceModifyRequestTransfer\n");
return;
}
for (int j = 0; j < pdusessionTransfer->protocolIEs.list.count; j++) {
NGAP_PDUSessionResourceModifyRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[j];
switch (pdusessionTransfer_ies->id) {
/* optional PDUSessionAggregateMaximumBitRate */
case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate\n");
break;
/* optional UL-NGU-UP-TNLModifyList */
case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList\n");
break;
/* optional NetworkInstance */
case NGAP_ProtocolIE_ID_id_NetworkInstance:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_NetworkInstance\n");
break;
/* optional QosFlowAddOrModifyRequestList */
case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList:
fill_qos2(&pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList, param);
break;
/* optional QosFlowToReleaseList */
case NGAP_ProtocolIE_ID_id_QosFlowToReleaseList:
// TODO
LOG_E(NR_RRC, "Can't handle NGAP_ProtocolIE_ID_id_QosFlowToReleaseList\n");
break;
/* optional AdditionalUL-NGU-UP-TNLInformation */
case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation\n");
break;
/* optional CommonNetworkInstance */
case NGAP_ProtocolIE_ID_id_CommonNetworkInstance:
// TODO
LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_CommonNetworkInstance\n");
break;
default:
LOG_E(NR_RRC, "could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id);
return;
}
}
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,pdusessionTransfer );
}
//------------------------------------------------------------------------------
int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t instance)
//------------------------------------------------------------------------------
@@ -1069,7 +871,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
bool all_failed = true;
for (int i = 0; i < req->nb_pdusessions_tomodify; i++) {
rrc_pdu_session_param_t *sess;
const pdusession_t *sessMod = req->pdusession_modify_params + i;
const pdusession_resource_item_t *sessMod = req->pdusession + i;
for (sess = UE->pduSession; sess < UE->pduSession + UE->nb_of_pdusessions; sess++)
if (sess->param.pdusession_id == sessMod->pdusession_id)
break;
@@ -1093,10 +895,8 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
if (sessMod->nas_pdu.buf != NULL) {
UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu;
}
// Save new pdu session parameters, qos, upf addr, teid
decodePDUSessionResourceModify(&sess->param, UE->pduSession[i].param.pdusessionTransfer);
sess->param.UPF_addr_N3 = sessMod->upf_addr;
sess->param.UPF_teid_N3 = sessMod->gtp_teid;
for (int i = 0; i < req->nb_pdusessions_tomodify; ++i)
cp_pdusession_resource_item_to_pdusession(&UE->pduSession[i].param, &req->pdusession[i]);
}
}
@@ -1457,16 +1257,6 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
return 0;
}
void nr_rrc_rx_tx(void) {
// check timers
// check if UEs are lost, to remove them from upper layers
//
}
/*------------------------------------------------------------------------------*/
int rrc_gNB_process_PAGING_IND(MessageDef *msg_p, instance_t instance)
{
for (uint16_t tai_size = 0; tai_size < NGAP_PAGING_IND(msg_p).tai_size; tai_size++) {

View File

@@ -32,6 +32,15 @@
#include "oai_asn1.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h"
/** @brief Deep copy pdusession_t */
void cp_pdusession(pdusession_t *dst, const pdusession_t *src)
{
// Shallow copy
*dst = *src;
// nas_pdu
dst->nas_pdu = copy_byte_array(src->nas_pdu);
}
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create)
{
int j;
@@ -208,11 +217,3 @@ int get_number_active_drbs(gNB_RRC_UE_t *ue)
n++;
return n;
}
bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id)
{
drb_t *drb = get_drb(ue, drb_id);
if (drb == NULL)
return DRB_INACTIVE;
return drb->status != DRB_INACTIVE;
}

View File

@@ -65,9 +65,6 @@ uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue);
/// @brief returns the number of active DRBs for this UE
int get_number_active_drbs(gNB_RRC_UE_t *ue);
/// @brief check if DRB with ID drb_id of UE ue is active
bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id);
/// @brief retrieve PDU session of UE ue with ID id, optionally creating it if
/// create is true
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create);
@@ -81,4 +78,7 @@ void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_S
/// @brief set PDCP configuration in a bearer context management message
void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb);
/// @brief Deep copy an instance of struct pdusession_t
void cp_pdusession(pdusession_t *dst, const pdusession_t *src);
#endif

View File

@@ -344,14 +344,6 @@ void *ngap_gNB_process_itti_msg(void *notUsed) {
ngap_gNB_nas_non_delivery_ind(instance, &NGAP_NAS_NON_DELIVERY_IND(received_msg));
break;
case NGAP_PATH_SWITCH_REQ:
ngap_gNB_path_switch_req(instance, &NGAP_PATH_SWITCH_REQ(received_msg));
break;
case NGAP_PDUSESSION_MODIFICATION_IND:
ngap_gNB_generate_PDUSESSION_Modification_Indication(instance, &NGAP_PDUSESSION_MODIFICATION_IND(received_msg));
break;
case NGAP_UE_CONTEXT_RELEASE_COMPLETE:
ngap_ue_context_release_complete(instance, &NGAP_UE_CONTEXT_RELEASE_COMPLETE(received_msg));
break;

View File

@@ -694,6 +694,99 @@ static int ngap_gNB_handle_error_indication(sctp_assoc_t assoc_id, uint32_t stre
return 0;
}
static void *decode_pdusession_transfer(const asn_TYPE_descriptor_t *td, const OCTET_STRING_t buf)
{
void *decoded = NULL;
asn_codec_ctx_t ctx = {.max_stack_size = 100 * 1000};
asn_dec_rval_t rval = aper_decode(&ctx, td, &decoded, buf.buf, buf.size, 0, 0);
if (rval.code != RC_OK) {
NGAP_ERROR("Decoding failed for %s\n", td->name);
return NULL;
}
return decoded;
}
static pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params)
{
pdusession_level_qos_parameter_t out = {0};
// QFI
out.qfi = qfi;
AssertFatal(params != NULL, "QoS parameters are NULL\n");
// QosCharacteristics
const NGAP_QosCharacteristics_t *qosChar = &params->qosCharacteristics;
AssertFatal(qosChar != NULL, "QoS characteristics are NULL\n");
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
AssertFatal(qosChar->choice.nonDynamic5QI != NULL, "nonDynamic5QI is NULL\n");
out.fiveQI_type = NON_DYNAMIC;
out.fiveQI = qosChar->choice.nonDynamic5QI->fiveQI;
} else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) {
AssertFatal(qosChar->choice.dynamic5QI != NULL, "dynamic5QI is NULL\n");
out.fiveQI_type = DYNAMIC;
out.fiveQI = *qosChar->choice.dynamic5QI->fiveQI;
} else {
AssertFatal(0, "Unsupported QoS Characteristics present value: %d\n", qosChar->present);
}
// Allocation and Retention Priority
const NGAP_AllocationAndRetentionPriority_t *arp = &params->allocationAndRetentionPriority;
out.allocation_retention_priority.priority_level = arp->priorityLevelARP;
out.allocation_retention_priority.pre_emp_capability = arp->pre_emptionCapability;
out.allocation_retention_priority.pre_emp_vulnerability = arp->pre_emptionVulnerability;
return out;
}
static gtpu_tunnel_t decode_TNLInformation(const NGAP_GTPTunnel_t *gTPTunnel_p)
{
gtpu_tunnel_t out = {0};
// Transport layer address
memcpy(out.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size);
out.addr.length = gTPTunnel_p->transportLayerAddress.size - gTPTunnel_p->transportLayerAddress.bits_unused;
// GTP tunnel endpoint ID
OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out.teid);
return out;
}
/** @brief Decode PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */
static bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRING_t in)
{
void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, in);
if (!decoded) {
LOG_E(NR_RRC, "Failed to decode PDUSessionResourceSetupRequestTransfer\n");
return false;
}
NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = (NGAP_PDUSessionResourceSetupRequestTransfer_t *)decoded;
for (int i = 0; i < pdusessionTransfer->protocolIEs.list.count; i++) {
NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[i];
switch (pdusessionTransfer_ies->id) {
// UL NG-U UP TNL Information (Mandatory)
case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation:
out->n3_incoming = decode_TNLInformation(pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel);
break;
// PDU Session Type (Mandatory)
case NGAP_ProtocolIE_ID_id_PDUSessionType:
out->pdu_session_type = pdusessionTransfer_ies->value.choice.PDUSessionType;
break;
// QoS Flow Setup Request List (Mandatory)
case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList:
out->nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count;
for (int i = 0; i < out->nb_qos; i++) {
NGAP_QosFlowSetupRequestItem_t *item = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[i];
out->qos[i] = fill_qos(item->qosFlowIdentifier, &item->qosFlowLevelQosParameters);
}
break;
default:
LOG_D(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id);
}
}
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, pdusessionTransfer);
return true;
}
static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
int i;
@@ -762,13 +855,16 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
for (i = 0; i < ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; i++) {
NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i];
msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID;
msg->pdusession_param[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI);
msg->pdusession[i].pdusession_id = item_p->pDUSessionID;
msg->pdusession[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI);
if (item_p->nAS_PDU) {
msg->pdusession_param[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
msg->pdusession[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
}
bool ret = decodePDUSessionResourceSetup(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
if (!ret) {
NGAP_ERROR("Failed to decode pDUSessionResourceSetupRequestTransfer in NG Initial Context Setup Request\n");
return -1;
}
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer;
msg->pdusession_param[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
}
}
@@ -936,16 +1032,19 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3
for (int i = 0; i < ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; i++) {
NGAP_PDUSessionResourceSetupItemSUReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListSUReq.list.array[i];
msg->pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID;
msg->pdusession[i].pdusession_id = item_p->pDUSessionID;
// S-NSSAI
msg->pdusession_setup_params[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI);
msg->pdusession[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI);
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer;
msg->pdusession_setup_params[i].nas_pdu = create_byte_array(item_p->pDUSessionNAS_PDU->size, item_p->pDUSessionNAS_PDU->buf);
msg->pdusession_setup_params[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
msg->pdusession[i].nas_pdu = create_byte_array(item_p->pDUSessionNAS_PDU->size, item_p->pDUSessionNAS_PDU->buf);
bool ret = decodePDUSessionResourceSetup(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
if (!ret) {
NGAP_ERROR("Failed to decode pDUSessionResourceSetupRequestTransfer in NG Setup Request\n");
return -1;
}
}
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
return 0;
}
@@ -1039,6 +1138,37 @@ static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_N
return 0;
}
static bool decodePDUSessionResourceModify(pdusession_transfer_t *out, const OCTET_STRING_t in)
{
void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, in);
if (!decoded) {
LOG_E(NR_RRC, "Failed to decode PDUSessionResourceModifyRequestTransfer\n");
return false;
}
NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer = (NGAP_PDUSessionResourceModifyRequestTransfer_t *)decoded;
for (int j = 0; j < pdusessionTransfer->protocolIEs.list.count; j++) {
NGAP_PDUSessionResourceModifyRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[j];
switch (pdusessionTransfer_ies->id) {
/* optional QosFlowAddOrModifyRequestList */
case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList:
out->nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count;
for (int i = 0; i < out->nb_qos; i++) {
NGAP_QosFlowAddOrModifyRequestItem_t *item =
pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[i];
out->qos[i] = fill_qos(item->qosFlowIdentifier, item->qosFlowLevelQosParameters);
}
break;
default:
LOG_E(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id);
return false;
}
}
ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer);
return true;
}
static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
ngap_gNB_amf_data_t *amf_desc_p = NULL;
@@ -1116,13 +1246,15 @@ static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint
for (int i = 0; i < ie->value.choice.PDUSessionResourceModifyListModReq.list.count; i++) {
NGAP_PDUSessionResourceModifyItemModReq_t *item_p = ie->value.choice.PDUSessionResourceModifyListModReq.list.array[i];
msg->pdusession_modify_params[i].pdusession_id = item_p->pDUSessionID;
msg->pdusession[i].pdusession_id = item_p->pDUSessionID;
// check for the NAS PDU
if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0) {
msg->pdusession_modify_params[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceModifyRequestTransfer;
msg->pdusession_modify_params[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
msg->pdusession[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
if (!decodePDUSessionResourceModify(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceModifyRequestTransfer)) {
NGAP_ERROR("Failed to decode pDUSessionResourceModifyRequestTransfer\n");
return -1;
}
} else {
LOG_W(NGAP, "received pdu session modify with void content for UE %u, pdu session %lu\n", msg->gNB_ue_ngap_id, item_p->pDUSessionID);
continue;

View File

@@ -35,6 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include "BIT_STRING.h"
#include "INTEGER.h"
#include "ngap_msg_includes.h"
@@ -57,6 +58,7 @@
#include "oai_asn1.h"
#include "s1ap_messages_types.h"
#include "xer_encoder.h"
#include "ds/byte_array.h"
/** @brief Selects the AMF instance for a given UE based on identity information.
* It attempts to select an AMF using the following prioritized criteria:
@@ -537,6 +539,46 @@ 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, &gtp->gTP_TEID);
tnl_to_bitstring(&gtp->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;
}
//------------------------------------------------------------------------------
int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p)
//------------------------------------------------------------------------------
@@ -606,39 +648,10 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceSetupListCxtRes.list, NGAP_PDUSessionResourceSetupItemCxtRes_t, item);
/* pDUSessionID */
item->pDUSessionID = initial_ctxt_resp_p->pdusessions[i].pdusession_id;
/* dLQosFlowPerTNLInformation */
NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0};
pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
asn1cCalloc(pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel, tmp);
GTP_TEID_TO_ASN1(initial_ctxt_resp_p->pdusessions[i].gtp_teid, &tmp->gTP_TEID);
tnl_to_bitstring(&tmp->transportLayerAddress, initial_ctxt_resp_p->pdusessions[i].gNB_addr);
NGAP_DEBUG("initial_ctxt_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld, TEID %u\n",
item->pDUSessionID,
tmp->transportLayerAddress.buf[0],
tmp->transportLayerAddress.buf[1],
tmp->transportLayerAddress.buf[2],
tmp->transportLayerAddress.buf[3],
tmp->transportLayerAddress.size,
initial_ctxt_resp_p->pdusessions[i].gtp_teid);
/* associatedQosFlowList. number of 1? */
for(int j=0; j < initial_ctxt_resp_p->pdusessions[i].nb_of_qos_flow; j++) {
asn1cSequenceAdd(pdusessionTransfer.dLQosFlowPerTNLInformation.associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, ass_qos_item_p);
/* qosFlowIdentifier */
ass_qos_item_p->qosFlowIdentifier = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qfi;
}
void *pdusessionTransfer_buffer;
ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, NULL, &pdusessionTransfer, &pdusessionTransfer_buffer);
AssertFatal(encoded > 0, "ASN1 message encoding failed !\n");
item->pDUSessionResourceSetupResponseTransfer.buf = pdusessionTransfer_buffer;
item->pDUSessionResourceSetupResponseTransfer.size = encoded;
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer);
// PDU Session Resource Setup Response Transfer (Mandatory)
byte_array_t ba = encode_ngap_pdusession_setup_response_transfer(&initial_ctxt_resp_p->pdusessions[i]);
item->pDUSessionResourceSetupResponseTransfer.buf = ba.buf;
item->pDUSessionResourceSetupResponseTransfer.size = ba.len;
}
}
/* optional */
@@ -924,40 +937,10 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_re
/* pDUSessionID */
item->pDUSessionID = pdusession->pdusession_id;
/* dLQosFlowPerTNLInformation */
NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0};
pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
asn1cCalloc(pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel, tmp);
GTP_TEID_TO_ASN1(pdusession->gtp_teid, &tmp->gTP_TEID);
tnl_to_bitstring(&tmp->transportLayerAddress, pdusession->gNB_addr);
NGAP_DEBUG("pdusession_setup_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld, TEID %u\n",
item->pDUSessionID,
tmp->transportLayerAddress.buf[0],
tmp->transportLayerAddress.buf[1],
tmp->transportLayerAddress.buf[2],
tmp->transportLayerAddress.buf[3],
tmp->transportLayerAddress.size,
pdusession->gtp_teid);
/* associatedQosFlowList. number of 1? */
for(int j=0; j < pdusession_setup_resp_p->pdusessions[i].nb_of_qos_flow; j++) {
asn1cSequenceAdd(pdusessionTransfer.dLQosFlowPerTNLInformation.associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, ass_qos_item_p);
/* qosFlowIdentifier */
ass_qos_item_p->qosFlowIdentifier = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qfi;
/* qosFlowMappingIndication */
// if(pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) {
// ass_qos_item_p->qosFlowMappingIndication = malloc(sizeof(*ass_qos_item_p->qosFlowMappingIndication));
// *ass_qos_item_p->qosFlowMappingIndication = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind;
// }
}
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);
item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer;
item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded;
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer);
// 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;
}
}
@@ -1225,17 +1208,3 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas
return 0;
}
int ngap_gNB_path_switch_req(instance_t instance, ngap_path_switch_req_t *path_switch_req_p)
//------------------------------------------------------------------------------
{
//TODO
return 0;
}
int ngap_gNB_generate_PDUSESSION_Modification_Indication(instance_t instance, ngap_pdusession_modification_ind_t *pdusession_modification_ind)
//-----------------------------------------------------------------------------
{
//TODO
return 0;
}

View File

@@ -63,10 +63,4 @@ int ngap_gNB_pdusession_modify_resp(instance_t instance,
int ngap_gNB_pdusession_release_resp(instance_t instance,
ngap_pdusession_release_resp_t *pdusession_release_resp_p);
int ngap_gNB_path_switch_req(instance_t instance,
ngap_path_switch_req_t *path_switch_req_p);
int ngap_gNB_generate_PDUSESSION_Modification_Indication(
instance_t instance, ngap_pdusession_modification_ind_t *pdusession_modification_ind);
#endif /* NGAP_GNB_NAS_PROCEDURES_H_ */

View File

@@ -71,5 +71,12 @@
#include "NGAP_UnsuccessfulOutcome.h"
#include "NGAP_UserLocationInformationNR.h"
#include "NGAP_asn_constant.h"
#include "NGAP_PDUSessionResourceSetupRequestTransfer.h"
#include "NGAP_QosFlowSetupRequestItem.h"
#include "NGAP_QosCharacteristics.h"
#include "NGAP_NonDynamic5QIDescriptor.h"
#include "NGAP_Dynamic5QIDescriptor.h"
#include "NGAP_PDUSessionResourceModifyRequestTransfer.h"
#include "NGAP_QosFlowAddOrModifyRequestItem.h"
#endif // NGAP_MSG_INCLUDES_H

View File

@@ -897,7 +897,8 @@ int gtpv1u_delete_all_s1u_tunnel(const instance_t instance, const rnti_t rnti)
return newGtpuDeleteAllTunnels(instance, rnti);
}
int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id) {
int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id)
{
LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n",
instance, ue_id);
pthread_mutex_lock(&globGtp.gtp_lock);

View File

@@ -103,7 +103,7 @@ extern "C" {
int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id);
int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id);
int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id);
int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id);
void gtpv1uSendDirect(instance_t instance, ue_id_t ue_id, int bearer_id, uint8_t *buf, size_t len, bool seqNumFlag, bool npduNumFlag);