diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 236913d3f8..67da0bb428 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -125,7 +125,7 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); } void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); } -void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) { abort(); } +void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { abort(); } void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd) { abort(); } int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { diff --git a/openair1/SIMULATION/NR_PHY/psbchsim.c b/openair1/SIMULATION/NR_PHY/psbchsim.c index 972605fc96..f5b0f88ab2 100644 --- a/openair1/SIMULATION/NR_PHY/psbchsim.c +++ b/openair1/SIMULATION/NR_PHY/psbchsim.c @@ -51,7 +51,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); } -void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) +void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { abort(); } diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 301beb19f5..5f2b7ce6c9 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -126,7 +126,7 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); } -void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) { abort(); } +void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { abort(); } void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd) { abort(); } int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 458cfc1f46..2f59cb62d6 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -252,10 +252,16 @@ typedef struct e1ap_setup_fail_s { criticality_diagnostics_t *crit_diag; } e1ap_setup_fail_t; -typedef struct up_params_s { +typedef struct UP_TL_information_s { in_addr_t tlAddress; - long teId; - int cell_group_id; + int32_t teId; +} UP_TL_information_t; + +typedef struct up_params_s { + // Transport layer info + UP_TL_information_t tl_info; + // Cell Group ID (M) + cell_group_id_t cell_group_id; } up_params_t; /* IE SDAP Configuration (clause 9.3.1.39 of 3GPP TS 38.463) */ @@ -325,38 +331,63 @@ typedef struct qos_flow_level_qos_parameters_s { ngran_allocation_retention_priority_t alloc_reten_priority; // additional members should be added!! } qos_flow_level_qos_parameters_t; +// QoS Flow QoS Parameters List 9.3.1.25 typedef struct qos_flow_setup_e { long qfi; // qos flow identifier qos_flow_level_qos_parameters_t qos_params; } qos_flow_to_setup_t; -/* DRB To Setup List according to 3GPP TS 38.463 */ +// 9.3.1.60 QoS Flow Mapping Indication +typedef enum qos_flow_mapping_indication_e { + QF_UL = 0, + QF_DL, + QF_BOTH +} qos_flow_mapping_indication_t; + +typedef struct qos_flow_list_s { + long qfi; // qos flow identifier + qos_flow_mapping_indication_t *indication; +} qos_flow_list_t; + +/** + * DRB To Setup List according to 3GPP TS 38.463 + */ typedef struct DRB_nGRAN_to_setup_s { - /* DRB ID (clause 9.3.1.16) */ + // DRB ID (M) (clause 9.3.1.16) long id; - - /* SDAP Configuration (clause 9.3.1.39) */ + // SDAP Configuration (M) (clause 9.3.1.39) bearer_context_sdap_config_t sdap_config; - /* PDCP Configuration (clause 9.3.1.38) */ + // PDCP Configuration (M) (clause 9.3.1.38) bearer_context_pdcp_config_t pdcp_config; - - /* DRB Data Forwarding Information (clause 9.3.2.6) */ - /* Transport Layer Address (clause 9.3.2.4) */ - in_addr_t tlAddress; - /* GTP-TEID (clause 9.3.2.3) */ - int teId; - /* DL UP Transport Layer Information (clause 9.3.2.1) */ - int numDlUpParam; - up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM]; - - /* Cell Group Information (clause 9.3.1.11) */ + // DRB Inactivity Timer (O) + int *drb_inactivity_timer; + // Cell Group Information (M) (clause 9.3.1.11) int numCellGroups; cell_group_id_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; - - /* DRB QoS Flows Parameters (clause 9.3.1.26) */ + // QoS Flows Information To Be Setup (M) (clause 9.3.1.25, 9.3.1.26) int numQosFlow2Setup; qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; -} DRB_nGRAN_to_setup_t, DRB_nGRAN_to_mod_t; +} DRB_nGRAN_to_setup_t; + +/** + * DRB To Modify List according to 3GPP TS 38.463 + */ +typedef struct DRB_nGRAN_to_modify_s { + // DRB ID (M) (clause 9.3.1.16) + long id; + // SDAP Configuration (O) (clause 9.3.1.39) + bearer_context_sdap_config_t *sdap_config; + // PDCP Configuration (O) (clause 9.3.1.38) + bearer_context_pdcp_config_t *pdcp_config; + // PDCP SN Status Request (O) + bool pdcp_sn_status_requested; + // DL UP Transport Layer Information (O) (clause 9.3.1.13, 9.3.2.1) + int numDlUpParam; + up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM]; + // QoS Flows Information To Modify (O) (clause 9.3.1.25, 9.3.1.26) + int numQosFlow2Setup; + qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; +} DRB_nGRAN_to_mod_t; typedef enum e1ap_indication_e { SECURITY_REQUIRED = 0, @@ -371,47 +402,108 @@ typedef struct security_indication_s { long maxIPrate; } security_indication_t; -typedef struct UP_TL_information_s { - in_addr_t tlAddress; - int32_t teId; -} UP_TL_information_t; - -/** - * PDU Session Resource To Setup List (clause 9.3.3.10) - * PDU Session Resource To Modify List (clause 9.3.3.11) -*/ -typedef struct pdu_session_to_setup_s { - long sessionId; - long sessionType; - e1ap_nssai_t nssai; - security_indication_t securityIndication; - UP_TL_information_t UP_TL_information; - long numDRB2Setup; - DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS]; - long numDRB2Modify; - DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; -} pdu_session_to_setup_t, pdu_session_to_mod_t; - -/** - * Bearer Context Setup Request message, clause 9.2.2.1 of 3GPP TS 38.463 - * out of simplicity, this same struct is used for clause 9.2.2.4 - * i.e. Bearer Context Modification Request message - */ -typedef struct e1ap_bearer_setup_req_s { - uint32_t gNB_cu_cp_ue_id; - uint32_t gNB_cu_up_ue_id; // Bearer Context Modification Request only +// Security Information (9.3.1.10) +typedef struct security_information_s { uint64_t cipheringAlgorithm; uint64_t integrityProtectionAlgorithm; char encryptionKey[E1AP_SECURITY_KEY_SIZE]; char integrityProtectionKey[E1AP_SECURITY_KEY_SIZE]; - long ueDlAggMaxBitRate; +} security_information_t; + +/** + * PDU Session Resource To Setup List (clause 9.3.3.10) + */ +typedef struct pdu_session_to_setup_s { + // PDU Session ID (M) + long sessionId; + // PDU Session Type (M) + long sessionType; + // S-NSSAI (M) + e1ap_nssai_t nssai; + // Security Indication (M) + security_indication_t securityIndication; + // PDU Session Resource DL Aggregate Maximum Bit Rate (O) + long *dlAggregateMaxBitRate; + // NG UL UP Transport Layer Information (M) + UP_TL_information_t UP_TL_information; + // PDU Session Inactivity Timer (O) + int *inactivityTimer; + // DRB To Setup List (M) + int numDRB2Setup; + // DRB To Setup Item (1..) + DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS]; +} pdu_session_to_setup_t; + +/** + * PDU Session Resource To Modify List (clause 9.3.3.11) + */ +typedef struct pdu_session_to_mod_s { + // PDU Session ID (M) + long sessionId; + // Security Indication (O) + security_indication_t *securityIndication; + // NG UL UP Transport Layer Information (O) + UP_TL_information_t *UP_TL_information; + // DRB To Setup List (0..1) + int numDRB2Setup; + // DRB To Setup Item (1..) + DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS]; + // DRB To Modify List (0..1) + long numDRB2Modify; + // DRB To Modify Item (1..) + DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; +} pdu_session_to_mod_t; + +/** + * Bearer Context Setup Request message, clause 9.2.2.1 of 3GPP TS 38.463 + */ +typedef struct e1ap_bearer_setup_req_s { + // gNB-CU-CP UE E1AP ID (M) + uint32_t gNB_cu_cp_ue_id; + // Security Information (M) + security_information_t secInfo; + // UE DL Aggregate Maximum Bit Rate (M) + long ueDlAggMaxBitRate; + // UE DL Maximum Integrity Protected Data Rate (O) + long *ueDlMaxIPBitRate; + // Serving PLMN (M) PLMN_ID_t servingPLMNid; + // Bearer Context Status Change (O) BEARER_CONTEXT_STATUS_t bearerContextStatus; + // UE Inactivity Timer (O) + int *inactivityTimerUE; + // NG-RAN PDU Session Resource To Setup List (M) int numPDUSessions; pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; +} e1ap_bearer_setup_req_t; + +/** + * Bearer Context Modification Request, clause 9.2.2.4 of 3GPP TS 38.463 + */ +typedef struct e1ap_bearer_mod_req_s { + // gNB-CU-CP UE E1AP ID (M) + uint32_t gNB_cu_cp_ue_id; + // gNB-CU-UP UE E1AP ID (M) + uint32_t gNB_cu_up_ue_id; + // Security Information (O) + security_information_t *secInfo; + // UE DL Aggregate Maximum Bit Rate (O) + uint32_t *ueDlAggMaxBitRate; + // UE DL Maximum Integrity Protected Data Rate (O) + uint32_t *ueDlMaxIPBitRate; + // Bearer Context Status Change (O) + BEARER_CONTEXT_STATUS_t *bearerContextStatus; + // UE Inactivity Timer (O) + int *inactivityTimer; + // Data Discard Required (O) + bool dataDiscardRequired; + // NG-RAN PDU Session Resource To Setup List (O) + int numPDUSessions; + pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; + // NG-RAN PDU Session Resource To Modify List (O) int numPDUSessionsMod; pdu_session_to_mod_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; -} e1ap_bearer_setup_req_t, e1ap_bearer_mod_req_t; +} e1ap_bearer_mod_req_t; typedef struct e1ap_bearer_release_cmd_s { uint32_t gNB_cu_cp_ue_id; @@ -425,43 +517,61 @@ typedef struct e1ap_bearer_release_cplt_s { uint32_t gNB_cu_up_ue_id; } e1ap_bearer_release_cplt_t; -typedef struct qos_flow_setup_s { - long qfi; -} qos_flow_setup_t; - typedef struct DRB_nGRAN_setup_s { + // DRB ID (M) long id; int numUpParam; up_params_t UpParamList[E1AP_MAX_NUM_UP_PARAM]; + // Flow Setup List (M) int numQosFlowSetup; - qos_flow_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; + qos_flow_list_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; } DRB_nGRAN_setup_t; +/* DRB Modified Item */ typedef struct DRB_nGRAN_modified_s { + // DRB ID (M) long id; + // UL UP Parameters (O) + int numUpParam; + up_params_t ul_UP_Params[E1AP_MAX_NUM_UP_PARAM]; + // Flow Setup List (O) + int numQosFlowSetup; + qos_flow_list_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; + // Old QoS Flow List (O) + int numOldQosFlow; + qos_flow_list_t oldQosFlows[E1AP_MAX_NUM_QOS_FLOWS]; } DRB_nGRAN_modified_t; typedef struct DRB_nGRAN_failed_s { long id; - long cause_type; - long cause; + e1ap_cause_t cause; } DRB_nGRAN_failed_t; typedef struct pdu_session_setup_s { long id; - in_addr_t tlAddress; - long teId; + // Transport layer info + UP_TL_information_t tl_info; int numDRBSetup; DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS]; int numDRBFailed; DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_DRBS]; } pdu_session_setup_t; +/* PDU Session Resource Modified List (9.3.3.17) */ typedef struct pdu_session_modif_s { + // PDU Session ID (M) long id; - // setup as part of PDU session modification not supported yet + // Security Result (O) + e1ap_indication_t *integrityProtectionIndication; + e1ap_indication_t *confidentialityProtectionIndication; + // NG DL UP Transport Layer Information (O) + UP_TL_information_t *ng_DL_UP_TL_info; + // DRB Modified List (O) int numDRBModified; DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; + // DRB Setup List (O) + int numDRBSetup; + DRB_nGRAN_setup_t DRBnGRanSetupList[E1AP_MAX_NUM_DRBS]; } pdu_session_modif_t; typedef struct e1ap_bearer_setup_resp_s { @@ -472,8 +582,11 @@ typedef struct e1ap_bearer_setup_resp_s { } e1ap_bearer_setup_resp_t; typedef struct e1ap_bearer_modif_resp_s { + // gNB-CU-CP UE E1AP ID (M) uint32_t gNB_cu_cp_ue_id; + // gNB-CU-UP UE E1AP ID (M) uint32_t gNB_cu_up_ue_id; + // NG-RAN PDU Session Resource Modified List (O) int numPDUSessionsMod; pdu_session_modif_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; } e1ap_bearer_modif_resp_t; diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index e9aa7f54df..72eff658cb 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -429,7 +429,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upc BEARER CONTEXT MODIFICATION REQUEST */ -static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu) +static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_mod_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu) { pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, msg); @@ -473,7 +473,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod); drb2Mod->dRB_ID = j->id; asn1cCalloc(drb2Mod->pDCP_Configuration, pDCP_Configuration); - if (j->pdcp_config.pDCP_Reestablishment) { + if (j->pdcp_config && j->pdcp_config->pDCP_Reestablishment) { asn1cCallocOne(pDCP_Configuration->pDCP_Reestablishment, E1AP_PDCP_Reestablishment_true); } if (j->numDlUpParam > 0) { @@ -482,8 +482,8 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con asn1cSequenceAdd(DL_UP_Param_List->list, E1AP_UP_Parameters_Item_t, DL_UP_Param); DL_UP_Param->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; asn1cCalloc(DL_UP_Param->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); - INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tl_info.tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(k->tl_info.teId, &gTPTunnel->gTP_TEID); DL_UP_Param->cell_Group_ID = k->cell_group_id; } @@ -491,7 +491,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con } } /* c4. E1AP_ProtocolIE_ID_id_BearerContextStatusChange */ - if (bearerCxt->bearerContextStatus == BEARER_SUSPEND) { + if (bearerCxt->bearerContextStatus && *bearerCxt->bearerContextStatus == BEARER_SUSPEND) { asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC4); ieC4->id = E1AP_ProtocolIE_ID_id_BearerContextStatusChange; ieC4->criticality = E1AP_Criticality_reject; @@ -635,7 +635,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p if (drb2Mod->pDCP_Configuration != NULL && drb2Mod->pDCP_Configuration->pDCP_Reestablishment != NULL && *drb2Mod->pDCP_Configuration->pDCP_Reestablishment == E1AP_PDCP_Reestablishment_true) { - drb->pdcp_config.pDCP_Reestablishment = true; + drb->pdcp_config = malloc_or_fail(sizeof(*drb->pdcp_config)); + drb->pdcp_config->pDCP_Reestablishment = true; } if (drb2Mod->dL_UP_Parameters) { /* Optional IE in the DRB To Modify Item */ E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; @@ -647,8 +648,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p DevAssert(dl_up_param_in->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel); BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4( &dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress, - dl_up_param->tlAddress); - OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->teId); + dl_up_param->tl_info.tlAddress); + OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->tl_info.teId); } else { AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n"); } @@ -663,7 +664,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p /* Bearer Context Status Change */ DevAssert(ie->criticality == E1AP_Criticality_reject); DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange); - bearerCxt->bearerContextStatus = (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) ? BEARER_SUSPEND : BEARER_ACTIVE; + bearerCxt->bearerContextStatus = malloc_or_fail(*bearerCxt->bearerContextStatus); + *bearerCxt->bearerContextStatus = (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) ? BEARER_SUSPEND : BEARER_ACTIVE; break; default: diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index 2552e478ba..d73a3bddd7 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -37,9 +37,130 @@ #include "e1ap_bearer_context_management.h" #include "e1ap_lib_includes.h" -/* ==================================== - * E1AP Bearer Context Setup Request - * ==================================== */ +/** @brief Encode E1AP_SecurityIndication_t (3GPP TS 38.463 9.3.1.23) */ +static E1AP_SecurityIndication_t e1_encode_security_indication(const security_indication_t *in) +{ + E1AP_SecurityIndication_t out = {0}; + out.integrityProtectionIndication = in->integrityProtectionIndication; + out.confidentialityProtectionIndication = in->confidentialityProtectionIndication; + if (in->integrityProtectionIndication != SECURITY_NOT_NEEDED) { + asn1cCalloc(out.maximumIPdatarate, ipDataRate); + ipDataRate->maxIPrate = in->maxIPrate; + } + return out; +} + +/** @brief Decode E1AP_SecurityIndication_t (3GPP TS 38.463 9.3.1.23) */ +static bool e1_decode_security_indication(security_indication_t *out, const E1AP_SecurityIndication_t *in) +{ + // Confidentiality Protection Indication (M) + out->confidentialityProtectionIndication = in->confidentialityProtectionIndication; + // Maximum Integrity Protected Data Rate (Conditional) + if (in->integrityProtectionIndication != SECURITY_NOT_NEEDED) { + if (in->maximumIPdatarate) + out->maxIPrate = in->maximumIPdatarate->maxIPrate; + else { + PRINT_ERROR("Received integrityProtectionIndication but maximumIPdatarate IE is missing\n"); + return false; + } + } + return true; +} + +/** + * @brief Encode E1AP_SecurityInformation_t + */ +static E1AP_SecurityInformation_t e1_encode_security_info(const security_information_t *secInfo) +{ + E1AP_SecurityInformation_t ie = {0}; + E1AP_SecurityAlgorithm_t *securityAlgorithm = &ie.securityAlgorithm; + E1AP_UPSecuritykey_t *uPSecuritykey = &ie.uPSecuritykey; + securityAlgorithm->cipheringAlgorithm = secInfo->cipheringAlgorithm; + OCTET_STRING_fromBuf(&uPSecuritykey->encryptionKey, secInfo->encryptionKey, E1AP_SECURITY_KEY_SIZE); + asn1cCallocOne(securityAlgorithm->integrityProtectionAlgorithm, secInfo->integrityProtectionAlgorithm); + asn1cCalloc(uPSecuritykey->integrityProtectionKey, protKey); + OCTET_STRING_fromBuf(protKey, secInfo->integrityProtectionKey, E1AP_SECURITY_KEY_SIZE); + return ie; +} + +/** + * @brief Decode E1AP_SecurityInformation_t + */ +static bool e1_decode_security_info(security_information_t *out, const E1AP_SecurityInformation_t *in) +{ + out->cipheringAlgorithm = in->securityAlgorithm.cipheringAlgorithm; + memcpy(out->encryptionKey, in->uPSecuritykey.encryptionKey.buf, in->uPSecuritykey.encryptionKey.size); + if (in->securityAlgorithm.integrityProtectionAlgorithm) + out->integrityProtectionAlgorithm = *in->securityAlgorithm.integrityProtectionAlgorithm; + if (in->uPSecuritykey.integrityProtectionKey) { + E1AP_IntegrityProtectionKey_t *ipKey = in->uPSecuritykey.integrityProtectionKey; + memcpy(out->integrityProtectionKey, ipKey->buf, ipKey->size); + } + return true; +} + +/** + * @brief Encode E1AP_UP_TNL_Information_t + */ +static E1AP_UP_TNL_Information_t e1_encode_up_tnl_info(const UP_TL_information_t *in) +{ + E1AP_UP_TNL_Information_t out = {0}; + out.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(out.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(in->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(in->teId, &gTPTunnel->gTP_TEID); + return out; +} + +/** + * @brief Decode E1AP_UP_TNL_Information_t + */ +static bool e1_decode_up_tnl_info(UP_TL_information_t *out, const E1AP_UP_TNL_Information_t *in) +{ + /* NG UL UP Transport Layer Information (M) (9.3.2.1 of 3GPP TS 38.463) */ + // GTP Tunnel + struct E1AP_GTPTunnel *gTPTunnel = in->choice.gTPTunnel; + AssertFatal(gTPTunnel != NULL, "item->nG_UL_UP_TNL_Information.choice.gTPTunnel is a mandatory IE"); + _E1_EQ_CHECK_INT(in->present, E1AP_UP_TNL_Information_PR_gTPTunnel); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, out->tlAddress); + // GTP-TEID + OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, out->teId); + return true; +} + +/** @brief Encode PDCP Configuration IE */ +static E1AP_PDCP_Configuration_t e1_encode_pdcp_config(const bearer_context_pdcp_config_t *in) +{ + E1AP_PDCP_Configuration_t out = {0}; + out.pDCP_SN_Size_UL = in->pDCP_SN_Size_UL; + out.pDCP_SN_Size_DL = in->pDCP_SN_Size_DL; + asn1cCallocOne(out.discardTimer, in->discardTimer); + E1AP_T_ReorderingTimer_t *roTimer = calloc_or_fail(1, sizeof(*roTimer)); + out.t_ReorderingTimer = roTimer; + roTimer->t_Reordering = in->reorderingTimer; + out.rLC_Mode = in->rLC_Mode; + if (in->pDCP_Reestablishment) { + asn1cCallocOne(out.pDCP_Reestablishment, E1AP_PDCP_Reestablishment_true); + } + return out; +} + +/** @brief Decode PDCP Configuration IE */ +static bool e1_decode_pdcp_config(bearer_context_pdcp_config_t *out, const E1AP_PDCP_Configuration_t *in) +{ + out->pDCP_SN_Size_UL = in->pDCP_SN_Size_UL; + out->pDCP_SN_Size_DL = in->pDCP_SN_Size_DL; + if (in->discardTimer) { + out->discardTimer = *in->discardTimer; + } + if (in->t_ReorderingTimer) { + out->reorderingTimer = in->t_ReorderingTimer->t_Reordering; + } + out->rLC_Mode = in->rLC_Mode; + if (in->pDCP_Reestablishment && *in->pDCP_Reestablishment == E1AP_PDCP_Reestablishment_true) + out->pDCP_Reestablishment = true; + return true; +} /** * @brief Equality check for bearer_context_pdcp_config_t @@ -55,6 +176,25 @@ static bool eq_pdcp_config(const bearer_context_pdcp_config_t *a, const bearer_c return true; } +/** @brief Encode SDAP Configuration IE */ +static E1AP_SDAP_Configuration_t e1_encode_sdap_config(const bearer_context_sdap_config_t *in) +{ + E1AP_SDAP_Configuration_t out; + out.defaultDRB = in->defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; + out.sDAP_Header_UL = in->sDAP_Header_UL; + out.sDAP_Header_DL = in->sDAP_Header_DL; + return out; +} + +/** @brief Decode SDAP Configuration IE */ +static bool e1_decode_sdap_config(bearer_context_sdap_config_t *out, const E1AP_SDAP_Configuration_t *in) +{ + out->defaultDRB = in->defaultDRB == E1AP_DefaultDRB_true; + out->sDAP_Header_UL = in->sDAP_Header_UL; + out->sDAP_Header_DL = in->sDAP_Header_DL; + return true; +} + /** * @brief Equality check for bearer_context_sdap_config_t */ @@ -66,6 +206,69 @@ static bool eq_sdap_config(const bearer_context_sdap_config_t *a, const bearer_c return true; } +static E1AP_QoS_Flow_QoS_Parameter_Item_t e1_encode_qos_flow_to_setup(const qos_flow_to_setup_t *in) +{ + E1AP_QoS_Flow_QoS_Parameter_Item_t out = {0}; + out.qoS_Flow_Identifier = in->qfi; + // QoS Characteristics + const qos_characteristics_t *qos_char_in = &in->qos_params.qos_characteristics; + if (qos_char_in->qos_type == NON_DYNAMIC) { // non Dynamic 5QI + out.qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; + asn1cCalloc(out.qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); + non_Dynamic_5QI->fiveQI = qos_char_in->non_dynamic.fiveqi; + } else { // dynamic 5QI + out.qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI; + asn1cCalloc(out.qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI); + dynamic_5QI->qoSPriorityLevel = qos_char_in->dynamic.qos_priority_level; + dynamic_5QI->packetDelayBudget = qos_char_in->dynamic.packet_delay_budget; + dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar; + dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent; + } + // QoS Retention Priority + const ngran_allocation_retention_priority_t *rent_priority_in = &in->qos_params.alloc_reten_priority; + E1AP_NGRANAllocationAndRetentionPriority_t *arp = &out.qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority; + arp->priorityLevel = rent_priority_in->priority_level; + arp->pre_emptionCapability = rent_priority_in->preemption_capability; + arp->pre_emptionVulnerability = rent_priority_in->preemption_vulnerability; + return out; +} + +bool e1_decode_qos_flow_to_setup(qos_flow_to_setup_t *out, const E1AP_QoS_Flow_QoS_Parameter_Item_t *in) +{ + // QoS Flow Identifier (M) + out->qfi = in->qoS_Flow_Identifier; + qos_characteristics_t *qos_char = &out->qos_params.qos_characteristics; + // QoS Flow Level QoS Parameters (M) + const E1AP_QoSFlowLevelQoSParameters_t *qosParams = &in->qoSFlowLevelQoSParameters; + const E1AP_QoS_Characteristics_t *qoS_Characteristics = &qosParams->qoS_Characteristics; + switch (qoS_Characteristics->present) { + case E1AP_QoS_Characteristics_PR_non_Dynamic_5QI: + qos_char->qos_type = NON_DYNAMIC; + qos_char->non_dynamic.fiveqi = qoS_Characteristics->choice.non_Dynamic_5QI->fiveQI; + break; + case E1AP_QoS_Characteristics_PR_dynamic_5QI: { + E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qoS_Characteristics->choice.dynamic_5QI; + qos_char->qos_type = DYNAMIC; + qos_char->dynamic.qos_priority_level = dynamic5QI->qoSPriorityLevel; + qos_char->dynamic.packet_delay_budget = dynamic5QI->packetDelayBudget; + qos_char->dynamic.packet_error_rate.per_scalar = dynamic5QI->packetErrorRate.pER_Scalar; + qos_char->dynamic.packet_error_rate.per_exponent = dynamic5QI->packetErrorRate.pER_Exponent; + break; + } + default: + PRINT_ERROR("Unexpected QoS Characteristics type: %d\n", qoS_Characteristics->present); + return false; + break; + } + // NG-RAN Allocation and Retention Priority (M) + ngran_allocation_retention_priority_t *rent_priority = &out->qos_params.alloc_reten_priority; + const E1AP_NGRANAllocationAndRetentionPriority_t *aRP = &qosParams->nGRANallocationRetentionPriority; + rent_priority->priority_level = aRP->priorityLevel; + rent_priority->preemption_capability = aRP->pre_emptionCapability; + rent_priority->preemption_vulnerability = aRP->pre_emptionVulnerability; + return true; +} + /** * @brief Equality check for qos_flow_to_setup_t */ @@ -110,36 +313,12 @@ static bool eq_drb_to_setup(const DRB_nGRAN_to_setup_t *a, const DRB_nGRAN_to_se return result; } -/** - * @brief Equality check for DRB_nGRAN_to_mod_t - */ -static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t *b) +static void free_drb_to_setup_item(const DRB_nGRAN_to_setup_t *msg) { - bool result = true; - _E1_EQ_CHECK_LONG(a->id, b->id); - _E1_EQ_CHECK_INT(a->numCellGroups, b->numCellGroups); - for (int i = 0; i < a->numCellGroups; i++) { - _E1_EQ_CHECK_INT(a->cellGroupList[i], b->cellGroupList[i]); - } - _E1_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup); - for (int i = 0; i < a->numQosFlow2Setup; i++) { - result &= eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]); - } - _E1_EQ_CHECK_INT(a->tlAddress, b->tlAddress); - _E1_EQ_CHECK_INT(a->teId, b->teId); - _E1_EQ_CHECK_INT(a->numDlUpParam, b->numDlUpParam); - for (int i = 0; i < a->numDlUpParam; i++) { - _E1_EQ_CHECK_INT(a->DlUpParamList[i].cell_group_id, b->DlUpParamList[i].cell_group_id); - _E1_EQ_CHECK_LONG(a->DlUpParamList[i].teId, b->DlUpParamList[i].teId); - _E1_EQ_CHECK_INT(a->DlUpParamList[i].tlAddress, b->DlUpParamList[i].tlAddress); - } - result &= eq_pdcp_config(&a->pdcp_config, &b->pdcp_config); - result &= eq_sdap_config(&a->sdap_config, &b->sdap_config); - return result; + free(msg->drb_inactivity_timer); } -/* PDU Session To Setup Item */ - +/** @brief Encode PDU Session Resource To Setup List Item (3GPP TS 38.463 9.3.3.2) */ static bool e1_encode_pdu_session_to_setup_item(E1AP_PDU_Session_Resource_To_Setup_Item_t *item, const pdu_session_to_setup_t *in) { item->pDU_Session_ID = in->sessionId; @@ -150,73 +329,33 @@ static bool e1_encode_pdu_session_to_setup_item(E1AP_PDU_Session_Resource_To_Set item->sNSSAI.sD = malloc_or_fail(sizeof(*item->sNSSAI.sD)); INT24_TO_OCTET_STRING(in->nssai.sd, item->sNSSAI.sD); } - // Security Indication - E1AP_SecurityIndication_t *siOut = &item->securityIndication; - const security_indication_t *siIn = &in->securityIndication; - siOut->integrityProtectionIndication = siIn->integrityProtectionIndication; - siOut->confidentialityProtectionIndication = siIn->confidentialityProtectionIndication; - if (siIn->integrityProtectionIndication != SECURITY_NOT_NEEDED) { - asn1cCalloc(siOut->maximumIPdatarate, ipDataRate); - ipDataRate->maxIPrate = siIn->maxIPrate; - } - // TNL Information - item->nG_UL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; - asn1cCalloc(item->nG_UL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); - const UP_TL_information_t *UP_TL_information = &in->UP_TL_information; - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(UP_TL_information->tlAddress, &gTPTunnel->transportLayerAddress); - INT32_TO_OCTET_STRING(UP_TL_information->teId, &gTPTunnel->gTP_TEID); - // DRB to setup + // Security Indication (M) + item->securityIndication = e1_encode_security_indication(&in->securityIndication); + // NG UL UP Transport Layer Information (M) + item->nG_UL_UP_TNL_Information = e1_encode_up_tnl_info(&in->UP_TL_information); + // DRB To Setup List (M) for (const DRB_nGRAN_to_setup_t *j = in->DRBnGRanList; j < in->DRBnGRanList + in->numDRB2Setup; j++) { asn1cSequenceAdd(item->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); ieC6_1_1->dRB_ID = j->id; - // SDAP Config - E1AP_SDAP_Configuration_t *sdap = &ieC6_1_1->sDAP_Configuration; - sdap->defaultDRB = j->sdap_config.defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; - sdap->sDAP_Header_UL = j->sdap_config.sDAP_Header_UL; - sdap->sDAP_Header_DL = j->sdap_config.sDAP_Header_DL; - // PDCP Config - E1AP_PDCP_Configuration_t *pdcp = &ieC6_1_1->pDCP_Configuration; - pdcp->pDCP_SN_Size_UL = j->pdcp_config.pDCP_SN_Size_UL; - pdcp->pDCP_SN_Size_DL = j->pdcp_config.pDCP_SN_Size_DL; - asn1cCallocOne(pdcp->discardTimer, j->pdcp_config.discardTimer); - E1AP_T_ReorderingTimer_t *roTimer = calloc_or_fail(1, sizeof(*roTimer)); - pdcp->t_ReorderingTimer = roTimer; - roTimer->t_Reordering = j->pdcp_config.reorderingTimer; - pdcp->rLC_Mode = j->pdcp_config.rLC_Mode; - // Cell Group + // SDAP Configuration (M) + ieC6_1_1->sDAP_Configuration = e1_encode_sdap_config(&j->sdap_config); + // PDCP Configuration (M) + ieC6_1_1->pDCP_Configuration = e1_encode_pdcp_config(&j->pdcp_config); + // Cell Group Information (M) for (const cell_group_id_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) { asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1); ieC6_1_1_1->cell_Group_ID = *k; } // QoS Flows for (const qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) { - asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); - ieC6_1_1_1->qoS_Flow_Identifier = k->qfi; - // QoS Characteristics - const qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics; - if (qos_char_in->qos_type == NON_DYNAMIC) { // non Dynamic 5QI - ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); - non_Dynamic_5QI->fiveQI = qos_char_in->non_dynamic.fiveqi; - } else { // dynamic 5QI - ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI); - dynamic_5QI->qoSPriorityLevel = qos_char_in->dynamic.qos_priority_level; - dynamic_5QI->packetDelayBudget = qos_char_in->dynamic.packet_delay_budget; - dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar; - dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent; - } - // QoS Retention Priority - const ngran_allocation_retention_priority_t *rent_priority_in = &k->qos_params.alloc_reten_priority; - E1AP_NGRANAllocationAndRetentionPriority_t *arp = &ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority; - arp->priorityLevel = rent_priority_in->priority_level; - arp->pre_emptionCapability = rent_priority_in->preemption_capability; - arp->pre_emptionVulnerability = rent_priority_in->preemption_vulnerability; + asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup.list, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_2); + *ieC6_1_1_2 = e1_encode_qos_flow_to_setup(k); } } return true; } +/** @brief Decode PDU Session Resource To Setup List Item (3GPP TS 38.463 9.3.3.2) */ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1AP_PDU_Session_Resource_To_Setup_Item_t *item) { // PDU Session ID (M) @@ -230,22 +369,8 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A // SD (O) if (item->sNSSAI.sD != NULL) OCTET_STRING_TO_INT24(item->sNSSAI.sD, out->nssai.sd); - /* Security Indication (M) */ - E1AP_SecurityIndication_t *securityIndication = &item->securityIndication; - // Integrity Protection Indication (M) - security_indication_t *sec = &out->securityIndication; - sec->integrityProtectionIndication = securityIndication->integrityProtectionIndication; - // Confidentiality Protection Indication (M) - sec->confidentialityProtectionIndication = securityIndication->confidentialityProtectionIndication; - // Maximum Integrity Protected Data Rate (Conditional) - if (sec->integrityProtectionIndication != SECURITY_NOT_NEEDED) { - if (securityIndication->maximumIPdatarate) - sec->maxIPrate = securityIndication->maximumIPdatarate->maxIPrate; - else { - PRINT_ERROR("Received integrityProtectionIndication but maximumIPdatarate IE is missing\n"); - return false; - } - } + // Security Indication (M) + CHECK_E1AP_DEC(e1_decode_security_indication(&out->securityIndication, &item->securityIndication)); /* NG UL UP Transport Layer Information (M) (9.3.2.1 of 3GPP TS 38.463) */ // GTP Tunnel struct E1AP_GTPTunnel *gTPTunnel = item->nG_UL_UP_TNL_Information.choice.gTPTunnel; @@ -254,38 +379,22 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A return false; } _E1_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel); - // Transport Layer Address - UP_TL_information_t *UP_TL_information = &out->UP_TL_information; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UP_TL_information->tlAddress); - // GTP-TEID - OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UP_TL_information->teId); - // DRB To Setup List ( > 1 item ) + CHECK_E1AP_DEC(e1_decode_up_tnl_info(&out->UP_TL_information, &item->nG_UL_UP_TNL_Information)); + /* DRB To Setup List ( > 1 item ) */ E1AP_DRB_To_Setup_List_NG_RAN_t *drb2SetupList = &item->dRB_To_Setup_List_NG_RAN; _E1_EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0); out->numDRB2Setup = drb2SetupList->list.count; - _E1_EQ_CHECK_LONG(out->numDRB2Setup, 1UL); // can only handle one DRB per PDU session + _E1_EQ_CHECK_INT(out->numDRB2Setup, 1); // can only handle one DRB per PDU session for (int j = 0; j < drb2SetupList->list.count; j++) { DRB_nGRAN_to_setup_t *drb = out->DRBnGRanList + j; E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; // DRB ID (M) drb->id = drb2Setup->dRB_ID; - // >SDAP Configuration (M) - E1AP_SDAP_Configuration_t *sdap = &drb2Setup->sDAP_Configuration; - drb->sdap_config.defaultDRB = sdap->defaultDRB == E1AP_DefaultDRB_true; - drb->sdap_config.sDAP_Header_UL = sdap->sDAP_Header_UL; - drb->sdap_config.sDAP_Header_DL = sdap->sDAP_Header_DL; + // SDAP Configuration (M) + CHECK_E1AP_DEC(e1_decode_sdap_config(&drb->sdap_config, &drb2Setup->sDAP_Configuration)); // PDCP Configuration (M) - E1AP_PDCP_Configuration_t *pdcp = &drb2Setup->pDCP_Configuration; - drb->pdcp_config.pDCP_SN_Size_UL = pdcp->pDCP_SN_Size_UL; - drb->pdcp_config.pDCP_SN_Size_DL = pdcp->pDCP_SN_Size_DL; - if (pdcp->discardTimer) { - drb->pdcp_config.discardTimer = *pdcp->discardTimer; - } - if (pdcp->t_ReorderingTimer) { - drb->pdcp_config.reorderingTimer = pdcp->t_ReorderingTimer->t_Reordering; - } - drb->pdcp_config.rLC_Mode = pdcp->rLC_Mode; - // Cell Group Information (M) ( > 1 item ) + CHECK_E1AP_DEC(e1_decode_pdcp_config(&drb->pdcp_config, &drb2Setup->pDCP_Configuration)); + // Cell Group Information (M) E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; _E1_EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0); drb->numCellGroups = cellGroupList->list.count; @@ -298,44 +407,42 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup; drb->numQosFlow2Setup = qos2SetupList->list.count; for (int k = 0; k < qos2SetupList->list.count; k++) { - qos_flow_to_setup_t *qos_flow = drb->qosFlows + k; - E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k]; - // QoS Flow Identifier (M) - qos_flow->qfi = qos2Setup->qoS_Flow_Identifier; - qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; - // QoS Flow Level QoS Parameters (M) - E1AP_QoSFlowLevelQoSParameters_t *qosParams = &qos2Setup->qoSFlowLevelQoSParameters; - E1AP_QoS_Characteristics_t *qoS_Characteristics = &qosParams->qoS_Characteristics; - switch (qoS_Characteristics->present) { - case E1AP_QoS_Characteristics_PR_non_Dynamic_5QI: - qos_char->qos_type = NON_DYNAMIC; - qos_char->non_dynamic.fiveqi = qoS_Characteristics->choice.non_Dynamic_5QI->fiveQI; - break; - case E1AP_QoS_Characteristics_PR_dynamic_5QI: { - E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qoS_Characteristics->choice.dynamic_5QI; - qos_char->qos_type = DYNAMIC; - qos_char->dynamic.qos_priority_level = dynamic5QI->qoSPriorityLevel; - qos_char->dynamic.packet_delay_budget = dynamic5QI->packetDelayBudget; - qos_char->dynamic.packet_error_rate.per_scalar = dynamic5QI->packetErrorRate.pER_Scalar; - qos_char->dynamic.packet_error_rate.per_exponent = dynamic5QI->packetErrorRate.pER_Exponent; - break; - } - default: - PRINT_ERROR("Unexpected QoS Characteristics type: %d\n", qoS_Characteristics->present); - return false; - break; - } - // NG-RAN Allocation and Retention Priority (M) - ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority; - E1AP_NGRANAllocationAndRetentionPriority_t *aRP = &qosParams->nGRANallocationRetentionPriority; - rent_priority->priority_level = aRP->priorityLevel; - rent_priority->preemption_capability = aRP->pre_emptionCapability; - rent_priority->preemption_vulnerability = aRP->pre_emptionVulnerability; + CHECK_E1AP_DEC(e1_decode_qos_flow_to_setup(drb->qosFlows + k, qos2SetupList->list.array[k])); } } return true; } +/** @brief Deep copy DRB To Setup List Item (3GPP TS 38.463 9.3.3.2) */ +static DRB_nGRAN_to_setup_t cp_drb_to_setup_item(const DRB_nGRAN_to_setup_t *msg) +{ + DRB_nGRAN_to_setup_t cp = {0}; + cp.id = msg->id; + cp.sdap_config = msg->sdap_config; + cp.pdcp_config = msg->pdcp_config; + cp.numCellGroups = msg->numCellGroups; + // Cell Group List + for (int k = 0; k < msg->numCellGroups; k++) { + cp.cellGroupList[k] = msg->cellGroupList[k]; + } + cp.numQosFlow2Setup = msg->numQosFlow2Setup; + // QoS Flow To Setup List + for (int k = 0; k < msg->numQosFlow2Setup; k++) { + cp.qosFlows[k].qfi = msg->qosFlows[k].qfi; + cp.qosFlows[k].qos_params = msg->qosFlows[k].qos_params; + } + return cp; +} + +/** @brief Free PDU Session Resource To Setup List item (3GPP TS 38.463 9.3.3.2) */ +void free_pdu_session_to_setup_item(const pdu_session_to_setup_t *msg) +{ + free(msg->dlAggregateMaxBitRate); + free(msg->inactivityTimer); + for (int i = 0; i < msg->numDRB2Setup; i++) + free_drb_to_setup_item(&msg->DRBnGRanList[i]); +} + /** * @brief Equality check for PDU session item to modify/setup */ @@ -345,55 +452,20 @@ static bool eq_pdu_session_item(const pdu_session_to_setup_t *a, const pdu_sessi _E1_EQ_CHECK_LONG(a->sessionType, b->sessionType); _E1_EQ_CHECK_INT(a->UP_TL_information.tlAddress, b->UP_TL_information.tlAddress); _E1_EQ_CHECK_INT(a->UP_TL_information.teId, b->UP_TL_information.teId); - _E1_EQ_CHECK_LONG(a->numDRB2Setup, b->numDRB2Setup); - if (a->numDRB2Setup != b->numDRB2Setup) - return false; + _E1_EQ_CHECK_INT(a->numDRB2Setup, b->numDRB2Setup); for (int i = 0; i < a->numDRB2Setup; i++) if (!eq_drb_to_setup(&a->DRBnGRanList[i], &b->DRBnGRanList[i])) return false; - _E1_EQ_CHECK_LONG(a->numDRB2Modify, b->numDRB2Modify); - if (a->numDRB2Modify != b->numDRB2Modify) - return false; - for (int i = 0; i < a->numDRB2Modify; i++) - if (!eq_drb_to_mod(&a->DRBnGRanModList[i], &b->DRBnGRanModList[i])) - return false; + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer); + if (a->inactivityTimer && b->inactivityTimer) + _E1_EQ_CHECK_INT(a->inactivityTimer, b->inactivityTimer); + _E1_EQ_CHECK_OPTIONAL_IE(a, b, dlAggregateMaxBitRate, _E1_EQ_CHECK_LONG); return true; } -static bool cp_pdu_session_item(pdu_session_to_setup_t *cp, const pdu_session_to_setup_t *msg) -{ - // Copy basic fields - *cp = *msg; - // Copy DRB to Setup List - for (int j = 0; j < msg->numDRB2Setup; j++) { - cp->DRBnGRanList[j].id = msg->DRBnGRanList[j].id; - cp->DRBnGRanList[j].sdap_config = msg->DRBnGRanList[j].sdap_config; - cp->DRBnGRanList[j].pdcp_config = msg->DRBnGRanList[j].pdcp_config; - cp->DRBnGRanList[j].tlAddress = msg->DRBnGRanList[j].tlAddress; - cp->DRBnGRanList[j].teId = msg->DRBnGRanList[j].teId; - cp->DRBnGRanList[j].numDlUpParam = msg->DRBnGRanList[j].numDlUpParam; - // Copy DL UP Params List - for (int k = 0; k < msg->DRBnGRanList[j].numDlUpParam; k++) { - cp->DRBnGRanList[j].DlUpParamList[k] = msg->DRBnGRanList[j].DlUpParamList[k]; - } - cp->DRBnGRanList[j].numCellGroups = msg->DRBnGRanList[j].numCellGroups; - // Copy Cell Group List - for (int k = 0; k < msg->DRBnGRanList[j].numCellGroups; k++) { - cp->DRBnGRanList[j].cellGroupList[k] = msg->DRBnGRanList[j].cellGroupList[k]; - } - cp->DRBnGRanList[j].numQosFlow2Setup = msg->DRBnGRanList[j].numQosFlow2Setup; - // Copy QoS Flow To Setup List - for (int k = 0; k < msg->DRBnGRanList[j].numQosFlow2Setup; k++) { - cp->DRBnGRanList[j].qosFlows[k].qfi = msg->DRBnGRanList[j].qosFlows[k].qfi; - cp->DRBnGRanList[j].qosFlows[k].qos_params = msg->DRBnGRanList[j].qosFlows[k].qos_params; - } - } - // Copy DRB to Modify List - for (int j = 0; j < msg->numDRB2Modify; j++) { - cp->DRBnGRanModList[j] = msg->DRBnGRanModList[j]; - } - return true; -} +/* ==================================== + * E1AP Bearer Context Setup Request + * ==================================== */ /** * @brief E1AP Bearer Context Setup Request encoding (9.2.2 of 3GPP TS 38.463) @@ -421,13 +493,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_ ieC2->id = E1AP_ProtocolIE_ID_id_SecurityInformation; ieC2->criticality = E1AP_Criticality_reject; ieC2->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation; - E1AP_SecurityAlgorithm_t *securityAlgorithm = &ieC2->value.choice.SecurityInformation.securityAlgorithm; - E1AP_UPSecuritykey_t *uPSecuritykey = &ieC2->value.choice.SecurityInformation.uPSecuritykey; - securityAlgorithm->cipheringAlgorithm = msg->cipheringAlgorithm; - OCTET_STRING_fromBuf(&uPSecuritykey->encryptionKey, msg->encryptionKey, E1AP_SECURITY_KEY_SIZE); - asn1cCallocOne(securityAlgorithm->integrityProtectionAlgorithm, msg->integrityProtectionAlgorithm); - asn1cCalloc(uPSecuritykey->integrityProtectionKey, protKey); - OCTET_STRING_fromBuf(protKey, msg->integrityProtectionKey, E1AP_SECURITY_KEY_SIZE); + ieC2->value.choice.SecurityInformation = e1_encode_security_info(&msg->secInfo); /* mandatory */ /* c3. UE DL Aggregate Maximum Bit Rate */ asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC3); @@ -479,7 +545,8 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_ */ void free_e1ap_context_setup_request(e1ap_bearer_setup_req_t *msg) { - // Do nothing + free(msg->inactivityTimerUE); + free(msg->ueDlMaxIPBitRate); } /** @@ -518,17 +585,7 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea case E1AP_ProtocolIE_ID_id_SecurityInformation: _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation); - E1AP_SecurityInformation_t *SecurityInformation = &ie->value.choice.SecurityInformation; - E1AP_SecurityAlgorithm_t *securityAlgorithm = &SecurityInformation->securityAlgorithm; - E1AP_EncryptionKey_t *encryptionKey = &SecurityInformation->uPSecuritykey.encryptionKey; - E1AP_IntegrityProtectionKey_t *integrityProtectionKey = SecurityInformation->uPSecuritykey.integrityProtectionKey; - - out->cipheringAlgorithm = securityAlgorithm->cipheringAlgorithm; - memcpy(out->encryptionKey, encryptionKey->buf, encryptionKey->size); - if (securityAlgorithm->integrityProtectionAlgorithm) - out->integrityProtectionAlgorithm = *securityAlgorithm->integrityProtectionAlgorithm; - if (integrityProtectionKey) - memcpy(out->integrityProtectionKey, integrityProtectionKey->buf, integrityProtectionKey->size); + e1_decode_security_info(&out->secInfo, &ie->value.choice.SecurityInformation); break; case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate: @@ -583,10 +640,7 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea for (int i = 0; i < pdu2SetupList->list.count; i++) { pdu_session_to_setup_t *pdu_session = out->pduSession + i; E1AP_PDU_Session_Resource_To_Setup_Item_t *pdu2Setup = pdu2SetupList->list.array[i]; - if (!e1_decode_pdu_session_to_setup_item(pdu_session, pdu2Setup)) { - PRINT_ERROR("Failed to decode PDU Session to setup item %d\n", i); - return false; - } + CHECK_E1AP_DEC(e1_decode_pdu_session_to_setup_item(pdu_session, pdu2Setup)); } break; default: @@ -597,19 +651,35 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea return true; } -/** - * @brief Deep copy function for E1 BEARER CONTEXT SETUP REQUEST - */ +/** @brief Deep copy PDU Session Resource To Setup List item (3GPP TS 38.463 9.3.3.2) */ +static pdu_session_to_setup_t cp_pdu_session_item(const pdu_session_to_setup_t *msg) +{ + pdu_session_to_setup_t cp = {0}; + // Copy basic fields + cp = *msg; + // Copy DRB to Setup List + for (int j = 0; j < msg->numDRB2Setup; j++) + cp.DRBnGRanList[j] = cp_drb_to_setup_item(&msg->DRBnGRanList[j]); + // Copy optional IEs + _E1_CP_OPTIONAL_IE(&cp, msg, inactivityTimer); + _E1_CP_OPTIONAL_IE(&cp, msg, dlAggregateMaxBitRate); + return cp; +} + +/** @brief Deep copy function for E1 BEARER CONTEXT SETUP REQUEST */ e1ap_bearer_setup_req_t cp_bearer_context_setup_request(const e1ap_bearer_setup_req_t *msg) { e1ap_bearer_setup_req_t cp = {0}; // Copy basi fields cp = *msg; - strncpy(cp.encryptionKey, msg->encryptionKey, sizeof(cp.encryptionKey)); - strncpy(cp.integrityProtectionKey, msg->integrityProtectionKey, sizeof(cp.integrityProtectionKey)); + strncpy(cp.secInfo.encryptionKey, msg->secInfo.encryptionKey, sizeof(cp.secInfo.encryptionKey)); + strncpy(cp.secInfo.integrityProtectionKey, msg->secInfo.integrityProtectionKey, sizeof(cp.secInfo.integrityProtectionKey)); // Copy PDU Sessions for (int i = 0; i < msg->numPDUSessions; i++) - cp_pdu_session_item(&cp.pduSession[i], &msg->pduSession[i]); + cp.pduSession[i] = cp_pdu_session_item(&msg->pduSession[i]); + // copy optional IEs + _E1_CP_OPTIONAL_IE(&cp, msg, ueDlMaxIPBitRate); + _E1_CP_OPTIONAL_IE(&cp, msg, inactivityTimerUE); return cp; } @@ -620,29 +690,28 @@ bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1a { // Primitive data types _E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id); - _E1_EQ_CHECK_LONG(a->cipheringAlgorithm, b->cipheringAlgorithm); - _E1_EQ_CHECK_LONG(a->integrityProtectionAlgorithm, b->integrityProtectionAlgorithm); + _E1_EQ_CHECK_LONG(a->secInfo.cipheringAlgorithm, b->secInfo.cipheringAlgorithm); + _E1_EQ_CHECK_LONG(a->secInfo.integrityProtectionAlgorithm, b->secInfo.integrityProtectionAlgorithm); _E1_EQ_CHECK_LONG(a->ueDlAggMaxBitRate, b->ueDlAggMaxBitRate); _E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions); - _E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod); // PLMN _E1_EQ_CHECK_INT(a->servingPLMNid.mcc, b->servingPLMNid.mcc); _E1_EQ_CHECK_INT(a->servingPLMNid.mnc, b->servingPLMNid.mnc); _E1_EQ_CHECK_INT(a->servingPLMNid.mnc_digit_length, b->servingPLMNid.mnc_digit_length); // Security Keys - _E1_EQ_CHECK_STR(a->encryptionKey, b->encryptionKey); - _E1_EQ_CHECK_STR(a->integrityProtectionKey, b->integrityProtectionKey); + _E1_EQ_CHECK_STR(a->secInfo.encryptionKey, b->secInfo.encryptionKey); + _E1_EQ_CHECK_STR(a->secInfo.integrityProtectionKey, b->secInfo.integrityProtectionKey); // PDU Sessions if (a->numPDUSessions != b->numPDUSessions) return false; for (int i = 0; i < a->numPDUSessions; i++) if (!eq_pdu_session_item(&a->pduSession[i], &b->pduSession[i])) return false; - if (a->numPDUSessionsMod != b->numPDUSessionsMod) - return false; - for (int i = 0; i < a->numPDUSessionsMod; i++) - if (!eq_pdu_session_item(&a->pduSessionMod[i], &b->pduSessionMod[i])) - return false; + // Check optional IEs + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimerUE); + if (a->inactivityTimerUE && b->inactivityTimerUE) + _E1_EQ_CHECK_INT(a->inactivityTimerUE, b->inactivityTimerUE); + _E1_EQ_CHECK_OPTIONAL_IE(a, b, ueDlMaxIPBitRate, _E1_EQ_CHECK_LONG); return true; } @@ -664,8 +733,8 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP E1AP_UP_TNL_Information_t *DL_UP_TNL_Info = &in->nG_DL_UP_TNL_Information; if (DL_UP_TNL_Info->choice.gTPTunnel) { _E1_EQ_CHECK_INT(DL_UP_TNL_Info->present, E1AP_UP_TNL_Information_PR_gTPTunnel); - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&DL_UP_TNL_Info->choice.gTPTunnel->transportLayerAddress, pduSetup->tlAddress); - OCTET_STRING_TO_INT32(&DL_UP_TNL_Info->choice.gTPTunnel->gTP_TEID, pduSetup->teId); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&DL_UP_TNL_Info->choice.gTPTunnel->transportLayerAddress, pduSetup->tl_info.tlAddress); + OCTET_STRING_TO_INT32(&DL_UP_TNL_Info->choice.gTPTunnel->gTP_TEID, pduSetup->tl_info.teId); } // DRB Setup List (1..) for (int j = 0; j < in->dRB_Setup_List_NG_RAN.list.count; j++) { @@ -685,8 +754,8 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP E1AP_GTPTunnel_t *gTPTunnel = UL_UP_item->uP_TNL_Information.choice.gTPTunnel; AssertError(gTPTunnel != NULL, return false, "gTPTunnel information in required in UP Transport Layer Information\n"); if (gTPTunnel) { - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UL_UP_param->tlAddress); - OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UL_UP_param->teId); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UL_UP_param->tl_info.tlAddress); + OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UL_UP_param->tl_info.teId); } else { } // Cell Group ID (M) @@ -695,7 +764,7 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP // Flow Setup List (M) drbSetup->numQosFlowSetup = drb->flow_Setup_List.list.count; for (int q = 0; q < drb->flow_Setup_List.list.count; q++) { - qos_flow_setup_t *qosflowSetup = &drbSetup->qosFlows[q]; + qos_flow_list_t *qosflowSetup = &drbSetup->qosFlows[q]; E1AP_QoS_Flow_Item_t *in_qosflowSetup = drb->flow_Setup_List.list.array[q]; qosflowSetup->qfi = in_qosflowSetup->qoS_Flow_Identifier; } @@ -713,8 +782,8 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite // NG DL UP Transport Layer Information (M) item->nG_DL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; asn1cCalloc(item->nG_DL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(in->tlAddress, &gTPTunnel->transportLayerAddress); - INT32_TO_OCTET_STRING(in->teId, &gTPTunnel->gTP_TEID); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(in->tl_info.tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(in->tl_info.teId, &gTPTunnel->gTP_TEID); // DRB Setup List (1..) for (const DRB_nGRAN_setup_t *j = in->DRBnGRanList; j < in->DRBnGRanList + in->numDRBSetup; j++) { asn1cSequenceAdd(item->dRB_Setup_List_NG_RAN.list, E1AP_DRB_Setup_Item_NG_RAN_t, ieC3_1_1); @@ -725,11 +794,11 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite asn1cSequenceAdd(ieC3_1_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1_1); ieC3_1_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; asn1cCalloc(ieC3_1_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); - INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tl_info.tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(k->tl_info.teId, &gTPTunnel->gTP_TEID); } // Flow Setup List(M) - for (const qos_flow_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlowSetup; k++) { + for (const qos_flow_list_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlowSetup; k++) { asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1); ieC3_1_1_1->qoS_Flow_Identifier = k->qfi; } @@ -743,24 +812,7 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite // DRB ID (M) ieC3_1_1->dRB_ID = j->id; // Cause (M) - ieC3_1_1->cause.present = j->cause_type; - switch (ieC3_1_1->cause.present) { - case E1AP_Cause_PR_radioNetwork: - ieC3_1_1->cause.choice.radioNetwork = j->cause; - break; - case E1AP_Cause_PR_transport: - ieC3_1_1->cause.choice.transport = j->cause; - break; - case E1AP_Cause_PR_protocol: - ieC3_1_1->cause.choice.protocol = j->cause; - break; - case E1AP_Cause_PR_misc: - ieC3_1_1->cause.choice.misc = j->cause; - break; - default: - PRINT_ERROR("DRB setup failure cause out of expected range\n"); - break; - } + ieC3_1_1->cause = e1_encode_cause_ie(&j->cause); } return true; } @@ -929,8 +981,8 @@ bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e const pdu_session_setup_t *ps_a = &a->pduSession[i]; const pdu_session_setup_t *ps_b = &b->pduSession[i]; _E1_EQ_CHECK_LONG(ps_a->id, ps_b->id); - _E1_EQ_CHECK_INT(ps_a->tlAddress, ps_b->tlAddress); - _E1_EQ_CHECK_LONG(ps_a->teId, ps_b->teId); + _E1_EQ_CHECK_INT(ps_a->tl_info.tlAddress, ps_b->tl_info.tlAddress); + _E1_EQ_CHECK_LONG(ps_a->tl_info.teId, ps_b->tl_info.teId); _E1_EQ_CHECK_INT(ps_a->numDRBSetup, ps_b->numDRBSetup); _E1_EQ_CHECK_INT(ps_a->numDRBFailed, ps_b->numDRBFailed); // Check DRB Setup @@ -946,8 +998,8 @@ bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e const DRB_nGRAN_failed_t *drbf_a = &ps_a->DRBnGRanFailedList[j]; const DRB_nGRAN_failed_t *drbf_b = &ps_b->DRBnGRanFailedList[j]; _E1_EQ_CHECK_LONG(drbf_a->id, drbf_b->id); - _E1_EQ_CHECK_LONG(drbf_a->cause_type, drbf_b->cause_type); - _E1_EQ_CHECK_LONG(drbf_a->cause, drbf_b->cause); + _E1_EQ_CHECK_LONG(drbf_a->cause.type, drbf_b->cause.type); + _E1_EQ_CHECK_LONG(drbf_a->cause.value, drbf_b->cause.value); } } return true; diff --git a/openair2/E1AP/lib/e1ap_lib_includes.h b/openair2/E1AP/lib/e1ap_lib_includes.h index 443d59e19e..785fd9d09c 100644 --- a/openair2/E1AP/lib/e1ap_lib_includes.h +++ b/openair2/E1AP/lib/e1ap_lib_includes.h @@ -48,6 +48,7 @@ #include "E1AP_System-BearerContextSetupRequest.h" #include "E1AP_MaximumIPdatarate.h" #include "E1AP_PDU-Session-Type.h" +#include "E1AP_Data-Forwarding-Information.h" // E1 Bearer Context Setup Response #include "E1AP_PDU-Session-Resource-Setup-Item.h" #include "E1AP_DRB-Setup-Item-NG-RAN.h" diff --git a/openair2/E1AP/tests/e1ap_lib_test.c b/openair2/E1AP/tests/e1ap_lib_test.c index 9a53e8074d..bc670486cd 100644 --- a/openair2/E1AP/tests/e1ap_lib_test.c +++ b/openair2/E1AP/tests/e1ap_lib_test.c @@ -70,6 +70,14 @@ static void e1ap_msg_free(E1AP_E1AP_PDU_t *pdu) ASN_STRUCT_FREE(asn_DEF_E1AP_E1AP_PDU, pdu); } +static UP_TL_information_t create_up_tl_info(void) +{ + UP_TL_information_t tl_info; + tl_info.tlAddress = htonl(0xC0A90001); // 192.169.0.1 + tl_info.teId = 0x2345; + return tl_info; +} + /** * @brief Test E1AP Bearer Context Setup Request encoding/decoding */ @@ -107,8 +115,8 @@ static void test_bearer_context_setup_request(void) // Step 1: Initialize the E1AP Bearer Context Setup Request e1ap_bearer_setup_req_t orig = { .gNB_cu_cp_ue_id = 1234, - .cipheringAlgorithm = 0x01, - .integrityProtectionAlgorithm = 0x01, + .secInfo.cipheringAlgorithm = 0x01, + .secInfo.integrityProtectionAlgorithm = 0x01, .ueDlAggMaxBitRate = 1000000000, .bearerContextStatus = 0, .servingPLMNid.mcc = 001, @@ -121,8 +129,7 @@ static void test_bearer_context_setup_request(void) .pduSession[0].nssai.sst = 0x01, .pduSession[0].securityIndication = security, .pduSession[0].numDRB2Setup = 1, - .pduSession[0].UP_TL_information.tlAddress = 167772161, - .pduSession[0].UP_TL_information.teId = 0x12345, + .pduSession[0].UP_TL_information = create_up_tl_info(), .pduSession[0].DRBnGRanList[0].id = 1, .pduSession[0].DRBnGRanList[0].sdap_config = sdap, .pduSession[0].DRBnGRanList[0].pdcp_config = pdcp, @@ -132,8 +139,8 @@ static void test_bearer_context_setup_request(void) .pduSession[0].DRBnGRanList[0].numQosFlow2Setup = 1, .pduSession[0].DRBnGRanList[0].qosFlows[0] = qos, }; - memset(orig.encryptionKey, 0xAB, sizeof(orig.encryptionKey)); - memset(orig.integrityProtectionKey, 0xCD, sizeof(orig.integrityProtectionKey)); + memset(orig.secInfo.encryptionKey, 0xAB, sizeof(orig.secInfo.encryptionKey)); + memset(orig.secInfo.integrityProtectionKey, 0xCD, sizeof(orig.secInfo.integrityProtectionKey)); // E1AP encode the original message E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_request(&orig); // E1AP decode the encoded message @@ -171,8 +178,7 @@ static void test_bearer_context_setup_response(void) .gNB_cu_up_ue_id = 5678, .numPDUSessions = 1, .pduSession[0].id = 1, - .pduSession[0].tlAddress = 167772161, - .pduSession[0].teId = 0x12345, + .pduSession[0].tl_info = create_up_tl_info(), .pduSession[0].numDRBSetup = 1, .pduSession[0].numDRBFailed = 0, .pduSession[0].DRBnGRanList[0].id = 1, @@ -180,8 +186,7 @@ static void test_bearer_context_setup_response(void) .pduSession[0].DRBnGRanList[0].numQosFlowSetup = 1, .pduSession[0].DRBnGRanList[0].qosFlows[0].qfi = 1, .pduSession[0].DRBnGRanList[0].UpParamList[0].cell_group_id = MCG, - .pduSession[0].DRBnGRanList[0].UpParamList[0].teId = 0x34345, - .pduSession[0].DRBnGRanList[0].UpParamList[0].tlAddress = 167772161, + .pduSession[0].DRBnGRanList[0].UpParamList[0].tl_info = create_up_tl_info(), }; // E1AP encode the original message E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_response(&orig); diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 380ae1f60a..ed39dbeff0 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -168,7 +168,6 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) const pdu_session_to_setup_t *req_pdu = req->pduSession + i; resp_pdu->id = req_pdu->sessionId; - AssertFatal(req_pdu->numDRB2Modify == 0, "DRB modification not implemented\n"); AssertFatal(req_pdu->numDRB2Setup == 1, "can only handle one DRB per PDU session\n"); resp_pdu->numDRBSetup = req_pdu->numDRB2Setup; const DRB_nGRAN_to_setup_t *req_drb = &req_pdu->DRBnGRanList[0]; @@ -178,7 +177,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup; for (int k = 0; k < resp_drb->numQosFlowSetup; k++) { const qos_flow_to_setup_t *qosflow2Setup = &req_drb->qosFlows[k]; - qos_flow_setup_t *qosflowSetup = &resp_drb->qosFlows[k]; + qos_flow_list_t *qosflowSetup = &resp_drb->qosFlows[k]; qosflowSetup->qfi = qosflow2Setup->qfi; } @@ -197,17 +196,17 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) &resp_n3); AssertFatal(ret >= 0, "Unable to create GTP Tunnel for NG-U\n"); AssertFatal(resp_n3.num_tunnels == req_pdu->numDRB2Setup, "could not create all tunnels\n"); - resp_pdu->teId = resp_n3.gnb_NGu_teid[0]; - memcpy(&resp_pdu->tlAddress, &resp_n3.gnb_addr.buffer, 4); + resp_pdu->tl_info.teId = resp_n3.gnb_NGu_teid[0]; + memcpy(&resp_pdu->tl_info.tlAddress, &resp_n3.gnb_addr.buffer, 4); // create PDCP bearers. This will also create SDAP bearers NR_DRB_ToAddModList_t DRB_configList = {0}; fill_DRB_configList_e1(&DRB_configList, req_pdu); nr_pdcp_entity_security_keys_and_algos_t security_parameters; - security_parameters.ciphering_algorithm = req->cipheringAlgorithm; - security_parameters.integrity_algorithm = req->integrityProtectionAlgorithm; - memcpy(security_parameters.ciphering_key, req->encryptionKey, NR_K_KEY_SIZE); - memcpy(security_parameters.integrity_key, req->integrityProtectionKey, NR_K_KEY_SIZE); + security_parameters.ciphering_algorithm = req->secInfo.cipheringAlgorithm; + security_parameters.integrity_algorithm = req->secInfo.integrityProtectionAlgorithm; + memcpy(security_parameters.ciphering_key, req->secInfo.encryptionKey, NR_K_KEY_SIZE); + memcpy(security_parameters.integrity_key, req->secInfo.integrityProtectionKey, NR_K_KEY_SIZE); nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE cu_up_ue_id, &DRB_configList, @@ -230,8 +229,8 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) &resp_f1); resp_drb->numUpParam = 1; AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n"); - memcpy(&resp_drb->UpParamList[0].tlAddress, &resp_f1.gnb_addr.buffer, 4); - resp_drb->UpParamList[0].teId = resp_f1.gnb_NGu_teid[0]; + memcpy(&resp_drb->UpParamList[0].tl_info.tlAddress, &resp_f1.gnb_addr.buffer, 4); + resp_drb->UpParamList[0].tl_info.teId = resp_f1.gnb_NGu_teid[0]; } // We assume all DRBs to setup have been setup successfully, so we always @@ -273,12 +272,14 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j]; modified->id = to_modif->id; - if (to_modif->pdcp_config.pDCP_Reestablishment) { + if (to_modif->pdcp_config && to_modif->pdcp_config->pDCP_Reestablishment) { nr_pdcp_entity_security_keys_and_algos_t security_parameters; - security_parameters.ciphering_algorithm = req->cipheringAlgorithm; - security_parameters.integrity_algorithm = req->integrityProtectionAlgorithm; - memcpy(security_parameters.ciphering_key, req->encryptionKey, NR_K_KEY_SIZE); - memcpy(security_parameters.integrity_key, req->integrityProtectionKey, NR_K_KEY_SIZE); + if (req->secInfo) { + security_parameters.ciphering_algorithm = req->secInfo->cipheringAlgorithm; + security_parameters.integrity_algorithm = req->secInfo->integrityProtectionAlgorithm; + memcpy(security_parameters.ciphering_key, req->secInfo->encryptionKey, NR_K_KEY_SIZE); + memcpy(security_parameters.integrity_key, req->secInfo->integrityProtectionKey, NR_K_KEY_SIZE); + } nr_pdcp_reestablishment(req->gNB_cu_up_ue_id, to_modif->id, false, @@ -291,8 +292,8 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) /* Loop through DL UP Transport Layer params list * and update GTP tunnel outgoing addr and TEID */ for (int k = 0; k < to_modif->numDlUpParam; k++) { - in_addr_t addr = to_modif->DlUpParamList[k].tlAddress; - GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[k].teId); + in_addr_t addr = to_modif->DlUpParamList[k].tl_info.tlAddress; + GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[k].tl_info.teId); } } } diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h index 7290043371..5d6860f2a7 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h @@ -27,9 +27,10 @@ void nr_pdcp_e1_if_init(bool uses_e1); struct e1ap_bearer_setup_req_s; +struct e1ap_bearer_mod_req_s; struct e1ap_bearer_release_cmd_s; void e1_bearer_context_setup(const struct e1ap_bearer_setup_req_s *req); -void e1_bearer_context_modif(const struct e1ap_bearer_setup_req_s *req); +void e1_bearer_context_modif(const struct e1ap_bearer_mod_req_s *req); void e1_bearer_release_cmd(const struct e1ap_bearer_release_cmd_s *cmd); #endif /* CUCP_CUUP_HANDLER_H */ diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h index 86b3a2435e..418e1f362e 100644 --- a/openair2/RRC/NR/cucp_cuup_if.h +++ b/openair2/RRC/NR/cucp_cuup_if.h @@ -29,9 +29,11 @@ #include "common/platform_types.h" struct e1ap_bearer_setup_req_s; +struct e1ap_bearer_mod_req_s; struct e1ap_bearer_setup_resp_s; struct e1ap_bearer_release_cmd_s; typedef void (*cucp_cuup_bearer_context_setup_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_setup_req_s *req); +typedef void (*cucp_cuup_bearer_context_mod_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_mod_req_s *req); typedef void (*cucp_cuup_bearer_context_release_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_release_cmd_s *cmd); struct gNB_RRC_INST_s; diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 953f723853..0861ebedb2 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -345,7 +345,7 @@ typedef struct nr_mac_rrc_dl_if_s { typedef struct cucp_cuup_if_s { cucp_cuup_bearer_context_setup_func_t bearer_context_setup; - cucp_cuup_bearer_context_setup_func_t bearer_context_mod; + cucp_cuup_bearer_context_mod_func_t bearer_context_mod; cucp_cuup_bearer_context_release_func_t bearer_context_release; } cucp_cuup_if_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index b4d33b16f0..6cfb0047af 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -740,6 +740,14 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size); } +static void fill_security_info(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, security_information_t *secInfo) +{ + secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; + secInfo->integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? UE->integrity_algorithm : 0; + nr_derive_key(UP_ENC_ALG, secInfo->cipheringAlgorithm, UE->kgnb, (uint8_t *)secInfo->encryptionKey); + nr_derive_key(UP_INT_ALG, secInfo->integrityProtectionAlgorithm, UE->kgnb, (uint8_t *)secInfo->integrityProtectionKey); +} + /* \brief find existing PDU session inside E1AP Bearer Modif message, or * point to new one. * \param bearer_modif E1AP Bearer Modification Message @@ -797,21 +805,20 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; drb_e1->id = drb_id; drb_e1->numDlUpParam = 1; - memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); - drb_e1->DlUpParamList[0].teId = drb->du_tunnel_config.teid; + memcpy(&drb_e1->DlUpParamList[0].tl_info.tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); + drb_e1->DlUpParamList[0].tl_info.teId = drb->du_tunnel_config.teid; /* PDCP configuration */ - bearer_context_pdcp_config_t *pdcp_config = &drb_e1->pdcp_config; + if (!drb_e1->pdcp_config) + drb_e1->pdcp_config = malloc_or_fail(sizeof(*drb_e1->pdcp_config)); + bearer_context_pdcp_config_t *pdcp_config = drb_e1->pdcp_config; set_bearer_context_pdcp_config(pdcp_config, drb, rrc->configuration.um_on_default_drb); pdcp_config->pDCP_Reestablishment = true; /* increase DRB to modify counter */ pdu_e1->numDRB2Modify += 1; } - - req.cipheringAlgorithm = rrc->security.do_drb_ciphering ? ue_p->ciphering_algorithm : 0; - req.integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? ue_p->integrity_algorithm : 0; - nr_derive_key(UP_ENC_ALG, req.cipheringAlgorithm, ue_p->kgnb, (uint8_t *)req.encryptionKey); - nr_derive_key(UP_INT_ALG, req.integrityProtectionAlgorithm, ue_p->kgnb, (uint8_t *)req.integrityProtectionKey); - + // Always send security information + req.secInfo = malloc_or_fail(sizeof(*req.secInfo)); + fill_security_info(rrc, ue_p, req.secInfo); /* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p); rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); @@ -1859,12 +1866,12 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC /* \brief fill E1 bearer modification's DRB from F1 DRB * \param drb_e1 pointer to a DRB inside an E1 bearer modification message * \param drb_f1 pointer to a DRB inside an F1 UE Ctxt modification Response */ -static void fill_e1_bearer_modif(DRB_nGRAN_to_setup_t *drb_e1, const f1ap_drb_to_be_setup_t *drb_f1) +static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_to_be_setup_t *drb_f1) { drb_e1->id = drb_f1->drb_id; drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length; - drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address; - drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid; + drb_e1->DlUpParamList[0].tl_info.tlAddress = drb_f1->up_dl_tnl[0].tl_address; + drb_e1->DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid; } /** @@ -1896,8 +1903,8 @@ static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_R */ static void f1u_ul_gtp_update(f1u_tunnel_t *f1u, const up_params_t *p) { - f1u->teid = p->teId; - memcpy(&f1u->addr.buffer, &p->tlAddress, sizeof(uint8_t) * 4); + 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); } @@ -1923,10 +1930,10 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %ld\n", UE->rrc_ue_id, drb_f1->drb_id); continue; } - pdu_session_to_setup_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id); + pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id); DevAssert(pdu_e1 != NULL); pdu_e1->sessionId = pdu_ue->param.pdusession_id; - DRB_nGRAN_to_setup_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; + DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; /* Fill E1 bearer context modification */ fill_e1_bearer_modif(drb_e1, drb_f1); pdu_e1->numDRB2Modify += 1; @@ -1934,10 +1941,9 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f DevAssert(req.numPDUSessionsMod > 0); DevAssert(req.numPDUSessions == 0); - req.cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; - req.integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? UE->integrity_algorithm : 0; - nr_derive_key(UP_ENC_ALG, req.cipheringAlgorithm, UE->kgnb, (uint8_t *)req.encryptionKey); - nr_derive_key(UP_INT_ALG, req.integrityProtectionAlgorithm, UE->kgnb, (uint8_t *)req.integrityProtectionKey); + // Always send security information + req.secInfo = malloc_or_fail(sizeof(*req.secInfo)); + fill_security_info(rrc, UE, req.secInfo); // send the E1 bearer modification request message to update F1-U tunnel info sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE); @@ -2275,9 +2281,9 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; drb->drb_id = pduSession[p].DRBnGRanList[i].id; drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; - drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress; + drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress; drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId; + drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId; drb->up_ul_tnl_length = 1; /* pass QoS info to MAC */ @@ -2328,8 +2334,8 @@ 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->teId; - memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tlAddress, sizeof(uint8_t) * 4); + 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); // save the tunnel address for the DRBs diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 08f83ea5c8..7f17baea4a 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -355,10 +355,11 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession session->nssai = sessions[i].nssai; decodePDUSessionResourceSetup(session); bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; - bearer_req.cipheringAlgorithm = UE->ciphering_algorithm; - bearer_req.integrityProtectionAlgorithm = UE->integrity_algorithm; - nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, (uint8_t *)bearer_req.encryptionKey); - nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, (uint8_t *)bearer_req.integrityProtectionKey); + security_information_t *secInfo = &bearer_req.secInfo; + secInfo->cipheringAlgorithm = UE->ciphering_algorithm; + secInfo->integrityProtectionAlgorithm = UE->integrity_algorithm; + nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, (uint8_t *)secInfo->encryptionKey); + nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, (uint8_t *)secInfo->integrityProtectionKey); bearer_req.ueDlAggMaxBitRate = ueAggMaxBitRateDownlink; pdu_session_to_setup_t *pdu = bearer_req.pduSession + bearer_req.numPDUSessions; bearer_req.numPDUSessions++;