diff --git a/common/5g_platform_types.h b/common/5g_platform_types.h index a5b7b7a1fc..b46490a2e8 100644 --- a/common/5g_platform_types.h +++ b/common/5g_platform_types.h @@ -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 diff --git a/common/platform_types.h b/common/platform_types.h index e345288061..9827dba974 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -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; //----------------------------------------------------------------------------- // diff --git a/common/utils/ds/seq_arr.c b/common/utils/ds/seq_arr.c index 708552a24e..50a332a16b 100644 --- a/common/utils/ds/seq_arr.c +++ b/common/utils/ds/seq_arr.c @@ -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); } } diff --git a/common/utils/ds/tests/test_seq_array.c b/common/utils/ds/tests/test_seq_array.c index 28a7c98b1e..e06f72c881 100644 --- a/common/utils/ds/tests/test_seq_array.c +++ b/common/utils/ds/tests/test_seq_array.c @@ -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); diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 5f12d1e9a2..30471c9c4f 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -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_ */ diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 62498698f2..4f05a564c4 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -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 ) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index b899bb33e2..2ad2db97bd 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -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 { diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c index 31d96433c1..158c126c39 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -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) { diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index f2434eceaf..804657e8ce 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -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 { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2ef11ce605..520dc469d0 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -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); } } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 9fd4306962..72aad97750 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -36,6 +36,7 @@ #include #include #include +#include #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++) { diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index e22ee7ffd6..7bed45ee64 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -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; -} diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 4a249496ff..1eac60a609 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -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 diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index ae8d806e18..8edb5c3aa3 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -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; diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 3f6b718861..f4c4ebb20f 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -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 = ¶ms->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 = ¶ms->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; diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index b00ce13f32..1aafeca8c9 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -35,6 +35,7 @@ #include #include #include +#include #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, >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; +} + //------------------------------------------------------------------------------ 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; -} diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.h b/openair3/NGAP/ngap_gNB_nas_procedures.h index 3cd03838b4..5189e6b311 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.h +++ b/openair3/NGAP/ngap_gNB_nas_procedures.h @@ -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_ */ diff --git a/openair3/NGAP/ngap_msg_includes.h b/openair3/NGAP/ngap_msg_includes.h index c7ef77be6a..1debc2e9f1 100644 --- a/openair3/NGAP/ngap_msg_includes.h +++ b/openair3/NGAP/ngap_msg_includes.h @@ -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 diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index fd571e8d0e..58be5ed638 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -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); diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index d5226bb972..7a8c4da627 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -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);