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
This commit is contained in:
+11
-9
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user