X2AP MOBILITY PROCEDURES (X2AP HANDOVER REQUEST/REQUEST ACK)

S1AP PATH SWITCH REQUEST/REQUEST ACK/FAILURE
RRC MEASUREMENT REPORT
MINOR CHANGES IN MAC LAYER
parent 67cc97a4
dev 1 128-ues 256_QAM_demod 2cw_fairRRscd 445-LDPC-implementation-on-GPU 459-pusch-based-ta-updates 464-ru_beamforming_in_gpu 464-ru_beamforming_in_gpu-CPUsubfunction 472-add-pusch-dmrs-modes 481-ldpc-decoder-on-gpu Fix_SA_SIB1 LTE-sidelink LTE_TRX_on_single_port NCTU_CS_ISIP NCTU_CS_ISIP_CPU NCTU_CS_ISIP_GPU NCTU_OpinConnect_LDPC NR-PHY-MAC-IF-multi-UE NRPRACH_highSpeed_saankhya NRUE_usedlschparallel NR_10MHz NR_CSI_reporting NR_DCI_01 NR_DLUL_PF NR_DLUL_PF_4UL NR_DLUL_PF_rebased NR_DL_MIMO NR_DL_sched_fixes NR_DL_scheduler NR_FAPI_beamindex_SSB_RO NR_FAPI_beamindex_SSB_RO_SEMPROJ NR_FDD_FIX NR_FR2_RA NR_FR2_RRC_SSB NR_FR2_initsync_fixes NR_MAC_CE_GlobalEdge NR_MAC_Multi_Rach_GlobalEdge NR_MAC_Multi_Rach_GlobalEdge-old NR_MAC_SSB NR_MAC_SSB_RO_GlobalEdge NR_MAC_SSB_RO_UE_IDCC NR_MAC_SSB_RO_merge NR_MAC_TCI_UCI_GlobalEdge NR_MCS_BLER NR_NGAP NR_PDCP_noS1 NR_PUCCH_MultiUE NR_RA_cleanup NR_RA_updates NR_RRCConfiguragion_FR2 NR_RRCConfiguration NR_RRCConfiguration_FR2 NR_RRCConfiguration_S1U NR_RRCConfiguration_merge_develop NR_RRCConfiguration_sync_source NR_RRCConfiguration_trx_thread NR_RRC_CP_bugfix NR_RRC_PDCP NR_RRC_PRACH_procedures NR_RRC_PRACH_procedures_todevelop NR_RRC_PUSCH NR_RRC_TA NR_RRC_X2AP_AMBR_Change_Global_edge NR_RRC_X2AP_RemoveHardcodings_GlobalEdge NR_RRC_config_simplified NR_RRC_harq NR_RRC_harq_b NR_RRC_harq_hacks NR_RRC_harq_newdcipdu NR_SA_F1AP_5GRECORDS NR_SA_F1AP_5GRECORDS_lts NR_SA_F1AP_RFSIMULATOR NR_SA_F1AP_RFSIMULATOR2 NR_SA_F1AP_RFSIMULATOR2_SRB NR_SA_F1AP_RFSIMULATOR3 NR_SA_F1AP_RFSIMULATOR3_tmp NR_SA_F1AP_RFSIMULATOR3_wf NR_SA_F1AP_RFSIMULATOR_w5GCN NR_SA_F1AP_dev NR_SA_NGAP_RRC NR_SA_NGAP_RRC_wk42 NR_SA_itti_sim_wk48 NR_SA_itti_sim_wk48_hs NR_SA_itti_sim_wk48_hs1 NR_SA_w5GCN_new_gtpu NR_SCHED NR_SCHED_HARQ NR_SCHED_PDCCH_PUCCH_HARQ NR_SCHED_PDCCH_PUCCH_HARQ_rebased NR_SCHED_fixes NR_SRB_Config NR_TRX_on_single_port NR_TRX_on_single_port2 NR_UE_CONFIG_REQ_FIXES NR_UE_MAC_scheduler NR_UE_RA_fixes NR_UE_SA NR_UE_UL_DCI_improvements NR_UE_dlsch_bugfix NR_UE_enable_parallelization NR_UE_stability_fixes NR_UL_FAPI_programming NR_UL_SCFDMA_100MHz NR_UL_scheduler NR_UL_scheduler_rebased NR_UL_scheduling NR_Wireshark NR_beam_simulation NR_beamforming_test NR_gNB_SCF_Indication NR_ipaccess_testing NR_mac_uci_functions_rework NR_msg2_phytest NR_scheduling_CSIRS NR_scheduling_request NR_scheduling_request2 NR_scheduling_request3 NR_test_S1U_RRC_PRACH_procedures NR_ue_dlsch_dmrs_cdm New-Merge-sidelink-develop OpInConnect_ISIP PBCHNRTCFIX PUSCH_TA_update RA_CI_test RFquality Saankhya_NRPRACH_HighSpeed UE_DL_DCI_hotfix UpdateRANRemoteUEReport add-dmrs-test addoptions_nr_USRPdevice bch-fixes-bitmap benetel_5g_prach_fix benetel_config_file_fix benetel_driver_uldl_pf_merge benetel_driver_update benetel_fixes benetel_phase_rotation benetel_phase_rotation_old bsr-fix bugfix-find-uci bugfix-free-ra-process bugfix-minor-remove-wrong-log bugfix-nr-bands bugfix-nr-ldpc-post-processing bugfix-nr-ldpc-size-typo bugfix-nr-pdcp-sn-size bugfix-nr-rate-matching-assertion bugfix-nr-t-reordering bugfix-x2-SgNBAdditionRequest bupt-sa-merge cce_indexing_fix cce_indexing_fix2 ci-deploy-asterix ci-deploy-docker-compose ci-new-docker-pipeline ci-rd-july-improvements ci-reduce-nb-vms ci-test ci-ul-iperf-from-trf-container ci-yacine ci_benetel_test ci_phytest ci_quectel_support ci_test_ra_fr2 ci_vm_resource_fix clean-5G-scope-round2 cleanup_softmodem_main constant_power container_fix container_v1.2.2 debug_branch_init_sync develop develop-CBRA-v3 develop-NR_SA_F1AP_5GRECORDS develop-NR_SA_F1AP_5GRECORDS-v3 develop-SA-CBRA develop-SA-CBRA-CUDU develop-SA-CBRA-Msg5 develop-SA-CBRA-lts develop-SA-CBRA-ulsch-lts develop-SA-RA develop-SnT develop-ci develop-large-scale-emulations develop-m2ap develop-multi-RRUs develop-nb-iot-merge develop-nb-iot-merge-w-conflicts develop-nb-iot-ntust develop-nr develop-nr-fr2 develop-nr-fr2-rework develop-nr_cppcheck develop-oriecpriupdates develop-sib1 develop-sib1-local develop-sib1-lts develop-sib1-update develop-sib1-update-test1 develop-sib1-update-ue develop-vco3 develop_ci develop_inria_ci_deployment develop_inria_ci_deployment_gp develop_inria_ci_deployment_gp_b4merge develop_integration_2019_w44 develop_integration_2020_w15 develop_integration_2020_w19 develop_integration_w08 develop_jenkins_replay develop_stable dfts_alternatives disable_CSI_measrep dlsch-all-dlslots dlsch_encode_mthread dlsch_parallel docker-improvements-2021-april docker-no-cache-option docupdate_tools dongzhanyi-zte-0001 dongzhanyi-zte-develop dongzhanyi-zte-develop2 dreibh/apt-auth-fix dreibh/device-load-fix dreibh/device-load-fix-develop-branch dual-connectivity dummy edrx enhance-rfsim episys-merge episys/nsa_development extend_sharedlibusage extend_sharedlibusage2 fapi_for_dmrs_and_ptrs feature-368-channel-simulator feature-4g-sched feature-flexran-cm-s1ap feature-nr-4g-nfapi-modifications feature-support-clang-format feature/make-s1-mme-port-configurable feature/make-s1-mme-port-configurable-with-astyle-fixes feature_tm3 fembms-enb-ue fft_bench_hotfix finalize-oaicn-integration firas fix-ci-tun fix-clock-source fix-dirty-ue-same-machine fix-itti-segv fix-l2-sim fix-limeSDR-compile fix-nr-pdcp-timer fix-nr-rlc-range-nack fix-quectel fix-realtime fix-softmodem-restart fix-warnings fix-x2-without-gnb fix_NR_DLUL_PF fix_NR_DLUL_PF_benchmark fix_coreset_dmrs_idx fix_do_ra_data fix_pdsch_low_prb fix_rb_corruption fix_reestablishment fix_rfsim_mimo fix_rrc_x2_ticking fixes-CE-RLC-PDU-size fixes-mac-sched-nfapi fixes-mac-sched-tun fixes-tun fixgtpu flexran-apps flexran-improvements flexran-repair-mme-mgmt flexran-report-split fr2-hw-test fujitsu_lte_contribution fujitsu_lte_contribution-128 generate_push_ptrs git-dashboard gnb-freerun-txru gnb-n300-fixes gnb-only-test gnb-realtime-hotfix gnb-realtime-quickfix gnb-threadpool hack-exit-gnb-when-no-enb-nsa harq-hotfix hotfix-minor-remove-nr-rlc-cppcheck-error hotfix-nr-rlc-tick hotfix-ocp-executable hotfix-ue-musim-compilation hotfix_usrp_lib improve_build_nr_lte_merge improve_nr_modulation improve_ue_stability initial-nfapi-PNF-fixes integ-w13-test-rt-issue integration-develop-nr-2019w45 integration_2020_wk15 integration_2020_wk40 integration_2020_wk41 integration_2020_wk42_2 integration_2020_wk45 integration_2020_wk45_2 integration_2020_wk46 integration_2020_wk46_2 integration_2020_wk47 integration_2020_wk48 integration_2020_wk48_2 integration_2020_wk49 integration_2020_wk50 integration_2020_wk50_1 integration_2020_wk51 integration_2020_wk51_2 integration_2021_wk02 integration_2021_wk02_wMR988 integration_2021_wk04 integration_2021_wk05 integration_2021_wk06 integration_2021_wk06_MR978 integration_2021_wk06_b integration_2021_wk06_c integration_2021_wk08 integration_2021_wk08_2 integration_2021_wk08_MR963 integration_2021_wk09 integration_2021_wk09_b integration_2021_wk10 integration_2021_wk10_b integration_2021_wk11 integration_2021_wk12 integration_2021_wk12_b integration_2021_wk13_a integration_2021_wk13_b integration_2021_wk13_b_fix_tdas integration_2021_wk13_b_fixed integration_2021_wk13_c integration_2021_wk14_a integration_2021_wk15_a integration_2021_wk16 integration_2021_wk17_a integration_w5GC_CBRA_test inter-RRU inter-RRU-final inter-RRU-nr inter-RRU-oairu inter-rru-UE interoperability-test isip_nr issue392-simplify-s1-nos1step2_01 issue416_nfapicleanup itti-enhancement l2-fixes ldpc-dec-layering ldpc-decoder-codegen ldpc-decoder-codegen2 ldpc-decoder-improvements ldpc-offload ldpc_short_codeword_fixes load_gnb lte-m-ue_type lte-ulsch-bugfix lte_uplink_improvement mac-fixes-wk45_2 main_python master mbms-fix-develop-nr merging-2019-w51-to-develop-nr migrate-cpp-check-container minor-fix-doc-basic-sim modify_fairRRscd_parallel mosaic5g-oai-ran mosaic5g-oai-sim msg4_phy_0303_lfq mu_allocate multi-RRUs multiple_ssb_sib1_bugfix nasmesh_kernel_5.8 new-gtpu new_pdcp new_rlc new_rlc_2020 new_rlc_in_mbms nfapi-bugfix nfapi_nr_arch_mod nfapi_nr_develop nfapi_nr_develop_new ngap-dlul ngap-support ngap-w48-merge2 ngap-wf ngap-wf-1120 ngap-wf-1120-srb ngap-wf-1120-srb-gtp ngap-wf-1120-srb-gtp-hs ngap-wf-1120-srb-gtp-hs1 ngap-wf-1120-srb-gtp-hs2 ngap-wf-1120-srb-gtp-yhz ngap-wf-1203-yunsdr ngap-wf-liuyu ngap_lfq_1120 ngap_merge noCore nr-bsr-fix nr-coreset-bug-fix nr-dl-mimo-2layer nr-dlsch-multi-thread nr-dlsch-thread nr-dmrs-fixes nr-dual-connectivity nr-interdigital-test nr-ip-uplink-noS1 nr-mac-pdu-wireshark nr-mac-remove-ue-list nr-pdcp nr-pdcp-improvements nr-pdcp-nea2-security nr-pdcp-nia2-integrity nr-pdcp-srb-integrity nr-pdsch-extraction-bugfix nr-physim-update nr-ra-fix nr-rlc-am-bugfix-w44 nr-rlc-bugfix-w44 nr-stats-print nr-timing-measurement-merge nr-ue-buffer-status nr-uldci nrPBCHTCFix nrPbchTcFix nrUE nrUE-hs nrUE-upper-layer nr_beamforming nr_bsr nr_csi_newbranch nr_dl_dmrs_type2 nr_dl_pf nr_dl_pf2 nr_dl_ul_ptrs nr_dlsch_parallel_measurements nr_fapi_for_push_tmp nr_fdd_if_fix nr_fix_easycppcheck nr_improve_build_procedures nr_increase_tp nr_pdcch_testing nr_polar_decoder_improvement nr_power_measurement_fixes nr_prach_fr2 nr_pucch nr_pucch2 nr_segmentation_fixes nr_tdd_configuration nr_ue_msg3 nr_ue_pdcp_fix nr_ue_tti_cleanup nr_ul_pf nr_ul_scfdma nr_vcd nrue-multi-thread nrue_msg2_reception nsa-ue nsa_remove_band_hardcodings oai-sim oai-ubuntu-docker oai-ubuntu-docker-for-lmssdr oairu oairu-dockerfile-support oc-docker-october-improvements ocp_simulator openxg/develop pdcp-benchmark pdsch-ch-est physim-build-deploy polar8 prb_based_dl_channel_estimation ptrs_rrc_config pusch-mthread-scaling-fix pusch-retrans-fix-ue ra-dl-ul recursive-cmake release_v1_2_0_candidate remove_nos1_hack_pdcp remove_x2_gnb_hardcoding repair-TA revert_memcpy rh-ci-add-ue-parallelization rh_ci_add_runtime_stats rh_ci_add_uldlharq_stats rh_ci_fix_autoterminate rh_ci_fr1_update rh_ci_gsheet_rt_monitoring rh_ci_nsa2jenkins rh_ci_nsa_test_n310 rh_ci_oc rh_ci_phy_test_improve rh_ci_py rh_ci_ra_fr2 rh_ci_rfsim_ra rh_ci_ue_parallel rh_doc_update_3 rh_fr1_newjenkins rh_fr1_update rh_gnb_compile_fix rh_wk50_debug rhel77-build rlc-v2-bugfix-status-reporting rlc-v2-tick rlc_v2_coverity_fixes rohan_ulsim2RxFix rrc-enb-phy-testmode ru-parallel-beamforming runel runel-reverse-test s1-subnormal_rewrite s1_subnormal s1_subnormal-robert s1ap-bugfix-rab_setup sa-demo sa-demo-hs sa-merge-rrc-srb sa-msg4 sa-msg4-rrc sa-msg4-rrc-yihz sa-msg4-rrc-yihz-hs sa_rrc_yihz sanitize-address sanitize-v1 sanitize-v1-tmp sarma_pvnp_oai signal-delay sim-channels small-bugfixes-w40 small-config-change small_nr_bugfixes smallcleanup softmodem_cleanup split73 t-gnb-tracer test-panos test_nsa_gtpu_fix test_rt-fix_phy-test testing_2symb_pdcch testing_with_external_txdata tools_5Gadapt tp-ota-test trx_thread_param trx_write_thread ue-csi ue-dci-false-detection ue-fixes ue-fixes-ota ue-pdsch-pusch-parallel ue-race-fix ue-updates-runel-test ue_beam_selection ue_dlsch_decoding_ldpc_offload ue_nfapi_mch uhd_priority_set_cleanup ul-freq-iq-samps-to-file ul_dl_dci_same_slot ul_harq ulsch_decode_mthread ulsim_changes usrp_fix_adc_shift_and_pps_sync usrp_gpio_test usrp_x400 wf-sa-rrc wireshark-T-hack-ueid wireshark-log-scheduling-requests wk11-with-phytest x2-endc-processing x2_neighbor_6cells x2_tdd xiangwab xiangwan xw2 yihongzheng_srb zzs 2021.wk14_a 2021.wk13_d 2021.wk13_c 2021.w16 2021.w15 2021.w14 2021.w13_a 2021.w12 2021.w11 2021.w10 2021.w09 2021.w08 2021.w06 2021.w05 2021.w04 2021.w02 2020.w51_2 2020.w51 2020.w50 2020.w49 2020.w48_2 2020.w48 2020.w47 2020.w46_2 2020.w46 2020.w45_2 2020.w45 2020.w44 2020.w42_2 2020.w42 2020.w41 2020.w39 2020.w38 2020.w37 2020.w36 2020.w34 2020.w33 2020.w31 2020.w30 2020.w29 2020.w28 2020.w26 2020.w25 2020.w24 2020.w23 2020.w22 2020.w19 2020.w17 2020.w16 2020.w15 2020.w11 2020.w09 2020.w06 2020.w05 2020.w04 2020.w03 2019.w51 2019.w44 2019.w41 2019.w36 2019.w30 2019.w28 2019.w27 2019.w25 2019.w23 2019.w21 2019.w17 2019.w15 2019.w13 2019.w11 2019.w10 2019.w09 2019.w08 2019.w07 v1.2.2 v1.2.1 v1.2.0 v1.1.1 v1.1.0 nr-ip-over-lte-v.1.5 nr-ip-over-lte-v.1.4 nr-ip-over-lte-v.1.3 nr-ip-over-lte-v.1.2 nr-ip-over-lte-v.1.1 nr-ip-over-lte-v.1.0 develop-nr-2020w03 develop-nr-2020w02 develop-nr-2019w51 develop-nr-2019w50 develop-nr-2019w48 develop-nr-2019w47 develop-nr-2019w45 develop-nr-2019w43 develop-nr-2019w42 develop-nr-2019w40 benetel_phase_rotation benetel_gnb_rel_1.0 benetel_enb_rel_1.0
No related merge requests found
...@@ -62,9 +62,9 @@ typedef enum { ...@@ -62,9 +62,9 @@ typedef enum {
MSC_S11_MME, MSC_S11_MME,
MSC_S6A_MME, MSC_S6A_MME,
MSC_HSS, MSC_HSS,
MAX_MSC_PROTOS,
MSC_X2AP_SRC_ENB, MSC_X2AP_SRC_ENB,
MSC_X2AP_TARGET_ENB, MSC_X2AP_TARGET_ENB,
MAX_MSC_PROTOS,
} msc_proto_t; } msc_proto_t;
......
...@@ -39,6 +39,8 @@ MESSAGE_DEF(S1AP_PAGING_LOG , MESSAGE_PRIORITY_MED, IttiMsgText ...@@ -39,6 +39,8 @@ MESSAGE_DEF(S1AP_PAGING_LOG , MESSAGE_PRIORITY_MED, IttiMsgText
MESSAGE_DEF(S1AP_E_RAB_RELEASE_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_release_request_log) MESSAGE_DEF(S1AP_E_RAB_RELEASE_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_release_request_log)
MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_release_response_log) MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_release_response_log)
MESSAGE_DEF(S1AP_ERROR_INDICATION_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_error_indication_log) MESSAGE_DEF(S1AP_ERROR_INDICATION_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_error_indication_log)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_path_switch_req_log)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_ACK_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_path_switch_req_ack_log)
/* eNB application layer -> S1AP messages */ /* eNB application layer -> S1AP messages */
MESSAGE_DEF(S1AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, s1ap_register_enb_req_t , s1ap_register_enb_req) MESSAGE_DEF(S1AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, s1ap_register_enb_req_t , s1ap_register_enb_req)
...@@ -62,6 +64,8 @@ MESSAGE_DEF(S1AP_E_RAB_SETUP_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_se ...@@ -62,6 +64,8 @@ MESSAGE_DEF(S1AP_E_RAB_SETUP_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_se
MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_req_fail_t , s1ap_e_rab_setup_request_fail) MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_req_fail_t , s1ap_e_rab_setup_request_fail)
MESSAGE_DEF(S1AP_E_RAB_MODIFY_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_modify_resp_t , s1ap_e_rab_modify_resp) MESSAGE_DEF(S1AP_E_RAB_MODIFY_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_modify_resp_t , s1ap_e_rab_modify_resp)
MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, s1ap_e_rab_release_resp_t , s1ap_e_rab_release_resp) MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, s1ap_e_rab_release_resp_t , s1ap_e_rab_release_resp)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, s1ap_path_switch_req_t , s1ap_path_switch_req)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, s1ap_path_switch_req_ack_t , s1ap_path_switch_req_ack)
/* S1AP -> RRC messages */ /* S1AP -> RRC messages */
MESSAGE_DEF(S1AP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t , s1ap_downlink_nas ) MESSAGE_DEF(S1AP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t , s1ap_downlink_nas )
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#define S1AP_E_RAB_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_resp #define S1AP_E_RAB_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_resp
#define S1AP_E_RAB_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_req_fail #define S1AP_E_RAB_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_req_fail
#define S1AP_E_RAB_MODIFY_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_modify_resp #define S1AP_E_RAB_MODIFY_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_modify_resp
#define S1AP_PATH_SWITCH_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_path_switch_req
#define S1AP_PATH_SWITCH_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.s1ap_path_switch_req_ack
#define S1AP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_downlink_nas #define S1AP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_downlink_nas
#define S1AP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req #define S1AP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req
...@@ -269,6 +271,17 @@ typedef struct e_rab_setup_s { ...@@ -269,6 +271,17 @@ typedef struct e_rab_setup_s {
uint32_t gtp_teid; uint32_t gtp_teid;
} e_rab_setup_t; } e_rab_setup_t;
typedef struct e_rab_tobeswitched_s {
/* Unique e_rab_id for the UE. */
uint8_t e_rab_id;
/* The transport layer address for the IP packets */
transport_layer_addr_t sgw_addr;
/* S-GW Tunnel endpoint identifier */
uint32_t gtp_teid;
} e_rab_tobeswitched_t;
typedef struct e_rab_modify_s { typedef struct e_rab_modify_s {
/* Unique e_rab_id for the UE. */ /* Unique e_rab_id for the UE. */
uint8_t e_rab_id; uint8_t e_rab_id;
...@@ -472,6 +485,8 @@ typedef struct s1ap_initial_context_setup_req_s { ...@@ -472,6 +485,8 @@ typedef struct s1ap_initial_context_setup_req_s {
/* eNB ue s1ap id as initialized by S1AP layer */ /* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
/* UE aggregate maximum bitrate */ /* UE aggregate maximum bitrate */
ambr_t ue_ambr; ambr_t ue_ambr;
...@@ -525,7 +540,7 @@ typedef struct s1ap_e_rab_setup_req_s { ...@@ -525,7 +540,7 @@ typedef struct s1ap_e_rab_setup_req_s {
uint16_t ue_initial_id; uint16_t ue_initial_id;
/* MME UE id */ /* MME UE id */
uint16_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
/* eNB ue s1ap id as initialized by S1AP layer */ /* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
...@@ -552,6 +567,58 @@ typedef struct s1ap_e_rab_setup_resp_s { ...@@ -552,6 +567,58 @@ typedef struct s1ap_e_rab_setup_resp_s {
e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB]; e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB];
} s1ap_e_rab_setup_resp_t; } s1ap_e_rab_setup_resp_t;
typedef struct s1ap_path_switch_req_s {
unsigned eNB_ue_s1ap_id:24;
/* Number of e_rab setup-ed in the list */
uint8_t nb_of_e_rabs;
/* list of e_rab setup-ed by RRC layers */
e_rab_setup_t e_rabs_tobeswitched[S1AP_MAX_E_RAB];
/* MME UE id */
uint32_t mme_ue_s1ap_id;
s1ap_gummei_t ue_gummei;
uint16_t ue_initial_id;
/* Security algorithms */
security_capabilities_t security_capabilities;
} s1ap_path_switch_req_t;
typedef struct s1ap_path_switch_req_ack_s {
/* UE id for initial connection to S1AP */
uint16_t ue_initial_id;
unsigned eNB_ue_s1ap_id:24;
/* MME UE id */
uint32_t mme_ue_s1ap_id;
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
/* Number of e_rab setup-ed in the list */
uint8_t nb_e_rabs_tobeswitched;
/* list of e_rab to be switched by RRC layers */
e_rab_tobeswitched_t e_rabs_tobeswitched[S1AP_MAX_E_RAB];
/* Number of e_rabs to be released by RRC */
uint8_t nb_e_rabs_tobereleased;
/* list of e_rabs to be released */
e_rab_failed_t e_rabs_tobereleased[S1AP_MAX_E_RAB];
/* Security key */
int next_hop_chain_count;
uint8_t next_security_key[SECURITY_KEY_LENGTH];
} s1ap_path_switch_req_ack_t;
// S1AP --> RRC messages // S1AP --> RRC messages
typedef struct s1ap_ue_release_command_s { typedef struct s1ap_ue_release_command_s {
...@@ -574,7 +641,7 @@ typedef struct s1ap_e_rab_modify_req_s { ...@@ -574,7 +641,7 @@ typedef struct s1ap_e_rab_modify_req_s {
uint16_t ue_initial_id; uint16_t ue_initial_id;
/* MME UE id */ /* MME UE id */
uint16_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
/* eNB ue s1ap id as initialized by S1AP layer */ /* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
...@@ -607,7 +674,7 @@ typedef struct e_rab_release_s { ...@@ -607,7 +674,7 @@ typedef struct e_rab_release_s {
typedef struct s1ap_e_rab_release_command_s { typedef struct s1ap_e_rab_release_command_s {
/* MME UE id */ /* MME UE id */
uint16_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
/* eNB ue s1ap id as initialized by S1AP layer */ /* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
...@@ -625,7 +692,7 @@ typedef struct s1ap_e_rab_release_command_s { ...@@ -625,7 +692,7 @@ typedef struct s1ap_e_rab_release_command_s {
typedef struct s1ap_e_rab_release_resp_s { typedef struct s1ap_e_rab_release_resp_s {
/* MME UE id */ /* MME UE id */
uint16_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
/* eNB ue s1ap id as initialized by S1AP layer */ /* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
......
...@@ -132,7 +132,7 @@ typedef struct x2ap_handover_req_s { ...@@ -132,7 +132,7 @@ typedef struct x2ap_handover_req_s {
int source_rnti; /* TODO: to be fixed/remove */ int source_rnti; /* TODO: to be fixed/remove */
int source_x2id; /* TODO: to be fixed/remove */ int source_x2id; /* TODO: to be fixed/remove */
unsigned old_eNB_ue_s1ap_id:24; int old_eNB_ue_x2ap_id;
PhysCellId_t target_physCellId; PhysCellId_t target_physCellId;
...@@ -158,10 +158,14 @@ typedef struct x2ap_handover_req_s { ...@@ -158,10 +158,14 @@ typedef struct x2ap_handover_req_s {
/* list of e_rab setup-ed by RRC layers */ /* list of e_rab setup-ed by RRC layers */
e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB]; e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
/* ue_context_pP->ue_context.e_rab[i].param.sgw_addr; */ /* list of e_rab to be setup by RRC layers */
e_rab_t e_rab_param[S1AP_MAX_E_RAB];
x2ap_lastvisitedcell_info_t lastvisitedcell_info; x2ap_lastvisitedcell_info_t lastvisitedcell_info;
uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
int rrc_buffer_size;
/* TODO: this parameter has to be removed */ /* TODO: this parameter has to be removed */
int target_mod_id; int target_mod_id;
} x2ap_handover_req_t; } x2ap_handover_req_t;
...@@ -171,6 +175,15 @@ typedef struct x2ap_handover_req_ack_s { ...@@ -171,6 +175,15 @@ typedef struct x2ap_handover_req_ack_s {
int source_x2id; /* TODO: to be fixed/remove */ int source_x2id; /* TODO: to be fixed/remove */
/* TODO: this parameter has to be removed */ /* TODO: this parameter has to be removed */
int target_mod_id; int target_mod_id;
uint8_t nb_e_rabs_tobesetup;
/* list of e_rab setup-ed by RRC layers */
e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
/* list of e_rab to be setup by RRC layers */
e_rab_t e_rab_param[S1AP_MAX_E_RAB];
uint8_t rrc_buffer[1024 /* arbitrary, big enough */]; uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
int rrc_buffer_size; int rrc_buffer_size;
......
...@@ -2294,6 +2294,7 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i) { ...@@ -2294,6 +2294,7 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i) {
if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) { if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4 = 1; S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4 = 1;
S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 0;
} else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) { } else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 1; S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 1;
} else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) { } else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
......
...@@ -896,6 +896,20 @@ rrc_mac_config_req_eNB(module_id_t Mod_idP, ...@@ -896,6 +896,20 @@ rrc_mac_config_req_eNB(module_id_t Mod_idP,
} }
} // mib != NULL } // mib != NULL
if (mobilityControlInfo !=NULL){
if ((UE_id = add_new_ue(Mod_idP, CC_idP,
rntiP, -1
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
,
-1
#endif
)) == -1)
{
LOG_E(MAC, "%s:%d: fatal\n", __FILE__, __LINE__);
abort();
}
}
// SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup
if (logicalChannelConfig != NULL) { // check for eMTC specific things if (logicalChannelConfig != NULL) { // check for eMTC specific things
UE_id = find_UE_id(Mod_idP, rntiP); UE_id = find_UE_id(Mod_idP, rntiP);
......
...@@ -323,51 +323,75 @@ rx_sdu(const module_id_t enb_mod_idP, ...@@ -323,51 +323,75 @@ rx_sdu(const module_id_t enb_mod_idP,
//cancel_ra_proc(enb_mod_idP, CC_idP, frameP, //cancel_ra_proc(enb_mod_idP, CC_idP, frameP,
// current_rnti); // current_rnti);
if (old_UE_id != -1) { if (old_UE_id != -1) {
/* TODO: if the UE did random access (followed by a MAC uplink with
* CRNTI) because none of its scheduling request was granted, then if (mac_eNB_get_rrc_status(enb_mod_idP,old_rnti) == RRC_HO_EXECUTION) {
* according to 36.321 5.4.4 the UE's MAC will notify RRC to release LOG_I(MAC,
* PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) Handover case\n",
* default configuration for CQI reporting and scheduling requests, enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);
* which basically means that the CQI requests won't work anymore and
* that the UE won't do any scheduling request anymore as long as the UE_id = old_UE_id;
* eNB doesn't reconfigure the UE. current_rnti = old_rnti;
* We have to take care of this. As the code is, nothing is done and //clear timer
* the UE state in the eNB is wrong. UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
*/ UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
for (ii = 0; ii < NB_RA_PROC_MAX; ii++) { UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
ra = &mac->common_channels[CC_idP].ra[ii]; if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
if ((ra->rnti == current_rnti) && (ra->state != IDLE)) { UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
mac_rrc_data_ind(enb_mod_idP, mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
CC_idP, subframeP, old_rnti);
frameP, subframeP, }
old_rnti, UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
DCCH, UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
(uint8_t *) payload_ptr, UE_list->UE_template[UE_PCCID(enb_mod_idP, UE_id)][UE_id].configured = 1;
rx_lengths[i], cancel_ra_proc(enb_mod_idP, CC_idP, frameP,current_rnti);
0); }
// prepare transmission of Msg4(RRCConnectionReconfiguration) else {
ra->state = MSGCRNTI; /* TODO: if the UE did random access (followed by a MAC uplink with
LOG_I(MAC, * CRNTI) because none of its scheduling request was granted, then
"[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) RRCConnectionReconfiguration(Msg4)\n", * according to 36.321 5.4.4 the UE's MAC will notify RRC to release
enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id); * PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply
* default configuration for CQI reporting and scheduling requests,
UE_id = old_UE_id; * which basically means that the CQI requests won't work anymore and
current_rnti = old_rnti; * that the UE won't do any scheduling request anymore as long as the
ra->rnti = old_rnti; * eNB doesn't reconfigure the UE.
ra->crnti_rrc_mui = rrc_eNB_mui-1; * We have to take care of this. As the code is, nothing is done and
ra->crnti_harq_pid = -1; * the UE state in the eNB is wrong.
//clear timer */
UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; for (ii = 0; ii < NB_RA_PROC_MAX; ii++) {
UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0; ra = &mac->common_channels[CC_idP].ra[ii];
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; if ((ra->rnti == current_rnti) && (ra->state != IDLE)) {
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) { mac_rrc_data_ind(enb_mod_idP,
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0; CC_idP,
mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP, frameP, subframeP,
subframeP, old_rnti); old_rnti,
DCCH,
(uint8_t *) payload_ptr,
rx_lengths[i],
0);
// prepare transmission of Msg4(RRCConnectionReconfiguration)
ra->state = MSGCRNTI;
LOG_I(MAC,
"[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) RRCConnectionReconfiguration(Msg4)\n",
enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);
UE_id = old_UE_id;
current_rnti = old_rnti;
ra->rnti = old_rnti;
ra->crnti_rrc_mui = rrc_eNB_mui-1;
ra->crnti_harq_pid = -1;
//clear timer
UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
subframeP, old_rnti);
}
UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
break;
} }
UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
break;
} }
} }
} else { } else {
......
...@@ -52,6 +52,8 @@ ...@@ -52,6 +52,8 @@
#include "RRCConnectionSetup.h" #include "RRCConnectionSetup.h"
#include "SRB-ToAddModList.h" #include "SRB-ToAddModList.h"
#include "DRB-ToAddModList.h" #include "DRB-ToAddModList.h"
#include "HandoverPreparationInformation.h"
#include "HandoverCommand.h"
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0)) #if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
#include "MCCH-Message.h" #include "MCCH-Message.h"
//#define MRB1 1 //#define MRB1 1
...@@ -2386,6 +2388,7 @@ do_RRCConnectionReconfiguration( ...@@ -2386,6 +2388,7 @@ do_RRCConnectionReconfiguration(
MAC_MainConfig_t *mac_MainConfig, MAC_MainConfig_t *mac_MainConfig,
MeasGapConfig_t *measGapConfig, MeasGapConfig_t *measGapConfig,
MobilityControlInfo_t *mobilityInfo, MobilityControlInfo_t *mobilityInfo,
SecurityConfigHO_t *securityConfigHO,
struct MeasConfig__speedStatePars *speedStatePars, struct MeasConfig__speedStatePars *speedStatePars,
RSRP_Range_t *rsrp, RSRP_Range_t *rsrp,
C_RNTI_t *cba_rnti, C_RNTI_t *cba_rnti,
...@@ -2485,8 +2488,16 @@ do_RRCConnectionReconfiguration( ...@@ -2485,8 +2488,16 @@ do_RRCConnectionReconfiguration(
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.mobilityControlInfo = NULL; rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.mobilityControlInfo = NULL;
} }
if (securityConfigHO != NULL) {
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO = CALLOC(1,
sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO));
memcpy((void*)rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO, (void*)securityConfigHO,
sizeof(SecurityConfigHO_t));
} else {
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO = NULL;
}
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.dedicatedInfoNASList = dedicatedInfoNASList; rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.dedicatedInfoNASList = dedicatedInfoNASList;
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO = NULL;
//TTN for D2D //TTN for D2D
//allocate dedicated resource pools for SL communication (sl_CommConfig_r12) //allocate dedicated resource pools for SL communication (sl_CommConfig_r12)
...@@ -2545,7 +2556,7 @@ do_RRCConnectionReconfiguration( ...@@ -2545,7 +2556,7 @@ do_RRCConnectionReconfiguration(
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT) # if !defined(DISABLE_XER_SPRINT)
{ {
char message_string[30000]; char message_string[40000];
size_t message_string_size; size_t message_string_size;
if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_DCCH_Message, (void *) &dl_dcch_msg)) > 0) { if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_DCCH_Message, (void *) &dl_dcch_msg)) > 0) {
...@@ -3368,6 +3379,88 @@ uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t ...@@ -3368,6 +3379,88 @@ uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t
return encoded; return encoded;
} }
int do_HandoverPreparation(char *ho_buf, int ho_size, UE_EUTRA_Capability_t *ue_eutra_cap, int rrc_size)
{
asn_enc_rval_t enc_rval;
HandoverPreparationInformation_t ho;
HandoverPreparationInformation_r8_IEs_t *ho_info;
UE_CapabilityRAT_Container_t *ue_cap_rat_container;
char rrc_buf[rrc_size];
memset(rrc_buf, 0, rrc_size);
enc_rval = uper_encode_to_buffer(&asn_DEF_UE_EUTRA_Capability,
NULL,
ue_eutra_cap,
rrc_buf,
rrc_size);
/* TODO: free the OCTET_STRING */
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
memset(&ho, 0, sizeof(ho));
ho.criticalExtensions.present = HandoverPreparationInformation__criticalExtensions_PR_c1;
ho.criticalExtensions.choice.c1.present = HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation_r8;
ho_info = &ho.criticalExtensions.choice.c1.choice.handoverPreparationInformation_r8;
{
ue_cap_rat_container = (UE_CapabilityRAT_Container_t *)calloc(1,sizeof(UE_CapabilityRAT_Container_t));
ue_cap_rat_container->rat_Type = RAT_Type_eutra;
AssertFatal (OCTET_STRING_fromBuf(
&ue_cap_rat_container->ueCapabilityRAT_Container,
rrc_buf, rrc_size) != -1, "fatal: OCTET_STRING_fromBuf failed\n");
ASN_SEQUENCE_ADD(&ho_info->ue_RadioAccessCapabilityInfo.list, ue_cap_rat_container);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_HandoverPreparationInformation,
NULL,
&ho,
ho_buf,
ho_size);
/* TODO: free the OCTET_STRING */
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
return((enc_rval.encoded+7)/8);
}
int do_HandoverCommand(char *ho_buf, int ho_size, char *rrc_buf, int rrc_size)
{
asn_enc_rval_t enc_rval;
HandoverCommand_t ho;
memset(&ho, 0, sizeof(ho));
ho.criticalExtensions.present = HandoverCommand__criticalExtensions_PR_c1;
ho.criticalExtensions.choice.c1.present = HandoverCommand__criticalExtensions__c1_PR_handoverCommand_r8;
AssertFatal (OCTET_STRING_fromBuf(
&ho.criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage,
rrc_buf, rrc_size) != -1, "fatal: OCTET_STRING_fromBuf failed\n");
enc_rval = uper_encode_to_buffer(&asn_DEF_HandoverCommand,
NULL,
&ho,
ho_buf,
ho_size);
/* TODO: free the OCTET_STRING */
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
return((enc_rval.encoded+7)/8);
}
OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname) OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname)
{ {
static OAI_UECapability_t UECapability; /* TODO declared static to allow returning this has an address should be allocated in a cleaner way. */ static OAI_UECapability_t UECapability; /* TODO declared static to allow returning this has an address should be allocated in a cleaner way. */
......
...@@ -192,6 +192,7 @@ do_RRCConnectionReconfiguration( ...@@ -192,6 +192,7 @@ do_RRCConnectionReconfiguration(
MAC_MainConfig_t *mac_MainConfig, MAC_MainConfig_t *mac_MainConfig,
MeasGapConfig_t *measGapConfig, MeasGapConfig_t *measGapConfig,
MobilityControlInfo_t *mobilityInfo, MobilityControlInfo_t *mobilityInfo,
SecurityConfigHO_t *securityConfigHO,
struct MeasConfig__speedStatePars *speedStatePars, struct MeasConfig__speedStatePars *speedStatePars,
RSRP_Range_t *rsrp, RSRP_Range_t *rsrp,
C_RNTI_t *cba_rnti, C_RNTI_t *cba_rnti,
...@@ -282,6 +283,10 @@ uint8_t do_Paging(uint8_t Mod_id, uint8_t *buffer, ue_paging_identity_t ue_pagin ...@@ -282,6 +283,10 @@ uint8_t do_Paging(uint8_t Mod_id, uint8_t *buffer, ue_paging_identity_t ue_pagin
uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t *pdu_buffer); uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t *pdu_buffer);
int do_HandoverPreparation(char *ho_buf, int ho_size, UE_EUTRA_Capability_t *ue_eutra_cap, int rrc_size);
int do_HandoverCommand(char *ho_buf, int ho_size, char *rrc_buf, int rrc_size);
OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer); OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer);
uint8_t uint8_t
......
...@@ -344,10 +344,13 @@ typedef enum UE_STATE_e { ...@@ -344,10 +344,13 @@ typedef enum UE_STATE_e {
typedef enum HO_STATE_e { typedef enum HO_STATE_e {
HO_IDLE=0, HO_IDLE=0,
HO_MEASURMENT, HO_MEASUREMENT,
HO_PREPARE, HO_PREPARE,
HO_CMD, // initiated by the src eNB HO_CMD, // initiated by the src eNB
HO_COMPLETE // initiated by the target eNB HO_COMPLETE, // initiated by the target eNB
HO_REQUEST,
HO_ACK,
HO_CONFIGURED
} HO_STATE_t; } HO_STATE_t;
typedef enum SL_TRIGGER_e { typedef enum SL_TRIGGER_e {
...@@ -433,6 +436,7 @@ typedef enum e_rab_satus_e { ...@@ -433,6 +436,7 @@ typedef enum e_rab_satus_e {
E_RAB_STATUS_NEW, E_RAB_STATUS_NEW,
E_RAB_STATUS_DONE, // from the eNB perspective E_RAB_STATUS_DONE, // from the eNB perspective
E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE
E_RAB_STATUS_REESTABLISHED, // after HO
E_RAB_STATUS_FAILED, E_RAB_STATUS_FAILED,
E_RAB_STATUS_TORELEASE // to release DRB between eNB and UE E_RAB_STATUS_TORELEASE // to release DRB between eNB and UE
} e_rab_status_t; } e_rab_status_t;
...@@ -446,14 +450,13 @@ typedef struct e_rab_param_s { ...@@ -446,14 +450,13 @@ typedef struct e_rab_param_s {
} __attribute__ ((__packed__)) e_rab_param_t; } __attribute__ ((__packed__)) e_rab_param_t;
#endif #endif
/* Intermediate structure for Handover management. Associated per-UE in eNB_RRC_INST */ /* Intermediate structure for Handover management. Associated per-UE in eNB_RRC_INST */
typedef struct HANDOVER_INFO_s { typedef struct HANDOVER_INFO_s {
uint8_t ho_prepare; uint8_t ho_prepare;
uint8_t ho_complete; uint8_t ho_complete;
uint8_t modid_s; //module_idP of serving cell HO_STATE_t state; //current state of handover
uint8_t modid_t; //module_idP of target cell uint32_t modid_s; //module_idP of serving cell
uint32_t modid_t; //module_idP of target cell
uint8_t ueid_s; //UE index in serving cell uint8_t ueid_s; //UE index in serving cell
uint8_t ueid_t; //UE index in target cell uint8_t ueid_t; //UE index in target cell
AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */ AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */
...@@ -511,6 +514,14 @@ typedef struct HANDOVER_INFO_UE_s { ...@@ -511,6 +514,14 @@ typedef struct HANDOVER_INFO_UE_s {
uint8_t measFlag; uint8_t measFlag;
} HANDOVER_INFO_UE; } HANDOVER_INFO_UE;
typedef struct rrc_gummei_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t mme_code;
uint16_t mme_group_id;
} rrc_gummei_t;
typedef struct eNB_RRC_UE_s { typedef struct eNB_RRC_UE_s {
uint8_t primaryCC_id; uint8_t primaryCC_id;
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0)) #if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
...@@ -537,8 +548,10 @@ typedef struct eNB_RRC_UE_s { ...@@ -537,8 +548,10 @@ typedef struct eNB_RRC_UE_s {
MeasConfig_t* measConfig; MeasConfig_t* measConfig;
HANDOVER_INFO* handover_info; HANDOVER_INFO* handover_info;
MeasResults_t* measResults; MeasResults_t* measResults;
MobilityControlInfo_t* mobilityInfo;
UE_EUTRA_Capability_t* UE_Capability; UE_EUTRA_Capability_t* UE_Capability;
int UE_Capability_size;
ImsiMobileIdentity_t imsi; ImsiMobileIdentity_t imsi;
#if defined(ENABLE_SECURITY) #if defined(ENABLE_SECURITY)
...@@ -570,8 +583,15 @@ typedef struct eNB_RRC_UE_s { ...@@ -570,8 +583,15 @@ typedef struct eNB_RRC_UE_s {
/* Information from S1AP initial_context_setup_req */ /* Information from S1AP initial_context_setup_req */
uint32_t eNB_ue_s1ap_id :24; uint32_t eNB_ue_s1ap_id :24;
uint32_t mme_ue_s1ap_id;
rrc_gummei_t ue_gummei;
security_capabilities_t security_capabilities; security_capabilities_t security_capabilities;
int next_hop_chain_count;
uint8_t next_security_key[SECURITY_KEY_LENGTH];
/* Total number of e_rab already setup in the list */ /* Total number of e_rab already setup in the list */
uint8_t setup_e_rabs; uint8_t setup_e_rabs;
/* Number of e_rab to be setup in the list */ /* Number of e_rab to be setup in the list */
...@@ -582,8 +602,12 @@ typedef struct eNB_RRC_UE_s { ...@@ -582,8 +602,12 @@ typedef struct eNB_RRC_UE_s {
e_rab_param_t modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; e_rab_param_t modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
/* list of e_rab to be setup by RRC layers */ /* list of e_rab to be setup by RRC layers */
e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
//release e_rabs //release e_rabs
uint8_t nb_release_of_e_rabs; uint8_t nb_release_of_e_rabs;
/* list of e_rab to be released by RRC layers */
uint8_t e_rabs_tobereleased[NB_RB_MAX];
e_rab_failed_t e_rabs_release_failed[S1AP_MAX_E_RAB]; e_rab_failed_t e_rabs_release_failed[S1AP_MAX_E_RAB];
// LG: For GTPV1 TUNNELS // LG: For GTPV1 TUNNELS
uint32_t enb_gtp_teid[S1AP_MAX_E_RAB]; uint32_t enb_gtp_teid[S1AP_MAX_E_RAB];
...@@ -639,6 +663,8 @@ typedef struct { ...@@ -639,6 +663,8 @@ typedef struct {
int p_eNB; int p_eNB;
uint32_t dl_CarrierFreq; uint32_t dl_CarrierFreq;
uint32_t ul_CarrierFreq; uint32_t ul_CarrierFreq;
uint32_t eutra_band;
uint32_t N_RB_DL;
uint32_t pbch_repetition; uint32_t pbch_repetition;
BCCH_BCH_Message_t mib; BCCH_BCH_Message_t mib;
BCCH_DL_SCH_Message_t siblock1; BCCH_DL_SCH_Message_t siblock1;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
# include "rrc_eNB_S1AP.h" # include "rrc_eNB_S1AP.h"
# include "enb_config.h" # include "enb_config.h"
# include "common/ran_context.h" # include "common/ran_context.h"
# include "gtpv1u.h"
# if defined(ENABLE_ITTI) # if defined(ENABLE_ITTI)
# include "asn1_conversions.h" # include "asn1_conversions.h"
...@@ -63,6 +64,11 @@ ...@@ -63,6 +64,11 @@
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
extern int
gtpv1u_delete_s1u_tunnel(
const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP);
/* Value to indicate an invalid UE initial id */ /* Value to indicate an invalid UE initial id */
static const uint16_t UE_INITIAL_ID_INVALID = 0; static const uint16_t UE_INITIAL_ID_INVALID = 0;
...@@ -793,6 +799,12 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( ...@@ -793,6 +799,12 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec); S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec);
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi); S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
ue_context_pP->ue_context.ue_gummei.mcc = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc;
ue_context_pP->ue_context.ue_gummei.mnc = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc;
ue_context_pP->ue_context.ue_gummei.mnc_len = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len;
ue_context_pP->ue_context.ue_gummei.mme_code = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code;
ue_context_pP->ue_context.ue_gummei.mme_group_id = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id;
MSC_LOG_TX_MESSAGE( MSC_LOG_TX_MESSAGE(
MSC_S1AP_ENB, MSC_S1AP_ENB,
MSC_S1AP_MME, MSC_S1AP_MME,
...@@ -976,6 +988,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char ...@@ -976,6 +988,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id; ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
ue_context_p->ue_context.mme_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).mme_ue_s1ap_id;
/* Save e RAB information for later */ /* Save e RAB information for later */
{ {
...@@ -1976,5 +1989,231 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance ...@@ -1976,5 +1989,231 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance
return (0); return (0);
} }
/*NN: careful about the typcast of xid (long -> uint8_t*/
int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP){
MessageDef *msg_p = NULL;
int e_rab = 0;
int e_rabs_done = 0;
rrc_ue_s1ap_ids_t* rrc_ue_s1ap_ids_p = NULL;
hashtable_rc_t h_rc;
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
uint8_t inde_list[ue_context_pP->ue_context.nb_of_e_rabs];
memset(inde_list, 0, ue_context_pP->ue_context.nb_of_e_rabs*sizeof(uint8_t));
msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ);
ue_context_pP->ue_context.ue_initial_id = get_next_ue_initial_id (ctxt_pP->module_id);
S1AP_PATH_SWITCH_REQ (msg_p).ue_initial_id = ue_context_pP->ue_context.ue_initial_id;
rrc_ue_s1ap_ids_p = malloc(sizeof(*rrc_ue_s1ap_ids_p));
rrc_ue_s1ap_ids_p->ue_initial_id = ue_context_pP->ue_context.ue_initial_id;
rrc_ue_s1ap_ids_p->eNB_ue_s1ap_id = UE_INITIAL_ID_INVALID;
rrc_ue_s1ap_ids_p->ue_rnti = ctxt_pP->rnti;
h_rc = hashtable_insert(RC.rrc[ctxt_pP->module_id]->initial_id2_s1ap_ids,
(hash_key_t)ue_context_pP->ue_context.ue_initial_id,
rrc_ue_s1ap_ids_p);
if (h_rc != HASH_TABLE_OK) {
LOG_E(S1AP, "[eNB %d] Error while hashtable_insert in initial_id2_s1ap_ids ue_initial_id %u\n",
ctxt_pP->module_id, ue_context_pP->ue_context.ue_initial_id);
}
S1AP_PATH_SWITCH_REQ (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
S1AP_PATH_SWITCH_REQ (msg_p).mme_ue_s1ap_id = ue_context_pP->ue_context.mme_ue_s1ap_id;
S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc;
S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mnc = ue_context_pP->ue_context.ue_gummei.mnc;
S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mnc_len = ue_context_pP->ue_context.ue_gummei.mnc_len;
S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mme_code = ue_context_pP->ue_context.ue_gummei.mme_code;
S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mme_group_id = ue_context_pP->ue_context.ue_gummei.mme_group_id;
S1AP_PATH_SWITCH_REQ (msg_p).security_capabilities.encryption_algorithms=ue_context_pP->ue_context.security_capabilities.encryption_algorithms;
S1AP_PATH_SWITCH_REQ (msg_p).security_capabilities.integrity_algorithms=ue_context_pP->ue_context.security_capabilities.integrity_algorithms;
LOG_I (RRC,"Path switch request: nb nb_of_e_rabs %u status %u\n",
ue_context_pP->ue_context.nb_of_e_rabs,
ue_context_pP->ue_context.e_rab[e_rab].status);
memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
// the context for UE to be handovered is obtained through ho_req message
for (e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_e_rabs ; e_rab++) {
if (ue_context_pP->ue_context.e_rab[e_rab].status == E_RAB_STATUS_ESTABLISHED) {
create_tunnel_req.eps_bearer_id[e_rabs_done] = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id;
create_tunnel_req.sgw_S1u_teid[e_rabs_done] = ue_context_pP->ue_context.e_rab[e_rab].param.gtp_teid;
memcpy(&create_tunnel_req.sgw_addr[e_rabs_done],
&ue_context_pP->ue_context.e_rab[e_rab].param.sgw_addr,
sizeof(transport_layer_addr_t));
inde_list[e_rabs_done] = e_rab;
e_rabs_done++;
}
}
S1AP_PATH_SWITCH_REQ (msg_p).nb_of_e_rabs = e_rabs_done;
create_tunnel_req.rnti = ue_context_pP->ue_context.rnti;
create_tunnel_req.num_tunnels = e_rabs_done;
gtpv1u_create_s1u_tunnel(
ctxt_pP->instance,
&create_tunnel_req,
&create_tunnel_resp);
rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
ctxt_pP,
&create_tunnel_resp,
&inde_list[0]);
for (e_rab = 0; e_rab < e_rabs_done; e_rab++) {
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].e_rab_id = create_tunnel_resp.eps_bearer_id[e_rab];
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].gtp_teid = create_tunnel_resp.enb_S1u_teid[e_rab];
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr = create_tunnel_resp.enb_addr;
LOG_I (RRC,"enb_gtp_addr (msg index %d, e_rab index %d, status %d): nb_of_e_rabs %d, e_rab_id %d, teid: %u, addr: %d.%d.%d.%d \n ",
e_rabs_done, e_rab, ue_context_pP->ue_context.e_rab[inde_list[e_rab]].status,
ue_context_pP->ue_context.nb_of_e_rabs,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].e_rab_id,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].gtp_teid,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[0],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[1],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[2],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[3]);
}
// NN: add conditions for e_rabs_failed
if (e_rabs_done > 0) {
LOG_I(RRC,"S1AP_PATH_SWITCH_REQ: sending the message: nb_of_erabstobeswitched %d, total e_rabs %d, index %d\n",
ue_context_pP->ue_context.nb_of_e_rabs, ue_context_pP->ue_context.setup_e_rabs, e_rab);
MSC_LOG_TX_MESSAGE(
MSC_RRC_ENB,
MSC_S1AP_ENB,
(const char *)&S1AP_PATH_SWITCH_REQ (msg_p),
sizeof(s1ap_path_switch_req_t),
MSC_AS_TIME_FMT" PATH_SWITCH_REQ UE %X eNB_ue_s1ap_id %u e_rabs:%u succ",
MSC_AS_TIME_ARGS(ctxt_pP),
ue_context_pP->ue_id_rnti,
S1AP_PATH_SWITCH_REQ (msg_p).eNB_ue_s1ap_id,
e_rabs_done);
itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
}
return 0;
}
int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance)
{
uint16_t ue_initial_id;
uint32_t eNB_ue_s1ap_id;
//gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
//gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
struct rrc_eNB_ue_context_s* ue_context_p = NULL;
protocol_ctxt_t ctxt;
int i;
ue_initial_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_initial_id;
eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id;
ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n",
instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_E_RAB_SETUP_REQ (msg_p).nb_e_rabs_tosetup);
if (ue_context_p == NULL) {
/* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
//MessageDef *msg_fail_p = NULL;
LOG_W(RRC, "[eNB %d] In S1AP_PATH_SWITCH_REQ_ACK: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id);
//msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ_ACK_FAIL);
//S1AP_PATH_SWITCH_REQ_ACK (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
// TODO add failure cause when defined!
//itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
return (-1);
} else {
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id;
ue_context_p->ue_context.mme_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).mme_ue_s1ap_id;
/* Save e RAB information for later */
{
for (i = 0;
i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg
i++) {
// assume that we are releasing all the DRBs
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_TORELEASE;
}
//memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
uint8_t nb_e_rabs_tobeswitched = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobeswitched;
// keep the previous bearer
// the index for the rec
for (i = 0;
i < 1;//nb_e_rabs_tobeswitched; // go over total number of e_rabs received through x2_ho_req msg
i++) {
LOG_I(RRC,"Bearer re-established with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id);
/* Harmonize with enb_gtp_teid, enb_gtp_addrs, and enb_gtp_rbi vars in the top level structure */
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_REESTABLISHED;
//ue_context_p->ue_context.e_rab[i].param.e_rab_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].e_rab_id;
//ue_context_p->ue_context.e_rab[i].param.sgw_addr= S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].sgw_addr;
//ue_context_p->ue_context.e_rab[i].param.gtp_teid = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].gtp_teid;
/* Tunnel must have been already created in X2_HO_REQ procedure */
}
ue_context_p->ue_context.setup_e_rabs=i;
ue_context_p->ue_context.nb_of_e_rabs=i;
}
ue_context_p->ue_context.ue_ambr=S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_ambr;
ue_context_p->ue_context.nb_release_of_e_rabs = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobereleased;
memset(&delete_tunnel_req, 0 , sizeof(delete_tunnel_req));
for (i = 0;
i < ue_context_p->ue_context.nb_release_of_e_rabs;
i++) {
LOG_I(RRC,"Bearer released with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id);
ue_context_p->ue_context.e_rabs_tobereleased[i]=S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id;
delete_tunnel_req.eps_bearer_id[i] = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id;
}
if (ue_context_p->ue_context.nb_release_of_e_rabs>0){
delete_tunnel_req.rnti= ue_context_p->ue_context.rnti;
delete_tunnel_req.num_erab= ue_context_p->ue_context.nb_release_of_e_rabs;
/* this could also be done through ITTI message */
gtpv1u_delete_s1u_tunnel(instance,
&delete_tunnel_req);
/* TBD: release the DRB not admitted */
//rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(&ctxt, ue_context_p, 0);
}
/* Security key */
ue_context_p->ue_context.next_hop_chain_count=S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_hop_chain_count;
memcpy ( ue_context_p->ue_context.next_security_key,
S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key,
SECURITY_KEY_LENGTH);
return (0);
}
}
# endif /* defined(ENABLE_ITTI) */ # endif /* defined(ENABLE_ITTI) */
#endif /* defined(ENABLE_USE_MME) */ #endif /* defined(ENABLE_USE_MME) */
...@@ -269,6 +269,10 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms ...@@ -269,6 +269,10 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms
*/ */
int rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid ); int rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid );
int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP);
int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance);
# endif # endif
# endif /* defined(ENABLE_USE_MME) */ # endif /* defined(ENABLE_USE_MME) */
#endif /* RRC_ENB_S1AP_H_ */ #endif /* RRC_ENB_S1AP_H_ */
...@@ -309,6 +309,15 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration( ...@@ -309,6 +309,15 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(
const uint8_t ho_state, const uint8_t ho_state,
agent_reconf_rrc * trig_param agent_reconf_rrc * trig_param
); );
void
rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP,
uint8_t* buffer,
int *_size
//const uint8_t ho_state
);
void
rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s* ue_context_p, protocol_ctxt_t* const ctxt_pP);
int freq_to_arfcn10(int band, unsigned long freq); int freq_to_arfcn10(int band, unsigned long freq);
...@@ -345,6 +354,8 @@ void *rrc_enb_task(void *args_p); ...@@ -345,6 +354,8 @@ void *rrc_enb_task(void *args_p);
void *rrc_ue_task(void *args_p); void *rrc_ue_task(void *args_p);
#endif #endif
void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m);
/**\brief Generate/decode the handover RRCConnectionReconfiguration at eNB /**\brief Generate/decode the handover RRCConnectionReconfiguration at eNB
\param module_idP Instance ID for eNB/CH \param module_idP Instance ID for eNB/CH
\param frame Frame index \param frame Frame index
...@@ -573,9 +584,11 @@ rrc_eNB_process_MeasurementReport( ...@@ -573,9 +584,11 @@ rrc_eNB_process_MeasurementReport(
void void
rrc_eNB_generate_HandoverPreparationInformation( rrc_eNB_generate_HandoverPreparationInformation(
const protocol_ctxt_t* const ctxt_pP, //const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP, rrc_eNB_ue_context_t* const ue_context_pP,
PhysCellId_t targetPhyId uint8_t* buffer,
int *_size
//PhysCellId_t targetPhyId
); );
void void
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB.c
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <pthread.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -64,6 +71,13 @@ void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p, ...@@ -64,6 +71,13 @@ void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
uint32_t enb_port_for_X2C, uint32_t enb_port_for_X2C,
int multi_sd); int multi_sd);
static
void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req);
static
void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_req_ack_t *x2ap_handover_req_ack);
static static
void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) { void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
...@@ -405,6 +419,62 @@ void x2ap_eNB_handle_sctp_init_msg_multi_cnf( ...@@ -405,6 +419,62 @@ void x2ap_eNB_handle_sctp_init_msg_multi_cnf(
} }
} }
static
void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req)
{
/* TODO: remove this hack (the goal is to find the correct
* eNodeB structure for the target) - we need a proper way for RRC
* and X2AP to identify eNodeBs
* RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
* the configuration file)
* as far as I understand.. CROUX
*/
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
int target_enb_id = x2ap_handover_req->target_physCellId;
instance_p = x2ap_eNB_pci_get_instance(target_enb_id);
DevAssert(instance_p != NULL);
//instance_p = x2ap_eNB_get_instance(instance);
//DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(instance_p->eNB_id);
DevAssert(target != NULL);
/* store rnti at index 0 */
//x2id_to_source_rnti[0] = x2ap_handover_req->source_rnti;
x2ap_eNB_generate_x2_handover_request(target, x2ap_handover_req);
}
static
void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_req_ack_t *x2ap_handover_req_ack)
{
/* TODO: remove this hack (the goal is to find the correct
* eNodeB structure for the other end) - we need a proper way for RRC
* and X2AP to identify eNodeBs
* RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
* the configuration file)
* as far as I understand.. CROUX
*/
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
int target_enb_id = x2ap_handover_req_ack->target_mod_id;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(target_enb_id);
DevAssert(target != NULL);
x2ap_eNB_generate_x2_handover_request_ack(target, x2ap_handover_req_ack);
//x2ap_eNB_generate_x2_handover_req_ack(instance_p, target, x2ap_handover_req_ack->source_x2id,
//x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size);
}
void *x2ap_task(void *arg) void *x2ap_task(void *arg)
{ {
MessageDef *received_msg = NULL; MessageDef *received_msg = NULL;
...@@ -429,6 +499,16 @@ void *x2ap_task(void *arg) ...@@ -429,6 +499,16 @@ void *x2ap_task(void *arg)
&X2AP_REGISTER_ENB_REQ(received_msg)); &X2AP_REGISTER_ENB_REQ(received_msg));
break; break;
case X2AP_HANDOVER_REQ:
x2ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_REQ(received_msg));
break;
case X2AP_HANDOVER_REQ_ACK:
x2ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_REQ_ACK(received_msg));
break;
case SCTP_INIT_MSG_MULTI_CNF: case SCTP_INIT_MSG_MULTI_CNF:
x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg), x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_init_msg_multi_cnf); &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB.h
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_decoder.c
* \brief x2ap decoder procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdio.h> #include <stdio.h>
#include "assertions.h" #include "assertions.h"
...@@ -33,7 +40,12 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu) ...@@ -33,7 +40,12 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
switch(pdu->choice.initiatingMessage.procedureCode) { switch(pdu->choice.initiatingMessage.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup: case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu); //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
case X2AP_ProcedureCode_id_handoverPreparation:
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n"); X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break; break;
...@@ -54,7 +66,12 @@ static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu) ...@@ -54,7 +66,12 @@ static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu)
switch(pdu->choice.successfulOutcome.procedureCode) { switch(pdu->choice.successfulOutcome.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup: case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu); //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
break;
case X2AP_ProcedureCode_id_handoverPreparation:
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n"); X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
break; break;
...@@ -73,7 +90,7 @@ static int x2ap_eNB_decode_unsuccessful_outcome(X2AP_X2AP_PDU_t *pdu) ...@@ -73,7 +90,7 @@ static int x2ap_eNB_decode_unsuccessful_outcome(X2AP_X2AP_PDU_t *pdu)
switch(pdu->choice.unsuccessfulOutcome.procedureCode) { switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup: case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu); //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_unsuccessfuloutcome_message!\n"); X2AP_INFO("x2ap_eNB_decode_unsuccessfuloutcome_message!\n");
break; break;
...@@ -99,8 +116,9 @@ int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint3 ...@@ -99,8 +116,9 @@ int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint3
length, length,
0, 0,
0); 0);
if (asn1_xer_print) {
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu); xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
}
if (dec_ret.code != RC_OK) { if (dec_ret.code != RC_OK) {
X2AP_ERROR("Failed to decode pdu\n"); X2AP_ERROR("Failed to decode pdu\n");
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_decoder.h
* \brief x2ap decoder procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_DECODER_H_ #ifndef X2AP_ENB_DECODER_H_
#define X2AP_ENB_DECODER_H_ #define X2AP_ENB_DECODER_H_
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_defs.h
* \brief x2ap struct definitions for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdint.h> #include <stdint.h>
#include "queue.h" #include "queue.h"
...@@ -156,6 +163,7 @@ typedef struct x2ap_eNB_instance_s { ...@@ -156,6 +163,7 @@ typedef struct x2ap_eNB_instance_s {
uint32_t downlink_frequency[MAX_NUM_CCs]; uint32_t downlink_frequency[MAX_NUM_CCs];
int32_t uplink_frequency_offset[MAX_NUM_CCs]; int32_t uplink_frequency_offset[MAX_NUM_CCs];
uint32_t Nid_cell[MAX_NUM_CCs]; uint32_t Nid_cell[MAX_NUM_CCs];
uint32_t Nid_target_cell[MAX_NUM_CCs];
int16_t N_RB_DL[MAX_NUM_CCs]; int16_t N_RB_DL[MAX_NUM_CCs];
lte_frame_type_t frame_type[MAX_NUM_CCs]; lte_frame_type_t frame_type[MAX_NUM_CCs];
uint32_t fdd_earfcn_DL[MAX_NUM_CCs]; uint32_t fdd_earfcn_DL[MAX_NUM_CCs];
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_encoder.c
* \brief x2ap encoder procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_encoder.h
* \brief x2ap encoder procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_ENCODER_H_ #ifndef X2AP_ENB_ENCODER_H_
#define X2AP_ENB_ENCODER_H_ #define X2AP_ENB_ENCODER_H_
......
...@@ -19,12 +19,22 @@ ...@@ -19,12 +19,22 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_generate_messages.c
* \brief x2ap procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include "intertask_interface.h" #include "intertask_interface.h"
#include "X2AP_LastVisitedCell-Item.h"
#include "x2ap_common.h" #include "x2ap_common.h"
#include "x2ap_eNB.h" #include "x2ap_eNB.h"
#include "x2ap_eNB_generate_messages.h" #include "x2ap_eNB_generate_messages.h"
#include "x2ap_eNB_encoder.h" #include "x2ap_eNB_encoder.h"
#include "x2ap_eNB_decoder.h"
#include "x2ap_eNB_itti_messaging.h" #include "x2ap_eNB_itti_messaging.h"
...@@ -403,3 +413,314 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p, ...@@ -403,3 +413,314 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
return 0; return 0;
} }
int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_t *x2ap_handover_req)
{
X2AP_X2AP_PDU_t pdu;
X2AP_HandoverRequest_t *out;
X2AP_HandoverRequest_IEs_t *ie;
X2AP_E_RABs_ToBeSetup_ItemIEs_t *e_RABS_ToBeSetup_ItemIEs;
X2AP_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item;
X2AP_LastVisitedCell_Item_t *lastVisitedCell_Item;
x2ap_eNB_instance_t *instance_p;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(x2ap_eNB_data_p != NULL);
/* get the eNB instance */
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
DevAssert(instance_p != NULL);
/* Prepare the X2AP handover message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_handoverPreparation;
pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject;
pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_HandoverRequest;
out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
/* mandatory */
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = x2ap_handover_req->old_eNB_ue_x2ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Cause;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_Cause;
ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_TargetCell_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_ECGI;
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&ie->value.choice.ECGI.pLMN_Identity);
MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_GUMMEI_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_GUMMEI;
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&ie->value.choice.GUMMEI.gU_Group_ID.pLMN_Identity);
//@TODO: consider to update these values
INT16_TO_OCTET_STRING(x2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
MME_CODE_TO_OCTET_STRING(x2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_UE_ContextInformation;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
//@TODO: consider to update this value
ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = x2ap_handover_req->mme_ue_s1ap_id;
KENB_STAR_TO_BIT_STRING(x2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
if (x2ap_handover_req->kenb_ncc >=0) { // Check this condition
ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = x2ap_handover_req->kenb_ncc;
}
else {
ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
}
ENCRALG_TO_BIT_STRING(x2ap_handover_req->security_capabilities.encryption_algorithms,
&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
INTPROTALG_TO_BIT_STRING(x2ap_handover_req->security_capabilities.integrity_algorithms,
&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
//@TODO: update with proper UEAMPR
UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
{
for (int i=0;i<x2ap_handover_req->nb_e_rabs_tobesetup;i++) {
e_RABS_ToBeSetup_ItemIEs = (X2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(X2AP_E_RABs_ToBeSetup_ItemIEs_t));
e_RABS_ToBeSetup_ItemIEs->id = X2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
e_RABS_ToBeSetup_ItemIEs->criticality = X2AP_Criticality_ignore;
e_RABS_ToBeSetup_ItemIEs->value.present = X2AP_E_RABs_ToBeSetup_ItemIEs__value_PR_E_RABs_ToBeSetup_Item;
e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
{
e_RABs_ToBeSetup_Item->e_RAB_ID = x2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = x2ap_handover_req->e_rab_param[i].qos.qci;
e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability;
e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length/8);
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length%8;
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf =
calloc(1,e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
memcpy (e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.buffer,
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
INT32_TO_OCTET_STRING(x2ap_handover_req->e_rabs_tobesetup[i].gtp_teid,&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID);
}
ASN_SEQUENCE_ADD(&ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list, e_RABS_ToBeSetup_ItemIEs);
}
}
OCTET_STRING_fromBuf(&ie->value.choice.UE_ContextInformation.rRC_Context, (char*) x2ap_handover_req->rrc_buffer, x2ap_handover_req->rrc_buffer_size);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_UE_HistoryInformation;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
//@TODO: consider to update this value
{
lastVisitedCell_Item = (X2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(X2AP_LastVisitedCell_Item_t));
lastVisitedCell_Item->present = X2AP_LastVisitedCell_Item_PR_e_UTRAN_Cell;
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
MACRO_ENB_ID_TO_CELL_IDENTITY(0, 0, &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
lastVisitedCell_Item->choice.e_UTRAN_Cell.cellType.cell_Size = X2AP_Cell_Size_small;
lastVisitedCell_Item->choice.e_UTRAN_Cell.time_UE_StayedInCell = 2;
ASN_SEQUENCE_ADD(&ie->value.choice.UE_HistoryInformation.list, lastVisitedCell_Item);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 handover request\n");
abort();
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
return ret;
}
int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_ack_t *x2ap_handover_req_ack)
{
X2AP_X2AP_PDU_t pdu;
X2AP_HandoverRequestAcknowledge_t *out;
X2AP_HandoverRequestAcknowledge_IEs_t *ie;
X2AP_E_RABs_Admitted_ItemIEs_t *e_RABS_Admitted_ItemIEs;
X2AP_E_RABs_Admitted_Item_t *e_RABs_Admitted_Item;
x2ap_eNB_instance_t *instance_p;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(x2ap_eNB_data_p != NULL);
/* get the eNB instance */
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
DevAssert(instance_p != NULL);
/* Prepare the X2AP handover message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_handoverPreparation;
pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject;
pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
/* mandatory */
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
{
for (int i=0;i<x2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
e_RABS_Admitted_ItemIEs = (X2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(X2AP_E_RABs_Admitted_ItemIEs_t));
e_RABS_Admitted_ItemIEs->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
e_RABS_Admitted_ItemIEs->criticality = X2AP_Criticality_ignore;
e_RABS_Admitted_ItemIEs->value.present = X2AP_E_RABs_Admitted_ItemIEs__value_PR_E_RABs_Admitted_Item;
e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
{
e_RABs_Admitted_Item->e_RAB_ID = x2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
}
ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_List.list, e_RABS_Admitted_ItemIEs);
}
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_TargeteNBtoSource_eNBTransparentContainer;
OCTET_STRING_fromBuf(&ie->value.choice.TargeteNBtoSource_eNBTransparentContainer, (char*) x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 handover response\n");
abort();
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", x2ap_eNB_data_p->assoc_id);
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
return ret;
}
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p)
{
X2AP_X2AP_PDU_t pdu;
X2AP_UEContextRelease_t *out;
X2AP_UEContextRelease_IEs_t *ie;
x2ap_eNB_instance_t *instance_p;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(x2ap_eNB_data_p != NULL);
/* get the eNB instance */
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
DevAssert(instance_p != NULL);
/* Prepare the X2AP ue context relase message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_uEContextRelease;
pdu.choice.initiatingMessage.criticality = X2AP_Criticality_ignore;
pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_UEContextRelease;
out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
/* mandatory */
ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 UE Context Release\n");
abort();
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
return ret;
}
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_generate_messages.h
* \brief x2ap procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_GENERATE_MESSAGES_H_ #ifndef X2AP_ENB_GENERATE_MESSAGES_H_
#define X2AP_ENB_GENERATE_MESSAGES_H_ #define X2AP_ENB_GENERATE_MESSAGES_H_
...@@ -26,9 +33,9 @@ ...@@ -26,9 +33,9 @@
#include "x2ap_common.h" #include "x2ap_common.h"
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p, int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p); x2ap_eNB_data_t *x2ap_eNB_data_p);
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_enb_data_p); int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p);
int x2ap_eNB_generate_x2_setup_failure(instance_t instance, int x2ap_eNB_generate_x2_setup_failure(instance_t instance,
uint32_t assoc_id, uint32_t assoc_id,
...@@ -40,5 +47,12 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p, ...@@ -40,5 +47,12 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
X2AP_Cause_PR cause_type, X2AP_Cause_PR cause_type,
long cause_value); long cause_value);
int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_t *x2ap_handover_req);
int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_ack_t *x2ap_handover_req_ack);
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */ #endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
...@@ -18,6 +18,14 @@ ...@@ -18,6 +18,14 @@
* For more information about the OpenAirInterface (OAI) Software Alliance: * For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_handler.c
* \brief x2ap handler procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdint.h> #include <stdint.h>
#include "intertask_interface.h" #include "intertask_interface.h"
...@@ -52,9 +60,20 @@ int x2ap_eNB_handle_x2_setup_failure (instance_t instance, ...@@ -52,9 +60,20 @@ int x2ap_eNB_handle_x2_setup_failure (instance_t instance,
uint32_t stream, uint32_t stream,
X2AP_X2AP_PDU_t *pdu); X2AP_X2AP_PDU_t *pdu);
static
int x2ap_eNB_handle_handover_preparation (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_eNB_handle_handover_response (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
/* Handlers matrix. Only eNB related procedure present here */ /* Handlers matrix. Only eNB related procedure present here */
x2ap_message_decoded_callback x2ap_messages_callback[][3] = { x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ 0, 0, 0 }, /* handoverPreparation */ { x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */
{ 0, 0, 0 }, /* handoverCancel */ { 0, 0, 0 }, /* handoverCancel */
{ 0, 0, 0 }, /* loadIndication */ { 0, 0, 0 }, /* loadIndication */
{ 0, 0, 0 }, /* errorIndication */ { 0, 0, 0 }, /* errorIndication */
...@@ -143,41 +162,105 @@ int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stre ...@@ -143,41 +162,105 @@ int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stre
const uint8_t *const data, const uint32_t data_length) const uint8_t *const data, const uint32_t data_length)
{ {
X2AP_X2AP_PDU_t pdu; X2AP_X2AP_PDU_t pdu;
int ret; int ret = 0;
DevAssert(data != NULL); DevAssert(data != NULL);
memset(&pdu, 0, sizeof(pdu)); memset(&pdu, 0, sizeof(pdu));
//printf("Data length received: %d\n", data_length);
if (x2ap_eNB_decode_pdu(&pdu, data, data_length) < 0) { if (x2ap_eNB_decode_pdu(&pdu, data, data_length) < 0) {
X2AP_ERROR("Failed to decode PDU\n"); X2AP_ERROR("Failed to decode PDU\n");
return -1; return -1;
} }
/* Checking procedure Code and direction of message */ switch (pdu.present) {
if (pdu.choice.initiatingMessage.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
x2ap_message_decoded_callback))
|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
X2AP_ERROR("[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1;
}
/* No handler present. case X2AP_X2AP_PDU_PR_initiatingMessage:
* This can mean not implemented or no procedure for eNB (wrong direction). /* Checking procedure Code and direction of message */
*/ if (pdu.choice.initiatingMessage.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
if (x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) { x2ap_message_decoded_callback))) {
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n", //|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
assoc_id, pdu.choice.initiatingMessage.procedureCode, X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
x2ap_direction2String(pdu.present - 1)); assoc_id, pdu.choice.initiatingMessage.procedureCode);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1; return -1;
} }
/* No handler present.
* This can mean not implemented or no procedure for eNB (wrong direction).
*/
if (x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
assoc_id, pdu.choice.initiatingMessage.procedureCode,
x2ap_direction2String(pdu.present - 1));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1;
}
/* Calling the right handler */
ret = (*x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
(instance, assoc_id, stream, &pdu);
break;
case X2AP_X2AP_PDU_PR_successfulOutcome:
/* Checking procedure Code and direction of message */
if (pdu.choice.successfulOutcome.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
x2ap_message_decoded_callback))) {
//|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
assoc_id, pdu.choice.successfulOutcome.procedureCode);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1;
}
/* Calling the right handler */ /* No handler present.
ret = (*x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1]) * This can mean not implemented or no procedure for eNB (wrong direction).
*/
if (x2ap_messages_callback[pdu.choice.successfulOutcome.procedureCode][pdu.present - 1] == NULL) {
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
assoc_id, pdu.choice.successfulOutcome.procedureCode,
x2ap_direction2String(pdu.present - 1));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1;
}
/* Calling the right handler */
ret = (*x2ap_messages_callback[pdu.choice.successfulOutcome.procedureCode][pdu.present - 1])
(instance, assoc_id, stream, &pdu); (instance, assoc_id, stream, &pdu);
break;
case X2AP_X2AP_PDU_PR_unsuccessfulOutcome:
/* Checking procedure Code and direction of message */
if (pdu.choice.unsuccessfulOutcome.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
x2ap_message_decoded_callback))) {
//|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
assoc_id, pdu.choice.unsuccessfulOutcome.procedureCode);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1;
}
/* No handler present.
* This can mean not implemented or no procedure for eNB (wrong direction).
*/
if (x2ap_messages_callback[pdu.choice.unsuccessfulOutcome.procedureCode][pdu.present - 1] == NULL) {
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
assoc_id, pdu.choice.unsuccessfulOutcome.procedureCode,
x2ap_direction2String(pdu.present - 1));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1;
}
/* Calling the right handler */
ret = (*x2ap_messages_callback[pdu.choice.unsuccessfulOutcome.procedureCode][pdu.present - 1])
(instance, assoc_id, stream, &pdu);
break;
default:
X2AP_ERROR("[SCTP %d] Direction %d exceed expected\n",
assoc_id, pdu.present);
break;
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return ret; return ret;
} }
...@@ -191,6 +274,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, ...@@ -191,6 +274,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
X2AP_X2SetupRequest_t *x2SetupRequest; X2AP_X2SetupRequest_t *x2SetupRequest;
X2AP_X2SetupRequest_IEs_t *ie; X2AP_X2SetupRequest_IEs_t *ie;
ServedCells__Member *servedCellMember;
x2ap_eNB_data_t *x2ap_eNB_data; x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0; uint32_t eNB_id = 0;
...@@ -283,6 +367,17 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, ...@@ -283,6 +367,17 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
*/ */
} }
/* Set proper pci */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupRequest_IEs_t, ie, x2SetupRequest,
X2AP_ProtocolIE_ID_id_ServedCells, true);
if (ie->value.choice.ServedCells.list.count > 0) {
x2ap_eNB_data->x2ap_eNB_instance->num_cc = ie->value.choice.ServedCells.list.count;
for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) {
servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i];
x2ap_eNB_data->x2ap_eNB_instance->Nid_target_cell[i] = servedCellMember->servedCellInfo.pCI;
}
}
return x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data); return x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data);
} }
...@@ -295,6 +390,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, ...@@ -295,6 +390,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
X2AP_X2SetupResponse_t *x2SetupResponse; X2AP_X2SetupResponse_t *x2SetupResponse;
X2AP_X2SetupResponse_IEs_t *ie; X2AP_X2SetupResponse_IEs_t *ie;
ServedCells__Member *servedCellMember;
x2ap_eNB_data_t *x2ap_eNB_data; x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0; uint32_t eNB_id = 0;
...@@ -367,6 +463,17 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, ...@@ -367,6 +463,17 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
*/ */
} }
/* Set proper pci */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse,
X2AP_ProtocolIE_ID_id_ServedCells, true);
if (ie->value.choice.ServedCells.list.count > 0) {
x2ap_eNB_data->x2ap_eNB_instance->num_cc = ie->value.choice.ServedCells.list.count;
for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) {
servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i];
x2ap_eNB_data->x2ap_eNB_instance->Nid_target_cell[i] = servedCellMember->servedCellInfo.pCI;
}
}
/* Optionaly set the target eNB name */ /* Optionaly set the target eNB name */
/* The association is now ready as source and target eNBs know parameters of each other. /* The association is now ready as source and target eNBs know parameters of each other.
...@@ -430,3 +537,165 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, ...@@ -430,3 +537,165 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
return 0; return 0;
} }
static
int x2ap_eNB_handle_handover_preparation (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_HandoverRequest_t *x2HandoverRequest;
X2AP_HandoverRequest_IEs_t *ie;
X2AP_E_RABs_ToBeSetup_ItemIEs_t *e_RABS_ToBeSetup_ItemIEs;
X2AP_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
DevAssert (pdu != NULL);
x2HandoverRequest = &pdu->choice.initiatingMessage.value.choice.HandoverRequest;
if (stream == 0) {
X2AP_ERROR ("Received new x2 handover request on stream == 0\n");
/* TODO: send a x2 failure response */
return 0;
}
X2AP_DEBUG ("Received a new X2 handover request\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ);
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
//X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti;
//X2AP_HANDOVER_REQ(m).source_x2id = x2HandoverRequest->old_eNB_UE_X2AP_ID;
X2AP_HANDOVER_REQ(msg).old_eNB_ue_x2ap_id = ie->value.choice.UE_X2AP_ID;
//X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
//measResultListEUTRA.list.array[ncell_index]->physCellId;
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
X2AP_ProtocolIE_ID_id_GUMMEI_ID, true);
TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, X2AP_HANDOVER_REQ(msg).ue_gummei.mcc,
X2AP_HANDOVER_REQ(msg).ue_gummei.mnc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len);
OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code);
OCTET_STRING_TO_INT16(&ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id);
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
X2AP_ProtocolIE_ID_id_UE_ContextInformation, true);
X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID;
X2AP_HANDOVER_REQ(msg).target_mod_id = x2ap_eNB_data->x2ap_eNB_instance->eNB_id;
X2AP_HANDOVER_REQ(msg).security_capabilities.encryption_algorithms =
BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
X2AP_HANDOVER_REQ(msg).security_capabilities.integrity_algorithms =
BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
//X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr;
if ((ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf) &&
(ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.size == 32)) {
memcpy(X2AP_HANDOVER_REQ(msg).kenb, ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf, 32);
X2AP_HANDOVER_REQ(msg).kenb_ncc = ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount;
} else {
X2AP_WARN ("Size of eNB key star does not match the expected value\n");
}
if (ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count > 0) {
X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count;
for (int i=0;i<ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count;i++) {
e_RABS_ToBeSetup_ItemIEs = (X2AP_E_RABs_ToBeSetup_ItemIEs_t *) ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.array[i];
e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].e_rab_id = e_RABs_ToBeSetup_Item->e_RAB_ID ;
memcpy(X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr.buffer,
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr.length =
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size * 8 - e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused;
OCTET_STRING_TO_INT32(&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID,
X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].gtp_teid);
X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.qci = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI;
X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.priority_level = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel;
X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability;
X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability;
}
}
else {
X2AP_ERROR ("Can't decode the e_RABs_ToBeSetup_List \n");
}
X2AP_RRC_Context_t *c = &ie->value.choice.UE_ContextInformation.rRC_Context;
if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/)
{ printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size;
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg);
return 0;
}
static
int x2ap_eNB_handle_handover_response (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_HandoverRequestAcknowledge_t *x2HandoverRequestAck;
X2AP_HandoverRequestAcknowledge_IEs_t *ie;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
DevAssert (pdu != NULL);
x2HandoverRequestAck = &pdu->choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
if (stream == 0) {
X2AP_ERROR ("Received new x2 handover response on stream == 0\n");
/* TODO: send a x2 failure response */
return 0;
}
X2AP_DEBUG ("Received a new X2 handover response\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ_ACK);
/* TODO: fill the message */
//extern int x2id_to_source_rnti[1];
//X2AP_HANDOVER_REQ_ACK(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID;
//X2AP_HANDOVER_REQ_ACK(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID];
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true);
X2AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer;
if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/)
{ printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size;
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg);
return 0;
}
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_handler.h
* \brief x2ap handler procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_HANDLERS_H_ #ifndef X2AP_ENB_HANDLERS_H_
#define X2AP_ENB_HANDLERS_H_ #define X2AP_ENB_HANDLERS_H_
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_itti_messaging.c
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include "intertask_interface.h" #include "intertask_interface.h"
#include "x2ap_eNB_itti_messaging.h" #include "x2ap_eNB_itti_messaging.h"
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_itti_messaging.h
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_ITTI_MESSAGING_H_ #ifndef X2AP_ENB_ITTI_MESSAGING_H_
#define X2AP_ENB_ITTI_MESSAGING_H_ #define X2AP_ENB_ITTI_MESSAGING_H_
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_management_procedures.c
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
...@@ -162,6 +169,22 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance) ...@@ -162,6 +169,22 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
return NULL; return NULL;
} }
x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci)
{
x2ap_eNB_instance_t *temp = NULL;
STAILQ_FOREACH(temp, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
x2ap_eNB_entries) {
for (int i=0; i<temp->num_cc;i++) {
if (temp->Nid_target_cell[i] == pci) {
/* Matching occurence */
return temp;
}
}
}
return NULL;
}
/// utility functions /// utility functions
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file x2ap_eNB_management_procedures.h
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_MANAGEMENT_PROCEDURES_H_ #ifndef X2AP_ENB_MANAGEMENT_PROCEDURES_H_
#define X2AP_ENB_MANAGEMENT_PROCEDURES_H #define X2AP_ENB_MANAGEMENT_PROCEDURES_H
...@@ -30,6 +37,8 @@ void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p); ...@@ -30,6 +37,8 @@ void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p);
x2ap_eNB_instance_t *x2ap_eNB_get_instance(uint8_t mod_id); x2ap_eNB_instance_t *x2ap_eNB_get_instance(uint8_t mod_id);
x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci);
uint16_t x2ap_eNB_fetch_add_global_cnx_id(void); uint16_t x2ap_eNB_fetch_add_global_cnx_id(void);
void x2ap_eNB_prepare_internal_data(void); void x2ap_eNB_prepare_internal_data(void);
......
...@@ -150,7 +150,7 @@ gtpv1u_create_s1u_tunnel( ...@@ -150,7 +150,7 @@ gtpv1u_create_s1u_tunnel(
const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP, const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP,
gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP); gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP);
static int int
gtpv1u_delete_s1u_tunnel( gtpv1u_delete_s1u_tunnel(
const instance_t instanceP, const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP); const gtpv1u_enb_delete_tunnel_req_t * const req_pP);
...@@ -911,7 +911,7 @@ int gtpv1u_update_s1u_tunnel( ...@@ -911,7 +911,7 @@ int gtpv1u_update_s1u_tunnel(
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static int gtpv1u_delete_s1u_tunnel( int gtpv1u_delete_s1u_tunnel(
const instance_t instanceP, const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP) const gtpv1u_enb_delete_tunnel_req_t * const req_pP)
{ {
......
...@@ -892,6 +892,11 @@ nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle, ...@@ -892,6 +892,11 @@ nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
ret = nwGtpv1uProcessGpdu(thiz, udpData, udpDataLen, peerIp); ret = nwGtpv1uProcessGpdu(thiz, udpData, udpDataLen, peerIp);
break; break;
case NW_GTP_END_MARKER:
GTPU_DEBUG("NW_GTP_END_MARKER\n");
ret = NW_GTPV1U_OK;
break;
default: default:
ret = NW_GTPV1U_FAILURE; ret = NW_GTPV1U_FAILURE;
NW_ASSERT(0); NW_ASSERT(0);
......
...@@ -371,6 +371,12 @@ void *s1ap_eNB_task(void *arg) ...@@ -371,6 +371,12 @@ void *s1ap_eNB_task(void *arg)
} }
break; break;
case S1AP_PATH_SWITCH_REQ: {
s1ap_eNB_path_switch_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&S1AP_PATH_SWITCH_REQ(received_msg));
}
break;
case S1AP_UE_CONTEXT_RELEASE_COMPLETE: { case S1AP_UE_CONTEXT_RELEASE_COMPLETE: {
s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg), s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg)); &S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg));
......
...@@ -166,6 +166,16 @@ static int s1ap_eNB_decode_successful_outcome(S1AP_S1AP_PDU_t *pdu) ...@@ -166,6 +166,16 @@ static int s1ap_eNB_decode_successful_outcome(S1AP_S1AP_PDU_t *pdu)
free(res.buffer); free(res.buffer);
break; break;
case S1AP_ProcedureCode_id_PathSwitchRequest:
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
message_id = S1AP_S1_SETUP_LOG;
message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
message_p->ittiMsg.s1ap_s1_setup_log.size = res.result.encoded;
memcpy(&message_p->ittiMsg.s1ap_s1_setup_log.text, res.buffer, res.result.encoded);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(res.buffer);
break;
default: default:
S1AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n", S1AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
(int)pdu->choice.successfulOutcome.procedureCode); (int)pdu->choice.successfulOutcome.procedureCode);
...@@ -192,6 +202,15 @@ static int s1ap_eNB_decode_unsuccessful_outcome(S1AP_S1AP_PDU_t *pdu) ...@@ -192,6 +202,15 @@ static int s1ap_eNB_decode_unsuccessful_outcome(S1AP_S1AP_PDU_t *pdu)
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(res.buffer); free(res.buffer);
break; break;
case S1AP_ProcedureCode_id_PathSwitchRequest:
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
message_id = S1AP_S1_SETUP_LOG;
message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
message_p->ittiMsg.s1ap_s1_setup_log.size = res.result.encoded;
memcpy(&message_p->ittiMsg.s1ap_s1_setup_log.text, res.buffer, res.result.encoded);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(res.buffer);
break;
default: default:
S1AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n", S1AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
......
...@@ -147,6 +147,16 @@ int s1ap_eNB_encode_initiating(S1AP_S1AP_PDU_t *pdu, ...@@ -147,6 +147,16 @@ int s1ap_eNB_encode_initiating(S1AP_S1AP_PDU_t *pdu,
free(res.buffer); free(res.buffer);
break; break;
case S1AP_ProcedureCode_id_PathSwitchRequest:
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
message_id = S1AP_UE_CONTEXT_RELEASE_REQ_LOG;
message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
message_p->ittiMsg.s1ap_ue_context_release_req_log.size = res.result.encoded;
memcpy(&message_p->ittiMsg.s1ap_ue_context_release_req_log.text, res.buffer, res.result.encoded);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(res.buffer);
break;
default: default:
S1AP_DEBUG("Unknown procedure ID (%d) for initiating message\n", S1AP_DEBUG("Unknown procedure ID (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage.procedureCode); (int)pdu->choice.initiatingMessage.procedureCode);
......
...@@ -93,13 +93,21 @@ static ...@@ -93,13 +93,21 @@ static
int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id,
uint32_t stream, uint32_t stream,
S1AP_S1AP_PDU_t *pdu); S1AP_S1AP_PDU_t *pdu);
static
int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
uint32_t stream,
S1AP_S1AP_PDU_t *pdu);
static
int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_id,
uint32_t stream,
S1AP_S1AP_PDU_t *pdu);
/* Handlers matrix. Only eNB related procedure present here */ /* Handlers matrix. Only eNB related procedure present here */
s1ap_message_decoded_callback messages_callback[][3] = { s1ap_message_decoded_callback messages_callback[][3] = {
{ 0, 0, 0 }, /* HandoverPreparation */ { 0, 0, 0 }, /* HandoverPreparation */
{ 0, 0, 0 }, /* HandoverResourceAllocation */ { 0, 0, 0 }, /* HandoverResourceAllocation */
{ 0, 0, 0 }, /* HandoverNotification */ { 0, 0, 0 }, /* HandoverNotification */
{ 0, 0, 0 }, /* PathSwitchRequest */ { 0, s1ap_eNB_handle_s1_path_switch_request_ack, s1ap_eNB_handle_s1_path_switch_request_failure }, /* PathSwitchRequest */
{ 0, 0, 0 }, /* HandoverCancel */ { 0, 0, 0 }, /* HandoverCancel */
{ s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */ { s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */
{ s1ap_eNB_handle_e_rab_modify_request, 0, 0 }, /* E_RABModify */ { s1ap_eNB_handle_e_rab_modify_request, 0, 0 }, /* E_RABModify */
...@@ -742,6 +750,8 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, ...@@ -742,6 +750,8 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).eNB_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).eNB_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id;
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).mme_ue_s1ap_id = ue_desc_p->mme_ue_s1ap_id;
/* id-uEaggregateMaximumBitrate */ /* id-uEaggregateMaximumBitrate */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, true); S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, true);
...@@ -1400,5 +1410,234 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, ...@@ -1400,5 +1410,234 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id,
itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
return 0;
}
static
int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
uint32_t stream,
S1AP_S1AP_PDU_t *pdu)
{
s1ap_eNB_mme_data_t *mme_desc_p = NULL;
s1ap_eNB_ue_context_t *ue_desc_p = NULL;
MessageDef *message_p = NULL;
S1AP_PathSwitchRequestAcknowledge_t *pathSwitchRequestAcknowledge;
S1AP_PathSwitchRequestAcknowledgeIEs_t *ie;
S1AP_E_RABToBeSwitchedULItemIEs_t *s1ap_E_RABToBeSwitchedULItemIEs;
S1AP_E_RABToBeSwitchedULItem_t *s1ap_E_RABToBeSwitchedULItem;
S1AP_E_RABItemIEs_t *e_RABItemIEs;
S1AP_E_RABItem_t *e_RABItem;
DevAssert(pdu != NULL);
pathSwitchRequestAcknowledge = &pdu->choice.successfulOutcome.value.choice.PathSwitchRequestAcknowledge;
/* Path Switch request == UE-related procedure -> stream !=0 */
if (stream == 0) {
S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream (%d)\n",
assoc_id, stream);
return -1;
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 path switch request ack for non existing "
"MME context\n", assoc_id);
return -1;
}
// send a message to RRC
message_p = itti_alloc_new_message(TASK_S1AP, S1AP_PATH_SWITCH_REQ_ACK);
/* mandatory */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);
S1AP_PATH_SWITCH_REQ_ACK(message_p).eNB_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;
if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
ie->value.choice.ENB_UE_S1AP_ID)) == NULL) {
S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
"existing UE context 0x%06lx\n", assoc_id,
ie->value.choice.ENB_UE_S1AP_ID);
return -1;
}
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_initial_id = ue_desc_p->ue_initial_id;
/* mandatory */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
S1AP_PATH_SWITCH_REQ_ACK(message_p).mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
if ( ue_desc_p->mme_ue_s1ap_id != ie->value.choice.MME_UE_S1AP_ID){
S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
ue_desc_p->mme_ue_s1ap_id, ie->value.choice.MME_UE_S1AP_ID);
}
/* mandatory */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
S1AP_ProtocolIE_ID_id_SecurityContext, true);
S1AP_PATH_SWITCH_REQ_ACK(message_p).next_hop_chain_count =
ie->value.choice.SecurityContext.nextHopChainingCount;
memcpy(&S1AP_PATH_SWITCH_REQ_ACK(message_p).next_security_key,
ie->value.choice.SecurityContext.nextHopParameter.buf,
ie->value.choice.SecurityContext.nextHopParameter.size);
/* optional */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, false);
if (ie) {
OCTET_STRING_TO_INT32 (
&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul
);
OCTET_STRING_TO_INT32 (
&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl
);
} else {
S1AP_WARN("UEAggregateMaximumBitrate not supported\n");
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0;
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl = 0;
}
/* optional */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedULList, false);
if (ie) {
S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobeswitched = ie->value.choice.E_RABToBeSwitchedULList.list.count;
for (int i = 0; i < ie->value.choice.E_RABToBeSwitchedULList.list.count; i++) {
s1ap_E_RABToBeSwitchedULItemIEs = (S1AP_E_RABToBeSwitchedULItemIEs_t *)ie->value.choice.E_RABToBeSwitchedULList.list.array[i];
s1ap_E_RABToBeSwitchedULItem = &s1ap_E_RABToBeSwitchedULItemIEs->value.choice.E_RABToBeSwitchedULItem;
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].e_rab_id = s1ap_E_RABToBeSwitchedULItem->e_RAB_ID;
memcpy(S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.buffer,
s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.buf, s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.size);
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.length =
s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.size * 8 - s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.bits_unused;
OCTET_STRING_TO_INT32(&s1ap_E_RABToBeSwitchedULItem->gTP_TEID,
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].gtp_teid);
}
}
else {
S1AP_WARN("E_RABToBeSwitchedULList not supported\n");
S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobeswitched = 0;
}
/* optional */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, false);
if (ie) {
S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobereleased = ie->value.choice.E_RABList.list.count;
for (int i = 0; i < ie->value.choice.E_RABList.list.count; i++) {
e_RABItemIEs = (S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i];
e_RABItem = &e_RABItemIEs->value.choice.E_RABItem;
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobereleased[i].e_rab_id = e_RABItem->e_RAB_ID;
}
}
else {
S1AP_WARN("E_RABToBeReleasedList not supported\n");
S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobereleased = 0;
}
/* optional */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
if(!ie) {
S1AP_WARN("Critical Diagnostic not supported\n");
}
/* optional */
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID_2, false);
if(!ie) {
S1AP_WARN("MME_UE_S1AP_ID_2 flag not supported\n");
}
// TODO continue
itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
return 0;
}
static
int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_id,
uint32_t stream,
S1AP_S1AP_PDU_t *pdu)
{
s1ap_eNB_mme_data_t *mme_desc_p = NULL;
S1AP_PathSwitchRequestFailure_t *pathSwitchRequestFailure;
S1AP_PathSwitchRequestFailureIEs_t *ie;
DevAssert(pdu != NULL);
pathSwitchRequestFailure = &pdu->choice.unsuccessfulOutcome.value.choice.PathSwitchRequestFailure;
if (stream != 0) {
S1AP_ERROR("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n",
assoc_id, stream);
return -1;
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 path switch request failure for non existing "
"MME context\n", assoc_id);
return -1;
}
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestFailureIEs_t, ie, pathSwitchRequestFailure,
S1AP_ProtocolIE_ID_id_Cause, true);
switch(ie->value.choice.Cause.present) {
case S1AP_Cause_PR_NOTHING:
S1AP_WARN("Received S1 Error indication cause NOTHING\n");
break;
case S1AP_Cause_PR_radioNetwork:
S1AP_WARN("Radio Network Layer Cause Failure\n");
break;
case S1AP_Cause_PR_transport:
S1AP_WARN("Transport Layer Cause Failure\n");
break;
case S1AP_Cause_PR_nas:
S1AP_WARN("NAS Cause Failure\n");
break;
case S1AP_Cause_PR_misc:
S1AP_WARN("Miscelaneous Cause Failure\n");
break;
default:
S1AP_WARN("Received an unknown S1 Error indication cause\n");
break;
}
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestFailureIEs_t, ie, pathSwitchRequestFailure,
S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
if(!ie) {
S1AP_WARN("Critical Diagnostic not supported\n");
}
// TODO continue
return 0; return 0;
} }
...@@ -1586,3 +1586,240 @@ int s1ap_eNB_e_rab_release_resp(instance_t instance, ...@@ -1586,3 +1586,240 @@ int s1ap_eNB_e_rab_release_resp(instance_t instance,
return 0; return 0;
} }
int s1ap_eNB_path_switch_req(instance_t instance,
s1ap_path_switch_req_t *path_switch_req_p)
//------------------------------------------------------------------------------
{
s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL;
struct s1ap_eNB_ue_context_s *ue_context_p = NULL;
struct s1ap_eNB_mme_data_s *mme_desc_p = NULL;
S1AP_S1AP_PDU_t pdu;
S1AP_PathSwitchRequest_t *out;
S1AP_PathSwitchRequestIEs_t *ie;
S1AP_E_RABToBeSwitchedDLItemIEs_t *e_RABToBeSwitchedDLItemIEs;
S1AP_E_RABToBeSwitchedDLItem_t *e_RABToBeSwitchedDLItem;
uint8_t *buffer = NULL;
uint32_t length;
int ret = 0;//-1;
/* Retrieve the S1AP eNB instance associated with Mod_id */
s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance);
DevAssert(path_switch_req_p != NULL);
DevAssert(s1ap_eNB_instance_p != NULL);
//if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p,
// path_switch_req_p->eNB_ue_s1ap_id)) == NULL) {
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
//S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: 0x%06x\n",
// path_switch_req_p->eNB_ue_s1ap_id);
//return -1;
//}
/* Uplink NAS transport can occur either during an s1ap connected state
* or during initial attach (for example: NAS authentication).
*/
//if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
// ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) {
//S1AP_WARN("You are attempting to send NAS data over non-connected "
// "eNB ue s1ap id: %06x, current state: %d\n",
// path_switch_req_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
//return -1;
//}
/* Select the MME corresponding to the provided GUMMEI. */
mme_desc_p = s1ap_eNB_nnsf_select_mme_by_gummei_no_cause(s1ap_eNB_instance_p, path_switch_req_p->ue_gummei);
if (mme_desc_p == NULL) {
/*
* In case eNB has no MME associated, the eNB should inform RRC and discard
* this request.
*/
S1AP_WARN("No MME is associated to the eNB\n");
// TODO: Inform RRC
return -1;
}
/* The eNB should allocate a unique eNB UE S1AP ID for this UE. The value
* will be used for the duration of the connectivity.
*/
ue_context_p = s1ap_eNB_allocate_new_UE_context();
DevAssert(ue_context_p != NULL);
/* Keep a reference to the selected MME */
ue_context_p->mme_ref = mme_desc_p;
ue_context_p->ue_initial_id = path_switch_req_p->ue_initial_id;
ue_context_p->eNB_instance = s1ap_eNB_instance_p;
do {
struct s1ap_eNB_ue_context_s *collision_p;
/* Peek a random value for the eNB_ue_s1ap_id */
ue_context_p->eNB_ue_s1ap_id = (random() + random()) & 0x00ffffff;
if ((collision_p = RB_INSERT(s1ap_ue_map, &s1ap_eNB_instance_p->s1ap_ue_head, ue_context_p))
== NULL) {
S1AP_DEBUG("Found usable eNB_ue_s1ap_id: 0x%06x %d(10)\n",
ue_context_p->eNB_ue_s1ap_id,
ue_context_p->eNB_ue_s1ap_id);
/* Break the loop as the id is not already used by another UE */
break;
}
} while(1);
ue_context_p->mme_ue_s1ap_id = path_switch_req_p->mme_ue_s1ap_id;
/* Prepare the S1AP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_PathSwitchRequest;
pdu.choice.initiatingMessage.criticality = S1AP_Criticality_reject;
pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_PathSwitchRequest;
out = &pdu.choice.initiatingMessage.value.choice.PathSwitchRequest;
/* mandatory */
ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_ENB_UE_S1AP_ID;
ie->value.choice.ENB_UE_S1AP_ID = ue_context_p->eNB_ue_s1ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
if (path_switch_req_p->nb_of_e_rabs > 0) {
ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedDLList;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_E_RABToBeSwitchedDLList;
for (int i = 0; i < path_switch_req_p->nb_of_e_rabs; i++) {
e_RABToBeSwitchedDLItemIEs = (S1AP_E_RABToBeSwitchedDLItemIEs_t *)calloc(1, sizeof(S1AP_E_RABToBeSwitchedDLItemIEs_t));
e_RABToBeSwitchedDLItemIEs->id = S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedDLItem;
e_RABToBeSwitchedDLItemIEs->criticality = S1AP_Criticality_reject;
e_RABToBeSwitchedDLItemIEs->value.present = S1AP_E_RABToBeSwitchedDLItemIEs__value_PR_E_RABToBeSwitchedDLItem;
e_RABToBeSwitchedDLItem = &e_RABToBeSwitchedDLItemIEs->value.choice.E_RABToBeSwitchedDLItem;
e_RABToBeSwitchedDLItem->e_RAB_ID = path_switch_req_p->e_rabs_tobeswitched[i].e_rab_id;
INT32_TO_OCTET_STRING(path_switch_req_p->e_rabs_tobeswitched[i].gtp_teid, &e_RABToBeSwitchedDLItem->gTP_TEID);
e_RABToBeSwitchedDLItem->transportLayerAddress.size = path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.length;
e_RABToBeSwitchedDLItem->transportLayerAddress.bits_unused = 0;
e_RABToBeSwitchedDLItem->transportLayerAddress.buf = calloc(1,e_RABToBeSwitchedDLItem->transportLayerAddress.size);
memcpy (e_RABToBeSwitchedDLItem->transportLayerAddress.buf,
path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.buffer,
path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.length);
S1AP_DEBUG("path_switch_req: e_rab ID %ld, teid %u, enb_addr %d.%d.%d.%d, SIZE %zu\n",
e_RABToBeSwitchedDLItem->e_RAB_ID,
path_switch_req_p->e_rabs_tobeswitched[i].gtp_teid,
e_RABToBeSwitchedDLItem->transportLayerAddress.buf[0],
e_RABToBeSwitchedDLItem->transportLayerAddress.buf[1],
e_RABToBeSwitchedDLItem->transportLayerAddress.buf[2],
e_RABToBeSwitchedDLItem->transportLayerAddress.buf[3],
e_RABToBeSwitchedDLItem->transportLayerAddress.size);
ASN_SEQUENCE_ADD(&ie->value.choice.E_RABToBeSwitchedDLList.list, e_RABToBeSwitchedDLItemIEs);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
}
/* mandatory */
ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_SourceMME_UE_S1AP_ID;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_MME_UE_S1AP_ID;
ie->value.choice.MME_UE_S1AP_ID = path_switch_req_p->mme_ue_s1ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_EUTRAN_CGI;
ie->criticality = S1AP_Criticality_ignore;
ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_EUTRAN_CGI;
MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id,
0,
&ie->value.choice.EUTRAN_CGI.cell_ID);
MCC_MNC_TO_TBCD(s1ap_eNB_instance_p->mcc,
s1ap_eNB_instance_p->mnc,
s1ap_eNB_instance_p->mnc_digit_length,
&ie->value.choice.EUTRAN_CGI.pLMNidentity);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_TAI;
ie->criticality = S1AP_Criticality_ignore;
ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_TAI;
/* Assuming TAI is the TAI from the cell */
INT16_TO_OCTET_STRING(s1ap_eNB_instance_p->tac, &ie->value.choice.TAI.tAC);
MCC_MNC_TO_PLMNID(s1ap_eNB_instance_p->mcc,
s1ap_eNB_instance_p->mnc,
s1ap_eNB_instance_p->mnc_digit_length,
&ie->value.choice.TAI.pLMNidentity);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_UESecurityCapabilities;
ie->criticality = S1AP_Criticality_ignore;
ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_UESecurityCapabilities;
ENCRALG_TO_BIT_STRING(path_switch_req_p->security_capabilities.encryption_algorithms,
&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms);
INTPROTALG_TO_BIT_STRING(path_switch_req_p->security_capabilities.integrity_algorithms,
&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (s1ap_eNB_encode_pdu(&pdu, &buffer, &length) < 0) {
S1AP_ERROR("Failed to encode Path Switch Req \n");
/* Encode procedure has failed... */
return -1;
}
/* Update the current S1AP UE state */
ue_context_p->ue_state = S1AP_UE_WAITING_CSR;
/* Assign a stream for this UE :
* From 3GPP 36.412 7)Transport layers:
* Within the SCTP association established between one MME and eNB pair:
* - a single pair of stream identifiers shall be reserved for the sole use
* of S1AP elementary procedures that utilize non UE-associated signalling.
* - At least one pair of stream identifiers shall be reserved for the sole use
* of S1AP elementary procedures that utilize UE-associated signallings.
* However a few pairs (i.e. more than one) should be reserved.
* - A single UE-associated signalling shall use one SCTP stream and
* the stream should not be changed during the communication of the
* UE-associated signalling.
*/
mme_desc_p->nextstream = (mme_desc_p->nextstream + 1) % mme_desc_p->out_streams;
if ((mme_desc_p->nextstream == 0) && (mme_desc_p->out_streams > 1)) {
mme_desc_p->nextstream += 1;
}
ue_context_p->tx_stream = mme_desc_p->nextstream;
MSC_LOG_TX_MESSAGE(
MSC_S1AP_ENB,
MSC_S1AP_MME,
(const char *)buffer,
length,
MSC_AS_TIME_FMT" E_RAN Setup successfulOutcome eNB_ue_s1ap_id %u mme_ue_s1ap_id %u",
0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
ue_context_p->eNB_ue_s1ap_id,
path_switch_req_p->mme_ue_s1ap_id);
/* UE associated signalling -> use the allocated stream */
s1ap_eNB_itti_send_sctp_data_req(s1ap_eNB_instance_p->instance,
mme_desc_p->assoc_id, buffer,
length, ue_context_p->tx_stream);
return ret;
}
...@@ -49,4 +49,7 @@ int s1ap_eNB_e_rab_modify_resp(instance_t instance, ...@@ -49,4 +49,7 @@ int s1ap_eNB_e_rab_modify_resp(instance_t instance,
int s1ap_eNB_e_rab_release_resp(instance_t instance, int s1ap_eNB_e_rab_release_resp(instance_t instance,
s1ap_e_rab_release_resp_t *e_rab_release_resp_p); s1ap_e_rab_release_resp_t *e_rab_release_resp_p);
int s1ap_eNB_path_switch_req(instance_t instance,
s1ap_path_switch_req_t *path_switch_req_p);
#endif /* S1AP_ENB_NAS_PROCEDURES_H_ */ #endif /* S1AP_ENB_NAS_PROCEDURES_H_ */
...@@ -255,3 +255,79 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p, ...@@ -255,3 +255,79 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p,
*/ */
return mme_highest_capacity_p; return mme_highest_capacity_p;
} }
struct s1ap_eNB_mme_data_s *
s1ap_eNB_nnsf_select_mme_by_gummei_no_cause(s1ap_eNB_instance_t *instance_p,
s1ap_gummei_t gummei)
{
struct s1ap_eNB_mme_data_s *mme_data_p = NULL;
struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL;
uint8_t current_capacity = 0;
RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
struct served_gummei_s *gummei_p = NULL;
if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) {
/* The association between MME and eNB is not ready for the moment,
* go to the next known MME.
*/
if (mme_data_p->state == S1AP_ENB_OVERLOAD) {
/* MME is overloaded. We have to check the RRC establishment
* cause and take decision to the select this MME depending on
* the overload state.
*/
} else {
/* The MME is not overloaded, association is simply not ready. */
continue;
}
}
if (current_capacity < mme_data_p->relative_mme_capacity) {
/* We find a better MME, keep a reference to it */
current_capacity = mme_data_p->relative_mme_capacity;
mme_highest_capacity_p = mme_data_p;
}
/* Looking for MME gummei matching the one provided by NAS */
STAILQ_FOREACH(gummei_p, &mme_data_p->served_gummei, next) {
struct served_group_id_s *group_id_p = NULL;
struct mme_code_s *mme_code_p = NULL;
struct plmn_identity_s *served_plmn_p = NULL;
STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) {
if ((served_plmn_p->mcc == gummei.mcc) &&
(served_plmn_p->mnc == gummei.mnc)) {
break;
}
}
STAILQ_FOREACH(mme_code_p, &gummei_p->mme_codes, next) {
if (mme_code_p->mme_code == gummei.mme_code) {
break;
}
}
STAILQ_FOREACH(group_id_p, &gummei_p->served_group_ids, next) {
if (group_id_p->mme_group_id == gummei.mme_group_id) {
break;
}
}
/* The MME matches the parameters provided by the NAS layer ->
* the MME is knwown and the association is ready.
* Return the reference to the MME to use it for this UE.
*/
if ((group_id_p != NULL) &&
(mme_code_p != NULL) &&
(served_plmn_p != NULL)) {
return mme_data_p;
}
}
}
/* At this point no MME matches the provided GUMMEI. Select the one with the
* highest relative capacity.
* In case the list of known MME is empty, simply return NULL, that way the RRC
* layer should know about it and reject RRC connectivity.
*/
return mme_highest_capacity_p;
}
...@@ -36,4 +36,8 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p, ...@@ -36,4 +36,8 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p,
rrc_establishment_cause_t cause, rrc_establishment_cause_t cause,
s1ap_gummei_t gummei); s1ap_gummei_t gummei);
struct s1ap_eNB_mme_data_s*
s1ap_eNB_nnsf_select_mme_by_gummei_no_cause(s1ap_eNB_instance_t *instance_p,
s1ap_gummei_t gummei);
#endif /* S1AP_ENB_NNSF_H_ */ #endif /* S1AP_ENB_NNSF_H_ */
...@@ -131,6 +131,54 @@ do { \ ...@@ -131,6 +131,54 @@ do { \
#define M_TMSI_TO_OCTET_STRING INT32_TO_OCTET_STRING #define M_TMSI_TO_OCTET_STRING INT32_TO_OCTET_STRING
#define MME_GID_TO_OCTET_STRING INT16_TO_OCTET_STRING #define MME_GID_TO_OCTET_STRING INT16_TO_OCTET_STRING
#define ENCRALG_TO_BIT_STRING(encralg, bitstring) \
do { \
(bitstring)->size=2; \
(bitstring)->bits_unused=0; \
(bitstring)->buf=calloc (1, sizeof (uint8_t)); \
(bitstring)->buf[0] = (encralg) >> 8; \
(bitstring)->buf[1] = (encralg); \
}while(0)
#define INTPROTALG_TO_BIT_STRING(intprotalg, bitstring) \
do { \
(bitstring)->size=2; \
(bitstring)->bits_unused=0; \
(bitstring)->buf=calloc (2, sizeof (uint8_t)); \
(bitstring)->buf[0] = (intprotalg) >> 8; \
(bitstring)->buf[1] = (intprotalg); \
}while(0)
#define KENB_STAR_TO_BIT_STRING(kenbstar, bitstring) \
do { \
(bitstring)->size=32; \
(bitstring)->bits_unused=0; \
(bitstring)->buf= calloc (32, sizeof (uint8_t));\
memcpy((bitstring)->buf, kenbstar, 32*sizeof(uint8_t)); \
}while(0)
#define UEAGMAXBITRTD_TO_ASN_PRIMITIVES(uegmaxbitrtd, asnprimitives) \
do { \
(asnprimitives)->size=5; \
(asnprimitives)->buf=calloc (5, sizeof (uint8_t)); \
(asnprimitives)->buf[0] = (uegmaxbitrtd) >> 32; \
(asnprimitives)->buf[1] = (uegmaxbitrtd) >> 24; \
(asnprimitives)->buf[2] = (uegmaxbitrtd) >> 16; \
(asnprimitives)->buf[3] = (uegmaxbitrtd) >> 8; \
(asnprimitives)->buf[4] = (uegmaxbitrtd); \
}while(0)
#define UEAGMAXBITRTU_TO_ASN_PRIMITIVES(uegmaxbitrtu, asnprimitives) \
do { \
(asnprimitives)->size=5; \
(asnprimitives)->buf=calloc (5, sizeof (uint8_t)); \
(asnprimitives)->buf[0] = (uegmaxbitrtu) >> 32; \
(asnprimitives)->buf[1] = (uegmaxbitrtu) >> 24; \
(asnprimitives)->buf[2] = (uegmaxbitrtu) >> 16; \
(asnprimitives)->buf[3] = (uegmaxbitrtu) >> 8; \
(asnprimitives)->buf[4] = (uegmaxbitrtu); \
}while(0)
#define OCTET_STRING_TO_INT8(aSN, x) \ #define OCTET_STRING_TO_INT8(aSN, x) \
do { \ do { \
DevCheck((aSN)->size == 1, (aSN)->size, 0, 0); \ DevCheck((aSN)->size == 1, (aSN)->size, 0, 0); \
......
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