Commit 85949411 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/e1ap-lib-improvements' into integration_2025_w06 (!3219)

E1AP enc/dec lib improvements

This MR is including some fixes and improvements for the E1AP library,
focusing mostly on Bearer Context Management:

- struct reorganization: split setup and modification request messages
  into distinct structures, ensuring compliance with 3GPP TS 38.463
  specifications
- add encoding/decoding sub-functions for different IEs
- improvements to Bearer Context Management: Implemented various
  improvements to the E1 Bearer Context Setup Response and Request,
  including the adoption of encoding/decoding sub-functions for
  different IEs
- use lib functions whenever need (e.g. cp_bearer_context_setup_request
  in cucp_cuup_e1ap.c)
- handle optional struct members as pointers
- updated copy/equality check utility functions

EDIT: The MR is also including the changes from !3222 (closed):

> While testing E1 with security enabled for DRBs, it was found that
> data traffic was not functional.
>
> The problem was that security settings were modified in the PDCP
> reestablishment happening when receiving Bearer Context Modification
> Request.
>
> So some restructuring was done.
>
> The actual fix is in 18176297, the others are for support. Basically
> we introduce a boolean to check if the security settings are present in
> Bearer Context Modification Request and we change PDCP security settings
> only if they are.
>
> (Note that in OAI CU security settings are not sent in Bearer Context
> Modification Request, so we could also remove all this, but we need to
> be compatible with other cu-up and/or cu-cp.)
parents 805ed557 ac6b1b18
...@@ -9,6 +9,7 @@ services: ...@@ -9,6 +9,7 @@ services:
environment: environment:
USE_ADDITIONAL_OPTIONS: --telnetsrv --telnetsrv.listenport 9090 --telnetsrv.shrmod ci USE_ADDITIONAL_OPTIONS: --telnetsrv --telnetsrv.listenport 9090 --telnetsrv.shrmod ci
--log_config.global_log_options level,nocolor,time,line_num,function --log_config.global_log_options level,nocolor,time,line_num,function
--security.drb_integrity yes
volumes: volumes:
- ../../conf_files/gnb-cucp.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf - ../../conf_files/gnb-cucp.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf
# for performance reasons, we use host mode: in bridge mode, we have # for performance reasons, we use host mode: in bridge mode, we have
......
...@@ -125,7 +125,7 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t ...@@ -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); } 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_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(); } 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) { int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
......
...@@ -51,7 +51,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) ...@@ -51,7 +51,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
{ {
abort(); 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(); abort();
} }
......
...@@ -126,7 +126,7 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t ...@@ -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 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_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(); } 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) { int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
......
...@@ -138,12 +138,6 @@ typedef enum BEARER_CONTEXT_STATUS_e { ...@@ -138,12 +138,6 @@ typedef enum BEARER_CONTEXT_STATUS_e {
BEARER_RESUME, BEARER_RESUME,
} BEARER_CONTEXT_STATUS_t; } BEARER_CONTEXT_STATUS_t;
typedef enum activity_notification_level_e {
ANL_DRB = 0,
ANL_PDU_SESSION,
ANL_UE,
} activity_notification_level_t;
typedef enum cell_group_id_e { typedef enum cell_group_id_e {
MCG = 0, MCG = 0,
SCG, SCG,
...@@ -258,10 +252,16 @@ typedef struct e1ap_setup_fail_s { ...@@ -258,10 +252,16 @@ typedef struct e1ap_setup_fail_s {
criticality_diagnostics_t *crit_diag; criticality_diagnostics_t *crit_diag;
} e1ap_setup_fail_t; } e1ap_setup_fail_t;
typedef struct up_params_s { typedef struct UP_TL_information_s {
in_addr_t tlAddress; in_addr_t tlAddress;
long teId; int32_t teId;
int cell_group_id; } 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; } up_params_t;
/* IE SDAP Configuration (clause 9.3.1.39 of 3GPP TS 38.463) */ /* IE SDAP Configuration (clause 9.3.1.39 of 3GPP TS 38.463) */
...@@ -331,38 +331,63 @@ typedef struct qos_flow_level_qos_parameters_s { ...@@ -331,38 +331,63 @@ typedef struct qos_flow_level_qos_parameters_s {
ngran_allocation_retention_priority_t alloc_reten_priority; // additional members should be added!! ngran_allocation_retention_priority_t alloc_reten_priority; // additional members should be added!!
} qos_flow_level_qos_parameters_t; } qos_flow_level_qos_parameters_t;
// QoS Flow QoS Parameters List 9.3.1.25
typedef struct qos_flow_setup_e { typedef struct qos_flow_setup_e {
long qfi; // qos flow identifier long qfi; // qos flow identifier
qos_flow_level_qos_parameters_t qos_params; qos_flow_level_qos_parameters_t qos_params;
} qos_flow_to_setup_t; } 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 { typedef struct DRB_nGRAN_to_setup_s {
/* DRB ID (clause 9.3.1.16) */ // DRB ID (M) (clause 9.3.1.16)
long id; long id;
// SDAP Configuration (M) (clause 9.3.1.39)
/* SDAP Configuration (clause 9.3.1.39) */
bearer_context_sdap_config_t sdap_config; 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; bearer_context_pdcp_config_t pdcp_config;
// DRB Inactivity Timer (O)
/* DRB Data Forwarding Information (clause 9.3.2.6) */ int *drb_inactivity_timer;
/* Transport Layer Address (clause 9.3.2.4) */ // Cell Group Information (M) (clause 9.3.1.11)
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) */
int numCellGroups; int numCellGroups;
cell_group_id_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; cell_group_id_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS];
// 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 QoS Flows Parameters (clause 9.3.1.26) */ /**
* 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; int numQosFlow2Setup;
qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS];
} DRB_nGRAN_to_setup_t, DRB_nGRAN_to_mod_t; } DRB_nGRAN_to_mod_t;
typedef enum e1ap_indication_e { typedef enum e1ap_indication_e {
SECURITY_REQUIRED = 0, SECURITY_REQUIRED = 0,
...@@ -377,48 +402,108 @@ typedef struct security_indication_s { ...@@ -377,48 +402,108 @@ typedef struct security_indication_s {
long maxIPrate; long maxIPrate;
} security_indication_t; } security_indication_t;
typedef struct UP_TL_information_s { // Security Information (9.3.1.10)
in_addr_t tlAddress; typedef struct security_information_s {
int32_t teId; uint64_t cipheringAlgorithm;
} UP_TL_information_t; uint64_t integrityProtectionAlgorithm;
char encryptionKey[E1AP_SECURITY_KEY_SIZE];
char integrityProtectionKey[E1AP_SECURITY_KEY_SIZE];
} security_information_t;
/** /**
* PDU Session Resource To Setup List (clause 9.3.3.10) * PDU Session Resource To Setup List (clause 9.3.3.10)
* PDU Session Resource To Modify List (clause 9.3.3.11) */
*/
typedef struct pdu_session_to_setup_s { typedef struct pdu_session_to_setup_s {
// PDU Session ID (M)
long sessionId; long sessionId;
// PDU Session Type (M)
long sessionType; long sessionType;
// S-NSSAI (M)
e1ap_nssai_t nssai; e1ap_nssai_t nssai;
// Security Indication (M)
security_indication_t securityIndication; 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; UP_TL_information_t UP_TL_information;
long numDRB2Setup; // PDU Session Inactivity Timer (O)
int *inactivityTimer;
// DRB To Setup List (M)
int numDRB2Setup;
// DRB To Setup Item (1..<E1AP_MAX_NUM_DRBS>)
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..<E1AP_MAX_NUM_DRBS>)
DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS]; DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS];
// DRB To Modify List (0..1)
long numDRB2Modify; long numDRB2Modify;
// DRB To Modify Item (1..<E1AP_MAX_NUM_DRBS>)
DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS];
} pdu_session_to_setup_t, pdu_session_to_mod_t; } pdu_session_to_mod_t;
/** /**
* Bearer Context Setup Request message, clause 9.2.2.1 of 3GPP TS 38.463 * 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 { typedef struct e1ap_bearer_setup_req_s {
// gNB-CU-CP UE E1AP ID (M)
uint32_t gNB_cu_cp_ue_id; uint32_t gNB_cu_cp_ue_id;
uint32_t gNB_cu_up_ue_id; // Bearer Context Modification Request only // Security Information (M)
uint64_t cipheringAlgorithm; security_information_t secInfo;
uint64_t integrityProtectionAlgorithm; // UE DL Aggregate Maximum Bit Rate (M)
char encryptionKey[E1AP_SECURITY_KEY_SIZE]; long ueDlAggMaxBitRate;
char integrityProtectionKey[E1AP_SECURITY_KEY_SIZE]; // UE DL Maximum Integrity Protected Data Rate (O)
long ueDlAggMaxBitRate; long *ueDlMaxIPBitRate;
// Serving PLMN (M)
PLMN_ID_t servingPLMNid; PLMN_ID_t servingPLMNid;
// Bearer Context Status Change (O)
BEARER_CONTEXT_STATUS_t bearerContextStatus; BEARER_CONTEXT_STATUS_t bearerContextStatus;
activity_notification_level_t activityNotificationLevel; // UE Inactivity Timer (O)
int *inactivityTimerUE;
// NG-RAN PDU Session Resource To Setup List (M)
int numPDUSessions; int numPDUSessions;
pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS];
} 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; int numPDUSessionsMod;
pdu_session_to_mod_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; 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 { typedef struct e1ap_bearer_release_cmd_s {
uint32_t gNB_cu_cp_ue_id; uint32_t gNB_cu_cp_ue_id;
...@@ -432,43 +517,61 @@ typedef struct e1ap_bearer_release_cplt_s { ...@@ -432,43 +517,61 @@ typedef struct e1ap_bearer_release_cplt_s {
uint32_t gNB_cu_up_ue_id; uint32_t gNB_cu_up_ue_id;
} e1ap_bearer_release_cplt_t; } e1ap_bearer_release_cplt_t;
typedef struct qos_flow_setup_s {
long qfi;
} qos_flow_setup_t;
typedef struct DRB_nGRAN_setup_s { typedef struct DRB_nGRAN_setup_s {
// DRB ID (M)
long id; long id;
int numUpParam; int numUpParam;
up_params_t UpParamList[E1AP_MAX_NUM_UP_PARAM]; up_params_t UpParamList[E1AP_MAX_NUM_UP_PARAM];
// Flow Setup List (M)
int numQosFlowSetup; 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_nGRAN_setup_t;
/* DRB Modified Item */
typedef struct DRB_nGRAN_modified_s { typedef struct DRB_nGRAN_modified_s {
// DRB ID (M)
long id; 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; } DRB_nGRAN_modified_t;
typedef struct DRB_nGRAN_failed_s { typedef struct DRB_nGRAN_failed_s {
long id; long id;
long cause_type; e1ap_cause_t cause;
long cause;
} DRB_nGRAN_failed_t; } DRB_nGRAN_failed_t;
typedef struct pdu_session_setup_s { typedef struct pdu_session_setup_s {
long id; long id;
in_addr_t tlAddress; // Transport layer info
long teId; UP_TL_information_t tl_info;
int numDRBSetup; int numDRBSetup;
DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS]; DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS];
int numDRBFailed; int numDRBFailed;
DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_DRBS]; DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_DRBS];
} pdu_session_setup_t; } pdu_session_setup_t;
/* PDU Session Resource Modified List (9.3.3.17) */
typedef struct pdu_session_modif_s { typedef struct pdu_session_modif_s {
// PDU Session ID (M)
long id; 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; int numDRBModified;
DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; 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; } pdu_session_modif_t;
typedef struct e1ap_bearer_setup_resp_s { typedef struct e1ap_bearer_setup_resp_s {
...@@ -479,8 +582,11 @@ typedef struct e1ap_bearer_setup_resp_s { ...@@ -479,8 +582,11 @@ typedef struct e1ap_bearer_setup_resp_s {
} e1ap_bearer_setup_resp_t; } e1ap_bearer_setup_resp_t;
typedef struct e1ap_bearer_modif_resp_s { typedef struct e1ap_bearer_modif_resp_s {
// gNB-CU-CP UE E1AP ID (M)
uint32_t gNB_cu_cp_ue_id; uint32_t gNB_cu_cp_ue_id;
// gNB-CU-UP UE E1AP ID (M)
uint32_t gNB_cu_up_ue_id; uint32_t gNB_cu_up_ue_id;
// NG-RAN PDU Session Resource Modified List (O)
int numPDUSessionsMod; int numPDUSessionsMod;
pdu_session_modif_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; pdu_session_modif_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS];
} e1ap_bearer_modif_resp_t; } e1ap_bearer_modif_resp_t;
......
...@@ -10,3 +10,7 @@ target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR}) ...@@ -10,3 +10,7 @@ target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR})
if(ENABLE_TESTS) if(ENABLE_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()
if(ENABLE_TESTS)
target_compile_definitions(e1ap PRIVATE E1AP_LOG_ERRORS)
endif()
...@@ -431,7 +431,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upc ...@@ -431,7 +431,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upc
BEARER CONTEXT MODIFICATION REQUEST 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; pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu->choice.initiatingMessage, msg); asn1cCalloc(pdu->choice.initiatingMessage, msg);
...@@ -453,6 +453,21 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con ...@@ -453,6 +453,21 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con
ieC2->criticality = E1AP_Criticality_reject; ieC2->criticality = E1AP_Criticality_reject;
ieC2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; ieC2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID;
ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = bearerCxt->gNB_cu_up_ue_id; ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = bearerCxt->gNB_cu_up_ue_id;
/* optional */
/* Security Information */
if (bearerCxt->secInfo) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie);
ie->id = E1AP_ProtocolIE_ID_id_SecurityInformation;
ie->criticality = E1AP_Criticality_reject;
ie->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_SecurityInformation;
E1AP_SecurityAlgorithm_t *securityAlgorithm = &ie->value.choice.SecurityInformation.securityAlgorithm;
E1AP_UPSecuritykey_t *uPSecuritykey = &ie->value.choice.SecurityInformation.uPSecuritykey;
securityAlgorithm->cipheringAlgorithm = bearerCxt->secInfo->cipheringAlgorithm;
OCTET_STRING_fromBuf(&uPSecuritykey->encryptionKey, bearerCxt->secInfo->encryptionKey, E1AP_SECURITY_KEY_SIZE);
asn1cCallocOne(securityAlgorithm->integrityProtectionAlgorithm, bearerCxt->secInfo->integrityProtectionAlgorithm);
asn1cCalloc(uPSecuritykey->integrityProtectionKey, protKey);
OCTET_STRING_fromBuf(protKey, bearerCxt->secInfo->integrityProtectionKey, E1AP_SECURITY_KEY_SIZE);
}
/* optional */ /* optional */
/* c3. E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest */ /* c3. E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest */
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC3); asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC3);
...@@ -475,7 +490,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con ...@@ -475,7 +490,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); asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod);
drb2Mod->dRB_ID = j->id; drb2Mod->dRB_ID = j->id;
asn1cCalloc(drb2Mod->pDCP_Configuration, pDCP_Configuration); 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); asn1cCallocOne(pDCP_Configuration->pDCP_Reestablishment, E1AP_PDCP_Reestablishment_true);
} }
if (j->numDlUpParam > 0) { if (j->numDlUpParam > 0) {
...@@ -484,8 +499,8 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con ...@@ -484,8 +499,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); 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; DL_UP_Param->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel;
asn1cCalloc(DL_UP_Param->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); asn1cCalloc(DL_UP_Param->uP_TNL_Information.choice.gTPTunnel, gTPTunnel);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tl_info.tlAddress, &gTPTunnel->transportLayerAddress);
INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); INT32_TO_OCTET_STRING(k->tl_info.teId, &gTPTunnel->gTP_TEID);
DL_UP_Param->cell_Group_ID = k->cell_group_id; DL_UP_Param->cell_Group_ID = k->cell_group_id;
} }
...@@ -493,7 +508,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con ...@@ -493,7 +508,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con
} }
} }
/* c4. E1AP_ProtocolIE_ID_id_BearerContextStatusChange */ /* 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); asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC4);
ieC4->id = E1AP_ProtocolIE_ID_id_BearerContextStatusChange; ieC4->id = E1AP_ProtocolIE_ID_id_BearerContextStatusChange;
ieC4->criticality = E1AP_Criticality_reject; ieC4->criticality = E1AP_Criticality_reject;
...@@ -608,6 +623,26 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p ...@@ -608,6 +623,26 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p
bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
break; break;
case E1AP_ProtocolIE_ID_id_SecurityInformation: {
DevAssert(ie->criticality == E1AP_Criticality_reject);
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_SecurityInformation);
E1AP_SecurityInformation_t *sec = &ie->value.choice.SecurityInformation;
DevAssert(sec->uPSecuritykey.encryptionKey.size == E1AP_SECURITY_KEY_SIZE);
DevAssert(sec->uPSecuritykey.integrityProtectionKey == NULL
|| sec->uPSecuritykey.integrityProtectionKey->size == E1AP_SECURITY_KEY_SIZE);
bearerCxt->secInfo = malloc_or_fail(sizeof(*bearerCxt->secInfo));
bearerCxt->secInfo->cipheringAlgorithm = sec->securityAlgorithm.cipheringAlgorithm;
bearerCxt->secInfo->integrityProtectionAlgorithm = sec->securityAlgorithm.integrityProtectionAlgorithm == NULL
? 0
: *sec->securityAlgorithm.integrityProtectionAlgorithm;
memcpy(bearerCxt->secInfo->encryptionKey, sec->uPSecuritykey.encryptionKey.buf, E1AP_SECURITY_KEY_SIZE);
if (sec->securityAlgorithm.integrityProtectionAlgorithm == NULL)
memset(bearerCxt->secInfo->integrityProtectionKey, 0, E1AP_SECURITY_KEY_SIZE);
else
memcpy(bearerCxt->secInfo->integrityProtectionKey, sec->uPSecuritykey.integrityProtectionKey->buf, E1AP_SECURITY_KEY_SIZE);
break;
}
case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest: case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest:
DevAssert(ie->criticality == E1AP_Criticality_reject); DevAssert(ie->criticality == E1AP_Criticality_reject);
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest); DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest);
...@@ -637,7 +672,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p ...@@ -637,7 +672,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p
if (drb2Mod->pDCP_Configuration != NULL if (drb2Mod->pDCP_Configuration != NULL
&& drb2Mod->pDCP_Configuration->pDCP_Reestablishment != NULL && drb2Mod->pDCP_Configuration->pDCP_Reestablishment != NULL
&& *drb2Mod->pDCP_Configuration->pDCP_Reestablishment == E1AP_PDCP_Reestablishment_true) { && *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 */ if (drb2Mod->dL_UP_Parameters) { /* Optional IE in the DRB To Modify Item */
E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters;
...@@ -649,8 +685,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p ...@@ -649,8 +685,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); DevAssert(dl_up_param_in->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel);
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4( BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(
&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress, &dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress,
dl_up_param->tlAddress); dl_up_param->tl_info.tlAddress);
OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->teId); OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->tl_info.teId);
} else { } else {
AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n"); AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n");
} }
...@@ -665,7 +701,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p ...@@ -665,7 +701,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p
/* Bearer Context Status Change */ /* Bearer Context Status Change */
DevAssert(ie->criticality == E1AP_Criticality_reject); DevAssert(ie->criticality == E1AP_Criticality_reject);
DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange); 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; break;
default: default:
...@@ -1131,7 +1168,7 @@ static void e1_task_handle_sctp_association_resp(E1_t type, ...@@ -1131,7 +1168,7 @@ static void e1_task_handle_sctp_association_resp(E1_t type,
if (getCxtE1(instance)->gtpInstF1U < 0) if (getCxtE1(instance)->gtpInstF1U < 0)
getCxtE1(instance)->gtpInstF1U = cuup_task_create_gtpu_instance_to_du(&IPaddr); getCxtE1(instance)->gtpInstF1U = cuup_task_create_gtpu_instance_to_du(&IPaddr);
if (getCxtE1(instance)->gtpInstF1U < 0) if (getCxtE1(instance)->gtpInstF1U < 0)
LOG_E(E1AP, "Failed to create CUUP F1-U UDP listener"); LOG_E(E1AP, "Failed to create CUUP F1-U UDP listener\n");
extern instance_t CUuniqInstance; extern instance_t CUuniqInstance;
CUuniqInstance = getCxtE1(instance)->gtpInstF1U; CUuniqInstance = getCxtE1(instance)->gtpInstF1U;
cuup_init_n3(instance); cuup_init_n3(instance);
...@@ -1154,7 +1191,7 @@ void cuup_init_n3(instance_t instance) ...@@ -1154,7 +1191,7 @@ void cuup_init_n3(instance_t instance)
legacyInstanceMapping = getCxtE1(instance)->gtpInstN3 = gtpv1Init(tmp); legacyInstanceMapping = getCxtE1(instance)->gtpInstN3 = gtpv1Init(tmp);
} }
if (getCxtE1(instance)->gtpInstN3 < 0) if (getCxtE1(instance)->gtpInstN3 < 0)
LOG_E(E1AP, "Failed to create CUUP N3 UDP listener"); LOG_E(E1AP, "Failed to create CUUP N3 UDP listener\n");
extern instance_t *N3GTPUInst; extern instance_t *N3GTPUInst;
N3GTPUInst = &getCxtE1(instance)->gtpInstN3; N3GTPUInst = &getCxtE1(instance)->gtpInstN3;
} }
......
add_library(e1ap_lib OBJECT add_library(e1ap_lib OBJECT
e1ap_bearer_context_management.c e1ap_bearer_context_management.c
e1ap_interface_management.c e1ap_interface_management.c
e1ap_lib_common.c
) )
target_link_libraries(e1ap_lib PRIVATE asn1_e1ap) target_link_libraries(e1ap_lib PRIVATE asn1_e1ap)
......
...@@ -37,9 +37,130 @@ ...@@ -37,9 +37,130 @@
#include "e1ap_bearer_context_management.h" #include "e1ap_bearer_context_management.h"
#include "e1ap_lib_includes.h" #include "e1ap_lib_includes.h"
/* ==================================== /** @brief Encode E1AP_SecurityIndication_t (3GPP TS 38.463 9.3.1.23) */
* E1AP Bearer Context Setup Request 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 * @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 ...@@ -55,6 +176,25 @@ static bool eq_pdcp_config(const bearer_context_pdcp_config_t *a, const bearer_c
return true; 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 = {0};
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 * @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 ...@@ -66,6 +206,69 @@ static bool eq_sdap_config(const bearer_context_sdap_config_t *a, const bearer_c
return true; 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 * @brief Equality check for qos_flow_to_setup_t
*/ */
...@@ -90,30 +293,66 @@ static bool eq_qos_flow(const qos_flow_to_setup_t *a, const qos_flow_to_setup_t ...@@ -90,30 +293,66 @@ static bool eq_qos_flow(const qos_flow_to_setup_t *a, const qos_flow_to_setup_t
return true; return true;
} }
/** @brief S-NSSAI Encoding (3GPP TS 38.463 9.3.1.9) */
static E1AP_SNSSAI_t e1_encode_snssai(const nssai_t *in)
{
E1AP_SNSSAI_t out = {0};
INT8_TO_OCTET_STRING(in->sst, &out.sST);
if (in->sd != 0xffffff) {
out.sD = malloc_or_fail(sizeof(*out.sD));
INT24_TO_OCTET_STRING(in->sd, out.sD);
}
return out;
}
/** @brief S-NSSAI Decoding (3GPP TS 38.463 9.3.1.9) */
static bool e1_decode_snssai(e1ap_nssai_t *out, const E1AP_SNSSAI_t *in)
{
// SST (M)
OCTET_STRING_TO_INT8(&in->sST, out->sst);
out->sd = 0xffffff;
// SD (O)
if (in->sD != NULL)
OCTET_STRING_TO_INT24(in->sD, out->sd);
return true;
}
/** /**
* @brief Equality check for DRB_nGRAN_to_setup_t * @brief Decode E1AP_UP_Parameters_t
*/ */
static bool eq_drb_to_setup(const DRB_nGRAN_to_setup_t *a, const DRB_nGRAN_to_setup_t *b) static int decode_dl_up_parameters(up_params_t *dl_up_param, const E1AP_UP_Parameters_t *dl_up_paramList)
{ {
bool result = true; for (int k = 0; k < dl_up_paramList->list.count; k++) {
_E1_EQ_CHECK_LONG(a->id, b->id); dl_up_param = dl_up_param + k;
_E1_EQ_CHECK_INT(a->numCellGroups, b->numCellGroups); E1AP_UP_Parameters_Item_t *dl_up_param_in = dl_up_paramList->list.array[k];
for (int i = 0; i < a->numCellGroups; i++) { // GTP tunnel
_E1_EQ_CHECK_INT(a->cellGroupList[i], b->cellGroupList[i]); if (!e1_decode_up_tnl_info(&dl_up_param->tl_info, &dl_up_param_in->uP_TNL_Information)) {
PRINT_ERROR("GTP tunnel decoding failed\n");
return -1;
}
// Cell group ID
dl_up_param->cell_group_id = dl_up_param_in->cell_Group_ID;
} }
_E1_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup); return dl_up_paramList->list.count;
for (int i = 0; i < a->numQosFlow2Setup; i++) { }
result &= eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]);
/**
* @brief Encode E1AP_UP_Parameters_t IE
*/
static E1AP_UP_Parameters_t encode_dl_up_parameters(const int numUpParam, const up_params_t *in)
{
E1AP_UP_Parameters_t out = {0};
for (const up_params_t *k = in; k < in + numUpParam; k++) {
asn1cSequenceAdd(out.list, E1AP_UP_Parameters_Item_t, ieC3_1_1_1);
ieC3_1_1_1->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info);
} }
result &= eq_pdcp_config(&a->pdcp_config, &b->pdcp_config); return out;
result &= eq_sdap_config(&a->sdap_config, &b->sdap_config);
return result;
} }
/** /**
* @brief Equality check for DRB_nGRAN_to_mod_t * @brief Equality check for DRB_nGRAN_to_setup_t
*/ */
static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t *b) static bool eq_drb_to_setup(const DRB_nGRAN_to_setup_t *a, const DRB_nGRAN_to_setup_t *b)
{ {
bool result = true; bool result = true;
_E1_EQ_CHECK_LONG(a->id, b->id); _E1_EQ_CHECK_LONG(a->id, b->id);
...@@ -125,127 +364,63 @@ static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t ...@@ -125,127 +364,63 @@ static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t
for (int i = 0; i < a->numQosFlow2Setup; i++) { for (int i = 0; i < a->numQosFlow2Setup; i++) {
result &= eq_qos_flow(&a->qosFlows[i], &b->qosFlows[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_pdcp_config(&a->pdcp_config, &b->pdcp_config);
result &= eq_sdap_config(&a->sdap_config, &b->sdap_config); result &= eq_sdap_config(&a->sdap_config, &b->sdap_config);
return result; return result;
} }
/* PDU Session To Setup Item */ static void free_drb_to_setup_item(const DRB_nGRAN_to_setup_t *msg)
{
free(msg->drb_inactivity_timer);
}
/** @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) 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)
{ {
// PDU Session ID (M)
item->pDU_Session_ID = in->sessionId; item->pDU_Session_ID = in->sessionId;
// PDU Session Type (M)
item->pDU_Session_Type = in->sessionType; item->pDU_Session_Type = in->sessionType;
// SNSSAI // S-NSSAI (M)
INT8_TO_OCTET_STRING(in->nssai.sst, &item->sNSSAI.sST); item->sNSSAI = e1_encode_snssai(&in->nssai);
if (in->nssai.sd != 0xffffff) { // Security Indication (M)
item->sNSSAI.sD = malloc_or_fail(sizeof(*item->sNSSAI.sD)); item->securityIndication = e1_encode_security_indication(&in->securityIndication);
INT24_TO_OCTET_STRING(in->nssai.sd, item->sNSSAI.sD); // NG UL UP Transport Layer Information (M)
} item->nG_UL_UP_TNL_Information = e1_encode_up_tnl_info(&in->UP_TL_information);
// Security Indication // DRB To Setup List (M)
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
for (const DRB_nGRAN_to_setup_t *j = in->DRBnGRanList; j < in->DRBnGRanList + in->numDRB2Setup; j++) { 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); asn1cSequenceAdd(item->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1);
// DRB ID (M)
ieC6_1_1->dRB_ID = j->id; ieC6_1_1->dRB_ID = j->id;
// SDAP Config // SDAP Configuration (M)
E1AP_SDAP_Configuration_t *sdap = &ieC6_1_1->sDAP_Configuration; ieC6_1_1->sDAP_Configuration = e1_encode_sdap_config(&j->sdap_config);
sdap->defaultDRB = j->sdap_config.defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; // PDCP Configuration (M)
sdap->sDAP_Header_UL = j->sdap_config.sDAP_Header_UL; ieC6_1_1->pDCP_Configuration = e1_encode_pdcp_config(&j->pdcp_config);
sdap->sDAP_Header_DL = j->sdap_config.sDAP_Header_DL; // Cell Group Information (M)
// 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
for (const cell_group_id_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) { 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); 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; ieC6_1_1_1->cell_Group_ID = *k;
} }
// QoS Flows // QoS Flows Information To Be Setup (M)
for (const qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) { 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); 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_1->qoS_Flow_Identifier = k->qfi; *ieC6_1_1_2 = e1_encode_qos_flow_to_setup(k);
// 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;
} }
} }
return true; 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) 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) // PDU Session ID (M)
out->sessionId = item->pDU_Session_ID; out->sessionId = item->pDU_Session_ID;
// PDU Session Type (M) // PDU Session Type (M)
out->sessionType = item->pDU_Session_Type; out->sessionType = item->pDU_Session_Type;
/* S-NSSAI (M) */ // S-NSSAI (M)
// SST (M) CHECK_E1AP_DEC(e1_decode_snssai(&out->nssai, &item->sNSSAI));
OCTET_STRING_TO_INT8(&item->sNSSAI.sST, out->nssai.sst); // Security Indication (M)
out->nssai.sd = 0xffffff; CHECK_E1AP_DEC(e1_decode_security_indication(&out->securityIndication, &item->securityIndication));
// 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;
}
}
/* NG UL UP Transport Layer Information (M) (9.3.2.1 of 3GPP TS 38.463) */ /* NG UL UP Transport Layer Information (M) (9.3.2.1 of 3GPP TS 38.463) */
// GTP Tunnel // GTP Tunnel
struct E1AP_GTPTunnel *gTPTunnel = item->nG_UL_UP_TNL_Information.choice.gTPTunnel; struct E1AP_GTPTunnel *gTPTunnel = item->nG_UL_UP_TNL_Information.choice.gTPTunnel;
...@@ -254,12 +429,8 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A ...@@ -254,12 +429,8 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A
return false; return false;
} }
_E1_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel); _E1_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel);
// Transport Layer Address CHECK_E1AP_DEC(e1_decode_up_tnl_info(&out->UP_TL_information, &item->nG_UL_UP_TNL_Information));
UP_TL_information_t *UP_TL_information = &out->UP_TL_information; /* DRB To Setup List ( > 1 item ) */
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 )
E1AP_DRB_To_Setup_List_NG_RAN_t *drb2SetupList = &item->dRB_To_Setup_List_NG_RAN; 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); _E1_EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0);
out->numDRB2Setup = drb2SetupList->list.count; out->numDRB2Setup = drb2SetupList->list.count;
...@@ -269,23 +440,11 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A ...@@ -269,23 +440,11 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A
E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j];
// DRB ID (M) // DRB ID (M)
drb->id = drb2Setup->dRB_ID; drb->id = drb2Setup->dRB_ID;
// >SDAP Configuration (M) // SDAP Configuration (M)
E1AP_SDAP_Configuration_t *sdap = &drb2Setup->sDAP_Configuration; CHECK_E1AP_DEC(e1_decode_sdap_config(&drb->sdap_config, &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;
// PDCP Configuration (M) // PDCP Configuration (M)
E1AP_PDCP_Configuration_t *pdcp = &drb2Setup->pDCP_Configuration; CHECK_E1AP_DEC(e1_decode_pdcp_config(&drb->pdcp_config, &drb2Setup->pDCP_Configuration));
drb->pdcp_config.pDCP_SN_Size_UL = pdcp->pDCP_SN_Size_UL; // Cell Group Information (M)
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 )
E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information;
_E1_EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0); _E1_EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0);
drb->numCellGroups = cellGroupList->list.count; drb->numCellGroups = cellGroupList->list.count;
...@@ -298,44 +457,50 @@ static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1A ...@@ -298,44 +457,50 @@ 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; E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup;
drb->numQosFlow2Setup = qos2SetupList->list.count; drb->numQosFlow2Setup = qos2SetupList->list.count;
for (int k = 0; k < qos2SetupList->list.count; k++) { for (int k = 0; k < qos2SetupList->list.count; k++) {
qos_flow_to_setup_t *qos_flow = drb->qosFlows + k; CHECK_E1AP_DEC(e1_decode_qos_flow_to_setup(drb->qosFlows + k, qos2SetupList->list.array[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;
} }
} }
return true; 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 UP Transport Layer Information (3GPP TS 38.463 9.3.2.1)*/
static bool eq_up_tl_info(const UP_TL_information_t *a, const UP_TL_information_t *b)
{
_E1_EQ_CHECK_INT(a->tlAddress, b->tlAddress);
_E1_EQ_CHECK_INT(a->teId, b->teId);
return true;
}
/** /**
* @brief Equality check for PDU session item to modify/setup * @brief Equality check for PDU session item to modify/setup
*/ */
...@@ -343,57 +508,21 @@ static bool eq_pdu_session_item(const pdu_session_to_setup_t *a, const pdu_sessi ...@@ -343,57 +508,21 @@ static bool eq_pdu_session_item(const pdu_session_to_setup_t *a, const pdu_sessi
{ {
_E1_EQ_CHECK_LONG(a->sessionId, b->sessionId); _E1_EQ_CHECK_LONG(a->sessionId, b->sessionId);
_E1_EQ_CHECK_LONG(a->sessionType, b->sessionType); _E1_EQ_CHECK_LONG(a->sessionType, b->sessionType);
_E1_EQ_CHECK_INT(a->UP_TL_information.tlAddress, b->UP_TL_information.tlAddress); eq_up_tl_info(&a->UP_TL_information, &b->UP_TL_information);
_E1_EQ_CHECK_INT(a->UP_TL_information.teId, b->UP_TL_information.teId); _E1_EQ_CHECK_INT(a->numDRB2Setup, b->numDRB2Setup);
_E1_EQ_CHECK_LONG(a->numDRB2Setup, b->numDRB2Setup);
if (a->numDRB2Setup != b->numDRB2Setup)
return false;
for (int i = 0; i < a->numDRB2Setup; i++) for (int i = 0; i < a->numDRB2Setup; i++)
if (!eq_drb_to_setup(&a->DRBnGRanList[i], &b->DRBnGRanList[i])) if (!eq_drb_to_setup(&a->DRBnGRanList[i], &b->DRBnGRanList[i]))
return false; return false;
_E1_EQ_CHECK_LONG(a->numDRB2Modify, b->numDRB2Modify); _E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer);
if (a->numDRB2Modify != b->numDRB2Modify) if (a->inactivityTimer && b->inactivityTimer)
return false; _E1_EQ_CHECK_INT(a->inactivityTimer, b->inactivityTimer);
for (int i = 0; i < a->numDRB2Modify; i++) _E1_EQ_CHECK_OPTIONAL_IE(a, b, dlAggregateMaxBitRate, _E1_EQ_CHECK_LONG);
if (!eq_drb_to_mod(&a->DRBnGRanModList[i], &b->DRBnGRanModList[i]))
return false;
return true; return true;
} }
static bool cp_pdu_session_item(pdu_session_to_setup_t *cp, const pdu_session_to_setup_t *msg) /* ====================================
{ * E1AP Bearer Context Setup Request
// 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;
}
/** /**
* @brief E1AP Bearer Context Setup Request encoding (9.2.2 of 3GPP TS 38.463) * @brief E1AP Bearer Context Setup Request encoding (9.2.2 of 3GPP TS 38.463)
...@@ -421,13 +550,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_ ...@@ -421,13 +550,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_
ieC2->id = E1AP_ProtocolIE_ID_id_SecurityInformation; ieC2->id = E1AP_ProtocolIE_ID_id_SecurityInformation;
ieC2->criticality = E1AP_Criticality_reject; ieC2->criticality = E1AP_Criticality_reject;
ieC2->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation; ieC2->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation;
E1AP_SecurityAlgorithm_t *securityAlgorithm = &ieC2->value.choice.SecurityInformation.securityAlgorithm; ieC2->value.choice.SecurityInformation = e1_encode_security_info(&msg->secInfo);
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);
/* mandatory */ /* mandatory */
/* c3. UE DL Aggregate Maximum Bit Rate */ /* c3. UE DL Aggregate Maximum Bit Rate */
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC3); asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC3);
...@@ -450,8 +573,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_ ...@@ -450,8 +573,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_
ieC5->criticality = E1AP_Criticality_reject; ieC5->criticality = E1AP_Criticality_reject;
ieC5->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel; ieC5->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel;
ieC5->value.choice.ActivityNotificationLevel = E1AP_ActivityNotificationLevel_pdu_session; // TODO: Remove hard coding ieC5->value.choice.ActivityNotificationLevel = E1AP_ActivityNotificationLevel_pdu_session; // TODO: Remove hard coding
/* mandatory */ // System (M)
/* */
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC6); asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC6);
ieC6->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest; ieC6->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest;
ieC6->criticality = E1AP_Criticality_reject; ieC6->criticality = E1AP_Criticality_reject;
...@@ -469,7 +591,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_ ...@@ -469,7 +591,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_
for (int i = 0; i < msg->numPDUSessions; i++) { for (int i = 0; i < msg->numPDUSessions; i++) {
const pdu_session_to_setup_t *pdu_session = &msg->pduSession[i]; const pdu_session_to_setup_t *pdu_session = &msg->pduSession[i];
asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Item_t, ieC6_1); asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Item_t, ieC6_1);
e1_encode_pdu_session_to_setup_item(ieC6_1, pdu_session); CHECK_E1AP_DEC(e1_encode_pdu_session_to_setup_item(ieC6_1, pdu_session));
} }
return pdu; return pdu;
} }
...@@ -479,7 +601,8 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_ ...@@ -479,7 +601,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) void free_e1ap_context_setup_request(e1ap_bearer_setup_req_t *msg)
{ {
// Do nothing free(msg->inactivityTimerUE);
free(msg->ueDlMaxIPBitRate);
} }
/** /**
...@@ -492,8 +615,7 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea ...@@ -492,8 +615,7 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
// Check message type // Check message type
_E1_EQ_CHECK_INT(pdu->present,E1AP_E1AP_PDU_PR_initiatingMessage); _E1_EQ_CHECK_INT(pdu->present,E1AP_E1AP_PDU_PR_initiatingMessage);
_E1_EQ_CHECK_INT(pdu->choice.initiatingMessage->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup); _E1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup);
_E1_EQ_CHECK_INT(pdu->choice.initiatingMessage->criticality, E1AP_Criticality_reject);
_E1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest); _E1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest);
const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest;
...@@ -519,17 +641,7 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea ...@@ -519,17 +641,7 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
case E1AP_ProtocolIE_ID_id_SecurityInformation: case E1AP_ProtocolIE_ID_id_SecurityInformation:
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation); _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation);
E1AP_SecurityInformation_t *SecurityInformation = &ie->value.choice.SecurityInformation; CHECK_E1AP_DEC(e1_decode_security_info(&out->secInfo, &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);
break; break;
case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate: case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate:
...@@ -545,12 +657,6 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea ...@@ -545,12 +657,6 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
out->servingPLMNid.mnc_digit_length); out->servingPLMNid.mnc_digit_length);
break; break;
case E1AP_ProtocolIE_ID_id_ActivityNotificationLevel:
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel);
DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel);
out->activityNotificationLevel = ie->value.choice.ActivityNotificationLevel;
break;
case E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest: case E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest:
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest); _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest);
E1AP_System_BearerContextSetupRequest_t *System_BearerContextSetupRequest = E1AP_System_BearerContextSetupRequest_t *System_BearerContextSetupRequest =
...@@ -590,10 +696,7 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea ...@@ -590,10 +696,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++) { for (int i = 0; i < pdu2SetupList->list.count; i++) {
pdu_session_to_setup_t *pdu_session = out->pduSession + i; pdu_session_to_setup_t *pdu_session = out->pduSession + i;
E1AP_PDU_Session_Resource_To_Setup_Item_t *pdu2Setup = pdu2SetupList->list.array[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)) { CHECK_E1AP_DEC(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;
}
} }
break; break;
default: default:
...@@ -604,19 +707,35 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea ...@@ -604,19 +707,35 @@ bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bea
return true; return true;
} }
/** /** @brief Deep copy PDU Session Resource To Setup List item (3GPP TS 38.463 9.3.3.2) */
* @brief Deep copy function for E1 BEARER CONTEXT SETUP REQUEST 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_bearer_context_setup_request(const e1ap_bearer_setup_req_t *msg)
{ {
e1ap_bearer_setup_req_t cp = {0}; e1ap_bearer_setup_req_t cp = {0};
// Copy basi fields // Copy basi fields
cp = *msg; cp = *msg;
strncpy(cp.encryptionKey, msg->encryptionKey, sizeof(cp.encryptionKey)); strncpy(cp.secInfo.encryptionKey, msg->secInfo.encryptionKey, sizeof(cp.secInfo.encryptionKey));
strncpy(cp.integrityProtectionKey, msg->integrityProtectionKey, sizeof(cp.integrityProtectionKey)); strncpy(cp.secInfo.integrityProtectionKey, msg->secInfo.integrityProtectionKey, sizeof(cp.secInfo.integrityProtectionKey));
// Copy PDU Sessions // Copy PDU Sessions
for (int i = 0; i < msg->numPDUSessions; i++) 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; return cp;
} }
...@@ -627,30 +746,28 @@ bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1a ...@@ -627,30 +746,28 @@ bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1a
{ {
// Primitive data types // Primitive data types
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id); _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->secInfo.cipheringAlgorithm, b->secInfo.cipheringAlgorithm);
_E1_EQ_CHECK_LONG(a->integrityProtectionAlgorithm, b->integrityProtectionAlgorithm); _E1_EQ_CHECK_LONG(a->secInfo.integrityProtectionAlgorithm, b->secInfo.integrityProtectionAlgorithm);
_E1_EQ_CHECK_LONG(a->ueDlAggMaxBitRate, b->ueDlAggMaxBitRate); _E1_EQ_CHECK_LONG(a->ueDlAggMaxBitRate, b->ueDlAggMaxBitRate);
_E1_EQ_CHECK_INT(a->activityNotificationLevel, b->activityNotificationLevel);
_E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions); _E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions);
_E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod);
// PLMN // PLMN
_E1_EQ_CHECK_INT(a->servingPLMNid.mcc, b->servingPLMNid.mcc); _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, b->servingPLMNid.mnc);
_E1_EQ_CHECK_INT(a->servingPLMNid.mnc_digit_length, b->servingPLMNid.mnc_digit_length); _E1_EQ_CHECK_INT(a->servingPLMNid.mnc_digit_length, b->servingPLMNid.mnc_digit_length);
// Security Keys // Security Keys
_E1_EQ_CHECK_STR(a->encryptionKey, b->encryptionKey); _E1_EQ_CHECK_STR(a->secInfo.encryptionKey, b->secInfo.encryptionKey);
_E1_EQ_CHECK_STR(a->integrityProtectionKey, b->integrityProtectionKey); _E1_EQ_CHECK_STR(a->secInfo.integrityProtectionKey, b->secInfo.integrityProtectionKey);
// PDU Sessions // PDU Sessions
if (a->numPDUSessions != b->numPDUSessions) if (a->numPDUSessions != b->numPDUSessions)
return false; return false;
for (int i = 0; i < a->numPDUSessions; i++) for (int i = 0; i < a->numPDUSessions; i++)
if (!eq_pdu_session_item(&a->pduSession[i], &b->pduSession[i])) if (!eq_pdu_session_item(&a->pduSession[i], &b->pduSession[i]))
return false; return false;
if (a->numPDUSessionsMod != b->numPDUSessionsMod) // Check optional IEs
return false; _E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimerUE);
for (int i = 0; i < a->numPDUSessionsMod; i++) if (a->inactivityTimerUE && b->inactivityTimerUE)
if (!eq_pdu_session_item(&a->pduSessionMod[i], &b->pduSessionMod[i])) _E1_EQ_CHECK_INT(a->inactivityTimerUE, b->inactivityTimerUE);
return false; _E1_EQ_CHECK_OPTIONAL_IE(a, b, ueDlMaxIPBitRate, _E1_EQ_CHECK_LONG);
return true; return true;
} }
...@@ -669,12 +786,7 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP ...@@ -669,12 +786,7 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP
pduSetup->id = in->pDU_Session_ID; pduSetup->id = in->pDU_Session_ID;
pduSetup->numDRBSetup = in->dRB_Setup_List_NG_RAN.list.count; pduSetup->numDRBSetup = in->dRB_Setup_List_NG_RAN.list.count;
// NG DL UP Transport Layer Information (M) // NG DL UP Transport Layer Information (M)
E1AP_UP_TNL_Information_t *DL_UP_TNL_Info = &in->nG_DL_UP_TNL_Information; CHECK_E1AP_DEC(e1_decode_up_tnl_info(&pduSetup->tl_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);
}
// DRB Setup List (1..<maxnoofDRBs>) // DRB Setup List (1..<maxnoofDRBs>)
for (int j = 0; j < in->dRB_Setup_List_NG_RAN.list.count; j++) { for (int j = 0; j < in->dRB_Setup_List_NG_RAN.list.count; j++) {
DRB_nGRAN_setup_t *drbSetup = pduSetup->DRBnGRanList + j; DRB_nGRAN_setup_t *drbSetup = pduSetup->DRBnGRanList + j;
...@@ -682,32 +794,29 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP ...@@ -682,32 +794,29 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP
// DRB ID (M) // DRB ID (M)
drbSetup->id = drb->dRB_ID; drbSetup->id = drb->dRB_ID;
// UL UP Parameters (M) // UL UP Parameters (M)
drbSetup->numUpParam = drb->uL_UP_Transport_Parameters.list.count; if ((drbSetup->numUpParam = decode_dl_up_parameters(drbSetup->UpParamList, &drb->uL_UP_Transport_Parameters)) < 0) {
for (int k = 0; k < drb->uL_UP_Transport_Parameters.list.count; k++) { PRINT_ERROR("UL UP Parameters decoding failed\n");
up_params_t *UL_UP_param = drbSetup->UpParamList + k; return false;
// UP Parameters List (1..<maxnoofUPParameters>)
E1AP_UP_Parameters_Item_t *UL_UP_item = drb->uL_UP_Transport_Parameters.list.array[k];
// UP Transport Layer Information (M)
DevAssert(UL_UP_item->uP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel);
// GTP Tunnel (M)
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);
} else {
}
// Cell Group ID (M)
UL_UP_param->cell_group_id = UL_UP_item->cell_Group_ID;
} }
// Flow Setup List (M) // Flow Setup List (M)
drbSetup->numQosFlowSetup = drb->flow_Setup_List.list.count; drbSetup->numQosFlowSetup = drb->flow_Setup_List.list.count;
for (int q = 0; q < drb->flow_Setup_List.list.count; q++) { 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]; E1AP_QoS_Flow_Item_t *in_qosflowSetup = drb->flow_Setup_List.list.array[q];
qosflowSetup->qfi = in_qosflowSetup->qoS_Flow_Identifier; qosflowSetup->qfi = in_qosflowSetup->qoS_Flow_Identifier;
} }
} }
// DRB Failed to Setup List (O)
if (in->dRB_Failed_List_NG_RAN) {
for (int j = 0; j < in->dRB_Failed_List_NG_RAN->list.count; j++) {
DRB_nGRAN_failed_t *drbFailed = pduSetup->DRBnGRanFailedList + j;
E1AP_DRB_Failed_Item_NG_RAN_t *item = in->dRB_Failed_List_NG_RAN->list.array[j];
// DRB ID (M)
drbFailed->id = item->dRB_ID;
// Cause (M)
drbFailed->cause = e1_decode_cause_ie(&item->cause);
}
}
return true; return true;
} }
...@@ -719,25 +828,16 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite ...@@ -719,25 +828,16 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite
// PDU Session ID (M) // PDU Session ID (M)
item->pDU_Session_ID = in->id; item->pDU_Session_ID = in->id;
// NG DL UP Transport Layer Information (M) // NG DL UP Transport Layer Information (M)
item->nG_DL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; item->nG_DL_UP_TNL_Information = e1_encode_up_tnl_info(&in->tl_info);
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);
// DRB Setup List (1..<maxnoofDRBs>) // DRB Setup List (1..<maxnoofDRBs>)
for (const DRB_nGRAN_setup_t *j = in->DRBnGRanList; j < in->DRBnGRanList + in->numDRBSetup; j++) { 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); asn1cSequenceAdd(item->dRB_Setup_List_NG_RAN.list, E1AP_DRB_Setup_Item_NG_RAN_t, ieC3_1_1);
// DRB ID (M) // DRB ID (M)
ieC3_1_1->dRB_ID = j->id; ieC3_1_1->dRB_ID = j->id;
// UL UP Parameters (M) // UL UP Parameters (M)
for (const up_params_t *k = j->UpParamList; k < j->UpParamList + j->numUpParam; k++) { ieC3_1_1->uL_UP_Transport_Parameters = encode_dl_up_parameters(j->numUpParam, j->UpParamList);
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);
}
// Flow Setup List(M) // 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); 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; ieC3_1_1_1->qoS_Flow_Identifier = k->qfi;
} }
...@@ -751,24 +851,7 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite ...@@ -751,24 +851,7 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite
// DRB ID (M) // DRB ID (M)
ieC3_1_1->dRB_ID = j->id; ieC3_1_1->dRB_ID = j->id;
// Cause (M) // Cause (M)
ieC3_1_1->cause.present = j->cause_type; ieC3_1_1->cause = e1_encode_cause_ie(&j->cause);
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;
}
} }
return true; return true;
} }
...@@ -816,7 +899,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_response(const e1ap_bearer_setup ...@@ -816,7 +899,7 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_response(const e1ap_bearer_setup
E1AP_PDU_Session_Resource_Setup_List_t *pduSetup = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; E1AP_PDU_Session_Resource_Setup_List_t *pduSetup = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List;
for (const pdu_session_setup_t *i = in->pduSession; i < in->pduSession + in->numPDUSessions; i++) { for (const pdu_session_setup_t *i = in->pduSession; i < in->pduSession + in->numPDUSessions; i++) {
asn1cSequenceAdd(pduSetup->list, E1AP_PDU_Session_Resource_Setup_Item_t, ieC3_1); asn1cSequenceAdd(pduSetup->list, E1AP_PDU_Session_Resource_Setup_Item_t, ieC3_1);
e1_encode_pdu_session_setup_item(ieC3_1, i); CHECK_E1AP_DEC(e1_encode_pdu_session_setup_item(ieC3_1, i));
} }
return pdu; return pdu;
} }
...@@ -828,8 +911,7 @@ bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_be ...@@ -828,8 +911,7 @@ bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_be
{ {
// Check message type // Check message type
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome); _E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
_E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup); _E1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup);
_E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->criticality, E1AP_Criticality_reject);
_E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse); _E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse);
const E1AP_BearerContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; const E1AP_BearerContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse;
...@@ -862,7 +944,7 @@ bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_be ...@@ -862,7 +944,7 @@ bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_be
ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse; ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse;
_E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1); _E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1);
E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0];
_E1_EQ_CHECK_INT(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List); _E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List);
_E1_EQ_CHECK_INT(msgNGRAN->value.present, _E1_EQ_CHECK_INT(msgNGRAN->value.present,
E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List); E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List);
E1AP_PDU_Session_Resource_Setup_List_t *pduSetupList = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; E1AP_PDU_Session_Resource_Setup_List_t *pduSetupList = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List;
...@@ -870,7 +952,7 @@ bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_be ...@@ -870,7 +952,7 @@ bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_be
for (int i = 0; i < pduSetupList->list.count; i++) { for (int i = 0; i < pduSetupList->list.count; i++) {
pdu_session_setup_t *pduSetup = out->pduSession + i; pdu_session_setup_t *pduSetup = out->pduSession + i;
E1AP_PDU_Session_Resource_Setup_Item_t *pdu_session = pduSetupList->list.array[i]; E1AP_PDU_Session_Resource_Setup_Item_t *pdu_session = pduSetupList->list.array[i];
e1_decode_pdu_session_setup_item(pduSetup, pdu_session); CHECK_E1AP_DEC(e1_decode_pdu_session_setup_item(pduSetup, pdu_session));
} }
} break; } break;
...@@ -938,8 +1020,7 @@ bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e ...@@ -938,8 +1020,7 @@ 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_a = &a->pduSession[i];
const pdu_session_setup_t *ps_b = &b->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_LONG(ps_a->id, ps_b->id);
_E1_EQ_CHECK_INT(ps_a->tlAddress, ps_b->tlAddress); eq_up_tl_info(&ps_a->tl_info, &ps_b->tl_info);
_E1_EQ_CHECK_LONG(ps_a->teId, ps_b->teId);
_E1_EQ_CHECK_INT(ps_a->numDRBSetup, ps_b->numDRBSetup); _E1_EQ_CHECK_INT(ps_a->numDRBSetup, ps_b->numDRBSetup);
_E1_EQ_CHECK_INT(ps_a->numDRBFailed, ps_b->numDRBFailed); _E1_EQ_CHECK_INT(ps_a->numDRBFailed, ps_b->numDRBFailed);
// Check DRB Setup // Check DRB Setup
...@@ -955,8 +1036,8 @@ bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e ...@@ -955,8 +1036,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_a = &ps_a->DRBnGRanFailedList[j];
const DRB_nGRAN_failed_t *drbf_b = &ps_b->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->id, drbf_b->id);
_E1_EQ_CHECK_LONG(drbf_a->cause_type, drbf_b->cause_type); _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.value, drbf_b->cause.value);
} }
} }
return true; return true;
...@@ -969,3 +1050,633 @@ void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg) ...@@ -969,3 +1050,633 @@ void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg)
{ {
// Do nothing (no dynamic allocation) // Do nothing (no dynamic allocation)
} }
/* ============================================
* E1AP Bearer Context Modification Request
* ============================================ */
/** @brief Encode PDU Session Item to modify */
static E1AP_PDU_Session_Resource_To_Modify_Item_t e1_encode_pdu_session_to_mod_item(const pdu_session_to_mod_t *in)
{
E1AP_PDU_Session_Resource_To_Modify_Item_t out = {0};
out.pDU_Session_ID = in->sessionId;
for (const DRB_nGRAN_to_mod_t *j = in->DRBnGRanModList; j < in->DRBnGRanModList + in->numDRB2Modify; j++) {
asn1cCalloc(out.dRB_To_Modify_List_NG_RAN, drb2Mod_List);
asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod);
drb2Mod->dRB_ID = j->id;
// PDCP Config (O)
if (j->pdcp_config) {
asn1cCalloc(drb2Mod->pDCP_Configuration, pDCP_Configuration);
*pDCP_Configuration = e1_encode_pdcp_config(j->pdcp_config);
}
// SDAP Config (O)
if (j->sdap_config) {
asn1cCalloc(drb2Mod->sDAP_Configuration, sDAP_Configuration);
*sDAP_Configuration = e1_encode_sdap_config(j->sdap_config);
}
// PDCP SN Status Request (O)
if (j->pdcp_sn_status_requested) {
asn1cCalloc(drb2Mod->pDCP_SN_Status_Request, pDCP_SN_Status_Request);
*pDCP_SN_Status_Request = E1AP_PDCP_SN_Status_Request_requested;
}
// DL UP TNL parameters (O)
if (j->numDlUpParam > 0) {
asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List);
for (const up_params_t *k = j->DlUpParamList; k < j->DlUpParamList + j->numDlUpParam; k++) {
asn1cSequenceAdd(DL_UP_Param_List->list, E1AP_UP_Parameters_Item_t, DL_UP_Param);
DL_UP_Param->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info);
DL_UP_Param->cell_Group_ID = k->cell_group_id;
}
}
// QoS Flows to setup (O)
for (const qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) {
asn1cCalloc(drb2Mod->flow_Mapping_Information, flow_Mapping_Information);
asn1cSequenceAdd(flow_Mapping_Information->list, E1AP_QoS_Flow_QoS_Parameter_Item_t, ie1_2);
*ie1_2 = e1_encode_qos_flow_to_setup(k);
}
}
return out;
}
/** @brief Common encoding for the NG-RAN System IE */
static E1AP_NG_RAN_BearerContextModificationRequest_t *encode_ng_ran_to_mod(E1AP_BearerContextModificationRequestIEs_t *ie)
{
ie->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest;
ie->criticality = E1AP_Criticality_reject;
ie->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest;
E1AP_System_BearerContextModificationRequest_t *reqIE = &ie->value.choice.System_BearerContextModificationRequest;
reqIE->present = E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest;
E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = calloc_or_fail(1, sizeof(*msgNGRAN_list));
reqIE->choice.nG_RAN_BearerContextModificationRequest = (struct E1AP_ProtocolIE_Container *)msgNGRAN_list;
asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextModificationRequest_t, msgNGRAN);
return msgNGRAN;
}
/** @brief Encode PDU Session Resource To Setup Modification List item */
static E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t e1_encode_pdu_session_to_setup_mod_item(const pdu_session_to_setup_t *in)
{
E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t item = {0};
// PDU Session ID (M)
item.pDU_Session_ID = in->sessionId;
// PDU Session Type (M)
item.pDU_Session_Type = in->sessionType;
// SNSSAI (M)
item.sNSSAI = e1_encode_snssai(&in->nssai);
// 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
for (const DRB_nGRAN_to_setup_t *j = in->DRBnGRanList; j < in->DRBnGRanList + in->numDRB2Setup; j++) {
asn1cSequenceAdd(item.dRB_To_Setup_Mod_List_NG_RAN.list, E1AP_DRB_To_Setup_Mod_Item_NG_RAN_t, ie1);
// DRB ID (M)
ie1->dRB_ID = j->id;
// SDAP Config (M)
ie1->sDAP_Configuration = e1_encode_sdap_config(&j->sdap_config);
// PDCP Config (M)
ie1->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(ie1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ie1_1);
ie1_1->cell_Group_ID = *k;
}
// QoS Flows Information To Be Setup (M)
for (const qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) {
asn1cSequenceAdd(ie1->flow_Mapping_Information.list, E1AP_QoS_Flow_QoS_Parameter_Item_t, ie1_2);
*ie1_2 = e1_encode_qos_flow_to_setup(k);
}
}
return item;
}
/**
* @brief Encodes the E1 Bearer Modification Request message
*/
E1AP_E1AP_PDU_t *encode_E1_bearer_context_mod_request(const e1ap_bearer_mod_req_t *in)
{
E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
// PDU Type
pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu->choice.initiatingMessage, msg);
msg->procedureCode = E1AP_ProcedureCode_id_bearerContextModification;
msg->criticality = E1AP_Criticality_reject;
msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest;
E1AP_BearerContextModificationRequest_t *out = &msg->value.choice.BearerContextModificationRequest;
// gNB-CU-CP UE E1AP ID (M)
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie1);
ie1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID;
ie1->criticality = E1AP_Criticality_reject;
ie1->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID;
ie1->value.choice.GNB_CU_CP_UE_E1AP_ID = in->gNB_cu_cp_ue_id;
// gNB-CU-UP UE E1AP ID (M)
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie2);
ie2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID;
ie2->criticality = E1AP_Criticality_reject;
ie2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID;
ie2->value.choice.GNB_CU_UP_UE_E1AP_ID = in->gNB_cu_up_ue_id;
// Security Information (O)
if (in->secInfo) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie3);
ie3->id = E1AP_ProtocolIE_ID_id_SecurityInformation;
ie3->criticality = E1AP_Criticality_reject;
ie3->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_SecurityInformation;
ie3->value.choice.SecurityInformation = e1_encode_security_info(in->secInfo);
}
// UE DL Aggregate Maximum Bit Rate (O)
if (in->ueDlAggMaxBitRate) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie4);
ie4->id = E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate;
ie4->criticality = E1AP_Criticality_reject;
ie4->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BitRate;
INT32_TO_OCTET_STRING(*in->ueDlAggMaxBitRate, &ie4->value.choice.BitRate);
}
// UE DL Maximum Integrity Protected Data Rate (O)
if (in->ueDlMaxIPBitRate) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie5);
ie5->id = E1AP_ProtocolIE_ID_id_UEDLMaximumIntegrityProtectedDataRate;
ie5->criticality = E1AP_Criticality_ignore;
ie5->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BitRate;
INT32_TO_OCTET_STRING(*in->ueDlMaxIPBitRate, &ie5->value.choice.BitRate);
}
// Bearer Context Status Change (O)
if (in->bearerContextStatus && *in->bearerContextStatus == BEARER_SUSPEND) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie6);
ie6->id = E1AP_ProtocolIE_ID_id_BearerContextStatusChange;
ie6->criticality = E1AP_Criticality_reject;
ie6->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange;
ie6->value.choice.BearerContextStatusChange = E1AP_BearerContextStatusChange_suspend;
}
// UE Inactivity Timer (O)
if (in->inactivityTimer) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie7);
ie7->id = E1AP_ProtocolIE_ID_id_UE_Inactivity_Timer;
ie7->criticality = E1AP_Criticality_ignore;
ie7->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_Inactivity_Timer;
ie7->value.choice.Inactivity_Timer = *in->inactivityTimer;
}
// Data Discard Required (O)
if (in->dataDiscardRequired) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie9);
ie9->id = E1AP_ProtocolIE_ID_id_DataDiscardRequired;
ie9->criticality = E1AP_Criticality_ignore;
ie9->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_DataDiscardRequired;
ie9->value.choice.DataDiscardRequired = in->dataDiscardRequired;
}
// NG-RAN PDU Session Resource To Setup List (O)
if (in->numPDUSessions) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, setupList);
E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = encode_ng_ran_to_mod(setupList);
msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List;
msgNGRAN->criticality = E1AP_Criticality_reject;
msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Setup_Mod_List;
E1AP_PDU_Session_Resource_To_Setup_Mod_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_Mod_List;
for (int i = 0; i < in->numPDUSessions; i++) {
const pdu_session_to_setup_t *pdu_session = &in->pduSession[i];
asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t, item);
*item = e1_encode_pdu_session_to_setup_mod_item(pdu_session);
}
}
// NG-RAN PDU Session Resource To Modify List (O)
if (in->numPDUSessionsMod) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, modList);
E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = encode_ng_ran_to_mod(modList);
msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List;
msgNGRAN->criticality = E1AP_Criticality_reject;
msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List;
E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List;
for (const pdu_session_to_mod_t *i = in->pduSessionMod; i < in->pduSessionMod + in->numPDUSessionsMod; i++) {
asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Modify_Item_t, ieC3_1);
*ieC3_1 = e1_encode_pdu_session_to_mod_item(i);
}
}
return pdu;
}
/** @brief Decode PDU Session Item to Setup (Bearer Context Modification Request) */
static bool e1_decode_pdu_session_to_setup_mod_item(pdu_session_to_setup_t *out,
const E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t *item)
{
// PDU Session ID (M)
out->sessionId = item->pDU_Session_ID;
// PDU Session Type (M)
out->sessionType = item->pDU_Session_Type;
// S-NSSAI (M)
CHECK_E1AP_DEC(e1_decode_snssai(&out->nssai, &item->sNSSAI));
// Security Indication (M)
CHECK_E1AP_DEC(e1_decode_security_indication(&out->securityIndication, &item->securityIndication));
/* NG UL UP Transport Layer Information (M) */
_E1_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel);
CHECK_E1AP_DEC(e1_decode_up_tnl_info(&out->UP_TL_information, &item->nG_UL_UP_TNL_Information));
/* DRB To Setup List ( > 1 item ) */
const E1AP_DRB_To_Setup_Mod_List_NG_RAN_t *drb2SetupList = &item->dRB_To_Setup_Mod_List_NG_RAN;
_E1_EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0);
out->numDRB2Setup = drb2SetupList->list.count;
_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;
const E1AP_DRB_To_Setup_Mod_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j];
// DRB ID (M)
drb->id = drb2Setup->dRB_ID;
// SDAP Configuration (M)
CHECK_E1AP_DEC(e1_decode_sdap_config(&drb->sdap_config, &drb2Setup->sDAP_Configuration));
// PDCP Configuration (M)
CHECK_E1AP_DEC(e1_decode_pdcp_config(&drb->pdcp_config, &drb2Setup->pDCP_Configuration));
// Cell Group Information (M)
const E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information;
_E1_EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0);
drb->numCellGroups = cellGroupList->list.count;
for (int k = 0; k < cellGroupList->list.count; k++) {
const E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k];
// Cell Group ID
drb->cellGroupList[k] = cg2Setup->cell_Group_ID;
}
// QoS Flows Information To Be Setup (M)
const E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->flow_Mapping_Information;
drb->numQosFlow2Setup = qos2SetupList->list.count;
for (int k = 0; k < qos2SetupList->list.count; k++) {
CHECK_E1AP_DEC(e1_decode_qos_flow_to_setup(drb->qosFlows + k, qos2SetupList->list.array[k]));
}
}
return true;
}
/** @brief Decode PDU Session Item to modify (Bearer Context Modification Request) */
static bool e1_decode_pdu_session_to_mod_item(pdu_session_to_mod_t *out, const E1AP_PDU_Session_Resource_To_Modify_Item_t *in)
{
// PDU Session ID
out->sessionId = in->pDU_Session_ID;
// DRB to modify list
E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = in->dRB_To_Modify_List_NG_RAN;
out->numDRB2Modify = drb2ModList->list.count;
for (int j = 0; j < drb2ModList->list.count; j++) {
DRB_nGRAN_to_mod_t *drb = out->DRBnGRanModList + j;
// DRB to modify item
E1AP_DRB_To_Modify_Item_NG_RAN_t *drb2Mod = drb2ModList->list.array[j];
drb->id = drb2Mod->dRB_ID;
// PDCP Config (O)
if (drb2Mod->pDCP_Configuration) {
drb->pdcp_config = malloc_or_fail(sizeof(*drb->pdcp_config));
CHECK_E1AP_DEC(e1_decode_pdcp_config(drb->pdcp_config, drb2Mod->pDCP_Configuration));
}
// SDAP Config (O)
if (drb2Mod->sDAP_Configuration) {
drb->sdap_config = malloc_or_fail(sizeof(*drb->sdap_config));
CHECK_E1AP_DEC(e1_decode_sdap_config(drb->sdap_config, drb2Mod->sDAP_Configuration));
}
// PDCP SN Status Request (O)
if (drb2Mod->pDCP_SN_Status_Request) {
drb->pdcp_sn_status_requested = true;
}
// DL UP TNL parameters (O)
if (drb2Mod->dL_UP_Parameters) {
E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters;
if((drb->numDlUpParam = decode_dl_up_parameters(drb->DlUpParamList, dl_up_paramList)) < 0) {
PRINT_ERROR("Failed to decode DL UP TNL parameters\n");
return false;
}
}
// QoS Flows Information To Be Setup (O)
E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = drb2Mod->flow_Mapping_Information;
drb->numQosFlow2Setup = qos2SetupList->list.count;
for (int k = 0; k < qos2SetupList->list.count; k++) {
CHECK_E1AP_DEC(e1_decode_qos_flow_to_setup(drb->qosFlows + k, qos2SetupList->list.array[k]));
}
}
return true;
}
/**
* @brief E1 Bearer Modification Request message decoding
*/
bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_mod_req_t *out)
{
DevAssert(pdu != NULL);
// Validate message type
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_initiatingMessage);
const E1AP_InitiatingMessage_t *im = pdu->choice.initiatingMessage;
_E1_EQ_CHECK_LONG(im->procedureCode, E1AP_ProcedureCode_id_bearerContextModification);
_E1_EQ_CHECK_INT(im->value.present, E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest);
const E1AP_BearerContextModificationRequest_t *in = &im->value.choice.BearerContextModificationRequest;
E1AP_BearerContextModificationRequestIEs_t *ie = NULL;
// Mandatory IEs
// gNB-CU-CP UE E1AP ID (M)
E1AP_LIB_FIND_IE(E1AP_BearerContextModificationRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID, true);
// gNB-CU-UP UE E1AP ID (M)
E1AP_LIB_FIND_IE(E1AP_BearerContextModificationRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID, true);
// Loop through all IEs and extract
for (int i = 0; i < in->protocolIEs.list.count; i++) {
ie = in->protocolIEs.list.array[i];
switch (ie->id) {
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID:
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID;
break;
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID:
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
out->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
break;
case E1AP_ProtocolIE_ID_id_SecurityInformation:
out->secInfo = malloc_or_fail(sizeof(*out->secInfo));
CHECK_E1AP_DEC(e1_decode_security_info(out->secInfo, &ie->value.choice.SecurityInformation));
break;
case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate:
out->ueDlAggMaxBitRate = malloc_or_fail(sizeof(*out->ueDlAggMaxBitRate));
OCTET_STRING_TO_UINT32(&ie->value.choice.BitRate, *out->ueDlAggMaxBitRate);
break;
case E1AP_ProtocolIE_ID_id_UEDLMaximumIntegrityProtectedDataRate:
out->ueDlMaxIPBitRate = malloc_or_fail(sizeof(*out->ueDlMaxIPBitRate));
OCTET_STRING_TO_UINT32(&ie->value.choice.BitRate, *out->ueDlMaxIPBitRate);
break;
case E1AP_ProtocolIE_ID_id_BearerContextStatusChange:
_E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange);
if (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) {
out->bearerContextStatus = malloc_or_fail(sizeof(*out->bearerContextStatus));
*out->bearerContextStatus = BEARER_SUSPEND;
}
break;
case E1AP_ProtocolIE_ID_id_UE_Inactivity_Timer:
out->inactivityTimer = malloc_or_fail(sizeof(*out->inactivityTimer));
*out->inactivityTimer = ie->value.choice.Inactivity_Timer;
break;
case E1AP_ProtocolIE_ID_id_DataDiscardRequired:
out->dataDiscardRequired = ie->value.choice.DataDiscardRequired;
break;
case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest: {
_E1_EQ_CHECK_INT(ie->value.present,
E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest);
E1AP_System_BearerContextModificationRequest_t *modReq = &ie->value.choice.System_BearerContextModificationRequest;
DevAssert(ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest != NULL);
// System IE can contain either UTRAN or NG-RAN
switch (modReq->present) {
case E1AP_System_BearerContextModificationRequest_PR_NOTHING:
PRINT_ERROR("System Bearer Context Setup Request: no choice present\n");
break;
case E1AP_System_BearerContextModificationRequest_PR_e_UTRAN_BearerContextModificationRequest:
PRINT_ERROR("UTRAN in E1 Setup Modification Request not supported\n");
return false;
break;
case E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest:
// NG-RAN
AssertFatal(modReq->choice.nG_RAN_BearerContextModificationRequest != NULL,
"System_BearerContextSetupRequest->choice.nG_RAN_BearerContextSetupRequest shall not be null");
E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list =
(E1AP_ProtocolIE_Container_4932P26_t *)modReq->choice.nG_RAN_BearerContextModificationRequest;
// loop through all items in the NG-RAN list (to setup, to modify, etc)
for (int i = 0; i < msgNGRAN_list->list.count; i++) {
E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = msgNGRAN_list->list.array[i];
switch (msgNGRAN->id) {
case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List:
_E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_Mod_List);
_E1_EQ_CHECK_INT(msgNGRAN->value.present,
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Setup_Mod_List);
E1AP_PDU_Session_Resource_To_Setup_Mod_List_t *setupList =
&msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_Mod_List;
// PDU Session Resource To Modify List
out->numPDUSessions = setupList->list.count;
// Loop through all PDU sessions
for (int i = 0; i < setupList->list.count; i++) {
pdu_session_to_setup_t *pdu_session = out->pduSession + i;
E1AP_PDU_Session_Resource_To_Setup_Mod_Item_t *pdu2Setup = setupList->list.array[i];
CHECK_E1AP_DEC(e1_decode_pdu_session_to_setup_mod_item(pdu_session, pdu2Setup));
}
break;
case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List:
/* PDU Session Resource To Modify List (see 9.3.3.11 of TS 38.463) */
_E1_EQ_CHECK_INT(msgNGRAN->value.present,
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List);
E1AP_PDU_Session_Resource_To_Modify_List_t *modList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List;
out->numPDUSessionsMod = modList->list.count;
// Loop through all PDU sessions
for (int i = 0; i < modList->list.count; i++) {
CHECK_E1AP_DEC(e1_decode_pdu_session_to_mod_item(out->pduSessionMod + i, modList->list.array[i]));
}
break;
default:
PRINT_ERROR("Unknown msgNGRAN->id in E1 Setup Modification Request\n");
return false;
break;
}
}
break;
default:
PRINT_ERROR("System Bearer Context Modification Request: No valid choice present.\n");
break;
}
break;
}
default:
PRINT_ERROR("System Bearer Context Modification Request: this IE is not implemented (or) invalid IE detected\n");
return false;
break;
}
}
return true;
}
/** @brief Deep copy for DRB Item to modify */
static DRB_nGRAN_to_mod_t cp_drb_to_mod_item(const DRB_nGRAN_to_mod_t *msg)
{
DRB_nGRAN_to_mod_t cp = {0};
// shallow copy
cp = *msg;
_E1_CP_OPTIONAL_IE(&cp, msg, sdap_config);
_E1_CP_OPTIONAL_IE(&cp, msg, pdcp_config);
return cp;
}
/** @brief Deep copy for PDU Session Item to modify */
static pdu_session_to_mod_t cp_pdu_session_to_mod_item(const pdu_session_to_mod_t *msg)
{
pdu_session_to_mod_t cp = {0};
// shallow copy
cp = *msg;
// DRB to setup list
for (int j = 0; j < msg->numDRB2Setup; j++)
cp.DRBnGRanList[j] = cp_drb_to_setup_item(&msg->DRBnGRanList[j]);
// DRB to modify list
for (int j = 0; j < msg->numDRB2Modify; j++)
cp.DRBnGRanModList[j] = cp_drb_to_mod_item(&msg->DRBnGRanModList[j]);
_E1_CP_OPTIONAL_IE(&cp, msg, securityIndication);
_E1_CP_OPTIONAL_IE(&cp, msg, UP_TL_information);
return cp;
}
/** @brief Deep copy for Bearer Context Modification Request */
e1ap_bearer_mod_req_t cp_bearer_context_mod_request(const e1ap_bearer_mod_req_t *msg)
{
e1ap_bearer_mod_req_t cp = {0};
// Shallow copy
cp = *msg;
// Deep copy for optional fields
_E1_CP_OPTIONAL_IE(&cp, msg, secInfo);
_E1_CP_OPTIONAL_IE(&cp, msg, bearerContextStatus);
_E1_CP_OPTIONAL_IE(&cp, msg, inactivityTimer);
// Deep copy PDU sessions
for (int i = 0; i < msg->numPDUSessions; i++)
cp.pduSession[i] = cp_pdu_session_item(&msg->pduSession[i]);
for (int i = 0; i < msg->numPDUSessionsMod; i++)
cp.pduSessionMod[i] = cp_pdu_session_to_mod_item(&msg->pduSessionMod[i]);
return cp;
}
/** @brief Equality check for Security Indication IE (3GPP TS 38.463 9.3.1.23) */
static bool eq_security_ind(security_indication_t *a, security_indication_t *b)
{
_E1_EQ_CHECK_INT(a->confidentialityProtectionIndication, b->confidentialityProtectionIndication);
_E1_EQ_CHECK_INT(a->integrityProtectionIndication, b->integrityProtectionIndication);
_E1_EQ_CHECK_LONG(a->maxIPrate, b->maxIPrate);
return true;
}
/**
* @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)
{
bool result = true;
_E1_EQ_CHECK_LONG(a->id, b->id);
_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->numDlUpParam, b->numDlUpParam);
for (int i = 0; i < a->numDlUpParam; i++) {
_E1_EQ_CHECK_INT(a->DlUpParamList[i].cell_group_id, b->DlUpParamList[i].cell_group_id);
eq_up_tl_info(&a->DlUpParamList[i].tl_info, &b->DlUpParamList[i].tl_info);
}
if (a->pdcp_config && b->pdcp_config)
result &= eq_pdcp_config(a->pdcp_config, b->pdcp_config);
if (a->sdap_config && b->sdap_config)
result &= eq_sdap_config(a->sdap_config, b->sdap_config);
return result;
}
/** @brief Equality check for PDU session item to modify */
static bool eq_pdu_session_to_mod_item(const pdu_session_to_mod_t *a, const pdu_session_to_mod_t *b)
{
_E1_EQ_CHECK_LONG(a->sessionId, b->sessionId);
if (a->UP_TL_information && a->UP_TL_information) {
if (!eq_up_tl_info(a->UP_TL_information, b->UP_TL_information))
return false;
}
_E1_EQ_CHECK_INT(a->numDRB2Setup, b->numDRB2Setup);
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);
for (int i = 0; i < a->numDRB2Modify; i++) {
if (!eq_drb_to_mod(&a->DRBnGRanModList[i], &b->DRBnGRanModList[i]))
return false;
}
if (a->securityIndication && b->securityIndication) {
eq_security_ind(a->securityIndication, b->securityIndication);
}
return true;
}
/**
* @brief E1AP Bearer Modification Request equality check
*/
bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_bearer_mod_req_t *b)
{
// basic members
_E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id);
_E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id);
_E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions);
_E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod);
// Security Info
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, secInfo);
if (a->secInfo && b->secInfo) {
_E1_EQ_CHECK_LONG(a->secInfo->cipheringAlgorithm, b->secInfo->cipheringAlgorithm);
_E1_EQ_CHECK_LONG(a->secInfo->integrityProtectionAlgorithm, b->secInfo->integrityProtectionAlgorithm);
_E1_EQ_CHECK_STR(a->secInfo->encryptionKey, b->secInfo->encryptionKey);
_E1_EQ_CHECK_STR(a->secInfo->integrityProtectionKey, b->secInfo->integrityProtectionKey);
}
// Bearer Context Status (O)
_E1_EQ_CHECK_OPTIONAL_IE(a, b, bearerContextStatus, _E1_EQ_CHECK_INT);
// Inactivity Timer (O)
_E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer);
if (a->inactivityTimer && b->inactivityTimer)
_E1_EQ_CHECK_INT(*a->inactivityTimer, *b->inactivityTimer);
// Activity Notification Level (O)
// 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;
}
// Modified PDU Sessions
if (a->numPDUSessionsMod != b->numPDUSessionsMod)
return false;
for (int i = 0; i < a->numPDUSessionsMod; i++) {
if (!eq_pdu_session_to_mod_item(&a->pduSessionMod[i], &b->pduSessionMod[i]))
return false;
}
return true;
}
/* Free DRB to modify item */
static void free_drb_to_mod_item(const DRB_nGRAN_to_mod_t *msg)
{
free(msg->pdcp_config);
free(msg->sdap_config);
}
/* Free PDU Session to modify item */
void free_pdu_session_to_mod_item(const pdu_session_to_mod_t *msg)
{
free(msg->securityIndication);
free(msg->UP_TL_information);
for (int i = 0; i < msg->numDRB2Modify; i++)
free_drb_to_mod_item(&msg->DRBnGRanModList[i]);
for (int i = 0; i < msg->numDRB2Setup; i++)
free_drb_to_setup_item(&msg->DRBnGRanList[i]);
}
/**
* @brief E1AP Bearer Context Modification Request memory management
*/
void free_e1ap_context_mod_request(const e1ap_bearer_mod_req_t *msg)
{
free(msg->secInfo);
free(msg->ueDlAggMaxBitRate);
free(msg->ueDlMaxIPBitRate);
free(msg->bearerContextStatus);
free(msg->inactivityTimer);
for (int i = 0; i < msg->numPDUSessions; i++)
free_pdu_session_to_setup_item(&msg->pduSession[i]);
for (int i = 0; i < msg->numPDUSessionsMod; i++)
free_pdu_session_to_mod_item(&msg->pduSessionMod[i]);
}
...@@ -40,4 +40,10 @@ void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg); ...@@ -40,4 +40,10 @@ void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg);
e1ap_bearer_setup_resp_t cp_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *msg); e1ap_bearer_setup_resp_t cp_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *msg);
bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e1ap_bearer_setup_resp_t *b); bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e1ap_bearer_setup_resp_t *b);
struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_request(const e1ap_bearer_mod_req_t *msg);
bool decode_E1_bearer_context_mod_request(const struct E1AP_E1AP_PDU *pdu, e1ap_bearer_mod_req_t *out);
void free_e1ap_context_mod_request(const e1ap_bearer_mod_req_t *msg);
e1ap_bearer_mod_req_t cp_bearer_context_mod_request(const e1ap_bearer_mod_req_t *msg);
bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_bearer_mod_req_t *b);
#endif /* E1AP_BEARER_CONTEXT_MANAGEMENT_H_ */ #endif /* E1AP_BEARER_CONTEXT_MANAGEMENT_H_ */
...@@ -508,61 +508,6 @@ bool eq_e1ap_cuup_setup_response(const e1ap_setup_resp_t *a, const e1ap_setup_re ...@@ -508,61 +508,6 @@ bool eq_e1ap_cuup_setup_response(const e1ap_setup_resp_t *a, const e1ap_setup_re
* GNB-CU-UP E1 SETUP FAILURE * GNB-CU-UP E1 SETUP FAILURE
* ==================================== */ * ==================================== */
static E1AP_Cause_t encode_e1ap_cause_ie(const e1ap_cause_t *cause)
{
E1AP_Cause_t ie;
switch (cause->type) {
case E1AP_CAUSE_RADIO_NETWORK:
ie.present = E1AP_Cause_PR_radioNetwork;
ie.choice.radioNetwork = cause->value;
break;
case E1AP_CAUSE_TRANSPORT:
ie.present = E1AP_Cause_PR_transport;
ie.choice.transport = cause->value;
break;
case E1AP_CAUSE_PROTOCOL:
ie.present = E1AP_Cause_PR_protocol;
ie.choice.protocol = cause->value;
break;
case E1AP_CAUSE_MISC:
ie.present = E1AP_Cause_PR_misc;
ie.choice.misc = cause->value;
break;
default:
ie.present = E1AP_Cause_PR_NOTHING;
break;
}
return ie;
}
static e1ap_cause_t decode_e1ap_cause_ie(const E1AP_Cause_t *ie)
{
e1ap_cause_t cause;
// Decode the 'choice' field based on the 'present' value
switch (ie->present) {
case E1AP_Cause_PR_radioNetwork:
cause.value = ie->choice.radioNetwork;
cause.type = E1AP_CAUSE_RADIO_NETWORK;
break;
case E1AP_Cause_PR_transport:
cause.value = ie->choice.transport;
cause.type = E1AP_CAUSE_TRANSPORT;
break;
case E1AP_Cause_PR_protocol:
cause.value = ie->choice.protocol;
cause.type = E1AP_CAUSE_PROTOCOL;
break;
case E1AP_Cause_PR_misc:
cause.value = ie->choice.misc;
cause.type = E1AP_CAUSE_MISC;
break;
default:
cause.type = E1AP_CAUSE_NOTHING;
break;
}
return cause;
}
/** /**
* @brief Encoder for GNB-CU-UP E1 Setup Failure * @brief Encoder for GNB-CU-UP E1 Setup Failure
* @ref 9.2.1.6 GNB-CU-UP E1 SETUP FAILURE of 3GPP TS 38.463 * @ref 9.2.1.6 GNB-CU-UP E1 SETUP FAILURE of 3GPP TS 38.463
...@@ -588,7 +533,7 @@ E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *msg) ...@@ -588,7 +533,7 @@ E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *msg)
ie2->id = E1AP_ProtocolIE_ID_id_Cause; ie2->id = E1AP_ProtocolIE_ID_id_Cause;
ie2->criticality = E1AP_Criticality_ignore; ie2->criticality = E1AP_Criticality_ignore;
ie2->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_Cause; ie2->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_Cause;
ie2->value.choice.Cause = encode_e1ap_cause_ie(&msg->cause); ie2->value.choice.Cause = e1_encode_cause_ie(&msg->cause);
// Time To Wait (O) // Time To Wait (O)
if (msg->time_to_wait) { if (msg->time_to_wait) {
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie3); asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie3);
...@@ -630,7 +575,7 @@ bool decode_e1ap_cuup_setup_failure(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_fail_ ...@@ -630,7 +575,7 @@ bool decode_e1ap_cuup_setup_failure(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_fail_
case E1AP_ProtocolIE_ID_id_Cause: case E1AP_ProtocolIE_ID_id_Cause:
// Cause // Cause
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_Cause, true); E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_Cause, true);
out->cause = decode_e1ap_cause_ie(&ie->value.choice.Cause); out->cause = e1_decode_cause_ie(&ie->value.choice.Cause);
break; break;
case E1AP_ProtocolIE_ID_id_Transport_Layer_Address_Info: case E1AP_ProtocolIE_ID_id_Transport_Layer_Address_Info:
// Time To Wait (O) // Time To Wait (O)
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "e1ap_lib_common.h"
#include "e1ap_lib_includes.h"
#include "e1ap_messages_types.h"
E1AP_Cause_t e1_encode_cause_ie(const e1ap_cause_t *cause)
{
E1AP_Cause_t ie;
switch (cause->type) {
case E1AP_CAUSE_RADIO_NETWORK:
ie.present = E1AP_Cause_PR_radioNetwork;
ie.choice.radioNetwork = cause->value;
break;
case E1AP_CAUSE_TRANSPORT:
ie.present = E1AP_Cause_PR_transport;
ie.choice.transport = cause->value;
break;
case E1AP_CAUSE_PROTOCOL:
ie.present = E1AP_Cause_PR_protocol;
ie.choice.protocol = cause->value;
break;
case E1AP_CAUSE_MISC:
ie.present = E1AP_Cause_PR_misc;
ie.choice.misc = cause->value;
break;
default:
ie.present = E1AP_Cause_PR_NOTHING;
PRINT_ERROR("encode_e1ap_cause_ie: no cause value provided\n");
break;
}
return ie;
}
e1ap_cause_t e1_decode_cause_ie(const E1AP_Cause_t *ie)
{
e1ap_cause_t cause;
// Decode the 'choice' field based on the 'present' value
switch (ie->present) {
case E1AP_Cause_PR_radioNetwork:
cause.value = ie->choice.radioNetwork;
cause.type = E1AP_CAUSE_RADIO_NETWORK;
break;
case E1AP_Cause_PR_transport:
cause.value = ie->choice.transport;
cause.type = E1AP_CAUSE_TRANSPORT;
break;
case E1AP_Cause_PR_protocol:
cause.value = ie->choice.protocol;
cause.type = E1AP_CAUSE_PROTOCOL;
break;
case E1AP_Cause_PR_misc:
cause.value = ie->choice.misc;
cause.type = E1AP_CAUSE_MISC;
break;
default:
cause.type = E1AP_CAUSE_NOTHING;
PRINT_ERROR("decode_e1ap_cause_ie: no cause value provided\n");
break;
}
return cause;
}
...@@ -26,13 +26,22 @@ ...@@ -26,13 +26,22 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include "openair3/UTILS/conversions.h" #include "openair3/UTILS/conversions.h"
#include "e1ap_messages_types.h"
#ifdef ENABLE_TESTS #ifdef E1AP_LOG_ERRORS
#define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__); #define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__);
#else #else
#define PRINT_ERROR(...) // Do nothing #define PRINT_ERROR(...) // Do nothing
#endif #endif
#define CHECK_E1AP_DEC(exp) \
do { \
if (!(exp)) { \
PRINT_ERROR("Failed executing " #exp " in %s() line %d\n", __func__, __LINE__); \
return false; \
} \
} while (0)
#define _E1_EQ_CHECK_GENERIC(condition, fmt, ...) \ #define _E1_EQ_CHECK_GENERIC(condition, fmt, ...) \
do { \ do { \
if (!(condition)) { \ if (!(condition)) { \
...@@ -66,4 +75,40 @@ ...@@ -66,4 +75,40 @@
} \ } \
} while (0) } while (0)
/* deep copy of optional E1AP IE */
#define _E1_CP_OPTIONAL_IE(dest, src, field) \
do { \
if ((src)->field) { \
(dest)->field = malloc_or_fail(sizeof(*(dest)->field)); \
*(dest)->field = *(src)->field; \
} \
} while (0)
#define _E1_EQ_CHECK_OPTIONAL_IE(a, b, field, EQ_MACRO) \
do { \
if (((a)->field && !(b)->field) || (!(a)->field && (b)->field)) { \
return false; /* One of the two is not allocated */ \
} \
if ((a)->field && (b)->field) { \
EQ_MACRO(*(a)->field, *(b)->field) \
} \
} while (0)
#define _E1_EQ_CHECK_OPTIONAL_PTR(a, b, field) \
do { \
if (((a)->field && !(b)->field) || (!(a)->field && (b)->field)) { \
PRINT_ERROR("%s:%d: optional IE '%s' not allocated: %p, %p\n", \
__FILE__, \
__LINE__, \
#field, \
(void *)(a)->field, \
(void *)(b)->field); \
return false; /* One of the two is not allocated */ \
} \
} while (0)
struct E1AP_Cause;
struct E1AP_Cause e1_encode_cause_ie(const e1ap_cause_t *cause);
e1ap_cause_t e1_decode_cause_ie(const struct E1AP_Cause *ie);
#endif /* E1AP_LIB_COMMON_H_ */ #endif /* E1AP_LIB_COMMON_H_ */
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "E1AP_System-BearerContextSetupRequest.h" #include "E1AP_System-BearerContextSetupRequest.h"
#include "E1AP_MaximumIPdatarate.h" #include "E1AP_MaximumIPdatarate.h"
#include "E1AP_PDU-Session-Type.h" #include "E1AP_PDU-Session-Type.h"
#include "E1AP_Data-Forwarding-Information.h"
// E1 Bearer Context Setup Response // E1 Bearer Context Setup Response
#include "E1AP_PDU-Session-Resource-Setup-Item.h" #include "E1AP_PDU-Session-Resource-Setup-Item.h"
#include "E1AP_DRB-Setup-Item-NG-RAN.h" #include "E1AP_DRB-Setup-Item-NG-RAN.h"
...@@ -66,5 +67,11 @@ ...@@ -66,5 +67,11 @@
#include "E1AP_Transport-UP-Layer-Addresses-Info-To-Remove-Item.h" #include "E1AP_Transport-UP-Layer-Addresses-Info-To-Remove-Item.h"
#include "E1AP_GTPTLAs.h" #include "E1AP_GTPTLAs.h"
#include "E1AP_GTPTLA-Item.h" #include "E1AP_GTPTLA-Item.h"
// E1 Bearer Context Modification Request
#include "E1AP_PDU-Session-Resource-To-Modify-Item.h"
#include "E1AP_DRB-To-Modify-List-NG-RAN.h"
#include "E1AP_DRB-To-Modify-Item-NG-RAN.h"
#include "E1AP_PDU-Session-Resource-To-Setup-Mod-Item.h"
#include "E1AP_DRB-To-Setup-Mod-Item-NG-RAN.h"
#endif /* E1AP_LIB_INCLUDES_H_ */ #endif /* E1AP_LIB_INCLUDES_H_ */
...@@ -70,6 +70,14 @@ static void e1ap_msg_free(E1AP_E1AP_PDU_t *pdu) ...@@ -70,6 +70,14 @@ static void e1ap_msg_free(E1AP_E1AP_PDU_t *pdu)
ASN_STRUCT_FREE(asn_DEF_E1AP_E1AP_PDU, 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 * @brief Test E1AP Bearer Context Setup Request encoding/decoding
*/ */
...@@ -77,7 +85,7 @@ static void test_bearer_context_setup_request(void) ...@@ -77,7 +85,7 @@ static void test_bearer_context_setup_request(void)
{ {
bearer_context_pdcp_config_t pdcp = { bearer_context_pdcp_config_t pdcp = {
.discardTimer = E1AP_DiscardTimer_ms10, .discardTimer = E1AP_DiscardTimer_ms10,
.pDCP_Reestablishment = E1AP_PDCP_Reestablishment_true, .pDCP_Reestablishment = true,
.pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_12, .pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_12,
.pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_12, .pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_12,
.reorderingTimer = 10, .reorderingTimer = 10,
...@@ -107,14 +115,13 @@ static void test_bearer_context_setup_request(void) ...@@ -107,14 +115,13 @@ static void test_bearer_context_setup_request(void)
// Step 1: Initialize the E1AP Bearer Context Setup Request // Step 1: Initialize the E1AP Bearer Context Setup Request
e1ap_bearer_setup_req_t orig = { e1ap_bearer_setup_req_t orig = {
.gNB_cu_cp_ue_id = 1234, .gNB_cu_cp_ue_id = 1234,
.cipheringAlgorithm = 0x01, .secInfo.cipheringAlgorithm = 0x01,
.integrityProtectionAlgorithm = 0x01, .secInfo.integrityProtectionAlgorithm = 0x01,
.ueDlAggMaxBitRate = 1000000000, .ueDlAggMaxBitRate = 1000000000,
.bearerContextStatus = 0, .bearerContextStatus = 0,
.servingPLMNid.mcc = 001, .servingPLMNid.mcc = 001,
.servingPLMNid.mnc = 01, .servingPLMNid.mnc = 01,
.servingPLMNid.mnc_digit_length = 0x02, .servingPLMNid.mnc_digit_length = 0x02,
.activityNotificationLevel = ANL_PDU_SESSION,
.numPDUSessions = 1, .numPDUSessions = 1,
.pduSession[0].sessionId = 1, .pduSession[0].sessionId = 1,
.pduSession[0].sessionType = E1AP_PDU_Session_Type_ipv4, .pduSession[0].sessionType = E1AP_PDU_Session_Type_ipv4,
...@@ -122,8 +129,7 @@ static void test_bearer_context_setup_request(void) ...@@ -122,8 +129,7 @@ static void test_bearer_context_setup_request(void)
.pduSession[0].nssai.sst = 0x01, .pduSession[0].nssai.sst = 0x01,
.pduSession[0].securityIndication = security, .pduSession[0].securityIndication = security,
.pduSession[0].numDRB2Setup = 1, .pduSession[0].numDRB2Setup = 1,
.pduSession[0].UP_TL_information.tlAddress = 167772161, .pduSession[0].UP_TL_information = create_up_tl_info(),
.pduSession[0].UP_TL_information.teId = 0x12345,
.pduSession[0].DRBnGRanList[0].id = 1, .pduSession[0].DRBnGRanList[0].id = 1,
.pduSession[0].DRBnGRanList[0].sdap_config = sdap, .pduSession[0].DRBnGRanList[0].sdap_config = sdap,
.pduSession[0].DRBnGRanList[0].pdcp_config = pdcp, .pduSession[0].DRBnGRanList[0].pdcp_config = pdcp,
...@@ -133,8 +139,8 @@ static void test_bearer_context_setup_request(void) ...@@ -133,8 +139,8 @@ static void test_bearer_context_setup_request(void)
.pduSession[0].DRBnGRanList[0].numQosFlow2Setup = 1, .pduSession[0].DRBnGRanList[0].numQosFlow2Setup = 1,
.pduSession[0].DRBnGRanList[0].qosFlows[0] = qos, .pduSession[0].DRBnGRanList[0].qosFlows[0] = qos,
}; };
memset(orig.encryptionKey, 0xAB, sizeof(orig.encryptionKey)); memset(orig.secInfo.encryptionKey, 0xAB, sizeof(orig.secInfo.encryptionKey));
memset(orig.integrityProtectionKey, 0xCD, sizeof(orig.integrityProtectionKey)); memset(orig.secInfo.integrityProtectionKey, 0xCD, sizeof(orig.secInfo.integrityProtectionKey));
// E1AP encode the original message // E1AP encode the original message
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_request(&orig); E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_request(&orig);
// E1AP decode the encoded message // E1AP decode the encoded message
...@@ -172,8 +178,7 @@ static void test_bearer_context_setup_response(void) ...@@ -172,8 +178,7 @@ static void test_bearer_context_setup_response(void)
.gNB_cu_up_ue_id = 5678, .gNB_cu_up_ue_id = 5678,
.numPDUSessions = 1, .numPDUSessions = 1,
.pduSession[0].id = 1, .pduSession[0].id = 1,
.pduSession[0].tlAddress = 167772161, .pduSession[0].tl_info = create_up_tl_info(),
.pduSession[0].teId = 0x12345,
.pduSession[0].numDRBSetup = 1, .pduSession[0].numDRBSetup = 1,
.pduSession[0].numDRBFailed = 0, .pduSession[0].numDRBFailed = 0,
.pduSession[0].DRBnGRanList[0].id = 1, .pduSession[0].DRBnGRanList[0].id = 1,
...@@ -181,8 +186,7 @@ static void test_bearer_context_setup_response(void) ...@@ -181,8 +186,7 @@ static void test_bearer_context_setup_response(void)
.pduSession[0].DRBnGRanList[0].numQosFlowSetup = 1, .pduSession[0].DRBnGRanList[0].numQosFlowSetup = 1,
.pduSession[0].DRBnGRanList[0].qosFlows[0].qfi = 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].cell_group_id = MCG,
.pduSession[0].DRBnGRanList[0].UpParamList[0].teId = 0x34345, .pduSession[0].DRBnGRanList[0].UpParamList[0].tl_info = create_up_tl_info(),
.pduSession[0].DRBnGRanList[0].UpParamList[0].tlAddress = 167772161,
}; };
// E1AP encode the original message // E1AP encode the original message
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_response(&orig); E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_response(&orig);
...@@ -335,6 +339,120 @@ static void test_e1_cuup_setup_failure(void) ...@@ -335,6 +339,120 @@ static void test_e1_cuup_setup_failure(void)
free_e1ap_cuup_setup_failure(&orig); free_e1ap_cuup_setup_failure(&orig);
} }
/**
* @brief Test E1AP Bearer Context Modification Request encoding/decoding
*/
static void test_bearer_context_modification_request(void)
{
const bearer_context_sdap_config_t dummy_sdap_config = {
.defaultDRB = 0,
.sDAP_Header_DL = false,
.sDAP_Header_UL = false,
};
const bearer_context_pdcp_config_t dummy_pdcp_config = {
.discardTimer = E1AP_DiscardTimer_ms100,
.pDCP_Reestablishment = true,
.pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_12,
.pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_12,
.reorderingTimer = 5,
.rLC_Mode = E1AP_RLC_Mode_rlc_um_bidirectional,
};
const qos_flow_to_setup_t dummy_qos_flows = {
.qfi = 9,
.qos_params.alloc_reten_priority.preemption_capability = E1AP_Pre_emptionCapability_may_trigger_pre_emption,
.qos_params.alloc_reten_priority.preemption_vulnerability = E1AP_Pre_emptionVulnerability_pre_emptable,
.qos_params.alloc_reten_priority.priority_level = E1AP_PriorityLevel_no_priority,
.qos_params.qos_characteristics.non_dynamic.fiveqi = 9,
};
DRB_nGRAN_to_mod_t drb_to_mod = {
.numDlUpParam = 1,
.DlUpParamList[0].cell_group_id = MCG,
.DlUpParamList[0].tl_info = create_up_tl_info(),
.id = 1,
.pdcp_config = malloc_or_fail(sizeof(*drb_to_mod.pdcp_config)),
.pdcp_sn_status_requested = true,
.numQosFlow2Setup = 1,
.qosFlows[0] = dummy_qos_flows,
};
*drb_to_mod.pdcp_config = dummy_pdcp_config;
pdu_session_to_mod_t pdusession_mod_item = {
.sessionId = 1,
.numDRB2Modify = 1,
.DRBnGRanModList[0] = drb_to_mod,
};
DRB_nGRAN_to_setup_t drb_to_setup = {
.id = 1,
.cellGroupList[0] = MCG,
.numCellGroups = 1,
.pdcp_config = dummy_pdcp_config,
.sdap_config = dummy_sdap_config,
.numQosFlow2Setup = 1,
.qosFlows[0] = dummy_qos_flows,
.drb_inactivity_timer = malloc_or_fail(sizeof(*drb_to_setup.drb_inactivity_timer)),
};
*drb_to_setup.drb_inactivity_timer = 500;
pdu_session_to_setup_t pdusession_setup_item = {
.numDRB2Setup = 1,
.nssai.sd = 0x01,
.nssai.sst = 0x01,
.UP_TL_information.teId = 0x12345,
.UP_TL_information.tlAddress = 167772161,
.DRBnGRanList[0] = drb_to_setup,
};
// Initialize the Bearer Context Modification Request
e1ap_bearer_mod_req_t orig = {
.gNB_cu_cp_ue_id = 0x1234,
.gNB_cu_up_ue_id = 0x5678,
.bearerContextStatus = malloc_or_fail(sizeof(*orig.bearerContextStatus)),
.inactivityTimer = malloc_or_fail(sizeof(*orig.inactivityTimer)),
.numPDUSessions = 1,
.pduSession[0] = pdusession_setup_item,
.numPDUSessionsMod = 1,
.pduSessionMod[0] = pdusession_mod_item,
};
*orig.bearerContextStatus = BEARER_SUSPEND;
*orig.inactivityTimer = 1000;
// Encode the original message
E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_mod_request(&orig);
// Decode the encoded message
E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc);
// Free the encoded message
e1ap_msg_free(enc);
// Decode the message into a new struct
e1ap_bearer_mod_req_t decoded = {0};
AssertFatal(decode_E1_bearer_context_mod_request(dec, &decoded), "decode_E1_bearer_context_mod_request(): could not decode message\n");
// Free the decoded E1AP message
e1ap_msg_free(dec);
// Compare the original and decoded structs
AssertFatal(eq_bearer_context_mod_request(&orig, &decoded), "eq_bearer_context_mod_request(): decoded message doesn't match\n");
// Free the memory for the decoded message
free_e1ap_context_mod_request(&decoded);
// Deep copy the original message
e1ap_bearer_mod_req_t cp = cp_bearer_context_mod_request(&orig);
// Verify the deep copy matches the original
AssertFatal(eq_bearer_context_mod_request(&orig, &cp), "eq_bearer_context_mod_request(): copied message doesn't match\n");
// Free the copied and original message
free_e1ap_context_mod_request(&cp);
free_e1ap_context_mod_request(&orig);
}
int main() int main()
{ {
// E1 Bearer Context Setup // E1 Bearer Context Setup
...@@ -344,5 +462,7 @@ int main() ...@@ -344,5 +462,7 @@ int main()
test_e1_cuup_setup_request(); test_e1_cuup_setup_request();
test_e1_cuup_setup_response(); test_e1_cuup_setup_response();
test_e1_cuup_setup_failure(); test_e1_cuup_setup_failure();
// E1 Bearer Context Modification Request
test_bearer_context_modification_request();
return 0; return 0;
} }
...@@ -168,7 +168,6 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) ...@@ -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; const pdu_session_to_setup_t *req_pdu = req->pduSession + i;
resp_pdu->id = req_pdu->sessionId; 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"); AssertFatal(req_pdu->numDRB2Setup == 1, "can only handle one DRB per PDU session\n");
resp_pdu->numDRBSetup = req_pdu->numDRB2Setup; resp_pdu->numDRBSetup = req_pdu->numDRB2Setup;
const DRB_nGRAN_to_setup_t *req_drb = &req_pdu->DRBnGRanList[0]; 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) ...@@ -178,7 +177,7 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup; resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
for (int k = 0; k < resp_drb->numQosFlowSetup; k++) { for (int k = 0; k < resp_drb->numQosFlowSetup; k++) {
const qos_flow_to_setup_t *qosflow2Setup = &req_drb->qosFlows[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; qosflowSetup->qfi = qosflow2Setup->qfi;
} }
...@@ -197,17 +196,17 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) ...@@ -197,17 +196,17 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
&resp_n3); &resp_n3);
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for NG-U\n"); 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"); AssertFatal(resp_n3.num_tunnels == req_pdu->numDRB2Setup, "could not create all tunnels\n");
resp_pdu->teId = resp_n3.gnb_NGu_teid[0]; resp_pdu->tl_info.teId = resp_n3.gnb_NGu_teid[0];
memcpy(&resp_pdu->tlAddress, &resp_n3.gnb_addr.buffer, 4); memcpy(&resp_pdu->tl_info.tlAddress, &resp_n3.gnb_addr.buffer, 4);
// create PDCP bearers. This will also create SDAP bearers // create PDCP bearers. This will also create SDAP bearers
NR_DRB_ToAddModList_t DRB_configList = {0}; NR_DRB_ToAddModList_t DRB_configList = {0};
fill_DRB_configList_e1(&DRB_configList, req_pdu); fill_DRB_configList_e1(&DRB_configList, req_pdu);
nr_pdcp_entity_security_keys_and_algos_t security_parameters; nr_pdcp_entity_security_keys_and_algos_t security_parameters;
security_parameters.ciphering_algorithm = req->cipheringAlgorithm; security_parameters.ciphering_algorithm = req->secInfo.cipheringAlgorithm;
security_parameters.integrity_algorithm = req->integrityProtectionAlgorithm; security_parameters.integrity_algorithm = req->secInfo.integrityProtectionAlgorithm;
memcpy(security_parameters.ciphering_key, req->encryptionKey, NR_K_KEY_SIZE); memcpy(security_parameters.ciphering_key, req->secInfo.encryptionKey, NR_K_KEY_SIZE);
memcpy(security_parameters.integrity_key, req->integrityProtectionKey, 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 nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE
cu_up_ue_id, cu_up_ue_id,
&DRB_configList, &DRB_configList,
...@@ -230,8 +229,8 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) ...@@ -230,8 +229,8 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
&resp_f1); &resp_f1);
resp_drb->numUpParam = 1; resp_drb->numUpParam = 1;
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n"); AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n");
memcpy(&resp_drb->UpParamList[0].tlAddress, &resp_f1.gnb_addr.buffer, 4); memcpy(&resp_drb->UpParamList[0].tl_info.tlAddress, &resp_f1.gnb_addr.buffer, 4);
resp_drb->UpParamList[0].teId = resp_f1.gnb_NGu_teid[0]; 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 // We assume all DRBs to setup have been setup successfully, so we always
...@@ -273,12 +272,18 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) ...@@ -273,12 +272,18 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j]; DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j];
modified->id = to_modif->id; 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; nr_pdcp_entity_security_keys_and_algos_t security_parameters;
security_parameters.ciphering_algorithm = req->cipheringAlgorithm; if (req->secInfo) {
security_parameters.integrity_algorithm = req->integrityProtectionAlgorithm; security_parameters.ciphering_algorithm = req->secInfo->cipheringAlgorithm;
memcpy(security_parameters.ciphering_key, req->encryptionKey, NR_K_KEY_SIZE); security_parameters.integrity_algorithm = req->secInfo->integrityProtectionAlgorithm;
memcpy(security_parameters.integrity_key, req->integrityProtectionKey, NR_K_KEY_SIZE); memcpy(security_parameters.ciphering_key, req->secInfo->encryptionKey, NR_K_KEY_SIZE);
memcpy(security_parameters.integrity_key, req->secInfo->integrityProtectionKey, NR_K_KEY_SIZE);
} else {
/* don't change security settings if not present in the Bearer Context Modification Request */
security_parameters.ciphering_algorithm = -1;
security_parameters.integrity_algorithm = -1;
}
nr_pdcp_reestablishment(req->gNB_cu_up_ue_id, nr_pdcp_reestablishment(req->gNB_cu_up_ue_id,
to_modif->id, to_modif->id,
false, false,
...@@ -291,8 +296,8 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) ...@@ -291,8 +296,8 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
/* Loop through DL UP Transport Layer params list /* Loop through DL UP Transport Layer params list
* and update GTP tunnel outgoing addr and TEID */ * and update GTP tunnel outgoing addr and TEID */
for (int k = 0; k < to_modif->numDlUpParam; k++) { for (int k = 0; k < to_modif->numDlUpParam; k++) {
in_addr_t addr = to_modif->DlUpParamList[k].tlAddress; 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].teId); GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[k].tl_info.teId);
} }
} }
} }
......
...@@ -27,9 +27,10 @@ ...@@ -27,9 +27,10 @@
void nr_pdcp_e1_if_init(bool uses_e1); void nr_pdcp_e1_if_init(bool uses_e1);
struct e1ap_bearer_setup_req_s; struct e1ap_bearer_setup_req_s;
struct e1ap_bearer_mod_req_s;
struct e1ap_bearer_release_cmd_s; struct e1ap_bearer_release_cmd_s;
void e1_bearer_context_setup(const struct e1ap_bearer_setup_req_s *req); 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); void e1_bearer_release_cmd(const struct e1ap_bearer_release_cmd_s *cmd);
void e1_reset(void); void e1_reset(void);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "e1ap_messages_types.h" #include "e1ap_messages_types.h"
#include "intertask_interface.h" #include "intertask_interface.h"
#include "nr_rrc_defs.h" #include "nr_rrc_defs.h"
#include "E1AP/lib/e1ap_bearer_context_management.h"
static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req) static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req)
{ {
...@@ -33,8 +34,7 @@ static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1a ...@@ -33,8 +34,7 @@ static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1a
MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ); MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ);
msg_p->ittiMsgHeader.originInstance = assoc_id; msg_p->ittiMsgHeader.originInstance = assoc_id;
e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p); e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p);
memcpy(bearer_req, req, sizeof(e1ap_bearer_setup_req_t)); *bearer_req = cp_bearer_context_setup_request(req);
itti_send_msg_to_task (TASK_CUCP_E1, 0, msg_p); itti_send_msg_to_task (TASK_CUCP_E1, 0, msg_p);
} }
......
...@@ -29,9 +29,11 @@ ...@@ -29,9 +29,11 @@
#include "common/platform_types.h" #include "common/platform_types.h"
struct e1ap_bearer_setup_req_s; struct e1ap_bearer_setup_req_s;
struct e1ap_bearer_mod_req_s;
struct e1ap_bearer_setup_resp_s; struct e1ap_bearer_setup_resp_s;
struct e1ap_bearer_release_cmd_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_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); 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; struct gNB_RRC_INST_s;
......
...@@ -343,7 +343,7 @@ typedef struct nr_mac_rrc_dl_if_s { ...@@ -343,7 +343,7 @@ typedef struct nr_mac_rrc_dl_if_s {
typedef struct cucp_cuup_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_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_bearer_context_release_func_t bearer_context_release;
} cucp_cuup_if_t; } cucp_cuup_if_t;
......
...@@ -736,6 +736,14 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, ...@@ -736,6 +736,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); 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 /* \brief find existing PDU session inside E1AP Bearer Modif message, or
* point to new one. * point to new one.
* \param bearer_modif E1AP Bearer Modification Message * \param bearer_modif E1AP Bearer Modification Message
...@@ -793,20 +801,27 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) ...@@ -793,20 +801,27 @@ 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_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify];
drb_e1->id = drb_id; drb_e1->id = drb_id;
drb_e1->numDlUpParam = 1; drb_e1->numDlUpParam = 1;
memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); memcpy(&drb_e1->DlUpParamList[0].tl_info.tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4);
drb_e1->DlUpParamList[0].teId = drb->du_tunnel_config.teid; drb_e1->DlUpParamList[0].tl_info.teId = drb->du_tunnel_config.teid;
/* PDCP configuration */ /* 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); set_bearer_context_pdcp_config(pdcp_config, drb, rrc->configuration.um_on_default_drb);
pdcp_config->pDCP_Reestablishment = true; pdcp_config->pDCP_Reestablishment = true;
/* increase DRB to modify counter */ /* increase DRB to modify counter */
pdu_e1->numDRB2Modify += 1; pdu_e1->numDRB2Modify += 1;
} }
req.cipheringAlgorithm = rrc->security.do_drb_ciphering ? ue_p->ciphering_algorithm : 0; #if 0
req.integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? ue_p->integrity_algorithm : 0; /* According to current understanding of E1 specifications, it is not needed
nr_derive_key(UP_ENC_ALG, req.cipheringAlgorithm, ue_p->kgnb, (uint8_t *)req.encryptionKey); * to send security information because this does not change.
nr_derive_key(UP_INT_ALG, req.integrityProtectionAlgorithm, ue_p->kgnb, (uint8_t *)req.integrityProtectionKey); * But let's keep the code here in case it's needed.
*/
// Always send security information
req.secInfo = malloc_or_fail(sizeof(*req.secInfo));
fill_security_info(rrc, ue_p, req.secInfo);
#endif
/* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */ /* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */
sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p); sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p);
...@@ -1855,12 +1870,12 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC ...@@ -1855,12 +1870,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 /* \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_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 */ * \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->id = drb_f1->drb_id;
drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length; 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].tl_info.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.teId = drb_f1->up_dl_tnl[0].teid;
} }
/** /**
...@@ -1892,8 +1907,8 @@ static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_R ...@@ -1892,8 +1907,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) static void f1u_ul_gtp_update(f1u_tunnel_t *f1u, const up_params_t *p)
{ {
f1u->teid = p->teId; f1u->teid = p->tl_info.teId;
memcpy(&f1u->addr.buffer, &p->tlAddress, sizeof(uint8_t) * 4); memcpy(&f1u->addr.buffer, &p->tl_info.tlAddress, sizeof(uint8_t) * 4);
f1u->addr.length = sizeof(in_addr_t); f1u->addr.length = sizeof(in_addr_t);
} }
...@@ -1919,10 +1934,10 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f ...@@ -1919,10 +1934,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); 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; 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); DevAssert(pdu_e1 != NULL);
pdu_e1->sessionId = pdu_ue->param.pdusession_id; 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 context modification */
fill_e1_bearer_modif(drb_e1, drb_f1); fill_e1_bearer_modif(drb_e1, drb_f1);
pdu_e1->numDRB2Modify += 1; pdu_e1->numDRB2Modify += 1;
...@@ -1930,10 +1945,9 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f ...@@ -1930,10 +1945,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.numPDUSessionsMod > 0);
DevAssert(req.numPDUSessions == 0); DevAssert(req.numPDUSessions == 0);
req.cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; // Always send security information
req.integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? UE->integrity_algorithm : 0; req.secInfo = malloc_or_fail(sizeof(*req.secInfo));
nr_derive_key(UP_ENC_ALG, req.cipheringAlgorithm, UE->kgnb, (uint8_t *)req.encryptionKey); fill_security_info(rrc, UE, req.secInfo);
nr_derive_key(UP_INT_ALG, req.integrityProtectionAlgorithm, UE->kgnb, (uint8_t *)req.integrityProtectionKey);
// send the E1 bearer modification request message to update F1-U tunnel info // 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); sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE);
...@@ -2270,9 +2284,9 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, ...@@ -2270,9 +2284,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]; f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
drb->drb_id = pduSession[p].DRBnGRanList[i].id; 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->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].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; drb->up_ul_tnl_length = 1;
/* pass QoS info to MAC */ /* pass QoS info to MAC */
...@@ -2323,8 +2337,8 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp ...@@ -2323,8 +2337,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); LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id);
continue; continue;
} }
rrc_pdu->param.gNB_teid_N3 = e1_pdu->teId; rrc_pdu->param.gNB_teid_N3 = e1_pdu->tl_info.teId;
memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tlAddress, sizeof(uint8_t) * 4); 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.gNB_addr_N3.length = sizeof(in_addr_t);
// save the tunnel address for the DRBs // save the tunnel address for the DRBs
......
...@@ -353,10 +353,11 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession ...@@ -353,10 +353,11 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
session->nssai = sessions[i].nssai; session->nssai = sessions[i].nssai;
decodePDUSessionResourceSetup(session); decodePDUSessionResourceSetup(session);
bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id;
bearer_req.cipheringAlgorithm = UE->ciphering_algorithm; security_information_t *secInfo = &bearer_req.secInfo;
bearer_req.integrityProtectionAlgorithm = UE->integrity_algorithm; secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0;
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, (uint8_t *)bearer_req.encryptionKey); secInfo->integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? UE->integrity_algorithm : 0;
nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, (uint8_t *)bearer_req.integrityProtectionKey); 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);
bearer_req.ueDlAggMaxBitRate = ueAggMaxBitRateDownlink; bearer_req.ueDlAggMaxBitRate = ueAggMaxBitRateDownlink;
pdu_session_to_setup_t *pdu = bearer_req.pduSession + bearer_req.numPDUSessions; pdu_session_to_setup_t *pdu = bearer_req.pduSession + bearer_req.numPDUSessions;
bearer_req.numPDUSessions++; bearer_req.numPDUSessions++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment