Commit 2146f29c authored by Guido Casati's avatar Guido Casati

Refactor E1 Bearer Context Management structs

Bearer context setup request and modification request messages
differ in various IEs according to 9.2.2 of 3GPP TS 38.463, e.g.
the Bearer context setup request does not contain a list of
DRBs to modify and does not contain an UP TL configuration.

Thus, the goal of this commit is to split the setup request message
and the modification request into two different structs:
* adopt e1ap_bearer_mod_req_t where necessary (e.g. fill_e1_bearer_modif)

Also, reorganized existing struct members according to specs:
* remove irrelevant struct members from the setup request
* group members from the same IEs into structs
* set optional struct members IEs as pointers
* add and adopt enc/dec/cp/eq lib functions for single IEs
* add UP_TL_information_t struct with TEID and TL address info and adopt in stack
* use int instead of long for count types
* update the relevant copy/equality check utility functions

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