X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=sim%2Fe2-interface.git;a=blobdiff_plain;f=e2sim%2Fe2apv1sim%2Fe2sim%2Fsrc%2FASN1%2Flib%2Fasn_e2ap.cpp;fp=e2sim%2Fe2apv1sim%2Fe2sim%2Fsrc%2FASN1%2Flib%2Fasn_e2ap.cpp;h=fa2fd887ae8fa7b2018e1ed752d81a9107bc9969;hp=0000000000000000000000000000000000000000;hb=3ebf932d23dcbec9ed19f4a51f9d00a0a54f5124;hpb=6896318f2b4ff01b4a88b16019c3dc93b0b693f5 diff --git a/e2sim/e2apv1sim/e2sim/src/ASN1/lib/asn_e2ap.cpp b/e2sim/e2apv1sim/e2sim/src/ASN1/lib/asn_e2ap.cpp new file mode 100644 index 0000000..fa2fd88 --- /dev/null +++ b/e2sim/e2apv1sim/e2sim/src/ASN1/lib/asn_e2ap.cpp @@ -0,0 +1,982 @@ +/***************************************************************************** +# * +# Copyright 2019 AT&T Intellectual Property * +# Copyright 2019 Nokia * +# * +# Licensed under the Apache License, Version 2.0 (the "License"); * +# you may not use this file except in compliance with the License. * +# You may obtain a copy of the License at * +# * +# http://www.apache.org/licenses/LICENSE-2.0 * +# * +# Unless required by applicable law or agreed to in writing, software * +# distributed under the License is distributed on an "AS IS" BASIS, * +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * +# See the License for the specific language governing permissions and * +# limitations under the License. * +# * +******************************************************************************/ +#include "asn_e2ap.hpp" +#include "asn_e2ap_wrapper.hpp" + +/*----------------------------------------------------------------------- + COMMON ROUTINES +------------------------------------------------------------------------- +*/ +e2ap_pdu_t* new_e2ap_pdu(void) +{ + E2APpduWrapper* pduWrapper = new E2APpduWrapper(); + return reinterpret_cast(pduWrapper); +} + +void e2ap_asn_print(e2ap_pdu_t* pdu, char* buf, size_t buf_size) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + buf[0] = 0; + + strncat(buf, asn::get_printed(pduWrapper->ref_pdu()).c_str(), buf_size - 1); +} + +int e2ap_asn_per_encode(e2ap_pdu_t* pdu, unsigned char* buf, size_t buf_size, + char* err_buf, size_t err_buf_size) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + asn::per::EncoderCtx ctx{ buf, buf_size }; + + if (!asn::per::pack(pduWrapper->ref_pdu(), ctx)) { + err_buf[0] = 0; + //strncat(err_buf, ctx.refErrorCtx().toString().c_str(), err_buf_size - 1); + return -1; + } else { + return static_cast(ctx.refBuffer().getBytesUsed()); + } + +} + +int e2ap_asn_per_decode(e2ap_pdu_t* pdu, unsigned char const* buf, size_t buf_size, + char* err_buf, size_t err_buf_size) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + asn::per::DecoderCtx ctx{ buf, + buf_size, + pduWrapper->m_allocation_buffer, + pduWrapper->m_allocation_buffer_size }; + + if (!asn::per::unpack(pduWrapper->ref_pdu(), ctx)) { + err_buf[0] = 0; + //strncat(err_buf, ctx.refErrorCtx().toString().c_str(), err_buf_size - 1); + return -1; + } + + return 0; + +} + +int e2ap_get_index(e2ap_pdu_t* pdu) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + return pduWrapper->ref_pdu().get_index(); +} + +int e2ap_get_procedureCode(e2ap_pdu_t* pdu) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + switch(pduWrapper->ref_pdu().get_index()) + { + case 1: + return pduWrapper->ref_pdu().get_initiatingMessage()->ref_procedureCode().get(); + break; + + case 2: + return pduWrapper->ref_pdu().get_successfulOutcome()->ref_procedureCode().get(); + break; + + case 3: + return pduWrapper->ref_pdu().get_unsuccessfulOutcome()->ref_procedureCode().get(); + break; + + default: + return -1; + } + +} + +/*----------------------------------------------------------------------- + MESSAGE GENERATORS +------------------------------------------------------------------------- +*/ +//X2Setup +bool e2ap_init_X2SetupRequest(e2ap_pdu_t* pdu) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + //Initialization + pduWrapper->ref_pdu().select_initiatingMessage(); + pduWrapper->ref_pdu().select_initiatingMessage().clear(); + pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_x2Setup(); + pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_x2Setup(); + pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_x2Setup(); + + return true; +} + +bool e2ap_create_X2SetupRequest(e2ap_pdu_t* pdu, eNB_config &cfg) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_x2Setup(); + pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_x2Setup(); + + X2SetupRequest* container = + &(pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_x2Setup()); + + using IE_value_t = X2SetupRequest::protocolIEs_t::value_type; + + /* X2SetupRequest-IEs : GlobalENB-ID*/ + IE_value_t* val_GlobalENB_ID = new IE_value_t; + container->ref_protocolIEs().push_back(*val_GlobalENB_ID); + + val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID(); + val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID(); + val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_pLMN_Identity() + .set(3, cfg.pLMN_Identity); + val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID() + .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID); + + /* X2SetupRequest-IEs : ServedCells*/ + IE_value_t* val_ServedCells = new IE_value_t; + container->ref_protocolIEs().push_back(*val_ServedCells); + + val_ServedCells->ref_id().select_id_ServedCells(); + val_ServedCells->ref_criticality().select_id_ServedCells(); + val_ServedCells->ref_value().select_id_ServedCells(); + + //Add servedCellInfo + ServedCells::value_type* elm = new ServedCells::value_type(); + ServedCell_Information* info = &(elm->ref_servedCellInfo()); + { + //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info + info->ref_pCI().set(cfg.pCI); + info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity); + info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier); + info->ref_tAC().set(2, cfg.tAC); + + BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type(); + item->set(3, cfg.pLMN_Identity); + info->ref_broadcastPLMNs().push_back(*item); + + info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN); + info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN); + info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth() + .set(static_cast(cfg.uL_Bandwidth)); + info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth() + .set(static_cast(cfg.dL_Bandwidth)); + } + val_ServedCells->ref_value().select_id_ServedCells().push_back(*elm); + + return true; +} + +bool e2ap_create_X2SetupResponse(e2ap_pdu_t* pdu, eNB_config &cfg) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_successfulOutcome().ref_procedureCode().select_id_x2Setup(); + pduWrapper->ref_pdu().select_successfulOutcome().ref_criticality().select_id_x2Setup(); + + X2SetupResponse* container = + &(pduWrapper->ref_pdu().select_successfulOutcome().ref_value().select_id_x2Setup()); + + using IE_value_t = X2SetupResponse::protocolIEs_t::value_type; + + /* X2SetupResponse-IEs : GlobalENB-ID*/ + IE_value_t* val_GlobalENB_ID = new IE_value_t; + container->ref_protocolIEs().push_back(*val_GlobalENB_ID); + + val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID(); + val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID(); + val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_pLMN_Identity() + .set(3, cfg.pLMN_Identity); + + val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID() + .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID); + + /* X2SetupResponse-IEs : ServedCells*/ + IE_value_t* val_ServedCells = new IE_value_t; + container->ref_protocolIEs().push_back(*val_ServedCells); + + val_ServedCells->ref_id().select_id_ServedCells(); + val_ServedCells->ref_criticality().select_id_ServedCells(); + val_ServedCells->ref_value().select_id_ServedCells(); + + //Add servedCellInfo + ServedCells::value_type* elm = new ServedCells::value_type(); + ServedCell_Information* info = &(elm->ref_servedCellInfo()); + { + //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info + info->ref_pCI().set(cfg.pCI); + info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity); + info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier); + info->ref_tAC().set(2, cfg.tAC); + + BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type(); + item->set(3, cfg.pLMN_Identity); + info->ref_broadcastPLMNs().push_back(*item); + + info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN); + info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN); + info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth() + .set(static_cast(cfg.uL_Bandwidth)); + info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth() + .set(static_cast(cfg.dL_Bandwidth)); + } + val_ServedCells->ref_value().select_id_ServedCells().push_back(*elm); + + return true; +} + +bool e2ap_create_X2SetupFailure(e2ap_pdu_t* pdu) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_procedureCode().select_id_x2Setup(); + pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_criticality().select_id_x2Setup(); + + X2SetupFailure* container = + &(pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_value().select_id_x2Setup()); + + using IE_value_t = X2SetupFailure::protocolIEs_t::value_type; + + /* X2SetupFailure-IEs << id-Cause */ + IE_value_t* val_cause = new IE_value_t; + container->ref_protocolIEs().push_back(*val_cause); + + val_cause->ref_id().select_id_Cause(); + val_cause->ref_criticality().select_id_Cause(); + + /* Cause << radioNetwork */ + val_cause->ref_value().select_id_Cause().select_radioNetwork(); + + /* CauseRadioNetwork = ho-target-not-allowed (enum = 8)*/ + val_cause->ref_value().select_id_Cause().select_radioNetwork() + .set(static_cast(8)); + + return true; +} + +//ENDCX2Setup +bool e2ap_create_ENDCX2SetupRequest(e2ap_pdu_t* pdu, eNB_config &cfg) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_endcX2Setup(); + pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_endcX2Setup(); + + ENDCX2SetupRequest* container = + &(pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_endcX2Setup()); + + using IE_value_t = ENDCX2SetupRequest::protocolIEs_t::value_type; + + /* ENDCX2SetupRequest-IEs = id-InitiatingNodeType-EndcX2Setup */ + IE_value_t* ie = new IE_value_t; + container->ref_protocolIEs().push_back(*ie); + ie->ref_id().select_id_InitiatingNodeType_EndcX2Setup(); + ie->ref_criticality().select_id_InitiatingNodeType_EndcX2Setup(); + ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup(); + + /* InitiatingNodeType-EndcX2Setup = init-eNB {ENB-ENDCX2SetupReqIEs} */ + ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup().select_init_eNB(); + + using eNB_val_t = InitiatingNodeType_EndcX2Setup::init_eNB_t::value_type; + + ProtocolIE_Container* eNB_node = + &(ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup().select_init_eNB()); + + /* ENB-ENDCX2SetupReqIEs <-- id-GlobalENB-ID */ + eNB_val_t* val_GlobalENB_ID = new eNB_val_t; + eNB_node->push_back(*val_GlobalENB_ID); + + val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID(); + val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID(); + val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID() + .ref_pLMN_Identity().set(3, cfg.pLMN_Identity); + val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID() + .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID); + + /* ENB-ENDCX2SetupReqIEs <-- id-ServedEUTRAcellsENDCX2ManagementList */ + eNB_val_t* val_EUTRAlist = new eNB_val_t; + eNB_node->push_back(*val_EUTRAlist); + + val_EUTRAlist->ref_id().select_id_ServedEUTRAcellsENDCX2ManagementList(); + val_EUTRAlist->ref_criticality().select_id_ServedEUTRAcellsENDCX2ManagementList(); + val_EUTRAlist->ref_value().select_id_ServedEUTRAcellsENDCX2ManagementList(); + + /* ServedEUTRAcellsENDCX2ManagementList <-- servedEUTRACellInfo */ + ServedEUTRAcellsENDCX2ManagementList::value_type* elm = + new ServedEUTRAcellsENDCX2ManagementList::value_type(); + ServedCell_Information* info = &(elm->ref_servedEUTRACellInfo()); + { + //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info + info->ref_pCI().set(cfg.pCI); + info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity); + info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier); + info->ref_tAC().set(2, cfg.tAC); + + BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type(); + item->set(3, cfg.pLMN_Identity); + info->ref_broadcastPLMNs().push_back(*item); + + info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN); + info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN); + info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth() + .set(static_cast(cfg.uL_Bandwidth)); + info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth() + .set(static_cast(cfg.dL_Bandwidth)); + } + val_EUTRAlist->ref_value().select_id_ServedEUTRAcellsENDCX2ManagementList() + .push_back(*elm); + + return true; +} + +bool e2ap_create_ENDCX2SetupResponse(e2ap_pdu_t* pdu, gNB_config &gnb_cfg) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_successfulOutcome().ref_procedureCode().select_id_endcX2Setup(); + pduWrapper->ref_pdu().select_successfulOutcome().ref_criticality().select_id_endcX2Setup(); + + ENDCX2SetupResponse* container = + &(pduWrapper->ref_pdu().select_successfulOutcome().ref_value().select_id_endcX2Setup()); + + using IE_value_t = ENDCX2SetupResponse::protocolIEs_t::value_type; + + /* ENDCX2SetupRequest-IEs = id-RespondingNodeType-EndcX2Setup */ + IE_value_t* ie = new IE_value_t; + container->ref_protocolIEs().push_back(*ie); + ie->ref_id().select_id_RespondingNodeType_EndcX2Setup(); + ie->ref_criticality().select_id_RespondingNodeType_EndcX2Setup(); + ie->ref_value().select_id_RespondingNodeType_EndcX2Setup(); + + /* RespondingNodeType-EndcX2Setup = respond-en-gNB {En-gNB-ENDCX2SetupReqAckIEs} */ + ie->ref_value().select_id_RespondingNodeType_EndcX2Setup().select_respond_en_gNB(); + + using gNB_val_t = RespondingNodeType_EndcX2Setup::respond_en_gNB_t::value_type; + + ProtocolIE_Container* gNB_node = + &(ie->ref_value().select_id_RespondingNodeType_EndcX2Setup().select_respond_en_gNB()); + + /* En-gNB-ENDCX2SetupReqAckIEs << id-Globalen-gNB-ID */ + gNB_val_t* val_Globalen_gNB_ID = new gNB_val_t; + gNB_node->push_back(*val_Globalen_gNB_ID); + + val_Globalen_gNB_ID->ref_id().select_id_Globalen_gNB_ID(); + val_Globalen_gNB_ID->ref_criticality().select_id_Globalen_gNB_ID(); + val_Globalen_gNB_ID->ref_value().select_id_Globalen_gNB_ID() + .ref_pLMN_Identity().set(3, gnb_cfg.pLMN_Identity); + val_Globalen_gNB_ID->ref_value().select_id_Globalen_gNB_ID().ref_gNB_ID() + .select_gNB_ID().set_buffer(22, gnb_cfg.gNB_ID); + + /* En-gNB-ENDCX2SetupReqAckIEs << id-ServedNRcellsENDCX2ManagementList */ + gNB_val_t* val_ServedNRCells = new gNB_val_t; + gNB_node->push_back(*val_ServedNRCells); + + val_ServedNRCells->ref_id().select_id_ServedNRcellsENDCX2ManagementList(); + val_ServedNRCells->ref_criticality().select_id_ServedNRcellsENDCX2ManagementList(); + val_ServedNRCells->ref_value().select_id_ServedNRcellsENDCX2ManagementList(); + + /* ServedNRcellsENDCX2ManagementList <-- servedNRCellInfo*/ + ServedNRcellsENDCX2ManagementList::value_type* elm = + new ServedNRcellsENDCX2ManagementList::value_type(); + + /* + ServedNRCell-Information ::= SEQUENCE { + nrpCI NRPCI, + nrCellID NRCGI, + fiveGS-TAC FiveGS-TAC OPTIONAL, + configured-TAC TAC OPTIONAL, + broadcastPLMNs BroadcastPLMNs-Item, + nrModeInfo CHOICE { + fdd FDD-InfoServedNRCell-Information, + tdd TDD-InfoServedNRCell-Information, + ... + }, + measurementTimingConfiguration OCTET STRING, + iE-Extensions ProtocolExtensionContainer { {ServedNRCell-Information-ExtIEs} } OPTIONAL, + ... + } + */ + ServedNRCell_Information* info = &(elm->ref_servedNRCellInfo()); + { + // nrpCI NRPCI, + info->ref_nrpCI().set(gnb_cfg.nrpCI); + + /* nrCellID NRCGI, + + NRCGI ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + nRcellIdentifier NRCellIdentifier, + iE-Extensions ProtocolExtensionContainer { {NRCGI-ExtIEs} } OPTIONAL, + ... + } + */ + info->ref_nrCellID().ref_pLMN_Identity().set(3, gnb_cfg.pLMN_Identity); + info->ref_nrCellID().ref_nRcellIdentifier().set_buffer(36, gnb_cfg.nRcellIdentifier); + + /* broadcastPLMNs BroadcastPLMNs-Item */ + BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type(); + item->set(3, gnb_cfg.pLMN_Identity); + info->ref_broadcastPLMNs().push_back(*item); + + /* nrModeInfo CHOICE { + fdd FDD-InfoServedNRCell-Information, + tdd TDD-InfoServedNRCell-Information, + ... + }, + + FDD-InfoServedNRCell-Information ::= SEQUENCE { + ul-NRFreqInfo NRFreqInfo, + dl-NRFreqInfo NRFreqInfo, + ul-NR-TxBW NR-TxBW, + dl-NR-TxBW NR-TxBW, + iE-Extensions ProtocolExtensionContainer { {FDD-InfoServedNRCell-Information-ExtIEs} } OPTIONAL, + ... + } + + NRFreqInfo ::= SEQUENCE{ + nRARFCN INTEGER (0.. 3279165), + freqBandListNr SEQUENCE (SIZE(1..maxnoofNrCellBands)) OF FreqBandNrItem, + sULInformation SULInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {NRFreqInfo-ExtIEs} } OPTIONAL, + + ... + } + + */ + info->ref_nrModeInfo().select_fdd().ref_ul_NRFreqInfo().ref_nRARFCN().set(gnb_cfg.uL_nRARFCN); + info->ref_nrModeInfo().select_fdd().ref_dl_NRFreqInfo().ref_nRARFCN().set(gnb_cfg.dL_nRARFCN); + + /* + FreqBandNrItem ::= SEQUENCE { + freqBandIndicatorNr INTEGER (1..1024,...), + supportedSULBandList SEQUENCE (SIZE(0..maxnoofNrCellBands)) OF SupportedSULFreqBandItem, + iE-Extensions ProtocolExtensionContainer { {FreqBandNrItem-ExtIEs} } OPTIONAL, + ... + } + */ + //uplink + asn::sequenceof::value_type* ul_band_item = + new asn::sequenceof::value_type(); + { + ul_band_item->ref_freqBandIndicatorNr().set(gnb_cfg.ul_freqBandIndicatorNr); + + /* + SupportedSULFreqBandItem ::= SEQUENCE { + freqBandIndicatorNr INTEGER (1..1024,...), + iE-Extensions ProtocolExtensionContainer { {SupportedSULFreqBandItem-ExtIEs} } OPTIONAL, + ... + } + */ + + asn::sequenceof::value_type* ul_supported_band_item = + new asn::sequenceof::value_type(); + + ul_supported_band_item->ref_freqBandIndicatorNr().set(gnb_cfg.ul_freqBandIndicatorNr); + + ul_band_item->ref_supportedSULBandList().push_back(*ul_supported_band_item); + } + info->ref_nrModeInfo().select_fdd().ref_ul_NRFreqInfo() + .ref_freqBandListNr().push_back(*ul_band_item); + + //downlink + asn::sequenceof::value_type* dl_band_item = + new asn::sequenceof::value_type(); + { + dl_band_item->ref_freqBandIndicatorNr().set(gnb_cfg.dl_freqBandIndicatorNr); + + /* + SupportedSULFreqBandItem ::= SEQUENCE { + freqBandIndicatorNr INTEGER (1..1024,...), + iE-Extensions ProtocolExtensionContainer { {SupportedSULFreqBandItem-ExtIEs} } OPTIONAL, + ... + } + */ + + asn::sequenceof::value_type* dl_supported_band_item = + new asn::sequenceof::value_type(); + + dl_supported_band_item->ref_freqBandIndicatorNr().set(gnb_cfg.dl_freqBandIndicatorNr); + + dl_band_item->ref_supportedSULBandList().push_back(*dl_supported_band_item); + } + info->ref_nrModeInfo().select_fdd().ref_dl_NRFreqInfo() + .ref_freqBandListNr().push_back(*dl_band_item); + + /* + NR-TxBW ::= SEQUENCE { + nRSCS NRSCS, + nRNRB NRNRB, + iE-Extensions ProtocolExtensionContainer { {NR-TxBW-ExtIEs} } OPTIONAL, + ... + } + */ + { + info->ref_nrModeInfo().select_fdd().ref_ul_NR_TxBW().ref_nRNRB() + .set( static_cast(gnb_cfg.uL_NRNRB) ); + info->ref_nrModeInfo().select_fdd().ref_ul_NR_TxBW().ref_nRSCS() + .set( static_cast(gnb_cfg.uL_NRSCS) ); + + info->ref_nrModeInfo().select_fdd().ref_dl_NR_TxBW().ref_nRNRB() + .set( static_cast(gnb_cfg.dL_NRNRB) ); + info->ref_nrModeInfo().select_fdd().ref_dl_NR_TxBW().ref_nRSCS() + .set( static_cast(gnb_cfg.dL_NRSCS) ); + } + + /* + measurementTimingConfiguration OCTET STRING, + */ + info->ref_measurementTimingConfiguration().set(gnb_cfg.measurementTimingConfiguration); + } + val_ServedNRCells->ref_value().select_id_ServedNRcellsENDCX2ManagementList().push_back(*elm); + + + + return true; +} + +bool e2ap_create_ENDCX2SetupFailure(e2ap_pdu_t* pdu) +{ + + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_procedureCode().select_id_endcX2Setup(); + pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_criticality().select_id_endcX2Setup(); + + ENDCX2SetupFailure* container = + &(pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_value().select_id_endcX2Setup()); + + using IE_value_t = ENDCX2SetupFailure::protocolIEs_t::value_type; + + /* ENDCX2SetupFailure-IEs := id-Cause*/ + IE_value_t* val_cause = new IE_value_t; + container->ref_protocolIEs().push_back(*val_cause); + + val_cause->ref_id().select_id_Cause(); + val_cause->ref_criticality().select_id_Cause(); + + /* Cause << radioNetwork */ + val_cause->ref_value().select_id_Cause().select_radioNetwork(); + + /* CauseRadioNetwork = ho-target-not-allowed (enum = 8)*/ + val_cause->ref_value().select_id_Cause().select_radioNetwork() + .set(static_cast(8)); + + return true; +} + +//RICSubscription +bool e2ap_create_RICsubscriptionRequest(e2ap_pdu_t* pdu, RICsubscription_params_t ¶ms) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_initiatingMessage() + .ref_procedureCode().select_id_ricSubscription(); + pduWrapper->ref_pdu().select_initiatingMessage() + .ref_criticality().select_id_ricSubscription(); + + RICsubscriptionRequest* container = &(pduWrapper->ref_pdu() + .select_initiatingMessage().ref_value().select_id_ricSubscription()); + + using IE_value_t = RICsubscriptionRequest::protocolIEs_t::value_type; + + /* RICsubscriptionRequest-IEs : RICrequestID */ + IE_value_t* ie_RICrequestID = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_RICrequestID); + + ie_RICrequestID->ref_id().select_id_RICrequestID(); + ie_RICrequestID->ref_criticality().select_id_RICrequestID(); + ie_RICrequestID->ref_value().select_id_RICrequestID() + .ref_ricRequestorID().set(params.request_id); + ie_RICrequestID->ref_value().select_id_RICrequestID() + .ref_ricRequestSequenceNumber().set(params.seq_number); + + /* RICsubscriptionRequest-IEs : RANfunctionID */ + IE_value_t* ie_RANfunctionID = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_RANfunctionID); + + ie_RANfunctionID->ref_id().select_id_RANfunctionID(); + ie_RANfunctionID->ref_criticality().select_id_RANfunctionID(); + ie_RANfunctionID->ref_value().select_id_RANfunctionID().set(params.ran_func_id); + + + /* + RICsubscription ::= SEQUENCE { + ricEventTriggerDefinition RICeventTriggerDefinition, + ricAction-ToBeSetup-List RICactions-ToBeSetup-List, + ... + } + + RICeventTriggerDefinition ::= OCTET STRING + RICactions-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxofRICactionID)) OF ProtocolIE-Single-Container { {RICaction-ToBeSetup-ItemIEs} } + + RICaction-ToBeSetup-ItemIEs X2AP-PROTOCOL-IES ::= { + { ID id-RICaction-ToBeSetup-Item CRITICALITY ignore TYPE RICaction-ToBeSetup-Item PRESENCE mandatory }, + ... + } + + RICaction-ToBeSetup-Item ::= SEQUENCE { + ricActionID RICactionID, + ricActionType RICactionType, + ricActionDefinition RICactionDefinition OPTIONAL, + ricSubsequentAction RICsubsequentAction OPTIONAL, + ... + } + + RICactionID ::= INTEGER (0..255) + + RICactionType ::= ENUMERATED{ + report, + insert, + policy, + ... + } + */ + + /* RICsubscriptionRequest-IEs : RICsubscription */ + IE_value_t* ie_RICsubscription = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_RICsubscription); + + ie_RICsubscription->ref_id().select_id_RICsubscription(); + ie_RICsubscription->ref_criticality().select_id_RICsubscription(); + + // RICeventTriggerDefinition + ie_RICsubscription->ref_value().select_id_RICsubscription() + .ref_ricEventTriggerDefinition().set(params.event_trigger_def); + + //RICactions-ToBeSetup-List + for( auto const &action : params.actionList) + { + RICactions_ToBeSetup_List::value_type* item = + new RICactions_ToBeSetup_List::value_type(); + + ie_RICsubscription->ref_value().select_id_RICsubscription() + .ref_ricAction_ToBeSetup_List().push_back(*item); + + item->ref_id().select_id_RICaction_ToBeSetup_Item(); + item->ref_criticality().select_id_RICaction_ToBeSetup_Item(); + item->ref_value().select_id_RICaction_ToBeSetup_Item() + .ref_ricActionID().set(action.action_id); + item->ref_value().select_id_RICaction_ToBeSetup_Item() + .ref_ricActionType().set(action.action_type); + + } + + return true; +} + +bool e2ap_parse_RICsubscriptionRequest(e2ap_pdu_t* pdu, RICsubscription_params_t ¶ms) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + RICsubscriptionRequest* container = &(pduWrapper->ref_pdu() + .select_initiatingMessage().ref_value().select_id_ricSubscription()); + + + for(auto &e : container->ref_protocolIEs()) + { + /*See struct RICsubscriptionRequest_IEs*/ + size_t type = e.ref_value().get_index(); + + switch(type) + { + case 1: //RICrequestID + { + params.request_id = e.ref_value().select_id_RICrequestID().ref_ricRequestorID().get(); + params.seq_number = e.ref_value().select_id_RICrequestID().ref_ricRequestSequenceNumber().get(); + } + break; + + case 2: //RANfunctionID + params.ran_func_id = e.ref_value().select_id_RANfunctionID().get(); + break; + + case 3: //RICsubscription + { + auto event = e.ref_value().select_id_RICsubscription().ref_ricEventTriggerDefinition().get(); + (params.event_trigger_def).assign(std::string(event.data(), event.data() + event.size())); + + //ricAction_ToBeSetup_List + for (auto & f : e.ref_value().select_id_RICsubscription().ref_ricAction_ToBeSetup_List()) + { + RIC_action_t action; + action.action_id = f.ref_value() + .select_id_RICaction_ToBeSetup_Item().ref_ricActionID().get(); + action.action_type = static_cast(f.ref_value() + .select_id_RICaction_ToBeSetup_Item().ref_ricActionType().get()); + + params.actionList.push_back(action); + } + } + break; + + default: + printf("Unknown IE type = %d\n", (int)type); + return false; + } + } + + return true; +} + +bool e2ap_create_RICsubscriptionResponse(e2ap_pdu_t* pdu, RICsubscription_params_t ¶ms) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_successfulOutcome().ref_procedureCode().select_id_ricSubscription(); + pduWrapper->ref_pdu().select_successfulOutcome().ref_criticality().select_id_ricSubscription(); + + RICsubscriptionResponse* container = &(pduWrapper->ref_pdu() + .select_successfulOutcome().ref_value().select_id_ricSubscription()); + + using IE_value_t = RICsubscriptionResponse::protocolIEs_t::value_type; + + /* RICsubscriptionResponse-IEs : RICrequestID */ + IE_value_t* ie_RICrequestID = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_RICrequestID); + + ie_RICrequestID->ref_id().select_id_RICrequestID(); + ie_RICrequestID->ref_criticality().select_id_RICrequestID(); + ie_RICrequestID->ref_value().select_id_RICrequestID() + .ref_ricRequestorID().set(params.request_id); + ie_RICrequestID->ref_value().select_id_RICrequestID() + .ref_ricRequestSequenceNumber().set(params.seq_number); + + /* RICsubscriptionResponse-IEs : RANfunctionID */ + IE_value_t* ie_RANfunctionID = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_RANfunctionID); + + ie_RANfunctionID->ref_id().select_id_RANfunctionID(); + ie_RANfunctionID->ref_criticality().select_id_RANfunctionID(); + ie_RANfunctionID->ref_value().select_id_RANfunctionID().set(params.ran_func_id); + + /* RICsubscriptionResponse-IEs : RICaction-Admitted-List */ + IE_value_t* ie_admittedList = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_admittedList); + + ie_admittedList->ref_id().select_id_RICactions_Admitted(); + ie_admittedList->ref_criticality().select_id_RICactions_Admitted(); + + /* RICsubscriptionResponse-IEs : RICaction-NotAdmitted-List */ + IE_value_t* ie_notAdmittedList = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_notAdmittedList); + + ie_notAdmittedList->ref_id().select_id_RICactions_NotAdmitted(); + ie_notAdmittedList->ref_criticality().select_id_RICactions_NotAdmitted(); + + //add action to admitted and not-admitted list + for(auto const &a : params.actionList) + { + if(a.isAdmitted) + { + RICaction_Admitted_List::value_type* item = new RICaction_Admitted_List::value_type(); + + ie_admittedList->ref_value().select_id_RICactions_Admitted().push_back(*item); + + item->ref_id().select_id_RICaction_Admitted_Item(); + item->ref_criticality().select_id_RICaction_Admitted_Item(); + item->ref_value().select_id_RICaction_Admitted_Item().ref_ricActionID().set(a.action_id); + } + else + { + RICaction_NotAdmitted_List::value_type* item = new RICaction_NotAdmitted_List::value_type(); + + ie_notAdmittedList->ref_value().select_id_RICactions_NotAdmitted().push_back(*item); + + item->ref_id().select_id_RICaction_NotAdmitted_Item(); + item->ref_criticality().select_id_RICaction_NotAdmitted_Item(); + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricActionID().set(a.action_id); + + // set cause and sub-cause + switch(a.notAdmitted_cause) + { + case RICcause_radioNetwork: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_radioNetwork().set(a.notAdmitted_subCause); + break; + + case RICcause_transport: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_transport().set(a.notAdmitted_subCause); + break; + + case RICcause_protocol: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_protocol().set(a.notAdmitted_subCause); + break; + + case RICcause_misc: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_misc().set(a.notAdmitted_subCause); + break; + + case RICcause_ric: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_ric().set(a.notAdmitted_subCause); + break; + + default: + printf("Unknown cause for action not admitted = %d", (int)a.notAdmitted_cause); + } + } + } + + return true; +} + +bool e2ap_create_RICsubscriptionFailure(e2ap_pdu_t* pdu, RICsubscription_params_t ¶ms) +{ + E2APpduWrapper* pduWrapper = reinterpret_cast(pdu); + + /* Initiaization */ + pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_procedureCode().select_id_ricSubscription(); + pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_criticality().select_id_ricSubscription(); + + RICsubscriptionFailure* container = &(pduWrapper->ref_pdu() + .select_unsuccessfulOutcome().ref_value().select_id_ricSubscription()); + + using IE_value_t = RICsubscriptionFailure::protocolIEs_t::value_type; + + /* RICsubscriptionFailure-IEs : RICrequestID */ + IE_value_t* ie_RICrequestID = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_RICrequestID); + + ie_RICrequestID->ref_id().select_id_RICrequestID(); + ie_RICrequestID->ref_criticality().select_id_RICrequestID(); + ie_RICrequestID->ref_value().select_id_RICrequestID() + .ref_ricRequestorID().set(params.request_id); + ie_RICrequestID->ref_value().select_id_RICrequestID() + .ref_ricRequestSequenceNumber().set(params.seq_number); + + /* RICsubscriptionFailure-IEs : RANfunctionID */ + IE_value_t* ie_RANfunctionID = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_RANfunctionID); + + ie_RANfunctionID->ref_id().select_id_RANfunctionID(); + ie_RANfunctionID->ref_criticality().select_id_RANfunctionID(); + ie_RANfunctionID->ref_value().select_id_RANfunctionID().set(params.ran_func_id); + + /* RICsubscriptionFailure-IEs : RICaction-NotAdmitted-List */ + IE_value_t* ie_notAdmittedList = new IE_value_t; + container->ref_protocolIEs().push_back(*ie_notAdmittedList); + + ie_notAdmittedList->ref_id().select_id_RICactions_NotAdmitted(); + ie_notAdmittedList->ref_criticality().select_id_RICactions_NotAdmitted(); + + for(auto const &a : params.actionList) + { + if(!a.isAdmitted) + { + RICaction_NotAdmitted_List::value_type* item = new RICaction_NotAdmitted_List::value_type(); + + ie_notAdmittedList->ref_value().select_id_RICactions_NotAdmitted().push_back(*item); + + item->ref_id().select_id_RICaction_NotAdmitted_Item(); + item->ref_criticality().select_id_RICaction_NotAdmitted_Item(); + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricActionID().set(a.action_id); + + // set cause and sub-cause + switch(a.notAdmitted_cause) + { + case RICcause_radioNetwork: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_radioNetwork().set(a.notAdmitted_subCause); + break; + + case RICcause_transport: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_transport().set(a.notAdmitted_subCause); + break; + + case RICcause_protocol: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_protocol().set(a.notAdmitted_subCause); + break; + + case RICcause_misc: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_misc().set(a.notAdmitted_subCause); + break; + + case RICcause_ric: + item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_ric().set(a.notAdmitted_subCause); + break; + + default: + printf("Unknown cause for action not admitted = %d", (int)a.notAdmitted_cause); + } + } + } + + return true; +} + + +/*----------------------------------------------------------------------- + TESTS +------------------------------------------------------------------------- +*/ +void test_E2AP_X2Setup_codec(void) +{ + e2ap_pdu_t* pdu = new_e2ap_pdu(); + + // e2ap_init_X2SetupRequest(pdu); + eNB_config cfg; + e2ap_create_X2SetupRequest(pdu, cfg); + + char pdu_str[1024]; + e2ap_asn_print(pdu, pdu_str, sizeof(pdu_str)); + printf("%s\n", pdu_str); + + //Test encode + unsigned char packed_buf[4096]; + char err_buf[1024]; + + int packed_len = e2ap_asn_per_encode(pdu, packed_buf, sizeof(packed_buf), + err_buf, sizeof(err_buf)); + if(packed_len != -1) { + printf("Encode successful, packed_len = %d\n", packed_len); + } else { + printf("Encode Error: %s\n", err_buf); + } + + //Test decode + e2ap_pdu_t* pdu2 = new_e2ap_pdu(); + int rc = e2ap_asn_per_decode(pdu2, packed_buf, packed_len, err_buf, sizeof(err_buf)); + if(rc == -1) { + printf("Decode error: %s\n", err_buf); + } else { + printf("Decode successful\n"); + } + + e2ap_asn_print(pdu2, pdu_str, sizeof(pdu_str)); + printf("%s\n", pdu_str); + + printf("index = %d\n", e2ap_get_index(pdu2)); + printf("procedureCode = %d\n", e2ap_get_procedureCode(pdu2)); + + //Test X2SetupResponse + e2ap_pdu_t* pdu_resp = new_e2ap_pdu(); + e2ap_create_X2SetupResponse(pdu_resp, cfg); + e2ap_asn_print(pdu_resp, pdu_str, sizeof(pdu_str)); + printf("%s\n", pdu_str); + + //Test X2SetupFailure + e2ap_pdu_t* pdu_failure = new_e2ap_pdu(); + e2ap_create_X2SetupFailure(pdu_failure); + e2ap_asn_print(pdu_failure, pdu_str, sizeof(pdu_str)); + printf("%s \n", pdu_str); +}