Commit 85e85fb9 authored by Cedric Roux's avatar Cedric Roux

- Update S1AP and SCTP layers to use ITTI for eNB: may broke the old version...

- Update S1AP and SCTP layers to use ITTI for eNB: may broke the old version of S1AP/SCTP (compile with USE_MME=R10 and ENABLE_ITTI=1)

pre-ci tests passed

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4342 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent d0de35dc
dev 1 128-ues 207-feature-ued-platform-support 256_QAM_demod 2cw_fairRRscd 340-fix-beamforming-for-multiple-antenna 342-isip-pcie-lib 375-syrtem-sdr-platform 383-ulsch-scheduler-optimization 387-fraunhofer-iis-transmission-mode-4 401-bug-related-to-nr-pucch-format-2-generator 408-reworked 408-ue-main-threads 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 5g_fapi_scf 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 PerfumeOldTdd RA_CI_test RFquality RRC-measurements-merge2develop Saankhya_NRPRACH_HighSpeed UE_DL_DCI_hotfix UpdateRANRemoteUEReport add-dmrs-test add_iris_hw 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 block_mmse_receiver_with_whitenning 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-pdcch_order 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-FeMBMS 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-aarch64build develop-ci develop-ci-fju develop-large-scale-emulations develop-m2ap develop-multi-RRUs develop-nb-iot develop-nb-iot-RRC develop-nb-iot-merge develop-nb-iot-merge-w-conflicts develop-nb-iot-ntust develop-nr develop-nr-adding-2018-09-asn1 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-sidekiq 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 dlsim-autotests docker-improvements-2021-april docker-no-cache-option documentation 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 dreibh/doxygen-fix dual-connectivity dummy edrx enhance-rfsim enhancement-149-iqtxshift episys-merge episys/nsa_development extend_sharedlibusage extend_sharedlibusage2 fapi_for_dmrs_and_ptrs feat-mac-sock feature-15-carrier_aggregation feature-21-TM7 feature-230-tm3_scheduler feature-247-tm89 feature-247-tm89-fixes feature-247-tm89-rebased feature-278-physical-layer-GPU-version feature-309-phy_procedures_eNB_TX_split_to_multi_threading feature-31-ff-scheduler-api feature-330-turbo_decoder_gpu feature-368-channel-simulator feature-39-X2-handover feature-4g-sched feature-68-enb-agent feature-flexran-cm-s1ap feature-nr-4g-nfapi-modifications feature-pdcp-task feature-send-rrc-message-for-wireshark-logging 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 fix-itti-segv fix-l2-sim fix-limeSDR-compile fix-nr-pdcp-timer fix-nr-rlc-range-nack fix-quectel fix-realtime fix-segfault-flexran-isolated 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 gNB-nrUE-USRP gNB_mwc18_integration 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-turbo-decoder-dynamic isip-turbo-decoder-parallel isip_nr issue271_simulator issue392-simplify-s1-nos1step2_01 issue416_nfapicleanup issue_345_l2_fapi_simulator itti-enhancement l2-fixes large_scale_simulations 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 mac-monitoring main_python master mbms-fix-develop-nr merging-2019-w51-to-develop-nr mex_mmse_receiver migrate-cpp-check-container minor-fix-doc-basic-sim mobipass-hack modify_fairRRscd_parallel mosaic5g-oai-ran mosaic5g-oai-sim msg4_phy_0303_lfq mu_allocate multi-L1 multi-RRUs multiple_ssb_sib1_bugfix nasmesh_kernel_5.8 new-gtpu new_nos1 new_pdcp new_rlc new_rlc_2020 new_rlc_in_mbms nfapi-L2-emulator nfapi-bugfix nfapi_improvement 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-multiple-ssb 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-ssb-measurements nr-stats-print nr-timing-measurement nr-timing-measurement-merge nr-ue-buffer-status nr-ue-slot-based nr-uldci nrPBCHTCFix nrPbchTcFix nrUE nrUE-hs nrUE-upper-layer nr_beamforming nr_bsr nr_ci_dlsim nr_csi_newbranch nr_dci_procedures nr_demo_wsa2019 nr_dl_dmrs_type2 nr_dl_pf nr_dl_pf2 nr_dl_ul_ptrs nr_dlsch_parallel_measurements nr_dlsim_plot nr_fapi_for_push_tmp nr_fdd_if_fix nr_fix_easycppcheck nr_flexible_NRBDL nr_improve_build_procedures nr_increase_tp nr_mib_vsa_test nr_pdcch_testing nr_pdcch_updates nr_pdsch_integration nr_polar_decoder_improvement nr_power_measurement_fixes nr_prach nr_prach_fr2 nr_pucch nr_pucch2 nr_segmentation_fixes nr_sim_fix 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 oai_ue_mwc18_integration 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 preprocessor_refactor-2 ptrs_rrc_config pucch2ab pucchsim-multiue pusch-mthread-scaling-fix pusch-retrans-fix-ue ra-dl-ul rau_rru_reciprocity_measurements recode_itti_from_scratch recursive-cmake reduce_memory_footprint release_v1_2_0_candidate remove-ci-workaround remove_nos1_hack_pdcp remove_x2_gnb_hardcoding repair-TA revert-f5c94279 revert-itti 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 rru-txwrite-modification ru-parallel-beamforming ru_rau_enhancement ru_rau_enhancement-external-timing 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 schedule-si-fix signal-delay sim-channels small-bugfixes-w40 small-config-change small_nr_bugfixes smallcleanup softmodem_cleanup split73 t-gnb-tracer tcri test-panos test-x310-perf test_nsa_gtpu_fix test_rt-fix_phy-test testing_2symb_pdcch testing_with_external_txdata thread-pool tm7-iris 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_adjust_gain ue_beam_selection ue_dlsch-multi-threading ue_dlsch_decoding_ldpc_offload ue_nfapi_mch ues_test_tmp uhd_priority_set_cleanup ul-freq-iq-samps-to-file ul_dl_dci_same_slot ul_harq ulsch_decode_mthread ulsim_changes update-to-2019-march-june-release 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 workaround-rebased workaround-restart-not-working x2-endc-processing x2-ho x2-ka-test 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 2019.w06 2019.w04 2019.w03 2018.w51 2018.w48 2018.w47 2018.w46 2018.w44 2018.w41 2018.w40 2018.w39 2018.w36 2018.w33 2018.w31 2018.w29 2018.w25 2018.w19 2018.w15 2018.w12 2018.w11 2018.w10 2018.w09 2018.w08 2018.w07 2018.w06 2018.w05 2018.w04 2018.w03 2018.w02 2017.w48 2017.w46 2017.w43 2017.w42 2017.w34 2017.w30 2017.w25 2017.w24 2017.w22 2017.w20 2017.w19 2017.w15 2017.w14 2017.w13 2017.w12 2017.w11 2017.w10 2017.w09 2017.w08 2017.w07 2017.w06 2017.w05 2017.w04 2017.w03 2017.w02 2017.w01 2016.w50 2016.w49 v1.2.2 v1.2.1 v1.2.0 v1.1.1 v1.1.0 v1.0.3 v1.0.2 v1.0.1 v1.0.0 v1B0.8 v1B0.7 v1B0.6 v1B0.5 v1B0.4 v1B0.3 v1B0.2 v1B0.1 v0.6.1 v0.6.1_tdd v0.6 v0.5.2 v0.5.1_tdd v0.5 v0.4 v0.3 v0.2 v0.1 testing-cmw500 osa-etsi-ws-ue osa-etsi-ws-try2 osa-etsi-ws-try1 osa-etsi-ws-gNB oai_nr_sync nr-ip-over-lte 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-pdcch 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 develop-nr-2019w28 develop-nr-2019w23 benetel_phase_rotation benetel_gnb_rel_1.0 benetel_enb_rel_1.0
No related merge requests found
S1AP_DIR = $(OPENAIR3_DIR)/OPENAIRMME/S1AP include $(OPENAIR_TARGETS)/SIMU/USER/Makerules
S1AP_OBJDIR = $(OPENAIR3_DIR)/OPENAIRMME/S1AP/enb_objs
S1AP_OBJDIR = $(S1AP_DIR)/enb_objs
ASN1MESSAGESDIR=$(S1AP_DIR)/MESSAGES ASN1MESSAGESDIR=$(S1AP_DIR)/MESSAGES
ASN1DIR=$(ASN1MESSAGESDIR)/ASN1 ASN1DIR=$(ASN1MESSAGESDIR)/ASN1
...@@ -26,7 +27,9 @@ libs1ap_OBJECTS = \ ...@@ -26,7 +27,9 @@ libs1ap_OBJECTS = \
$(S1AP_OBJDIR)/s1ap_encoder.o \ $(S1AP_OBJDIR)/s1ap_encoder.o \
$(S1AP_OBJDIR)/s1ap_decoder.o \ $(S1AP_OBJDIR)/s1ap_decoder.o \
$(S1AP_OBJDIR)/s1ap_xer_print.o \ $(S1AP_OBJDIR)/s1ap_xer_print.o \
s1ap_eNB_decoder.o s1ap_eNB_encoder.o \ s1ap_eNB_itti_messaging.o \
s1ap_eNB_decoder.o \
s1ap_eNB_encoder.o \
s1ap_eNB_handlers.o \ s1ap_eNB_handlers.o \
s1ap_eNB_nnsf.o s1ap_eNB_ue_context.o \ s1ap_eNB_nnsf.o s1ap_eNB_ue_context.o \
s1ap_eNB_trace.o s1ap_eNB_overload.o \ s1ap_eNB_trace.o s1ap_eNB_overload.o \
...@@ -35,42 +38,30 @@ libs1ap_OBJECTS = \ ...@@ -35,42 +38,30 @@ libs1ap_OBJECTS = \
$(addprefix MESSAGES/, $(S1AP_ASN_MODULE_SOURCES)) $(addprefix MESSAGES/, $(S1AP_ASN_MODULE_SOURCES))
# pull in dependency info for *existing* .o files # pull in dependency info for *existing* .o files
-include .*.d -include *.d
# -include .*.d
CFLAGS = \ CFLAGS = \
-DENB_MODE \
-DENABLE_USE_MME \
-DEMIT_ASN_DEBUG=1 \
-DUSER_MODE \
-I./MESSAGES \ -I./MESSAGES \
-I$(S1AP_OBJDIR) \ -I$(S1AP_OBJDIR) \
-I../GTPV1-U \ -I../UTILS \
-I../GTPV1-U/nw-gtpv1u/shared \
-I../GTPV1-U/nw-gtpv1u/include \
-I../SCTP \
-I../UDP \
-I../UTILS \
-I../UTILS/HASHTABLE \
-I$(OPENAIR2_DIR)/COMMON \
-I$(S1AP_DIR) \
-I$(OPENAIR2_DIR) \
-I$(OPENAIR2_DIR)/UTIL \
$(ADD_CFLAGS) \ $(ADD_CFLAGS) \
-DENB_MODE \ -DENB_MODE \
-DENABLE_USE_MME \ $(S1AP_CFLAGS) \
-DEMIT_ASN_DEBUG_EXTERN \
-DUSER_MODE \
-g \
-O2 \
-Wall \
-Werror=implicit-function-declaration -Werror=implicit-function-declaration
$(libs1ap_OBJECTS): %.o : %.c $(libs1ap_OBJECTS): %.o : %.c
@echo "Compiling $<" @echo "Compiling $<"
@$(CC) -c $(CFLAGS) -o $@ $< @$(CC) -c $(CFLAGS) -o $@ $<
@$(CC) -MM $(CFLAGS) $*.c > .$(notdir $*).d @$(CC) -MM $(CFLAGS) $*.c > $*.d
@mv -f .$(notdir $*).d .$(notdir $*).d.tmp @mv -f $*.d $*.d.tmp
@sed -e 's|.*:|$*.o:|' < .$(notdir $*).d.tmp > .$(notdir $*).d @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d
@sed -e 's/.*://' -e 's/\\$$//' < .$(notdir $*).d.tmp | fmt -1 | \ @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> .$(notdir $*).d sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
@rm -f .$(notdir $*).tmp @rm -f $*.d.tmp
$(S1AP_OBJDIR)/s1ap_ieregen.stamp: $(ASN1DIR)/$(ASN1RELDIR)/S1AP-PDU-Contents.asn $(ASN1DIR)/asn1tostruct.py $(S1AP_OBJDIR)/s1ap_ieregen.stamp: $(ASN1DIR)/$(ASN1RELDIR)/S1AP-PDU-Contents.asn $(ASN1DIR)/asn1tostruct.py
mkdir -p $(S1AP_OBJDIR) mkdir -p $(S1AP_OBJDIR)
...@@ -87,10 +78,19 @@ libs1ap.a: $(S1AP_OBJDIR)/s1ap_ieregen.stamp $(S1AP_OBJDIR)/s1ap_asn1regen.stamp ...@@ -87,10 +78,19 @@ libs1ap.a: $(S1AP_OBJDIR)/s1ap_ieregen.stamp $(S1AP_OBJDIR)/s1ap_asn1regen.stamp
@$(AR) rcs $@ $(libs1ap_OBJECTS) @$(AR) rcs $@ $(libs1ap_OBJECTS)
clean: clean:
rm -f $(libs1ap_OBJECTS) @$(RM_F_V) $(libs1ap_OBJECTS)
rm -f $(libs1ap_OBJECTS:.o=.d) @$(RM_F_V) .*.d
rm -f libs1ap.a @$(RM_F_V) $(addprefix MESSAGES/, $(S1AP_ASN_MODULE_SOURCES))
rm -f $(S1AP_OBJDIR)/s1ap_asn1regen.stamp @$(RM_F_V) $(addprefix MESSAGES/, $(S1AP_ASN_MODULE_SOURCES:.o=.d))
rm -f $(S1AP_OBJDIR)/s1ap_ieregen.stamp @$(RM_F_V) libs1ap.a
rm -f $(S1AP_OBJDIR)/s1ap_decoder.c $(S1AP_OBJDIR)/s1ap_encoder.c @$(RM_F_V) $(S1AP_OBJDIR)/s1ap_asn1regen.stamp
rm -f $(S1AP_OBJDIR)/s1ap_xer_print.c $(S1AP_OBJDIR)/s1ap_ies_defs.h @$(RM_F_V) $(S1AP_OBJDIR)/s1ap_ieregen.stamp
\ No newline at end of file @$(RM_F_V) $(S1AP_OBJDIR)/s1ap_decoder.c $(S1AP_OBJDIR)/s1ap_encoder.c
@$(RM_F_V) $(S1AP_OBJDIR)/s1ap_xer_print.c $(S1AP_OBJDIR)/s1ap_ies_defs.h
cleanall: clean
@$(RM_F_V) $(addprefix MESSAGES/, $(S1AP_ASN_MODULE_SOURCES:.o=.c))
@$(RM_F_V) $(addprefix MESSAGES/, $(S1AP_ASN_MODULE_SOURCES:.o=.h))
showcflags:
@echo s1ap cflags: $(CFLAGS)
\ No newline at end of file
...@@ -41,8 +41,9 @@ ...@@ -41,8 +41,9 @@
#include "S1AP-PDU.h" #include "S1AP-PDU.h"
int asn_debug = 0; int asn_debug = 0;
int asn1_xer_print = 0; int asn1_xer_print = 1;
#if defined(EMIT_ASN_DEBUG_EXTERN)
inline void ASN_DEBUG(const char *fmt, ...) inline void ASN_DEBUG(const char *fmt, ...)
{ {
if (asn_debug) { if (asn_debug) {
...@@ -56,6 +57,7 @@ inline void ASN_DEBUG(const char *fmt, ...) ...@@ -56,6 +57,7 @@ inline void ASN_DEBUG(const char *fmt, ...)
va_end(ap); va_end(ap);
} }
} }
#endif
ssize_t s1ap_generate_initiating_message( ssize_t s1ap_generate_initiating_message(
uint8_t **buffer, uint8_t **buffer,
......
...@@ -44,7 +44,9 @@ ...@@ -44,7 +44,9 @@
// extern int asn_debug_indent; // extern int asn_debug_indent;
extern int asn_debug; extern int asn_debug;
#if defined(EMIT_ASN_DEBUG_EXTERN)
inline void ASN_DEBUG(const char *fmt, ...); inline void ASN_DEBUG(const char *fmt, ...);
#endif
#include "Criticality.h" #include "Criticality.h"
#include "Presence.h" #include "Presence.h"
...@@ -400,9 +402,8 @@ extern int asn_debug; ...@@ -400,9 +402,8 @@ extern int asn_debug;
extern int asn1_xer_print; extern int asn1_xer_print;
#if defined(ENB_MODE) #if defined(ENB_MODE)
# include "mme_sim.h"
# include "UTIL/LOG/log.h" # include "UTIL/LOG/log.h"
# include "eNB_default_values.h" # include "s1ap_eNB_default_values.h"
# define S1AP_ERROR(x, args...) LOG_E(S1AP, x, ##args) # define S1AP_ERROR(x, args...) LOG_E(S1AP, x, ##args)
# define S1AP_WARN(x, args...) LOG_W(S1AP, x, ##args) # define S1AP_WARN(x, args...) LOG_W(S1AP, x, ##args)
# define S1AP_TRAF(x, args...) LOG_T(S1AP, x, ##args) # define S1AP_TRAF(x, args...) LOG_T(S1AP, x, ##args)
...@@ -420,19 +421,18 @@ struct s1ap_message_s; ...@@ -420,19 +421,18 @@ struct s1ap_message_s;
/** \brief Function callback prototype. /** \brief Function callback prototype.
**/ **/
#if defined(ENB_MODE) // typedef int (*s1ap_message_decoded_callback)(
typedef int (*s1ap_message_decoded_callback)( // eNB_mme_desc_t *eNB_desc_p,
eNB_mme_desc_t *eNB_desc_p, // sctp_queue_item_t *packet_p,
sctp_queue_item_t *packet_p, // struct s1ap_message_s *message_p
struct s1ap_message_s *message_p // );
);
#else
typedef int (*s1ap_message_decoded_callback)( typedef int (*s1ap_message_decoded_callback)(
uint32_t assocId, uint32_t assoc_id,
uint32_t stream, uint32_t stream,
struct s1ap_message_s *message_p struct s1ap_message_s *message_p
); );
#endif
/** \brief Encode a successfull outcome message /** \brief Encode a successfull outcome message
\param buffer pointer to buffer in which data will be encoded \param buffer pointer to buffer in which data will be encoded
\param length pointer to the length of buffer \param length pointer to the length of buffer
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
*******************************************************************************/ *******************************************************************************/
#include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
...@@ -35,8 +36,9 @@ ...@@ -35,8 +36,9 @@
#include "tree.h" #include "tree.h"
#include "queue.h" #include "queue.h"
#include "mme_sim.h" #include "intertask_interface.h"
#include "eNB_default_values.h"
#include "s1ap_eNB_default_values.h"
#include "s1ap_common.h" #include "s1ap_common.h"
#include "s1ap_ies_defs.h" #include "s1ap_ies_defs.h"
...@@ -50,157 +52,299 @@ ...@@ -50,157 +52,299 @@
#include "s1ap_eNB_nas_procedures.h" #include "s1ap_eNB_nas_procedures.h"
#include "s1ap_eNB_management_procedures.h" #include "s1ap_eNB_management_procedures.h"
#include "s1ap_eNB_itti_messaging.h"
#include "sctp_primitives_client.h" #include "sctp_primitives_client.h"
#include "assertions.h" #include "assertions.h"
#include "conversions.h" #include "conversions.h"
static int s1ap_eNB_generate_s1_setup_request(eNB_mme_desc_t *eNB_desc_p, s1ap_eNB_internal_data_t s1ap_eNB_internal_data;
s1ap_eNB_mme_data_t *mme_assoc_p);
static int s1ap_eNB_generate_s1_setup_request(
s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p);
RB_GENERATE(s1ap_mme_map, s1ap_eNB_mme_data_s, entry, s1ap_eNB_compare_assoc_id); RB_GENERATE(s1ap_mme_map, s1ap_eNB_mme_data_s, entry, s1ap_eNB_compare_assoc_id);
inline int s1ap_eNB_compare_assoc_id( inline int s1ap_eNB_compare_assoc_id(
struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2) struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2)
{ {
if (p1->sctp_data.assoc_id < p2->sctp_data.assoc_id) { if (p1->assoc_id == -1) {
return -1; if (p1->cnx_id < p2->cnx_id) {
} return -1;
if (p1->sctp_data.assoc_id > p2->sctp_data.assoc_id) { }
return 1; if (p1->cnx_id > p2->cnx_id) {
return 1;
}
} else {
if (p1->assoc_id < p2->assoc_id) {
return -1;
}
if (p1->assoc_id > p2->assoc_id) {
return 1;
}
} }
/* Matching reference */
return 0; return 0;
} }
inline struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(eNB_mme_desc_t *eNB_desc_p, inline struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
uint32_t assoc_id) s1ap_eNB_instance_t *instance_p,
int32_t assoc_id, uint16_t cnx_id)
{ {
struct s1ap_eNB_mme_data_s temp; struct s1ap_eNB_mme_data_s temp;
struct s1ap_eNB_mme_data_s *found;
memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s)); memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s));
temp.sctp_data.assoc_id = assoc_id; temp.assoc_id = assoc_id;
temp.cnx_id = cnx_id;
if (instance_p == NULL) {
STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
s1ap_eNB_entries)
{
found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
if (found != NULL) {
return found;
}
}
} else {
return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
}
return RB_FIND(s1ap_mme_map, &eNB_desc_p->s1ap_mme_head, &temp); return NULL;
} }
int s1ap_run(eNB_mme_desc_t *eNB_desc_p) // int s1ap_run(eNB_mme_desc_t *eNB_desc_p)
// {
// int ret = 0;
// struct s1ap_eNB_mme_data_s *mme_p;
//
// DevAssert(eNB_desc_p != NULL);
//
// RB_FOREACH(mme_p, s1ap_mme_map, &eNB_desc_p->s1ap_mme_head) {
// struct sctp_queue_item_s *item_p;
//
// /* Run the SCTP part for each MME */
// sctp_run(&mme_p->sctp_data);
//
// S1AP_DEBUG("Entering s1ap_run for eNB %d: %d packet(s) to handle\n",
// eNB_desc_p->eNB_id, mme_p->sctp_data.queue_length);
//
// /* Handle every message in the queue */
// TAILQ_FOREACH(item_p, &mme_p->sctp_data.sctp_queue, entry) {
// /* Handle the message in S1AP */
// s1ap_eNB_handle_message(eNB_desc_p, item_p);
// /* Remove the packet from the list and update data */
// TAILQ_REMOVE(&mme_p->sctp_data.sctp_queue, item_p, entry);
// ret += item_p->length;
// mme_p->sctp_data.queue_size -= item_p->length;
// mme_p->sctp_data.queue_length--;
// /* Deallocate memory as the message has been handled */
// free(item_p->buffer);
// free(item_p);
// }
// }
// return ret;
// }
static s1ap_eNB_instance_t *s1ap_eNB_get_instance(uint8_t mod_id)
{ {
int ret = 0; s1ap_eNB_instance_t *temp = NULL;
struct s1ap_eNB_mme_data_s *mme_p;
STAILQ_FOREACH(temp, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
DevAssert(eNB_desc_p != NULL); s1ap_eNB_entries)
{
RB_FOREACH(mme_p, s1ap_mme_map, &eNB_desc_p->s1ap_mme_head) { if (temp->mod_id == mod_id) {
struct sctp_queue_item_s *item_p; /* Matching occurence */
return temp;
/* Run the SCTP part for each MME */
sctp_run(&mme_p->sctp_data);
S1AP_DEBUG("Entering s1ap_run for eNB %d: %d packet(s) to handle\n",
eNB_desc_p->eNB_id, mme_p->sctp_data.queue_length);
/* Handle every message in the queue */
TAILQ_FOREACH(item_p, &mme_p->sctp_data.sctp_queue, entry) {
/* Handle the message in S1AP */
s1ap_eNB_handle_message(eNB_desc_p, item_p);
/* Remove the packet from the list and update data */
TAILQ_REMOVE(&mme_p->sctp_data.sctp_queue, item_p, entry);
ret += item_p->length;
mme_p->sctp_data.queue_size -= item_p->length;
mme_p->sctp_data.queue_length--;
/* Deallocate memory as the message has been handled */
free(item_p->buffer);
free(item_p);
} }
} }
return ret;
return NULL;
} }
int s1ap_eNB_init(eNB_mme_desc_t *eNB_desc_p, static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
char **local_ip_addr, int nb_local_ip, net_ip_address_t *mme_ip_address,
char **remote_ip_addr, int nb_remote_ip) net_ip_address_t *local_ip_addr)
{ {
int i; MessageDef *message_p;
sctp_data_t sctp_data; sctp_new_association_req_t *sctp_new_association_req_p;
char hostname[30]; s1ap_eNB_mme_data_t *s1ap_mme_data_p;
DevAssert(eNB_desc_p != NULL); DevAssert(instance_p != NULL);
DevAssert(mme_ip_address != NULL);
if (eNB_desc_p->eNB_id >= (1 << 20)) message_p = itti_alloc_new_message(TASK_S1AP, SCTP_NEW_ASSOCIATION_REQ);
S1AP_WARN("eNB_id exceed limit of 20 bits...\n");
if (gethostname(hostname, sizeof(hostname)) == -1) { sctp_new_association_req_p = &message_p->msg.sctp_new_association_req;
hostname[0] = '\0';
}
/* Set the eNB name */ sctp_new_association_req_p->port = S1AP_PORT_NUMBER;
snprintf(eNB_desc_p->eNB_name, S1AP_ENB_NAME_LENGTH_MAX, sctp_new_association_req_p->ppid = S1AP_SCTP_PPID;
ENB_NAME " %s %u", hostname, eNB_desc_p->eNB_id & 0xFFFFF);
S1AP_DEBUG("Initializing S1AP layer for eNB %u\n", memcpy(&sctp_new_association_req_p->remote_address, mme_ip_address,
eNB_desc_p->eNB_id); sizeof(*mme_ip_address));
/* TODO: RRM configuration... */ /* Create new MME descriptor */
eNB_desc_p->tac = ENB_TAC; s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p));
eNB_desc_p->mcc = ENB_MCC; DevAssert(s1ap_mme_data_p != NULL);
eNB_desc_p->mnc = ENB_MNC;
RB_INIT(&eNB_desc_p->s1ap_mme_head); s1ap_mme_data_p->cnx_id = s1ap_eNB_internal_data.global_cnx_id;
RB_INIT(&eNB_desc_p->s1ap_ue_head); sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
s1ap_eNB_internal_data.global_cnx_id++;
memset(&sctp_data, 0, sizeof(sctp_data_t)); s1ap_mme_data_p->assoc_id = -1;
s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
for (i = 0; i < nb_remote_ip; i++) STAILQ_INIT(&s1ap_mme_data_p->served_gummei);
{
/* Connecting eNB to provided MME IP address and port */
if (sctp_connect_to_remote_host(local_ip_addr, nb_local_ip,
remote_ip_addr[i], S1AP_PORT_NUMBER,
SOCK_STREAM, &sctp_data) <= 0)
{
S1AP_ERROR("Failed to connect to %s:%d\n",
remote_ip_addr[i], S1AP_PORT_NUMBER);
return -1;
} else {
struct s1ap_eNB_mme_data_s *mme_assoc_p;
struct s1ap_eNB_mme_data_s *collision_p;
mme_assoc_p = calloc(1, sizeof(struct s1ap_eNB_mme_data_s)); /* Insert the new descriptor in list of known MME
mme_assoc_p->nextstream = 1; * but not yet associated.
*/
RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p);
memcpy(&mme_assoc_p->sctp_data, &sctp_data, sizeof(sctp_data_t)); itti_send_msg_to_task(TASK_SCTP, INSTANCE_DEFAULT, message_p);
}
TAILQ_INIT(&mme_assoc_p->sctp_data.sctp_queue); void s1ap_eNB_handle_register_eNB(s1ap_register_eNB_t *s1ap_register_eNB)
{
s1ap_eNB_instance_t *new_instance;
uint8_t index;
if ((collision_p = RB_INSERT(s1ap_mme_map, &eNB_desc_p->s1ap_mme_head, DevAssert(s1ap_register_eNB != NULL);
mme_assoc_p)) != NULL) {
S1AP_WARN("Failed to add MME to the tree of associated MME\n");
free(mme_assoc_p);
return -1;
}
S1AP_DEBUG("[%d] Successfully added MME to the list of known host\n", /* Look if the provided mod id already exists
sctp_data.assoc_id); * If so notify user...
S1AP_DEBUG("[%d] Now tries to send S1 setup request\n", */
sctp_data.assoc_id); new_instance = s1ap_eNB_get_instance(s1ap_register_eNB->mod_id);
DevAssert(new_instance == NULL);
new_instance = calloc(1, sizeof(s1ap_eNB_instance_t));
DevAssert(new_instance != NULL);
RB_INIT(&new_instance->s1ap_ue_head);
RB_INIT(&new_instance->s1ap_mme_head);
/* Copy usefull parameters */
new_instance->mod_id = s1ap_register_eNB->mod_id;
new_instance->eNB_name = s1ap_register_eNB->eNB_name;
new_instance->eNB_id = s1ap_register_eNB->eNB_id;
new_instance->cell_type = s1ap_register_eNB->cell_type;
new_instance->tac = s1ap_register_eNB->tac;
new_instance->mcc = s1ap_register_eNB->mcc;
new_instance->mnc = s1ap_register_eNB->mnc;
new_instance->default_drx = s1ap_register_eNB->default_drx;
STAILQ_INSERT_TAIL(&s1ap_eNB_internal_data.s1ap_eNB_instances_head,
new_instance, s1ap_eNB_entries);
S1AP_DEBUG("Registered new eNB with mod_id %u and %s eNB id %u\n",
s1ap_register_eNB->mod_id,
s1ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
s1ap_register_eNB->eNB_id);
DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS,
S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0);
/* Trying to connect to provided list of MME ip address */
for (index = 0; index < s1ap_register_eNB->nb_mme; index++) {
s1ap_eNB_register_mme(new_instance, &s1ap_register_eNB->mme_ip_address[index],
&s1ap_register_eNB->enb_ip_address);
}
}
STAILQ_INIT(&mme_assoc_p->served_gummei); void s1ap_eNB_handle_sctp_association_resp(sctp_new_association_resp_t *sctp_new_association_resp)
if (s1ap_eNB_generate_s1_setup_request(eNB_desc_p, mme_assoc_p) == -1) {
{ s1ap_eNB_instance_t *instance_p;
exit(EXIT_FAILURE); s1ap_eNB_mme_data_t *s1ap_mme_data_p;
}
} DevAssert(sctp_new_association_resp != NULL);
instance_p = s1ap_eNB_get_instance(sctp_new_association_resp->mod_id);
DevAssert(instance_p != NULL);
s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1,
sctp_new_association_resp->ulp_cnx_id);
DevAssert(s1ap_mme_data_p != NULL);
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
S1AP_WARN("Received unsuccessful result for SCTP association (%u), mod_id %u, cnx_id %u\n",
sctp_new_association_resp->sctp_state,
sctp_new_association_resp->mod_id,
sctp_new_association_resp->ulp_cnx_id);
} }
S1AP_DEBUG("Initializing S1AP layer for eNB %d: DONE\n", eNB_desc_p->eNB_id); /* Update parameters */
return 0; s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id;
s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams;
s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
/* Prepare new S1 Setup Request */
s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p);
}
static
void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind)
{
DevAssert(sctp_data_ind != NULL);
s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream,
sctp_data_ind->buffer, sctp_data_ind->buffer_length);
free(sctp_data_ind->buffer);
}
void *s1ap_eNB_task(void *arg)
{
MessageDef *received_msg = NULL;
S1AP_DEBUG("Starting S1AP layer\n");
memset(&s1ap_eNB_internal_data, 0, sizeof(s1ap_eNB_internal_data));
STAILQ_INIT(&s1ap_eNB_internal_data.s1ap_eNB_instances_head);
itti_mark_task_ready(TASK_S1AP);
while (1) {
itti_receive_msg(TASK_S1AP, &received_msg);
switch (received_msg->header.messageId) {
case TERMINATE_MESSAGE:
itti_exit_task();
break;
case S1AP_REGISTER_ENB: {
/* Register a new eNB.
* in Virtual mode eNBs will be distinguished using the mod_id/
* Each eNB has to send an S1AP_REGISTER_ENB message with its
* own parameters.
*/
s1ap_eNB_handle_register_eNB(&received_msg->msg.s1ap_register_eNB);
} break;
case SCTP_NEW_ASSOCIATION_RESP: {
s1ap_eNB_handle_sctp_association_resp(&received_msg->msg.sctp_new_association_resp);
} break;
case SCTP_DATA_IND: {
s1ap_eNB_handle_sctp_data_ind(&received_msg->msg.sctp_data_ind);
} break;
default:
S1AP_ERROR("Received unhandled message with id %d\n",
received_msg->header.messageId);
break;
}
free(received_msg);
received_msg = NULL;
}
return NULL;
} }
static int s1ap_eNB_generate_s1_setup_request( static int s1ap_eNB_generate_s1_setup_request(
eNB_mme_desc_t *eNB_desc_p, s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p)
s1ap_eNB_mme_data_t *mme_assoc_p)
{ {
s1ap_message message; s1ap_message message;
S1SetupRequestIEs_t *s1SetupRequest_p; S1SetupRequestIEs_t *s1SetupRequest_p;
PLMNidentity_t plmnIdentity; PLMNidentity_t plmnIdentity;
SupportedTAs_Item_t ta; SupportedTAs_Item_t ta;
...@@ -208,39 +352,40 @@ static int s1ap_eNB_generate_s1_setup_request( ...@@ -208,39 +352,40 @@ static int s1ap_eNB_generate_s1_setup_request(
uint32_t len; uint32_t len;
int ret; int ret;
DevAssert(eNB_desc_p != NULL); DevAssert(instance_p != NULL);
DevAssert(mme_assoc_p != NULL); DevAssert(s1ap_mme_data_p != NULL);
memset(&message, 0, sizeof(s1ap_message)); memset(&message, 0, sizeof(s1ap_message));
message.direction = S1AP_PDU_PR_initiatingMessage; message.direction = S1AP_PDU_PR_initiatingMessage;
message.procedureCode = ProcedureCode_id_S1Setup; message.procedureCode = ProcedureCode_id_S1Setup;
message.criticality = Criticality_reject;
s1SetupRequest_p = &message.msg.s1SetupRequestIEs; s1SetupRequest_p = &message.msg.s1SetupRequestIEs;
memset((void *)&plmnIdentity, 0, sizeof(PLMNidentity_t)); memset((void *)&plmnIdentity, 0, sizeof(PLMNidentity_t));
memset((void *)&ta, 0, sizeof(SupportedTAs_Item_t)); memset((void *)&ta, 0, sizeof(SupportedTAs_Item_t));
mme_assoc_p->state = S1AP_ENB_STATE_WAITING; s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
s1SetupRequest_p->global_ENB_ID.eNB_ID.present = ENB_ID_PR_macroENB_ID; s1SetupRequest_p->global_ENB_ID.eNB_ID.present = ENB_ID_PR_macroENB_ID;
MACRO_ENB_ID_TO_BIT_STRING(eNB_desc_p->eNB_id, MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
&s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID); &s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID);
MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc, MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,
&s1SetupRequest_p->global_ENB_ID.pLMNidentity); &s1SetupRequest_p->global_ENB_ID.pLMNidentity);
INT16_TO_OCTET_STRING(eNB_desc_p->tac, &ta.tAC); INT16_TO_OCTET_STRING(instance_p->tac, &ta.tAC);
MCC_MNC_TO_TBCD(eNB_desc_p->mcc, eNB_desc_p->mnc, &plmnIdentity); MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, &plmnIdentity);
ASN_SEQUENCE_ADD(&ta.broadcastPLMNs.list, &plmnIdentity); ASN_SEQUENCE_ADD(&ta.broadcastPLMNs.list, &plmnIdentity);
ASN_SEQUENCE_ADD(&s1SetupRequest_p->supportedTAs.list, &ta); ASN_SEQUENCE_ADD(&s1SetupRequest_p->supportedTAs.list, &ta);
s1SetupRequest_p->defaultPagingDRX = PagingDRX_v64; s1SetupRequest_p->defaultPagingDRX = instance_p->default_drx;
if (eNB_desc_p->eNB_name != NULL) { if (instance_p->eNB_name != NULL) {
s1SetupRequest_p->presenceMask |= S1SETUPREQUESTIES_ENBNAME_PRESENT; s1SetupRequest_p->presenceMask |= S1SETUPREQUESTIES_ENBNAME_PRESENT;
OCTET_STRING_fromBuf(&s1SetupRequest_p->eNBname, eNB_desc_p->eNB_name, OCTET_STRING_fromBuf(&s1SetupRequest_p->eNBname, instance_p->eNB_name,
strlen(eNB_desc_p->eNB_name)); strlen(instance_p->eNB_name));
} }
if (s1ap_eNB_encode_pdu(&message, &buffer, &len) < 0) { if (s1ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
...@@ -248,165 +393,128 @@ static int s1ap_eNB_generate_s1_setup_request( ...@@ -248,165 +393,128 @@ static int s1ap_eNB_generate_s1_setup_request(
return -1; return -1;
} }
if ((ret = sctp_send_msg(&mme_assoc_p->sctp_data, S1AP_SCTP_PPID, 0, buffer, /* Non UE-Associated signalling -> stream = 0 */
len)) < 0) { s1ap_eNB_itti_send_sctp_data_req(s1ap_mme_data_p->assoc_id, buffer, len, 0);
S1AP_ERROR("Failed to send S1 setup request\n");
}
free(buffer);
return ret; return ret;
} }
int s1ap_eNB_generate_initial_UE_message(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_generate_initial_UE_message(eNB_mme_desc_t *eNB_desc_p,
s1ap_nas_first_req_t nas_req_p) // s1ap_nas_first_req_t nas_req_p)
{ // {
s1ap_message message; // s1ap_message message;
struct s1ap_eNB_mme_data_s *mme_desc_p; // struct s1ap_eNB_mme_data_s *mme_desc_p;
struct s1ap_eNB_ue_context_s *ue_desc_p; // struct s1ap_eNB_ue_context_s *ue_desc_p;
InitialUEMessageIEs_t *initial_ue_message_p; // InitialUEMessageIEs_t *initial_ue_message_p;
//
uint8_t *buffer; // uint8_t *buffer;
uint32_t length; // uint32_t length;
//
DevAssert(eNB_desc_p != NULL); // DevAssert(eNB_desc_p != NULL);
//
// memset(&message, 0, sizeof(s1ap_message));
//
// message.direction = S1AP_PDU_PR_initiatingMessage;
// message.procedureCode = ProcedureCode_id_initialUEMessage;
//
// initial_ue_message_p = &message.msg.initialUEMessageIEs;
//
// /* Select the MME corresponding to the provided GUMMEI.
// * If no MME corresponds to the GUMMEI, the function selects the MME with the
// * highest capacity.
// * In case eNB has no MME associated, the eNB should inform RRC and discard
// * this request.
// */
// if (nas_req_p.ue_identity.present == GUMMEI_PROVIDED) {
// mme_desc_p = s1ap_eNB_nnsf_select_mme_by_gummei(
// eNB_desc_p,
// nas_req_p.establishment_cause, nas_req_p.ue_identity.identity.gummei);
// } else {
// mme_desc_p = s1ap_eNB_nnsf_select_mme_by_mme_code(
// eNB_desc_p,
// nas_req_p.establishment_cause, nas_req_p.ue_identity.identity.s_tmsi.mme_code);
// }
// if (mme_desc_p == NULL) {
// 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.
// */
// if ((ue_desc_p = s1ap_eNB_allocate_new_UE_context()) == NULL) {
// return -1;
// }
//
// /* Keep a reference to the selected MME */
// ue_desc_p->mme_ref = mme_desc_p;
// ue_desc_p->rnti = nas_req_p.rnti;
//
// do {
// struct s1ap_eNB_ue_context_s *collision_p;
//
// /* Peek a random value for the eNB_ue_s1ap_id */
// ue_desc_p->eNB_ue_s1ap_id = (random() + random()) & 0x00ffffff;
// if ((collision_p = RB_INSERT(s1ap_ue_map, &eNB_desc_p->s1ap_ue_head, ue_desc_p))
// == NULL) {
// /* Break the loop as the id is not already used by another UE */
// break;
// }
// } while(1);
//
// initial_ue_message_p->eNB_UE_S1AP_ID = ue_desc_p->eNB_ue_s1ap_id;
// /* Prepare the NAS PDU */
// initial_ue_message_p->nas_pdu.buf = nas_req_p.nas_pdu.buffer;
// initial_ue_message_p->nas_pdu.size = nas_req_p.nas_pdu.length;
//
// /* Set the establishment cause according to those provided by RRC */
// DevCheck(nas_req_p.establishment_cause <= RRC_CAUSE_MAX,
// nas_req_p.establishment_cause, 0, 0);
// initial_ue_message_p->rrC_Establishment_Cause = nas_req_p.establishment_cause;
//
// if (nas_req_p.ue_identity.present == S_TMSI_PROVIDED) {
// initial_ue_message_p->presenceMask |= INITIALUEMESSAGEIES_S_TMSI_PRESENT;
//
// MME_CODE_TO_OCTET_STRING(nas_req_p.ue_identity.identity.s_tmsi.mme_code,
// &initial_ue_message_p->s_tmsi.mMEC);
// M_TMSI_TO_OCTET_STRING(nas_req_p.ue_identity.identity.s_tmsi.m_tmsi,
// &initial_ue_message_p->s_tmsi.m_TMSI);
// } else {
// initial_ue_message_p->presenceMask |= INITIALUEMESSAGEIES_GUMMEI_ID_PRESENT;
//
// MCC_MNC_TO_PLMNID(nas_req_p.ue_identity.identity.gummei.mcc,
// nas_req_p.ue_identity.identity.gummei.mnc,
// &initial_ue_message_p->gummei_id.pLMN_Identity);
// MME_GID_TO_OCTET_STRING(nas_req_p.ue_identity.identity.gummei.mme_group_id,
// &initial_ue_message_p->gummei_id.mME_Group_ID);
// MME_CODE_TO_OCTET_STRING(nas_req_p.ue_identity.identity.gummei.mme_code,
// &initial_ue_message_p->gummei_id.mME_Code);
// }
//
// /* Assuming TAI is the TAI from the cell */
// INT16_TO_OCTET_STRING(eNB_desc_p->tac, &initial_ue_message_p->tai.tAC);
// MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc,
// &initial_ue_message_p->tai.pLMNidentity);
//
// /* Set the EUTRAN CGI
// * The cell identity is defined on 28 bits but as we use macro enb id,
// * we have to pad.
// */
// MACRO_ENB_ID_TO_CELL_IDENTITY(eNB_desc_p->eNB_id,
// &initial_ue_message_p->eutran_cgi.cell_ID);
// MCC_MNC_TO_TBCD(eNB_desc_p->mcc, eNB_desc_p->mnc,
// &initial_ue_message_p->eutran_cgi.pLMNidentity);
//
// if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
// /* Failed to encode message */
// return -1;
// }
//
// /* Update the current S1AP UE state */
// ue_desc_p->ue_state = S1AP_UE_WAITING_CSR;
//
// /* Send encoded message over sctp */
// return sctp_send_msg(&mme_desc_p->sctp_data, S1AP_SCTP_PPID, 1, buffer, length);
// }
memset(&message, 0, sizeof(s1ap_message));
message.direction = S1AP_PDU_PR_initiatingMessage;
message.procedureCode = ProcedureCode_id_initialUEMessage;
initial_ue_message_p = &message.msg.initialUEMessageIEs;
/* Select the MME corresponding to the provided GUMMEI.
* If no MME corresponds to the GUMMEI, the function selects the MME with the
* highest capacity.
* In case eNB has no MME associated, the eNB should inform RRC and discard
* this request.
*/
if (nas_req_p.ue_identity.present == GUMMEI_PROVIDED) {
mme_desc_p = s1ap_eNB_nnsf_select_mme_by_gummei(
eNB_desc_p,
nas_req_p.establishment_cause, nas_req_p.ue_identity.identity.gummei);
} else {
mme_desc_p = s1ap_eNB_nnsf_select_mme_by_mme_code(
eNB_desc_p,
nas_req_p.establishment_cause, nas_req_p.ue_identity.identity.s_tmsi.mme_code);
}
if (mme_desc_p == NULL) {
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.
*/
if ((ue_desc_p = s1ap_eNB_allocate_new_UE_context()) == NULL) {
return -1;
}
/* Keep a reference to the selected MME */
ue_desc_p->mme_ref = mme_desc_p;
ue_desc_p->rnti = nas_req_p.rnti;
do {
struct s1ap_eNB_ue_context_s *collision_p;
/* Peek a random value for the eNB_ue_s1ap_id */
ue_desc_p->eNB_ue_s1ap_id = (random() + random()) & 0x00ffffff;
if ((collision_p = RB_INSERT(s1ap_ue_map, &eNB_desc_p->s1ap_ue_head, ue_desc_p))
== NULL) {
/* Break the loop as the id is not already used by another UE */
break;
}
} while(1);
initial_ue_message_p->eNB_UE_S1AP_ID = ue_desc_p->eNB_ue_s1ap_id;
/* Prepare the NAS PDU */
initial_ue_message_p->nas_pdu.buf = nas_req_p.nas_pdu.buffer;
initial_ue_message_p->nas_pdu.size = nas_req_p.nas_pdu.length;
/* Set the establishment cause according to those provided by RRC */
DevCheck(nas_req_p.establishment_cause <= RRC_CAUSE_MAX,
nas_req_p.establishment_cause, 0, 0);
initial_ue_message_p->rrC_Establishment_Cause = nas_req_p.establishment_cause;
if (nas_req_p.ue_identity.present == S_TMSI_PROVIDED) {
initial_ue_message_p->presenceMask |= INITIALUEMESSAGEIES_S_TMSI_PRESENT;
MME_CODE_TO_OCTET_STRING(nas_req_p.ue_identity.identity.s_tmsi.mme_code,
&initial_ue_message_p->s_tmsi.mMEC);
M_TMSI_TO_OCTET_STRING(nas_req_p.ue_identity.identity.s_tmsi.m_tmsi,
&initial_ue_message_p->s_tmsi.m_TMSI);
} else {
initial_ue_message_p->presenceMask |= INITIALUEMESSAGEIES_GUMMEI_ID_PRESENT;
MCC_MNC_TO_PLMNID(nas_req_p.ue_identity.identity.gummei.mcc,
nas_req_p.ue_identity.identity.gummei.mnc,
&initial_ue_message_p->gummei_id.pLMN_Identity);
MME_GID_TO_OCTET_STRING(nas_req_p.ue_identity.identity.gummei.mme_group_id,
&initial_ue_message_p->gummei_id.mME_Group_ID);
MME_CODE_TO_OCTET_STRING(nas_req_p.ue_identity.identity.gummei.mme_code,
&initial_ue_message_p->gummei_id.mME_Code);
}
/* Assuming TAI is the TAI from the cell */
INT16_TO_OCTET_STRING(eNB_desc_p->tac, &initial_ue_message_p->tai.tAC);
MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc,
&initial_ue_message_p->tai.pLMNidentity);
/* Set the EUTRAN CGI
* The cell identity is defined on 28 bits but as we use macro enb id,
* we have to pad.
*/
MACRO_ENB_ID_TO_CELL_IDENTITY(eNB_desc_p->eNB_id,
&initial_ue_message_p->eutran_cgi.cell_ID);
MCC_MNC_TO_TBCD(eNB_desc_p->mcc, eNB_desc_p->mnc,
&initial_ue_message_p->eutran_cgi.pLMNidentity);
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
/* Failed to encode message */
return -1;
}
/* Update the current S1AP UE state */
ue_desc_p->ue_state = S1AP_UE_WAITING_CSR;
/* Send encoded message over sctp */
return sctp_send_msg(&mme_desc_p->sctp_data, S1AP_SCTP_PPID, 1, buffer, length);
}
int s1ap_eNB_handle_api_req(eNB_mme_desc_t *eNB_desc_p,
s1ap_rrc_api_req_t *api_req_p)
{
int ret = -1;
DevAssert(eNB_desc_p != NULL);
DevAssert(api_req_p != NULL);
switch(api_req_p->api_req) {
case S1AP_API_NAS_FIRST_REQ:
return s1ap_eNB_generate_initial_UE_message(eNB_desc_p,
api_req_p->msg.first_nas_req);
case S1AP_API_NAS_UPLINK:
return s1ap_eNB_nas_uplink(eNB_desc_p, &api_req_p->msg.nas_uplink);
case S1AP_API_UE_CAP_INFO_IND:
return s1ap_eNB_ue_capabilities(eNB_desc_p, &api_req_p->msg.ue_cap_info_ind);
case S1AP_API_INITIAL_CONTEXT_SETUP_RESP:
return s1ap_eNB_initial_ctxt_resp(eNB_desc_p, &api_req_p->msg.initial_ctxt_resp);
case S1AP_API_NAS_NON_DELIVERY_IND:
case S1AP_API_PATH_SWITCH_REQ:
case S1AP_API_INITIAL_CONTEXT_SETUP_FAIL:
case S1AP_API_E_RAB_SETUP_RESP:
case S1AP_API_E_RAB_MODIFY_RESP:
case S1AP_API_E_RAB_RELEASE_RESP:
case S1AP_API_RESET:
case S1AP_API_RESET_ACK:
S1AP_ERROR("This API type (%02x) is not implemented yet\n",
api_req_p->api_req);
break;
default:
S1AP_ERROR("Unknown API type %02x\n", api_req_p->api_req);
break;
}
return ret;
}
...@@ -31,101 +31,18 @@ ...@@ -31,101 +31,18 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include "tree.h" /** @defgroup _s1ap_impl_ S1AP Layer Reference Implementation for eNB
#include "queue.h" * @ingroup _ref_implementation_
* @{
#include "mme_sim.h" */
#include "s1ap_eNB_defs.h"
#ifndef S1AP_ENB_H_ #ifndef S1AP_ENB_H_
#define S1AP_ENB_H_ #define S1AP_ENB_H_
/* Served PLMN identity element */ void *s1ap_eNB_task(void *arg);
struct plmn_identity_s {
uint16_t mcc;
uint16_t mnc;
STAILQ_ENTRY(plmn_identity_s) next;
};
/* Served group id element */
struct served_group_id_s {
uint16_t mme_group_id;
STAILQ_ENTRY(served_group_id_s) next;
};
/* Served mme code for a particular MME */
struct mme_code_s {
uint8_t mme_code;
STAILQ_ENTRY(mme_code_s) next;
};
/* Served gummei element */
struct served_gummei_s {
/* Number of MME served PLMNs */
uint8_t nb_served_plmns;
/* List of served PLMNs by MME */
STAILQ_HEAD(served_plmns_s, plmn_identity_s) served_plmns;
/* Number of group id in list */
uint8_t nb_group_id;
/* Served group id list */
STAILQ_HEAD(served_group_ids_s, served_group_id_s) served_group_ids;
/* Number of MME code */
uint8_t nb_mme_code;
/* MME Code to uniquely identify an MME within an MME pool area */
STAILQ_HEAD(mme_codes_s, mme_code_s) mme_codes;
/* Next GUMMEI element */
STAILQ_ENTRY(served_gummei_s) next;
};
/* This structure describes association of a eNB to a MME */
typedef struct s1ap_eNB_mme_data_s {
/* This is the optional name provided by the MME */
char *mme_name;
/* Remote MME IP addr */
char *ip_addr;
/* List of served GUMMEI per MME. There is one GUMMEI per RAT with a max
* number of 8 RATs but in our case only one is used. The LTE related pool
* configuration is included on the first place in the list.
*/
STAILQ_HEAD(served_gummeis_s, served_gummei_s) served_gummei;
/* Relative processing capacity of an MME with respect to the other MMEs
* in the pool in order to load-balance MMEs within a pool as defined
* in TS 23.401.
*/
uint8_t relative_mme_capacity;
/* Current MME overload information (if any). */
s1ap_overload_state_t overload_state;
/* Current eNB->MME S1AP association state */
s1ap_eNB_state_t state;
/* SCTP related data for this MME */
sctp_data_t sctp_data;
/* Next usable stream for UE signalling */
int32_t nextstream;
/* MME descriptors tree, ordered by sctp assoc id */
RB_ENTRY(s1ap_eNB_mme_data_s) entry;
} s1ap_eNB_mme_data_t;
inline int s1ap_eNB_compare_assoc_id(
struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2);
/* Generate the tree management functions */
RB_PROTOTYPE(s1ap_mme_map, s1ap_eNB_mme_data_s, entry,
s1ap_eNB_compare_assoc_id);
struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(eNB_mme_desc_t *eNB_desc_p,
uint32_t assocId);
int s1ap_eNB_init(eNB_mme_desc_t *eNB_desc_p,
char *local_ip_addr[], int nb_local_ip,
char *remote_ip_addr[], int nb_remote_ip);
#endif /* S1AP_ENB_H_ */ #endif /* S1AP_ENB_H_ */
/**
* @}
*/
...@@ -106,7 +106,8 @@ static int s1ap_eNB_decode_unsuccessful_outcome(s1ap_message *message, ...@@ -106,7 +106,8 @@ static int s1ap_eNB_decode_unsuccessful_outcome(s1ap_message *message,
return -1; return -1;
} }
int s1ap_eNB_decode_pdu(s1ap_message *message, uint8_t *buffer, uint32_t length) int s1ap_eNB_decode_pdu(s1ap_message *message, const uint8_t * const buffer,
const uint32_t length)
{ {
S1AP_PDU_t pdu; S1AP_PDU_t pdu;
S1AP_PDU_t *pdu_p = &pdu; S1AP_PDU_t *pdu_p = &pdu;
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#ifndef S1AP_ENB_DECODER_H_ #ifndef S1AP_ENB_DECODER_H_
#define S1AP_ENB_DECODER_H_ #define S1AP_ENB_DECODER_H_
int s1ap_eNB_decode_pdu(s1ap_message *message, uint8_t *buffer, uint32_t length) int s1ap_eNB_decode_pdu(s1ap_message *message, const uint8_t * const buffer,
__attribute__ ((warn_unused_result)); const uint32_t length) __attribute__ ((warn_unused_result));
#endif /* S1AP_ENB_DECODER_H_ */ #endif /* S1AP_ENB_DECODER_H_ */
#ifndef S1AP_ENB_DEFAULT_VALUES_H_
#define S1AP_ENB_DEFAULT_VALUES_H_
#define ENB_TAC (0)
#define ENB_MCC (208)
#define ENB_MNC (34)
#define ENB_NAME "Eurecom ENB"
#define ENB_NAME_FORMAT (ENB_NAME" %u")
#define S1AP_PORT_NUMBER (36412)
#define S1AP_SCTP_PPID (18)
#define X2AP_PORT_NUMBER (36422)
#define X2AP_SCTP_PPID (27)
#define SCTP_OUT_STREAMS (64)
#define SCTP_IN_STREAMS (64)
#define SCTP_MAX_ATTEMPTS (5)
#define SCTP_RECV_BUFFER_SIZE (1024)
#endif /* S1AP_ENB_DEFAULT_VALUES_H_ */
...@@ -82,12 +82,12 @@ typedef enum { ...@@ -82,12 +82,12 @@ typedef enum {
S1AP_OVERLOAD_MAX, S1AP_OVERLOAD_MAX,
} s1ap_overload_state_t; } s1ap_overload_state_t;
typedef enum { // typedef enum {
PAGING_DRX_32 = 0x0, // PAGING_DRX_32 = 0x0,
PAGING_DRX_64 = 0x1, // PAGING_DRX_64 = 0x1,
PAGING_DRX_128 = 0x2, // PAGING_DRX_128 = 0x2,
PAGING_DRX_256 = 0x3, // PAGING_DRX_256 = 0x3,
} paging_drx_t; // } paging_drx_t;
typedef struct { typedef struct {
/* Octet string data */ /* Octet string data */
...@@ -176,161 +176,156 @@ typedef struct { ...@@ -176,161 +176,156 @@ typedef struct {
} identity; } identity;
} ue_identity_t; } ue_identity_t;
typedef struct { /* Served PLMN identity element */
/* The NAS First Req is the first message exchanged between RRC and S1AP struct plmn_identity_s {
* for an UE. uint16_t mcc;
* The rnti uniquely identifies an UE within a cell. Later the enb_ue_s1ap_id uint16_t mnc;
* will be the unique identifier used between RRC and S1AP. STAILQ_ENTRY(plmn_identity_s) next;
};
/* Served group id element */
struct served_group_id_s {
uint16_t mme_group_id;
STAILQ_ENTRY(served_group_id_s) next;
};
/* Served mme code for a particular MME */
struct mme_code_s {
uint8_t mme_code;
STAILQ_ENTRY(mme_code_s) next;
};
/* Served gummei element */
struct served_gummei_s {
/* Number of MME served PLMNs */
uint8_t nb_served_plmns;
/* List of served PLMNs by MME */
STAILQ_HEAD(served_plmns_s, plmn_identity_s) served_plmns;
/* Number of group id in list */
uint8_t nb_group_id;
/* Served group id list */
STAILQ_HEAD(served_group_ids_s, served_group_id_s) served_group_ids;
/* Number of MME code */
uint8_t nb_mme_code;
/* MME Code to uniquely identify an MME within an MME pool area */
STAILQ_HEAD(mme_codes_s, mme_code_s) mme_codes;
/* Next GUMMEI element */
STAILQ_ENTRY(served_gummei_s) next;
};
struct s1ap_eNB_instance_s;
/* This structure describes association of a eNB to a MME */
typedef struct s1ap_eNB_mme_data_s {
/* MME descriptors tree, ordered by sctp assoc id */
RB_ENTRY(s1ap_eNB_mme_data_s) entry;
/* This is the optional name provided by the MME */
char *mme_name;
/* List of served GUMMEI per MME. There is one GUMMEI per RAT with a max
* number of 8 RATs but in our case only one is used. The LTE related pool
* configuration is included on the first place in the list.
*/ */
uint16_t rnti; STAILQ_HEAD(served_gummeis_s, served_gummei_s) served_gummei;
rrc_establishment_cause_t establishment_cause; /* Relative processing capacity of an MME with respect to the other MMEs
nas_pdu_t nas_pdu; * in the pool in order to load-balance MMEs within a pool as defined
/* If this flag is set S1AP layer is expecting the GUMMEI. If = 0, * in TS 23.401.
* the temporary s-tmsi is used.
*/ */
ue_identity_t ue_identity; uint8_t relative_mme_capacity;
} s1ap_nas_first_req_t;
typedef struct { /* Current MME overload information (if any). */
unsigned eNB_ue_s1ap_id:24; s1ap_overload_state_t overload_state;
nas_pdu_t nas_pdu; /* Current eNB->MME S1AP association state */
} s1ap_nas_uplink_t; s1ap_eNB_state_t state;
typedef struct { /* Next usable stream for UE signalling */
nas_pdu_t nas_pdu; int32_t nextstream;
// cause_t cause;
} s1ap_nas_non_delivery_t;
typedef struct { /* Number of input/ouput streams */
uint16_t rnti; uint16_t in_streams;
unsigned eNB_ue_s1ap_id:24; uint16_t out_streams;
/* Number of e_rab to be setup in the list */ /* Connexion id used when SCTP association is not established yet */
uint8_t nb_of_e_rabs; uint16_t cnx_id;
/* list of e_rab to be setup by RRC layers */
e_rab_t **e_rab_param;
} s1ap_e_rab_setup_req_t,
s1ap_initial_ctxt_setup_req_t;
typedef struct { /* SCTP association id */
unsigned eNB_ue_s1ap_id:24; int32_t assoc_id;
ue_radio_cap_t ue_radio_cap;
} s1ap_ue_cap_info_ind_t;
typedef struct { /* Only meaningfull in virtual mode */
unsigned eNB_ue_s1ap_id:24; struct s1ap_eNB_instance_s *s1ap_eNB_instance;
} s1ap_eNB_mme_data_t;
/* 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;
/* Number of e_rab failed to be setup in list */
uint8_t nb_of_e_rabs_failed;
/* list of e_rabs that failed to be setup */
e_rab_failed_t *e_rabs_failed;
} s1ap_initial_ctxt_setup_resp_t;
typedef enum { typedef struct s1ap_eNB_instance_s {
/** RRC -> S1AP API **/ /* Next s1ap eNB association.
#define S1AP_API_REQ_IS_INPUT(x) (x & 0x10) * Only used for virtual mode.
/* RRC should use this api request for the first NAS message */
S1AP_API_NAS_FIRST_REQ = 0x10,
/* NAS messages with no context activation */
S1AP_API_NAS_UPLINK = 0x11,
/* When the eNB decides to not start the delivery of a NAS message that has
* been received over a UE-associated logical S1-connection or the eNB is
* unable to ensure that the message has been received by the UE, it shall
* report the non-delivery of this NAS message.
*/
S1AP_API_NAS_NON_DELIVERY_IND = 0x12,
/* This message is sent by the eNB to request the MME to switch DL GTP
* tunnel termination point(s) from one end-point to another.
*/
S1AP_API_PATH_SWITCH_REQ = 0x13,
/* This message is used to report the outcome of the request from the
* S1AP_API_NAS_INITIAL_CONTEXT_SETUP_REQ API request.
*/
S1AP_API_INITIAL_CONTEXT_SETUP_RESP = 0x14,
/* This message is used to report the unsuccessfull outcome of the request
* from the S1AP_API_NAS_INITIAL_CONTEXT_SETUP_REQ API request.
*/
S1AP_API_INITIAL_CONTEXT_SETUP_FAIL = 0x15,
/* This message is used to report the outcome of the request from the
* S1AP_API_INITIAL_CONTEXT_SETUP_REQ API request.
*/
S1AP_API_E_RAB_SETUP_RESP = 0x16,
/* This message is used to report the outcome of the request from the
* S1AP_API_E_RAB_SETUP_REQ API request.
*/
S1AP_API_E_RAB_MODIFY_RESP = 0x17,
/* This message is used to report the outcome of the request from the
* S1AP_API_E_RAB_MODIFY_REQ API request.
*/
S1AP_API_E_RAB_RELEASE_RESP = 0x18,
/* The purpose of the UE Capability Info Indication procedure is to enable
* the eNB to provide to the MME UE capability-related information.
*/
S1AP_API_UE_CAP_INFO_IND = 0x19,
/** S1AP -> RRC API **/
#define S1AP_API_REQ_IS_OUTPUT(x) (x & 0x20)
/* S1AP layer received a valid downlink info transfer message */
S1AP_API_NAS_DOWNLINK = 0x20,
/* The purpose of the Initial Context Setup procedure is to establish the
* necessary overall initial UE Context including ERAB context, the Security
* Key, Handover Restriction List, UE Radio capability and UE Security
* Capabilities etc.
*/ */
S1AP_API_NAS_INITIAL_CONTEXT_SETUP_REQ = 0x21, STAILQ_ENTRY(s1ap_eNB_instance_s) s1ap_eNB_entries;
/* The purpose of the E-RAB Setup procedure is to assign resources on Uu and
* S1 for one or several E-RABs and to setup corresponding Data Radio /* Tree of S1AP MME associations ordered by association ID */
* Bearers for a given UE. RB_HEAD(s1ap_mme_map, s1ap_eNB_mme_data_s) s1ap_mme_head;
*/
S1AP_API_E_RAB_SETUP_REQ = 0x22, /* TODO: add a map ordered by relative MME capacity */
/* This message is sent by the MME and is used to request the eNB to modify
* the Data Radio Bearers and the allocated resources on Uu and S1 for one /* Tree of UE ordered by eNB_ue_s1ap_id's */
* or several E-RABs. RB_HEAD(s1ap_ue_map, s1ap_eNB_ue_context_s) s1ap_ue_head;
*/
S1AP_API_E_RAB_MODIFY_REQ = 0x23, /* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
/* This message is sent by the MME and is used to request the eNB to release uint8_t mod_id;
* allocated resources on Uu and S1 for one or several E-RABs.
/* Displayable name of eNB */
char *eNB_name;
/* Unique eNB_id to identify the eNB within EPC.
* In our case the eNB is a macro eNB so the id will be 20 bits long.
* For Home eNB id, this field should be 28 bits long.
*/ */
S1AP_API_E_RAB_RELEASE_REQ = 0x24, uint32_t eNB_id;
/* The type of the cell */
/** S1AP <-> RRC API **/ enum cell_type_e cell_type;
/** Messages below are bi-directionnal and can be triggered by both RRC and
* S1AP. /* Tracking area code */
**/ uint16_t tac;
#define S1AP_API_REQ_IS_BIDIR(x) (x & 0x40)
/* At reception of RESET message, the eNB (or MME) shall release all /* Mobile Country Code
* allocated resources on S1 and Uu related to the UE association(s) * Mobile Network Code
* indicated explicitly or implicitly in the RESET message and remove the
* indicated UE contexts including S1AP ID.
*/ */
S1AP_API_RESET = 0x40, uint16_t mcc;
S1AP_API_RESET_ACK = 0x41, uint16_t mnc;
} s1ap_rrc_api_req_type_t;
/* Default Paging DRX of the eNB as defined in TS 36.304 */
paging_drx_t default_drx;
} s1ap_eNB_instance_t;
typedef struct { typedef struct {
/* The API request type */ /* List of served eNBs
s1ap_rrc_api_req_type_t api_req; * Only used for virtual mode
union { */
/** RRC -> S1AP requests **/ STAILQ_HEAD(s1ap_eNB_instances_head_s, s1ap_eNB_instance_s) s1ap_eNB_instances_head;
s1ap_nas_first_req_t first_nas_req; /* Nb of registered eNBs */
s1ap_nas_uplink_t nas_uplink; uint8_t nb_registered_eNBs;
s1ap_initial_ctxt_setup_resp_t initial_ctxt_resp;
s1ap_nas_non_delivery_t nas_non_delivery; /* Generate a unique connexion id used between S1AP and SCTP */
s1ap_ue_cap_info_ind_t ue_cap_info_ind; uint16_t global_cnx_id;
/** S1AP -> RRC requests **/ } s1ap_eNB_internal_data_t;
s1ap_e_rab_setup_req_t e_rab_setup_req;
s1ap_initial_ctxt_setup_req_t initial_ctxt_setup_req; inline int s1ap_eNB_compare_assoc_id(
} msg; struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2);
} s1ap_rrc_api_req_t;
/* Generate the tree management functions */
/* Callback notifier. RB_PROTOTYPE(s1ap_mme_map, s1ap_eNB_mme_data_s, entry,
* Called when a new event has to be notified between S1AP -> RRC s1ap_eNB_compare_assoc_id);
*/
typedef int (*rrc_event_notify_t)(s1ap_rrc_api_req_t *api_req); inline struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
s1ap_eNB_instance_t *instance_p,
int32_t assoc_id, uint16_t cnx_id);
int s1ap_eNB_init(s1ap_eNB_instance_t *eNB_desc_p,
char *local_ip_addr[], int nb_local_ip,
char *remote_ip_addr[], int nb_remote_ip);
#endif /* S1AP_ENB_DEFS_H_ */ #endif /* S1AP_ENB_DEFS_H_ */
...@@ -37,9 +37,12 @@ ...@@ -37,9 +37,12 @@
#include <stdint.h> #include <stdint.h>
#include "intertask_interface.h"
#include "s1ap_common.h" #include "s1ap_common.h"
#include "s1ap_ies_defs.h" #include "s1ap_ies_defs.h"
#include "s1ap_eNB.h" // #include "s1ap_eNB.h"
#include "s1ap_eNB_defs.h"
#include "s1ap_eNB_handlers.h" #include "s1ap_eNB_handlers.h"
#include "s1ap_eNB_decoder.h" #include "s1ap_eNB_decoder.h"
...@@ -47,12 +50,22 @@ ...@@ -47,12 +50,22 @@
#include "s1ap_eNB_trace.h" #include "s1ap_eNB_trace.h"
#include "s1ap_eNB_nas_procedures.h" #include "s1ap_eNB_nas_procedures.h"
#include "eNB_default_values.h" #include "s1ap_eNB_default_values.h"
#include "conversions.h" #include "conversions.h"
//Forward declaration static
struct s1ap_message_s; int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
static
int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
/* 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] = {
...@@ -73,7 +86,7 @@ s1ap_message_decoded_callback messages_callback[][3] = { ...@@ -73,7 +86,7 @@ s1ap_message_decoded_callback messages_callback[][3] = {
{ 0, 0, 0 }, /* Reset */ { 0, 0, 0 }, /* Reset */
{ 0, 0, 0 }, /* ErrorIndication */ { 0, 0, 0 }, /* ErrorIndication */
{ 0, 0, 0 }, /* NASNonDeliveryIndication */ { 0, 0, 0 }, /* NASNonDeliveryIndication */
{ 0, s1ap_eNB_handle_s1_setup_response, 0 }, /* S1Setup */ { 0, s1ap_eNB_handle_s1_setup_response, s1ap_eNB_handle_s1_setup_failure }, /* S1Setup */
{ 0, 0, 0 }, /* UEContextReleaseRequest */ { 0, 0, 0 }, /* UEContextReleaseRequest */
{ 0, 0, 0 }, /* DownlinkS1cdma2000tunneling */ { 0, 0, 0 }, /* DownlinkS1cdma2000tunneling */
{ 0, 0, 0 }, /* UplinkS1cdma2000tunneling */ { 0, 0, 0 }, /* UplinkS1cdma2000tunneling */
...@@ -115,23 +128,16 @@ static const char *direction2String[] = { ...@@ -115,23 +128,16 @@ static const char *direction2String[] = {
"UnSuccessfull outcome", /* successfull outcome */ "UnSuccessfull outcome", /* successfull outcome */
}; };
int s1ap_eNB_handle_message(eNB_mme_desc_t *eNB_desc_p, int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
sctp_queue_item_t *packet_p) const uint8_t * const data, const uint32_t data_length)
{ {
struct s1ap_message_s message; struct s1ap_message_s message;
DevAssert(eNB_desc_p != NULL); DevAssert(data != NULL);
DevAssert(packet_p != NULL);
if (packet_p->ppid != S1AP_SCTP_PPID) {
S1AP_ERROR("Received data on unexpected PPID %d, expecting %d\n",
packet_p->ppid, S1AP_SCTP_PPID);
return -1;
}
memset(&message, 0, sizeof(struct s1ap_message_s)); memset(&message, 0, sizeof(struct s1ap_message_s));
if (s1ap_eNB_decode_pdu(&message, packet_p->buffer, packet_p->length) < 0) { if (s1ap_eNB_decode_pdu(&message, data, data_length) < 0) {
S1AP_ERROR("Failed to decode PDU\n"); S1AP_ERROR("Failed to decode PDU\n");
return -1; return -1;
} }
...@@ -140,7 +146,7 @@ int s1ap_eNB_handle_message(eNB_mme_desc_t *eNB_desc_p, ...@@ -140,7 +146,7 @@ int s1ap_eNB_handle_message(eNB_mme_desc_t *eNB_desc_p,
s1ap_message_decoded_callback)) s1ap_message_decoded_callback))
|| (message.direction > S1AP_PDU_PR_unsuccessfulOutcome)) { || (message.direction > S1AP_PDU_PR_unsuccessfulOutcome)) {
S1AP_ERROR("[SCTP %d] Either procedureCode %d or direction %d exceed expected\n", S1AP_ERROR("[SCTP %d] Either procedureCode %d or direction %d exceed expected\n",
packet_p->assoc_id, message.procedureCode, message.direction); assoc_id, message.procedureCode, message.direction);
return -1; return -1;
} }
/* No handler present. /* No handler present.
...@@ -148,40 +154,56 @@ int s1ap_eNB_handle_message(eNB_mme_desc_t *eNB_desc_p, ...@@ -148,40 +154,56 @@ int s1ap_eNB_handle_message(eNB_mme_desc_t *eNB_desc_p,
*/ */
if (messages_callback[message.procedureCode][message.direction-1] == NULL) { if (messages_callback[message.procedureCode][message.direction-1] == NULL) {
S1AP_ERROR("[SCTP %d] No handler for procedureCode %d in %s\n", S1AP_ERROR("[SCTP %d] No handler for procedureCode %d in %s\n",
packet_p->assoc_id, message.procedureCode, assoc_id, message.procedureCode,
direction2String[message.direction]); direction2String[message.direction]);
return -1; return -1;
} }
/* Calling the right handler */ /* Calling the right handler */
return (*messages_callback[message.procedureCode][message.direction-1])( return (*messages_callback[message.procedureCode][message.direction-1])
eNB_desc_p, packet_p, &message); (assoc_id, stream, &message);
} }
int s1ap_eNB_handle_s1_setup_response(eNB_mme_desc_t *eNB_desc_p, int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
sctp_queue_item_t *packet_p, uint32_t stream,
struct s1ap_message_s *message_p)
{
/* S1 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
assoc_id, stream);
}
S1AP_DEBUG("Received s1 setup failure for MME... please check your parameters\n");
return 0;
}
// int s1ap_eNB_handle_s1_setup_response(eNB_mme_desc_t *eNB_desc_p,
// sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p)
static
int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p) struct s1ap_message_s *message_p)
{ {
S1SetupResponseIEs_t *s1SetupResponse_p; S1SetupResponseIEs_t *s1SetupResponse_p;
s1ap_eNB_mme_data_t *mme_desc_p; s1ap_eNB_mme_data_t *mme_desc_p;
int i; int i;
DevAssert(eNB_desc_p != NULL);
DevAssert(packet_p != NULL);
DevAssert(message_p != NULL); DevAssert(message_p != NULL);
s1SetupResponse_p = &message_p->msg.s1SetupResponseIEs; s1SetupResponse_p = &message_p->msg.s1SetupResponseIEs;
/* S1 Setup Response == Non UE-related procedure -> stream 0 */ /* S1 Setup Response == Non UE-related procedure -> stream 0 */
if (packet_p->local_stream != 0) { if (stream != 0) {
S1AP_ERROR("[SCTP %d] Received s1 setup response on stream != 0 (%d)\n", S1AP_ERROR("[SCTP %d] Received s1 setup response on stream != 0 (%d)\n",
packet_p->assoc_id, packet_p->local_stream); assoc_id, stream);
return -1; return -1;
} }
if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) { if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing " S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
"MME context\n", packet_p->assoc_id); "MME context\n", assoc_id);
return -1; return -1;
} }
...@@ -255,128 +277,136 @@ int s1ap_eNB_handle_s1_setup_response(eNB_mme_desc_t *eNB_desc_p, ...@@ -255,128 +277,136 @@ int s1ap_eNB_handle_s1_setup_response(eNB_mme_desc_t *eNB_desc_p,
*/ */
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
/* We call back our self // /* We call back our self
* -> generate a dummy initial UE message // * -> generate a dummy initial UE message
*/ // */
{ // {
extern int s1ap_eNB_handle_api_req(eNB_mme_desc_t *eNB_desc_p, // extern int s1ap_eNB_handle_api_req(eNB_mme_desc_t *eNB_desc_p,
s1ap_rrc_api_req_t *api_req_p); // s1ap_rrc_api_req_t *api_req_p);
s1ap_rrc_api_req_t api_req; // s1ap_rrc_api_req_t api_req;
s1ap_nas_first_req_t *nas_req_p; // s1ap_nas_first_req_t *nas_req_p;
//
memset(&api_req, 0, sizeof(s1ap_rrc_api_req_t)); // memset(&api_req, 0, sizeof(s1ap_rrc_api_req_t));
//
nas_req_p = &api_req.msg.first_nas_req; // nas_req_p = &api_req.msg.first_nas_req;
api_req.api_req = S1AP_API_NAS_FIRST_REQ; // api_req.api_req = S1AP_API_NAS_FIRST_REQ;
//
nas_req_p->rnti = 0xC03A; // nas_req_p->rnti = 0xC03A;
nas_req_p->establishment_cause = RRC_CAUSE_MO_DATA; // nas_req_p->establishment_cause = RRC_CAUSE_MO_DATA;
nas_req_p->ue_identity.present = GUMMEI_PROVIDED; // nas_req_p->ue_identity.present = GUMMEI_PROVIDED;
//
nas_req_p->ue_identity.identity.gummei.mcc = 208; // nas_req_p->ue_identity.identity.gummei.mcc = 208;
nas_req_p->ue_identity.identity.gummei.mnc = 34; // nas_req_p->ue_identity.identity.gummei.mnc = 34;
nas_req_p->ue_identity.identity.gummei.mme_code = 0; // nas_req_p->ue_identity.identity.gummei.mme_code = 0;
nas_req_p->ue_identity.identity.gummei.mme_group_id = 0; // nas_req_p->ue_identity.identity.gummei.mme_group_id = 0;
//
/* NAS Attach request with IMSI */ // /* NAS Attach request with IMSI */
uint8_t nas_attach_req_imsi[] = // uint8_t nas_attach_req_imsi[] =
{ // {
0x07, 0x41, // 0x07, 0x41,
/* EPS Mobile identity = IMSI */ // /* EPS Mobile identity = IMSI */
0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87, // 0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
0xF9, // 0xF9,
/* End of EPS Mobile Identity */ // /* End of EPS Mobile Identity */
0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03, // 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, // 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, // 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, // 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
0x01, 0x27, 0x11, // 0x01, 0x27, 0x11,
}; // };
//
/* NAS Attach request with GUTI */ // /* NAS Attach request with GUTI */
uint8_t nas_attach_req_guti[] = // uint8_t nas_attach_req_guti[] =
{ // {
0x07, 0x41, // 0x07, 0x41,
/* EPS Mobile identity = IMSI */ // /* EPS Mobile identity = IMSI */
0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00, // 0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
0xDA, 0x1F, // 0xDA, 0x1F,
/* End of EPS Mobile Identity */ // /* End of EPS Mobile Identity */
0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03, // 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, // 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, // 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, // 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
0x01, 0x27, 0x11, // 0x01, 0x27, 0x11,
}; // };
//
nas_req_p->nas_pdu.buffer = nas_attach_req_guti; // nas_req_p->nas_pdu.buffer = nas_attach_req_guti;
nas_req_p->nas_pdu.length = sizeof(nas_attach_req_guti); // nas_req_p->nas_pdu.length = sizeof(nas_attach_req_guti);
//
s1ap_eNB_handle_api_req(eNB_desc_p, &api_req); // s1ap_eNB_handle_api_req(eNB_desc_p, &api_req);
} // }
return 0; return 0;
} }
int s1ap_eNB_handle_initial_context_request(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_handle_initial_context_request(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p, // sctp_queue_item_t *packet_p,
struct s1ap_message_s *message_p) // struct s1ap_message_s *message_p)
static
int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p)
{ {
s1ap_eNB_mme_data_t *mme_desc_p; s1ap_eNB_mme_data_t *mme_desc_p;
s1ap_eNB_ue_context_t *ue_desc_p; s1ap_eNB_ue_context_t *ue_desc_p;
InitialContextSetupRequestIEs_t *initialContextSetupRequest_p; InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
DevAssert(eNB_desc_p != NULL); // DevAssert(eNB_desc_p != NULL);
DevAssert(packet_p != NULL);
DevAssert(message_p != NULL); DevAssert(message_p != NULL);
initialContextSetupRequest_p = &message_p->msg.initialContextSetupRequestIEs; initialContextSetupRequest_p = &message_p->msg.initialContextSetupRequestIEs;
DevAssert(packet_p->local_stream > 0); /* Initial context request = UE-related procedure -> stream != 0 */
if (stream == 0) {
if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) { S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream = 0 (%d)\n",
S1AP_ERROR("[SCTP %d] Received initial context setup request for non " assoc_id, stream);
"existing MME context\n", packet_p->assoc_id);
return -1;
}
if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) {
S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
"existing UE context\n", packet_p->assoc_id);
return -1; return -1;
} }
ue_desc_p->mme_ue_s1ap_id = initialContextSetupRequest_p->mme_ue_s1ap_id; // if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, assoc_id)) == NULL) {
// S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
{ // "existing MME context\n", packet_p->assoc_id);
int i; // return -1;
// }
extern int s1ap_eNB_handle_api_req(eNB_mme_desc_t *eNB_desc_p, // if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
s1ap_rrc_api_req_t *api_req_p); // initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) {
// S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
s1ap_rrc_api_req_t api_req; // "existing UE context\n", packet_p->assoc_id);
s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p; // return -1;
// }
memset(&api_req, 0, sizeof(s1ap_rrc_api_req_t)); ue_desc_p->mme_ue_s1ap_id = initialContextSetupRequest_p->mme_ue_s1ap_id;
initial_ctxt_resp_p = &api_req.msg.initial_ctxt_resp;
api_req.api_req = S1AP_API_INITIAL_CONTEXT_SETUP_RESP;
initial_ctxt_resp_p->eNB_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id;
initial_ctxt_resp_p->e_rabs_failed = 0;
initial_ctxt_resp_p->nb_of_e_rabs
= initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.e_RABToBeSetupItemCtxtSUReq.count;
for (i = 0; i < initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.e_RABToBeSetupItemCtxtSUReq.count; i++)
{
struct E_RABToBeSetupItemCtxtSUReq_s *item;
item = (struct E_RABToBeSetupItemCtxtSUReq_s *)initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.e_RABToBeSetupItemCtxtSUReq.array[i];
initial_ctxt_resp_p->e_rabs = realloc(initial_ctxt_resp_p->e_rabs, i * sizeof(e_rab_setup_t));
initial_ctxt_resp_p->e_rabs[i].e_rab_id = 5;
}
s1ap_eNB_handle_api_req(eNB_desc_p, &api_req); // {
} // int i;
//
// extern int s1ap_eNB_handle_api_req(eNB_mme_desc_t *eNB_desc_p,
// s1ap_rrc_api_req_t *api_req_p);
//
// s1ap_rrc_api_req_t api_req;
// s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p;
//
// memset(&api_req, 0, sizeof(s1ap_rrc_api_req_t));
//
// initial_ctxt_resp_p = &api_req.msg.initial_ctxt_resp;
// api_req.api_req = S1AP_API_INITIAL_CONTEXT_SETUP_RESP;
//
// initial_ctxt_resp_p->eNB_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id;
// initial_ctxt_resp_p->e_rabs_failed = 0;
// initial_ctxt_resp_p->nb_of_e_rabs
// = initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.e_RABToBeSetupItemCtxtSUReq.count;
// for (i = 0; i < initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.e_RABToBeSetupItemCtxtSUReq.count; i++)
// {
// struct E_RABToBeSetupItemCtxtSUReq_s *item;
// item = (struct E_RABToBeSetupItemCtxtSUReq_s *)initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.e_RABToBeSetupItemCtxtSUReq.array[i];
// initial_ctxt_resp_p->e_rabs = realloc(initial_ctxt_resp_p->e_rabs, i * sizeof(e_rab_setup_t));
// initial_ctxt_resp_p->e_rabs[i].e_rab_id = 5;
//
// }
//
// s1ap_eNB_handle_api_req(eNB_desc_p, &api_req);
// }
return 0; return 0;
} }
...@@ -31,19 +31,7 @@ ...@@ -31,19 +31,7 @@
#ifndef S1AP_ENB_HANDLERS_H_ #ifndef S1AP_ENB_HANDLERS_H_
#define S1AP_ENB_HANDLERS_H_ #define S1AP_ENB_HANDLERS_H_
int s1ap_eNB_handle_message(eNB_mme_desc_t *eNB_desc_p, int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
sctp_queue_item_t *packet_p); const uint8_t * const data, const uint32_t data_length);
int s1ap_eNB_handle_s1_setup_response(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p,
struct s1ap_message_s *message);
int s1ap_eNB_handle_s1_setup_failure(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p,
struct s1ap_message_s *message);
int s1ap_eNB_handle_initial_context_request(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p,
struct s1ap_message_s *message_p);
#endif /* S1AP_ENB_HANDLERS_H_ */ #endif /* S1AP_ENB_HANDLERS_H_ */
#include "intertask_interface.h"
#include "s1ap_eNB_itti_messaging.h"
void s1ap_eNB_itti_send_sctp_data_req(int32_t assoc_id, uint8_t *buffer,
uint32_t buffer_length, uint16_t stream)
{
MessageDef *message_p;
sctp_data_req_t *sctp_data_req;
message_p = itti_alloc_new_message(TASK_S1AP, SCTP_DATA_REQ);
sctp_data_req = &message_p->msg.sctp_data_req;
sctp_data_req->assoc_id = assoc_id;
sctp_data_req->buffer = buffer;
sctp_data_req->buffer_length = buffer_length;
sctp_data_req->stream = stream;
itti_send_msg_to_task(TASK_SCTP, INSTANCE_DEFAULT, message_p);
}
#ifndef S1AP_ENB_ITTI_MESSAGING_H_
#define S1AP_ENB_ITTI_MESSAGING_H_
void s1ap_eNB_itti_send_sctp_data_req(int32_t assoc_id, uint8_t *buffer,
uint32_t buffer_length, uint16_t stream);
#endif /* S1AP_ENB_ITTI_MESSAGING_H_ */
...@@ -32,7 +32,10 @@ ...@@ -32,7 +32,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "mme_sim.h" #include "intertask_interface.h"
#include "assertions.h"
// #include "conversions.h"
#include "s1ap_common.h" #include "s1ap_common.h"
#include "s1ap_ies_defs.h" #include "s1ap_ies_defs.h"
...@@ -44,72 +47,69 @@ ...@@ -44,72 +47,69 @@
#include "sctp_primitives_client.h" #include "sctp_primitives_client.h"
#include "assertions.h" // int s1ap_eNB_ue_capabilities(eNB_mme_desc_t *eNB_desc_p,
#include "conversions.h" // s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p)
// {
int s1ap_eNB_ue_capabilities(eNB_mme_desc_t *eNB_desc_p, // struct s1ap_eNB_ue_context_s *ue_context_p;
s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p) // UECapabilityInfoIndicationIEs_t *ue_cap_info_ind_ies_p;
{ //
struct s1ap_eNB_ue_context_s *ue_context_p; // s1ap_message message;
UECapabilityInfoIndicationIEs_t *ue_cap_info_ind_ies_p; //
// uint8_t *buffer;
s1ap_message message; // uint32_t length;
// int ret = -1;
uint8_t *buffer; //
uint32_t length; // DevAssert(ue_cap_info_ind_p != NULL);
int ret = -1; // DevAssert(eNB_desc_p != NULL);
//
DevAssert(ue_cap_info_ind_p != NULL); // if ((ue_context_p = s1ap_eNB_get_ue_context(eNB_desc_p, ue_cap_info_ind_p->eNB_ue_s1ap_id)) == NULL)
DevAssert(eNB_desc_p != NULL); // {
// /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
if ((ue_context_p = s1ap_eNB_get_ue_context(eNB_desc_p, ue_cap_info_ind_p->eNB_ue_s1ap_id)) == NULL) // S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n",
{ // ue_cap_info_ind_p->eNB_ue_s1ap_id);
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ // return -1;
S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n", // }
ue_cap_info_ind_p->eNB_ue_s1ap_id); //
return -1; // /* UE capabilities message can occur either during an s1ap connected state
} // * or during initial attach (for example: NAS authentication).
// */
/* UE capabilities message can occur either during an s1ap connected state // if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
* or during initial attach (for example: NAS authentication). // ue_context_p->ue_state == S1AP_UE_WAITING_CSR))
*/ // {
if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED || // S1AP_WARN("You are attempting to send NAS data over non-connected "
ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) // "eNB ue s1ap id: %u, current state: %d\n",
{ // ue_cap_info_ind_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
S1AP_WARN("You are attempting to send NAS data over non-connected " // return -1;
"eNB ue s1ap id: %u, current state: %d\n", // }
ue_cap_info_ind_p->eNB_ue_s1ap_id, ue_context_p->ue_state); //
return -1; // /* Prepare the S1AP message to encode */
} // memset(&message, 0, sizeof(s1ap_message));
//
/* Prepare the S1AP message to encode */ // message.direction = S1AP_PDU_PR_initiatingMessage;
memset(&message, 0, sizeof(s1ap_message)); // message.procedureCode = ProcedureCode_id_UECapabilityInfoIndication;
//
message.direction = S1AP_PDU_PR_initiatingMessage; // ue_cap_info_ind_ies_p = &message.msg.ueCapabilityInfoIndicationIEs;
message.procedureCode = ProcedureCode_id_UECapabilityInfoIndication; //
// ue_cap_info_ind_ies_p->ueRadioCapability.buf = ue_cap_info_ind_p->ue_radio_cap.buffer;
ue_cap_info_ind_ies_p = &message.msg.ueCapabilityInfoIndicationIEs; // ue_cap_info_ind_ies_p->ueRadioCapability.size = ue_cap_info_ind_p->ue_radio_cap.length;
//
ue_cap_info_ind_ies_p->ueRadioCapability.buf = ue_cap_info_ind_p->ue_radio_cap.buffer; // ue_cap_info_ind_ies_p->eNB_UE_S1AP_ID = ue_cap_info_ind_p->eNB_ue_s1ap_id;
ue_cap_info_ind_ies_p->ueRadioCapability.size = ue_cap_info_ind_p->ue_radio_cap.length; // ue_cap_info_ind_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id;
//
ue_cap_info_ind_ies_p->eNB_UE_S1AP_ID = ue_cap_info_ind_p->eNB_ue_s1ap_id; // if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
ue_cap_info_ind_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; // /* Encode procedure has failed... */
// S1AP_ERROR("Failed to encode UE capabilities indication\n");
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { // return -1;
/* Encode procedure has failed... */ // }
S1AP_ERROR("Failed to encode UE capabilities indication\n"); //
return -1; // /* UE associated signalling -> use the allocated stream */
} // if ((ret = sctp_send_msg(&ue_context_p->mme_ref->sctp_data, S1AP_SCTP_PPID,
// ue_context_p->stream, buffer, length)) < 0)
/* UE associated signalling -> use the allocated stream */ // {
if ((ret = sctp_send_msg(&ue_context_p->mme_ref->sctp_data, S1AP_SCTP_PPID, // S1AP_ERROR("[SCTP %d] Failed to send message over SCTP: %d\n",
ue_context_p->stream, buffer, length)) < 0) // ue_context_p->mme_ref->sctp_data.assoc_id, ret);
{ // }
S1AP_ERROR("[SCTP %d] Failed to send message over SCTP: %d\n", //
ue_context_p->mme_ref->sctp_data.assoc_id, ret); // free(buffer);
} // return ret;
// }
free(buffer);
return ret;
}
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#ifndef S1AP_ENB_MANAGEMENT_PROCEDURES_H_ #ifndef S1AP_ENB_MANAGEMENT_PROCEDURES_H_
#define S1AP_ENB_MANAGEMENT_PROCEDURES_H_ #define S1AP_ENB_MANAGEMENT_PROCEDURES_H_
int s1ap_eNB_ue_capabilities(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_ue_capabilities(eNB_mme_desc_t *eNB_desc_p,
s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p); // s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p);
#endif /* S1AP_ENB_MANAGEMENT_PROCEDURES_H_ */ #endif /* S1AP_ENB_MANAGEMENT_PROCEDURES_H_ */
...@@ -32,229 +32,230 @@ ...@@ -32,229 +32,230 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "mme_sim.h" #include "assertions.h"
#include "conversions.h"
#include "intertask_interface.h"
#include "s1ap_common.h" #include "s1ap_common.h"
#include "s1ap_ies_defs.h"
#include "s1ap_eNB_defs.h" #include "s1ap_eNB_defs.h"
#include "s1ap_eNB.h"
#include "s1ap_ies_defs.h"
#include "s1ap_eNB_encoder.h" #include "s1ap_eNB_encoder.h"
#include "s1ap_eNB_ue_context.h"
#include "s1ap_eNB_nas_procedures.h" #include "s1ap_eNB_nas_procedures.h"
#include "sctp_primitives_client.h" #include "sctp_primitives_client.h"
#include "assertions.h" // int s1ap_eNB_handle_nas_downlink(eNB_mme_desc_t *eNB_desc_p,
#include "conversions.h" // sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p)
int s1ap_eNB_handle_nas_downlink(eNB_mme_desc_t *eNB_desc_p, int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
sctp_queue_item_t *packet_p, uint32_t stream,
struct s1ap_message_s *message_p) struct s1ap_message_s *message_p)
{ {
DownlinkNASTransportIEs_t *downlink_NAS_transport_p; DownlinkNASTransportIEs_t *downlink_NAS_transport_p;
s1ap_eNB_mme_data_t *mme_desc_p; s1ap_eNB_mme_data_t *mme_desc_p;
s1ap_eNB_ue_context_t *ue_desc_p; s1ap_eNB_ue_context_t *ue_desc_p;
DevAssert(eNB_desc_p != NULL);
DevAssert(packet_p != NULL);
DevAssert(message_p != NULL); DevAssert(message_p != NULL);
downlink_NAS_transport_p = &message_p->msg.downlinkNASTransportIEs; downlink_NAS_transport_p = &message_p->msg.downlinkNASTransportIEs;
/* UE-related procedure -> stream != 0 */ /* UE-related procedure -> stream != 0 */
if (packet_p->local_stream == 0) { if (stream == 0) {
S1AP_ERROR("[SCTP %d] Received s1 setup response on stream == 0\n", S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream == 0\n",
packet_p->assoc_id); assoc_id);
return -1; return -1;
} }
if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) { // if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, assoc_id)) == NULL) {
S1AP_ERROR("[SCTP %d] Received initial context setup request for non " // S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
"existing MME context\n", packet_p->assoc_id); // "existing MME context\n", assoc_id);
return -1; // return -1;
} // }
if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p, // if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL) // downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL)
{ // {
S1AP_ERROR("[SCTP %d] Received initial context setup request for non " // S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
"existing UE context\n", packet_p->assoc_id); // "existing UE context\n", assoc_id);
return -1; // return -1;
} // }
/* Is it the first outcome of the MME for this UE ? If so store the mme /* Is it the first outcome of the MME for this UE ? If so store the mme
* UE s1ap id. * UE s1ap id.
*/ */
if (ue_desc_p->mme_ue_s1ap_id == 0) { // if (ue_desc_p->mme_ue_s1ap_id == 0) {
ue_desc_p->mme_ue_s1ap_id = downlink_NAS_transport_p->mme_ue_s1ap_id; // ue_desc_p->mme_ue_s1ap_id = downlink_NAS_transport_p->mme_ue_s1ap_id;
} else { // } else {
/* We already have a mme ue s1ap id check the received is the same */ // /* We already have a mme ue s1ap id check the received is the same */
if (ue_desc_p->mme_ue_s1ap_id != downlink_NAS_transport_p->mme_ue_s1ap_id) { // if (ue_desc_p->mme_ue_s1ap_id != downlink_NAS_transport_p->mme_ue_s1ap_id) {
S1AP_ERROR("[SCTP %d] Mismatch is MME UE S1AP ID (0x%08x != 0x%08x)\n", // S1AP_ERROR("[SCTP %d] Mismatch is MME UE S1AP ID (0x%08x != 0x%08x)\n",
downlink_NAS_transport_p->mme_ue_s1ap_id, // downlink_NAS_transport_p->mme_ue_s1ap_id,
ue_desc_p->mme_ue_s1ap_id, // ue_desc_p->mme_ue_s1ap_id,
packet_p->assoc_id); // packet_p->assoc_id);
} // }
} // }
/* TODO: forward NAS pdu to RRC for transmission */ /* TODO: forward NAS pdu to RRC for transmission */
return 0; return 0;
} }
int s1ap_eNB_nas_uplink(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_nas_uplink(eNB_mme_desc_t *eNB_desc_p,
s1ap_nas_uplink_t *nas_uplink_p) // s1ap_nas_uplink_t *nas_uplink_p)
{ // {
struct s1ap_eNB_ue_context_s *ue_context_p; // struct s1ap_eNB_ue_context_s *ue_context_p;
UplinkNASTransportIEs_t *uplink_NAS_transport_p; // UplinkNASTransportIEs_t *uplink_NAS_transport_p;
//
s1ap_message message; // s1ap_message message;
//
uint8_t *buffer; // uint8_t *buffer;
uint32_t length; // uint32_t length;
int ret = -1; // int ret = -1;
//
DevAssert(nas_uplink_p != NULL); // DevAssert(nas_uplink_p != NULL);
DevAssert(eNB_desc_p != NULL); // DevAssert(eNB_desc_p != NULL);
//
if ((ue_context_p = s1ap_eNB_get_ue_context(eNB_desc_p, nas_uplink_p->eNB_ue_s1ap_id)) == NULL) // if ((ue_context_p = s1ap_eNB_get_ue_context(eNB_desc_p, nas_uplink_p->eNB_ue_s1ap_id)) == NULL)
{ // {
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ // /* 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: %u\n", // S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n",
nas_uplink_p->eNB_ue_s1ap_id); // nas_uplink_p->eNB_ue_s1ap_id);
return -1; // return -1;
} // }
//
/* Uplink NAS transport can occur either during an s1ap connected state // /* Uplink NAS transport can occur either during an s1ap connected state
* or during initial attach (for example: NAS authentication). // * or during initial attach (for example: NAS authentication).
*/ // */
if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED || // if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) // ue_context_p->ue_state == S1AP_UE_WAITING_CSR))
{ // {
S1AP_WARN("You are attempting to send NAS data over non-connected " // S1AP_WARN("You are attempting to send NAS data over non-connected "
"eNB ue s1ap id: %u, current state: %d\n", // "eNB ue s1ap id: %u, current state: %d\n",
nas_uplink_p->eNB_ue_s1ap_id, ue_context_p->ue_state); // nas_uplink_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
return -1; // return -1;
} // }
//
/* Prepare the S1AP message to encode */ // /* Prepare the S1AP message to encode */
memset(&message, 0, sizeof(s1ap_message)); // memset(&message, 0, sizeof(s1ap_message));
//
message.direction = S1AP_PDU_PR_initiatingMessage; // message.direction = S1AP_PDU_PR_initiatingMessage;
message.procedureCode = ProcedureCode_id_uplinkNASTransport; // message.procedureCode = ProcedureCode_id_uplinkNASTransport;
//
uplink_NAS_transport_p = &message.msg.uplinkNASTransportIEs; // uplink_NAS_transport_p = &message.msg.uplinkNASTransportIEs;
//
uplink_NAS_transport_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; // uplink_NAS_transport_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id;
uplink_NAS_transport_p->eNB_UE_S1AP_ID = ue_context_p->eNB_ue_s1ap_id; // uplink_NAS_transport_p->eNB_UE_S1AP_ID = ue_context_p->eNB_ue_s1ap_id;
//
uplink_NAS_transport_p->nas_pdu.buf = nas_uplink_p->nas_pdu.buffer; // uplink_NAS_transport_p->nas_pdu.buf = nas_uplink_p->nas_pdu.buffer;
uplink_NAS_transport_p->nas_pdu.size = nas_uplink_p->nas_pdu.length; // uplink_NAS_transport_p->nas_pdu.size = nas_uplink_p->nas_pdu.length;
//
MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc, // MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc,
&uplink_NAS_transport_p->eutran_cgi.pLMNidentity); // &uplink_NAS_transport_p->eutran_cgi.pLMNidentity);
MACRO_ENB_ID_TO_CELL_IDENTITY(eNB_desc_p->eNB_id, // MACRO_ENB_ID_TO_CELL_IDENTITY(eNB_desc_p->eNB_id,
&uplink_NAS_transport_p->eutran_cgi.cell_ID); // &uplink_NAS_transport_p->eutran_cgi.cell_ID);
//
/* MCC/MNC should be repeated in TAI and EUTRAN CGI */ // /* MCC/MNC should be repeated in TAI and EUTRAN CGI */
MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc, // MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc,
&uplink_NAS_transport_p->tai.pLMNidentity); // &uplink_NAS_transport_p->tai.pLMNidentity);
TAC_TO_ASN1(eNB_desc_p->tac, &uplink_NAS_transport_p->tai.tAC); // TAC_TO_ASN1(eNB_desc_p->tac, &uplink_NAS_transport_p->tai.tAC);
//
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { // if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
S1AP_ERROR("Failed to encode uplink NAS transport\n"); // S1AP_ERROR("Failed to encode uplink NAS transport\n");
/* Encode procedure has failed... */ // /* Encode procedure has failed... */
return -1; // return -1;
} // }
//
/* UE associated signalling -> use the allocated stream */ // /* UE associated signalling -> use the allocated stream */
if ((ret = sctp_send_msg(&ue_context_p->mme_ref->sctp_data, S1AP_SCTP_PPID, // if ((ret = sctp_send_msg(&ue_context_p->mme_ref->sctp_data, S1AP_SCTP_PPID,
ue_context_p->stream, buffer, length)) < 0) // ue_context_p->stream, buffer, length)) < 0)
{ // {
S1AP_ERROR("[SCTP %d] Failed to send message over SCTP: %d\n", // S1AP_ERROR("[SCTP %d] Failed to send message over SCTP: %d\n",
ue_context_p->mme_ref->sctp_data.assoc_id, ret); // ue_context_p->mme_ref->sctp_data.assoc_id, ret);
} // }
//
free(buffer); // free(buffer);
return ret; // return ret;
} // }
int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *eNB_desc_p,
s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p) // s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p)
{ // {
struct s1ap_eNB_ue_context_s *ue_context_p; // struct s1ap_eNB_ue_context_s *ue_context_p;
InitialContextSetupResponseIEs_t *initial_ies_p; // InitialContextSetupResponseIEs_t *initial_ies_p;
//
s1ap_message message; // s1ap_message message;
//
uint8_t *buffer; // uint8_t *buffer;
uint32_t length; // uint32_t length;
int ret = -1; // int ret = -1;
int i; // int i;
//
DevAssert(initial_ctxt_resp_p != NULL); // DevAssert(initial_ctxt_resp_p != NULL);
DevAssert(eNB_desc_p != NULL); // DevAssert(eNB_desc_p != NULL);
//
if ((ue_context_p = s1ap_eNB_get_ue_context(eNB_desc_p, // if ((ue_context_p = s1ap_eNB_get_ue_context(eNB_desc_p,
initial_ctxt_resp_p->eNB_ue_s1ap_id)) == NULL) // initial_ctxt_resp_p->eNB_ue_s1ap_id)) == NULL)
{ // {
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ // /* 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: %u\n", // S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n",
initial_ctxt_resp_p->eNB_ue_s1ap_id); // initial_ctxt_resp_p->eNB_ue_s1ap_id);
return -1; // return -1;
} // }
//
/* Uplink NAS transport can occur either during an s1ap connected state // /* Uplink NAS transport can occur either during an s1ap connected state
* or during initial attach (for example: NAS authentication). // * or during initial attach (for example: NAS authentication).
*/ // */
if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED || // if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) // ue_context_p->ue_state == S1AP_UE_WAITING_CSR))
{ // {
S1AP_WARN("You are attempting to send NAS data over non-connected " // S1AP_WARN("You are attempting to send NAS data over non-connected "
"eNB ue s1ap id: %u, current state: %d\n", // "eNB ue s1ap id: %u, current state: %d\n",
initial_ctxt_resp_p->eNB_ue_s1ap_id, ue_context_p->ue_state); // initial_ctxt_resp_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
return -1; // return -1;
} // }
//
/* Prepare the S1AP message to encode */ // /* Prepare the S1AP message to encode */
memset(&message, 0, sizeof(s1ap_message)); // memset(&message, 0, sizeof(s1ap_message));
//
message.direction = S1AP_PDU_PR_successfulOutcome; // message.direction = S1AP_PDU_PR_successfulOutcome;
message.procedureCode = ProcedureCode_id_InitialContextSetup; // message.procedureCode = ProcedureCode_id_InitialContextSetup;
//
initial_ies_p = &message.msg.initialContextSetupResponseIEs; // initial_ies_p = &message.msg.initialContextSetupResponseIEs;
//
initial_ies_p->eNB_UE_S1AP_ID = initial_ctxt_resp_p->eNB_ue_s1ap_id; // initial_ies_p->eNB_UE_S1AP_ID = initial_ctxt_resp_p->eNB_ue_s1ap_id;
initial_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; // initial_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id;
//
for (i = 0; i < initial_ctxt_resp_p->nb_of_e_rabs; i++) // for (i = 0; i < initial_ctxt_resp_p->nb_of_e_rabs; i++)
{ // {
E_RABSetupItemCtxtSURes_t *new_item; // E_RABSetupItemCtxtSURes_t *new_item;
//
new_item = calloc(1, sizeof(E_RABSetupItemCtxtSURes_t)); // new_item = calloc(1, sizeof(E_RABSetupItemCtxtSURes_t));
//
new_item->e_RAB_ID = initial_ctxt_resp_p->e_rabs[i].e_rab_id; // new_item->e_RAB_ID = initial_ctxt_resp_p->e_rabs[i].e_rab_id;
GTP_TEID_TO_ASN1(initial_ctxt_resp_p->e_rabs[i].gtp_teid, &new_item->gTP_TEID); // GTP_TEID_TO_ASN1(initial_ctxt_resp_p->e_rabs[i].gtp_teid, &new_item->gTP_TEID);
new_item->transportLayerAddress.buf = initial_ctxt_resp_p->e_rabs[i].eNB_addr.buffer; // new_item->transportLayerAddress.buf = initial_ctxt_resp_p->e_rabs[i].eNB_addr.buffer;
new_item->transportLayerAddress.size = initial_ctxt_resp_p->e_rabs[i].eNB_addr.length; // new_item->transportLayerAddress.size = initial_ctxt_resp_p->e_rabs[i].eNB_addr.length;
new_item->transportLayerAddress.bits_unused = 0; // new_item->transportLayerAddress.bits_unused = 0;
//
ASN_SEQUENCE_ADD(&initial_ies_p->e_RABSetupListCtxtSURes.e_RABSetupItemCtxtSURes, new_item); // ASN_SEQUENCE_ADD(&initial_ies_p->e_RABSetupListCtxtSURes.e_RABSetupItemCtxtSURes, new_item);
} // }
//
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { // if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
S1AP_ERROR("Failed to encode uplink NAS transport\n"); // S1AP_ERROR("Failed to encode uplink NAS transport\n");
/* Encode procedure has failed... */ // /* Encode procedure has failed... */
return -1; // return -1;
} // }
//
/* UE associated signalling -> use the allocated stream */ // /* UE associated signalling -> use the allocated stream */
if ((ret = sctp_send_msg(&ue_context_p->mme_ref->sctp_data, S1AP_SCTP_PPID, // if ((ret = sctp_send_msg(&ue_context_p->mme_ref->sctp_data, S1AP_SCTP_PPID,
ue_context_p->stream, buffer, length)) < 0) // ue_context_p->stream, buffer, length)) < 0)
{ // {
S1AP_ERROR("[SCTP %d] Failed to send message over SCTP: %d\n", // S1AP_ERROR("[SCTP %d] Failed to send message over SCTP: %d\n",
ue_context_p->mme_ref->sctp_data.assoc_id, ret); // ue_context_p->mme_ref->sctp_data.assoc_id, ret);
} // }
//
free(buffer); // free(buffer);
return ret; // return ret;
} // }
...@@ -31,14 +31,11 @@ ...@@ -31,14 +31,11 @@
#ifndef S1AP_ENB_NAS_PROCEDURES_H_ #ifndef S1AP_ENB_NAS_PROCEDURES_H_
#define S1AP_ENB_NAS_PROCEDURES_H_ #define S1AP_ENB_NAS_PROCEDURES_H_
int s1ap_eNB_nas_uplink(eNB_mme_desc_t *eNB_desc_p, int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
s1ap_nas_uplink_t *nas_uplink_p); uint32_t stream,
int s1ap_eNB_handle_nas_downlink(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p,
struct s1ap_message_s *message_p); struct s1ap_message_s *message_p);
int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *eNB_desc_p,
s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p); // s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p);
#endif /* S1AP_ENB_NAS_PROCEDURES_H_ */ #endif /* S1AP_ENB_NAS_PROCEDURES_H_ */
...@@ -38,13 +38,15 @@ ...@@ -38,13 +38,15 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "mme_sim.h" #include "intertask_interface.h"
#include "s1ap_eNB.h" #include "s1ap_common.h"
#include "s1ap_eNB_defs.h"
#include "s1ap_eNB_nnsf.h" #include "s1ap_eNB_nnsf.h"
struct s1ap_eNB_mme_data_s * struct s1ap_eNB_mme_data_s *
s1ap_eNB_nnsf_select_mme_by_mme_code(eNB_mme_desc_t *eNB_desc_p, s1ap_eNB_nnsf_select_mme_by_mme_code(s1ap_eNB_instance_t *instance_p,
rrc_establishment_cause_t cause, rrc_establishment_cause_t cause,
uint8_t mme_code) uint8_t mme_code)
{ {
...@@ -52,7 +54,7 @@ s1ap_eNB_nnsf_select_mme_by_mme_code(eNB_mme_desc_t *eNB_desc_p, ...@@ -52,7 +54,7 @@ s1ap_eNB_nnsf_select_mme_by_mme_code(eNB_mme_desc_t *eNB_desc_p,
struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL;
uint8_t current_capacity = 0; uint8_t current_capacity = 0;
RB_FOREACH(mme_data_p, s1ap_mme_map, &eNB_desc_p->s1ap_mme_head) { RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
struct served_gummei_s *gummei_p = NULL; struct served_gummei_s *gummei_p = NULL;
if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) { if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) {
...@@ -112,7 +114,7 @@ s1ap_eNB_nnsf_select_mme_by_mme_code(eNB_mme_desc_t *eNB_desc_p, ...@@ -112,7 +114,7 @@ s1ap_eNB_nnsf_select_mme_by_mme_code(eNB_mme_desc_t *eNB_desc_p,
} }
struct s1ap_eNB_mme_data_s * struct s1ap_eNB_mme_data_s *
s1ap_eNB_nnsf_select_mme_by_gummei(eNB_mme_desc_t *eNB_desc_p, s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p,
rrc_establishment_cause_t cause, rrc_establishment_cause_t cause,
gummei_t gummei) gummei_t gummei)
{ {
...@@ -120,7 +122,7 @@ s1ap_eNB_nnsf_select_mme_by_gummei(eNB_mme_desc_t *eNB_desc_p, ...@@ -120,7 +122,7 @@ s1ap_eNB_nnsf_select_mme_by_gummei(eNB_mme_desc_t *eNB_desc_p,
struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL;
uint8_t current_capacity = 0; uint8_t current_capacity = 0;
RB_FOREACH(mme_data_p, s1ap_mme_map, &eNB_desc_p->s1ap_mme_head) { RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
struct served_gummei_s *gummei_p = NULL; struct served_gummei_s *gummei_p = NULL;
if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) { if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) {
......
...@@ -37,12 +37,12 @@ ...@@ -37,12 +37,12 @@
#define S1AP_ENB_NNSF_H_ #define S1AP_ENB_NNSF_H_
struct s1ap_eNB_mme_data_s* struct s1ap_eNB_mme_data_s*
s1ap_eNB_nnsf_select_mme_by_mme_code(eNB_mme_desc_t *eNB_desc_p, s1ap_eNB_nnsf_select_mme_by_mme_code(s1ap_eNB_instance_t *instance_p,
rrc_establishment_cause_t cause, rrc_establishment_cause_t cause,
uint8_t mme_code); uint8_t mme_code);
struct s1ap_eNB_mme_data_s* struct s1ap_eNB_mme_data_s*
s1ap_eNB_nnsf_select_mme_by_gummei(eNB_mme_desc_t *eNB_desc_p, s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p,
rrc_establishment_cause_t cause, rrc_establishment_cause_t cause,
gummei_t gummei); gummei_t gummei);
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "intertask_interface.h"
#include "s1ap_common.h" #include "s1ap_common.h"
#include "s1ap_ies_defs.h" #include "s1ap_ies_defs.h"
#include "s1ap_eNB_defs.h" #include "s1ap_eNB_defs.h"
...@@ -52,58 +54,69 @@ ...@@ -52,58 +54,69 @@
#include "assertions.h" #include "assertions.h"
int s1ap_eNB_handle_overload_start(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_handle_overload_start(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p, // sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p)
int s1ap_eNB_handle_overload_start(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p) struct s1ap_message_s *message_p)
{ {
OverloadStartIEs_t *overload_start_p; OverloadStartIEs_t *overload_start_p;
s1ap_eNB_mme_data_t *mme_desc_p; s1ap_eNB_mme_data_t *mme_desc_p;
overload_start_p = &message_p->msg.overloadStartIEs; DevAssert(message_p != NULL);
DevCheck(overload_start_p->overloadResponse.present ==
OverloadResponse_PR_overloadAction,
OverloadResponse_PR_overloadAction, 0, 0);
/* Non UE-associated signalling -> stream 0 */ overload_start_p = &message_p->msg.overloadStartIEs;
DevCheck(packet_p->local_stream == 0, packet_p->local_stream,
packet_p->remote_port, packet_p->assoc_id);
if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) { // DevCheck(overload_start_p->overloadResponse.present ==
/* No MME context associated */ // OverloadResponse_PR_overloadAction,
return -1; // OverloadResponse_PR_overloadAction, 0, 0);
} //
// /* Non UE-associated signalling -> stream 0 */
/* Mark the MME as overloaded and set the overload state according to // DevCheck(packet_p->local_stream == 0, packet_p->local_stream,
* the value received. // packet_p->remote_port, packet_p->assoc_id);
*/ //
mme_desc_p->state = S1AP_ENB_OVERLOAD; // if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) {
mme_desc_p->overload_state = // /* No MME context associated */
overload_start_p->overloadResponse.choice.overloadAction; // return -1;
// }
//
// /* Mark the MME as overloaded and set the overload state according to
// * the value received.
// */
// mme_desc_p->state = S1AP_ENB_OVERLOAD;
// mme_desc_p->overload_state =
// overload_start_p->overloadResponse.choice.overloadAction;
return 0; return 0;
} }
int s1ap_eNB_handle_overload_stop(eNB_mme_desc_t *eNB_desc_p, int s1ap_eNB_handle_overload_stop(uint32_t assoc_id,
sctp_queue_item_t *packet_p, uint32_t stream,
struct s1ap_message_s *message_p) struct s1ap_message_s *message_p)
// int s1ap_eNB_handle_overload_stop(eNB_mme_desc_t *eNB_desc_p,
// sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p)
{ {
/* We received Overload stop message, meaning that the MME is no more /* We received Overload stop message, meaning that the MME is no more
* overloaded. This is an empty message, with only message header and no * overloaded. This is an empty message, with only message header and no
* Information Element. * Information Element.
*/ */
s1ap_eNB_mme_data_t *mme_desc_p;
/* Non UE-associated signalling -> stream 0 */
DevCheck(packet_p->local_stream == 0, packet_p->local_stream,
packet_p->remote_port, packet_p->assoc_id);
if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) {
/* No MME context associated */
return -1;
}
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; DevAssert(message_p != NULL);
mme_desc_p->overload_state = S1AP_NO_OVERLOAD;
// s1ap_eNB_mme_data_t *mme_desc_p;
//
// /* Non UE-associated signalling -> stream 0 */
// DevCheck(packet_p->local_stream == 0, packet_p->local_stream,
// packet_p->remote_port, packet_p->assoc_id);
//
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) {
// /* No MME context associated */
// return -1;
// }
//
// mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
// mme_desc_p->overload_state = S1AP_NO_OVERLOAD;
return 0; return 0;
} }
...@@ -34,15 +34,21 @@ ...@@ -34,15 +34,21 @@
/** /**
* \brief Handle an overload start message * \brief Handle an overload start message
**/ **/
int s1ap_eNB_handle_overload_start(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_handle_overload_start(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p, // sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p);
int s1ap_eNB_handle_overload_start(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p); struct s1ap_message_s *message_p);
/** /**
* \brief Handle an overload stop message * \brief Handle an overload stop message
**/ **/
int s1ap_eNB_handle_overload_stop(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_handle_overload_stop(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p, // sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p);
int s1ap_eNB_handle_overload_stop(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p); struct s1ap_message_s *message_p);
#endif /* S1AP_ENB_OVERLOAD_H_ */ #endif /* S1AP_ENB_OVERLOAD_H_ */
...@@ -28,6 +28,12 @@ ...@@ -28,6 +28,12 @@
*******************************************************************************/ *******************************************************************************/
#include <stdint.h>
#include "intertask_interface.h"
#include "s1ap_eNB_default_values.h"
#include "s1ap_common.h" #include "s1ap_common.h"
#include "s1ap_ies_defs.h" #include "s1ap_ies_defs.h"
#include "s1ap_eNB_defs.h" #include "s1ap_eNB_defs.h"
...@@ -37,84 +43,90 @@ ...@@ -37,84 +43,90 @@
#include "s1ap_eNB_encoder.h" #include "s1ap_eNB_encoder.h"
#include "s1ap_eNB_trace.h" #include "s1ap_eNB_trace.h"
#include "eNB_default_values.h"
#include "sctp_primitives_client.h" #include "sctp_primitives_client.h"
#include "assertions.h" #include "assertions.h"
int s1ap_eNB_generate_trace_failure(sctp_data_t *sctp_data_p, // int s1ap_eNB_generate_trace_failure(sctp_data_t *sctp_data_p,
int32_t stream, // int32_t stream,
uint32_t eNB_ue_s1ap_id, // uint32_t eNB_ue_s1ap_id,
uint32_t mme_ue_s1ap_id, // uint32_t mme_ue_s1ap_id,
E_UTRAN_Trace_ID_t *trace_id, // E_UTRAN_Trace_ID_t *trace_id,
Cause_t *cause_p) // Cause_t *cause_p)
{ // {
s1ap_message message; // s1ap_message message;
TraceFailureIndicationIEs_t *trace_failure_p; // TraceFailureIndicationIEs_t *trace_failure_p;
uint8_t *buffer; // uint8_t *buffer;
uint32_t length; // uint32_t length;
int ret; // int ret;
//
DevAssert(sctp_data_p != NULL); // DevAssert(sctp_data_p != NULL);
//
memset(&message, 0, sizeof(s1ap_message)); // memset(&message, 0, sizeof(s1ap_message));
//
trace_failure_p = &message.msg.traceFailureIndicationIEs; // trace_failure_p = &message.msg.traceFailureIndicationIEs;
//
trace_failure_p->mme_ue_s1ap_id = mme_ue_s1ap_id; // trace_failure_p->mme_ue_s1ap_id = mme_ue_s1ap_id;
trace_failure_p->eNB_UE_S1AP_ID = eNB_ue_s1ap_id; // trace_failure_p->eNB_UE_S1AP_ID = eNB_ue_s1ap_id;
//
memcpy(&trace_failure_p->e_UTRAN_Trace_ID, trace_id, sizeof(E_UTRAN_Trace_ID_t)); // memcpy(&trace_failure_p->e_UTRAN_Trace_ID, trace_id, sizeof(E_UTRAN_Trace_ID_t));
memcpy(&trace_failure_p->cause, cause_p, sizeof(Cause_t)); // memcpy(&trace_failure_p->cause, cause_p, sizeof(Cause_t));
//
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { // if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
return -1; // return -1;
} // }
if ((ret = sctp_send_msg(sctp_data_p, S1AP_SCTP_PPID, // if ((ret = sctp_send_msg(sctp_data_p, S1AP_SCTP_PPID,
stream, buffer, length)) < 0) { // stream, buffer, length)) < 0) {
S1AP_ERROR("Failed to send Trace failure\n"); // S1AP_ERROR("Failed to send Trace failure\n");
} // }
free(buffer); // free(buffer);
return ret; // return ret;
} // }
int s1ap_eNB_handle_trace_start(eNB_mme_desc_t *eNB_desc_p, int s1ap_eNB_handle_trace_start(uint32_t assoc_id,
sctp_queue_item_t *packet_p, uint32_t stream,
struct s1ap_message_s *message_p) struct s1ap_message_s *message_p)
// int s1ap_eNB_handle_trace_start(eNB_mme_desc_t *eNB_desc_p,
// sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p)
{ {
TraceStartIEs_t *trace_start_p; TraceStartIEs_t *trace_start_p;
struct s1ap_eNB_ue_context_s *ue_desc_p; struct s1ap_eNB_ue_context_s *ue_desc_p;
DevAssert(message_p != NULL);
trace_start_p = &message_p->msg.traceStartIEs; trace_start_p = &message_p->msg.traceStartIEs;
if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p, // if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
trace_start_p->eNB_UE_S1AP_ID)) == NULL) { // trace_start_p->eNB_UE_S1AP_ID)) == NULL) {
/* Could not find context associated with this eNB_ue_s1ap_id -> generate // /* Could not find context associated with this eNB_ue_s1ap_id -> generate
* trace failure indication. // * trace failure indication.
*/ // */
struct s1ap_eNB_mme_data_s *mme_ref_p; // struct s1ap_eNB_mme_data_s *mme_ref_p;
E_UTRAN_Trace_ID_t trace_id; // E_UTRAN_Trace_ID_t trace_id;
Cause_t cause; // Cause_t cause;
//
memset(&trace_id, 0, sizeof(E_UTRAN_Trace_ID_t)); // memset(&trace_id, 0, sizeof(E_UTRAN_Trace_ID_t));
memset(&cause, 0, sizeof(Cause_t)); // memset(&cause, 0, sizeof(Cause_t));
mme_ref_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id); // mme_ref_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id);
//
cause.present = Cause_PR_radioNetwork; // cause.present = Cause_PR_radioNetwork;
cause.choice.radioNetwork = CauseRadioNetwork_unknown_pair_ue_s1ap_id; // cause.choice.radioNetwork = CauseRadioNetwork_unknown_pair_ue_s1ap_id;
//
return s1ap_eNB_generate_trace_failure(&mme_ref_p->sctp_data, // return s1ap_eNB_generate_trace_failure(&mme_ref_p->sctp_data,
packet_p->local_stream, // packet_p->local_stream,
trace_start_p->eNB_UE_S1AP_ID, // trace_start_p->eNB_UE_S1AP_ID,
trace_start_p->mme_ue_s1ap_id, &trace_id, &cause); // trace_start_p->mme_ue_s1ap_id, &trace_id, &cause);
} // }
return 0; return 0;
} }
int s1ap_eNB_handle_deactivate_trace(eNB_mme_desc_t *eNB_desc_p, int s1ap_eNB_handle_deactivate_trace(uint32_t assoc_id,
sctp_queue_item_t *packet_p, uint32_t stream,
struct s1ap_message_s *message_p) struct s1ap_message_s *message_p)
// int s1ap_eNB_handle_deactivate_trace(eNB_mme_desc_t *eNB_desc_p,
// sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p)
{ {
DeactivateTraceIEs_t *deactivate_trace_p; DeactivateTraceIEs_t *deactivate_trace_p;
......
...@@ -31,19 +31,25 @@ ...@@ -31,19 +31,25 @@
#ifndef S1AP_ENB_TRACE_H_ #ifndef S1AP_ENB_TRACE_H_
#define S1AP_ENB_TRACE_H_ #define S1AP_ENB_TRACE_H_
int s1ap_eNB_generate_trace_failure(sctp_data_t *sctp_data_p, // int s1ap_eNB_generate_trace_failure(sctp_data_t *sctp_data_p,
int32_t stream, // int32_t stream,
uint32_t eNB_ue_s1ap_id, // uint32_t eNB_ue_s1ap_id,
uint32_t mme_ue_s1ap_id, // uint32_t mme_ue_s1ap_id,
E_UTRAN_Trace_ID_t *trace_id, // E_UTRAN_Trace_ID_t *trace_id,
Cause_t *cause_p); // Cause_t *cause_p);
int s1ap_eNB_handle_trace_start(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_handle_trace_start(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p, // sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p);
int s1ap_eNB_handle_trace_start(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p); struct s1ap_message_s *message_p);
int s1ap_eNB_handle_deactivate_trace(eNB_mme_desc_t *eNB_desc_p, // int s1ap_eNB_handle_deactivate_trace(eNB_mme_desc_t *eNB_desc_p,
sctp_queue_item_t *packet_p, // sctp_queue_item_t *packet_p,
// struct s1ap_message_s *message_p);
int s1ap_eNB_handle_deactivate_trace(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p); struct s1ap_message_s *message_p);
#endif /* S1AP_ENB_TRACE_H_ */ #endif /* S1AP_ENB_TRACE_H_ */
...@@ -42,8 +42,10 @@ ...@@ -42,8 +42,10 @@
#include "tree.h" #include "tree.h"
#include "intertask_interface.h"
#include "s1ap_common.h" #include "s1ap_common.h"
#include "s1ap_eNB.h" #include "s1ap_eNB_defs.h"
#include "s1ap_eNB_ue_context.h" #include "s1ap_eNB_ue_context.h"
inline int s1ap_eNB_compare_eNB_ue_s1ap_id( inline int s1ap_eNB_compare_eNB_ue_s1ap_id(
...@@ -79,7 +81,7 @@ struct s1ap_eNB_ue_context_s *s1ap_eNB_allocate_new_UE_context(void) ...@@ -79,7 +81,7 @@ struct s1ap_eNB_ue_context_s *s1ap_eNB_allocate_new_UE_context(void)
} }
struct s1ap_eNB_ue_context_s *s1ap_eNB_get_ue_context( struct s1ap_eNB_ue_context_s *s1ap_eNB_get_ue_context(
struct eNB_mme_desc_s *eNB_desc_p, s1ap_eNB_instance_t *instance_p,
uint32_t eNB_ue_s1ap_id) uint32_t eNB_ue_s1ap_id)
{ {
s1ap_eNB_ue_context_t temp; s1ap_eNB_ue_context_t temp;
...@@ -89,7 +91,7 @@ struct s1ap_eNB_ue_context_s *s1ap_eNB_get_ue_context( ...@@ -89,7 +91,7 @@ struct s1ap_eNB_ue_context_s *s1ap_eNB_get_ue_context(
/* eNB ue s1ap id = 24 bits wide */ /* eNB ue s1ap id = 24 bits wide */
temp.eNB_ue_s1ap_id = eNB_ue_s1ap_id & 0x00FFFFFF; temp.eNB_ue_s1ap_id = eNB_ue_s1ap_id & 0x00FFFFFF;
return RB_FIND(s1ap_ue_map, &eNB_desc_p->s1ap_ue_head, &temp); return RB_FIND(s1ap_ue_map, &instance_p->s1ap_ue_head, &temp);
} }
void s1ap_eNB_free_ue_context(struct s1ap_eNB_ue_context_s *ue_context_p) void s1ap_eNB_free_ue_context(struct s1ap_eNB_ue_context_s *ue_context_p)
......
...@@ -50,6 +50,9 @@ typedef enum { ...@@ -50,6 +50,9 @@ typedef enum {
} s1ap_ue_state; } s1ap_ue_state;
typedef struct s1ap_eNB_ue_context_s { typedef struct s1ap_eNB_ue_context_s {
/* Tree related data */
RB_ENTRY(s1ap_eNB_ue_context_s) entries;
/* Uniquely identifies the UE between MME and eNB within the eNB. /* Uniquely identifies the UE between MME and eNB within the eNB.
* This id is encoded on 24bits. * This id is encoded on 24bits.
*/ */
...@@ -69,9 +72,6 @@ typedef struct s1ap_eNB_ue_context_s { ...@@ -69,9 +72,6 @@ typedef struct s1ap_eNB_ue_context_s {
/* Reference to MME data this UE is attached to */ /* Reference to MME data this UE is attached to */
struct s1ap_eNB_mme_data_s *mme_ref; struct s1ap_eNB_mme_data_s *mme_ref;
/* Tree related data */
RB_ENTRY(s1ap_eNB_ue_context_s) entries;
} s1ap_eNB_ue_context_t; } s1ap_eNB_ue_context_t;
inline int s1ap_eNB_compare_eNB_ue_s1ap_id( inline int s1ap_eNB_compare_eNB_ue_s1ap_id(
...@@ -83,8 +83,8 @@ RB_PROTOTYPE(s1ap_ue_map, s1ap_eNB_ue_context_s, entries, ...@@ -83,8 +83,8 @@ RB_PROTOTYPE(s1ap_ue_map, s1ap_eNB_ue_context_s, entries,
struct s1ap_eNB_ue_context_s *s1ap_eNB_allocate_new_UE_context(void); struct s1ap_eNB_ue_context_s *s1ap_eNB_allocate_new_UE_context(void);
struct s1ap_eNB_ue_context_s *s1ap_eNB_get_ue_context(struct eNB_mme_desc_s struct s1ap_eNB_ue_context_s *s1ap_eNB_get_ue_context(
*eNB_desc_p, s1ap_eNB_instance_t *instance_p,
uint32_t eNB_ue_s1ap_id); uint32_t eNB_ue_s1ap_id);
#endif /* S1AP_ENB_UE_CONTEXT_H_ */ #endif /* S1AP_ENB_UE_CONTEXT_H_ */
libsctp_OBJECTS = \ include $(OPENAIR_TARGETS)/SIMU/USER/Makerules
sctp_primitives_client.o \
sctp_common.o
-include .deps/*.d libsctp_OBJECTS = \
sctp_common.o \
sctp_eNB_task.o \
sctp_eNB_itti_messaging.o
.PHONY = depdir # pull in dependency info for *existing* .o files
-include .*.d
CFLAGS = \ CFLAGS = \
$(S1AP_CFLAGS) \
-I../SCTP \ -I../SCTP \
-I../UTILS \
-I$(OPENAIR2_DIR) \
-I$(OPENAIR2_DIR)/COMMON \
-I$(OPENAIR2_DIR)/S1AP \
-I$(OPENAIR2_DIR)/GTPV1U \
-I$(OPENAIR2_DIR)/GTPV1U/nw-gtpv1u/include \
-I$(OPENAIR2_DIR)/GTPV1U/nw-gtpv1u/shared \
-I$(OPENAIR2_DIR)/UTIL \
-I$(OPENAIR2_DIR)/UTIL/UDP \
-DUPDATE_RELEASE_9 \
-DENB_MODE \ -DENB_MODE \
-DENABLE_USE_MME \
-DUSER_MODE \
-O2 \
-g \
-Wall \
-Werror=implicit-function-declaration -Werror=implicit-function-declaration
$(libsctp_OBJECTS): %.o : %.c $(libsctp_OBJECTS): %.o : %.c
@echo "Compiling $<" @echo "Compiling $<"
@$(CC) -c $(CFLAGS) -o $@ $< @$(CC) -c $(CFLAGS) -o $@ $<
@if ! test -d ".deps/" ; then mkdir -p .deps; fi @$(CC) -MM $(CFLAGS) $*.c > $*.d
@$(CC) -MM $(CFLAGS) $*.c > .deps/$*.d @mv -f $*.d $*.d.tmp
@mv -f .deps/$*.d .deps/$*.d.tmp @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d
@sed -e 's|.*:|$*.o:|' < .deps/$*.d.tmp > .deps/$*.d @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
@sed -e 's/.*://' -e 's/\\$$//' < .deps/$*.d.tmp | fmt -1 | \ sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
sed -e 's/^ *//' -e 's/$$/:/' >> .deps/$*.d @rm -f $*.d.tmp
@rm -f .deps/$*.d.tmp
libsctp.a: $(libsctp_OBJECTS) libsctp.a: $(libsctp_OBJECTS)
@echo Creating SCTP archive @echo Creating SCTP archive
@$(AR) rcvs $@ $(libsctp_OBJECTS) @$(AR) rcs $@ $(libsctp_OBJECTS)
clean: clean:
rm -f $(libsctp_OBJECTS) @$(RM_F_V) $(libsctp_OBJECTS)
rm -rf .deps/ @$(RM_F_V) *.d
rm -f libsctp.a @$(RM_F_V) libsctp.a
\ No newline at end of file \ No newline at end of file
...@@ -83,7 +83,7 @@ int sctp_set_init_opt(int sd, uint16_t instreams, uint16_t outstreams, ...@@ -83,7 +83,7 @@ int sctp_set_init_opt(int sd, uint16_t instreams, uint16_t outstreams,
} }
int sctp_get_sockinfo(int sock, uint16_t *instream, uint16_t *outstream, int sctp_get_sockinfo(int sock, uint16_t *instream, uint16_t *outstream,
uint32_t *assoc_id) int32_t *assoc_id)
{ {
socklen_t i; socklen_t i;
struct sctp_status status; struct sctp_status status;
...@@ -95,7 +95,7 @@ int sctp_get_sockinfo(int sock, uint16_t *instream, uint16_t *outstream, ...@@ -95,7 +95,7 @@ int sctp_get_sockinfo(int sock, uint16_t *instream, uint16_t *outstream,
memset(&status, 0, sizeof(struct sctp_status)); memset(&status, 0, sizeof(struct sctp_status));
i = sizeof(struct sctp_status); i = sizeof(struct sctp_status);
if(getsockopt(sock, IPPROTO_SCTP, SCTP_STATUS, &status, &i) < 0) { if (getsockopt(sock, IPPROTO_SCTP, SCTP_STATUS, &status, &i) < 0) {
SCTP_ERROR("Getsockopt SCTP_STATUS failed: %s\n", strerror(errno)); SCTP_ERROR("Getsockopt SCTP_STATUS failed: %s\n", strerror(errno));
return -1; return -1;
} }
......
...@@ -47,6 +47,11 @@ ...@@ -47,6 +47,11 @@
# define SCTP_ERROR(x, args...) LOG_E(SCTP, x, ##args) # define SCTP_ERROR(x, args...) LOG_E(SCTP, x, ##args)
# define SCTP_WARN(x, args...) LOG_W(SCTP, x, ##args) # define SCTP_WARN(x, args...) LOG_W(SCTP, x, ##args)
# define SCTP_DEBUG(x, args...) LOG_D(SCTP, x, ##args) # define SCTP_DEBUG(x, args...) LOG_D(SCTP, x, ##args)
# define SCTP_OUT_STREAMS (64)
# define SCTP_IN_STREAMS (64)
# define SCTP_MAX_ATTEMPTS (5)
# define SCTP_RECV_BUFFER_SIZE (1024)
#else #else
# define SCTP_ERROR(x, args...) do { fprintf(stderr, "[SCTP][E]"x, ##args); } while(0) # define SCTP_ERROR(x, args...) do { fprintf(stderr, "[SCTP][E]"x, ##args); } while(0)
# define SCTP_DEBUG(x, args...) do { fprintf(stdout, "[SCTP][D]"x, ##args); } while(0) # define SCTP_DEBUG(x, args...) do { fprintf(stdout, "[SCTP][D]"x, ##args); } while(0)
...@@ -57,7 +62,7 @@ int sctp_set_init_opt(int sd, uint16_t instreams, uint16_t outstreams, ...@@ -57,7 +62,7 @@ int sctp_set_init_opt(int sd, uint16_t instreams, uint16_t outstreams,
uint16_t max_attempts, uint16_t init_timeout); uint16_t max_attempts, uint16_t init_timeout);
int sctp_get_sockinfo(int sock, uint16_t *instream, uint16_t *outstream, int sctp_get_sockinfo(int sock, uint16_t *instream, uint16_t *outstream,
uint32_t *assoc_id); int32_t *assoc_id);
int sctp_get_peeraddresses(int sock, struct sockaddr **remote_addr, int sctp_get_peeraddresses(int sock, struct sockaddr **remote_addr,
int *nb_remote_addresses); int *nb_remote_addresses);
......
#include "intertask_interface.h"
#include "sctp_common.h"
#include "sctp_eNB_itti_messaging.h"
int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t *buffer,
uint32_t buffer_length, uint16_t stream)
{
MessageDef *message_p;
sctp_data_ind_t *sctp_data_ind_p;
message_p = itti_alloc_new_message(TASK_SCTP, SCTP_DATA_IND);
sctp_data_ind_p = &message_p->msg.sctp_data_ind;
sctp_data_ind_p->buffer = malloc(sizeof(uint8_t) * buffer_length);
/* Copy the buffer */
memcpy((void *)sctp_data_ind_p->buffer, (void *)buffer, buffer_length);
sctp_data_ind_p->stream = stream;
sctp_data_ind_p->buffer_length = buffer_length;
sctp_data_ind_p->assoc_id = assoc_id;
return itti_send_msg_to_task(task_id, INSTANCE_DEFAULT, message_p);
}
#ifndef SCTP_ITTI_MESSAGING_H_
#define SCTP_ITTI_MESSAGING_H_
int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t *buffer,
uint32_t buffer_length, uint16_t stream);
#endif /* SCTP_ITTI_MESSAGING_H_ */
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
*******************************************************************************/
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include "assertions.h"
#include "queue.h"
#include "intertask_interface.h"
#include "sctp_common.h"
#include "sctp_eNB_itti_messaging.h"
struct sctp_cnx_list_elm_s {
STAILQ_ENTRY(sctp_cnx_list_elm_s) entries;
/* Socket descriptor of connection */
int sd;
/* IN/OUT streams */
uint16_t in_streams;
uint16_t out_streams;
/* Configured PPID */
uint16_t ppid;
/* Association id */
int32_t assoc_id;
/* Nb of messages received on interface */
uint32_t nb_messages;
/* Task id of the task who asked for this connection */
task_id_t task_id;
/* Upper layer identifier */
uint16_t cnx_id;
};
static STAILQ_HEAD(sctp_cnx_list_head, sctp_cnx_list_elm_s) sctp_cnx_list;
static uint16_t sctp_nb_cnx = 0;
struct sctp_cnx_list_elm_s *sctp_get_cnx(int32_t assoc_id, int sd)
{
struct sctp_cnx_list_elm_s *elm;
STAILQ_FOREACH(elm, &sctp_cnx_list, entries)
{
if (assoc_id != -1) {
if (elm->assoc_id == assoc_id) {
return elm;
}
} else {
if (elm->sd == sd) {
return elm;
}
}
}
return NULL;
}
void sctp_handle_new_association_req(
const task_id_t requestor,
const sctp_new_association_req_t * const sctp_new_association_req_p)
{
int sd;
int32_t assoc_id;
struct sctp_initmsg init;
struct sctp_event_subscribe events;
/* Prepare a new SCTP association as requested by upper layer and try to connect
* to remote host.
*/
DevAssert(sctp_new_association_req_p != NULL);
/* Create new socket with IPv6 affinity */
if ((sd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) {
SCTP_ERROR("Socket creation failed: %s\n", strerror(errno));
return;
}
/* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd(TASK_SCTP, sd);
/* Request a number of in/out streams */
init.sinit_num_ostreams = SCTP_OUT_STREAMS;
init.sinit_max_instreams = SCTP_IN_STREAMS;
init.sinit_max_attempts = SCTP_MAX_ATTEMPTS;
SCTP_DEBUG("Requesting (%d %d) (in out) streams\n", init.sinit_num_ostreams,
init.sinit_max_instreams);
if (setsockopt(sd, IPPROTO_SCTP, SCTP_INITMSG,
&init, (socklen_t)sizeof(struct sctp_initmsg)) < 0) {
SCTP_ERROR("Setsockopt IPPROTO_SCTP_INITMSG failed: %s\n",
strerror(errno));
return;
}
/* Subscribe to all events */
memset((void *)&events, 1, sizeof(struct sctp_event_subscribe));
if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &events,
sizeof(struct sctp_event_subscribe)) < 0) {
SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n",
strerror(errno));
return;
}
/* SOCK_STREAM socket type requires an explicit connect to the remote host
* address and port.
* Only use IPv4 for the first connection attempt
*/
{
uint8_t address_index = 0;
uint8_t used_address = sctp_new_association_req_p->remote_address.ipv6 +
sctp_new_association_req_p->remote_address.ipv4;
struct sockaddr_in addr[used_address];
memset(addr, 0, used_address * sizeof(struct sockaddr_in));
if (sctp_new_association_req_p->remote_address.ipv6 == 1) {
if (inet_pton(AF_INET6, sctp_new_association_req_p->remote_address.ipv6_address,
&addr[address_index].sin_addr.s_addr) != 1)
{
SCTP_ERROR("Failed to convert ipv6 address %*s to network type\n",
strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
return;
}
SCTP_DEBUG("Converted ipv6 address %*s to network type\n",
strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
addr[address_index].sin_family = AF_INET6;
addr[address_index].sin_port = htons(sctp_new_association_req_p->port);
address_index++;
}
if (sctp_new_association_req_p->remote_address.ipv4 == 1) {
if (inet_pton(AF_INET, sctp_new_association_req_p->remote_address.ipv4_address,
&addr[address_index].sin_addr.s_addr) != 1)
{
SCTP_ERROR("Failed to convert ipv4 address %*s to network type\n",
strlen(sctp_new_association_req_p->remote_address.ipv4_address),
sctp_new_association_req_p->remote_address.ipv4_address);
return;
}
SCTP_DEBUG("Converted ipv4 address %*s to network type\n",
strlen(sctp_new_association_req_p->remote_address.ipv4_address),
sctp_new_association_req_p->remote_address.ipv4_address);
addr[address_index].sin_family = AF_INET;
addr[address_index].sin_port = htons(sctp_new_association_req_p->port);
address_index++;
}
SCTP_DEBUG("Connecting...\n");
/* Connect to remote host and port */
if (sctp_connectx(sd, (struct sockaddr *)addr, used_address, &assoc_id) < 0) {
SCTP_ERROR("Connect failed: %s\n", strerror(errno));
return;
}
SCTP_DEBUG("Connected... assoc_id %u\n", assoc_id);
}
if (sctp_get_peeraddresses(sd, NULL, NULL) != 0) {
/* TODO Failure -> notify upper layer */
} else {
MessageDef *new_message_p;
sctp_new_association_resp_t *sctp_new_association_resp;
struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
sctp_cnx = calloc(1, sizeof(*sctp_cnx));
sctp_cnx->sd = sd;
sctp_cnx->task_id = requestor;
sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id;
sctp_cnx->ppid = sctp_new_association_req_p->ppid;
/* Get socket info */
sctp_get_sockinfo(sd,
&sctp_cnx->in_streams,
&sctp_cnx->out_streams,
&sctp_cnx->assoc_id);
/* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries);
sctp_nb_cnx++;
SCTP_DEBUG("Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d\n",
sd, sctp_nb_cnx, assoc_id);
new_message_p = itti_alloc_new_message(TASK_SCTP, SCTP_NEW_ASSOCIATION_RESP);
sctp_new_association_resp = &new_message_p->msg.sctp_new_association_resp;
sctp_new_association_resp->in_streams = sctp_cnx->in_streams;
sctp_new_association_resp->out_streams = sctp_cnx->out_streams;
sctp_new_association_resp->sctp_state = SCTP_STATE_ESTABLISHED;
sctp_new_association_resp->ulp_cnx_id = sctp_new_association_req_p->ulp_cnx_id;
sctp_new_association_resp->assoc_id = sctp_cnx->assoc_id;
SCTP_DEBUG("Sending SCTP new association resp message to %s\n",
itti_get_task_name(requestor));
itti_send_msg_to_task(requestor, INSTANCE_DEFAULT, new_message_p);
}
}
void sctp_send_data(task_id_t task_id, sctp_data_req_t *sctp_data_req_p)
{
struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
DevAssert(sctp_data_req_p != NULL);
sctp_cnx = sctp_get_cnx(sctp_data_req_p->assoc_id, 0);
if (sctp_cnx == NULL) {
SCTP_ERROR("Failed to find SCTP description for assoc_id %d\n",
sctp_data_req_p->assoc_id);
/* TODO: notify upper layer */
return;
}
if (sctp_data_req_p->stream >= sctp_cnx->out_streams) {
SCTP_ERROR("Requested stream (%u) >= nb out streams\n",
sctp_data_req_p->stream, sctp_cnx->out_streams);
return;
}
/* Send message on specified stream of the sd association
* NOTE: PPID should be defined in network order
*/
if (sctp_sendmsg(sctp_cnx->sd, sctp_data_req_p->buffer,
sctp_data_req_p->buffer_length, NULL, 0,
htonl(sctp_cnx->ppid), 0, sctp_data_req_p->stream, 0, 0) < 0) {
SCTP_ERROR("Sctp_sendmsg failed: %s\n", strerror(errno));
/* TODO: notify upper lkayer */
return;
}
SCTP_DEBUG("Successfully sent %u bytes on stream %d for assoc_id %u\n",
sctp_data_req_p->buffer_length, sctp_data_req_p->stream,
sctp_cnx->assoc_id);
}
static
inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx)
{
int flags = 0, n;
socklen_t from_len;
struct sctp_sndrcvinfo sinfo;
struct sockaddr_in addr;
uint8_t buffer[SCTP_RECV_BUFFER_SIZE];
DevAssert(sctp_cnx != NULL);
memset((void *)&addr, 0, sizeof(struct sockaddr_in));
from_len = (socklen_t)sizeof(struct sockaddr_in);
memset((void *)&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
n = sctp_recvmsg(sctp_cnx->sd, (void *)buffer, SCTP_RECV_BUFFER_SIZE,
(struct sockaddr *)&addr, &from_len,
&sinfo, &flags);
if (n < 0) {
SCTP_DEBUG("An error occured during read\n");
SCTP_ERROR("sctp_recvmsg: %s:%d\n", strerror(errno), errno);
return;
}
if (flags & MSG_NOTIFICATION) {
union sctp_notification *snp;
snp = (union sctp_notification *)buffer;
/* Client deconnection */
if (SCTP_SHUTDOWN_EVENT == snp->sn_header.sn_type) {
DevMessage("Other peer has requested a com down -> not handled\n");
// return sctp_handle_com_down(snp->sn_shutdown_event.sse_assoc_id);
itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd);
}
/* Association has changed. */
else if (SCTP_ASSOC_CHANGE == snp->sn_header.sn_type) {
struct sctp_assoc_change *sctp_assoc_changed;
sctp_assoc_changed = &snp->sn_assoc_change;
SCTP_DEBUG("Client association changed: %d\n", sctp_assoc_changed->sac_state);
/* New physical association requested by a peer */
switch (sctp_assoc_changed->sac_state) {
case SCTP_COMM_UP: {
// struct sctp_association_s *new_association;
//
// sctp_get_sockinfo(sd, NULL, NULL, NULL);
//
// SCTP_DEBUG("New connection\n");
// if ((new_association = sctp_add_new_peer()) == NULL) {
// // TODO: handle this case
// DevMessage("Unexpected error...\n");
// return SCTP_RC_ERROR;
// } else {
// new_association->sd = sd;
// new_association->ppid = ppid;
// new_association->instreams = sctp_assoc_changed->sac_inbound_streams;
// new_association->outstreams = sctp_assoc_changed->sac_outbound_streams;
// new_association->assoc_id = sctp_assoc_changed->sac_assoc_id;
//
// sctp_get_localaddresses(sd, NULL, NULL);
// sctp_get_peeraddresses(sd, &new_association->peer_addresses,
// &new_association->nb_peer_addresses);
//
// if (sctp_itti_send_new_association(
// new_association->assoc_id, new_association->instreams,
// new_association->outstreams) < 0)
// {
// SCTP_ERROR("Failed to send message to S1AP\n");
// return SCTP_RC_ERROR;
// }
// }
} break;
default:
break;
}
}
} else {
sctp_cnx->nb_messages++;
if (sinfo.sinfo_ppid != sctp_cnx->ppid) {
/* Mismatch in Payload Protocol Identifier,
* may be we received unsollicited traffic from stack other than S1AP.
*/
SCTP_ERROR("Received data from peer with unsollicited PPID %d, expecting %d\n",
sinfo.sinfo_ppid, sctp_cnx->ppid);
}
SCTP_DEBUG("[%d][%d] Msg of length %d received from port %u, on stream %d, PPID %d\n",
sinfo.sinfo_assoc_id, sctp_cnx->sd, n, ntohs(addr.sin_port),
sinfo.sinfo_stream, sinfo.sinfo_ppid);
sctp_itti_send_new_message_ind(sctp_cnx->task_id,
sinfo.sinfo_assoc_id,
buffer, n, sinfo.sinfo_stream);
}
}
void sctp_eNB_flush_sockets(struct epoll_event *events, int nb_events)
{
int i;
struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
if (events == NULL) {
return;
}
for (i = 0; i < nb_events; i++) {
sctp_cnx = sctp_get_cnx(-1, events[i].data.fd);
if (sctp_cnx == NULL) {
continue;
}
SCTP_DEBUG("Found data for descriptor %d\n", events[i].data.fd);
sctp_eNB_read_from_socket(sctp_cnx);
}
}
void *sctp_eNB_task(void *arg)
{
int nb_events;
struct epoll_event *events;
MessageDef *received_msg = NULL;
SCTP_DEBUG("Starting SCTP layer\n");
STAILQ_INIT(&sctp_cnx_list);
itti_mark_task_ready(TASK_SCTP);
while (1) {
itti_receive_msg(TASK_SCTP, &received_msg);
/* Check if there is a packet to handle */
if (received_msg != NULL) {
switch (received_msg->header.messageId) {
case TERMINATE_MESSAGE:
itti_exit_task();
break;
case SCTP_NEW_ASSOCIATION_REQ: {
sctp_handle_new_association_req(received_msg->header.originTaskId,
&received_msg->msg.sctp_new_association_req);
} break;
case SCTP_DATA_REQ: {
sctp_send_data(received_msg->header.originTaskId,
&received_msg->msg.sctp_data_req);
} break;
default:
SCTP_ERROR("Received unhandled message with id %d\n",
received_msg->header.messageId);
break;
}
}
free(received_msg);
received_msg = NULL;
nb_events = itti_get_events(TASK_SCTP, &events);
/* Now handle notifications for other sockets */
sctp_eNB_flush_sockets(events, nb_events);
}
return NULL;
}
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
*******************************************************************************/
#ifndef SCTP_ENB_TASK_H_
#define SCTP_ENB_TASK_H_
void *sctp_eNB_task(void *arg);
#endif /* SCTP_ENB_TASK_H_ */
...@@ -4,3 +4,5 @@ ...@@ -4,3 +4,5 @@
// Messages files used between tasks // Messages files used between tasks
#include "rrc_messages_def.h" #include "rrc_messages_def.h"
#include "s1ap_messages_def.h"
#include "sctp_messages_def.h"
\ No newline at end of file
...@@ -11,5 +11,7 @@ ...@@ -11,5 +11,7 @@
#include "timer_messages_types.h" #include "timer_messages_types.h"
#include "rrc_messages_types.h" #include "rrc_messages_types.h"
#include "s1ap_messages_types.h"
#include "sctp_messages_types.h"
#endif /* MESSAGES_TYPES_H_ */ #endif /* MESSAGES_TYPES_H_ */
MESSAGE_DEF(S1AP_REGISTER_ENB, MESSAGE_PRIORITY_MED, s1ap_register_eNB_t, s1ap_register_eNB)
#ifndef S1AP_MESSAGES_TYPES_H_
#define S1AP_MESSAGES_TYPES_H_
enum cell_type_e {
CELL_MACRO_ENB,
CELL_HOME_ENB
};
typedef enum {
PAGING_DRX_32 = 0x0,
PAGING_DRX_64 = 0x1,
PAGING_DRX_128 = 0x2,
PAGING_DRX_256 = 0x3,
} paging_drx_t;
typedef struct {
unsigned ipv4:1;
unsigned ipv6:1;
char ipv4_address[16];
char ipv6_address[40];
} net_ip_address_t;
#define S1AP_MAX_NB_MME_IP_ADDRESS 10
typedef struct {
/* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
uint8_t mod_id;
/* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long.
* For home eNB ids this field should be 28 bits long.
*/
uint32_t eNB_id;
/* The type of the cell */
enum cell_type_e cell_type;
/* Optional name for the cell
* NOTE: the name can be NULL (i.e no name) and will be cropped to 150
* characters.
*/
char *eNB_name;
/* Tracking area code */
uint16_t tac;
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t mcc;
uint16_t mnc;
/* Default Paging DRX of the eNB as defined in TS 36.304 */
paging_drx_t default_drx;
/* The eNB IP address to bind */
net_ip_address_t enb_ip_address;
/* Nb of MME to connect to */
uint8_t nb_mme;
/* List of MME to connect to */
net_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS];
} s1ap_register_eNB_t;
#endif /* S1AP_MESSAGES_TYPES_H_ */
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ , MESSAGE_PRIORITY_MED, sctp_new_association_req_t , sctp_new_association_req)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_RESP, MESSAGE_PRIORITY_MED, sctp_new_association_resp_t , sctp_new_association_resp)
MESSAGE_DEF(SCTP_REGISTER_UPPER_LAYER, MESSAGE_PRIORITY_MED, sctp_listener_register_upper_layer_t, sctp_listener_register_upper_layer)
MESSAGE_DEF(SCTP_DATA_REQ, MESSAGE_PRIORITY_MED, sctp_data_req_t , sctp_data_req)
MESSAGE_DEF(SCTP_DATA_IND, MESSAGE_PRIORITY_MED, sctp_data_ind_t , sctp_data_ind)
\ No newline at end of file
#ifndef SCTP_MESSAGES_TYPES_H_
#define SCTP_MESSAGES_TYPES_H_
enum sctp_state_e {
SCTP_STATE_CLOSED,
SCTP_STATE_SHUTDOWN_PENDING,
SCTP_STATE_ESTABLISHED
};
typedef struct {
/* Module id: used in virtual mode */
uint8_t mod_id;
/* Upper layer connexion identifier */
uint16_t ulp_cnx_id;
/* The port to connect to */
uint16_t port;
/* Payload Protocol Identifier to use */
uint32_t ppid;
/* Local address to bind to */
net_ip_address_t local_address;
/* Remote address to connect to */
net_ip_address_t remote_address;
} sctp_new_association_req_t;
typedef struct {
/* Module id: used in virtual mode */
uint8_t mod_id;
/* Upper layer connexion identifier */
uint16_t ulp_cnx_id;
/* SCTP Association ID */
int32_t assoc_id;
/* Input/output streams */
uint16_t out_streams;
uint16_t in_streams;
/* State of the association at SCTP level */
enum sctp_state_e sctp_state;
} sctp_new_association_resp_t;
typedef struct {
int32_t assoc_id;
uint32_t buffer_length;
uint8_t *buffer;
/* Streams on which data will be sent/received */
uint16_t stream;
} sctp_data_ind_t;
typedef sctp_data_ind_t sctp_data_req_t;
typedef struct {
/* Port to listen to */
uint16_t port;
/* Payload protocol identifier
* Any data receveid on PPID != will be discarded
*/
uint32_t ppid;
} sctp_listener_register_upper_layer_t;
#endif /* SCTP_MESSAGES_TYPES_H_ */
...@@ -31,3 +31,6 @@ TASK_DEF(TASK_NAS_UE, TASK_PRIORITY_MED) ...@@ -31,3 +31,6 @@ TASK_DEF(TASK_NAS_UE, TASK_PRIORITY_MED)
/// S1ap task for eNodeB /// S1ap task for eNodeB
TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED) TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED)
/// Sctp task for eNodeB (Used by both S1AP and X2AP)
TASK_DEF(TASK_SCTP, TASK_PRIORITY_MED)
...@@ -476,11 +476,13 @@ openair_rrc_lite_eNB_init (u8 Mod_id) ...@@ -476,11 +476,13 @@ openair_rrc_lite_eNB_init (u8 Mod_id)
/* Connect eNB to MME */ /* Connect eNB to MME */
if (oai_emulation.info.mme_enabled > 0) if (oai_emulation.info.mme_enabled > 0)
{ {
# if !defined(ENABLE_ITTI)
if (s1ap_eNB_init (oai_emulation.info.mme_ip_address, Mod_id) < 0) if (s1ap_eNB_init (oai_emulation.info.mme_ip_address, Mod_id) < 0)
{ {
mac_xface->macphy_exit (""); mac_xface->macphy_exit ("");
return -1; return -1;
} }
# endif
} }
#endif #endif
...@@ -796,7 +798,7 @@ rrc_eNB_decode_dcch (u8 Mod_id, u32 frame, u8 Srb_id, u8 UE_index, ...@@ -796,7 +798,7 @@ rrc_eNB_decode_dcch (u8 Mod_id, u32 frame, u8 Srb_id, u8 UE_index,
case UL_DCCH_MessageType__c1_PR_ulHandoverPreparationTransfer: case UL_DCCH_MessageType__c1_PR_ulHandoverPreparationTransfer:
break; break;
case UL_DCCH_MessageType__c1_PR_ulInformationTransfer: case UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
#if defined(ENABLE_USE_MME) #if defined(ENABLE_USE_MME) && !defined(ENABLE_ITTI)
{ {
if (oai_emulation.info.mme_enabled == 1) if (oai_emulation.info.mme_enabled == 1)
{ {
...@@ -1053,7 +1055,7 @@ rrc_eNB_process_RRCConnectionSetupComplete (u8 Mod_id, ...@@ -1053,7 +1055,7 @@ rrc_eNB_process_RRCConnectionSetupComplete (u8 Mod_id,
Mod_id, frame, UE_index); Mod_id, frame, UE_index);
// Forward message to S1AP layer // Forward message to S1AP layer
#if defined(ENABLE_USE_MME) #if defined(ENABLE_USE_MME) && !defined(ENABLE_ITTI)
if (oai_emulation.info.mme_enabled == 1) if (oai_emulation.info.mme_enabled == 1)
s1ap_eNB_new_data_request (Mod_id, UE_index, s1ap_eNB_new_data_request (Mod_id, UE_index,
rrcConnectionSetupComplete->dedicatedInfoNAS. rrcConnectionSetupComplete->dedicatedInfoNAS.
......
...@@ -10,7 +10,6 @@ OMG_DIR=$(OPENAIR2_TOP)/UTIL/OMG ...@@ -10,7 +10,6 @@ OMG_DIR=$(OPENAIR2_TOP)/UTIL/OMG
OTG_DIR=$(OPENAIR2_TOP)/UTIL/OTG OTG_DIR=$(OPENAIR2_TOP)/UTIL/OTG
CLI_DIR=$(OPENAIR2_TOP)/UTIL/CLI CLI_DIR=$(OPENAIR2_TOP)/UTIL/CLI
OMV_DIR=$(OPENAIR2_TOP)/UTIL/OMV OMV_DIR=$(OPENAIR2_TOP)/UTIL/OMV
SCTP_DIR=$(OPENAIR2_TOP)/UTIL/SCTP
LFDS_DIR=$(OPENAIR2_TOP)/UTIL/LFDS/liblfds6.1.1/liblfds611 LFDS_DIR=$(OPENAIR2_TOP)/UTIL/LFDS/liblfds6.1.1/liblfds611
OSA_DIR=$(OPENAIR2_TOP)/UTIL/OSA OSA_DIR=$(OPENAIR2_TOP)/UTIL/OSA
...@@ -71,12 +70,19 @@ CLI_OBJ = $(CLI_DIR)/cli_server.o ...@@ -71,12 +70,19 @@ CLI_OBJ = $(CLI_DIR)/cli_server.o
CLI_OBJ += $(CLI_DIR)/cli.o CLI_OBJ += $(CLI_DIR)/cli.o
CLI_OBJ += $(CLI_DIR)/cli_cmd.o CLI_OBJ += $(CLI_DIR)/cli_cmd.o
ifdef $(USE_MME) UTIL_OBJ = \
SCTP_OBJS = $(SCTP_DIR)/sctp_primitives_client.o $(OSA_OBJS) \
else $(FIFO_OBJ) \
SCTP_OBJS = $(LIST_OBJ) \
endif $(TIMER_OBJ) \
UTIL_OBJ = $(OSA_OBJS) $(FIFO_OBJ) $(LIST_OBJ) $(TIMER_OBJ) $(MEM_OBJ) $(LOG_OBJS) $(OCG_OBJS) $(MATH_OBJS) $(OTG_OBJS) $(CLI_OBJ) $(OMG_OBJS) $(OPT_OBJS) $(SCTP_OBJS) $(MEM_OBJ) \
$(LOG_OBJS) \
$(OCG_OBJS) \
$(MATH_OBJS) \
$(OTG_OBJS) \
$(CLI_OBJ) \
$(OMG_OBJS) \
$(OPT_OBJS)
UTIL_incl = \ UTIL_incl = \
-I$(OPENAIR2_TOP)/UTIL \ -I$(OPENAIR2_TOP)/UTIL \
...@@ -93,5 +99,4 @@ UTIL_incl = \ ...@@ -93,5 +99,4 @@ UTIL_incl = \
-I$(OTG_DIR) \ -I$(OTG_DIR) \
-I$(CLI_DIR) \ -I$(CLI_DIR) \
-I$(OPT_DIR) \ -I$(OPT_DIR) \
-I$(OMV_DIR) \ -I$(OMV_DIR)
-I$(SCTP_DIR)
CC = gcc # Include some standard directives
MPICC = gcc #mpicc include Makerules
RM_F_V = rm -f -v
CPUFLAGS = -mmmx -msse -msse2 -msse4.1 -march=native CPUFLAGS = -mmmx -msse -msse2 -msse4.1 -march=native
# FORCE ssse3 for compilation of openair on User Mode Linux # FORCE ssse3 for compilation of openair on User Mode Linux
...@@ -8,8 +7,6 @@ CPUFLAGS += $(shell if grep --silent ssse3 /proc/cpuinfo ; then echo "-mssse3" ; ...@@ -8,8 +7,6 @@ CPUFLAGS += $(shell if grep --silent ssse3 /proc/cpuinfo ; then echo "-mssse3" ;
CPUFLAGS += $(shell if grep --silent sse4 /proc/cpuinfo ; then echo "-msse4" ; else echo ""; fi) CPUFLAGS += $(shell if grep --silent sse4 /proc/cpuinfo ; then echo "-msse4" ; else echo ""; fi)
linux = $(shell if [ `uname` = "Linux" ] ; then echo "1" ; else echo "0" ; fi) linux = $(shell if [ `uname` = "Linux" ] ; then echo "1" ; else echo "0" ; fi)
NUM_CORES=$(shell cat /proc/cpuinfo | grep processor | wc -l)
COMMON_UTILS_DIR = $(OPENAIR_HOME)/common/utils COMMON_UTILS_DIR = $(OPENAIR_HOME)/common/utils
TOP_DIR = $(OPENAIR1_DIR) TOP_DIR = $(OPENAIR1_DIR)
OPENAIR1_TOP = $(OPENAIR1_DIR) OPENAIR1_TOP = $(OPENAIR1_DIR)
...@@ -17,6 +14,12 @@ OPENAIR2_TOP = $(OPENAIR2_DIR) ...@@ -17,6 +14,12 @@ OPENAIR2_TOP = $(OPENAIR2_DIR)
OPENAIR3_TOP = $(OPENAIR3_DIR) OPENAIR3_TOP = $(OPENAIR3_DIR)
OPENAIR3 = $(OPENAIR3_DIR) OPENAIR3 = $(OPENAIR3_DIR)
S1AP_DIR = $(OPENAIR_HOME)/openair-cn/S1AP
SCTP_DIR = $(OPENAIR_HOME)/openair-cn/SCTP
export S1AP_DIR
export COMMON_UTILS_DIR
CFLAGS = -Wall -fno-strict-aliasing -DUSER_MODE -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -g -ggdb $(CPUFLAGS) -I/usr/include/X11 #-Wno-packed-bitfield-compat CFLAGS = -Wall -fno-strict-aliasing -DUSER_MODE -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -g -ggdb $(CPUFLAGS) -I/usr/include/X11 #-Wno-packed-bitfield-compat
ifdef ENABLE_ITTI ifdef ENABLE_ITTI
...@@ -172,9 +175,6 @@ UPDATE_RELEASE_9=1 ...@@ -172,9 +175,6 @@ UPDATE_RELEASE_9=1
endif endif
ifdef SECU ifdef SECU
NETTLE_FOUND = $(shell if pkg-config --exists nettle; then echo "1" ; else echo "0"; fi)
OPENSSL_FOUND = $(shell if pkg-config --exists openssl; then echo "1" ; else echo "0"; fi)
ifeq ($(NETTLE_FOUND), 0) ifeq ($(NETTLE_FOUND), 0)
@echo "Nettle library >= 2.5 is not installed on your system, continuing with security disabled" @echo "Nettle library >= 2.5 is not installed on your system, continuing with security disabled"
SECU=0 SECU=0
...@@ -204,15 +204,6 @@ include $(OPENAIR2_DIR)/S1AP/MESSAGES/Makefile.inc ...@@ -204,15 +204,6 @@ include $(OPENAIR2_DIR)/S1AP/MESSAGES/Makefile.inc
#LOG_OBJS += $(LOG_DIR)/vcd_signal_dumper.o #LOG_OBJS += $(LOG_DIR)/vcd_signal_dumper.o
#LOG_OBJS += $(LOG_DIR)/log.o #LOG_OBJS += $(LOG_DIR)/log.o
CFLAGS += -DENB_MODE
S1AP_BUILT_OBJS=
ifdef USE_MME
CFLAGS += -DENABLE_USE_MME
CFLAGS_S1AP += -DENB_MODE -DENABLE_USE_MME -DEMIT_ASN_DEBUG=1 -DUSER_MODE
S1AP_BUILT_OBJS += $(S1AP_OBJS) $(addprefix $(OPENAIR2_DIR)/S1AP/MESSAGES/, $(S1AP_ASN_MODULE_SOURCES))
endif
ITTI_MESSAGES_H = messages_xml.h ITTI_MESSAGES_H = messages_xml.h
ITTI_MESSAGES_XML = messages.xml ITTI_MESSAGES_XML = messages.xml
...@@ -274,8 +265,7 @@ endif ...@@ -274,8 +265,7 @@ endif
# Check if libpgm is installed and use it if found instead of the unreliable # Check if libpgm is installed and use it if found instead of the unreliable
# multicast # multicast
ENABLE_PGM = $(shell if pkg-config --exists openpgm-5.1; then echo "1" ; else echo "0"; fi) ifeq ($(PGM_FOUND), 1)
ifeq ($(ENABLE_PGM), 1)
CFLAGS += `pkg-config --cflags openpgm-5.1` -DENABLE_PGM_TRANSPORT CFLAGS += `pkg-config --cflags openpgm-5.1` -DENABLE_PGM_TRANSPORT
PGM_LDFLAGS = `pkg-config --libs openpgm-5.1` PGM_LDFLAGS = `pkg-config --libs openpgm-5.1`
endif endif
...@@ -285,9 +275,19 @@ ifeq ($(OPENAIR2),1) ...@@ -285,9 +275,19 @@ ifeq ($(OPENAIR2),1)
OBJ += $(L2_OBJS) OBJ += $(L2_OBJS)
endif endif
LIB = $(LFDS_DIR)/bin/liblfds611.a LIBS = $(LFDS_DIR)/bin/liblfds611.a
ifdef USE_MME ifdef USE_MME
LIB += $(S1AP_DIR)/libs1ap.a CFLAGS += -DENB_MODE -DENABLE_USE_MME -DENABLE_EVENT_FD -I$(S1AP_DIR) -I$(SCTP_DIR)
S1AP_CFLAGS = $(CFLAGS) -I$(TOP_DIR) $(L2_incl) $(UTIL_incl) $(UTILS_incl)
LIBS += $(S1AP_DIR)/libs1ap.a $(SCTP_DIR)/libsctp.a -lsctp
export S1AP_CFLAGS
$(S1AP_DIR)/libs1ap.a: force_look
$(MAKE) -C $(S1AP_DIR) -f Makefile.eNB libs1ap.a
$(SCTP_DIR)/libsctp.a: force_look
$(MAKE) -C $(SCTP_DIR) -f Makefile.eNB libsctp.a
endif endif
default: oaisim default: oaisim
...@@ -313,16 +313,6 @@ printvars: ...@@ -313,16 +313,6 @@ printvars:
@echo CFLAGS: $(CFLAGS) @echo CFLAGS: $(CFLAGS)
@echo Enable PGM: $(ENABLE_PGM) @echo Enable PGM: $(ENABLE_PGM)
ASN1RELDIR=R9.8
ifeq ($(USE_MME), R8)
ASN1RELDIR=R8.10
else
CFLAGS_S1AP += -DUPDATE_RELEASE_9
endif
S1AP_DIR=$(OPENAIR2_DIR)/S1AP
ASN1MESSAGESDIR=$(S1AP_DIR)/MESSAGES
ASN1DIR=$(ASN1MESSAGESDIR)/ASN1
-include $(ITTI_MESSAGES_XML:.xml=.d) -include $(ITTI_MESSAGES_XML:.xml=.d)
-include $(OBJ:.o=.d) -include $(OBJ:.o=.d)
-include $(OAISIM_OBJS:.o=.d) -include $(OAISIM_OBJS:.o=.d)
...@@ -333,7 +323,7 @@ ifdef ENABLE_ITTI ...@@ -333,7 +323,7 @@ ifdef ENABLE_ITTI
gccxml_available = $(shell if [ `gccxml --version | grep GCC-XML -c` = "0" ]; then echo "0" ; else echo "1" ; fi ) gccxml_available = $(shell if [ `gccxml --version | grep GCC-XML -c` = "0" ]; then echo "0" ; else echo "1" ; fi )
ifeq ($(gccxml_available), 0) ifeq ($(gccxml_available), 0)
$(error gccxml is missing, please install) $(error gccxml is missing, please install)
endif endif
endif endif
$(ITTI_MESSAGES_XML): $(ITTI_MESSAGES_FILE) $(ITTI_MESSAGES_XML): $(ITTI_MESSAGES_FILE)
...@@ -366,22 +356,6 @@ $(OBJ) $(OAISIM_OBJS) $(OAISIM_PAD_OBJS) $(ASN1_MSG_OBJS1): %.o : %.c ...@@ -366,22 +356,6 @@ $(OBJ) $(OAISIM_OBJS) $(OAISIM_PAD_OBJS) $(ASN1_MSG_OBJS1): %.o : %.c
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
@rm -f $*.d.tmp @rm -f $*.d.tmp
$(S1AP_BUILT_OBJS): %.o : %.c
@echo Compiling $<
@$(CC) -Wall -c $(CFLAGS_S1AP) $(S1AP_Incl) $(UTIL_incl) $(UTILS_incl) -o $@ $<
$(ASN1MESSAGESDIR)/s1ap_ieregen.stamp: $(ASN1DIR)/$(ASN1RELDIR)/S1AP-PDU-Contents.asn $(ASN1DIR)/asn1tostruct.py
echo Timestamp > $@
(cd $(ASN1DIR) && python $(ASN1DIR)/asn1tostruct.py -f$<)
$(ASN1MESSAGESDIR)/s1ap_asn1regen.stamp: $(ASN1DIR)/$(ASN1RELDIR)/S1AP-CommonDataTypes.asn $(ASN1DIR)/$(ASN1RELDIR)/S1AP-Constants.asn $(ASN1DIR)/$(ASN1RELDIR)/S1AP-IEs.asn $(ASN1DIR)/$(ASN1RELDIR)/S1AP-PDU.asn
echo Timestamp > $@
(cd $(ASN1MESSAGESDIR) && asn1c -gen-PER -fnative-types -fskeletons-copy $^)
$(S1AP_DIR)/libs1ap.a: $(ASN1MESSAGESDIR)/s1ap_ieregen.stamp $(ASN1MESSAGESDIR)/s1ap_asn1regen.stamp $(S1AP_BUILT_OBJS)
@echo Creating $@
$(AR) rcs $@ $^
$(LFDS_DIR)/bin/liblfds611.a: $(LFDS_DIR)/bin/liblfds611.a:
$(MAKE) -C $(LFDS_DIR) -f makefile.linux $(MAKE) -C $(LFDS_DIR) -f makefile.linux
...@@ -390,11 +364,11 @@ oaisim_pad: $(OBJ) $(OAISIM_PAD_OBJS) $(ASN1_MSG_OBJS1) ...@@ -390,11 +364,11 @@ oaisim_pad: $(OBJ) $(OAISIM_PAD_OBJS) $(ASN1_MSG_OBJS1)
@$(MPICC) -I$(TOP_DIR) $(L2_incl) $(UTIL_incl) $(UTILS_incl) -I$(ASN1_MSG_INC) $(S1AP_Incl) -o oaisim_pad $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(OAISIM_PAD_OBJS) $(ASN1_MSG_OBJS1) \ @$(MPICC) -I$(TOP_DIR) $(L2_incl) $(UTIL_incl) $(UTILS_incl) -I$(ASN1_MSG_INC) $(S1AP_Incl) -o oaisim_pad $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(OAISIM_PAD_OBJS) $(ASN1_MSG_OBJS1) \
-lm -lblas -lpthread -llapack_atlas -lforms -lxml2 -lX11 -lXpm -lrt -lm -lblas -lpthread -llapack_atlas -lforms -lxml2 -lX11 -lXpm -lrt
oaisim: $(OBJ) $(OAISIM_OBJS) $(ASN1_MSG_OBJS1) $(LIB) oaisim: $(OBJ) $(OAISIM_OBJS) $(ASN1_MSG_OBJS1) $(LIBS)
@echo "Linking oaisim ..." @echo "Linking oaisim ..."
@$(CC) -I$(TOP_DIR) $(L2_incl) $(UTIL_incl) $(UTILS_incl) -I$(ASN1_MSG_INC) $(S1AP_Incl) -o oaisim $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(OAISIM_OBJS) $(ASN1_MSG_OBJS1) \ @$(CC) -I$(TOP_DIR) $(L2_incl) $(UTIL_incl) $(UTILS_incl) -I$(ASN1_MSG_INC) $(S1AP_Incl) -o oaisim $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(OAISIM_OBJS) $(ASN1_MSG_OBJS1) \
-lm -lblas -lpthread -llapack_atlas -lforms -lxml2 -lX11 -lXpm -lrt \ -lm -lblas -lpthread -llapack_atlas -lforms -lxml2 -lX11 -lXpm -lrt \
$(LIB) $(PGM_LDFLAGS) $(DB_LDFLAGS) $(OSA_LDFLAGS) $(LIBS) $(PGM_LDFLAGS) $(DB_LDFLAGS) $(OSA_LDFLAGS)
ifeq ($(rrc_cellular_eNB),1) ifeq ($(rrc_cellular_eNB),1)
mv oaisim oaisim_eNB mv oaisim oaisim_eNB
...@@ -438,7 +412,7 @@ rrm_std_cellular: ...@@ -438,7 +412,7 @@ rrm_std_cellular:
( cd $(OPENAIR2_DIR)/NAS/SIMU_CELLULAR && make cell_rrm CELL_RRM=1 CELLULAR=1 NO_RRM=1) ( cd $(OPENAIR2_DIR)/NAS/SIMU_CELLULAR && make cell_rrm CELL_RRM=1 CELLULAR=1 NO_RRM=1)
cleanall: clean cleanasn1 cleanmmeasn1 cleanall: clean cleanasn1
clean: clean:
@$(MAKE) -C $(LFDS_DIR) -f makefile.linux clean @$(MAKE) -C $(LFDS_DIR) -f makefile.linux clean
...@@ -449,10 +423,10 @@ clean: ...@@ -449,10 +423,10 @@ clean:
@$(RM_F_V) $(OAISIM_OBJS) $(OAISIM_OBJS:.o=.d) @$(RM_F_V) $(OAISIM_OBJS) $(OAISIM_OBJS:.o=.d)
@$(RM_F_V) $(OAISIM_PAD_OBJS) $(OAISIM_PAD_OBJS:.o=.d) @$(RM_F_V) $(OAISIM_PAD_OBJS) $(OAISIM_PAD_OBJS:.o=.d)
@$(RM_F_V) $(ASN1_MSG_OBJS1) $(ASN1_MSG_OBJS1:.o=.d) @$(RM_F_V) $(ASN1_MSG_OBJS1) $(ASN1_MSG_OBJS1:.o=.d)
@$(RM_F_V) $(S1AP_BUILT_OBJS)
@$(RM_F_V) $(ASN1MESSAGESDIR)/libs1ap.a
@$(RM_F_V) *.exe* @$(RM_F_V) *.exe*
@$(RM_F_V) $(ASN1_MSG_INC)/asn1_msg.o @$(RM_F_V) $(ASN1_MSG_INC)/asn1_msg.o
@$(MAKE) -C $(S1AP_DIR) -f Makefile.eNB clean
@$(MAKE) -C $(SCTP_DIR) -f Makefile.eNB clean
cleanl1: cleanl1:
@$(RM_F_V) LOG_THREAD oaisim @$(RM_F_V) LOG_THREAD oaisim
...@@ -471,13 +445,7 @@ cleanasn1: ...@@ -471,13 +445,7 @@ cleanasn1:
@$(RM_F_V) $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/Makefile.inc.generated @$(RM_F_V) $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/Makefile.inc.generated
@$(RM_F_V) $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/asn1c/ASN1_files/.lock-rel10 @$(RM_F_V) $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/asn1c/ASN1_files/.lock-rel10
@$(RM_F_V) $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/asn1c/ASN1_files/.lock-rel8 @$(RM_F_V) $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/asn1c/ASN1_files/.lock-rel8
@$(MAKE) -C $(S1AP_DIR) -f Makefile.eNB cleanall
cleanmmeasn1:
@$(RM_F_V) $(S1AP_BUILT_OBJS)
@$(RM_F_V) $(S1AP_BUILT_OBJS:.o:.c)
@$(RM_F_V) $(ASN1MESSAGESDIR)/libs1ap.a
@$(RM_F_V) $(ASN1MESSAGESDIR)/s1ap_asn1regen.stamp
@$(RM_F_V) $(ASN1MESSAGESDIR)/s1ap_ieregen.stamp
cleancell: cleancell:
@$(RM_F_V) $(OPENAIR2_DIR)/RRC/CELLULAR/*.o @$(RM_F_V) $(OPENAIR2_DIR)/RRC/CELLULAR/*.o
...@@ -489,15 +457,15 @@ cleancell: ...@@ -489,15 +457,15 @@ cleancell:
print: print:
# @echo $(cygwin) # @echo $(cygwin)
@echo "OBJ " $(OBJ) @echo "OBJ " $(OBJ)
@echo "OAISIM_OBJS " $(OAISIM_OBJS) @echo "OAISIM_OBJS " $(OAISIM_OBJS)
@echo "OAISIM_PAD_OBJS " $(OAISIM_PAD_OBJS) @echo "OAISIM_PAD_OBJS " $(OAISIM_PAD_OBJS)
@echo "OCG_FLAG are " $(OCG_FLAG) @echo "OCG_FLAG are " $(OCG_FLAG)
@echo "CFLAGS are " $(CFLAGS) @echo "CFLAGS are " $(CFLAGS)
@echo "EXTRA_CFLAGS are" $(EXTRA_CFLAGS) @echo "EXTRA_CFLAGS are" $(EXTRA_CFLAGS)
@echo "L2 includes are" $(L2_incl) @echo "L2 includes are" $(L2_incl)
@echo "S1AP Includes are" $(S1AP_Incl) @echo "S1AP Includes are" $(S1AP_Incl)
@echo "TOP_DIR Include is" I$(TOP_DIR) @echo "TOP_DIR Include is" I$(TOP_DIR)
@echo "UTIL includes are" $(UTIL_incl) @echo "UTIL includes are" $(UTIL_incl)
@echo "UTILS includes are" $(UTILS_incl) @echo "UTILS includes are" $(UTILS_incl)
@echo "IS_REL8 is " $(IS_REL8) @echo "IS_REL8 is " $(IS_REL8)
...@@ -505,7 +473,11 @@ print: ...@@ -505,7 +473,11 @@ print:
@echo "ENABLE_DB is " $(ENABLE_DB) @echo "ENABLE_DB is " $(ENABLE_DB)
showcflags: showcflags:
@echo $(CFLAGS) @echo oaisim cflags: $(CFLAGS)
@$(MAKE) -C $(S1AP_DIR) -f Makefile.eNB showcflags
force_look:
true
otg_all: otg_latency otg_gp otg_all: otg_latency otg_gp
...@@ -537,10 +509,10 @@ ifeq ($(pexpect), 1) ...@@ -537,10 +509,10 @@ ifeq ($(pexpect), 1)
ifndef PW ifndef PW
@echo "Usage: make pre-ci PW=mypassword" @echo "Usage: make pre-ci PW=mypassword"
@echo "Password is used to access the local host through ssh." @echo "Password is used to access the local host through ssh."
python $(OPENAIR_TARGETS)/TEST/OAI/test01.py python $(OPENAIR_TARGETS)/TEST/OAI/test01.py
else else
python $(OPENAIR_TARGETS)/TEST/OAI/test01.py -w $(PW) python $(OPENAIR_TARGETS)/TEST/OAI/test01.py -w $(PW)
endif endif
else else
@echo "Python pexpect package is missing, please install" @echo "Python pexpect package is missing, please install"
endif endif
CC = gcc
MPICC = gcc #mpicc
RM_F_V = rm -f -v
NUM_CORES=$(shell cat /proc/cpuinfo | grep processor | wc -l)
NETTLE_FOUND = $(shell if pkg-config --exists nettle; then echo "1" ; else echo "0"; fi)
OPENSSL_FOUND = $(shell if pkg-config --exists openssl; then echo "1" ; else echo "0"; fi)
PGM_FOUND = $(shell if pkg-config --exists openpgm-5.1; then echo "1" ; else echo "0"; fi)
...@@ -73,6 +73,10 @@ char smbv_ip[16]; ...@@ -73,6 +73,10 @@ char smbv_ip[16];
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
# include "intertask_interface_init.h" # include "intertask_interface_init.h"
# include "timer.h" # include "timer.h"
# if defined(ENABLE_USE_MME)
# include "s1ap_eNB.h"
# include "sctp_eNB_task.h"
# endif
#endif #endif
#define RF #define RF
...@@ -381,6 +385,40 @@ void *l2l1_task(void *args_p) { ...@@ -381,6 +385,40 @@ void *l2l1_task(void *args_p) {
MessageDef *message_p; MessageDef *message_p;
itti_mark_task_ready (TASK_L2L1); itti_mark_task_ready (TASK_L2L1);
# if defined(ENABLE_USE_MME)
/* Trying to register each eNB */
for (eNB_id = oai_emulation.info.first_enb_local;
(eNB_id < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.cli_start_enb[eNB_id] == 1);
eNB_id++)
{
/* FIXME: acquire MMEs IP address by XML file or command line */
char *mme_address_v4 = "192.168.12.87";
char *mme_address_v6 = "2001:660:5502:12:30da:829a:2343:b6cf";
s1ap_register_eNB_t *s1ap_register_eNB;
message_p = itti_alloc_new_message(TASK_L2L1, S1AP_REGISTER_ENB);
s1ap_register_eNB = &message_p->msg.s1ap_register_eNB;
/* Some default/random parameters */
s1ap_register_eNB->mod_id = eNB_id;
/* FIXME: generate unique eNB id */
s1ap_register_eNB->eNB_id = 1 + eNB_id;
s1ap_register_eNB->cell_type = CELL_MACRO_ENB;
s1ap_register_eNB->tac = 8;
s1ap_register_eNB->mcc = 208;
s1ap_register_eNB->mnc = 35;
s1ap_register_eNB->default_drx = PAGING_DRX_256;
s1ap_register_eNB->nb_mme = 1;
s1ap_register_eNB->mme_ip_address[0].ipv4 = 1;
s1ap_register_eNB->mme_ip_address[0].ipv6 = 0;
memcpy(s1ap_register_eNB->mme_ip_address[0].ipv4_address, mme_address_v4,
strlen(mme_address_v4));
memcpy(s1ap_register_eNB->mme_ip_address[0].ipv6_address, mme_address_v6,
strlen(mme_address_v6));
itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
}
# endif
#endif #endif
for (frame = 0; frame < oai_emulation.info.n_frames; frame++) { for (frame = 0; frame < oai_emulation.info.n_frames; frame++) {
...@@ -987,6 +1025,19 @@ int main(int argc, char **argv) { ...@@ -987,6 +1025,19 @@ int main(int argc, char **argv) {
LOG_N(EMU, "\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU initialization done <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); LOG_N(EMU, "\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU initialization done <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
if (itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) {
LOG_E(EMU, "Create task failed");
LOG_D(EMU, "Initializing SCTP task interface: FAILED\n");
return -1;
}
if (itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL) < 0) {
LOG_E(EMU, "Create task failed");
LOG_D(EMU, "Initializing S1AP task interface: FAILED\n");
return -1;
}
# endif
if (itti_create_task(TASK_L2L1, l2l1_task, NULL) < 0) { if (itti_create_task(TASK_L2L1, l2l1_task, NULL) < 0) {
LOG_E(EMU, "Create task failed"); LOG_E(EMU, "Create task failed");
LOG_D(EMU, "Initializing L2L1 task interface: FAILED\n"); LOG_D(EMU, "Initializing L2L1 task interface: FAILED\n");
......
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