From 553f1d1a52845911be4ba61ec2bcc5c60ad42ae7 Mon Sep 17 00:00:00 2001 From: Laurent Thomas Date: Wed, 1 Feb 2023 15:22:38 +0100 Subject: [PATCH 1/7] Add basic E1 functionality With contributions from * Sakthivel Velumani * Robert Schmidt Squashed commit of the following: commit e8488acbcdaef6ee1688dc233c9e48e85b0fbfc8 Merge: f09468eb13 5d58645a85 Author: laurent Date: Sat Jan 21 15:03:40 2023 +0100 merge develop commit f09468eb13f729c49830786150918b03ae2d7524 Author: laurent Date: Fri Jan 20 10:43:51 2023 +0100 continue e1AP development commit 76545cfbfc7ec5031633b1b0ec599c3560c1e5a7 Author: laurent Date: Wed Jan 18 14:18:47 2023 +0100 fix regressions after merge develop commit 7071c480a6c433eb94501c49f4a7694ba77f4f6d Merge: 569b9fc5f3 214aa50595 Author: laurent Date: Mon Jan 16 15:51:50 2023 +0100 merge develop commit 569b9fc5f37b9947b722885e423572a211d658da Author: laurent Date: Wed Jan 4 17:07:01 2023 +0100 fix srb2 addition, simplify and remove dead code, fix one race commit 9fa89151c0f9b4a16a79d0685cc04d8cf2adfa44 Author: Sakthivel Velumani Date: Wed Jan 4 20:02:05 2023 +0530 Bearer context release decoder and encoder commit 7011cb518ed6df015ace536e9a08b2d1865188d9 Author: Sakthivel Velumani Date: Wed Jan 4 13:43:58 2023 +0530 Update documentation commit 3e8899fc962cb16fc1ded49590ca5dddede54978 Author: Sakthivel Velumani Date: Wed Jan 4 10:14:11 2023 +0530 Fix function arguments and warnings commit 989ad183a8d66961facaa6719fa7793b9d40d5b4 Author: Sakthivel Velumani Date: Tue Jan 3 20:18:31 2023 +0530 Moved E1-design.md to doc/ commit 04a8633dd509d9525755c5f3abfad976a1ba704e Author: Sakthivel Velumani Date: Tue Jan 3 20:13:46 2023 +0530 Make libraries lower case in CMakeLists commit 033ec174c1f48a0e745a2a2e1c367aa361f5ae76 Author: Sakthivel Velumani Date: Tue Jan 3 17:55:25 2023 +0530 Renamed and updated cucp cuup config files commit f76a6913352bd8b2bb73ac25f225140cf05f93f2 Author: Sakthivel Velumani Date: Tue Jan 3 13:31:19 2023 +0530 Removed CU-UP checks from nr-softmodem commit ae70afe44c84ac16b977b388c63e80e24803c43c Author: laurent Date: Mon Jan 2 13:01:45 2023 +0100 fix for gcc version hat doesnt accept declarations in switch commit 6a7a01043bf1e6e0ee9ac40b4d85ced7cdf6dcf4 Author: laurent Date: Tue Dec 27 15:59:28 2022 +0100 first functional commit standalone cu-up commit 0caa4690f9e1acbe578d4de5a82ba62f45444a12 Merge: 3619f9550e 1a0c0cd1c9 Author: Sakthivel Velumani Date: Fri Dec 23 14:21:00 2022 +0530 Merge remote-tracking branch 'origin/develop' into e1-implementation-wip commit 3619f9550e4d3e78815334150ff8443db914f738 Merge: 1bcf8d5e00 cfe698eb70 Author: Sakthivel Velumani Date: Wed Dec 21 15:47:40 2022 +0530 Merge remote-tracking branch 'origin/develop' into e1-implementation-wip commit 1bcf8d5e00a9b9ce440d825f83ddc1b48086daa8 Author: Sakthivel Velumani Date: Tue Sep 13 02:10:34 2022 -0400 Fix GTP rnti to ue_id after rebase commit 23075ff8b7ef5d56df844c05e0a7100fe7bd35de Author: Sakthivel Velumani Date: Tue Sep 6 00:32:12 2022 -0400 Added documentation commit 28f6e507f74d3fb069441e05da523378dee0f6ed Author: Sakthivel Velumani Date: Mon Sep 5 15:02:02 2022 -0400 Header cleaups and unitary simulators build fixes commit e665dbab28c49327066cff72aed22e1de7797b59 Author: Sakthivel Velumani Date: Thu Sep 1 17:52:07 2022 -0400 Common interface between CUCP & CUUP for E1 and non E1 modes commit 5dcc1bf59a37ed87d7d32a617cfcd663d6415757 Author: Sakthivel Velumani Date: Thu Sep 1 13:53:49 2022 -0400 Allocate stack where ever possible Free memory after ASN encode commit 793a5379539a3a2b6c42cd327d8cef79fe21fb55 Author: Sakthivel Velumani Date: Thu Sep 1 10:41:50 2022 -0400 Fixes for build issues commit 0d3564f25a0d8746b0fc550ed371ce21e08cd05a Author: Sakthivel Velumani Date: Wed Aug 31 20:57:14 2022 -0400 Fixed uesoftmodem linkage error commit 34adf865820f09900a5efed693ada1ccf6f0f1ad Author: Sakthivel Velumani Date: Wed Aug 31 19:31:50 2022 -0400 Removed RRC thread from CUUP commit 536741910aff90a86ba3a60612f943b412c5ab40 Author: Sakthivel Velumani Date: Wed Aug 31 14:21:31 2022 -0400 Add header guard in one of E1AP header commit 22e9d9b6dea5d84d259ee2dc1aaa7cb943e55b08 Author: Sakthivel Velumani Date: Wed Aug 31 14:00:47 2022 -0400 Fix bug in PDCP ue_id commit 4c65339b07d347003ed89d5e00f49a62e9b21483 Author: Sakthivel Velumani Date: Tue Aug 30 18:04:59 2022 -0400 Linked E1AP lib to L2_NR target E1AP builds for nr-softmodem commit 014fe30ac93c84d810e0209bc7f0d3b7a1bbaee3 Author: Sakthivel Velumani Date: Tue Aug 30 15:49:27 2022 -0400 Remove xer prints from e1ap and gcc warning fixes commit 71f0c9126bbb91bc595b66d57e1e91db676d3b9d Author: Sakthivel Velumani Date: Tue Aug 30 15:42:30 2022 -0400 Fixed bug in integrity protection config commit 4e393ef9528c2b14d670a341b52fc63262abf894 Author: Sakthivel Velumani Date: Tue Aug 30 14:34:37 2022 -0400 GTP init with only local address IP traffic works both directions in Mono, F1 and E1 commit ec3bde2c5deb99f554afc2053e351b9f79525e96 Author: Sakthivel Velumani Date: Tue Aug 30 00:16:03 2022 -0400 Fix bug in pdcp config and GTP instance UL iperf still not works. Can see packets in wireshark. commit be8df4435eeae0a0755e2ac658f33caa2a3e3c94 Author: Sakthivel Velumani Date: Sat Aug 27 20:15:04 2022 -0400 Fixes in node config after rebase commit 6f42ff88de7f1615f87c46771fd6617a5fdfc48f Author: Sakthivel Velumani Date: Sat Aug 27 01:38:21 2022 -0400 Added N3 tunnel address in config params fixed bug in address length feild commit b5e132041994344ebb5c2c59ca392612a32658fd Author: Sakthivel Velumani Date: Fri Aug 26 20:38:47 2022 -0400 Send UL UP address via F1 UE cxt mod msg commit ecfd0fe260aee6aad78c291368c246f88b6bffcf Author: Sakthivel Velumani Date: Fri Aug 26 15:08:53 2022 -0400 Update GTP remote address from response message Modified GTP tunnel update function accordingly Put GTP tunnel update out of F1AP F1 split works commit 14a37e414de3d653f25ccef1a790bc5b08fc7dc2 Author: Sakthivel Velumani Date: Sat Aug 20 01:17:36 2022 -0400 Moved GTP tunnel creation out of F1AP message sending commit cdd58ab96e84f48cc8ab8f0fe6b3133081ff02f7 Author: Sakthivel Velumani Date: Fri Aug 19 17:40:43 2022 -0400 Moved DRB config out of RRCReconfig complete Monolithic and F1 split works commit 61d66e490a1b61aa2b6ce18d993bb90d112d6374 Author: Sakthivel Velumani Date: Thu Aug 11 01:30:10 2022 -0400 Allow CUUP to have RRC inst without error commit dd7ae889372bb9fdf9e96be87c28eed0d9461d7f Author: Sakthivel Velumani Date: Thu Aug 11 01:29:21 2022 -0400 Added missing IEs in bearer cxt response handler commit a6f1fe5fd254ccb36a54ede5b652161cb5e542e8 Author: Sakthivel Velumani Date: Wed Aug 10 21:02:30 2022 -0400 Unified bearer context message transfer for E1 and non-E1 mode compiles, to be tested commit f245ace285632edcc28d669123746b9bf458bc38 Author: laurent Date: Tue Aug 9 17:46:52 2022 +0200 remove log_i() of fatal errors commit d2a0f3c8620981f3b65a136f0169e3be9c549742 Author: laurent Date: Fri Aug 5 15:01:39 2022 +0200 fix rnti/ue_id for ue commit 7b52c6cd9e675c28cb9d6347d122f77234ec6542 Author: Sakthivel Velumani Date: Thu Aug 4 19:14:46 2022 -0400 Created separate functions in PDCP for E1 mode commit 46680d2b3d221e675c3aeb675137f45318e31acb Author: Sakthivel Velumani Date: Thu Aug 4 19:13:10 2022 -0400 Bug fixes in bearer context setup response commit 3d091bfd31b7aba625e4ba4b4f0f337cf2c1f6db Author: laurent Date: Thu Aug 4 15:42:11 2022 +0200 add missing file from previous commit commit 21838572196dec947da99f350f20c4d9408c3c17 Author: Sakthivel Velumani Date: Wed Aug 3 16:59:16 2022 -0400 Minor bug fixes commit 34eb73fbc6f9d33098850d62b4808e54c80bb4ca Author: Sakthivel Velumani Date: Tue Aug 2 23:16:47 2022 -0400 Added config files for testing To be renamed or removed later commit a7e9c6fb9332295ad42585eb4338a6f9ff0ae7c0 Author: Sakthivel Velumani Date: Tue Aug 2 23:15:21 2022 -0400 Made rrc_gNB_get_ue_context_from_ngap_ids() non static commit 028f0407571466ff24cf72b5c3814e42c346ae81 Author: Sakthivel Velumani Date: Tue Aug 2 23:12:16 2022 -0400 Completed bearer context setup cycle To be tested: Handling of bearer context setup response and subsequent UE context modifition msg to F1AP task commit 4481d11324b13efa73ab0b5f4f156012485661ae Author: Sakthivel Velumani Date: Tue Aug 2 23:01:50 2022 -0400 Fixed E1AP PPID (wireshark fixed) commit 7a22573f3e7e16960e3310609dea2783ddf404a2 Author: laurent Date: Fri Jul 29 13:03:31 2022 +0200 fix compile issues, simplify gtp send function commit 0209011aa75a16e4c9c1eb36ebcf4fe0ff93aba2 Author: laurent Date: Thu Jul 28 11:51:18 2022 +0200 restore compilation capability, gtp replacement of rnti by ueid commit ce3b886fd7f11322a8d37b924d1752e6a6adf777 Author: Sakthivel Velumani Date: Fri Jul 22 08:35:31 2022 -0400 Included missing IEs in bearer cxt setup message commit 1208ae0d6fe4b25341c9036dde111fd4d00fd6e9 Author: Cedric Roux Date: Tue Jul 19 10:53:35 2022 +0200 replace rnti by ue_id in pdcp some sdap and gtp files had to be touched, the work is not finished in there some changes in nr_pdcp_oai_api.c simply assume ue_id is indeed rnti (will functions in this file be used by cu-up?) commit e67d1c88c786267458194e4de516919d0b5d1002 Author: Sakthivel Velumani Date: Tue Jul 19 10:08:39 2022 +0200 Replace RNTI with UE ID in GTP files (half done. Laurent to change ctxt_t) commit 7a141e8e941e5c2624a47da7c764531c03b8f617 Author: Sakthivel Velumani Date: Tue Jul 19 10:04:15 2022 +0200 Added RRC handler for bearer cxt setup in CUUP commit fe2106676bf9144347f30969a1bfd351136f536a Author: laurent Date: Mon Jul 11 13:30:30 2022 +0200 fix race in startup procedure (config before starting threads that use the config) commit 3197baab60e53459928da30cea7a4e0514a074e3 Author: Sakthivel Velumani Date: Sun Jul 10 11:30:31 2022 +0200 Fixed bugs in bearer creation commit 26be61167dec9068e572e08a21ddc96a0f2a7731 Author: laurent Date: Sun Jul 10 10:50:57 2022 +0200 fix a race, add asn1c debug method commit 26750d1818aa206c4c56ada6dbed9bb66dfe3811 Author: laurent Date: Wed Jul 6 22:34:10 2022 +0200 e1ap bearer setup encoding invalid commit d092788aa3f8229eb5c938a41534dfb318955135 Author: laurent Date: Wed Jul 6 14:18:39 2022 +0200 fix regression with F1, some basic cleaning in NGAP commit 41a135734a33b284808d4c5049c431dbc0ff1c46 Author: laurent Date: Wed Jul 6 11:24:52 2022 +0200 fix some ngap regressions commit 460acd840dd58fd46a995219cb9da8fda103668e Author: laurent Date: Tue Jul 5 21:19:13 2022 +0200 build, run in F1 mode until UE connect but pdu session still fails commit 7c067095df287cc7a542be53e9a1471c11ec5af8 Author: Sakthivel Velumani Date: Sat Jun 25 22:45:46 2022 +0530 Populate PDU and DRB paramenters from NGAP commit c4ada56a8c31b4c07fc1498e15b0954d9b1ad2f6 Author: Sakthivel Velumani Date: Tue Jun 7 22:16:58 2022 +0530 setup resp decoding success commit a2f41597c7438934a203ccf3cced35b6b65e8cee Author: Sakthivel Velumani Date: Sat Jun 4 13:50:55 2022 +0530 Fixed bugs in E1 setup procedure E1 setup request decoding successful commit 6106207ba74c74579b5f375d572930a609abe3a9 Author: Sakthivel Velumani Date: Thu May 26 20:13:14 2022 +0530 Fixing build issues commit 67235fac01aaca4c17da13bf658144ffe6bd12df Author: Robert Schmidt Date: Mon May 23 12:04:22 2022 +0200 Make nr-softmodem depend on E1AP module commit 391cee938e8250c355b6b914e747f2004c795817 Author: Robert Schmidt Date: Mon May 23 11:57:15 2022 +0200 Fix ITTI errors in E1AP target commit db4146e4a0432b7e3759d71efbeb450754c1f0d3 Author: Sakthivel Velumani Date: Wed May 18 06:59:03 2022 +0530 CP UP task created commit 3058d2fc445acf5681a09f70409023718294d093 Author: Sakthivel Velumani Date: Tue May 10 08:12:19 2022 +0530 Bearer context setup response message commit b911e9db2a4d0a35eb9a449ef02acefff30b558f Author: Sakthivel Velumani Date: Tue May 3 16:52:49 2022 +0530 Bearer context setup c structs commit d0f4d5f3539803253b9a995a90a47b3d825ea0ca Author: Sakthivel Velumani Date: Thu Apr 28 02:21:50 2022 +0530 Bearer context setup message commit 489a5358fa0e199314254561a2d52c1a93f7803e Author: Sakthivel Velumani Date: Thu Apr 21 10:11:03 2022 +0530 Started with CUUP task commit b416061f5a237cbabbe09c6d81fe92df9e33fd72 Author: Sakthivel Velumani Date: Fri Apr 15 18:46:27 2022 +0530 Setup request and response messages commit faca4b97dba92be857bd8442193365fc2c8ed122 Author: Robert Schmidt Date: Mon Apr 11 15:01:48 2022 +0200 Fixup for cmake execution commit ecfd9f7608a5820ae85278939e9bbaf7f1245dd6 Author: Robert Schmidt Date: Tue Nov 24 21:39:20 2020 +0100 Move CMakeLists.txt into root commit 9f41f7c52b3c7a185e5e34bb1591b0eb66459837 Author: Robert Schmidt Date: Tue Apr 12 12:07:18 2022 +0200 Remove hwlat refs in build_oai: targets don't exist anymore commit e666cf5eedc67695febd33de1397331d6b7b2320 Author: Robert Schmidt Date: Mon Apr 11 14:37:32 2022 +0200 Create CMake E1AP_RELEASE variable from E1AP_VERSION commit 1f8413361c1b99ea46ee613da035803a1387f65c Author: Robert Schmidt Date: Sun Apr 10 14:25:38 2022 +0200 Add E1AP lib commit 7465cea49243fd6eb9869035b18860dface57098 Author: Robert Schmidt Date: Sun Apr 10 14:48:40 2022 +0200 Add E1AP Grammar and build ASN.1 lib at build time commit cde22f83032a199387ae1eae6b702f44ed154f3e Author: Robert Schmidt Date: Fri Apr 22 13:42:51 2022 +0200 Accept higher vers. nums in make_version/MAKE_VERSION commit d5127b23608240374a439d1d9c2ff6d53c4b527c Author: Robert Schmidt Date: Tue Nov 24 21:39:20 2020 +0100 Move CMakeLists.txt into root --- CMakeLists.txt | 50 +- ci-scripts/conf_files/gnb-cucp.sa.conf | 248 +++ ci-scripts/conf_files/gnb-cuup.sa.conf | 100 ++ cmake_targets/build_oai | 2 +- common/ngran_types.h | 10 +- common/utils/LOG/log.c | 1 + common/utils/ocp_itti/all_msg.h | 1 + common/utils/ocp_itti/intertask_interface.h | 3 +- doc/E1-design.md | 108 ++ doc/TESTING_5GSA_setup.md | 9 +- doc/images/e1-archi.pdf | Bin 0 -> 20052 bytes doc/images/e1-archi.png | Bin 0 -> 24521 bytes doc/images/e1-archi.tex | 73 + executables/nr-cuup.c | 160 ++ executables/nr-softmodem.c | 90 +- executables/nr-uesoftmodem.c | 2 + openair1/SIMULATION/NR_PHY/dlsim.c | 71 - openair1/SIMULATION/NR_PHY/prachsim.c | 73 +- openair1/SIMULATION/NR_PHY/ulsim.c | 71 - openair2/COMMON/e1ap_messages_def.h | 33 + openair2/COMMON/e1ap_messages_types.h | 226 +++ openair2/COMMON/gtpv1_u_messages_types.h | 2 +- openair2/COMMON/messages_def.h | 1 + openair2/COMMON/ngap_messages_types.h | 15 + openair2/E1AP/CMakeLists.txt | 10 +- openair2/E1AP/e1ap.c | 1582 +++++++++++++++-- openair2/E1AP/e1ap.h | 34 +- openair2/E1AP/e1ap_api.c | 195 ++ openair2/E1AP/e1ap_api.h | 35 + openair2/E1AP/e1ap_asnc.h | 65 + openair2/E1AP/e1ap_common.c | 235 +++ openair2/E1AP/e1ap_common.h | 64 + .../E1AP/e1ap_default_values.h | 11 +- openair2/E1AP/e1ap_setup.c | 129 ++ openair2/ENB_APP/enb_app.c | 3 +- openair2/ENB_APP/enb_config.c | 2 +- openair2/ENB_APP/enb_paramdef.h | 7 +- openair2/F1AP/dummy_enb.c | 6 - openair2/F1AP/f1ap_cu_interface_management.c | 4 +- openair2/F1AP/f1ap_cu_task.c | 31 +- openair2/F1AP/f1ap_cu_ue_context_management.c | 16 +- openair2/F1AP/f1ap_decoder.c | 3 +- openair2/F1AP/f1ap_du_task.c | 29 +- openair2/F1AP/f1ap_du_ue_context_management.c | 2 +- openair2/GNB_APP/gnb_app.c | 87 +- openair2/GNB_APP/gnb_app.h | 5 +- openair2/GNB_APP/gnb_config.c | 102 +- openair2/GNB_APP/gnb_config.h | 4 +- openair2/GNB_APP/gnb_paramdef.h | 22 + openair2/LAYER2/MAC/mac_proto.h | 2 - openair2/LAYER2/NR_MAC_gNB/main.c | 5 +- openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c | 59 + openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h | 53 + openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 59 +- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 1 + openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h | 1 + openair2/MCE_APP/mce_app.c | 3 +- openair2/RRC/LTE/rrc_eNB.c | 1 + openair2/RRC/NR/MESSAGES/asn1_msg.c | 172 +- openair2/RRC/NR/cucp_cuup_direct.c | 229 +++ openair2/RRC/NR/cucp_cuup_e1ap.c | 61 + openair2/RRC/NR/cucp_cuup_if.h | 42 + openair2/RRC/NR/nr_rrc_common.c | 19 +- openair2/RRC/NR/nr_rrc_defs.h | 13 +- openair2/RRC/NR/nr_rrc_extern.h | 4 +- openair2/RRC/NR/nr_rrc_proto.h | 41 +- openair2/RRC/NR/rrc_gNB.c | 553 +++--- openair2/RRC/NR/rrc_gNB_GTPV1U.c | 20 +- openair2/RRC/NR/rrc_gNB_GTPV1U.h | 3 +- openair2/RRC/NR/rrc_gNB_NGAP.c | 220 ++- openair2/RRC/NR/rrc_gNB_NGAP.h | 9 +- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 26 - openair2/RRC/NR/rrc_gNB_radio_bearers.h | 4 - openair2/SDAP/nr_sdap/nr_sdap_entity.c | 5 +- openair2/SDAP/nr_sdap/nr_sdap_entity.h | 3 + openair3/MME_APP/mme_app.c | 3 +- openair3/NGAP/ngap_gNB_handlers.c | 338 ++-- openair3/SCTP/sctp_eNB_task.c | 20 +- openair3/ocp-gtpu/gtp_itf.cpp | 67 +- openair3/ocp-gtpu/gtp_itf.h | 6 +- 80 files changed, 4652 insertions(+), 1422 deletions(-) create mode 100644 ci-scripts/conf_files/gnb-cucp.sa.conf create mode 100644 ci-scripts/conf_files/gnb-cuup.sa.conf create mode 100644 doc/E1-design.md create mode 100644 doc/images/e1-archi.pdf create mode 100644 doc/images/e1-archi.png create mode 100644 doc/images/e1-archi.tex create mode 100644 executables/nr-cuup.c create mode 100644 openair2/COMMON/e1ap_messages_def.h create mode 100644 openair2/COMMON/e1ap_messages_types.h create mode 100644 openair2/E1AP/e1ap_api.c create mode 100644 openair2/E1AP/e1ap_api.h create mode 100644 openair2/E1AP/e1ap_asnc.h create mode 100644 openair2/E1AP/e1ap_common.c create mode 100644 openair2/E1AP/e1ap_common.h rename executables/create_nr_tasks.h => openair2/E1AP/e1ap_default_values.h (88%) create mode 100644 openair2/E1AP/e1ap_setup.c create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h create mode 100644 openair2/RRC/NR/cucp_cuup_direct.c create mode 100644 openair2/RRC/NR/cucp_cuup_e1ap.c create mode 100644 openair2/RRC/NR/cucp_cuup_if.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a781499ce..7cb2847a3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,7 +280,7 @@ if (SANITIZE_UNDEFINED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") endif () -add_definitions("-DASN_DISABLE_OER_SUPPORT") +add_definitions("-DASN_DISABLE_OER_SUPPORT -DHAVE_CONFIG_H -DHAVE_CONFIG_H_") ######################### set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb2 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}") @@ -336,23 +336,19 @@ add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") # Debug related options ######################################### -add_boolean_option(DEBUG_ASN1C False "ASN1 coder/decoder Debug traces, see common/utils/config.h, the logs are regular OAI logs, in the log group 'ASN'") -add_boolean_option(DISABLE_XER_PRINT False "print XER Format") -add_boolean_option(XER_PRINT False "print XER Format") -add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace +add_boolean_option(DEBUG_ASN1 False "ASN1 coder/decoder Debug") add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace -add_boolean_option(PRINT_STATS False "This adds the possibility to see the status") add_boolean_option(T_TRACER True "Activate the T tracer, a debugging/monitoring framework" ) add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs") add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace") add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace") -add_boolean_option(DEBUG_CONSOLE False "disables stdout/stderr buffering") set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti) add_library(ITTI ${OCP_ITTI}/intertask_interface.cpp ${OPENAIR_DIR}/common/utils/backtrace.c ) + target_link_libraries(ITTI PRIVATE asn1_nr_rrc asn1_lte_rrc) # asn1c skeletons have hardcoded this flag to make customized debug logs @@ -819,7 +815,6 @@ include_directories("${OPENAIR2_DIR}/UTIL/OTG") include_directories("${OPENAIR2_DIR}/UTIL/CLI") include_directories("${OPENAIR2_DIR}/UTIL/OPT") include_directories("${OPENAIR2_DIR}/UTIL/OMV") -include_directories("${OPENAIR2_DIR}/RRC/LTE/MESSAGES") include_directories("${OPENAIR_DIR}") ########### @@ -1594,6 +1589,7 @@ set (ENB_APP_SRC set (GNB_APP_SRC ${OPENAIR2_DIR}/GNB_APP/gnb_app.c + ${OPENAIR2_DIR}/E1AP/e1ap_setup.c ${OPENAIR2_DIR}/GNB_APP/gnb_config.c ) @@ -1639,7 +1635,20 @@ add_library(L2_NR ${GNB_APP_SRC} ) -target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc) +add_library(e1_if + ${NR_RRC_DIR}/cucp_cuup_direct.c + ${NR_RRC_DIR}/cucp_cuup_e1ap.c + ) + +target_link_libraries(e1_if PRIVATE asn1_nr_rrc asn1_lte_rrc asn1_f1ap e1ap GTPV1U) + +add_library(e1_pdcp_if + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_e1_api.c + ) + +target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc asn1_lte_rrc) + +target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap) add_library(L2_LTE_NR ${L2_RRC_SRC} @@ -2373,7 +2382,7 @@ target_link_libraries(nr-softmodem PRIVATE UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECU_CN SECU_OSA ITTI ${RAL_LIB} ${NAS_UE_LIB} lte_rrc nr_rrc ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU - x2ap f1ap m2ap m3ap + x2ap f1ap m2ap m3ap e1ap -Wl,--end-group z dl) target_link_libraries(nr-softmodem PRIVATE ${LIBXML2_LIBRARIES}) @@ -2390,8 +2399,27 @@ endif () # force the generation of ASN.1 so that we don't need to wait during the build target_link_libraries(nr-softmodem PRIVATE - asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp) + asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp) +add_executable(nr-cuup + executables/nr-cuup.c + executables/softmodem-common.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${NR_RRC_DIR}/rrc_gNB_UE_context.c + ${OPENAIR2_DIR}/E1AP/e1ap_setup.c + ${NR_PDCP_SRC} + ${NR_SDAP_SRC} + ${T_SOURCE} + ${SHLIB_LOADER_SOURCES} + ) + +target_link_libraries(nr-cuup PRIVATE + CONFIG_LIB ITTI SCTP_CLIENT + GTPV1U e1ap e1_pdcp_if f1ap + SECU_OSA ${OPENSSL_LIBRARIES} crypt z sctp dl pthread) +target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc asn1_nr_rrc) + # nr-uesoftmodem is UE implementation ####################################### diff --git a/ci-scripts/conf_files/gnb-cucp.sa.conf b/ci-scripts/conf_files/gnb-cucp.sa.conf new file mode 100644 index 0000000000..7932098584 --- /dev/null +++ b/ci-scripts/conf_files/gnb-cucp.sa.conf @@ -0,0 +1,248 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; +Num_Threads_PUSCH = 8; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x1; // 0 false, else true + } + ); + + }); + + + nr_cellid = 12345678L; + + tr_s_preference = "f1"; + + local_s_if_name = "lo"; + local_s_address = "127.0.0.4"; + remote_s_address = "127.0.0.3"; + local_s_portc = 501; + local_s_portd = 2152; + remote_s_portc = 500; + remote_s_portd = 2152; + ssb_SubcarrierOffset = 0; + min_rxtxtime = 6; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.70.132"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + E1_INTERFACE = + ( + { + type = "cp"; + ipv4_cucp = "127.0.0.4"; + port_cucp = 2152; + ipv4_cuup = "127.0.0.5"; + port_cuup = 2152; + } + ) + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : + { + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="debug"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + f1ap_log_level ="debug"; + ngap_log_level ="debug"; + }; + diff --git a/ci-scripts/conf_files/gnb-cuup.sa.conf b/ci-scripts/conf_files/gnb-cuup.sa.conf new file mode 100644 index 0000000000..9e18459f87 --- /dev/null +++ b/ci-scripts/conf_files/gnb-cuup.sa.conf @@ -0,0 +1,100 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x1; // 0 false, else true + } + ); + + }); + + + tr_s_preference = "f1"; + + local_s_if_name = "lo"; + local_s_address = "127.0.0.4"; + remote_s_address = "127.0.0.3"; + local_s_portc = 501; + local_s_portd = 2152; + remote_s_portc = 500; + remote_s_portd = 2152; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + E1_INTERFACE = + ( + { + type = "up"; + ipv4_cucp = "127.0.0.4"; + port_cucp = 2152; + ipv4_cuup = "127.0.0.5"; + port_cuup = 2152; + } + ) + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : + { + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="debug"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + f1ap_log_level ="debug"; + ngap_log_level ="debug"; + }; + diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 720d0f0c96..7d43b33f4f 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -531,7 +531,7 @@ function main() { execlist="$execlist ocp-enb" fi if [ "$gNB" = "1" ] ; then - execlist="$execlist nr-softmodem" + execlist="$execlist nr-softmodem nr-cuup" fi if [ "$RU" = "1" ] ; then execlist="$execlist oairu" diff --git a/common/ngran_types.h b/common/ngran_types.h index 3dfa7aa01a..ddd1ec2cca 100644 --- a/common/ngran_types.h +++ b/common/ngran_types.h @@ -42,12 +42,16 @@ typedef enum { ngran_gNB_CU = 5, ngran_eNB_DU = 6, ngran_gNB_DU = 7, - ngran_eNB_MBMS_STA = 8 + ngran_eNB_MBMS_STA = 8, + ngran_gNB_CUCP = 9, + ngran_gNB_CUUP = 10 } ngran_node_t; +typedef enum { CPtype = 0, UPtype } E1_t; + #define NODE_IS_MONOLITHIC(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB || (nOdE_TyPe) == ngran_ng_eNB || (nOdE_TyPe) == ngran_gNB) -#define NODE_IS_CU(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_CU || (nOdE_TyPe) == ngran_ng_eNB_CU || (nOdE_TyPe) == ngran_gNB_CU) +#define NODE_IS_CU(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_CU || (nOdE_TyPe) == ngran_ng_eNB_CU || (nOdE_TyPe) == ngran_gNB_CU || (nOdE_TyPe) == ngran_gNB_CUCP || (nOdE_TyPe) == ngran_gNB_CUUP) #define NODE_IS_DU(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_DU || (nOdE_TyPe) == ngran_gNB_DU) #define NODE_IS_MBMS(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_MBMS_STA) - +#define GTPV1_U_PORT_NUMBER (2152) #endif diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index 2215e4bd40..84c70c3767 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -483,6 +483,7 @@ int logInit (void) register_log_component("SDAP","",SDAP); register_log_component("S1AP","",S1AP); register_log_component("F1AP","",F1AP); + register_log_component("E1AP","",E1AP); register_log_component("M2AP","",M2AP); register_log_component("M3AP","",M3AP); register_log_component("SCTP","",SCTP); diff --git a/common/utils/ocp_itti/all_msg.h b/common/utils/ocp_itti/all_msg.h index ab75eaffdd..eb484ce8f1 100644 --- a/common/utils/ocp_itti/all_msg.h +++ b/common/utils/ocp_itti/all_msg.h @@ -15,5 +15,6 @@ #include "openair2/COMMON/udp_messages_def.h" #include "openair2/COMMON/gtpv1_u_messages_def.h" #include "openair2/COMMON/f1ap_messages_def.h" +#include "openair2/COMMON/e1ap_messages_def.h" #include "openair2/COMMON/ngap_messages_def.h" diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 0a7bbc3b78..2b17c7e3ef 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -79,6 +79,7 @@ typedef struct IttiMsgText_s { #include #include #include +#include #include #include @@ -409,7 +410,7 @@ typedef struct MessageHeader_s { } MessageHeader; typedef struct message_info_s { - int id; + MessagesIds id; message_priorities_t priority; /* Message payload size */ MessageHeaderSize size; diff --git a/doc/E1-design.md b/doc/E1-design.md new file mode 100644 index 0000000000..db4bc85f74 --- /dev/null +++ b/doc/E1-design.md @@ -0,0 +1,108 @@ +[[_TOC_]] + +# 1. Introduction + +E1 is named for the interface that lies between the nodes CU Control Plane (CUCP) and CU User Plane (CUUP). Once the nodes are configured, all user plane traffic flows through CUUP. + +The E1 design in OAI follows the 3GPP specification in TS 38.460. The code design on E1 in OAI is very similar to +F1. The ITTI message passing mechanism is used to exchange messages between E1AP thread, SCTP thread and RRC thread. + +The following sequence chart shows the current E1AP message flow. + +```mermaid +sequenceDiagram + participant c as CUCP + participant u as CUUP + u->>c: SCTP new association + c->>u: SCTP new association response + Note over u: Create UDP sockets for F1-U and N3 + u->>c: E1AP Setup Request + c->>u: E1AP Setup Response + Note over c: Receives PDU session setup request from AMF + c->>u: Bearer Context Setup Request + Note over u: Configure DRBs and create GTP Tunnels for F1-U and N3 + u->>c: Bearer Context Setup Response + Note over c: Sends F1-U UL TNL info to DU and receives DL TNL info + c->>u: Bearer Context Modification Request + Note over u: Updates GTP Tunnels with received info +``` + +_Note that the E1 bearer release procedures are currently not implemented._ + +# 2. Running the E1 Split + +## 2.1 Configuration File + +The gNB is started based on the node type that is specified in the configuration file. To start a gNB instance in CUCP or CUUP, the `tr_s_preference` should be set to "f1" and the config member `E1_INTERFACE` should be present in the config file. The `type` parameter within the `E1_INTERFACE` should be set to `cp`, and `nr-softmodem` should be used to run a CU-CP. The type should be `up` and `nr-cuup` should be used to run the CU-UP. Further, there are the parameters `ipv4_cucp` and `ipv4_cuup` to specify the IP addresses of the respective network functions. + +For CUCP, a typical `E1_INTERFACE` config looks like +``` +E1_INTERFACE = +( + { + type = "cp"; + ipv4_cucp = "127.0.0.4"; + ipv4_cuup = "127.0.0.5"; + } +) +``` + +For CUUP, it is +``` +E1_INTERFACE = +( + { + type = "up"; + ipv4_cucp = "127.0.0.4"; + ipv4_cuup = "127.0.0.5"; + } +) +``` +One could take an existing CU configuration file and add the above parameters to run the gNB as CUCP or CUUP. + +The CUUP uses the IP address specified in `local_s_address` for F1-U and `GNB_IPV4_ADDRESS_FOR_NGU` for N3 links. Note that `local_s_address` is under `gNBs` and `GNB_IPV4_ADDRESS_FOR_NGU` is part of the `NETWORK_INTERFACES` config member. + +Alternatively, you can use the config files `ci-scripts/conf_files/gnb-cucp.sa.conf` and `ci-scripts/conf_files/gnb-cuup.sa.conf` which are already in the repository. + +## 2.2 Steps to Run the Split in rfsimulator with OAI UE + +Note: A 5G core must be running at this point. Steps to start the OAI 5G core can be found [in the oai-cn5g-fed repository](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/docs/DEPLOY_HOME.md) or [here](NR_SA_CN5G_gNB_USRP_COTS_UE_Tutorial.md). + +0. Open wireshark to capture the E1AP messages. You might set the capture filter + to `sctp` to limit the number of captured packages. + +1. Start the CUCP first by running the following command +``` +sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb-cucp.sa.conf --gNBs.[0].min_rxtxtime 6 --sa +``` + +Note that `min_rxtxtime` should be set to `6` only when you are connecting an OAI UE to the gNB. + +2. Start the CUUP and DU (in any order) + +CUUP (has its own executable): +``` +sudo ./nr-cuup -O ../../../ci-scripts/conf_files/gnb-cuup.sa.conf --sa +``` + +DU: +``` +sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gNB_SA_DU.conf --rfsim --sa +``` + +You need to use `--rfsim` if you are running the test with rfsimulator. + +3. Start OAI UE or COTS UE. + +OAI UE: +``` +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa +``` + +# 3. Configuration file IP addresses of network functions + +You can also run the nodes on different machines. If you do so please change the interface parameters accordingly and make sure the interfaces are reachable. Please refer to the following figure for an overview of all parameters. + +![E1/F1/NG parameters](images/e1-archi.png){width=1200} + +[PDF version](images/e1-archi.pdf) | [LaTeX/TikZ version](img/e1-archi.tex) if you want to modify to reflect your setup diff --git a/doc/TESTING_5GSA_setup.md b/doc/TESTING_5GSA_setup.md index 1828f967b1..18b61d30a5 100644 --- a/doc/TESTING_5GSA_setup.md +++ b/doc/TESTING_5GSA_setup.md @@ -91,7 +91,8 @@ In the first part (*amf_ip_address*) we specify the IP of the AMF and in the sec Please read [CN5G tutorial for more details](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md). -### **gNB configuration in CU/DU split mode** +### gNB configuration in F1 (CU/DU split mode) + For the configuration of the gNB in CU and DU blocks, the following sample configuration files are provided for the [CU](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf) and the [DU](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf) entities respectively. These configuration files have to be updated with the IP addresses of the CU and the DU over the F1 interface. For example, in the following section from the DU configuration file, *local_n_address* corresponds to the DU address and *remote_n_address* corresponds to the CU address: ```bash @@ -112,9 +113,11 @@ MACRLCs = ( ); ``` - At the point of writing this document the control-plane exchanges between the CU and the DU over *F1-C* interface, as well as some IP traffic tests over *F1-U* have been validated using the OAI gNB/nrUE in RFSIMULATOR mode. - + +### gNB configuration with F1 and E1 + +Please refer to [E1-design](E1-design) for more information. ## 1.2 OAI 5G Core Network installation and configuration The instructions for the installation of OAI CN components (AMF, SMF, NRF, UPF) using `docker-compose` can be found [here](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md). diff --git a/doc/images/e1-archi.pdf b/doc/images/e1-archi.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ddbed79e51a30221f449c6168d990a9da2030108 GIT binary patch literal 20052 zcma&MLzFID(50ESZQHtO+qP}nHg4LsZQFj+zG>U8uX^=A=+!l-7)7jgMtcxDPQ*j5 zC@N0R%d|`QX9fqBViO9j&8itn_hEdkc-on+Ah?$Lxjp+Xg7)Eg`TURq@B1Umr zBUdv~GZP0>GZ=n;7#CM(Gb1|~&&^sbIhSQlq~7`Z1*ccT!uhljdaxwzstJ^&ePO49 zq^nhRax$>>@6XT8wDGiSr(iy{pukhH`tIkC%44egcEtnN;=H%I`*svipFUsRynXq-+ZK-t-7KrrE9H9-HPBp6*SMW4$oY(-h(I(R{d1|2(9Z4a=XE~afy05JyGMoygXgxxxux6ie({~j4{b&ZeU|l6;_vQ$d2CA{14AH7 zPbAyFoooRU9Lek-cb0Dij)}ggR@m0`K6n=KOewPfJAo#kn~63 zZCZ(QOF0lcg~$a+&+gwQM!}FPmlC~#?x$7~DeAI2n}fAYDG8(0w>Sw--50L=_JY2* z_}yH%X2OA~r)u`i#y6ky-=w!cSrATjfWCWmZBwrDZ;Yj-pOoJ>v5E*6O{`;?Xp~})`KlMAN7U}27aQ~eu#)sCz!1Z|zBogB znA%32suE{rQJY&jTLxUEjGOmM75z#(1D><;<-kC~g|**D&Bz~qAKHszU`kNZTcqsx z3Pk1Z^&ACe6zd9Kq4)96c>7>hLGy)UU`~39*(tiN2# zvdw}I9oq)!YchsU3+udNtrS=}{*(Ojd49NGW%d|dLrV~*O3Su!!Hdq$y8E!_!|Qn< z0w%6i1B?^RK(AOYs%$E9cw)I7xu&lrb|P{IZw)HM$y?j=KTX_}9iA57_|*>}-j@g6 z8|Nm51`A{L%3(vc5{tC-Oea`ffyuI;fL#|)dp_P>^fC1iO!Qp;Si@*N|1~TwedG+i zY`a3Roo>ey6QkAO44r&TQ;o`P=gOp2ZU`SqCxg=o>Um|Ig|pUx)W${_WZdF}^#j}W z4e1f&`k-c+ru0&^O2F#wl*KO z1hh<=%7(L%2G{+KI8SL{$;GokaA8R;FbmCB_dPVog6ntshpCxinw#gI5j&Z{ow@Z{ z&Dd_D7fKe=9!u6Pj-hneRu4ONYr-B2o_1Sby}`svuG26Z-B2UZY2zj1&cpJ;8iP;n zAFuX-jl)R;>B9gIABRyS|D0iBWL4+H_Lk#<5Wjy;(SekIY>8njdWi>bp-;whX^HKO zBr%*6jj(U|UGT!Q>D_f@>DQ$$`^h2)9Rh(Ls6)G&>qDcl3ffP^3r36<=GCR}=J@+| z=pFCiagcd;EuZ`8o88^weCB;~+XvUbC?6+`MNG`i^2#O;E%baTm5dW}eo}ejfaMKk5u0Tz;qxf1| zwmwbEFd~lMI%%mh+C~to3dfW12O#*t42C|@vXr>B>o>}&S`Iv&x$WblYbQfrBlVQO zkPB$jNHAvhrvGn)|1bOB=D^JQ|8oguB4&0b_W$t=79tLIE|&kP{(JpDDG?_J8|(kA znZ$X3tESkju|pLR=>gz&;C4uMb|ev)29Q_>;PjLMacoot0OB|RK7g7yS6UhhW$%pZ z_MYeVxBmI}Qp+aqbkps&_txgNH9SgQCS7I|!W>*ZPzYJKXPeg;NXt!64;cs%QGf#x zkq`qlnE-4b>_;bd)D*})M8r_B@z;##5(0uafrSeR#Ht)21VnW^7pUh8NS~Nl--wxj z0EiGV{wx5_$le%;D*g9WR4(+_e3BcNZp1VsJ^0t>D0j^ zu!VIU-WWa@WLXHxr-AiB)FuH{5YrqUn6&2?Jy>msAjlCJ6oikDuTyBw(LN(PmkgJ3 z05!M)@+@%QkOQ#+{-4Gm5PSmbTm4i=V+N4-3(}i`vt9=M5b6;G1QEDAk_{8u-zUe2 z&A=U?iDBTbDQh4(Or|GBlh%GXPT+u7h=J+ZPlb;D-T?4m!2q6+np&ed2BHcMFl)$$ zFwP+0EEwx;C`K?!Ah6bVGbrca;e;O|M5GaD(=fKTTrQ{rqFQ($V%V>4-i}t>5pdws zaFHDURH!d>hz&EZia5HN4Qx2EfkyvhN=PSA9n!5E_^(TI{6Z#$irc*b43O5wZ?(|4 zZdgS^7$-MK+Uak*U^Jue#El?iARz(*0%QVxpmlVhm!>wzADH^nYmlGXFM4tHf47$) zF2L&~F+iUpwu2LxX^ePBzz{^++k-!SzdH90p`+8V4MCcuKN zZlI2UDuxqGfW946MD7eksu9|PI(UBD)vAfQN|q*P;VqG9u0goF^2UT}SHTJCczHR1Zu{zP~0uDB5Jq)*~OHqJac% zZwu~fPRNLp2n8}SI%C)k==V#(0Xd5pL6yJ)Y2^tFV4Q?MUy3KT07?I%e20Ys3vLKV zf&ry`hKK?Sz6T^QAp%w0LEeJ|Mh76VM1K&5#unWpq6mFheG5%2J^u=UNSfYW8^`N% z{vzL#Sb#%)ngq=NcS`>n9!WV;B5nT!a6thFMg|ZiISPjM;=aYhHYEy%o*EGUu1MK< zaBv*4ywAFsX8(o+I504+!`j9@dqJ4f6I>|bZ+;a^X91FJT(C^MTK}*Nc2Ei<4f1|& zuIXP3l^uju$Ck=*Z761~>fXoPV+%;Xgb(7ojsZpDRs+3 zLett=n&tg|W|Y}oR%T4AuEtlj&c?u8(v4N}ZdiSFG2VZB4BL-%C%M4_NWjYD>i!Hc z!|LPg#pORd=F~o*mZM8N((6RS7xUOYH0*s))zwfBy~B3ow<#6HWt7ztM9l4^!_QqX z_U!$9Z_FN{uT3*~bzB4Jw`urEZ%q4jE~!S5-Le)c6qBv{_U=+)s#7#aht+{=zZ6%{ zd~icbMzd!>EB&W431=yGXX@532u_nr5E^~+e0^qp&3&oEq<^E|suU%?bFWNmA8=EX z2=wayNj>z58`orKgRjKa;kBoTsA1iHAjA*Ji}GmJ!^y1E}vo z<$=F_+ndi3jgz%*fxbBP>x+%RYSiXWxvq>U1VZ2gs_mE8fwXNZ~7MPqkz42D^>;n8= zS!CUhYnG!74b?3CDJ1U}o15w1Io3T`7?qKXk?cJWI1gM9go?8bJ!J(!2r^#hGu1am z4agthppbS{k^+|~--Ar4#iAO_OxsF7fq64clo8#x8-}S@)4n*F%S!%t1!dvU{QeNY8k}rTXCew+cjy%Y(BGagrtmu05v56fP?LH;p zM{w{852ke(2i+s~Na7)Xh3 z4~i!~{8-CDvK^vI*3-Utudo=7;ZHK*F@O$E&l$q*-4c35F&zh+3_n^F~0 z53?I@73yzkkSiY}!M8CJ1*vhZz<$63Yn*0o; zd?+x_S;;;2&+iJHg-dc=zbYEX;EL7DhwEw(@|06^ErbK~xN9yreCO(8ib}Lk*FJ>= z3LlHF^T~TC68NJ;>bf#=oi4OER=A*aUnpDTy3K{9oQbdkL@$kZ;&k!dcl}G@lPMlN zs!7ww)zW6ub3CseYu09Pr^JO5bzJ+TcjeSURK5QKl6^me@?ZilxD+b1)l8i70E{fJ zaO3-BHU4!NVjKl1*g1WpTN4zL|K|KB>jb= zodEn|{yC`M+}T!OUZ<&xaX%@|$PjGREVGMp&_qN=zA`c`J;71qLkvR)1Zqy*m;K5HsM4tn(i-Uhx%1Qvo_>sp0_n7{!wU?H^eCqke z0yC^J79AgLSyEJ)n5gB!NDmxWaVSkR=19l!^SwYjEj-;^Z&$RE+0?S1^&F#IB5lL9 z8hX7G{d)xj7C+tLR<=8W5@4rwG5=>9i*lUo ze&o%eG@l<*%h!=DRSX#+A+>1Y`0%%b{gGfIRgiY#VEPSWI1TVh?!P~HXfyTQ;DDSgX5XYg;(R$X$r9X#5|NS!oVs@tFJb`_HG0$Pw#v6%8S zf4fQq&9(}fOi;fuK>$|DMnmDnEaMtP84a}xTe=vZ4#dMtiO%8LOOk<{9{S-io(27( zSbp%B27IX08P5ICDNaUAK{j%EQYVV-QmLw$MqFqxCPtRD_iRZ>7qN^bHpjHoOy><8 zUX83T*&xQCfaU9_fsEVXbb<$bX~h=YQFo-yn6mXgQX-}-#3SPXDnl2->6M06 zq2|fh4c~=qaP(<$z)}Nm2T#>TRq(Qtp%Sv7mVH`tt-_kbm@5}(@9fIB8yHT%m6|7S zflq3s%k?vS3i!>3k&Ud(LzzDZ%<_0~FbBKO$(o`GdMKmo(VLqwGe&kNA<}i51Z|)F z*WqL{4U>dCG-&ZG@f$d=zORXrvZhQ*`css>{&82uLg@HAD5SGi!h&mW2JzK`R~M>~`1E*)7xlqGp?wzk<& zxb$yKRKlwjm=TEKoW`-69WVIaWCXSc^SRS8+RYo|i}Sx6j7xbcR+u^5yZ1^kK( zynY{HS^;%^IP&>Wk|+CL06ydhggT$;a3>9B^C{=XZWZ};5wXw0lSQ-qPxb)eT9>@h zp42cMV(BE4#2F5LHBa^P+FH2Ka}#bGW?K#Zw(k9n3{?jE!C?#O@X-iB(N#@|wQY*G z6)}&e;;&6OP_|XH*kb-4>R=VBhZ!Dnit$Z4FO!WJ1X?bKRRoz8 zLE|D})QlgRk`x01I~M1dS~foGchQ%;g9$LxeJNZef)$T>JSvRE59}nvuI|L{edu>- zMk}fLmr9*}m7A%vs(T6UKS^MO4se~ffWw9snPdtMPR`|X zYImBR)P2ekoI3j>D@u-@fjHeFZoLIK&1cCUP1AuFqKgSdFT+l`yKRxs5uqHFo)T^q z(Z-{&dZ05org_)ux7!-X?D92JU?R8=_r4PJ%k2}`aVq0zdxGOX^{Oxw!B_zaW^Nbi zXrl8=(eCjYc&6HVWp~}>1jCl>CQvY=oG9d0m2@s>AZao^5$ZDUAo`1MC~E8pI zk;=c|BI5qRDC&a3vQ;aKqLFb$6~OmlS;Je6jm+iF(9H^*jZbo}D+FZd?277g@_l%~ z+qrEB45OUC7iI4miKN_XM?1@gADs(n&yx3}!`bjc53et7^xke>IE6{MjpLA~`$ow$ z=6wwxMs$cLY#-KR*DS$d_Cbi=j^@qCd$`o!Q1-6Mw6cP^QXm?+(P9HJRj;PC+QsHL z@R`X{XN-`xjV4P|!)X5Nd=0#}GHW0&ajU{^m8BjJB3q|SMtj|qB*i*OGqNFTSa3T?2c*VxQ;wusUp?1JLDM*m1$P*2{%Rlh{oHW ztrC0fc=nQiP+jox1|G z3AJ26UjOygZ@WV5rm zj;<98&r=`n^-oj{jaEpATDSJ~)j?6SIm@`Q&SL~gKai(4+Cmh*G5agNp?x$dIGgR; z@%AqWKzB8E`k%EATjlWfR6Fo&nBP|1PxL~Me=ZO34$HJe5LuJ)eeR`8yBZF`a+cEw zChI(91>|Z!fr(iq%P+_R{rESW1Zp>t#8Um*KSfaLgATY@AB*vF2pMsk^=x?Mn;)V~ zM;c@yrFc5)`trm_`OHraQ#P@&;R^*W1OnqaLqjqMWug4Y z2%-VWxuO^?E49x;K@B~tZE;5ClsN}^TCA^g+8qVtaI{u4JXbagA!73A%3`~f6v&y zJ$rE5t}Bwe+-&N+_FWmn0$_a?j8XcR=o)&`?+bNA2U(9C|A0t8r=?%8cVN@V|IM{e zv{Nnch%H>Dk^3D+Ym`gycC9|*p?*2*G2tN?u!MpewSVUY0t=~KcqbDN(RAz}(XU!%f3xI?XYjY`|oBDl0R^JU#b zP<2OTYP+hw#-14lck-_{rEoh0UQ1&8r1b#Veefyy0dvv68IkdASmE;%tVn6w3qUU< z)zAp(mE}(MOrH7l(c8 zvYEE{!dC8~G!MoWFTXx3;mzKQ&%UiG;{B0lQ7~lMIuQAN zSFs%%-c4COaVfhbgG2w8-q6!*nO+1J-e*5ztH0VA%vM?lQ76Cl60kj@*b#G*?`ap^ zGRQoHqkpFs=`65}O6BcSR=-|jn6{ojlj46nNU)b{23!cBPP$>!! z6(`OT?uzcu9O~r)a%qe5l|NO{beJ)l44li#2JIeu;_3dT=9t%@srZT?o9KqJLBBOu zkX0DuB$v{`eQH>Z4>ciW!#j}>iN~=%l*P=VH^>ga@qKo(e%2d~1u0!Tu&N7DEN{*q zhg@M(I;iZ+Pcm;U4g*67Vr08Np(yIqhqpQ4w(}@WtOz8x9@9CFKyp~CVap>gGhUOJJ`N&*CqJ064~qb zCDZHIqRhlt<6w97?iVO-ZwWCL+9x4M4HD0kIq|O>0IyF0fAL0G8A z*>+h@&5Y;%C6MMEwS*GZ$?xp z-BsKvsI~Xs=WX)aW~o3F<`?!pB>|DK1LG#rgx`+J{AQ$I5!Tw&tJN_1^Mw4a%)hQb zx_R)6wHapADuB+m7cpRKP6ZY1Ld1$vfKF0fjkea*`0V#Ai%Ve+adtP)J}hw$_fYd( zZUw^r=1>@EpXOGPGn{zeDd~X2pWI~?Qs<4?Nk%Xx5Xp60*xp}DY!MFSo0Or{N+=Oq zrO51G_k$!HRCb#!Tvb|h#<;y-WzHsQ@S&$?@wLQi1u4Q%#i{dmoRjkS?7sfE&!nZx z8`hPN#TVJz5o^|BmoeQ`tW68g&`$hp4t8rZzXExJ40n;#^2daxOJuK?M>3^m8FP?7 zmi*USj!xiem26`IvVmSafI3@b$tPR6&~*?zh^1$!bUFxWj^VZd z2L7l47@DHx?y%{P25Z;i4EBh)I#o4fu6eIrrmUwX*$#8Fs%Ydo>o6GS?k)R9d@mtk z4I$)CBK46Ch=&)J2Q-l1%uH+eE6_LMBQ)rdt8o+ZNTG#O9I}l}TtS|Au{6P86HKBKTYe|xW3I*skx077W`3tw7euIW#-#!` zYIse{cvBn#761#TlKKw?F#ciY@5{Aai1pHx%f&eH*2(5pGbIg|YzY?vNVm4Z-OMVZ zE{BLL@t9=%k|uKCkTa;8n~r>;Lo75>Qd&YYIpW2Q4t0=>RrM2x`f7k!-9ERvYM>DRT&L^(o z5EFFGMQ_MROnXJFmQnn}?>5Gvb{p0F&36#)^2DuGR1yv5gOWQwvPxo*R}u6mOi+HT z1}y5_CoYKyZEL<^tYHnU!sA`9=0%^%+2s0I9&QQMiCUP_=lyQRbv7hsTw6jRl@8R~ z6HGV7eg!k_#&{tt_)}uu)3jB-xNX**kruJx_njh_gr1AH_9G;#9^-QwFyHt?Io7niTs1!kRDk(vIkbTSPf1cr&Pw{2I0NT z3naksN!I^Mkhy7K=bPDRVOc4okpVhi&<{t*s>JZikg*<#;R1CQC&Vo9&d-9(TBHKEX4mN<~m`r}4w3I?dLXe4bZa{}Z3)oAkz7pf~DBScI!FF-5gmtt`VYr}+hc2EifGOdhysZmO|4(q&N_4(CEe z8)@J7rsdQ9#v5c~cnqCa@@2_k_>;0=T4mMYfm=7UR1q;3^iDj)Gf`^Jbo{0`N}-La z#)y|e2{NVub^I!V6lYRut;I+f#&9`GbTRhM1NE}I!ZDNm?y zV!9xM@6NQD)Vm~Bh>HS4e36>Z6yOM<=9G%I1>f-ixD?szc>5bg-bHCIQE<98&W-Gy zj59$}ce*OkF@4;tdRh=pqMrPFHM*OvUTBiKIl*k~3>=q0mzp#2s{cAF z+LlTv!h(TjKh+RYTzW&rjR#uY;l7xYe^m+$Jb(DHw^40}raJ znWBx!ImrBxLoS3}+&Dk6`RszBEzLlPc>^e!SmO)iSd-3A(RDtIo)kL>d|#>8P&j!0 z=D;w|?I>T-NWAd?MpL?1FA;Anq@Jx|13pXX$*K1-*h;(MYW0&;5H?xOy~5-76A`Fl z0lXYNcd=O>3u9mow{l&eNJm zS3IHIdNzbxq^jvyMR80Shp*J4>GL8LS*>N3&*~w4kO|q~SEn?qJRN+DbDJh7X z&qz1EdMAfCZuIL|+?h&c2!^*M>VIF2`J2xxN6p07S>y4W@XWL8{hP3UUvhnMfPYW7lvOeia&lv{r&+Ky z3y$u2!dGcZw1Ka2JTGFtw?g4*0crKyapjdN4uxFau5#LWBO)|JHq=|2wvU~*Wo`gF zQBK}ien5Rd>d|h|LSclcoex+~Jw!~8{EYP&-%tTnv!2s{ju4ND0}VN_Fo@ChLHxC%e-&zimwT<0N(C$thY3ZmUpo~U`jrhF~6(?>o{uat@V zJ@wW4EkS9JNPzGUbGS8PycR*47Y-w$C$h!*3SPlU#Xb%ZVt88$@xLafZ{&)AXcb`l zuv6>#@Q&TtWP%T;j>jfq0=dBMc3}I3*2Wdu-(CNA4Hwk{9FGC@k4~{=2MmsZ`Y#o8 zVLPg%UBcpdn)OKqd6pDW_(4Kva{E#|*BLm&5~tBc#vL2?0W|;2rUfqb+Qnv{zXWvz zOQ|5vPot59aKVgaTCr$1xhg_C)r?>$bTB5~zz>n%WA@&;PP=hFu-6!DTjitL0;MgJ75V4$aYXnkI6 zGV?e`M9eNnVMO)|<^M@jw(?wARKOU?Vi6YMOma;!`hGZepLFGyN@8XmH{-fhGSVK%E+sW8N~U-8>ggr@%}QIv+)=Nni~^E^5O1%Doc@yC;Mu=tXx9>&D1x zlLsqVab<&)XbhnTC)@28c#XXf8(qeX+DH@D{RQ07c(9$q+Nc5Bj@ngtJd?THR+NAB zL34{1ZC*AahkTIP5s9lMhxtyz8NEX=rb#O7j`(c+`wILDs+C?1QPsV?O0__*$2hBn z3i3(>UrVgsJId~J+!lZVH^0GwXs_D+i0DRKW}kXHEWD9xt3@`i_;b)3V2OVGmh@{_ zQgm(wiV=T)b&bjBDcF{Ax|w$ba(*_~!lo=DhOp zobG;i9=MFYcJ*;_;zlmI8Wf;CkUbe#yiFxf!+Q{q>8;cBr3G)BRC;1Vnuf#P7r9&vntDb6TZeCAgHOA zbYigc=&^T^ZDJ_05eSPr9v3J)dQ>TPL5(T#V{m~6>E)Y8s#Jbyt7t+5O|3pnO zS$ME8h(I7hM#BbxGGKvDpj#ooi#VQ~!@t#GzEBQn?jD`Qc|iYlkQn+yal*YyoE*Y9 zMF2Noab)Dr??wNLn}UD<>42gAho@{1E1F_naWcdGKpr9xhTMT=gg7-*0s;Mge1Dop z;WFy5!JNAp{e1cgy}GHnxwU%!sD9PU3jtq4-|eFU-$BDbgNTNT0TrR30QLV;EQS#M zNP+n7SN;ty21W^R9{qDJ@ZR<7@-+~k9s+x}r^{`*Ju?I}5QE$f6cbq35i#)lSn%uq z{+oSkK=<2@{JR&bx}7kwXZ_FN`&RUrQm068SBNutktLu zilh8@rOJf3<4=Ob2Jx>Q>5v-uK6LYnh+*MNKjdNj+fO~Z2#F#SUkmNQS}w>xRG^Sw ziHI%Q3euZh$I;nC2Xwf0_FsG@Y;duypG`&~WTpSMGC`h+K~5%QR3spG$OH66^fQmI zV4#9uRBRZhAOmWrkb%X_ru_)2s$f7#zvLhP!6-ywuw)28)OtkFK$7nUWDpR6stgH0 zKqcNmp+H2>uw)QGRt7|P<#XUeP8UBhBThNqn3709fPO(v`4HI9>5m`qAv3!t#-xGK z5M3f&u(N(iFiiYt@q?^y!pZu)5ZmA24rxQo7tRxb)9-q)bV$7YpLA#jInGV^M@(=A zt`P$yOw@PG5%MEfU~tF%-zf+W#=wPNVWS-So96p;9L$+_Mk+X86x_0{jAziDR{{4VivSs*?!JWx| zM)>W4AIRSypaH`?CaR4iP8=Ha14ROWrzTCnY=}dlfnr9J3y*X9h^Kz$#`kA0k=S`L zeqp*2>Vty>X7OKhOATEn=bmb{ybL^vv;b}Vhu&pHkXS(w`L>lDK@mUDRWuf=d?}pY1(31 zY=m$i;+!WsshRQzK|cq1k?pfCg@WNC8HglKGu9ky}UtdqU9&9$D7#Nr&ZZHGE}RrMev zW4ks|p^^y^MCK16L?+rX*)H%UIq41>y@&2#PNS>mW<4yMvUa1Lkq6j!J9-LhHxN+AT*ZLF8q9lT^~;a+jOzfpU*vcTk9lHnLt z6Rz2^ECx-y=Ly>S_)02pEHnXr}Gt>55YfP zoqln}oKy%r7I=U4EE)IpH zhtt`ys`izB`|3JV=CFZp*TokL=(Wrls=~q(%wv*KTw5tOPXvL59ug4Df&!{neNm}a zJaKimzO)~{gEAz}h{Doi*f*&)sDtsfZvhIml@7s$lD)n^2->s0kF^V>l=6&O!KeT} zdPoL=nXO&8YvM>vm6F~cSpD+(g5kv5vVGj;Q9z~jRv6QI=b1LXP>BqC>D7Zj{0 zmvn86%NP2jhs);l*(9%8D2|b^Bogv3Mc;$8Np;cEEy976HrU9(%`~HLyD^L<6IN}l z1FGEyhXMD7E_LD$|D->8&>w!{jB0~NGyjK{zrDs;8e+JtE3IBt?c~$)CtRqveSAvG z3+=qUWcO0x!g{I-DgFhq3+!K)vk~!(y{6On2*yZjVZJndz-09L8gZO87?@8teEC6J zoXbb>=Mx)9XZl0K#0*jDX1l*8GueSMw$t{(pXF&;|ga}vy347T|@bi4iO&4>I# zzgO8P<_AEu`$l0ruyeQIscQo5cGrN!Np!DkIe~_B&&_)O?^fMP+QA`}Uc(!96rVPa z&w^2!y-Ho&mh<$km9g5JB8%o++WYp|3~MiMls@xa*31malPd*NA2``}&Vypu>|p`|B$A4GO!!*YCK6jIIAlR@M9cW2g~8`Ib9S6+aRVIO6C|~mC|lp*#dV@Z z4C-`yB%`lCbD?g(J3ry45Q-<=XeS_6rqdoafz|L=G%hL>$?0?X71?WQcHpJ1m7gpzua^0bxVX@Eyz+F%(ACR=isgNIIk((Oh3Vi3zJUIoLO(;@ z7thh}i@Ek#k79wp<1toSo}XskiuSMi0(ALDFRk5oPya2GnBPJ7jwcj#Duy-xixvm)6;EeSv(+MHvge{BiK?c zLY7s>rW<+UVU0l=8{<-98T*HVBV^7bWP4VbKA>M&F=b?>nfZcC&*eAISebcHZ**FH zn>P#^rSEvmxKxcVq-anlO2H!d0n(@r(lkjk;(B5zt$7u_RDccR*4?Pq*rq05pDIVk za9rW3WD#bD<;o{kQQAmM)&GFGB+UhW_7&rFn6N z@Is|pp+#Ju+Hu*9;phb#vBnTpu7yVM-(DyJkzbX*9c2!c~_AY~7V>}#a7 z%vqCIY>$Ipiid&uF9Ghxq;|#S=WrBPIf-^DsNo}mmKfqsscJgKNFqzp8{Qv$*IEE+7 zUrTz$bgGz@!<_JHQ5#M4}7GP2jX^rW!tv#xociE_10i%2UCTo=Xo>JL|EW8r!!o zeo`8j%rVCm)LYB3bi-w0BXWl#k(o)f(H*mc9fXb#IGJi(2J8;C*i+&un?tU*nU^xa z$WJ)ZD2soG4RvTNJL?l3vG3fBe;pz8bnMSeNXpkw-*6|xOQl6GH)*hDe$Q)YdnrM( z`Uvb!kG{-GfA{>zh3HOg>iU7pRP+l0`0lHoHkAf7y*&>ChKcUAHK-QX9J^!n=7?@&h93dql^NBx^ZDYC$v1zv2*D{?8V{eZ1U(%Ew| ztuZHSakw-IfBif4=fzU?UHMY1E;MNnw9zjtgbgE#kCEjGygVLUiiBC@DeyCvR6p!a zs*xj4Px^wkJ0wsq!Ch6HbG}WPHip~9YL4V%Hv`pNS>UTvE6K=gxW$@rBF2JGvn-n+c?SBwc3cgFsDO!(KKm zSMfG#FV|XuW8XsEJ_?w3!A42G%hq<5h{@8u24y42c;yt^hX)pC_?FmM{&g2roEwcV z`EU?|wdQk(KT6lYftG1yWlR84`?3$!*S4oN&SyUu=$^GW|R&+&~hh^$^gc`O_VD0pA(}HNqeBBb{SdWME zb-cYqrz=rI zZyedHn&=7?l%REdF$)j1)Gu{x!<~-nAJVhN(KF(5Y4D%Mcs#9_OYdQ4mi41l0aXp` zEdAHIRD8^Eh;PqkE>?C(3qMJjS%r+0DU2;dn-4( zf=>MI`o@vI-5h*gB8hE|svHhc(qB3^KGpJZD=c(Adb4bKxxSaC5f7{~M9Bh+)GjWN z>E6GE#Z&K@LPk-)WWY)*ljIDTFeD^5ejD!UwRe~DZA!bSsX|HQV^3*^HND9(FxuI8#Ez}_yn#4Q0d$J`?z%ov*nMaD;#S}Cq|Mn`4_}416U!% z*Br#9246l`WhDALb(3z~)9pS7wVFgWnI!y;}T-aI~Z~#)l8PHENh_- ztIfEc+zm;m<7%Y&S<3cvd4Q6SA(YFW3<4BU6&#j2rx21oW^0C;n`R&YT=kzB=9k<%W+3udzwI?MLa^cwhVn z-!B{sHg2-3CvA=r9u#M(e)lhv;2<+8EU^)$VS-_1z1kfhEhg_!sBZb^Ay~@mcNK@n z#1(G`Us{{HsCsJ$br7;{Xm9*!*L)RKxYE~)@U5@=PaU!6?Nl@G-;-w|NT0Y5h!wEw z+-Jf1gfg(Z-Jm38O!4gxJ45hhdGzbC>D`YF@hVUPE&^&MbBV*b3!`%S!-xznhh2PkZg~ z12=$WarSTzuSb@=6#TvY^Hf*FBv<^^(kYB;%O^deiT(NamnAoRmPumc#u?FGPHF{B z=z)wQ`qjE8jzBSVrnV`+t#0J(5%>c*uLxJuYsX`p=EhpyIGZ;nN=vk5mpod!rV znFPWy@n>gcu!XKP>Mgsqxe3jmzbQO>y(OrOA3VtcfBS};n6eKRx*LkX$evw5PU!{! zg{FsoQhn5B_hsccsf;HSVTAMFk=={e3+CAqdj#K>iqqkeJ?#d67tazQzb?RH((Qn* zMalduMZRUeg=CQ7*86der*G(BZ~Pi3l(`)=CMM8|ayxbx-eNjA zGW$tRC}Fo6Q{V3FUM}^1@a$%t-YfqULVkO)rU0Bb;3M7;2W2xX(EdAxT?2)&oVDI^ z&x=q+B*J7MEt=J(amp~RGLmj5(voguufCB@@)=nS5Kz-oS$RcR8t1Za4$khDZ|saX zui5WK@-Gj~bJ#xT)lj}cdJPrFi;~0OmA=z@gDvjKS$oZzW46|UK?}!^iIlvNhB8Bn z5-a1D9DCHwQ-7Bfd$E)c$Upq+syr6_D;*MK7=$1^$;QeoM`@_|@1nY{MjoSoTOnTc zM29ySK2Dh;1XEw$@;-?sl)o|vZ3m%JZJV8)a9G&okZ7fl_)Q7hg7+yivlGM%P`vsFS?Jo}NK~&`V_<%j>x| zxJDC2f2K=8+02Z!3l}*P8Fna9EpB^1+_if$HG{B6J0>chF93!QXOw%lHx&+AP0 z?GiE?Qn^;Hz^b{|;i=RDhS$5Y_+op?YpDhd47JWxWE#0Dkh?Ga`Eu>i(`1 zo#onOR0s{1Nvo9A8O6V2ZLZ5rJ9!6^bTp3mQTDM>Ih0bzSNH9`WcXJ$J6}2fgN%T~@^ST)24s54Zf#?;EL-5>FC6UiMO}Ex8=EH17s^3mTTV+#1?lbr>i&AO#KYcF+tugBSan4g(MYnJUA$* zw<#(+jFtQe`oiDZ2J^041%HAW9Fc?P2V<%m9ga^Q%fK1muMcRE8UcQmOY#kAZ;(yB zAs^KFP%Fc!aECJ` zpH-3p>Z1fvohtbW-||b2fC{+1QkKos8r|^G)+WElJ_w3>YBrJkWZ*}`AI)7u@m0Yi zDe@%EBWaq|Qt&iG#`D$kh|Sly;3?W$l{-gBXvNSpjlz>L-ehH;l}Vuo*{8uXJ^k@_ z4(R44@3n{?5;fn(?m5K}Qnp9BjKK-u3+vmSYqdw853H`a-*$Y}rjDGZ&411HS)*)D zS#kYNwkf`eF%=KS(riYvr~o2B0-7+Xy%)FLJbVd zx39Yfx)|dWS4-+xotAuerLC=p!w<(aJ%;-Z=fy`Je=x3lM=vWd;=N&wdf;3((06}t zHj3I&ib-!0rWulFaZ~%Ad+T6Fc1?)4$ZfmSVprP|OY+i0g@cMzK{bHDHBCt^xBfkI ze$R_wRr(-XsQAwf{U_(Qja3q}HaXnNgRUqiThz3U@MJN@MLzB-bKk!KuaNdlPzW!= zp89Cra8C4IA1Sk8^hJK*(5F?&HL5}0pAGtBr=*&l15vDQqPugA@)70MS)GtZ+S&>9 zWrNVo)-2=x#f02iim$|%@#{4g#z4ab=#@lvP9VQ4FQVWGQA01*Xj*v3weZg4*>Z2- z8;ww_c9Z!d5a{k8ujbMP!=EQsSU=!6GV5S3os4@HOdh4^Eso9QY|JVy(gwr66r}Mx z(Uo~)mPzM#;MGC+`(^9){%RTi2Nxy{PpI`}1U^=mjVyl^UwaHPvN9nylg05kZ|rA@ zb1l!ta*&n*+bwar54%`KHO<6tSHNJZuM;;9gvatUdDAyv704atgGS4kj z>D7bqP`6#nZKS8>%Ln#%V-7m7(w83jtwq?mpqmN~o%yqkUS$ZiUKC{|RVDd~+&)B& zZhL&?Iu!gdFp{78Z7gk=pRH4>bfUh~_U-hmmtYsHQ(i^7Y+6@WY=@J&o*7T-b@TZf_-RPiiXWmCu_mD&spc-`|I)vHuOP-bC%H{NxBcKC2^r;@Y1`N++Q3I2 zM0p3DpbY8xxf^y#(CQHmpT=swU5Ixr18?+lCZc7K6OVM()Zf$QoOrBv#G^2L51I#E z2XOE#!MyPB%k}6HZ@KQY&lCMyy4+np!eUaXeL871y|0a{9iIwttb7VVV>XCU7=L#%@8HIK)6yxc>oO*F_S~LN62yj7j6nw=P=f%X;{7Jp>Vwf6mE)z)v1nFLeL*WQ09I6OI!k`Ga926!4g~~AfOz`gi znS3J`pFk`CVrrph4b~6x@o{zW^ZS*Hg%>Um$Q=L9Ngim44G3h01|q=B zXbQ@3MTJXnu;Smj{$GZ`tGHk+5DtYYLv*pOI2S)zpf|yV=oN@{0S5oIT@lPYK=v0& z=`X^D@_$sq;wAwLgrHq-V2Hi|$Tc90*~p-e3kW1KVH$roF#wfNO8;(L0RA(i>Ff1r z^n~Wg$bP4pP7?wDRq(DPzxK;ZST9X8J7;rRT*_JB+>aLB&F`W#oXoudI)k}tD=v_} zG0%f7hE#PdhpPb+`spf*3@-YaJ&WW+S1JmmV|(>(7Yl|Oi`3*ZDvLfjZs5#UDrIEw zBHz7v#wB`=QT1EB5krycR~8VwaM3hY=_J9cXtu1!NAFYBOiSNpCC0~@pM1+(2wp&4 zhu&{T=EzIm2@_e1AkMQ!mxB`nDz71or3dd^3GB;|n>8zv5evB-P*9=UFUGclksyR} zj4~2XLyi%C)S)XzNmf{La&ZhNc6pn%GkDH<+tNqd z{$qn?ZPuR)8uIzgx?QN;HFdJY0hdj-YO{I78u^+GU(VZI3Z6J2nK~246#8#>Y8===oG>bz@4lwdsrGD-&TNtN2ULs@3>hy5TKQZl$yy3`e z99Jvv((zeNyw})c0$tV5Mo}jPe*fWMIGa%!im2|KD0)+`%s96`T-a_`8Zq_MYRXe# zi`DU00u>*;5r(bD89y`qFznD41{dhGj7(=RQSM}1i<=T+}jBaZG zkE`gv1!!%K^#DK&{oJvkKszW?&<+3y21oiOZ2-gyXa@trfiUKrIUY|0!jzZ-Hvi@B zfd|5V-D|%LU7(#RR6$7#0n>(|pgKx0MFkzGK3qvbUr!OHr=_E#tgEjM{AU+tl)u<) zim1O-|NoG^o3ry?e;c*?cw3KV4_jN3W)HQC+Ru`!d@D0?AW-yPFLzt9W=}_#2it4~ y;)XrjfVgH)>*7E!by2Q^g{6A=HZ+&fss5s@_#P9D1PuTHOc`lORRBN&0{}b%3akKdH{$Sz{ew4_ zdoKw*hQ;^z~kx`IB-hoHLMtiLh-6IMB26Hl!V(On3 z4%^#nwgl%YTt~G);_#NZeb=%Ge8IGH&oe}QPz*8yGJ=AB4!@WSdWP>NU1ya8XlQoA z)#bXqBdGg$Y>522{A+IbOWXjPM!#E&VIAuhuVt-2;7J|3d+qYYn7iHa7(g6_dTag~ z*$s|52xou@b`giZgk9)C|GA)SN8pH~2CEZvD)pa>G8lIEKkNQ?1OL?h z?*{(XZHBw5HKcp0wKZSdW(Ap(Evk8^s(js(`+htuMy ze4~t~lay0gu2k4RMQYGdsQuKyXh3nyt37%^KK~mdzgj;qCgV9@wO?_GL@%kzN&-?{ zHbBk!DgmMftvcqzC9R(QrcM`FMshhRsT!J7-6Dy}}1wz?f0Xn58TWS@Kl{ zAs+{rbvh6JRJdCY9{ii-+tWl+sRB&DwahpYW0=&DL_O|5f)vPkSf|A>30d(ZSA9+! z^B_pj2K7oDC$T~{W8Y~k4O%T5%HoU+ZG^FYmf7J3;mR4KN3RcUtibKovaNx*9|LG> zQMIE>=|e}D_ZJ&NUn*0cBNEhO7IzHB8If+bh!>!Hdcn`_(<~W?h;+z8c zPQPf29lud6yVlpgY;MQml2G^)GJf-Nt8zlnvW63O@qvP0XcJ7}sl z2o3PG4M=?MW##i+yl?6}Z9k^VGGp3qvO4wG*8ZF4I#=bO@7>bvoTWtNux0e(WeOIH ziup2iH)fJ7sI{e+H*QG-)AyB=S~*;-Ttex3i2TUt1Yp^c>G3230XHfjan~-lAbgpwAhQ_xl;3wP02^-&*%$6sF z9i!NBZwOa~cC$=s;XQ}T1xqN0Mab3q$@-H?kjNvNy*zi!xuhWCT+U%#5V@Jltki^Z z5Ls+8#T}O;crg1uyM%)l+F)e+TtE8TfhSpNS44|-NBJ980NLWWoOQOw9Y?x30?YHs zNAKoO(kLE;cA6E_Wo%Lq8YLtmY*gyiP+c;fzlM?mT?zX4Q}9SYDc>$|pQI%Ck|2uh z?+v-ue~P}IxYFpbJz3;Fm?Q-Po=mY)56ieG>XW6Vz@R3!x=J#f!W8f05zCoFelk4& zAN$;gEIKM7Zr3?8!zW5lJ&Jsyi4~hb?Ahuup^&Cw=MbPA{)74fU+ZLOYt-0k3!w)P z1@msa_pA2x{i1wa{GMtn~&M76eO>Dci#)afKP*1Bin_;8H-vpXm@ZTW%o!1FYAiUKH2 z5@99o%Hd9gNz4H5xTOHOOql=pBRar2F3W3Si&?BRz-+Ch70FW{x|k@q6ezg0V035S zaQ&X^5tS8n*`@lAkOe3$l7IG0ur(bp1d*%=BNGP-#wWzGb=ZcDXj*I=5;gpB_Byo?0>>etHCNTaW`oV8KpT$aeCR)EHTKxKM zYOM4`W@kznOrhUVH=}d6Oh$Y2X81tDIfs=TUI&45wVMQ(6DL=NOXBHrb@p0U_qDSv zt)J1kMYBS^hTk(lkkRe}OJKNB;0z}5rzbtl3fEbYt(4fsV_y?`@guZf?O;fpUB0**+465mi_m`j3+?Yml-t3Ko< zyrRw#!_4M|g!+X7;}a#~+epy9Q#17V`MK%KMvJ>_e=n~&tXfMx{cVN{yd0naEKOF==QN+o3$Eqw8)^C zBaTv}$-CwICX{^;!}yZKjiJc$I=|HKkY5%Dpz7jinU*RFG#Qeh(1fjrM=IJCOzNP7 z&o-nJ4~JuiF+;iHD4v4x&bcf#2Lg;a(U*`4()WfQq`$rNcvvmoIxmNjd*(xs^m!-- zU0)%@kCZWHHQRCLW%Al5`bYZRI?Q6~fJQ@>KUtdD7`3F(FQSPvOpU0&P=3+(Y^J4A zu=Rne{$xz`17tmUrsW+UG%8q`{eIx`wV2l@hbdrEXklxbK}Xl z2wF{U0S+D29b5&GC9ws7VMH+f8}Kem&Dq!1RzGW*<%$sR)Du@F^O0UeNpXrVrTV(# z1j;*S8b4fie6pe|9+@{IW@Zz#LGR&QF{rt}dU^NzpW{bGa0)}VsDsq_J)J<+;E9=x zyVpb%A%%Q2Cub_IN{Y2XyOKF%-72|OOkQCPYTgtX$&DX;`QNHuI_6%|8j?E8G-Agv zHrUwsm^tq(J7fw)f*Qf`gGyhnv_UCc8M+|UiVW;Ju%(Yr^@Z!(iY=En)H)z)gsD$E zBPR*p*1J;)aHkR$B{J~6^dy=D@3eWU{nfkA8mki4?|Nn}%BdYr{_HVdxf#zaq~eQi zxBjZFd(3f0!g=tt`@+x`PeMPqZN%GG@{S2#m6VzGC-zRJ_jEI=teHZK@`^FkxQ!f? z1AvI^CX1WMN+zFySsN}4Itk?}ypwYH_HUwoJ=k5*-NrQ@RSYdv^eEVcKeD}gRq>|- z{xLnPw(Ajk6v{q%Yes{ZoW)ZowhXl^=eL_1e=DD)1~#B{_Vw2~`2-))-@pW#;_=cg zswf7e3sMAid->+~=<6c7Imw4->-U(kJJeUUPm#luX*-rH;O;V%2H*ZTkhRG(0y;PE zYCi|WJ6|wTKAdB$4mZ#Ww5g>WEOgZn6lwK0%V+OL*dcVM8n$@@SC&6m(5rG1(`4<@)&HD{>{J@3`Q5Yq z8GYbuHA?e?R<4v7_*Qks6L$9XJLFoId%tKTbTnzxy9V11Csyu=quMWorty!A@3-CA zB>G=8y?VCZAS(yR7TCMK(e}yyoo|yB^Zh})3!kM8GS$nR+^7mZMsijW%{LJkiN|7ck)FC zs1p_wPBE~wIGkUUZiZa@*L!wPzSw>Y4}-ra61vEm2(+U=+Vx`)iC)ljWNPIPZ-LBzBc6^|}Wy{df@>MDItzVqidR1MChg0SjH7Mu+~JY%c5a_-Cq+V+Tf9W=9_ znFv4T*=AB>y^%*c>sf42hHcH0dG)4Z9y8uqFQsxY?FoR!uz}2m|NjX|@=-$HF4_y#nAfeRfh)m*o#eTDi@u?i=MHg3+qJx}xMG zX>QFepiVK{GT*l2@E=OsK7l?D5qTFEiRP)`OeYo0iM^!2;{k8;Y<&hO(qmp8ufjlv z54hjFg|JuCd+EV6jZjp-d{?CgQ8~syf%JPv894I=HFk8y`!Q)|Ln6hCIGHG&=^ShC z@w3=ixh;}TH{AK*My8N6Jd3Cwf=e5=Y0ppB)KmLa(3p{h<^4-9%T|8C_A=E4abeG_%#sDkEfPz8(v9lS|`ZC7$Scru26&yJQujKctF zIbe}q418l2An4<6J~~(+bh>I`JN3Ao{Q$pdP2r;@SErjum)}_se2yJZK^mktUdcJn zkMYtx?7U4lHN5=2hRh2y>8(9V(@T!jmP^ilw+pczlL;3jLkN)XIs3v(maQ$RN=gKA z5ck2mS{CRez`{uj4~@(EHgkv;HYscN7Uw-2V7K!=Z5X#@Bi}}=cx3y%oEE^IbTY=j zoSq61%rlt<9!+M4U#bCm&m|-+lfHO3ZraD(vZT2l1Scn9Wma@)Qqt+13(@ zLwo@!3~qO+Dn0hBdtWg=!EBkzjHT0Yx;-p*rV-NX1NQl)&i7z@_JoX3KWE=ab?7zK z&g2>@mk?N>7JIQ_sWcBrZ;BwX+(>K0voP~%Ay!|i91d%?{xcSxE@R=|JI*-u~wy= z@}gb3U_ch{#1TO`Ga7Yjjh{8!%a~(T|`7g!g zl%hTgT%k}21vyv>TZ=Yh!Z7o9+tVi)$pgyyG|f zi;}6i{-|Fj@Ock{QIDJ}poHfoywD=r{6K*vZ4PFz@)b69;mA{W_9KLYL;p#@=^-p- zky&-w!vSvFbL)(7oJD@nq4Zq3rKrju`iy}y!sg4|z>W#_Q{-Nrq$ZLOEm)vYKVt27A^Mryi;DHO#`Wr61O2J5x@HRXg_Hlc1Jw)7FOGhf5*ZH4?e{?P`)RUG2xeW+rgWoxjRLe$y zbQ*a|O~A`4%0+WYr-M&##b3bMs-|46Y^$IJC2}Qb+Fqs6xHn8f!v;>Yk=(nvDAXkP z^8>Aj)c_GRdY~Zjr!|=RgP<~dNvPwAN$a$2(ZDAJVr!~}0tVZ!7X*}l+%?UKqS)wn zyB3@I)>81^s_=|J4DBpiz7&=+>miz+C`>UM8FOiB>F_YwwXd>LImJ9sT>A_OLw#V=r(Pw2r_O*gEp zQW+k8FKbalOXAq6m(b0{C$hy|CbemN4pN=okr0}E)}2dWwI5ZF6wLSib!45M0ctHb zlig6&Dxm<(EWqN|zg?ei;#Hob{&8J@8wGF3V^DQS$b3dl(3$BK<;KLBWVAT12Y0ROL-iGvb&H zybf+0sQYHS*z9zDwpdlI@D&&mdVe&aCEXQ}sRSi$eD`_U*ZzJDu&< z+VSQHNk=2#E#oJcx%}agyx}Bw`B-E0S|BSa)V|u5FEETplSwqm@zxfFT7qx6f$TDZ z!#}x^1skXDb96>3-H+J#;4wK_YZfZH=g|wxqmw~)l#a9E+R)HVkBmwk`45)T&L~Dp zr?Fze1sgq!$)WcRV^2yv9;Cc4finMT(aE{VQ_e&yv6BJgXi`>*CxO}<2j`abm1uis zgP9JfviY+*e&Yv&#gmqBzo=S)$okcx-y}oU!IgM`)yKEQP4RS6LbVFGo$V&%8nX?4 z7fIK?e4=b^QsE3L^oCivv zJI2)^*}?I}`N7er+DXM#duwv9f`VBJE`cwM;li1rzw)CmL$af7m|hoLzw6FAy=dc_ z-e3pcAFOUdMoEe0(SgLT)s6LF#D){GO5Z%qZLp}m##dUfOZ1$3-W1?m)*wE)!2}=U< z|17t*r8)!>+A*JE0BC96G2tyszK0e}@_xE37pL`Kj)@+&rJ)bF_(X1=ngO{S-OuaaC|h;glH!r`kAAq3 z!#_!^(4WrQ6i}Qy-#$(bY7B3-6Pi+Wyif5Py0x9D?v6;&^^EH3R`(%5LkH|kViA-X z+yq3Vn;r%q&7>0G{O8+!Qq~oD!Yo{uKU@y`Pgwc3`6hRYt$EjtopB~J)bHkwb5`P0bIEAfDET+upj9scU8`mx4@i$ng$-Y{ax#>l*`Nb*$mSCfl0w=mzRm&B+DY zK2;Ztn@IFzXU>`}#L)nG_55@NKwa{;5sGsc_ZuCr${zR2o2EhtlE=^9IMT{R4^i&Q zTAkuV_4Gzc90e6V_jvPrS85V0k26a6fRPSaUn=Vg5V z+cH+MYt|HRi@3rBS6)O>x}Tc;jpXQwEaX$2d0cb)=hYwN#~_=biIs$t)$Zwn?)%z` zSie{&+rL5h4`fKcvoZjC{oKpbT6bTs);aiZ&kT|5{41$Sd)$evw-Xv7-fV zkO?zAOjd}VZN+$zN>*Y?L=m9BM^xj)(6Oy(S0lSCASe@v8rFYlNsH>1Gl)YCVo?D&k!gR`%i?EfjLdG|)pgAWO+24vos zRh*e@!A!Da)qipWtqRqq7jVH-A{EgzvEmB2-I&j}NA=R`DOmr1mT^?^VJgdvlhRFKS zZ+}PZp?N+&<=TiYN3%!CYex+E?!&n)E8H6Xc(wz?hbN@c@D0d2c`xBic$0+sB zTxjL3;%Ru6>ZvmQsCfM}Ia=wUOIGMtCn3fahM7>Df!W6RO5GSy#~B?+i5{qP#O!M1 zz7>As{7pSqeLarORjZ{G+O z=%CE&+ET~3%MKt-_zYva>bfckE08_AXdovkRcE>=aXZ0vwOk~Vk;Qs-+I)x5x|UR4 z$pj{?Sh4ke@MMZa2GUH2_nJoE6lE!GJ&auFnu1)IWi_a+#CgrTdIAN9Gg6*57DlUg zPCgB~l>=(hMrFkYFm^&%YWSOIKVA2)Zmr*+kCALEIwVzF&J{@)O70@^I{_H6FiUF9 z?QhH7ohbXZqAz7%O+$K+eh}-A)Lr81kJb^9jTtbpcnw$5tVUHkp%x@=q=kZdvo;Xb za_=~8%Y%<7yaj>dG4Qymj9JS5rkk`ZApN~BL`lxd_TvB%OuerLXXo4l2QJ(lu>enj zSwQ@UF3OwhR#?pK-c>-)<-%b`T!z3op=MaJQjeXr;@2f*!Z#fK;Tfc!CgCI^l_B*& z%Rtv|InqH=Md1`tgH*DbW!u$uS~B#;R7z_1T$ORX@#rY#OpyLz`vAIpVo=FHGbhsKGzG`GBndVlyw^ zriOdJv)w3YhR8#tvm-}(K@Z#5$MsA1ZQvGh7lV}bFZu)BL1udq3!~|q0a)xFGmGGh^xyS`D%l@=*4myjRj=qx zsdS^^2;lui)7W%G=MYIWI9ckQCD|zb;ix;_n?;YEfi=is;#HQ_l~=#S?QGrs5({}W zBmn_un<2BNA9qV8OO6VbU$Ro9m+K@{+*tmKnp9Aw&C&v zSd(oxLidG8K@e{cPM4VIvB_s)mZ>7iBGu5idRJ9B1-dPX_0~!vle=v6$MMJL$I}k8 zN`$gaTVN>&q-+C0SBWqU$0UXfNj7hEtT>ya zLD8Euk>hO-rM5RW>?crTFFe6`at3%+=tNBgKKfvsEOg_g#)FaH8AzF#)9(@9?mesi zwt)5OH7?BFLI&Q1l{;!y^krET#BjCSYcptx05b->4@`-P0?Q(%{C?~E+@kYg%znvP;usNb|{ljoh1zWz&!xuTt#a!`lvA&z>HN36h^|HBux@4>GkMF#5IU+p1hE?^lNF@Q! zz{E5|W6Mro%Z;<{kI|q80R6`m{nO?#uWh~;gNY*p-KVaBO{81Tg|Mm9ankd?Ws8QG zo))Z3D!H3d2MOg~p3quQ2T{cZ;Y6b?gDdwC<$lrZhDsysN}y1axwf7$A=XT?8>!~t zaKmi4rKyXUVAwTZP)GuL-lkx4u^ywoT7@01%)A-)OOV8DgxxDbfB|s4G*P1NF*sZn zU!o3jcEKPQM=1zHa%1w55$OH3RS*_U2wH1mvSa&3y4A9Naupy@ZVi$+9aAc zw#~iG(L8tyKfXL_0VR}O)T2Al=$#F1>KjBI51mNChHa8mmhqjri0BEH2*x&cE4Y|NH`_YJ2kph4Q?GQk?i8Pfl4J<{1AbpsB!6 z56m|73?M#X8km<%U`SC9Z--^1C9*NX@+Dv;$VT6}{;i(mq%HSPn@ftr(CG!oC+p0A#Zi(t$p6oae|x0|J@rbR zSXu2P_D{PPYpGwHWC}i6qr&8HvD@bH^tLw}^yUPu{F+YbsaGA4Qm@Euyv9~tkr79M+MOnCjV?c{UAKJ=OK<8Cse)zG!AAA}%@Bdf?62VdrU1qj^(-EN zlC#86pt^UjTG!%&jd%RzLDJVBqWJUEIc$M*`IzFM8riJ znbTQ;wseQUT zx1j>Z_OK{N0%e^lS8=k1z7M7WEw_tsVXh;v#08RXkf+3jA;q0KQO;Z=Hk?zLwp{P5 zbXvspLaS&;-((mhteqFkvMl$P2V`AU>3}R6c*`z^IN&Q^KH}xNcL4kpLy+2#m{ocG zN+|oV(NE#@&&oRRz1pvwM9tF(v#_%9sW!CEjl0?|C%?wPk69H;-A3*0%%LJ|N43u< z)(o!aQw>U3a*kjAp?)x92GLcs2dUCOG{IoHGWaOIlGiqKXJ+Ixjx-?{?RBpMzU9WV zN-W0(!Xg|_Doi?2GI5FsUbJFZ9R7J0JohH*$N28=mD5IMEo|SyGbc0`E%!<;Yjc@%t* zPMBs~vKf--7CZr<_G%R9^SN5EPG>K>|89x=LW}s#)WlBH?~*u71GEOV4z~ucAHQ2u zyg9U4oA5NHi&kPEFh57blJb>BnLWDuYhPtm@+%3H7%oUjgawpIiKtnV zv!yC7){@a0*B)JD7dn_XGD&J3^4`1G=RAEW8^2g}Ifg&ymRydm7-l!-$_;*3Nur$z zT<1gSlyH#Rm%|=}hR!bYtpStY__ft@&WoJXTWTH`KA_73i6TOi^MY<`mB#eVujp9^ z;JI|s9X}=$Lb;6J4qV{kW%h5T>CQFuo6Y8R+y zxkqB(eza(RF9|MXQ7^e3eA-n%gylOG`uVuf%#;(ZxZ*Ww*SQAq$fV5kR)QX=?E8$S zuTO~)xzrn?Lt=QCP-mGs$|rFBRrhrDx6ekiKDy#+;N$GgMU&=4PIyJx$a8T+-|5ts zcRI8O#j>qU>+{4D`yu$3Q&liq6%_0EbuF8>I*BEQWLd9D)#KH>jt{h^cWZDBHB7rz zFG#IM%XD1~2&mgx(kqJehCjlXdfi0Cd?eg!mhrbkwIu2bf$iY99PWqs!N(evCWyaHseTU`;6q#i-@rnrP3SC1QIuW+$iWC)#OTQ*m-5})NhW+162bmJ@~!;C3={RA|g(8g0@D=dBYv5yr- zRT`#zHecCAQsWaXlq(SuA1?@ba`Tjw7N-eQsGZ9U?T7dl29|Zu4Z7u zrjZIiBA=tVZ?XIKTpXINQV6UxIf?c4sv=lneDl^w%YP>57YM7`=xfz!Ki?hX{dxqD zS-LPg)VPNiePTs#FVOwhPpPRXWv1;uC^~fS=h@Ok!ceAuA3gvg!#n+PS`grN@hAK& zR!>l&ClDzjhp>3|HzQdhs%f^pXV_3 z+In|7UZfweA)&NX3O6s8tM2x@joNEb{;baIN#z8QMu7c0H--7Mvyh>AIoQ~q6AvZJ zp->+ez$+_VdMae`pg`Yx|86k*#BPd7P1!TSx@{fDg96LxFo4L_#-KupFPudAyeV83 z2S-R@#&o630E@_EW~?YX_BN7@Z>Ds>AfipI4|19o5sK(v=j^8%7V!lSx>3d=bXQ8&!MR&m<&ep)Xfcl)SFCc_@^jYoVHO8l2T5s&?hCS5w}K=ZUb%>CH80v<4To z=fexG`aU0+eQ&%XNEOQAShLWL;cMyJJ4x1eWlrJX6+}QAJ%e9JP<4a&;As1bh z5QpCI?hgRU!($EcP{O&(h$~-{fXqrTO4^_frS>M7vB?id1Ym;Pkj(ErOmG$*&HA?j z)+v%THf@}##^^S-v~bs+I{}$WQ9(;RpEuvpfr^P4!(sjgg^Pb*+M*V7uw>3tJt^@d zPgS|S@2a5r%pO`J`Ncsk8urC@60%v$EEcalwY-{|lxT*VHpF1ZZH@G8@wOexJm0x=|471Xj+&PYm<&N&F;GzrSXl@ztsOoANs{?0oYA`0m;H!0xa7 z$1QcVDqq_yB_jKRih8S{ugiH-K7A}w*KN1(qYsIn65x;0iw|sZz~V(5iUp@QUC%`s z;T-#b{KFKilg|hE8w5fgUO%WppECf7X#mxL$1BA{GS(}7*+}hp#@$~*!3#sadM9chK>36{$0gv1F~wFNA}vuwGq`;|ERP z@{W+iA#e`X?b5C$z)RkR8_1{5`s$pk0Q|#smK_}TWCH7g%Oc8tE`C!wF0y=#R+{s{ zUoC{BVT<$hV(pZmC`xhAbDAIJH980}-h>y8+wrqjDDT-9HIx^zA$U|+)G<TzldBik}}-s;O+0&=M{zM3xKTlnHAbT42XFD>$I zBV4`@BS0*$h}FNnGWfV1Q|-kr;SlJzYbfmm+{O2x9~PvpAvn zB!j=8D~LIz5F&#$36A!gk~_1~c5}-3Wpl<#NuG>rUY|oy-fAbaDN>lzDm8dOeTxvA zh4E!l^{Iz&gZ-x-Du0%FQOv|Tg`rQ4I*(nn9 zygCmo6V}X;wEsZePxv}ox7uBGmuFw`@D~RFdI|739~jwM{2}&!JO?Yjd)Ar;ld;ud zGlf4AM|`xK?#Ea68ntqZ1ydw)gNT+a5^_QR%hr#(eKTg}L&jEYgOCk3rlx@?K1>Bm-ndR+eq~I;g`A=AA1e(?=S!v_BX4VO^NpF0|d% z*U!6cQYXSklJ9U1y0yc$I%jnaBm7#&1Ezatuda|oel^#}Ptm|86Baml0mH81t^9$% z_a}zvL)41Am9WYhW_ucYbAC;(PrF=d@W}U0evKLdKImpNe$%^-ysf<}eIVYTvS-|T zz{8+JUk619fh&iQ+xeNVf!=uPT%#iSH0$l`Mo%bFJgmZsnMw|gH}}T z@~KX*uSU#tsrZ5uK7SaXHtjYz+MnkO&#@OnfiFd+=5870L#R>XHQQYRTcFl1D1~E@ zaEz+8dKlh#wAezKZX`gvG3IlWaQ>F!mg?Up#Q#ySU3UHvye=P53@Zp3(CP7DMxd%s z?WN`Kh}d(-&WdkRMlPO|0dSB}spb(>?xIWYz4+(sF}@g(gz`mhL2~LLws~)SuuP!* zVMbM8<|De~EColD+8~cZI;lq0JW2Qdzp0|L7oo5m8!jmP7PLV@R;T!&ZdV&y6}Ew7 zFqm|eC?LR4-$0CobnznR&tGUg7=vctFsr9yt)hN;=%``%XpvXr3&%ttu#?-0;1kMc z*tEAxxx=L2?ao_T!f2o8(!xan$ZGH+XU$6KJ}|GVZg1im9euQi%gUF_`KIidPzai( zw3tr23QcXB98l&9%WtVfM(q2E3d%(pZ&77i z_Jr2|#;4G{+fC#eGP?t_Pwn>!Ol|kAUdir=BuDAAFjSS|9alt|%I2U3OKb6dDOeHz zpI8zU?IBKIlmZ)}GouwW`IlY0lWHLFFU6&ELwpMGWh0Y!2aa9;r7gMQ{#4K3rZ#aVU$`0gDVPU?VH5fM5gmV$cTaJ*qL&DU2g=>~@j9q0puZtW zUY+-t&PYI}#7PZ_IZ-A{aLcQ}0XR<8082tPbB#`C%0(Cbp3U0j25=S4WzphJ(Cc2iz0$|Vn*h| z5i(%7-je|nAxM=i&*-B^-f`o0>c1~$*3WnXE2*>NReb8O<96GSf>=%{1xaC0V*iYT zDIRQbPF2ypbdY|!TYcA^o1`8d81OgX`PFEIAIJ@P3dlm5xrcNmFkd}IO>3#^3jZk# z=9Xu75c(UdRPFwB4U2uijL*An+R#eD{E+$KKM4aKkiSIeGm_uUTxm~x4|hvq>>sdg z$iOVu$2k)+FsA`)em*X&Yg4K2B?)pW+Fg|=*~RH{GpB<_-BAjiCpDi`0g`bNiOi?f zosjZkBIPMs8iL6!FYLAE*?TJsd*6o%vzEf&ImYXHpvyCl(?4gB2*K=0SyrXHDeeId zp;@*s^UXsI3bapM^Q@y{|B!D0_Dxewf!A$muri`I^7I8;CKbJ3>flTBbY39jF9|&{ z-zwb{H&i>{FWEH~{4NDVP1^#W8gQRwznVi1>-R>t8Q)7;{Xn%-_9WT}lFJmVA4|X1 zGy!AD8}scJd|g9pF4WFh0qiXXd(tP3{Ns-0)ZjyP!}NSlt@@&vkzq6G^ZwHoJC2Fu z5+}40hQn@IzpAG@Zo^=d-kl+SUS*f==AlR9G=gPnWjU9!Dh+<65-cCuC{YFmlG=mF zFO@?L(O8L}WVrP~_WpjeceHW;yZSHlO!mqcwznd_cMJ7_ zGj@LW*C$@qpNje|Bu2a6=ZT170KyYkWtqP->O1n)(X&IR2~R&2<=ap#&)z9FX33Y( zMuR;UOXC@*WqnFDo2K$?onJFFM~lMZ|Jds3Jm_w7Ih3!o2}m!GHXR-_j~cH_Z9O!C z^HJARQAv@bJkDwagC%GWGC&ohZV(L*GzJ@jX{Nsi*7y$kEb#iijaz@nJaTCed604Q zH_mw==gdu`NuEDh(NiCTopV+2=Y*~K$r(NItc_g!K0=5Zyw&0ibCB9CLlABsAADbt z_-qt%UH3a=zQ;W{WJT8Wf@!5DH|nJ;YE$5 z-U>c@Q?4+~g#oJ$^)$u24U=GJQBv_GGmflyC@6#r`rL@~@sB$L9OM?_*2gO3$7}t3 zG>Pk^%mHicgLEpvEN0w;i4*?UviXJL7qdmDFT>M5E)TSXMfc zQ(0LI<2q_SeG0o$&bG%?hQ(?JVc=MwKRQnklp+>f)$*yyUg}+rv7Lgh^n#fPtZkwe zvmb5&e}-i0lcw%Bj2gf5mc$&);?tkswI5IID#7(9n=ODCDAI&^MNy>4`mNBxT`g?W#u)x{bQeVla~r zX8zSCJR_#n^QriC26GfYs}7zH$kZ|vGug#OlVZ2|#HE6C{?B`4D!vd0*>N2XwA&fZ z!NpPS5A|S9Dj_L}qR3{m^5Oi}gI?6y4V_oEhLMMxYYSJu)yW)NZ2R(shoQs!KZ68} zjZ>b(Ok(Szkvj#|yV0ok9VK4C*K^k-RN%`SRA5RPFtpfic?_(KO$K67;09bCDi>pyVStCmn7nwk1f zE?9Xxt^4`XCmWsR{&h&xwWb$Puf@qatv`3C3$>$WQ&`a^1IB~aopObP9T*E1e||9U zV64YpS2u1wLBDwJ&szxp(%vuvcGR2sa;ZUHm z*G|c-dGTJ8TA`sk^1@(3zYj|Te_)KV-7N4hTx6DE=(gP^jN5MEqcaUvZkGi+(Im1t zg@z1cf%0~GYL^rwg%dkh!$0Nwg-wrc8^EDX6taw>LY;=4@Ks#%cgs*jK%LMa1V=| z{TESEY~RLtESit|y<9LoN4`DV>A_}h(d?&s6WdAjEeM(mNyf7!fE@T~^s+=9g zj|O`o8^juPZ$u`V4u8oyExrZA_}_0xT4<)yw4nVDzMS!%o|L6^a?9aH%uVNVMVq;0)|e*%DNp#9YVxJe|3v@sXC&L zEG7>&;g*lcFaYH=A-Wl%G(idQ`N{sgk{27b959D~-Q02QUSfpJ0@9`h;;=S8yq!cL zJp7!UI;aIxEB^y{OmkfSzKP3yZCG>2%UQ6jd&>oyU-^~pkia-HLI|EQ3U=MPNYCjn z2R4{?TMe>B-A9=|dLZ*93^Hdm2>wQ{@&1jtdnn{ZPOCMV$s2+SV~u+w|4$+39o1B` zXz@@40Vyg{r77x1?>$uMQWfb%s`Su{grb542t`18Q+f-65~)GyU_b~E2u->WYA|4^ z@1Xa-_3m5it@jUML1yM;&YaB5p1pru=AP}`&rbMXG)wf(MdiJO3)w|ozs~J~oh*wo z!M9SrN=|fn!qsVGDcWc`lq*ofC}Y1;&JRzx>VEE|Np#tn2BT}0<;hdd*APn&s^P;O zzg}`Y)A_Ry2xaLdTGcF*b(YyjF7AV7wTW3>m+^hT2q=cZ=jvrcZ$6k4$V>WWYf*Y|4se12Y>tegZF*j{7asI3I9g8ps~3*!6)8kkjQ6PvsEs?fDzbYFP6 zRNu7t`2s7EUM>qenb_}PbbhyikjqZQWAN21AXuENF$4=VrTbF!BH64MpO6b^cZOb2 z8?>mL9C=C-eOR|Rs6cCR;31k3RQoBAF6yl=yzNWnb#AmT);n+12KH;#5?C$}*@#b8 z!wzjba$u&{na-QIxl{>?I+VSVKw6J!csPHk0azFZoww5p zY%H5*+p`<3zp@&zq*1!5FZ{>He<#s`YBZmC2yJ95&}6!?>;a!oDJ^lY(R^5xqUH{l zn&lT}X1y#2N|m>4prX+ojb-IWK4#jTuurw@^hK{~ zo5s$SWaU^ABeFQHrL`%_UNhKIx8(%vCH5ZZhQ2gYgKjA1R0&u_a0k1Yn{ui>aPi&! zKGt=fNyy#ZV8ur`QU7+>ga^^6!07$nqVm(-bM(BcV#rO<9Oz7vvJf}b4pU7p}mL>0PU8eEXSD$zT4!0lj|J~mWRb|chrjij6ORB>b_A|ZIzn~KSwX%e* z9yP@5E~YIRa@yY0{0xX*8Fhq2v4p~jXNP(2IBKS`iN?Z#C1I`i#cbHFm;HS<`V+0I%NJK`?Z%;Z3jum86qT7BA z4$pNTer8#zVa2@aP8MbSo|6n1ApEq8^8!onh|W=)zQc!ymk8_c39}|NAkkbd15Ls^ zAc#?D4_1kvjvlAj8hB@sk%lpo83h)TfK*A&`Ao-K1{o{z1|IrxcFMzel=ZGAaOx-( zZ*%ua$DL}X1i{OTQBDnKzqRrx2NKwEpFkiEP=RpO6!r}Q$fmV5zu4Wm<|hrUh`D($ z_4O9JP;&%a<#)=via@*LF3TL9HwdiRC_9qOR{r5>Ord1u#vBOF@BlUr)`C?KmQ%&1vs)%{aow()T&+R-t1f5WBp2WkC?x=%8(<^6FEup1vP2UlN*E#U?&Cs3k2%yMEe zK;7wX6Y%_O8-3a^-@0-F`72G5eksLrD#i&zq)H){5^Xx|k-gdZasqK{DcmNd-hS z_x2}O>9(4y)r?RZSrthr0T??=Otkm%cDNtoZTCD>^VDk)ba(UBJ_xJ+m5?{BDqcTn zJbc@c-Sf%lWwq)|SoAB!IVdo+8q-P@dNW(DR;Pax2(QwgnY?=+caJ*tr_E;btNUvK z1LiRGSsR*36Ah$8rpxs}`Y(y?O58&laQj`=-zSuEkbh%QhN}_hSd@3{hgf;CTVvK0 z5sl&awh<3pPO5w;$u9PqYaX}-)&2eO#*oKLIZDo@<7y+Bo@E<5s}{!U1KqXj_Vg5h zX9*Z_ATd7~sqk4qP&f_@xp=#g`42M%Kf!jJ^>dyet6ko#5|G*Cv_9XtWoeS*GI+f1%g1vig6UeTu za|h%3uV?Lf+)J;C0APz)!uEFL5YT1M$yrc7YcTJUd_%(^i5gXTGwf~}*%EKmEHD@O zFCX^PjsPO=S-yjG@6X$3yVmRn>6Cb4!Q{NgcJ;kK&=n2reFVR2SYxft#uU7E zxE5sjaMq}vrYk&*joVSADv1Pj6e-QzbF%!j<)eo+62W=iV(c;@OaYn~9c=etV?W(~ zHD&ee1Ujp-vcSWWj?rxZabK;D2Iipl)!Y}8LP4w$cX|Y0=x54MO=0?_HHZ1;NF$(k zYbt>APEZoSyc%0Yrj2Oh-+>yyIk8}g0Wu3Iu2e+;YtvX_yB>17`}+9zEwO<=r+BlZ z_)+MJN(uCGUBVwC$?O%ofC*?8N!t%aZo|Ph^dHmYHNF_J!2W{T%rknakks>dPkAKBPr+c4L22AM7k{zQumW4nS%%P{Ozfvf~mvI!M zU&tmVk(nJVGkW6Lw}2|)=9Wlb28{fM%OXysKYh=4CMKzL1%3YJk~L;f=N!sjoWoE8 z%`jI+Oy?q8uWG~EBa|f9k<4K}2f<#-YMfARbl~%(u~JQ_%PW|Ni4?c^>;?Q1(B~xt z!d5v-R*|k`qbg?IcH3O$w~wO4U(e4QF)>shXz>jt)$EOkouHkX9t(jqOA+sKXyum2 zSs9UQG=l8n1xSy*3x&o|7Vf&IWH!ZIX5a+JIL40Mu9*!HqIjB38yPo{6LmIR$NrWW zdAg#~@LsI)^oKd9+qO-yeV03ez{7txX#K(dCh&a%@Hqso`ysRLW;jzk4cJG78f1c^ zObEVNT2z3W=#~AAzegr3JoExx08E9!sFct@gjIGw^*h33A!kn+K@OiKErgjAy|#R1 z8}`!Zn&lS2K76jkJL)-x*>A^n@b2G3f8@(vOF1Hz4#8xRN=d6*4-QWV1q6cd24FRG zq(OVR&6qOi76z5{NA;`Rt{rb(#=u+EeKm?45eil+rmM|&UC zFh>lllsqKR;c)*HBmmfffJ8dhq&&5Yq0sODEWSVEyO3apN@UcLv{?H3yjQZ6H$tgm ztK9i50~<&?Vg8@*AJY`084RcwKAKEB5Z8W9Mw$~Xj_#oByw9=-fgesj@Xe<-1buJ8 z-9gb7vMQPn9<2u9?m<5hq%0rIhuVR+aZ*D^_fbh?)o^(6PTghDuL#Eq#;AYoZ$a9Q z1&qmYs2MXNN*uDJr*iL>Wp%z#3z(18wSlNJmQ~{EzSZrVk*CPwH199~~WW zMb~+k1D%=caOTwUn)Js;*!X6pebi=q{v|*RqwG95V>QTPr!QoD@#b zhV0ug$|^1YBfjk^6cfk<%bU>@Z0LV~rcrLTidS!#)BqvK4A4K2fUtgE{SZNv&b=Im zArjCt-<8vs?{U9qu}~X?H7iM$4^mD8n(fe6GMHmOrkS&UQPrq@u**!~b-T1deX}fc z@Plokp;I~_)o1Wg?v{_Q^yX~!w<~Y?r()HrrmBF^vpJN{9_ax*%x65Ca6!;-n_n(j zfhX^LFM`HHgYTVL9~YN^*3*O>br^?}IbPFznb~U1OVV0O?iLGHX>pvx=%_C7lQLR`=wF1n3~YzneD~p zyrA>dah3U^Mhmgz!!icO@}yJn9Mpx}N{4P*>%N{Fp3d$k}Hi+H%M*qaRatTn;6<4|-RP`usCy<%Lm$V%>J6=X<*5du;|4 zn+K}Bso@V$ysKiBBF8W6?`|DXu~ZTY13V-}60)^FGLE zQtYw>QTOgeivxMxbRG@P1MxLkUb>UHU*J*(T`CnWanJ%o302%4QHk1o(g4WMtx$cq z5>7#b%11;_AL~>KDo$aw)Yn_;8i87XHoz|1z;3T>e?!EQu zFenC}?F=Nl1>OIArFdt7FeGSKN|SumAQjG>0vA|3rCG*N9u&1OD=V0|=PVqfcE@l1 z*gOpNM(4QP8mbf@>R20Fs7Z@-Ji0^0g+Ar##s3TlF$?Q4tFlIlAw2u=&Fh|=-J87@ zt1x3PlA=uVAGln~n&^<0fRk=eQ=>n_srm2Nau1OdPctqj@J*A)pawdXis0PD`VpFN z2SA}J6`UVpt|SLp&x4Z7LnylCOn%oy$qJc$_vB6>1x*ho0#kHAm(C<7*hiQPoYUQ)j+eEiNYFeZ1+5yoF8>y2JpVXi_?}2tGF_ zJB^}|zCX20=ah17es@2v75LtQOp04P#j8YMMD0+ohj^BfiQn$HhA-|wy3yGzc@hkc zWC+{b1^0}vG?>U#LK=ZiP~Y|DjtoyHpT8vJ=L2)1@Pa(fen*F+sdQ`W!g}ah2?_6b zK7LALTJ<_bptUZ`sLK_7uQeW*?ZEq%Z zrxu?O-BM+t&ZBO7F%WPbAux2>AK>QoB*Pi9KIRiml(H-gR*~F_v$fwEo}5tjnbGmS ztTo$&M!I7CUFqaZ{4eR#E$O2-9;l!^Fp~Q3lNz3y(CdQ_Zx~|J+4ZT1bJQ;O0Kukf z9VzN1zV-=yO$OvyC4Ev38$T`7Qpoh{hnx_M(`j>(`T^hjqBa;3ie0T_3|Ryt&t%#o zrz0$Q;_jz&sQn_tiZIF??ibCKaD;i9WOE9HTAI8nqOzYxQ;NNT3wv(*p0LyN*`;?Y zF2^Nly@4})E$plFM2hO?_M4FL_a(}l?rgW5DiP&B`tO#@XcgQt;EBF%i&b!!_7GWr zp;TgXAXAMVY}sS)|I9hkyJxg2II(%o~GeQ6yBD2YmudWwvX#)r2qFFXNu~>?%aIO&@4*vN(bu zoHstc841n1^MnT)WGT&aeSZ?RO}E{8IvC96_0c4mPG)_S#>_oXOI;|pa33Uz^;&G0 zlk}#pdO0Sp@@(zJuH;Lx^eehjM|9-mf=RgtizIu|!!i*IbF5w$0&JWvig_R2_pOhx zTAzr^xu+eNJsk8PBoHIRnK8uCgHR>jNE`^NC#gU|_B*R((YYd`6B=0#zKfrtkcx|v zgEc3ekV9@&1*i3A&_3H;itVhWB26^86dXG*D(Jit=rc+CzX=qh1*%YqnG*M0X=b$# zBGBj7(PH#{i|?%FM1dAYPkvQgnImMIjQ8Ct4tt5qY@h(eZ@0D7^CKlQJ@{HOnNqjh zMTB`-;!oFMZ^RmIHw=%U<$m4&nkDKAT6xwh%o!+pj+?M?-R`d32l+j0Dra}kvaRSE zIY(N8`KZYFXFS4l6Kf{v4~GZoX#*ifh@N8gu?zl!Ef1sq&?H8N4JfWWi3m!d=niA; zrkc`GseSiKI7M85Ki&Ol1j;9?w&)*Zdd}fX{yLjDW$B-Y<%C>g;GhCWJAOLgv0pC6 zl$4u)EHuXrY)ouT+TL!w3NWLWa=8P7B+vR574Q`}S4wEoCKylMK&Quxxb`-76_((~ z?y!VdH3z-F1{w{jHnlR zVH^TTgghesBa*^Ed`$BlsY-eFZ6^rGkyag-UkK|Wj$sD-H{R`D7-RKBL({J=K=bl) zRW(;l}NT~5U z>Q1AxaPE{MX)o3&zGx*8bI9XLCvI5XW9c=d%ebdiG8mf;MQ$U~5?bed9UP5?;p7#<;@Xz<%eb#H zy)1yc0x#bi7EkO6xlvdG*j;$5+PAOW{M_(YTloQmU9FJrFesB&5=s2x&h#b>! z`FSUD>U<0)VQ#4AK+v}-@c~J;BGz#So)!SnJ?PwMDZsst_ z;1Cu)B`U+?KRo5IfZwK-Z}nfNC?ck%xX7vUgEYvwF|S3~&8tD_`5z)eb05?-jxDpD zd!nFaGbZjzgre=sN{Yrt@4f083hWy0EA05%W2)~Lj&%cKNz2J=E1MMC7Nggp&&FF~ zn`#y)=Bv4=g6*a)zThnYAd#ty29NmfTvpF%VXz*;Ytp-Aq6g*KT>N}FwJvQO6idqA zyv*)I?UEv^ZV@1sKm;@NsgHH+A;&cY}C?jMO!S Y#Dt}|FIdya0sjZ-Xc(y1s6Bf2U+!?HxBvhE literal 0 HcmV?d00001 diff --git a/doc/images/e1-archi.tex b/doc/images/e1-archi.tex new file mode 100644 index 0000000000..7a18d63c53 --- /dev/null +++ b/doc/images/e1-archi.tex @@ -0,0 +1,73 @@ +\documentclass{standalone} +%\usepackage[tt=false]{libertine} +\renewcommand{\familydefault}{\sfdefault} +% improve for some encodings +\usepackage{textcomp} +\usepackage{tikz} +\usetikzlibrary{positioning} +\usetikzlibrary{shapes.symbols} +\usetikzlibrary{decorations.markings} +\usetikzlibrary{fit} + +\tikzset{splitpos/.store in=\splitpos,splitpos=0.5} +\newcommand{\ip}[1]{\texttt{#1}} + +\begin{document} +\begin{tikzpicture} + [ + font=\scriptsize, + node distance=1.5cm and 3.2cm, + entity/.style={ + rectangle, + draw, + inner sep=0pt, + minimum height=6mm,minimum width=11mm, + align=center + }, + split/.style={postaction={% + decorate, + decoration={ + markings,mark={ + at position \splitpos + with { + \draw (0pt,2.5pt) -- (0pt,-2.5pt); + } + } + } + } + }, + ip/.style={font=\tiny,outer sep=1pt,inner sep=1pt}, + ] + \node[entity] (cu-cp) {CU-CP}; + \node[entity,below=of cu-cp] (cu-up) {CU-UP}; + \node[entity,below left=0.45cm and 3.2cm of cu-cp] (du) {DU}; + \node[entity,right=of cu-cp] (amf) {AMF}; + \node[entity,right=of cu-up] (upf) {UPF}; + + \draw[split,splitpos=0.5] (cu-cp) -- + node[ip,at start, below right, align=left] {\ip{GNB\_IPV4\_ADDRESS\_FOR\_NG\_AMF:38412}} + node[above] {NG-C/N2} + %node[ip,at end, below left] {127.0.1.10/24} + (amf); + \draw[split,splitpos=0.5] (cu-up) -- + node[ip, at start, below right,align=left] {\ip{GNB\_IPV4\_ADDRESS\_FOR\_NGU:2152}} + node[above] {NG-U/N3} + %node[ip, at end, below left] {127.0.1.10/24} + (upf); + \draw[split,splitpos=0.5] (cu-cp) -- + node[ip, at start, below right] {\ip{ipv4\_cucp:38462}} + node[right] {E1AP} + node[ip, at end, above right] {\ip{ipv4\_cuup:38462}} + (cu-up); + \draw[split] (du.north east) -- + node[ip, at start, below right] {to \ip{remote\_n\_address:38472}} + node[above] {F1-C} + node[ip, at end, above left, align=right] {\ip{local\_s\_address:38472}} + (cu-cp); + \draw[split] (du.south east) -- + node[ip, at start, above right] {to \ip{remote\_n\_address:remote\_n\_portd}} + node[above] {F1-U} + node[ip, at end, below left, align=right] {\ip{local\_s\_address:local\_s\_portd}} + (cu-up); +\end{tikzpicture} +\end{document} diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c new file mode 100644 index 0000000000..e2b2bdb50b --- /dev/null +++ b/executables/nr-cuup.c @@ -0,0 +1,160 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "common/utils/simple_executable.h" +#include "executables/softmodem-common.h" +#include "common/utils/ocp_itti/intertask_interface.h" +#include "openair3/ocp-gtpu/gtp_itf.h" +#include "openair2/E1AP/e1ap.h" +#include "common/ran_context.h" +#include "nfapi/oai_integration/vendor_ext.h" +#include "openair2/F1AP/f1ap_common.h" +#include "openair2/GNB_APP/gnb_config.h" + +RAN_CONTEXT_t RC; +THREAD_STRUCT thread_struct; +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int asn1_xer_print; +int oai_exit = 0; +instance_t CUuniqInstance = 0; +RRC_release_list_t rrc_release_info; + +void exit_function(const char *file, const char *function, const int line, const char *s) +{ +} + +nfapi_mode_t nfapi_mod = -1; +void nfapi_setmode(nfapi_mode_t nfapi_mode) +{ + nfapi_mod = nfapi_mode; +} +nfapi_mode_t nfapi_getmode(void) +{ + return nfapi_mod; +} + +ngran_node_t get_node_type() +{ + return ngran_gNB_CUUP; +} + +rlc_op_status_t rlc_data_req(const protocol_ctxt_t *const pc, + const srb_flag_t sf, + const MBMS_flag_t mf, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t c, + const sdu_size_t size, + mem_block_t *const buf, + const uint32_t *const a, + const uint32_t *const b) +{ + abort(); + return 0; +} + +int nr_rlc_get_available_tx_space(const rnti_t rntiP, const logical_chan_id_t channel_idP) +{ + abort(); + return 0; +} + +void nr_rlc_bearer_init(NR_RLC_BearerConfig_t *RLC_BearerConfig, NR_RLC_BearerConfig__servedRadioBearer_PR rb_type) +{ + abort(); +} + +void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, NR_CellGroupConfig_t *cell_groupConfig_from_DU) +{ + abort(); +} + +void nr_rlc_bearer_init_ul_spec(struct NR_LogicalChannelConfig *mac_LogicalChannelConfig) +{ + abort(); +} + +rlc_op_status_t nr_rrc_rlc_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, + const NR_SRB_ToAddModList_t *const srb2add_listP, + const NR_DRB_ToAddModList_t *const drb2add_listP, + const NR_DRB_ToReleaseList_t *const drb2release_listP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) +{ + abort(); + return 0; +} + +int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_pP, const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP) +{ + abort(); + return 0; +} + +void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr) +{ + abort(); +} + +void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp) +{ + abort(); +} + +f1ap_cudu_inst_t *getCxt(F1_t isCU, instance_t instanceP) +{ + abort(); + return NULL; +} + +void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP) +{ + abort(); +} + +int main(int argc, char **argv) +{ + /// static configuration for NR at the moment + if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + logInit(); + set_softmodem_sighandler(); + itti_init(TASK_MAX, tasks_info); + int rc; + rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); + AssertFatal(rc >= 0, "Create task for SCTP failed\n"); + rc = itti_create_task(TASK_GTPV1_U, gtpv1uTask, NULL); + AssertFatal(rc >= 0, "Create task for GTPV1U failed\n"); + rc = itti_create_task(TASK_CUUP_E1, E1AP_CUUP_task, NULL); + AssertFatal(rc >= 0, "Create task for CUUP E1 failed\n"); + pdcp_layer_init(); + MessageDef *msg = RCconfig_NR_CU_E1(true); + AssertFatal(msg != NULL, "Send init to task for E1AP UP failed\n"); + itti_send_msg_to_task(TASK_CUUP_E1, 0, msg); + + printf("TYPE TO TERMINATE\n"); + itti_wait_tasks_end(); + + logClean(); + printf("Bye.\n"); + return 0; +} diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 2cbea144cf..68eb294a34 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -78,6 +78,9 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "gnb_paramdef.h" #include #include "nfapi/oai_integration/vendor_ext.h" +#include "gnb_config.h" +#include "openair2/E1AP/e1ap_common.h" +#include "openair2/E1AP/e1ap_api.h" pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; @@ -289,16 +292,60 @@ void exit_function(const char *file, const char *function, const int line, const -int create_gNB_tasks(uint32_t gnb_nb) { +static int create_gNB_tasks(void) { + uint32_t gnb_nb = RC.nb_nr_inst; + uint32_t gnb_id_start = 0; + uint32_t gnb_id_end = gnb_id_start + gnb_nb; LOG_D(GNB_APP, "%s(gnb_nb:%d)\n", __FUNCTION__, gnb_nb); itti_wait_ready(1); + LOG_I(PHY, "%s() Task ready initialize structures\n", __FUNCTION__); + + RCconfig_NR_L1(); + RCconfig_nr_prs(); + + if (RC.nb_nr_macrlc_inst>0) RCconfig_nr_macrlc(); + + LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst); + + if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n"); + + AssertFatal (gnb_nb <= RC.nb_nr_inst, + "Number of gNB is greater than gNB defined in configuration file (%d/%d)!", + gnb_nb, RC.nb_nr_inst); + + LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst); + + RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *)); + LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc); + ngran_node_t node_type = get_node_type(); + for (int gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) { + RC.nrrrc[gnb_id] = (gNB_RRC_INST*)calloc(1,sizeof(gNB_RRC_INST)); + LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, gnb_id_end); + configure_nr_rrc(gnb_id); + } + + if (RC.nb_nr_inst > 0 && + !get_softmodem_params()->nsa && + !(node_type == ngran_gNB_DU)) { + // we start pdcp in both cuup (for drb) and cucp (for srb) + init_pdcp(); + } + + if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(node_type) + LOG_I(X2AP, "X2AP enabled \n"); + __attribute__((unused)) uint32_t x2_register_gnb_pending = gNB_app_register_x2 (gnb_id_start, gnb_id_end); + } + + /* For the CU case the gNB registration with the AMF might have to take place after the F1 setup, as the PLMN info + * can originate from the DU. Add check on whether x2ap is enabled to account for ENDC NSA scenario.*/ + if ((get_softmodem_params()->sa || is_x2ap_enabled()) && + !NODE_IS_DU(node_type)) { + /* Try to register each gNB */ + //registered_gnb = 0; + __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); + } if (gnb_nb > 0) { - /* Last task to create, others task must be ready before its start */ - /*if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { - LOG_E(GNB_APP, "Create task for gNB APP failed\n"); - return -1; - }*/ if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) { LOG_E(SCTP, "Create task for SCTP failed\n"); return -1; @@ -313,7 +360,8 @@ int create_gNB_tasks(uint32_t gnb_nb) { } } - if (get_softmodem_params()->sa) { + if (get_softmodem_params()->sa && + !NODE_IS_DU(node_type)) { char* gnb_ipv4_address_for_NGU = NULL; uint32_t gnb_port_for_NGU = 0; @@ -326,9 +374,10 @@ int create_gNB_tasks(uint32_t gnb_nb) { for(int i = GNB_INTERFACE_NAME_FOR_NG_AMF_IDX; i <= GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX; i++) { if( NETParams[i].strptr == NULL) { - LOG_E(NGAP, "No AMF configuration in the file.\n"); + LOG_E(NGAP, "No AMF configuration in the file.\n"); + exit(1); } else { - LOG_D(NGAP, "Configuration in the file: %s.\n",*NETParams[i].strptr); + LOG_D(NGAP, "Configuration in the file: %s.\n",*NETParams[i].strptr); } } @@ -346,15 +395,26 @@ int create_gNB_tasks(uint32_t gnb_nb) { return -1; } - LOG_I(NR_RRC,"Creating NR RRC gNB Task\n"); - + LOG_I(NR_RRC, "Creating NR RRC gNB Task, that will also create TASKS\n"); if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) { LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n"); return -1; } - //Use check on x2ap to consider the NSA scenario and check for SA scenario - if(is_x2ap_enabled() || get_softmodem_params()->sa) { + // If CU + if (node_type == ngran_gNB_CU || node_type == ngran_gNB) { + MessageDef *msg = RCconfig_NR_CU_E1(false); + instance_t inst = 0; + createE1inst(UPtype, inst, &E1AP_SETUP_REQ(msg)); + cuup_init_n3(inst); + itti_free(TASK_UNKNOWN, msg); + getCxtE1(inst)->same_process = true; + ; + RC.nrrrc[gnb_id_start]->e1_inst = inst; // stupid instance !!!*/ + } + + //Use check on x2ap to consider the NSA scenario + if((is_x2ap_enabled() || get_softmodem_params()->sa) && (node_type != ngran_gNB_CUCP)) { if (itti_create_task (TASK_GTPV1_U, >pv1uTask, NULL) < 0) { LOG_E(GTPU, "Create task for GTPV1U failed\n"); return -1; @@ -504,7 +564,7 @@ void init_pdcp(void) { LINK_ENB_PDCP_TO_GTPV1U_BIT; if (!get_softmodem_params()->nsa) { - if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) { + if (!NODE_IS_DU(get_node_type())) { pdcp_layer_init(); nr_pdcp_module_init(pdcp_initmask, 0); } @@ -582,7 +642,7 @@ int main( int argc, char **argv ) { // don't create if node doesn't connect to RRC/S1/GTP if (NFAPI_MODE != NFAPI_MODE_PNF) { - int ret = create_gNB_tasks(1); + int ret = create_gNB_tasks(); AssertFatal(ret == 0, "cannot create ITTI tasks\n"); } diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 4aef4e56a3..1630ef8ef0 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -102,6 +102,8 @@ int config_sync_var=-1; instance_t CUuniqInstance=0; instance_t DUuniqInstance=0; +int get_node_type() {return -1;} + RAN_CONTEXT_t RC; int oai_exit = 0; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index da5bbbffdf..9b6db46aa8 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -81,8 +81,6 @@ const char *__asan_default_options() return "detect_leaks=0"; } -LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; - PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; @@ -100,22 +98,6 @@ nfapi_ue_release_request_body_t release_rntis; //Fixme: Uniq dirty DU instance, by global var, datamodel need better management instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; -teid_t newGtpuCreateTunnel(instance_t instance, - ue_id_t ue_id, - int incoming_bearer_id, - int outgoing_bearer_id, - teid_t outgoing_teid, - int qfi, - transport_layer_addr_t remoteAddr, - int port, - gtpCallback callBack, - gtpCallbackSDAP callBackSDAP) { - return 0; -} - -int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { - return 0; -} // dummy functions int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); } @@ -158,59 +140,6 @@ rrc_data_ind( { } -int -gtpv1u_create_s1u_tunnel( - const instance_t instanceP, - const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, - gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP -) { - return 0; -} - -int -rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -) { - return 0; -} - -int -gtpv1u_create_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, - gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ - return 0; -} - -int -gtpv1u_update_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, - const ue_id_t prior_ue_id -){ - return 0; -} - -int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { - return 0; -} - -int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req) { - return 0; -} - -int -nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -){ - return 0; -} - int nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out) { diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index f0ac036926..9489b1aeb3 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -58,7 +58,9 @@ #define NR_PRACH_DEBUG 1 #define PRACH_WRITE_OUTPUT_DEBUG 1 -LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; +THREAD_STRUCT thread_struct; +char *parallel_config = NULL; +char *worker_config = NULL; char *uecap_file; PHY_VARS_gNB *gNB; @@ -91,22 +93,6 @@ int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); //Fixme: Uniq dirty DU instance, by global var, datamodel need better management instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; -teid_t newGtpuCreateTunnel(instance_t instance, - ue_id_t ue_id, - int incoming_bearer_id, - int outgoing_bearer_id, - teid_t outgoing_teid, - int qfi, - transport_layer_addr_t remoteAddr, - int port, - gtpCallback callBack, - gtpCallbackSDAP callBackSDAP) { - return 0; -} - -int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { - return 0; -} void rrc_data_ind( @@ -118,59 +104,6 @@ rrc_data_ind( { } -int -gtpv1u_create_s1u_tunnel( - const instance_t instanceP, - const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, - gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP -) { - return 0; -} - -int -rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -) { - return 0; -} - -int -gtpv1u_create_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, - gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ - return 0; -} - -int -gtpv1u_update_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, - const ue_id_t prior_ue_id -){ - return 0; -} - -int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { - return 0; -} - -int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req) { - return 0; -} - -int -nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -){ - return 0; -} - int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 11c131a5c2..b407b90113 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -76,8 +76,6 @@ const char *__asan_default_options() return "detect_leaks=0"; } -LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; - PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; @@ -96,22 +94,6 @@ nfapi_ue_release_request_body_t release_rntis; //Fixme: Uniq dirty DU instance, by global var, datamodel need better management instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; -teid_t newGtpuCreateTunnel(instance_t instance, - ue_id_t ue_id, - int incoming_bearer_id, - int outgoing_bearer_id, - teid_t outgoing_teid, - int qfi, - transport_layer_addr_t remoteAddr, - int port, - gtpCallback callBack, - gtpCallbackSDAP callBackSDAP) { - return 0; -} - -int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { - return 0; -} extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration @@ -149,59 +131,6 @@ rrc_data_ind( } -int -gtpv1u_create_s1u_tunnel( - const instance_t instanceP, - const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, - gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP -) { - return 0; -} - -int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { - return 0; -} - -int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req) { - return 0; -} - -int -rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -) { - return 0; -} - -int -gtpv1u_create_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, - gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ - return 0; -} - -int -gtpv1u_update_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, - const ue_id_t prior_ue_id -){ - return 0; -} - -int -nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -){ - return 0; -} - // Dummy function to avoid linking error at compilation of nr-ulsim int is_x2ap_enabled(void) { diff --git a/openair2/COMMON/e1ap_messages_def.h b/openair2/COMMON/e1ap_messages_def.h new file mode 100644 index 0000000000..70533f8add --- /dev/null +++ b/openair2/COMMON/e1ap_messages_def.h @@ -0,0 +1,33 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* gNB_CUUP application layer -> E1AP messages */ +MESSAGE_DEF(E1AP_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_setup_req_t , e1ap_setup_req) + +/* E1AP -> eNB_DU or eNB_CU_RRC -> E1AP application layer messages */ +MESSAGE_DEF(E1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, e1ap_setup_resp_t , e1ap_setup_resp) + +MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_req_t , e1ap_bearer_setup_req) + +MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_RESP , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_resp_t , e1ap_bearer_setup_resp) + +MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_req_t , e1ap_bearer_mod_req) + diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h new file mode 100644 index 0000000000..941d95b044 --- /dev/null +++ b/openair2/COMMON/e1ap_messages_types.h @@ -0,0 +1,226 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef E1AP_MESSAGES_TYPES_H +#define E1AP_MESSAGES_TYPES_H + +#include "f1ap_messages_types.h" +#include "ngap_messages_types.h" + +#define E1AP_MAX_NUM_TRANSAC_IDS 4 +#define E1AP_MAX_NUM_PLMNS 4 +#define E1AP_MAX_NUM_CELL_GROUPS 4 +#define E1AP_MAX_NUM_QOS_FLOWS 4 +#define E1AP_MAX_NUM_NGRAN_DRB 4 +#define E1AP_MAX_NUM_PDU_SESSIONS 4 +#define E1AP_MAX_NUM_DRBS 4 +#define E1AP_MAX_NUM_DRBS 4 +#define E1AP_MAX_NUM_UP_PARAM 4 + +#define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req +#define E1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_resp +#define E1AP_BEARER_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req +#define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp +#define E1AP_BEARER_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req + +typedef f1ap_net_ip_address_t e1ap_net_ip_address_t; + +typedef struct PLMN_ID_s { + int mcc; + int mnc; + int mnc_digit_length; +} PLMN_ID_t; + +typedef struct e1ap_setup_req_s { + uint64_t gNB_cu_up_id; + char * gNB_cu_up_name; + int assoc_id; + uint64_t transac_id; + int supported_plmns; + PLMN_ID_t plmns[E1AP_MAX_NUM_PLMNS]; + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; + uint16_t default_sctp_stream_id; + net_ip_address_t CUUP_e1_ip_address; + net_ip_address_t CUCP_e1_ip_address; + long cn_support; + uint16_t remotePortF1U; + char* localAddressF1U; + uint16_t localPortF1U; + char* localAddressN3; + uint16_t localPortN3; + uint16_t remotePortN3; +} e1ap_setup_req_t; + +typedef struct e1ap_setup_resp_s { + long transac_id; +} e1ap_setup_resp_t; + +typedef struct cell_group_s { + long id; +} cell_group_t; + +typedef struct up_params_s { + in_addr_t tlAddress; + long teId; + int cell_group_id; +} up_params_t; + +typedef struct drb_to_setup_s { + long drbId; + long pDCP_SN_Size_UL; + long pDCP_SN_Size_DL; + long rLC_Mode; + long qci; + long qosPriorityLevel; + long pre_emptionCapability; + long pre_emptionVulnerability; + in_addr_t tlAddress; + long teId; + int numCellGroups; + cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; +} drb_to_setup_t; + +typedef struct qos_flow_to_setup_s { + long id; + fiveQI_type_t fiveQI_type; + long fiveQI; + long qoSPriorityLevel; + long packetDelayBudget; + long packetError_scalar; + long packetError_exponent; + long priorityLevel; + long pre_emptionCapability; + long pre_emptionVulnerability; +} qos_flow_to_setup_t; + +typedef struct DRB_nGRAN_to_setup_s { + long id; + long defaultDRB; + long sDAP_Header_UL; + long sDAP_Header_DL; + long pDCP_SN_Size_UL; + long pDCP_SN_Size_DL; + long discardTimer; + long reorderingTimer; + long rLC_Mode; + in_addr_t tlAddress; + int teId; + int numDlUpParam; + up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM]; + int numCellGroups; + cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; + int numQosFlow2Setup; + qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; +} DRB_nGRAN_to_setup_t; + +typedef struct pdu_session_to_setup_s { + long sessionId; + long sessionType; + int8_t sst; + long integrityProtectionIndication; + long confidentialityProtectionIndication; + in_addr_t tlAddress; + in_addr_t tlAddress_dl; + int32_t teId; + int32_t teId_dl; + int tl_port; + int tl_port_dl; + long numDRB2Setup; + DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; + long numDRB2Modify; + DRB_nGRAN_to_setup_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; +} pdu_session_to_setup_t; + +typedef struct e1ap_bearer_setup_req_s { + uint32_t gNB_cu_cp_ue_id; + uint32_t gNB_cu_up_ue_id; + rnti_t rnti; + uint64_t cipheringAlgorithm; + uint64_t integrityProtectionAlgorithm; + char encryptionKey[128]; + char integrityProtectionKey[128]; + long ueDlAggMaxBitRate; + PLMN_ID_t servingPLMNid; + long activityNotificationLevel; + int numDRBs; + drb_to_setup_t DRBList[E1AP_MAX_NUM_DRBS]; + int numPDUSessions; + pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; + int numPDUSessionsMod; + pdu_session_to_setup_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; +} e1ap_bearer_setup_req_t; + +typedef struct e1ap_bearer_release_cmd_s { + uint32_t gNB_cu_cp_ue_id; + uint32_t gNB_cu_up_ue_id; + long cause_type; + long cause; +} e1ap_bearer_release_cmd_t; + +typedef struct drb_setup_s { + int drbId; + in_addr_t tlAddress; + int teId; + int numUpParam; + up_params_t UpParamList[E1AP_MAX_NUM_UP_PARAM]; +} drb_setup_t; + +typedef struct qos_flow_setup_s { + long id; +} qos_flow_setup_t; + +typedef struct DRB_nGRAN_setup_s { + long id; + int numUpParam; + up_params_t UpParamList[E1AP_MAX_NUM_UP_PARAM]; + int numQosFlowSetup; + qos_flow_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; +} DRB_nGRAN_setup_t; + +typedef struct DRB_nGRAN_failed_s { + long id; + long cause_type; + long cause; +} DRB_nGRAN_failed_t; + +typedef struct pdu_session_setup_s { + long id; + in_addr_t tlAddress; + long teId; + int numDRBSetup; + DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; + int numDRBFailed; + DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_NGRAN_DRB]; +} pdu_session_setup_t; + +typedef struct e1ap_bearer_setup_resp_s { + uint64_t gNB_cu_cp_ue_id; + uint64_t gNB_cu_up_ue_id; + int numDRBs; + drb_setup_t DRBList[E1AP_MAX_NUM_DRBS]; + int numPDUSessions; + pdu_session_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; +} e1ap_bearer_setup_resp_t; + +#endif /* E1AP_MESSAGES_TYPES_H */ diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 7c784a0c35..77e92f39bb 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -185,7 +185,7 @@ typedef struct gtpv1u_gnb_create_tunnel_resp_s { ue_id_t ue_id; int num_tunnels; teid_t gnb_NGu_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier - pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; transport_layer_addr_t gnb_addr; } gtpv1u_gnb_create_tunnel_resp_t; typedef struct gtpv1u_gnb_delete_tunnel_req_s { diff --git a/openair2/COMMON/messages_def.h b/openair2/COMMON/messages_def.h index 394b40eeed..8334700dd0 100644 --- a/openair2/COMMON/messages_def.h +++ b/openair2/COMMON/messages_def.h @@ -41,3 +41,4 @@ #include "sctp_messages_def.h" #include "udp_messages_def.h" #include "gtpv1_u_messages_def.h" +#include "e1ap_messages_def.h" diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 961599a9ed..70412e8368 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -274,9 +274,15 @@ typedef struct ngap_transport_layer_addr_s { dEST.length = sOURCE.length; \ } while (0) +typedef enum { + non_dynamic, + dynamic +} fiveQI_type_t; + typedef struct pdusession_level_qos_parameter_s { uint8_t qfi; uint64_t fiveQI; + fiveQI_type_t fiveQI_type; ngap_allocation_retention_priority_t allocation_retention_priority; } pdusession_level_qos_parameter_t; @@ -706,12 +712,21 @@ typedef struct ngap_pdusession_setup_req_s { /* gNB ue ngap id as initialized by NGAP layer */ uint32_t gNB_ue_ngap_id; + /* S-NSSAI */ + ngap_allowed_NSSAI_t allowed_nssai[8]; + /* Number of pdusession to be setup in the list */ uint8_t nb_pdusessions_tosetup; /* E RAB setup request */ pdusession_t pdusession_setup_params[NGAP_MAX_PDUSESSION]; + /* UE Uplink Aggregated Max Bitrates */ + uint64_t ueAggMaxBitRateUplink; + + /* UE Downlink Aggregated Max Bitrates */ + uint64_t ueAggMaxBitRateDownlink; + } ngap_pdusession_setup_req_t; typedef struct ngap_pdusession_setup_resp_s { diff --git a/openair2/E1AP/CMakeLists.txt b/openair2/E1AP/CMakeLists.txt index 89d87fe555..a8bacdd3fa 100644 --- a/openair2/E1AP/CMakeLists.txt +++ b/openair2/E1AP/CMakeLists.txt @@ -1,7 +1,7 @@ add_subdirectory(MESSAGES) -add_library(E1AP e1ap.c) -target_link_libraries(E1AP - PUBLIC asn1_e1ap - PRIVATE UTIL asn1_nr_rrc asn1_lte_rrc) -target_include_directories(E1AP PUBLIC ${CMAKE_CURRENT_DIR}) +add_library(e1ap e1ap.c e1ap_common.c e1ap_api.c) +target_link_libraries(e1ap + PUBLIC asn1_e1ap f1ap + PRIVATE asn1_nr_rrc asn1_lte_rrc asn1_f1ap UTIL e1_pdcp_if e1_if) +target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR}) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index b49f4d4ca1..52043602e2 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -22,48 +22,87 @@ */ #include "e1ap.h" +#include "e1ap_common.h" +#include "e1ap_api.h" +#include "gnb_config.h" +#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" +#include "openair3/UTILS/conversions.h" +#include "openair2/RRC/NR/MESSAGES/asn1_msg.h" +#include "common/openairinterface5g_limits.h" +#include "common/utils/LOG/log.h" +#include "openair2/F1AP/f1ap_common.h" +#include "e1ap_default_values.h" -int asn1_encoder_xer_print = 1; +#define E1AP_NUM_MSG_HANDLERS 14 +typedef int (*e1ap_message_processing_t)(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p); +e1ap_message_processing_t e1ap_message_processing[E1AP_NUM_MSG_HANDLERS][3] = { -int e1ap_assoc_id(bool isCu, instance_t instance) { - return 0; + { 0, 0, 0 }, /* Reset */ + { 0, 0, 0 }, /* ErrorIndication */ + { 0, 0, 0 }, /* privateMessage */ + { e1apCUCP_handle_SETUP_REQUEST, e1apCUUP_handle_SETUP_RESPONSE, e1apCUUP_handle_SETUP_FAILURE }, /* gNBCUUPE1Setup */ + { 0, 0, 0 }, /* gNBCUCPE1Setup */ + { 0, 0, 0 }, /* gNBCUUPConfigurationUpdate */ + { 0, 0, 0 }, /* gNBCUCPConfigurationUpdate */ + { 0, 0, 0 }, /* E1Release */ + { e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST, e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE, e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE }, /* bearerContextSetup */ + { e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST, 0, 0 }, /* bearerContextModification */ + { 0, 0, 0 }, /* bearerContextModificationRequired */ + { e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND, e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE, 0 }, /* bearerContextRelease */ + { 0, 0, 0 }, /* bearerContextReleaseRequired */ + { 0, 0, 0 } /* bearerContextInactivityNotification */ +}; + +const char *e1ap_direction2String(int e1ap_dir) { + static const char *e1ap_direction_String[] = { + "", /* Nothing */ + "Initiating message", /* initiating message */ + "Successfull outcome", /* successfull outcome */ + "UnSuccessfull outcome", /* successfull outcome */ + }; + return(e1ap_direction_String[e1ap_dir]); } -int e1ap_encode_send(bool isCu, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func) { - DevAssert(pdu != NULL); +int e1ap_handle_message(instance_t instance, uint32_t assoc_id, + const uint8_t *const data, const uint32_t data_length) { + E1AP_E1AP_PDU_t pdu= {0}; + int ret; + DevAssert(data != NULL); - if (asn1_encoder_xer_print) { - LOG_E(E1AP, "----------------- ASN1 ENCODER PRINT START ----------------- \n"); - xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, pdu); - LOG_E(E1AP, "----------------- ASN1 ENCODER PRINT END----------------- \n"); + if (e1ap_decode_pdu(&pdu, data, data_length) < 0) { + LOG_E(E1AP, "Failed to decode PDU\n"); + return -1; } - - char errbuf[2048]; /* Buffer for error message */ - size_t errlen = sizeof(errbuf); /* Size of the buffer */ - int ret = asn_check_constraints(&asn_DEF_E1AP_E1AP_PDU, pdu, errbuf, &errlen); - - if(ret) { - fprintf(stderr, "%s: Constraint validation failed: %s\n", func, errbuf); - } - - void *buffer = NULL; - ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_E1AP_E1AP_PDU, 0, pdu, buffer); - - if (encoded < 0) { - LOG_E(E1AP, "%s: Failed to encode E1AP message\n", func); + const E1AP_ProcedureCode_t procedureCode = pdu.choice.initiatingMessage->procedureCode; + /* Checking procedure Code and direction of message */ + if ((procedureCode >= E1AP_NUM_MSG_HANDLERS) || (pdu.present > E1AP_E1AP_PDU_PR_unsuccessfulOutcome) || (pdu.present <= E1AP_E1AP_PDU_PR_NOTHING)) { + LOG_E(E1AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n", assoc_id, procedureCode, pdu.present); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, &pdu); return -1; - } else { - MessageDef *message = itti_alloc_new_message(isCu?TASK_CUCP_E1:TASK_CUUP_E1, 0, SCTP_DATA_REQ); - sctp_data_req_t *s = &message->ittiMsg.sctp_data_req; - s->assoc_id = e1ap_assoc_id(isCu,instance); - s->buffer = buffer; - s->buffer_length = encoded; - s->stream = stream; - LOG_I(E1AP, "%s: Sending ITTI message to SCTP Task\n", func); - itti_send_msg_to_task(TASK_SCTP, instance, message); } - return encoded; + if (e1ap_message_processing[procedureCode][pdu.present - 1] == NULL) { + // No handler present. This can mean not implemented or no procedure for eNB (wrong direction). + LOG_E(E1AP, "[SCTP %d] No handler for procedureCode %ld in %s\n", assoc_id, procedureCode, e1ap_direction2String(pdu.present - 1)); + ret=-1; + } else { + /* Calling the right handler */ + LOG_I(E1AP, "Calling handler with instance %ld\n",instance); + ret = (*e1ap_message_processing[procedureCode][pdu.present - 1])(getCxtE1(instance), &pdu); + } + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, &pdu); + return ret; +} + +void e1_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) +{ + int result; + DevAssert(sctp_data_ind != NULL); + e1ap_handle_message(instance, sctp_data_ind->assoc_id, + sctp_data_ind->buffer, sctp_data_ind->buffer_length); + result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } void e1ap_itti_send_sctp_close_association(bool isCu, instance_t instance) { @@ -73,14 +112,16 @@ void e1ap_itti_send_sctp_close_association(bool isCu, instance_t instance) { itti_send_msg_to_task(TASK_SCTP, instance, message); } -int e1ap_send_RESET(bool isCu, instance_t instance, E1AP_Reset_t *Reset) { +int e1ap_send_RESET(bool isCu, e1ap_setup_req_t *setupReq, E1AP_Reset_t *Reset) +{ AssertFatal(false,"Not implemented yet\n"); E1AP_E1AP_PDU_t pdu= {0}; - return e1ap_encode_send(isCu, instance, &pdu,0, __func__); + return e1ap_encode_send(isCu, setupReq, &pdu, 0, __func__); } int e1ap_send_RESET_ACKNOWLEDGE(instance_t instance, E1AP_Reset_t *Reset) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_handle_RESET(instance_t instance, @@ -88,6 +129,7 @@ int e1ap_handle_RESET(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_handle_RESET_ACKNOWLEDGE(instance_t instance, @@ -95,6 +137,7 @@ int e1ap_handle_RESET_ACKNOWLEDGE(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* @@ -105,10 +148,12 @@ int e1ap_handle_ERROR_INDICATION(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_send_ERROR_INDICATION(instance_t instance, E1AP_ErrorIndication_t *ErrorIndication) { AssertFatal(false,"Not implemented yet\n"); + return -1; } @@ -116,74 +161,316 @@ int e1ap_send_ERROR_INDICATION(instance_t instance, E1AP_ErrorIndication_t *Erro E1 Setup: can be sent on both ways, to be refined */ -int e1apCUUP_send_SETUP_REQUEST(instance_t instance, E1AP_Reset_t *Reset) { - AssertFatal(false,"Not implemented yet\n"); +static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup; + initMsg->criticality = E1AP_Criticality_reject; + initMsg->value.present = E1AP_InitiatingMessage__value_PR_GNB_CU_UP_E1SetupRequest; + E1AP_GNB_CU_UP_E1SetupRequest_t *e1SetupUP = &initMsg->value.choice.GNB_CU_UP_E1SetupRequest; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID; + setup->transac_id = E1AP_get_next_transaction_identifier(); + ieC1->value.choice.TransactionID = setup->transac_id; + LOG_I(E1AP, "Transaction ID of setup request %ld\n", setup->transac_id); + /* mandatory */ + /* c2. GNB_CU_ID (integer value) */ + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID; + asn_int642INTEGER(&ieC2->value.choice.GNB_CU_UP_ID, setup->gNB_cu_up_id); + /* mandatory */ + /* c4. CN Support */ + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC4); + ieC4->id = E1AP_ProtocolIE_ID_id_CNSupport; + ieC4->criticality = E1AP_Criticality_reject; + ieC4->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport; + ieC4->value.choice.CNSupport = setup->cn_support; + + /* mandatory */ + /* c5. Supported PLMNs */ + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC5); + ieC5->id = E1AP_ProtocolIE_ID_id_SupportedPLMNs; + ieC5->criticality = E1AP_Criticality_reject; + ieC5->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List; + + int numSupportedPLMNs = setup->supported_plmns; + + for (int i=0; i < numSupportedPLMNs; i++) { + asn1cSequenceAdd(ieC5->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN); + /* 5.1 PLMN Identity */ + MCC_MNC_TO_PLMNID(setup->plmns[i].mcc, setup->plmns[i].mnc, setup->plmns[i].mnc_digit_length, &supportedPLMN->pLMN_Identity); + } } -int e1apCUCP_send_SETUP_RESPONSE(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +static void fill_SETUP_RESPONSE(const e1ap_setup_resp_t *e1ap_setup_resp, E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, initMsg); + initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup; + initMsg->criticality = E1AP_Criticality_reject; + initMsg->value.present = E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse; + E1AP_GNB_CU_UP_E1SetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = e1ap_setup_resp->transac_id; } -int e1apCUCP_send_SETUP_FAILURE() { - AssertFatal(false,"Not implemented yet\n"); +void e1ap_send_SETUP_RESPONSE(instance_t inst, const e1ap_setup_resp_t *e1ap_setup_resp) +{ + AssertFatal(getCxtE1(inst), ""); + e1ap_setup_req_t *setupReq = &getCxtE1(inst)->setupReq; + E1AP_E1AP_PDU_t pdu = {0}; + fill_SETUP_RESPONSE(e1ap_setup_resp, &pdu); + e1ap_encode_send(getCxtE1(inst)->type, setupReq, &pdu, 0, __func__); } -int e1apCUCP_handle_SETUP_REQUEST(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +static void fill_SETUP_FAILURE(long transac_id, E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_unsuccessfulOutcome; + asn1cCalloc(pdu->choice.unsuccessfulOutcome, initMsg); + initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup; + initMsg->criticality = E1AP_Criticality_reject; + initMsg->value.present = E1AP_UnsuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupFailure; + E1AP_GNB_CU_UP_E1SetupFailure_t *out = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = transac_id; + /* mandatory */ + /* c2. cause (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_Cause; + ieC2->criticality = E1AP_Criticality_ignore; + ieC2->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_Cause; + ieC2->value.choice.Cause.present = E1AP_Cause_PR_radioNetwork; //choose this accordingly + ieC2->value.choice.Cause.choice.radioNetwork = E1AP_CauseRadioNetwork_unspecified; } -int e1apCUUP_handle_SETUP_RESPONSE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void e1apCUCP_send_SETUP_FAILURE(e1ap_setup_req_t *setupReq, long transac_id) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_SETUP_FAILURE(transac_id, &pdu); + e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__); } -int e1apCUUP_handle_SETUP_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void extract_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, + e1ap_setup_req_t *req) { + E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie; + E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest; + /* assoc_id */ + /* req->assoc_id = assoc_id; */ + + /* transac_id */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_TransactionID, true); + req->transac_id = ie->value.choice.TransactionID; + LOG_D(E1AP, "gNB CU UP E1 setup request transaction ID: %ld\n", req->transac_id); + + /* gNB CU UP ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID, true); + asn_INTEGER2ulong(&ie->value.choice.GNB_CU_UP_ID, &req->gNB_cu_up_id); + LOG_D(E1AP, "gNB CU UP ID: %ld\n", req->gNB_cu_up_id); + + /* CN Support */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_CNSupport, true); + req->cn_support = ie->value.choice.CNSupport; + LOG_D(E1AP, "E1ap CN support: %ld\n", req->cn_support); + + /* Supported PLMNs */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_SupportedPLMNs, true); + req->supported_plmns = ie->value.choice.SupportedPLMNs_List.list.count; + LOG_D(E1AP, "Number of supported PLMNs: %d\n", req->supported_plmns); + + for (int i=0; i < req->supported_plmns; i++) { + E1AP_SupportedPLMNs_Item_t *supported_plmn_item = (E1AP_SupportedPLMNs_Item_t *)(ie->value.choice.SupportedPLMNs_List.list.array[i]); + + /* PLMN Identity */ + PLMNID_TO_MCC_MNC(&supported_plmn_item->pLMN_Identity, + req->plmns[i].mcc, + req->plmns[i].mnc, + req->plmns[i].mnc_digit_length); + LOG_D(E1AP, "MCC: %d\nMNC: %d\n", req->plmns[i].mcc, req->plmns[i].mnc); + } +} + +int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + extract_SETUP_REQUEST(pdu, &inst->setupReq); + /* Create ITTI message and send to queue */ + MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0 /*unused by callee*/, E1AP_SETUP_REQ); + memcpy(&E1AP_SETUP_REQ(msg_p), &inst->setupReq, sizeof(e1ap_setup_req_t)); + + if (inst->setupReq.supported_plmns > 0) { + itti_send_msg_to_task(TASK_RRC_GNB, 0 /*unused by callee*/, msg_p); + } else { + e1apCUCP_send_SETUP_FAILURE(&inst->setupReq, inst->setupReq.transac_id); + itti_free(TASK_CUCP_E1, msg_p); + return -1; + } + + return 0; +} + +int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ + LOG_D(E1AP, "%s\n", __func__); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome); + DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup); + DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse); + const E1AP_GNB_CU_UP_E1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse; + E1AP_GNB_CU_UP_E1SetupResponseIEs_t *ie; + + /* transac_id */ + long transaction_id; + long old_transaction_id = inst->setupReq.transac_id; + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_TransactionID, true); + transaction_id = ie->value.choice.TransactionID; + LOG_D(E1AP, "gNB CU UP E1 setup response transaction ID: %ld\n", transaction_id); + + if (old_transaction_id != transaction_id) + LOG_E(E1AP, "Transaction IDs do not match %ld != %ld\n", old_transaction_id, transaction_id); + + E1AP_free_transaction_identifier(transaction_id); + + /* do the required processing */ + + return 0; +} + +int e1apCUUP_handle_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ + E1AP_GNB_CU_UP_E1SetupFailureIEs_t *ie; + DevAssert(pdu != NULL); + E1AP_GNB_CU_UP_E1SetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure; + /* Transaction ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_TransactionID, true); + /* Cause */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_Cause, true); + + return 0; +} + +static void fill_CONFIGURATION_UPDATE(E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_ConfigurationUpdate; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_GNB_CU_UP_ConfigurationUpdate; + E1AP_GNB_CU_UP_ConfigurationUpdate_t *out = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_ConfigurationUpdate; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = 0;//get this from stored transaction IDs in CU + /* mandatory */ + /* c2. Supported PLMNs */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_SupportedPLMNs; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_SupportedPLMNs_List; + + int numSupportedPLMNs = 1; + + for (int i=0; i < numSupportedPLMNs; i++) { + asn1cSequenceAdd(ieC2->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN); + /* 5.1 PLMN Identity */ + OCTET_STRING_fromBuf(&supportedPLMN->pLMN_Identity, "OAI", strlen("OAI")); + } + + /* mandatory */ + /* c3. TNLA to remove list */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_GNB_CU_UP_TNLA_To_Remove_List; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_GNB_CU_UP_TNLA_To_Remove_List; + + int numTNLAtoRemoveList = 1; + + for (int i=0; i < numTNLAtoRemoveList; i++) { + asn1cSequenceAdd(ieC2->value.choice.GNB_CU_UP_TNLA_To_Remove_List.list, E1AP_GNB_CU_UP_TNLA_To_Remove_Item_t, TNLAtoRemove); + TNLAtoRemove->tNLAssociationTransportLayerAddress.present = E1AP_CP_TNL_Information_PR_endpoint_IP_Address; + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &TNLAtoRemove->tNLAssociationTransportLayerAddress.choice.endpoint_IP_Address); // TODO: correct me + } } /* E1 configuration update: can be sent in both ways, to be refined */ -int e1apCUUP_send_gNB_DU_CONFIGURATION_UPDATE(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +void e1apCUUP_send_CONFIGURATION_UPDATE(e1ap_setup_req_t *setupReq) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_CONFIGURATION_UPDATE(&pdu); + e1ap_encode_send(UPtype, setupReq, &pdu, 0, __func__); } -int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(instance_t instance) { +int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(e1ap_setup_req_t *setupReq) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUCP_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance) { +int e1apCUCP_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(e1ap_setup_req_t *setupReq) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUCP_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { +int e1apCUCP_handle_CONFIGURATION_UPDATE(e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu) +{ + /* + E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie; + DevAssert(pdu != NULL); + E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest; + */ + AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { +int e1apCUUP_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(e1ap_setup_req_t *setupReq, uint32_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { +int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(e1ap_setup_req_t *setupReq, uint32_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } /* @@ -192,10 +479,12 @@ int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, int e1ap_send_RELEASE_REQUEST(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_send_RELEASE_ACKNOWLEDGE(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_handle_RELEASE_REQUEST(instance_t instance, @@ -203,6 +492,7 @@ int e1ap_handle_RELEASE_REQUEST(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_handle_RELEASE_ACKNOWLEDGE(instance_t instance, @@ -210,66 +500,750 @@ int e1ap_handle_RELEASE_ACKNOWLEDGE(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* BEARER CONTEXT SETUP REQUEST */ -int e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu) +{ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextSetup; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest; + E1AP_BearerContextSetupRequest_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; + /* mandatory */ + /* c1. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. Security Information */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_SecurityInformation; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation; + ieC2->value.choice.SecurityInformation.securityAlgorithm.cipheringAlgorithm = bearerCxt->cipheringAlgorithm; + OCTET_STRING_fromBuf(&ieC2->value.choice.SecurityInformation.uPSecuritykey.encryptionKey, + bearerCxt->encryptionKey, strlen(bearerCxt->encryptionKey)); + + asn1cCallocOne(ieC2->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm, bearerCxt->integrityProtectionAlgorithm); + asn1cCalloc(ieC2->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey, protKey); + OCTET_STRING_fromBuf(protKey, bearerCxt->integrityProtectionKey, strlen(bearerCxt->integrityProtectionKey)); + /* mandatory */ + /* c3. UE DL Aggregate Maximum Bit Rate */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_BitRate; + asn_long2INTEGER(&ieC3->value.choice.BitRate, bearerCxt->ueDlAggMaxBitRate); + /* mandatory */ + /* c4. Serving PLMN */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC4); + ieC4->id = E1AP_ProtocolIE_ID_id_Serving_PLMN; + ieC4->criticality = E1AP_Criticality_ignore; + ieC4->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity; + PLMN_ID_t *servingPLMN = setup->plmns; // First PLMN is serving PLMN. TODO: Remove hard coding here + MCC_MNC_TO_PLMNID(servingPLMN->mcc, servingPLMN->mnc, servingPLMN->mnc_digit_length, &ieC4->value.choice.PLMN_Identity); + /* mandatory */ + /* Activity Notification Level */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC5); + ieC5->id = E1AP_ProtocolIE_ID_id_ActivityNotificationLevel; + ieC5->criticality = E1AP_Criticality_reject; + ieC5->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel; + ieC5->value.choice.ActivityNotificationLevel = E1AP_ActivityNotificationLevel_pdu_session;// TODO: Remove hard coding + /* mandatory */ + /* */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC6); + ieC6->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest; + ieC6->criticality = E1AP_Criticality_reject; + ieC6->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest; + ieC6->value.choice.System_BearerContextSetupRequest.present = E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest; + E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P19_t)); + ieC6->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupRequest_t, msgNGRAN); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List; + E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; + for(pdu_session_to_setup_t *i=bearerCxt->pduSession; i < bearerCxt->pduSession+bearerCxt->numPDUSessions; i++) { + asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Item_t, ieC6_1); + ieC6_1->pDU_Session_ID = i->sessionId; + ieC6_1->pDU_Session_Type = i->sessionType; + + INT8_TO_OCTET_STRING(i->sst, &ieC6_1->sNSSAI.sST); + + ieC6_1->securityIndication.integrityProtectionIndication = i->integrityProtectionIndication; + ieC6_1->securityIndication.confidentialityProtectionIndication = i->confidentialityProtectionIndication; + + ieC6_1->nG_UL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC6_1->nG_UL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); + + for (DRB_nGRAN_to_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRB2Setup; j++) { + asn1cSequenceAdd(ieC6_1->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); + ieC6_1_1->dRB_ID = j->id; + + ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB; + ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sDAP_Header_UL; + ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sDAP_Header_DL; + + ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pDCP_SN_Size_UL; + ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pDCP_SN_Size_DL; + asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->discardTimer); + E1AP_T_ReorderingTimer_t *roTimer = calloc(1, sizeof(E1AP_T_ReorderingTimer_t)); + ieC6_1_1->pDCP_Configuration.t_ReorderingTimer = roTimer; + roTimer->t_Reordering = j->reorderingTimer; + ieC6_1_1->pDCP_Configuration.rLC_Mode = j->rLC_Mode; + + for (cell_group_t *k=j->cellGroupList; k < j->cellGroupList+j->numCellGroups; k++) { + asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1); + ieC6_1_1_1->cell_Group_ID = k->id; + } + + for (qos_flow_to_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlow2Setup; k++) { + asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); + ieC6_1_1_1->qoS_Flow_Identifier = k->id; + + if (k->fiveQI_type == non_dynamic) { // non Dynamic 5QI + ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; + asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); + non_Dynamic_5QI->fiveQI = k->fiveQI; + } else { // dynamic 5QI + ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI; + asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI); + dynamic_5QI->qoSPriorityLevel = k->qoSPriorityLevel; + dynamic_5QI->packetDelayBudget = k->packetDelayBudget; + dynamic_5QI->packetErrorRate.pER_Scalar = k->packetError_scalar; + dynamic_5QI->packetErrorRate.pER_Exponent = k->packetError_exponent; + } + + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = k->priorityLevel; + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = k->pre_emptionCapability; + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = k->pre_emptionVulnerability; + } + } + } + return 0; } -int e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +void e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, e1ap_bearer_setup_req_t *const bearerCxt) +{ + if (!getCxtE1(instance)) { + LOG_E(E1AP, "Received a UE bearer to establish while no CU-UP is connected, response on NGAP to send failure is not developped\n"); + // Fixme: add response on NGAP to send failure + return; + } + + E1AP_E1AP_PDU_t pdu = {0}; + e1ap_setup_req_t *setupReq = &getCxtE1(instance)->setupReq; + fill_BEARER_CONTEXT_SETUP_REQUEST(setupReq, bearerCxt, &pdu); + e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__); +} + +static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const resp, E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextSetup; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse; + E1AP_BearerContextSetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; + /* mandatory */ + /* c1. gNB-CU-CP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_up_ue_id; + + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse; + if (0) { // EUTRAN + ieC3->value.choice.System_BearerContextSetupResponse.present = E1AP_System_BearerContextSetupResponse_PR_e_UTRAN_BearerContextSetupResponse; + E1AP_ProtocolIE_Container_4932P21_t *msgEUTRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P21_t)); + ieC3->value.choice.System_BearerContextSetupResponse.choice.e_UTRAN_BearerContextSetupResponse = (struct E1AP_ProtocolIE_Container *) msgEUTRAN_list; + asn1cSequenceAdd(msgEUTRAN_list->list, E1AP_EUTRAN_BearerContextSetupResponse_t, msgEUTRAN); + msgEUTRAN->id = E1AP_ProtocolIE_ID_id_DRB_Setup_List_EUTRAN; + msgEUTRAN->criticality = E1AP_Criticality_reject; + msgEUTRAN->value.present = E1AP_EUTRAN_BearerContextSetupResponse__value_PR_DRB_Setup_List_EUTRAN; + E1AP_DRB_Setup_List_EUTRAN_t *drbSetup = &msgEUTRAN->value.choice.DRB_Setup_List_EUTRAN; + + for (drb_setup_t *i=resp->DRBList; i < resp->DRBList+resp->numDRBs; i++) { + asn1cSequenceAdd(drbSetup->list, E1AP_DRB_Setup_Item_EUTRAN_t, ieC3_1); + ieC3_1->dRB_ID = i->drbId; + + ieC3_1->s1_DL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1->s1_DL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); + + for (up_params_t *j=i->UpParamList; j < i->UpParamList+i->numUpParam; j++) { + asn1cSequenceAdd(ieC3_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1); + ieC3_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(j->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(j->teId, &gTPTunnel->gTP_TEID); + } + } + } else { + ieC3->value.choice.System_BearerContextSetupResponse.present = E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse; + E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P22_t)); + ieC3->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupResponse_t, msgNGRAN); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List; + E1AP_PDU_Session_Resource_Setup_List_t *pduSetup = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; + + for (pdu_session_setup_t *i=resp->pduSession; i < resp->pduSession+resp->numPDUSessions; i++) { + asn1cSequenceAdd(pduSetup->list, E1AP_PDU_Session_Resource_Setup_Item_t, ieC3_1); + ieC3_1->pDU_Session_ID = i->id; + + ieC3_1->nG_DL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1->nG_DL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); + + for (DRB_nGRAN_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRBSetup; j++) { + asn1cSequenceAdd(ieC3_1->dRB_Setup_List_NG_RAN.list, E1AP_DRB_Setup_Item_NG_RAN_t, ieC3_1_1); + ieC3_1_1->dRB_ID = j->id; + + for (up_params_t *k=j->UpParamList; k < j->UpParamList+j->numUpParam; k++) { + asn1cSequenceAdd(ieC3_1_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1_1); + ieC3_1_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); + } + + for (qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) { + asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1); + ieC3_1_1_1->qoS_Flow_Identifier = k->id; + } + } + + if (i->numDRBFailed > 0) + ieC3_1->dRB_Failed_List_NG_RAN = calloc(1, sizeof(E1AP_DRB_Failed_List_NG_RAN_t)); + + for (DRB_nGRAN_failed_t *j=i->DRBnGRanFailedList; j < i->DRBnGRanFailedList+i->numDRBFailed; j++) { + asn1cSequenceAdd(ieC3_1->dRB_Failed_List_NG_RAN->list, E1AP_DRB_Failed_Item_NG_RAN_t, ieC3_1_1); + ieC3_1_1->dRB_ID = j->id; + + ieC3_1_1->cause.present = j->cause_type; + switch (ieC3_1_1->cause.present) { + case E1AP_Cause_PR_radioNetwork: + ieC3_1_1->cause.choice.radioNetwork = j->cause; + break; + + case E1AP_Cause_PR_transport: + ieC3_1_1->cause.choice.transport = j->cause; + break; + + case E1AP_Cause_PR_protocol: + ieC3_1_1->cause.choice.protocol = j->cause; + break; + + case E1AP_Cause_PR_misc: + ieC3_1_1->cause.choice.misc = j->cause; + break; + + default: + LOG_E(E1AP, "DRB setup failure cause out of expected range\n"); + break; + } + } + } + } +} + +void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, e1ap_bearer_setup_resp_t *const resp) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_BEARER_CONTEXT_SETUP_RESPONSE(resp, &pdu); + e1ap_encode_send(UPtype, &inst->setupReq, &pdu, 0, __func__); } int e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_setup_req_t *bearerCxt) { + const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; + E1AP_BearerContextSetupRequestIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_SecurityInformation: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation); + bearerCxt->cipheringAlgorithm = ie->value.choice.SecurityInformation.securityAlgorithm.cipheringAlgorithm; + memcpy(bearerCxt->encryptionKey, + ie->value.choice.SecurityInformation.uPSecuritykey.encryptionKey.buf, + ie->value.choice.SecurityInformation.uPSecuritykey.encryptionKey.size); + if (ie->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm) { + bearerCxt->integrityProtectionAlgorithm = *ie->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm; + } + if (ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey) { + memcpy(bearerCxt->integrityProtectionKey, + ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey->buf, + ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey->size); + } + break; + + case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_BitRate); + asn_INTEGER2long(&ie->value.choice.BitRate, &bearerCxt->ueDlAggMaxBitRate); + break; + + case E1AP_ProtocolIE_ID_id_Serving_PLMN: + DevAssert(ie->criticality == E1AP_Criticality_ignore); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity); + PLMNID_TO_MCC_MNC(&ie->value.choice.PLMN_Identity, + bearerCxt->servingPLMNid.mcc, + bearerCxt->servingPLMNid.mnc, + bearerCxt->servingPLMNid.mnc_digit_length); + break; + + case E1AP_ProtocolIE_ID_id_ActivityNotificationLevel: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel); + bearerCxt->activityNotificationLevel = ie->value.choice.ActivityNotificationLevel; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest); + DevAssert(ie->value.choice.System_BearerContextSetupRequest.present == + E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest); + DevAssert(ie->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest); + E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P19_t *) ie->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest; + E1AP_NG_RAN_BearerContextSetupRequest_t *msgNGRAN = msgNGRAN_list->list.array[0]; + DevAssert(msgNGRAN_list->list.count == 1); + DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List); + DevAssert(msgNGRAN->value.present == E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List); + + E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2SetupList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; + bearerCxt->numPDUSessions = pdu2SetupList->list.count; + for (int i=0; i < pdu2SetupList->list.count; i++) { + pdu_session_to_setup_t *pdu_session = bearerCxt->pduSession + i; + E1AP_PDU_Session_Resource_To_Setup_Item_t *pdu2Setup = pdu2SetupList->list.array[i]; + + pdu_session->sessionId = pdu2Setup->pDU_Session_ID; + pdu_session->sessionType = pdu2Setup->pDU_Session_Type; + + OCTET_STRING_TO_INT8(&pdu2Setup->sNSSAI.sST, pdu_session->sst); + + pdu_session->integrityProtectionIndication = pdu2Setup->securityIndication.integrityProtectionIndication; + pdu_session->confidentialityProtectionIndication = pdu2Setup->securityIndication.confidentialityProtectionIndication; + + if (pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel) { // Optional IE + DevAssert(pdu2Setup->nG_UL_UP_TNL_Information.present == + E1AP_UP_TNL_Information_PR_gTPTunnel); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, + pdu_session->tlAddress); + OCTET_STRING_TO_INT32(&pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, pdu_session->teId); + } + + E1AP_DRB_To_Setup_List_NG_RAN_t *drb2SetupList = &pdu2Setup->dRB_To_Setup_List_NG_RAN; + pdu_session->numDRB2Setup = drb2SetupList->list.count; + for (int j=0; j < drb2SetupList->list.count; j++) { + DRB_nGRAN_to_setup_t *drb = pdu_session->DRBnGRanList + j; + E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; + + drb->id = drb2Setup->dRB_ID; + + drb->defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB; + drb->sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL; + drb->sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL; + + drb->pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL; + drb->pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL; + + if (drb2Setup->pDCP_Configuration.discardTimer) { + drb->discardTimer = *drb2Setup->pDCP_Configuration.discardTimer; + } + + if (drb2Setup->pDCP_Configuration.t_ReorderingTimer) { + drb->reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering; + } + + drb->rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode; + + E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; + drb->numCellGroups = cellGroupList->list.count; + for (int k=0; k < cellGroupList->list.count; k++) { + E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k]; + + drb->cellGroupList[k].id = cg2Setup->cell_Group_ID; + } + + E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup; + drb->numQosFlow2Setup = qos2SetupList->list.count; + for (int k=0; k < qos2SetupList->list.count; k++) { + qos_flow_to_setup_t *qos = drb->qosFlows + k; + E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k]; + + qos->id = qos2Setup->qoS_Flow_Identifier; + + if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == + E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + qos->fiveQI_type = non_dynamic; + qos->fiveQI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; + } else { + E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI; + qos->fiveQI_type = dynamic; + qos->qoSPriorityLevel = dynamic5QI->qoSPriorityLevel; + qos->packetDelayBudget = dynamic5QI->packetDelayBudget; + qos->packetError_scalar = dynamic5QI->packetErrorRate.pER_Scalar; + qos->packetError_exponent = dynamic5QI->packetErrorRate.pER_Exponent; + } + + qos->priorityLevel = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel; + qos->pre_emptionCapability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability; + qos->pre_emptionVulnerability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability; + } + } + } + break; + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } + + } -int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage); + DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextSetup); + DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest); + + e1ap_bearer_setup_req_t bearerCxt = {0}; + extract_BEARER_CONTEXT_SETUP_REQUEST(pdu, &bearerCxt); + process_e1_bearer_context_setup_req(e1_inst->instance, &bearerCxt); + return 0; } -int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { +void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_setup_resp_t *bearerCxt) { + const E1AP_BearerContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; + E1AP_BearerContextSetupResponseIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup response number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse); + DevAssert(ie->value.choice.System_BearerContextSetupResponse.present == + E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse); + E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P22_t *) ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse; + DevAssert(msgNGRAN_list->list.count == 1); + E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; + DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List); + DevAssert(msgNGRAN->criticality == E1AP_Criticality_reject); + DevAssert(msgNGRAN->value.present == E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List); + E1AP_PDU_Session_Resource_Setup_List_t *pduSetupList = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; + bearerCxt->numPDUSessions = pduSetupList->list.count; + + for (int i=0; i < pduSetupList->list.count; i++) { + pdu_session_setup_t *pduSetup = bearerCxt->pduSession + i; + E1AP_PDU_Session_Resource_Setup_Item_t *pdu_session = pduSetupList->list.array[i]; + pduSetup->id = pdu_session->pDU_Session_ID; + + if (pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel) { + DevAssert(pdu_session->nG_DL_UP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, + pduSetup->tlAddress); + OCTET_STRING_TO_INT32(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, + pduSetup->teId); + } + + pduSetup->numDRBSetup = pdu_session->dRB_Setup_List_NG_RAN.list.count; + for (int j=0; j < pdu_session->dRB_Setup_List_NG_RAN.list.count; j++) { + DRB_nGRAN_setup_t *drbSetup = pduSetup->DRBnGRanList + j; + E1AP_DRB_Setup_Item_NG_RAN_t *drb = pdu_session->dRB_Setup_List_NG_RAN.list.array[j]; + + drbSetup->id = drb->dRB_ID; + + drbSetup->numUpParam = drb->uL_UP_Transport_Parameters.list.count; + for (int k=0; k < drb->uL_UP_Transport_Parameters.list.count; k++) { + up_params_t *UL_UP_param = drbSetup->UpParamList + k; + E1AP_UP_Parameters_Item_t *in_UL_UP_param = drb->uL_UP_Transport_Parameters.list.array[k]; + + DevAssert(in_UL_UP_param->uP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); + E1AP_GTPTunnel_t *gTPTunnel = in_UL_UP_param->uP_TNL_Information.choice.gTPTunnel; + if (gTPTunnel) { + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, + UL_UP_param->tlAddress); + OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, + UL_UP_param->teId); + } else { + AssertFatal(false, "gTPTunnel information in required\n"); + } + } + } + } + break; + + // TODO: remaining IE handlers + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } +} + +int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome); + DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextSetup); + DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse); + + MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP); + e1ap_bearer_setup_resp_t *bearerCxt = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg); + extract_BEARER_CONTEXT_SETUP_RESPONSE(pdu, bearerCxt); + // Fixme: instance is the NGAP instance, no good way to set it here + instance_t instance = 0; + itti_send_msg_to_task(TASK_RRC_GNB, instance, msg); + + return 0; +} + +int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } /* BEARER CONTEXT MODIFICATION REQUEST */ -int e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_setup_req_t *setupReq, e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu) +{ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextModification; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest; + E1AP_BearerContextModificationRequest_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest; + /* mandatory */ + /* c1. gNB-CU-CP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id; + /* optional */ + /* */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest; + ieC3->value.choice.System_BearerContextModificationRequest.present = E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest; + E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P26_t)); + ieC3->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextModificationRequest_t, msgNGRAN); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List; + E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; + for(pdu_session_to_setup_t *i=bearerCxt->pduSessionMod; i < bearerCxt->pduSessionMod+bearerCxt->numPDUSessionsMod; i++) { + asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Modify_Item_t, ieC3_1); + ieC3_1->pDU_Session_ID = i->sessionId; + + for (DRB_nGRAN_to_setup_t *j=i->DRBnGRanModList; j < i->DRBnGRanModList+i->numDRB2Modify; j++) { + asn1cCalloc(ieC3_1->dRB_To_Modify_List_NG_RAN, drb2Mod_List); + asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod); + drb2Mod->dRB_ID = j->id; + + if (j->numDlUpParam > 0) { + asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List); + for (up_params_t *k=j->DlUpParamList; k < j->DlUpParamList+j->numDlUpParam; k++) { + asn1cSequenceAdd(DL_UP_Param_List->list, E1AP_UP_Parameters_Item_t, DL_UP_Param); + DL_UP_Param->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(DL_UP_Param->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); + + DL_UP_Param->cell_Group_ID = k->cell_group_id; + } + } + } + } + return 0; +} + +static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t inst, e1ap_bearer_setup_req_t *const bearerCxt) +{ + AssertFatal(getCxtE1(inst), ""); + e1ap_setup_req_t *setupReq = &getCxtE1(inst)->setupReq; + E1AP_E1AP_PDU_t pdu = {0}; + fill_BEARER_CONTEXT_MODIFICATION_REQUEST(setupReq, bearerCxt, &pdu); + e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__); } int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_setup_req_t *bearerCxt) { + const E1AP_BearerContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest; + E1AP_BearerContextModificationRequestIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest); + DevAssert(ie->value.choice.System_BearerContextModificationRequest.present == + E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest); + DevAssert(ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest != NULL); + E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P26_t *) ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest; + E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = msgNGRAN_list->list.array[0]; + DevAssert(msgNGRAN_list->list.count == 1); + DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List); + DevAssert(msgNGRAN->value.present = + E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List); + + E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2ModList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; + bearerCxt->numPDUSessionsMod = pdu2ModList->list.count; + for (int i=0; i < pdu2ModList->list.count; i++) { + pdu_session_to_setup_t *pdu_session = bearerCxt->pduSessionMod + i; + E1AP_PDU_Session_Resource_To_Modify_Item_t *pdu2Mod = pdu2ModList->list.array[i]; + + pdu_session->sessionId = pdu2Mod->pDU_Session_ID; + + E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = pdu2Mod->dRB_To_Modify_List_NG_RAN; + pdu_session->numDRB2Modify = drb2ModList->list.count; + for (int j=0; j < drb2ModList->list.count; j++) { + DRB_nGRAN_to_setup_t *drb = pdu_session->DRBnGRanModList + j; + E1AP_DRB_To_Modify_Item_NG_RAN_t *drb2Mod = drb2ModList->list.array[j]; + + drb->id = drb2Mod->dRB_ID; + + E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; + drb->numDlUpParam = dl_up_paramList->list.count; + for (int k=0; k < dl_up_paramList->list.count; k++) { + up_params_t *dl_up_param = drb->DlUpParamList + k; + E1AP_UP_Parameters_Item_t *dl_up_param_in = dl_up_paramList->list.array[k]; + if (dl_up_param_in->uP_TNL_Information.choice.gTPTunnel) { // Optional IE + DevAssert(dl_up_param_in->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress, + dl_up_param->tlAddress); + OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->teId); + } else { + AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n"); + } + dl_up_param->cell_group_id = dl_up_param_in->cell_Group_ID; + } + } + } + break; + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } +} + +int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage); + DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextModification); + DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest); + + e1ap_bearer_setup_req_t bearerCxt = {0}; + extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt); + CUUP_process_bearer_context_mod_req(e1_inst->instance, &bearerCxt); + return 0; } int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, @@ -277,6 +1251,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance, @@ -284,14 +1259,17 @@ int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_REQUIRED(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, @@ -299,6 +1277,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, @@ -306,35 +1285,178 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* BEARER CONTEXT RELEASE */ -int e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +static int fill_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd, E1AP_E1AP_PDU_t *pdu) +{ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextRelease; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextReleaseCommand; + E1AP_BearerContextReleaseCommand_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextReleaseCommand; + /* mandatory */ + /* c1. gNB-CU-CP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCommandIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextReleaseCommandIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCommandIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextReleaseCommandIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id; + + return 0; } -int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +int e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_BEARER_CONTEXT_RELEASE_COMMAND(setupReq, cmd, &pdu); + return e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__); +} + +int fill_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd, E1AP_E1AP_PDU_t *pdu) +{ + pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextRelease; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextReleaseComplete; + E1AP_BearerContextReleaseComplete_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextReleaseComplete; + /* mandatory */ + /* c1. gNB-CU-CP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCompleteIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCompleteIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id; + + return 0; +} + +int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, e1ap_bearer_release_cmd_t *const cmd) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_BEARER_CONTEXT_RELEASE_COMPLETE(&inst->setupReq, cmd, &pdu); + return e1ap_encode_send(CPtype, &inst->setupReq, &pdu, 0, __func__); } int e1apCUUP_send_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void extract_BEARER_CONTEXT_RELEASE_COMMAND(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_release_cmd_t *bearerCxt) { + const E1AP_BearerContextReleaseCommand_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextReleaseCommand; + E1AP_BearerContextReleaseCommandIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCommandIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCommandIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_Cause: + DevAssert(ie->criticality == E1AP_Criticality_ignore); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCommandIEs__value_PR_Cause); + bearerCxt->cause_type = ie->value.choice.Cause.present; + if ((ie->value.choice.Cause.present != E1AP_Cause_PR_NOTHING) && + (ie->value.choice.Cause.present != E1AP_Cause_PR_choice_extension)) + bearerCxt->cause = ie->value.choice.Cause.choice.radioNetwork; + + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } } -int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage); + DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextRelease); + DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextReleaseCommand); + + e1ap_bearer_release_cmd_t bearerCxt = {0}; + extract_BEARER_CONTEXT_RELEASE_COMMAND(pdu, &bearerCxt); + CUUP_process_bearer_release_command(e1_inst->instance, &bearerCxt); + return 0; +} + +void extract_BEARER_CONTEXT_RELEASE_COMPLETE(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_release_cmd_t *bearerCxt) { + const E1AP_BearerContextReleaseComplete_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextReleaseComplete; + E1AP_BearerContextReleaseCompleteIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } +} + +int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome); + DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextRelease); + DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextReleaseComplete); + + e1ap_bearer_release_cmd_t bearerCxt = {0}; + extract_BEARER_CONTEXT_RELEASE_COMPLETE(pdu, &bearerCxt); + //TODO: CUCP_process_bearer_release_complete(&beareCxt, instance); + return 0; } int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance, @@ -342,6 +1464,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* @@ -350,6 +1473,7 @@ BEARER CONTEXT INACTIVITY NOTIFICATION int e1apCUUP_send_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance, @@ -357,6 +1481,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* DL DATA @@ -364,10 +1489,12 @@ int e1apCUCP_handle_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance, int e1apCUUP_send_DL_DATA_NOTIFICATION(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUUP_send_DATA_USAGE_REPORT(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_DL_DATA_NOTIFICATION(instance_t instance, @@ -375,6 +1502,7 @@ int e1apCUCP_handle_DL_DATA_NOTIFICATION(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_send_DATA_USAGE_REPORT(instance_t instance, @@ -382,4 +1510,236 @@ int e1apCUCP_handle_send_DATA_USAGE_REPORT(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } + +static instance_t cuup_task_create_gtpu_instance_to_du(eth_params_t *IPaddrs) { + openAddr_t tmp= {0}; + strncpy(tmp.originHost, IPaddrs->my_addr, sizeof(tmp.originHost)-1); + sprintf(tmp.originService, "%d", IPaddrs->my_portd); + return gtpv1Init(tmp); +} + +static void e1_task_send_sctp_association_req(long task_id, instance_t instance, e1ap_setup_req_t *e1ap_setup_req) +{ + DevAssert(e1ap_setup_req != NULL); + getCxtE1(instance)->sockState = SCTP_STATE_CLOSED; + MessageDef *message_p = itti_alloc_new_message(task_id, 0, SCTP_NEW_ASSOCIATION_REQ); + sctp_new_association_req_t *sctp_new_req = &message_p->ittiMsg.sctp_new_association_req; + sctp_new_req->ulp_cnx_id = instance; + sctp_new_req->port = E1AP_PORT_NUMBER; + sctp_new_req->ppid = E1AP_SCTP_PPID; + sctp_new_req->in_streams = e1ap_setup_req->sctp_in_streams; + sctp_new_req->out_streams = e1ap_setup_req->sctp_out_streams; + // remote + sctp_new_req->remote_address = e1ap_setup_req->CUCP_e1_ip_address; + // local + sctp_new_req->local_address = e1ap_setup_req->CUUP_e1_ip_address; + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + +static void e1apCUUP_send_SETUP_REQUEST(e1ap_setup_req_t *setup) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_SETUP_REQUEST(setup, &pdu); + e1ap_encode_send(UPtype, setup, &pdu, 0, __func__); +} + +static void e1_task_handle_sctp_association_resp(E1_t type, instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) +{ + DevAssert(sctp_new_association_resp != NULL); + getCxtE1(instance)->sockState = sctp_new_association_resp->sctp_state; + if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { + LOG_W(E1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", + sctp_new_association_resp->sctp_state, + instance, + sctp_new_association_resp->ulp_cnx_id); + long timer_id; // if we want to cancel timer + timer_setup(1, 0, TASK_CUUP_E1, 0, TIMER_ONE_SHOT, NULL, &timer_id); + return; + } + + if (type == UPtype) { + e1ap_setup_req_t *e1ap_cuup_setup_req = &getCxtE1(instance)->setupReq; + e1ap_cuup_setup_req->assoc_id = sctp_new_association_resp->assoc_id; + e1ap_cuup_setup_req->sctp_in_streams = sctp_new_association_resp->in_streams; + e1ap_cuup_setup_req->sctp_out_streams = sctp_new_association_resp->out_streams; + e1ap_cuup_setup_req->default_sctp_stream_id = 0; + + eth_params_t IPaddr; + IPaddr.my_addr = e1ap_cuup_setup_req->localAddressF1U; + IPaddr.my_portd = e1ap_cuup_setup_req->localPortF1U; + if (getCxtE1(instance)->gtpInstF1U < 0) + getCxtE1(instance)->gtpInstF1U = cuup_task_create_gtpu_instance_to_du(&IPaddr); + if (getCxtE1(instance)->gtpInstF1U < 0) + LOG_E(E1AP, "Failed to create CUUP F1-U UDP listener"); + extern instance_t CUuniqInstance; + CUuniqInstance = getCxtE1(instance)->gtpInstF1U; + cuup_init_n3(instance); + e1apCUUP_send_SETUP_REQUEST(&getCxtE1(instance)->setupReq); + } +} + +void cuup_init_n3(instance_t instance) +{ + if (getCxtE1(instance)->gtpInstN3 < 0) { + e1ap_setup_req_t *setup = &getCxtE1(instance)->setupReq; + openAddr_t tmp = {0}; + strcpy(tmp.originHost, setup->localAddressN3); + sprintf(tmp.originService, "%d", setup->localPortN3); + sprintf(tmp.destinationService, "%d", setup->remotePortN3); + LOG_I(GTPU, "Configuring GTPu address : %s, port : %s\n", tmp.originHost, tmp.originService); + // Fixme: fully inconsistent instances management + // dirty global var is a bad fix + extern instance_t legacyInstanceMapping; + legacyInstanceMapping = getCxtE1(instance)->gtpInstN3 = gtpv1Init(tmp); + } + if (getCxtE1(instance)->gtpInstN3 < 0) + LOG_E(E1AP, "Failed to create CUUP N3 UDP listener"); + extern instance_t *N3GTPUInst; + N3GTPUInst = &getCxtE1(instance)->gtpInstN3; +} + +void cucp_task_send_sctp_init_req(instance_t instance, char *my_addr) { + LOG_I(E1AP, "E1AP_CUCP_SCTP_REQ(create socket)\n"); + MessageDef *message_p = NULL; + message_p = itti_alloc_new_message (TASK_CUCP_E1, 0, SCTP_INIT_MSG); + message_p->ittiMsg.sctp_init.port = E1AP_PORT_NUMBER; + message_p->ittiMsg.sctp_init.ppid = E1AP_SCTP_PPID; + message_p->ittiMsg.sctp_init.ipv4 = 1; + message_p->ittiMsg.sctp_init.ipv6 = 0; + message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1; + message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(my_addr); + /* + * SR WARNING: ipv6 multi-homing fails sometimes for localhost. + * * * * Disable it for now. + */ + message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0; + message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1"; + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + +void e1_task_handle_sctp_association_ind(E1_t type, instance_t instance, sctp_new_association_ind_t *sctp_new_ind) +{ + if (getCxtE1(instance)) + LOG_W(E1AP, "CUCP incoming call, re-use older socket context, finish implementation required\n"); + else + createE1inst(type, instance, NULL); + getCxtE1(instance)->sockState = SCTP_STATE_ESTABLISHED; + getCxtE1(instance)->incoming_sock = true; + e1ap_setup_req_t *setup_req = &getCxtE1(instance)->setupReq; + setup_req->assoc_id = sctp_new_ind->assoc_id; + setup_req->sctp_in_streams = sctp_new_ind->in_streams; + setup_req->sctp_out_streams = sctp_new_ind->out_streams; + setup_req->default_sctp_stream_id = 0; +} + +void e1apHandleTimer(instance_t myInstance) +{ + LOG_W(E1AP, "Try to reconnect to CP\n"); + if (getCxtE1(myInstance)->sockState != SCTP_STATE_ESTABLISHED) + e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, &getCxtE1(myInstance)->setupReq); +} + +void *E1AP_CUCP_task(void *arg) { + LOG_I(E1AP, "Starting E1AP at CU CP\n"); + MessageDef *msg = NULL; + e1ap_common_init(); + int result; + + while (1) { + itti_receive_msg(TASK_CUCP_E1, &msg); + instance_t myInstance=ITTI_MSG_DESTINATION_INSTANCE(msg); + const int msgType = ITTI_MSG_ID(msg); + LOG_I(E1AP, "CUCP received %s for instance %ld\n", messages_info[msgType].name, myInstance); + + switch (ITTI_MSG_ID(msg)) { + case SCTP_NEW_ASSOCIATION_IND: + e1_task_handle_sctp_association_ind(CPtype, ITTI_MSG_ORIGIN_INSTANCE(msg), &msg->ittiMsg.sctp_new_association_ind); + break; + + case SCTP_NEW_ASSOCIATION_RESP: + e1_task_handle_sctp_association_resp(CPtype, ITTI_MSG_ORIGIN_INSTANCE(msg), &msg->ittiMsg.sctp_new_association_resp); + break; + + case E1AP_SETUP_REQ: { + e1ap_setup_req_t *req = &E1AP_SETUP_REQ(msg); + if (req->CUCP_e1_ip_address.ipv4 == 0) { + LOG_E(E1AP, "No IPv4 address configured\n"); + return NULL; + } + cucp_task_send_sctp_init_req(0, req->CUCP_e1_ip_address.ipv4_address); + } break; + + case SCTP_DATA_IND: + e1_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind); + break; + + case E1AP_SETUP_RESP: + e1ap_send_SETUP_RESPONSE(myInstance, &E1AP_SETUP_RESP(msg)); + break; + + case E1AP_BEARER_CONTEXT_SETUP_REQ: + e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(myInstance, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); + break; + + case E1AP_BEARER_CONTEXT_MODIFICATION_REQ: + e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(myInstance, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); + break; + + default: + LOG_E(E1AP, "Unknown message received in TASK_CUCP_E1\n"); + break; + } + + result = itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d) in E1AP_CUCP_task!\n", result); + msg = NULL; + + } +} + +void *E1AP_CUUP_task(void *arg) { + LOG_I(E1AP, "Starting E1AP at CU UP\n"); + e1ap_common_init(); + int result; + + // SCTP + while (1) { + MessageDef *msg = NULL; + itti_receive_msg(TASK_CUUP_E1, &msg); + const instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(msg); + const int msgType = ITTI_MSG_ID(msg); + LOG_I(E1AP, "CUUP received %s for instance %ld\n", messages_info[msgType].name, myInstance); + switch (msgType) { + case E1AP_SETUP_REQ: { + e1ap_setup_req_t *msgSetup = &E1AP_SETUP_REQ(msg); + createE1inst(UPtype, myInstance, msgSetup); + + e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, msgSetup); + } break; + + case SCTP_NEW_ASSOCIATION_RESP: + e1_task_handle_sctp_association_resp(UPtype, myInstance, &msg->ittiMsg.sctp_new_association_resp); + break; + + case SCTP_DATA_IND: + e1_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind); + break; + + case TIMER_HAS_EXPIRED: + e1apHandleTimer(myInstance); + break; + + default: + LOG_E(E1AP, "Unknown message received in TASK_CUUP_E1\n"); + break; + } + + result = itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d) in E1AP_CUUP_task!\n", result); + msg = NULL; + + } +} + diff --git a/openair2/E1AP/e1ap.h b/openair2/E1AP/e1ap.h index ef22152648..af1dcae363 100644 --- a/openair2/E1AP/e1ap.h +++ b/openair2/E1AP/e1ap.h @@ -24,11 +24,33 @@ #ifndef __E1AP_H_ #define __E1AP_H_ -#include -#include "common/openairinterface5g_limits.h" -#include +#include "openair2/COMMON/e1ap_messages_types.h" +#include "e1ap_asnc.h" +#include "openair2/E1AP/e1ap_common.h" -#include -#include -#include +int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_handle_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, e1ap_bearer_setup_resp_t *const resp); + +int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, e1ap_bearer_release_cmd_t *const cmd); + +void *E1AP_CUUP_task(void *arg); + +void *E1AP_CUCP_task(void *arg); #endif diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c new file mode 100644 index 0000000000..23a9fcd1ea --- /dev/null +++ b/openair2/E1AP/e1ap_api.c @@ -0,0 +1,195 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include "e1ap_api.h" +#include "UTIL/OSA/osa_defs.h" +#include "nr_pdcp/nr_pdcp_entity.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h" +#include "openair2/RRC/NR/cucp_cuup_if.h" +#include "openair2/RRC/LTE/MESSAGES/asn1_msg.h" +#include "openair3/ocp-gtpu/gtp_itf.h" +#include "e1ap_asnc.h" +#include "e1ap_common.h" +#include "e1ap.h" + +struct NR_DRB_ToAddMod; +static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_setup_t *pdu) { + + for (int i=0; i < pdu->numDRB2Setup; i++) { + DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i; + asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie); + ie->drb_Identity = drb->id; + ie->cnAssociation = CALLOC(1, sizeof(*ie->cnAssociation)); + ie->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + + // sdap_Config + asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config); + sdap_config->pdu_Session = pdu->sessionId; + sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL; + sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL; + sdap_config->defaultDRB = drb->defaultDRB; + + asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); + for (int j=0; j < drb->numQosFlow2Setup; j++) { + asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi); + *qfi = drb->qosFlows[j].fiveQI; + } + sdap_config->mappedQoS_FlowsToRelease = NULL; + + // pdcp_Config + ie->reestablishPDCP = NULL; + ie->recoverPDCP = NULL; + asn1cCalloc(ie->pdcp_Config, pdcp_config); + asn1cCalloc(pdcp_config->drb, drbCfg); + asn1cCallocOne(drbCfg->discardTimer, drb->discardTimer); + asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pDCP_SN_Size_UL); + asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pDCP_SN_Size_DL); + drbCfg->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drbCfg->headerCompression.choice.notUsed = 0; + + drbCfg->integrityProtection = NULL; + drbCfg->statusReportRequired = NULL; + drbCfg->outOfOrderDelivery = NULL; + pdcp_config->moreThanOneRLC = NULL; + + pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); + *pdcp_config->t_Reordering = drb->reorderingTimer; + pdcp_config->ext1 = NULL; + + if (pdu->integrityProtectionIndication == 0 || // Required + pdu->integrityProtectionIndication == 1) { // Preferred + asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + } + + if (pdu->confidentialityProtectionIndication == 0 || // Required + pdu->confidentialityProtectionIndication == 1) { // Preferred + asn1cCalloc(pdcp_config->ext1, ext1); + asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); + } + } +} + +static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req, + gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp, + instance_t instance) { + + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; + + NR_DRB_ToAddModList_t DRB_configList = {0}; + for (int i=0; i < req->numPDUSessions; i++) { + pdu_session_to_setup_t *const pdu = &req->pduSession[i]; + create_tunnel_req.pdusession_id[i] = pdu->sessionId; + create_tunnel_req.incoming_rb_id[i] = pdu->DRBnGRanList[0].id; // taking only the first DRB. TODO:change this + memcpy(&create_tunnel_req.dst_addr[i].buffer, + &pdu->tlAddress, + sizeof(uint8_t)*4); + create_tunnel_req.dst_addr[i].length = 32; // 8bits * 4bytes + create_tunnel_req.outgoing_teid[i] = pdu->teId; + fill_DRB_configList_e1(&DRB_configList, pdu); + } + create_tunnel_req.num_tunnels = req->numPDUSessions; + create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF); + + // Create N3 tunnel + int ret = gtpv1u_create_ngu_tunnel(instance, + &create_tunnel_req, + create_tunnel_resp); + if (ret != 0) { + LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE id %ld\n", + create_tunnel_req.ue_id); + return ret; + } + + // Configure DRBs + uint8_t *kUPenc = NULL; + uint8_t *kUPint = NULL; + + nr_derive_key(UP_ENC_ALG, req->cipheringAlgorithm, (uint8_t *)req->encryptionKey, &kUPenc); + + nr_derive_key(UP_INT_ALG, req->integrityProtectionAlgorithm, (uint8_t *)req->integrityProtectionKey, &kUPint); + + nr_pdcp_e1_add_drbs(true, // set this to notify PDCP that his not UE + create_tunnel_req.ue_id, + &DRB_configList, + (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm, + kUPenc, + kUPint); + return ret; +} + +void process_e1_bearer_context_setup_req(instance_t instance, e1ap_bearer_setup_req_t *const req) +{ + e1ap_upcp_inst_t *inst = getCxtE1(instance); + AssertFatal(inst, ""); + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp_N3={0}; + + // GTP tunnel for UL + drb_config_N3gtpu_create(req, &create_tunnel_resp_N3, inst->gtpInstN3); + + MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP); + e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg); + + in_addr_t my_addr; + if (inet_pton(AF_INET, inst->setupReq.localAddressF1U, &my_addr) != 1) + LOG_E(E1AP, "can't use the F1-U local interface: %s\n", inst->setupReq.localAddressF1U); + fill_e1ap_bearer_setup_resp(resp, req, inst->gtpInstF1U, req->gNB_cu_cp_ue_id, inst->setupReq.remotePortF1U, my_addr); + + resp->gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id; + resp->numPDUSessions = req->numPDUSessions; + for (int i=0; i < req->numPDUSessions; i++) { + pdu_session_setup_t *pduSetup = resp->pduSession + i; + pdu_session_to_setup_t *pdu2Setup = req->pduSession + i; + + pduSetup->id = pdu2Setup->sessionId; + if (inet_pton(AF_INET, inst->setupReq.localAddressN3, &pduSetup->tlAddress) != 1) + LOG_E(E1AP, "can't use the N3 local interface: %s\n", inst->setupReq.localAddressN3); + pduSetup->teId = create_tunnel_resp_N3.gnb_NGu_teid[i]; + pduSetup->numDRBSetup = pdu2Setup->numDRB2Setup; + + // At this point we don't have a way to know the DRBs that failed to setup + // We assume all DRBs to setup have are setup successfully so we always send successful outcome in response + // TODO: Modify nr_pdcp_add_drbs() to return DRB list that failed to setup to support E1AP + pduSetup->numDRBFailed = 0; + } + + e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst, resp); +} + +void CUUP_process_bearer_context_mod_req(instance_t instance, e1ap_bearer_setup_req_t *const req) +{ + e1ap_upcp_inst_t *inst = getCxtE1(instance); + AssertFatal(inst, ""); + // assume we receive modification of F1-U but it is wrong, we can also get modification of N3 when HO will occur + CU_update_UP_DL_tunnel(req, inst->gtpInstF1U, req->gNB_cu_cp_ue_id); + // TODO: send bearer cxt mod response +} + +void CUUP_process_bearer_release_command(instance_t instance, e1ap_bearer_release_cmd_t *const cmd) +{ + e1ap_upcp_inst_t *inst = getCxtE1(instance); + AssertFatal(inst, ""); + newGtpuDeleteAllTunnels(inst->gtpInstN3, cmd->gNB_cu_up_ue_id); + newGtpuDeleteAllTunnels(inst->gtpInstF1U, cmd->gNB_cu_up_ue_id); + e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(inst, cmd); +} diff --git a/openair2/E1AP/e1ap_api.h b/openair2/E1AP/e1ap_api.h new file mode 100644 index 0000000000..1b9f219fcc --- /dev/null +++ b/openair2/E1AP/e1ap_api.h @@ -0,0 +1,35 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef E1AP_API_H +#define E1AP_API_H + +#include "platform_types.h" +#include "openair2/COMMON/e1ap_messages_types.h" +#include "openair2/E1AP/e1ap_common.h" +void cuup_init_n3(instance_t instance); +void process_e1_bearer_context_setup_req(instance_t, e1ap_bearer_setup_req_t *const req); +void CUUP_process_bearer_context_mod_req(instance_t, e1ap_bearer_setup_req_t *const req); + +void CUUP_process_bearer_release_command(instance_t, e1ap_bearer_release_cmd_t *const cmd); +#endif diff --git a/openair2/E1AP/e1ap_asnc.h b/openair2/E1AP/e1ap_asnc.h new file mode 100644 index 0000000000..00dbcc13f3 --- /dev/null +++ b/openair2/E1AP/e1ap_asnc.h @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef E1AP_ASNC_H +#define E1AP_ASNC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c new file mode 100644 index 0000000000..2db1ecef65 --- /dev/null +++ b/openair2/E1AP/e1ap_common.c @@ -0,0 +1,235 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include "e1ap_common.h" +#include "e1ap_default_values.h" +#include "e1ap_asnc.h" +#include "common/openairinterface5g_limits.h" +#include "common/utils/ocp_itti/intertask_interface.h" + +static e1ap_upcp_inst_t *e1ap_inst[NUMBER_OF_gNB_MAX] = {0}; + +e1ap_upcp_inst_t *getCxtE1(instance_t instance) +{ + AssertFatal(instance < sizeofArray(e1ap_inst), "instance exceeds limit\n"); + return e1ap_inst[instance]; +} + +int e1ap_assoc_id(E1_t type, instance_t instance) { + AssertFatal(e1ap_inst[instance] != NULL, "Trying to access uninitiated instance of CUCP\n"); + return e1ap_inst[instance]->setupReq.assoc_id; +} + +void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req) { + AssertFatal(e1ap_inst[instance] == NULL, "Double call to E1 instance %d\n", (int)instance); + e1ap_inst[instance] = calloc(1, sizeof(e1ap_upcp_inst_t)); + e1ap_inst[instance]->type = type; + e1ap_inst[instance]->instance = instance; + if (req) + memcpy(&e1ap_inst[instance]->setupReq, req, sizeof(*req)); + e1ap_inst[instance]->gtpInstN3 = -1; + e1ap_inst[instance]->gtpInstF1U = -1; +} + +E1AP_TransactionID_t transacID[E1AP_MAX_NUM_TRANSAC_IDS] = {0}; + +void e1ap_common_init() { + srand(time(NULL)); +} + +bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx) { + + bool isFreeIdxSet = false; + for (int i=0; i < E1AP_MAX_NUM_TRANSAC_IDS; i++) { + if (id == transacID[i]) + return false; + else if (!isFreeIdxSet && (transacID[i] == 0)) { + *freeIdx = i; + isFreeIdxSet = true; + } + } + + return true; +} + +E1AP_TransactionID_t E1AP_get_next_transaction_identifier() { + E1AP_TransactionID_t genTransacId; + bool isTransacIdValid = false; + int freeIdx; + + while (!isTransacIdValid) { + genTransacId = rand() & 255; + isTransacIdValid = check_transac_id(genTransacId, &freeIdx); + } + + AssertFatal(freeIdx < E1AP_MAX_NUM_TRANSAC_IDS, "Free Index exceeds array length\n"); + transacID[freeIdx] = genTransacId; + return genTransacId; +} + +void E1AP_free_transaction_identifier(E1AP_TransactionID_t id) { + + for (int i=0; i < E1AP_MAX_NUM_TRANSAC_IDS; i++) { + if (id == transacID[i]) { + transacID[i] = 0; + return; + } + } + LOG_E(E1AP, "Couldn't find transaction ID %ld in list\n", id); +} + +int e1ap_decode_initiating_message(E1AP_E1AP_PDU_t *pdu) { + DevAssert(pdu != NULL); + + switch(pdu->choice.initiatingMessage->procedureCode) { + case E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup: + break; + + case E1AP_ProcedureCode_id_gNB_CU_UP_ConfigurationUpdate: + break; + + case E1AP_ProcedureCode_id_bearerContextSetup: + break; + + case E1AP_ProcedureCode_id_bearerContextModification: + break; + + default: + LOG_E(E1AP, "Unsupported procedure code (%d) for initiating message\n", + (int)pdu->choice.initiatingMessage->procedureCode); + return -1; + } + return 0; +} + +int e1ap_decode_successful_outcome(E1AP_E1AP_PDU_t *pdu) { + DevAssert(pdu != NULL); + switch(pdu->choice.successfulOutcome->procedureCode) { + case E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup: + break; + + case E1AP_ProcedureCode_id_bearerContextSetup: + break; + + default: + LOG_E(E1AP, "Unsupported procedure code (%d) for successful message\n", + (int)pdu->choice.successfulOutcome->procedureCode); + return -1; + } + return 0; +} + +int e1ap_decode_unsuccessful_outcome(E1AP_E1AP_PDU_t *pdu) { + DevAssert(pdu != NULL); + switch(pdu->choice.unsuccessfulOutcome->procedureCode) { + case E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup: + break; + + default: + LOG_E(E1AP, "Unsupported procedure code (%d) for unsuccessful message\n", + (int)pdu->choice.unsuccessfulOutcome->procedureCode); + return -1; + } + return 0; +} + +int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length) { + asn_dec_rval_t dec_ret; + DevAssert(buffer != NULL); + dec_ret = aper_decode(NULL, + &asn_DEF_E1AP_E1AP_PDU, + (void **)&pdu, + buffer, + length, + 0, + 0); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + LOG_E(E1AP, "----------------- ASN1 DECODER PRINT START----------------- \n"); + xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, pdu); + LOG_E(E1AP, "----------------- ASN1 DECODER PRINT END ----------------- \n"); + } + + if (dec_ret.code != RC_OK) { + AssertFatal(1==0,"Failed to decode pdu\n"); + return -1; + } + + switch(pdu->present) { + case E1AP_E1AP_PDU_PR_initiatingMessage: + return e1ap_decode_initiating_message(pdu); + + case E1AP_E1AP_PDU_PR_successfulOutcome: + return e1ap_decode_successful_outcome(pdu); + + case E1AP_E1AP_PDU_PR_unsuccessfulOutcome: + return e1ap_decode_unsuccessful_outcome(pdu); + + default: + LOG_E(E1AP, "Unknown presence (%d) or not implemented\n", (int)pdu->present); + break; + } + + return -1; +} + +int e1ap_encode_send(E1_t type, e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func) +{ + DevAssert(pdu != NULL); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + LOG_E(E1AP, "----------------- ASN1 ENCODER PRINT START ----------------- \n"); + xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, pdu); + LOG_E(E1AP, "----------------- ASN1 ENCODER PRINT END----------------- \n"); + } + + char errbuf[2048]; /* Buffer for error message */ + size_t errlen = sizeof(errbuf); /* Size of the buffer */ + int ret = asn_check_constraints(&asn_DEF_E1AP_E1AP_PDU, pdu, errbuf, &errlen); + + if(ret) { + LOG_E(E1AP, "%s: Constraint validation failed: %s\n", func, errbuf); + } + + void *buffer = NULL; + ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_E1AP_E1AP_PDU, 0, pdu, &buffer); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, pdu); + + if (encoded < 0) { + LOG_E(E1AP, "%s: Failed to encode E1AP message\n", func); + return -1; + } else { + MessageDef *message = itti_alloc_new_message((type==CPtype)?TASK_CUCP_E1:TASK_CUUP_E1, 0, SCTP_DATA_REQ); + sctp_data_req_t *s = &message->ittiMsg.sctp_data_req; + s->assoc_id = setupReq->assoc_id; + s->buffer = buffer; + s->buffer_length = encoded; + s->stream = stream; + LOG_I(E1AP, "%s: Sending ITTI message to SCTP Task\n", func); + itti_send_msg_to_task(TASK_SCTP, 0 /*unused by callee*/, message); + } + + return encoded; +} diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h new file mode 100644 index 0000000000..80a2b925e1 --- /dev/null +++ b/openair2/E1AP/e1ap_common.h @@ -0,0 +1,64 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef E1AP_COMMON_H_ +#define E1AP_COMMON_H_ +#include "openair2/COMMON/e1ap_messages_types.h" +#include "e1ap_asnc.h" +#include "openair2/COMMON/sctp_messages_types.h" +#include "common/ngran_types.h" + +typedef struct e1ap_upcp_inst_s { + bool incoming_sock; + instance_t instance; + bool same_process; + E1_t type; + enum sctp_state_e sockState; + uint32_t assoc_id; + instance_t gtpInstN3; + instance_t gtpInstF1U; + e1ap_setup_req_t setupReq; + e1ap_bearer_setup_req_t bearerSetupReq; + e1ap_bearer_setup_resp_t bearerSetupResp; +} e1ap_upcp_inst_t; + +extern int asn1_xer_print; + +int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length); + +e1ap_upcp_inst_t *getCxtE1(instance_t instance); + +E1AP_TransactionID_t E1AP_get_next_transaction_identifier(); + +void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req); + +bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx); + +int e1ap_assoc_id(E1_t type, instance_t instance); + +int e1ap_encode_send(E1_t type, e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func); + +void e1ap_common_init(); + +void E1AP_free_transaction_identifier(E1AP_TransactionID_t id); +#endif /* E1AP_COMMON_H_ */ diff --git a/executables/create_nr_tasks.h b/openair2/E1AP/e1ap_default_values.h similarity index 88% rename from executables/create_nr_tasks.h rename to openair2/E1AP/e1ap_default_values.h index 23dd23e7db..f5980031df 100644 --- a/executables/create_nr_tasks.h +++ b/openair2/E1AP/e1ap_default_values.h @@ -19,11 +19,10 @@ * contact@openairinterface.org */ -#ifndef CREATE_NR_TASKS_H_ -#define CREATE_NR_TASKS_H_ +#ifndef E1AP_DEFAULT_VALUES_H +#define E1AP_DEFAULT_VALUES_H +#define E1AP_PORT_NUMBER (38462) +#define E1AP_SCTP_PPID (64) -int create_gNB_tasks(uint32_t gnb_nb); - - -#endif /* CREATE_TASKS_H_ */ +#endif diff --git a/openair2/E1AP/e1ap_setup.c b/openair2/E1AP/e1ap_setup.c new file mode 100644 index 0000000000..349e3dcab5 --- /dev/null +++ b/openair2/E1AP/e1ap_setup.c @@ -0,0 +1,129 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include "common/utils/LOG/log.h" +#include "common/utils/nr/nr_common.h" +#include "common/utils/LOG/log_extern.h" +#include "assertions.h" +#include "common/utils/ocp_itti/intertask_interface.h" +#include "openair2/GNB_APP/gnb_paramdef.h" +#include "openair3/ocp-gtpu/gtp_itf.h" + +static void get_NGU_S1U_addr(char **addr, uint16_t *port) +{ + int num_gnbs = 0; + char *gnb_ipv4_address_for_NGU = NULL; + uint32_t gnb_port_for_NGU = 0; + char *gnb_ipv4_address_for_S1U = NULL; + uint32_t gnb_port_for_S1U = 0; + char gtpupath[MAX_OPTNAME_SIZE * 2 + 8]; + + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + paramdef_t NETParams[] = GNBNETPARAMS_DESC; + LOG_I(GTPU, "Configuring GTPu\n"); + + /* get number of active eNodeBs */ + config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL); + num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; + AssertFatal(num_gnbs > 0, "Failed to parse config file no active gNodeBs in %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS); + + sprintf(gtpupath, "%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); + config_get(NETParams, sizeof(NETParams) / sizeof(paramdef_t), gtpupath); + char *address; + if (NETParams[1].strptr != NULL) { + LOG_I(GTPU, "SA mode \n"); + address = strdup(gnb_ipv4_address_for_NGU); + *port = gnb_port_for_NGU; + } else { + LOG_I(GTPU, "NSA mode \n"); + address = strdup(gnb_ipv4_address_for_S1U); + *port = gnb_port_for_S1U; + } + if (strchr(address, '/')) + *strchr(address, '/') = 0; + *addr = address; + return; +} + +MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) +{ + MessageDef *msgConfig = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_REQ); + if (!msgConfig) + return NULL; + + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + paramdef_t GNBParams[] = GNBPARAMS_DESC; + paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0}; + config_get(GNBSParams, sizeofArray(GNBSParams), NULL); + char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; + AssertFatal(num_gnbs == 1, "Support only one gNB per process\n"); + + if (num_gnbs > 0) { + config_getlist(&GNBParamList, GNBParams, sizeofArray(GNBParams), NULL); + paramdef_t *gnbParms = GNBParamList.paramarray[0]; + AssertFatal(gnbParms[GNB_GNB_ID_IDX].uptr != NULL, "gNB id %u is not defined in configuration file\n", 0); + e1ap_setup_req_t *e1Setup = &E1AP_SETUP_REQ(msgConfig); + msgConfig->ittiMsgHeader.destinationInstance = 0; + e1Setup->gNB_cu_up_id = *(gnbParms[GNB_GNB_ID_IDX].uptr); + + paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC; + paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0}; + /* map parameter checking array instances to parameter definition array instances */ + checkedparam_t config_check_PLMNParams[] = PLMNPARAMS_CHECK; + + for (int I = 0; I < sizeofArray(PLMNParams); ++I) + PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]); + + config_getlist(&PLMNParamList, PLMNParams, sizeofArray(PLMNParams), aprefix); + int numPLMNs = PLMNParamList.numelt; + e1Setup->supported_plmns = numPLMNs; + + for (int I = 0; I < numPLMNs; I++) { + e1Setup->plmns[I].mcc = *PLMNParamList.paramarray[I][GNB_MOBILE_COUNTRY_CODE_IDX].uptr; + e1Setup->plmns[I].mnc = *PLMNParamList.paramarray[I][GNB_MOBILE_NETWORK_CODE_IDX].uptr; + e1Setup->plmns[I].mnc = *PLMNParamList.paramarray[I][GNB_MNC_DIGIT_LENGTH].u8ptr; + } + + e1Setup->remotePortF1U = *(GNBParamList.paramarray[0][GNB_REMOTE_S_PORTD_IDX].uptr); + e1Setup->localAddressF1U = strdup(*(GNBParamList.paramarray[0][GNB_LOCAL_S_ADDRESS_IDX].strptr)); + e1Setup->localPortF1U = *(GNBParamList.paramarray[0][GNB_LOCAL_S_PORTD_IDX].uptr); + get_NGU_S1U_addr(&e1Setup->localAddressN3, &e1Setup->localPortN3); + e1Setup->remotePortN3 = GTPV1_U_PORT_NUMBER; + + if (separate_CUUP_process) { + paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0}; + paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC; + config_getlist(&GNBE1ParamList, GNBE1Params, sizeofArray(GNBE1Params), aprefix); + paramdef_t *e1Parms = GNBE1ParamList.paramarray[0]; + strcpy(e1Setup->CUCP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUCP].strptr)); + e1Setup->CUCP_e1_ip_address.ipv4 = 1; + strcpy(e1Setup->CUUP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUUP].strptr)); + e1Setup->CUUP_e1_ip_address.ipv4 = 1; + e1Setup->cn_support = *e1Parms[GNB_CONFIG_E1_CN_SUPPORT].uptr; + } + } + return msgConfig; +} diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 98ddaebfdc..9a0ed3f04a 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -40,7 +40,8 @@ # include "intertask_interface.h" # include "s1ap_eNB.h" -#include "sctp_eNB_task.h" +# include "sctp_eNB_task.h" +# include "openair3/ocp-gtpu/gtp_itf.h" # include "x2ap_eNB.h" # include "x2ap_messages_types.h" diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index fbb5fd0225..776c89c02b 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2015,7 +2015,7 @@ int RCconfig_gtpu(void ) { int num_enbs = 0; char *enb_interface_name_for_S1U = NULL; char *enb_ipv4_address_for_S1U = NULL; - uint32_t enb_port_for_S1U = 0; + uint16_t enb_port_for_S1U = 0; char *address = NULL; char *cidr = NULL; char gtpupath[MAX_OPTNAME_SIZE*2 + 8]; diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 1f2ca6392f..647ac96c18 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -1123,12 +1123,13 @@ typedef struct srb1_params_s { /* S1/X2 interface configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*--------------------------------------------------------------------------------------------------------------------------------------------------*/ +// clang-format off #define NETPARAMS_DESC { \ {ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDRESS_FOR_S1_MME, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ - {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, uptr:NULL, defintval:2152L, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, u16ptr:NULL, defuintval:GTPV1_U_PORT_NUMBER, TYPE_UINT16, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_PORT_FOR_X2C, NULL, 0, uptr:NULL, defintval:0L, TYPE_UINT, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_M2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ @@ -1144,8 +1145,10 @@ typedef struct srb1_params_s { #define GTPUPARAMS_DESC { \ {ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U, NULL, 0, strptr:&enb_interface_name_for_S1U, defstrval:"lo", TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U, NULL, 0, strptr:&enb_ipv4_address_for_S1U, defstrval:"127.0.0.1", TYPE_STRING, 0}, \ - {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, uptr:&enb_port_for_S1U, defintval:2152, TYPE_UINT, 0} \ + {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, u16ptr:&enb_port_for_S1U, defuintval:GTPV1_U_PORT_NUMBER, TYPE_UINT16, 0} \ } +// clang-format on + /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/F1AP/dummy_enb.c b/openair2/F1AP/dummy_enb.c index afb4a1048a..942e652213 100644 --- a/openair2/F1AP/dummy_enb.c +++ b/openair2/F1AP/dummy_enb.c @@ -26,12 +26,6 @@ #include "NR_ServingCellConfigCommon.h" #include "NR_MIB.h" -void apply_macrlc_config(gNB_RRC_INST *rrc, - rrc_gNB_ue_context_t *const ue_context_pP, - const protocol_ctxt_t *const ctxt_pP ) { - abort(); -} - bool sdap_data_req(protocol_ctxt_t *ctxt_p, const ue_id_t ue_id, const srb_flag_t srb_flag, diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 39274cdf38..0dfcefaef3 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -144,7 +144,9 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, // LTS: FIXME data model failure: we don't KNOW if we receive a 4G or a 5G cell // Furthermore, cell_type is not a attribute of a cell in the data structure !!!!!!!!!! - if (RC.nrrrc && RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CU) + if (RC.nrrrc && + ( RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CU || + RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CUCP) ) f1ap_req(true, instance)->cell_type=CELL_MACRO_GNB; else f1ap_req(true, instance)->cell_type=CELL_MACRO_ENB; diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index b4e0c1ad2a..09b3651035 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -57,8 +57,11 @@ static void cu_task_handle_sctp_association_ind(instance_t instance, sctp_new_as f1ap_cu_data->sctp_in_streams = sctp_new_association_ind->in_streams; f1ap_cu_data->sctp_out_streams = sctp_new_association_ind->out_streams; f1ap_cu_data->default_sctp_stream_id = 0; - getCxt(CUtype, instance)->gtpInst=cu_task_create_gtpu_instance(IPaddrs); - AssertFatal(getCxt(CUtype, instance)->gtpInst>0,"Failed to create CU F1-U UDP listener"); + if (RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type != ngran_gNB_CUCP) { + getCxt(CUtype, instance)->gtpInst = cu_task_create_gtpu_instance(IPaddrs); + AssertFatal(getCxt(CUtype, instance)->gtpInst > 0, "Failed to create CU F1-U UDP listener"); + } else + LOG_I(F1AP, "In F1AP connection, don't start GTP-U, as we have also E1AP\n"); // Fixme: fully inconsistent instances management // dirty global var is a bad fix CUuniqInstance=getCxt(CUtype, instance)->gtpInst; @@ -120,7 +123,9 @@ void *F1AP_CU_task(void *arg) { eth_params_t *IPaddrs; // Hardcoded instance id! - if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_CU) + if (RC.nrrrc && + (RC.nrrrc[0]->node_type == ngran_gNB_CU || + RC.nrrrc[0]->node_type == ngran_gNB_CUCP ) ) IPaddrs=&RC.nrrrc[0]->eth_params_s; else IPaddrs=&RC.rrc[0]->eth_params_s; @@ -129,71 +134,57 @@ void *F1AP_CU_task(void *arg) { while (1) { itti_receive_msg(TASK_CU_F1, &received_msg); - + LOG_I(F1AP, "CU Task Received %s for instance %ld\n", + ITTI_MSG_NAME(received_msg), ITTI_MSG_DESTINATION_INSTANCE(received_msg)); switch (ITTI_MSG_ID(received_msg)) { case SCTP_NEW_ASSOCIATION_IND: - LOG_I(F1AP, "CU Task Received SCTP_NEW_ASSOCIATION_IND for instance %ld\n", - ITTI_MSG_DESTINATION_INSTANCE(received_msg)); cu_task_handle_sctp_association_ind(ITTI_MSG_ORIGIN_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_ind, IPaddrs); break; case SCTP_NEW_ASSOCIATION_RESP: - LOG_I(F1AP, "CU Task Received SCTP_NEW_ASSOCIATION_RESP for instance %ld\n", - ITTI_MSG_DESTINATION_INSTANCE(received_msg)); cu_task_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_DATA_IND: - LOG_I(F1AP, "CU Task Received SCTP_DATA_IND for Instance %ld\n", - ITTI_MSG_DESTINATION_INSTANCE(received_msg)); cu_task_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; case F1AP_SETUP_RESP: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_SETUP_RESP\n"); CU_send_F1_SETUP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_SETUP_RESP(received_msg)); break; case F1AP_GNB_CU_CONFIGURATION_UPDATE: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_GNB_CU_CONFIGURAITON_UPDATE\n"); - // CU_send_f1setup_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), - // &F1AP_SETUP_RESP(received_msg)); CU_send_gNB_CU_CONFIGURATION_UPDATE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_GNB_CU_CONFIGURATION_UPDATE(received_msg)); break; case F1AP_DL_RRC_MESSAGE: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_DL_RRC_MESSAGE\n"); CU_send_DL_RRC_MESSAGE_TRANSFER(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_DL_RRC_MESSAGE(received_msg)); free(F1AP_DL_RRC_MESSAGE(received_msg).rrc_container); break; case F1AP_UE_CONTEXT_SETUP_REQ: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_UE_CONTEXT_SETUP_REQ\n"); CU_send_UE_CONTEXT_SETUP_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); break; case F1AP_UE_CONTEXT_MODIFICATION_REQ: - LOG_I(F1AP, "CU Task received F1AP_UE_CONTEXT_MODIFICATION_REQ\n"); CU_send_UE_CONTEXT_MODIFICATION_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), - &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); + &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); break; case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_UE_CONTEXT_RELEASE_CMD\n"); CU_send_UE_CONTEXT_RELEASE_COMMAND(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); break; case F1AP_PAGING_IND: - LOG_I(F1AP, "CU Task Received F1AP_PAGING_IND\n"); CU_send_Paging(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_PAGING_IND(received_msg)); break; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 597887b841..d609cb98cb 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -510,6 +510,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { + /*Use a dummy teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU*/ /* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU */ transport_layer_addr_t addr = { length: 32, buffer: { 0 } }; f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid = newGtpuCreateTunnel(getCxt(CUtype, instance)->gtpInst, @@ -1009,7 +1010,7 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, f1ap_remove_ue(CUtype, instance, rnti); return 0; } -//void CU_send_UE_CONTEXT_MODIFICATION_REQUEST(F1AP_UEContextModificationRequest_t *UEContextModificationRequest) { + int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context_setup_t *f1ap_ue_context_modification_req) { F1AP_F1AP_PDU_t pdu= {0}; F1AP_UEContextModificationRequest_t *out; @@ -1477,19 +1478,6 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ for (int j = 0; j < f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { /* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context modification response from the DU */ - transport_layer_addr_t addr = { length: 32, buffer: { 0 } }; - - f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl[j].teid = newGtpuCreateTunnel(getCxt(CUtype, instance)->gtpInst, - f1ap_ue_context_modification_req->rnti, - f1ap_ue_context_modification_req->drbs_to_be_setup[i].drb_id, - f1ap_ue_context_modification_req->drbs_to_be_setup[i].drb_id, - 0xFFFF, // We will set the right value from DU answer - -1, // no qfi - addr, // We will set the right value from DU answer - f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_dl_tnl[0].port, - cu_f1u_data_req, - NULL); - /* 12.3.1 ULTunnels_ToBeSetup_Item */ asn1cSequenceAdd(drbs_toBeSetupMod_item->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; diff --git a/openair2/F1AP/f1ap_decoder.c b/openair2/F1AP/f1ap_decoder.c index 6d1c60c67d..0085add838 100644 --- a/openair2/F1AP/f1ap_decoder.c +++ b/openair2/F1AP/f1ap_decoder.c @@ -166,7 +166,8 @@ static int f1ap_decode_unsuccessful_outcome(F1AP_F1AP_PDU_t *pdu) { int f1ap_decode_pdu(F1AP_F1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length) { asn_dec_rval_t dec_ret; DevAssert(buffer != NULL); - dec_ret = aper_decode(NULL, + asn_codec_ctx_t st={.max_stack_size = 100 * 1000}; + dec_ret = aper_decode(&st, &asn_DEF_F1AP_F1AP_PDU, (void **)&pdu, buffer, diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index ac952e0498..c11316e19b 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -107,18 +107,18 @@ void *F1AP_DU_task(void *arg) { MessageDef *msg = NULL; itti_receive_msg(TASK_DU_F1, &msg); instance_t myInstance=ITTI_MSG_DESTINATION_INSTANCE(msg); - + LOG_I(F1AP, "DU Task Received %s for instance %ld\n", + ITTI_MSG_NAME(msg),myInstance); switch (ITTI_MSG_ID(msg)) { - case F1AP_SETUP_REQ: + case F1AP_SETUP_REQ: { // this is not a true F1 message, but rather an ITTI message sent by enb_app // 1. save the itti msg so that you can use it to sen f1ap_setup_req, fill the f1ap_setup_req message, // 2. store the message in f1ap context, that is also stored in RC // 2. send a sctp_association req - LOG_I(F1AP, "DU Task Received F1AP_SETUP_REQ\n"); - f1ap_setup_req_t *msgSetup=&F1AP_SETUP_REQ(msg); + f1ap_setup_req_t *msgSetup = &F1AP_SETUP_REQ(msg); createF1inst(false, myInstance, msgSetup); - du_task_send_sctp_association_req(myInstance,msgSetup); - break; + du_task_send_sctp_association_req(myInstance, msgSetup); + } break; case F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE: DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MSG_ORIGIN_INSTANCE(msg), @@ -133,32 +133,23 @@ void *F1AP_DU_task(void *arg) { case SCTP_NEW_ASSOCIATION_RESP: // 1. store the respon // 2. send the f1setup_req - LOG_I(F1AP, "DU Task Received SCTP_NEW_ASSOCIATION_RESP\n"); du_task_handle_sctp_association_resp(myInstance, &msg->ittiMsg.sctp_new_association_resp); break; case SCTP_DATA_IND: // ex: any F1 incoming message for DU ends here - LOG_I(F1AP, "DU Task Received SCTP_DATA_IND\n"); du_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind); break; case F1AP_INITIAL_UL_RRC_MESSAGE: // from rrc - LOG_I(F1AP, "DU Task Received F1AP_INITIAL_UL_RRC_MESSAGE\n"); + { f1ap_initial_ul_rrc_message_t *msgRrc = &F1AP_INITIAL_UL_RRC_MESSAGE(msg); - DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(0,0,0,msgRrc->crnti, - msgRrc->rrc_container, - msgRrc->rrc_container_length, - msgRrc->du2cu_rrc_container, - msgRrc->du2cu_rrc_container_length - ); - break; + DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(0, 0, 0, msgRrc->crnti, msgRrc->rrc_container, msgRrc->rrc_container_length, msgRrc->du2cu_rrc_container, msgRrc->du2cu_rrc_container_length); + } break; case F1AP_UL_RRC_MESSAGE: // to rrc - LOG_D(F1AP, "DU Task Received F1AP_UL_RRC_MESSAGE\n"); - if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_DU) { DU_send_UL_NR_RRC_MESSAGE_TRANSFER(myInstance, &F1AP_UL_RRC_MESSAGE(msg)); @@ -174,12 +165,10 @@ void *F1AP_DU_task(void *arg) { break; case F1AP_UE_CONTEXT_MODIFICATION_RESP: - LOG_I(F1AP, "DU task received itti message from RRC for F1AP_UE_CONTEXT_MODIFICATION_RESP message generation \n"); DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(myInstance, &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg)); break; case F1AP_UE_CONTEXT_RELEASE_REQ: // from MAC - LOG_I(F1AP, "DU Task Received F1AP_UE_CONTEXT_RELEASE_REQ\n"); DU_send_UE_CONTEXT_RELEASE_REQUEST(myInstance, &F1AP_UE_CONTEXT_RELEASE_REQ(msg)); break; diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 4be90a9c15..23ab58c6ed 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -1078,7 +1078,7 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, static instance_t du_create_gtpu_instance_to_cu(char *CUaddr, uint16_t CUport, char *DUaddr, uint16_t DUport) { - openAddr_t tmp={0}; + openAddr_t tmp = {0}; strncpy(tmp.originHost, DUaddr, sizeof(tmp.originHost)-1); strncpy(tmp.destinationHost, CUaddr, sizeof(tmp.destinationHost)-1); sprintf(tmp.originService, "%d", DUport); diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 862cf9dddc..680b566eec 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -35,7 +35,6 @@ #include #include "gnb_app.h" -#include "gnb_config.h" #include "assertions.h" #include "common/ran_context.h" @@ -52,6 +51,8 @@ #include "nfapi/oai_integration/vendor_ext.h" #include #include "openair2/LAYER2/PDCP_v10.1.0/pdcp.h" +#include "openair2/E1AP/e1ap.h" +#include "gnb_config.h" extern unsigned char NB_gNB_INST; extern RAN_CONTEXT_t RC; @@ -59,7 +60,7 @@ extern RAN_CONTEXT_t RC; #define GNB_REGISTER_RETRY_DELAY 10 /*------------------------------------------------------------------------------*/ -static void configure_nr_rrc(uint32_t gnb_id) +void configure_nr_rrc(uint32_t gnb_id) { MessageDef *msg_p = NULL; // int CC_id; @@ -80,7 +81,7 @@ static void configure_nr_rrc(uint32_t gnb_id) /*------------------------------------------------------------------------------*/ -static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, const Enb_properties_array_t *enb_properties) +uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, const Enb_properties_array_t *enb_properties) { uint32_t gnb_id; MessageDef *msg_p; @@ -102,7 +103,6 @@ static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, itti_send_msg_to_task (TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p); } - if (gnb_id == 0) RCconfig_nr_gtpu(); } LOG_I(GNB_APP,"[gNB %d] gNB_app_register for instance %d\n", gnb_id, GNB_MODULE_ID_TO_INSTANCE(gnb_id)); @@ -115,7 +115,7 @@ static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, /*------------------------------------------------------------------------------*/ -static uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) { +uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) { uint32_t gnb_id; MessageDef *msg_p; uint32_t register_gnb_x2_pending = 0; @@ -138,10 +138,6 @@ static uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) void *gNB_app_task(void *args_p) { - uint32_t gnb_nb = RC.nb_nr_inst; - uint32_t gnb_id_start = 0; - uint32_t gnb_id_end = gnb_id_start + gnb_nb; - uint32_t gnb_id; MessageDef *msg_p = NULL; const char *msg_name = NULL; instance_t instance; @@ -151,60 +147,35 @@ void *gNB_app_task(void *args_p) int cell_to_activate = 0; itti_mark_task_ready (TASK_GNB_APP); + ngran_node_t node_type = get_node_type(); - LOG_I(PHY, "%s() Task ready initialize structures\n", __FUNCTION__); - - RCconfig_NR_L1(); - RCconfig_nr_prs(); - - if (RC.nb_nr_macrlc_inst>0) RCconfig_nr_macrlc(); - - LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst); - - if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n"); - - AssertFatal (gnb_nb <= RC.nb_nr_inst, - "Number of gNB is greater than gNB defined in configuration file (%d/%d)!", - gnb_nb, RC.nb_nr_inst); - - LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst); - - RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *)); - LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc); - for (gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) { - RC.nrrrc[gnb_id] = (gNB_RRC_INST*)calloc(1,sizeof(gNB_RRC_INST)); - LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, gnb_id_end); - configure_nr_rrc(gnb_id); - } - - if (RC.nb_nr_inst > 0 && !get_softmodem_params()->nsa) { - init_pdcp(); - } - - if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(RC.rrc[0]->node_type) - LOG_I(X2AP, "X2AP enabled \n"); - __attribute__((unused)) uint32_t x2_register_gnb_pending = gNB_app_register_x2 (gnb_id_start, gnb_id_end); - } - - /* For the CU case the gNB registration with the AMF might have to take place after the F1 setup, as the PLMN info - * can originate from the DU. Add check on whether x2ap is enabled to account for ENDC NSA scenario.*/ - if ((get_softmodem_params()->sa || is_x2ap_enabled()) && !NODE_IS_DU(RC.nrrrc[0]->node_type) ) { //&& !NODE_IS_CU(RC.nrrrc[0]->node_type)) { - /* Try to register each gNB */ - //registered_gnb = 0; - __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); - } - if (RC.nb_nr_inst > 0) { - if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + if (node_type == ngran_gNB_CUCP || + node_type == ngran_gNB_CU || + node_type == ngran_eNB_CU || + node_type == ngran_ng_eNB_CU) { if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { - LOG_E(F1AP, "Create task for F1AP CU failed\n"); - AssertFatal(1==0,"exiting"); + LOG_E(F1AP, "Create task for F1AP CU failed\n"); + AssertFatal(1==0,"exiting"); } } - if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { + if (node_type == ngran_gNB_CUCP) { + if (itti_create_task(TASK_CUCP_E1, E1AP_CUCP_task, NULL) < 0) + AssertFatal(false, "Create task for E1AP CP failed\n"); + MessageDef *msg = RCconfig_NR_CU_E1(true); + if (msg) + itti_send_msg_to_task(TASK_CUCP_E1, 0, msg); + else + AssertFatal(false, "Send inti to task for E1AP CP failed\n"); + } + if (node_type == ngran_gNB_CUUP) { + AssertFatal(false, "To run CU-UP use executable nr-cuup\n"); + } + + if (NODE_IS_DU(node_type)) { if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) { LOG_E(F1AP, "Create task for F1AP DU failed\n"); AssertFatal(1==0,"exiting"); @@ -213,7 +184,7 @@ void *gNB_app_task(void *args_p) LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_SETUP_REQ); RCconfig_NR_DU_F1(msg_p, 0); - + itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); } } @@ -279,7 +250,7 @@ void *gNB_app_task(void *args_p) break; case F1AP_SETUP_RESP: - AssertFatal(NODE_IS_DU(RC.nrrrc[0]->node_type), "Should not have received F1AP_SETUP_RESP in CU/gNB\n"); + AssertFatal(NODE_IS_DU(node_type), "Should not have received F1AP_SETUP_RESP in CU/gNB\n"); LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p), F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate); @@ -289,7 +260,7 @@ void *gNB_app_task(void *args_p) break; case F1AP_GNB_CU_CONFIGURATION_UPDATE: - AssertFatal(NODE_IS_DU(RC.nrrrc[0]->node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n"); + AssertFatal(NODE_IS_DU(node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n"); LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p), F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).gNB_CU_name,F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate); diff --git a/openair2/GNB_APP/gnb_app.h b/openair2/GNB_APP/gnb_app.h index b0b422aae1..44c4374fc3 100644 --- a/openair2/GNB_APP/gnb_app.h +++ b/openair2/GNB_APP/gnb_app.h @@ -33,6 +33,7 @@ #include void *gNB_app_task(void *args_p); - - +void configure_nr_rrc(uint32_t gnb_id); +uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end); +uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end); #endif /* GNB_APP_H_ */ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index e4a855acda..dd4cb32bd7 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -91,8 +91,6 @@ extern uint16_t sf_ahead; int macrlc_has_f1 = 0; -static ngran_node_t get_node_type(void); - extern int config_check_band_frequencies(int ind, int16_t band, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint32_t frame_type); @@ -1154,7 +1152,8 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { printf("NRRRC %d: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr)); - if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) { + rrc->node_type = get_node_type(); + if (NODE_IS_CU(rrc->node_type)) { paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC; char aprefix[MAX_OPTNAME_SIZE*2 + 8]; sprintf(aprefix,"%s.[%u].%s",GNB_CONFIG_STRING_GNB_LIST,i,GNB_CONFIG_STRING_SCTP_CONFIG); @@ -1171,21 +1170,12 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { rrc->eth_params_s.my_portd = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTD_IDX].uptr); rrc->eth_params_s.remote_portd = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTD_IDX].uptr); rrc->eth_params_s.transp_preference = ETH_UDP_MODE; - rrc->node_type = ngran_gNB_CU; rrc->sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); rrc->sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); - } else { - // set to ngran_gNB for now, it will get set to ngran_gNB_DU if macrlc entity which uses F1 is present - // Note: we will have to handle the case of ngran_ng_gNB_DU - if (macrlc_has_f1 == 0) { - rrc->node_type = ngran_gNB; - LOG_I(NR_RRC,"Setting node_type to ngran_gNB\n"); - } else { - rrc->node_type = ngran_gNB_DU; - LOG_I(NR_RRC,"Setting node_type to ngran_gNB_DU\n"); - } } + + rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr); rrc->um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr); @@ -1282,55 +1272,6 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { config_security(rrc); }//End RCconfig_NRRRC function -int RCconfig_nr_gtpu(void ) { - - int num_gnbs = 0; - char* gnb_ipv4_address_for_NGU = NULL; - uint32_t gnb_port_for_NGU = 0; - char* gnb_ipv4_address_for_S1U = NULL; - uint32_t gnb_port_for_S1U = 0; - char gtpupath[MAX_OPTNAME_SIZE*2 + 8]; - - paramdef_t GNBSParams[] = GNBSPARAMS_DESC; - paramdef_t NETParams[] = GNBNETPARAMS_DESC; - LOG_I(GTPU,"Configuring GTPu\n"); - -/* get number of active eNodeBs */ - config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); - num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; - AssertFatal (num_gnbs >0, - "Failed to parse config file no active gNodeBs in %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS); - - sprintf(gtpupath,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); - config_get(NETParams,sizeof(NETParams)/sizeof(paramdef_t),gtpupath); - char *cidr=NULL, *address = NULL; - int port; - if (NETParams[1].strptr != NULL) { - LOG_I(GTPU, "SA mode \n"); - address = strtok_r(gnb_ipv4_address_for_NGU, "/", &cidr); - port=gnb_port_for_NGU; - } else { - LOG_I(GTPU, "NSA mode \n"); - address = strtok_r(gnb_ipv4_address_for_S1U, "/", &cidr); - port=gnb_port_for_S1U; - } - - if (address) { - MessageDef *message; - message = itti_alloc_new_message(TASK_GNB_APP, 0, GTPV1U_REQ); - AssertFatal(message!=NULL,""); - IPV4_STR_ADDR_TO_INT_NWBO (address, GTPV1U_REQ(message).localAddr, "BAD IP ADDRESS FORMAT FOR gNB NG_U !\n" ); - LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_REQ(message).localAddr); - GTPV1U_REQ(message).localPort = port; - strcpy(GTPV1U_REQ(message).localAddrStr,address); - sprintf(GTPV1U_REQ(message).localPortStr,"%d", port); - itti_send_msg_to_task (TASK_GTPV1_U, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id) - } else - LOG_E(GTPU,"invalid address for NGU or S1U\n"); - -return 0; -} - int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) { int j,k = 0; @@ -1957,8 +1898,8 @@ int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i) { f1Setup->mib_length[k] = rrc->carrier.sizeof_MIB; NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; - - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + asn_codec_ctx_t st={100*1000}; + asn_dec_rval_t dec_rval = uper_decode_complete( &st, &asn_DEF_NR_BCCH_DL_SCH_Message, (void **)&bcch_message, (const void *)rrc->carrier.SIB1, @@ -2252,16 +2193,24 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up return(ret); } -static ngran_node_t get_node_type(void) +ngran_node_t get_node_type(void) { paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC; paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0}; paramdef_t GNBParams[] = GNBPARAMS_DESC; paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; + paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC; + paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0}; + config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); + + if (GNBParamList.numelt == 0) // We have no valid configuration, let's return a default + return ngran_gNB; + config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL); - config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); - + char aprefix[MAX_OPTNAME_SIZE*2 + 8]; + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + config_getlist( &GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), aprefix); if ( MacRLC_ParamList.numelt > 0) { RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; for (int j = 0; j < RC.nb_nr_macrlc_inst; j++) { @@ -2271,9 +2220,16 @@ static ngran_node_t get_node_type(void) } } - if (strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) - return ngran_gNB_CU; - else if (macrlc_has_f1 == 0) + if (strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) { + if ( GNBE1ParamList.paramarray == NULL || GNBE1ParamList.numelt == 0 ) + return ngran_gNB_CU; + else if (strcmp(*(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_CU_TYPE_IDX].strptr), "cp") == 0) + return ngran_gNB_CUCP; + else if (strcmp(*(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_CU_TYPE_IDX].strptr), "up") == 0) + return ngran_gNB_CUUP; + else + return ngran_gNB_CU; + } else if (macrlc_has_f1 == 0) return ngran_gNB; else return ngran_gNB_DU; @@ -2309,9 +2265,7 @@ void nr_read_config_and_init(void) { RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]); } - if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + if (NODE_IS_CU(RC.nrrrc[0]->node_type) && RC.nrrrc[0]->node_type != ngran_gNB_CUCP) { pdcp_layer_init(); -// nr_DRB_preconfiguration(0x1234); - rrc_init_nr_global_param(); } } diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index b2a9ece078..3089753cff 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -41,6 +41,7 @@ #include "s1ap_messages_types.h" #include "ngap_messages_types.h" #include "f1ap_messages_types.h" +#include "e1ap_messages_types.h" #include "rrc_messages_types.h" #include "intertask_interface.h" @@ -94,7 +95,6 @@ extern void NRRCconfig_RU(void); extern void RCconfig_nr_prs(void); extern void RCconfig_NR_L1(void); extern void RCconfig_nr_macrlc(void); -extern int RCconfig_nr_gtpu(void ); extern void NRRCConfig(void); //void enb_config_display(void); @@ -107,6 +107,8 @@ int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i); int gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp); int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update); void nr_read_config_and_init(void); +MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process); +ngran_node_t get_node_type(void); #endif /* GNB_CONFIG_H_ */ /** @} */ diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index bf5e9f9660..8b62b7720b 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -34,6 +34,7 @@ #define __GNB_APP_GNB_PARAMDEF__H__ #include "common/config/config_paramdesc.h" +#include "common/ngran_types.h" #include "RRC_nr_paramsvalues.h" @@ -369,6 +370,27 @@ typedef enum { /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* E1 configuration section */ +#define GNB_CONFIG_STRING_E1_PARAMETERS "E1_INTERFACE" + +#define GNB_CONFIG_E1_CU_TYPE_IDX 0 +#define GNB_CONFIG_E1_IPV4_ADDRESS_CUCP 1 +#define GNB_CONFIG_E1_IPV4_ADDRESS_CUUP 2 +#define GNB_CONFIG_E1_CN_SUPPORT 3 + +#define GNB_CONFIG_STRING_E1_CU_TYPE "type" +#define GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUCP "ipv4_cucp" +#define GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUUP "ipv4_cuup" +#define GNB_CONFIG_STRING_E1_CN_SUPPORT "cn_support" + +// clang-format off +#define GNBE1PARAMS_DESC { \ + {GNB_CONFIG_STRING_E1_CU_TYPE, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUCP, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUUP, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_CN_SUPPORT, NULL, 0, uptr :NULL, defintval:1L, TYPE_UINT, 0} \ + } +// clang-format on /* L1 configuration section names */ #define CONFIG_STRING_L1_LIST "L1s" #define CONFIG_STRING_L1_CONFIG "l1_config" diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index af94ef3ae0..abb6ba0ec3 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -664,8 +664,6 @@ int remove_ue_list(UE_list_t *listP, int UE_id); void dump_ue_list(UE_list_t *listP); void init_ue_list(UE_list_t *listP); int UE_num_active_CC(UE_info_t *listP, int ue_idP); -int UE_PCCID(module_id_t mod_idP, int ue_idP); -rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP); uint8_t find_rb_table_index(uint8_t average_rbs); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 6d592b797f..e9d41986c5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -249,14 +249,11 @@ void mac_top_init_gNB(ngran_node_t node_type) AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n"); // These should be out of here later - pdcp_layer_init(); + if (get_softmodem_params()->usim_test == 0 ) pdcp_layer_init(); if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) nr_DRB_preconfiguration(0x1234); - rrc_init_nr_global_param(); - - } else { RC.nrmac = NULL; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c new file mode 100644 index 0000000000..9a584a3b27 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c @@ -0,0 +1,59 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include "nr_pdcp_e1_api.h" + +void e1_add_drb(int is_gnb, + uint64_t ue_id, + struct NR_DRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) +{ + add_drb_am(is_gnb, ue_id, s, ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); + LOG_I(PDCP, "%s:%s:%d: added DRB for UE ID %ld\n", __FILE__, __FUNCTION__, __LINE__, ue_id); +} + +void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag, + uint64_t ue_id, + NR_DRB_ToAddModList_t *const drb2add_list, + const uint8_t security_modeP, + uint8_t *const kUPenc, + uint8_t *const kUPint) { + + if (drb2add_list != NULL) { + for (int i = 0; i < drb2add_list->list.count; i++) { + e1_add_drb(enb_flag, ue_id, drb2add_list->list.array[i], + security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, + kUPenc, kUPint); + } + } else + LOG_W(PDCP, "%s with void list\n", __FUNCTION__); + if (kUPenc) + free(kUPenc); + if (kUPint) + free(kUPint); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h new file mode 100644 index 0000000000..a4b44fb74a --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h @@ -0,0 +1,53 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include "common/utils/oai_asn1.h" +#include "NR_RadioBearerConfig.h" + +#include "pdcp.h" +#include "LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include +#include "openair2/SDAP/nr_sdap/nr_sdap.h" + +void e1_add_drb(int is_gnb, + uint64_t ue_id, + struct NR_DRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key); + +void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag, + uint64_t ue_id, + NR_DRB_ToAddModList_t *const drb2add_list, + const uint8_t security_modeP, + uint8_t *const kUPenc, + uint8_t *const kUPint); + +void add_drb_am(int is_gnb, ue_id_t rntiMaybeUEid, struct NR_DRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key); + diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index fd1430420c..190757d74c 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -38,6 +38,8 @@ #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include #include "openair2/SDAP/nr_sdap/nr_sdap.h" +#include "nr_pdcp_e1_api.h" +#include "gnb_config.h" #include "executables/softmodem-common.h" #define TODO do { \ @@ -56,10 +58,11 @@ static int nr_pdcp_current_time_last_subframe; hash_table_t *pdcp_coll_p; static uint64_t pdcp_optmask; -ngran_node_t node_type = ngran_gNB; uint8_t first_dcch = 0; uint8_t proto_agent_flag = 0; +static ngran_node_t node_type; + /****************************************************************************/ /* rlc_data_req queue - begin */ /****************************************************************************/ @@ -524,6 +527,10 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) return 0; } +static void set_node_type() { + node_type = get_node_type(); +} + void pdcp_layer_init(void) { /* hack: be sure to initialize only once */ @@ -539,7 +546,9 @@ void pdcp_layer_init(void) nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1); - if ((RC.nrrrc == NULL) || (!NODE_IS_CU(RC.nrrrc[0]->node_type))) { + set_node_type(); + + if ((RC.nrrrc == NULL) || (!NODE_IS_CU(node_type))) { init_nr_rlc_data_req_queue(); } @@ -667,7 +676,7 @@ rb_found: ctxt.brOption = 0; ctxt.rntiMaybeUEid = ue->rntiMaybeUEid; - if (RC.nrrrc != NULL && NODE_IS_CU(RC.nrrrc[0]->node_type)) { + if (NODE_IS_CU(node_type)) { MessageDef *message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0, GTPV1U_TUNNEL_DATA_REQ, sizeof(gtpv1u_tunnel_data_req_t) @@ -688,7 +697,6 @@ rb_found: extern instance_t CUuniqInstance; itti_send_msg_to_task(TASK_GTPV1_U, CUuniqInstance, message_p); } else { - memblock = get_free_mem_block(size, __FUNCTION__); memcpy(memblock->data, buf, size); LOG_D(PDCP, "%s(): (drb %d) calling rlc_data_req size %d\n", __func__, rb_id, size); @@ -764,7 +772,7 @@ srb_found: LOG_D(PDCP, "%s(): (srb %d) calling rlc_data_req size %d\n", __func__, srb_id, size); //for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]); //printf("\n"); - if ((RC.nrrrc == NULL) || (!NODE_IS_CU(RC.nrrrc[0]->node_type))) { + if ((RC.nrrrc == NULL) || (!NODE_IS_CU(node_type))) { if (entity->is_gnb) { f1ap_dl_rrc_message_t dl_rrc = {.old_gNB_DU_ue_id = 0xFFFFFF, .rrc_container = (uint8_t *)buf, .rrc_container_length = size, .rnti = ue->rntiMaybeUEid, .srb_id = DCCH}; gNB_RRC_INST *rrc = RC.nrrrc[0]; @@ -1056,35 +1064,30 @@ void nr_DRB_preconfiguration(ue_id_t crntiMaybeUEid) drb_ToAddMod->reestablishPDCP = NULL; drb_ToAddMod->recoverPDCP = NULL; drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); - drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); - drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); - *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity; - drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); - *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; - drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); - *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; - drb_ToAddMod->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - drb_ToAddMod->pdcp_Config->drb->headerCompression.choice.notUsed = 0; + asn1cCalloc(drb_ToAddMod->pdcp_Config->drb, drb); + asn1cCallocOne(drb->discardTimer, NR_PDCP_Config__drb__discardTimer_infinity); + asn1cCallocOne(drb->pdcp_SN_SizeUL, NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits); + asn1cCallocOne(drb->pdcp_SN_SizeDL, NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits); + drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drb->headerCompression.choice.notUsed = 0; - drb_ToAddMod->pdcp_Config->drb->integrityProtection=NULL; - drb_ToAddMod->pdcp_Config->drb->statusReportRequired=NULL; - drb_ToAddMod->pdcp_Config->drb->outOfOrderDelivery=NULL; + drb->integrityProtection = NULL; + drb->statusReportRequired = NULL; + drb->outOfOrderDelivery = NULL; drb_ToAddMod->pdcp_Config->moreThanOneRLC = NULL; - drb_ToAddMod->pdcp_Config->t_Reordering = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->t_Reordering)); - *drb_ToAddMod->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; + asn1cCallocOne(drb_ToAddMod->pdcp_Config->t_Reordering, NR_PDCP_Config__t_Reordering_ms0); drb_ToAddMod->pdcp_Config->ext1 = NULL; asn1cSeqAdd(&rbconfig->drb_ToAddModList->list,drb_ToAddMod); rbconfig->drb_ToReleaseList = NULL; - rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig)); - rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig)); - rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; - rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL; - rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse)); - *rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; + asn1cCalloc(rbconfig->securityConfig, secConf); + asn1cCalloc(secConf->securityAlgorithmConfig, secConfAlgo); + secConfAlgo->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; + secConfAlgo->integrityProtAlgorithm = NULL; + asn1cCallocOne(secConf->keyToUse, NR_SecurityConfig__keyToUse_master); if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); @@ -1108,11 +1111,7 @@ void nr_DRB_preconfiguration(ue_id_t crntiMaybeUEid) nr_pdcp_add_drbs(ctxt.enb_flag, ctxt.rntiMaybeUEid, rbconfig->drb_ToAddModList, 0, NULL, NULL, Rlc_Bearer_ToAdd_list); - nr_rrc_rlc_config_asn1_req (&ctxt, - (NR_SRB_ToAddModList_t *) NULL, - rbconfig->drb_ToAddModList, - rbconfig->drb_ToReleaseList, - Rlc_Bearer_ToAdd_list); + nr_rrc_rlc_config_asn1_req(&ctxt, (NR_SRB_ToAddModList_t *)NULL, rbconfig->drb_ToAddModList, rbconfig->drb_ToReleaseList, Rlc_Bearer_ToAdd_list); LOG_D(PDCP, "%s:%d: done RRC PDCP/RLC ASN1 request for UE ID/RNTI %ld\n", __FUNCTION__, __LINE__, ctxt.rntiMaybeUEid); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 29aab4ab5a..60c002537a 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -985,6 +985,7 @@ rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt if(rlc_bearer2add_list->list.array[j]->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity){ if(srb2add_listP->list.array[i]->srb_Identity == rlc_bearer2add_list->list.array[j]->servedRadioBearer->choice.srb_Identity){ add_rlc_srb(rnti, srb2add_listP->list.array[i], rlc_bearer2add_list->list.array[j]); + LOG_D(RLC, "Add srb %ld\n", srb2add_listP->list.array[i]->srb_Identity); } } } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h index 92d20d1aca..c7e42a0a0d 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h @@ -28,6 +28,7 @@ typedef void nr_rlc_ue_manager_t; typedef struct nr_rlc_ue_t { int rnti; + ue_id_t ue_id; nr_rlc_entity_t *srb0; nr_rlc_entity_t *srb[3]; nr_rlc_entity_t *drb[MAX_DRBS_PER_UE]; diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c index 37b461e819..e626a09a98 100644 --- a/openair2/MCE_APP/mce_app.c +++ b/openair2/MCE_APP/mce_app.c @@ -40,7 +40,8 @@ # include "intertask_interface.h" # include "s1ap_eNB.h" -#include "sctp_eNB_task.h" +# include "sctp_eNB_task.h" +# include "openair3/ocp-gtpu/gtp_itf.h" # include "x2ap_eNB.h" # include "x2ap_messages_types.h" diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index b4f7eece01..171e69ea59 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -5629,6 +5629,7 @@ rrc_eNB_generate_RRCConnectionSetup( case ngran_eNB_CU : case ngran_ng_eNB_CU : case ngran_gNB_CU : + case ngran_gNB_CUCP : // create an ITTI message /* TODO: F1 IDs ar missing in RRC */ message_p = itti_alloc_new_message (TASK_RRC_ENB, 0, F1AP_DL_RRC_MESSAGE); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 299e0acaa9..8dbc078c2c 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -295,11 +295,6 @@ uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) { 24); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); - - if (enc_rval.encoded==-1) { - return(-1); - } - return((enc_rval.encoded+7)/8); } @@ -638,11 +633,6 @@ uint8_t do_SIB23_NR(rrc_gNB_carrier_data_t *carrier, 100); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); - - if (enc_rval.encoded==-1) { - return(-1); - } - return((enc_rval.encoded+7)/8); } @@ -690,11 +680,8 @@ int do_RRCReject(uint8_t Mod_id, buffer, 100); - if(enc_rval.encoded == -1) { - LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); LOG_D(NR_RRC,"RRCReject Encoded %zd bits (%zd bytes)\n", enc_rval.encoded,(enc_rval.encoded+7)/8); @@ -1297,13 +1284,11 @@ int do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP, (void *)&dl_ccch_msg, buffer, 1000); + - if(enc_rval.encoded == -1) { - LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } - + LOG_D(NR_RRC,"RRCSetup Encoded %zd bits (%zd bytes)\n", enc_rval.encoded,(enc_rval.encoded+7)/8); return((enc_rval.encoded+7)/8); @@ -1346,19 +1331,11 @@ uint8_t do_NR_SecurityModeCommand( buffer, 100); - if(enc_rval.encoded == -1) { - LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + AssertFatal(enc_rval.encoded >0 , "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); LOG_D(NR_RRC, "[gNB %d] securityModeCommand for UE %lx Encoded %zd bits (%zd bytes)\n", ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid, enc_rval.encoded, (enc_rval.encoded + 7) / 8); - if (enc_rval.encoded==-1) { - LOG_E(NR_RRC, "[gNB %d] ASN1 : securityModeCommand encoding failed for UE %lx\n", ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid); - return(-1); - } - // rrc_ue_process_ueCapabilityEnquiry(0,1000,&dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry,0); // exit(-1); return((enc_rval.encoded+7)/8); @@ -1411,6 +1388,9 @@ uint8_t do_NR_SA_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, (void *)sa_band_filter, req_freq_buf, 1024); + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_UE_CapabilityRequestFilterNR, (void *)sa_band_filter); @@ -1435,19 +1415,11 @@ uint8_t do_NR_SA_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, buffer, 100); - if(enc_rval.encoded == -1) { - LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } - + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(NR_RRC, "[gNB %d] NR UECapabilityRequest for UE %lx Encoded %zd bits (%zd bytes)\n", ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid, enc_rval.encoded, (enc_rval.encoded + 7) / 8); - if (enc_rval.encoded==-1) { - LOG_E(NR_RRC, "[gNB %d] ASN1 : NR UECapabilityRequest encoding failed for UE %lx\n", ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid); - return(-1); - } - return((enc_rval.encoded+7)/8); } @@ -1480,11 +1452,8 @@ uint8_t do_NR_RRCRelease(uint8_t *buffer, (void *)&dl_dcch_msg, buffer, buffer_size); - if(enc_rval.encoded == -1) { - LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); return((enc_rval.encoded+7)/8); } @@ -1508,19 +1477,18 @@ int16_t do_RRCReconfiguration( NR_CellGroupConfig_t *cellGroupConfig) //------------------------------------------------------------------------------ { - NR_DL_DCCH_Message_t dl_dcch_msg; + NR_DL_DCCH_Message_t dl_dcch_msg={0}; asn_enc_rval_t enc_rval; NR_RRCReconfiguration_IEs_t *ie; unsigned char masterCellGroup_buf[1000]; - memset(&dl_dcch_msg, 0, sizeof(NR_DL_DCCH_Message_t)); dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; - dl_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_DL_DCCH_MessageType__c1)); - dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + asn1cCalloc(dl_dcch_msg.message.choice.c1, c1);// = CALLOC(1, sizeof(struct NR_DL_DCCH_MessageType__c1)); + c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; - dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration = calloc(1, sizeof(NR_RRCReconfiguration_t)); - dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->rrc_TransactionIdentifier = Transaction_id; - dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; + asn1cCalloc(c1->choice.rrcReconfiguration, rrcReconf); // = calloc(1, sizeof(NR_RRCReconfiguration_t)); + rrcReconf->rrc_TransactionIdentifier = Transaction_id; + rrcReconf->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; /******************** Radio Bearer Config ********************/ /* Configure Security */ @@ -1532,7 +1500,8 @@ int16_t do_RRCReconfiguration( // *security_config->keyToUse = NR_SecurityConfig__keyToUse_master; ie = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t)); - if (SRB_configList || DRB_configList) { + if ((SRB_configList && SRB_configList->list.size) || + (DRB_configList && DRB_configList->list.size)) { ie->radioBearerConfig = calloc(1, sizeof(NR_RadioBearerConfig_t)); ie->radioBearerConfig->srb_ToAddModList = SRB_configList; ie->radioBearerConfig->drb_ToAddModList = DRB_configList; @@ -1561,42 +1530,42 @@ int16_t do_RRCReconfiguration( configuration); enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, - NULL, - (void *)cellGroupConfig, - masterCellGroup_buf, - 1000); - if(enc_rval.encoded == -1) { - LOG_E(NR_RRC, "ASN1 message CellGroupConfig encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + NULL, + (void *)cellGroupConfig, + masterCellGroup_buf, + 1000); + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); } ie->nonCriticalExtension->masterCellGroup = calloc(1,sizeof(OCTET_STRING_t)); - + ie->nonCriticalExtension->masterCellGroup->buf = masterCellGroup_buf; ie->nonCriticalExtension->masterCellGroup->size = (enc_rval.encoded+7)/8; } - + dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie; - + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg); } - + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, - NULL, - (void *)&dl_dcch_msg, - buffer, - buffer_size); - - if(enc_rval.encoded == -1) { - LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } - + NULL, + (void *)&dl_dcch_msg, + buffer, + buffer_size); + + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + LOG_D(NR_RRC,"[gNB %d] RRCReconfiguration for UE %lx Encoded %zd bits (%zd bytes)\n", + ctxt_pP->module_id, + ctxt_pP->rntiMaybeUEid, + enc_rval.encoded, + (enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); } @@ -1731,9 +1700,9 @@ uint8_t do_RRCSetupComplete(uint8_t Mod_id, uint8_t *buffer, size_t buffer_size, NR_UL_DCCH_Message_t ul_dcch_msg; NR_RRCSetupComplete_t *RrcSetupComplete; memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); - + uint8_t buf[6]; - + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; ul_dcch_msg.message.choice.c1 = CALLOC(1,sizeof(struct NR_UL_DCCH_MessageType__c1)); ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_rrcSetupComplete; @@ -1746,7 +1715,7 @@ uint8_t do_RRCSetupComplete(uint8_t Mod_id, uint8_t *buffer, size_t buffer_size, // sizeof(*RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->nonCriticalExtension)); RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->selectedPLMN_Identity = sel_plmn_id; RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->registeredAMF = NULL; - + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value = CALLOC(1, sizeof(struct NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value)); RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->present = NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI; RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size = 6; @@ -1757,23 +1726,23 @@ uint8_t do_RRCSetupComplete(uint8_t Mod_id, uint8_t *buffer, size_t buffer_size, RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[3] = 0x78; RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[4] = 0x9A; RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[5] = 0xBC; - - memset(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,0,sizeof(OCTET_STRING_t)); - OCTET_STRING_fromBuf(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,dedicatedInfoNAS,dedicatedInfoNASLength); -if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); -} - -enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, - NULL, - (void *)&ul_dcch_msg, - buffer, - buffer_size); -AssertFatal(enc_rval.encoded > 0,"ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name,enc_rval.encoded); -LOG_D(NR_RRC,"RRCSetupComplete Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); - -return((enc_rval.encoded+7)/8); + + memset(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,0,sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,dedicatedInfoNAS,dedicatedInfoNASLength); + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, + NULL, + (void *)&ul_dcch_msg, + buffer, + buffer_size); + AssertFatal(enc_rval.encoded > 0,"ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name,enc_rval.encoded); + LOG_D(NR_RRC,"RRCSetupComplete Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + + return((enc_rval.encoded+7)/8); } //------------------------------------------------------------------------------ @@ -1993,11 +1962,8 @@ NR_SRB_ToAddModList_t **SRB_configList buffer, 100); - if(enc_rval.encoded == -1) { - LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); LOG_D(NR_RRC,"RRCReestablishment Encoded %u bits (%u bytes)\n", (uint32_t)enc_rval.encoded, (uint32_t)(enc_rval.encoded+7)/8); diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c new file mode 100644 index 0000000000..12530c7b82 --- /dev/null +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -0,0 +1,229 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * conmnc_digit_lengtht@openairinterface.org + */ + +#include + +#include "cucp_cuup_if.h" +#include "platform_types.h" +#include "nr_rrc_defs.h" + +#include "softmodem-common.h" +#include "nr_rrc_proto.h" +#include "nr_rrc_extern.h" +#include "openair2/COMMON/e1ap_messages_types.h" +#include "UTIL/OSA/osa_defs.h" +#include "nr_pdcp/nr_pdcp_entity.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h" +#include +#include "openair3/ocp-gtpu/gtp_itf.h" +#include "rrc_gNB_GTPV1U.h" +#include "common/ran_context.h" +#include "openair2/F1AP/f1ap_common.h" +#include "openair2/E1AP/e1ap_common.h" +extern RAN_CONTEXT_t RC; + +void fill_e1ap_bearer_setup_resp(e1ap_bearer_setup_resp_t *resp, + e1ap_bearer_setup_req_t *const req, + instance_t gtpInst, + ue_id_t ue_id, + int remote_port, + in_addr_t my_addr) { + + resp->numPDUSessions = req->numPDUSessions; + transport_layer_addr_t dummy_address = {0}; + dummy_address.length = 32; // IPv4 + for (int i=0; i < req->numPDUSessions; i++) { + resp->pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup; + for (int j=0; j < req->pduSession[i].numDRB2Setup; j++) { + DRB_nGRAN_to_setup_t *drb2Setup = req->pduSession[i].DRBnGRanList + j; + DRB_nGRAN_setup_t *drbSetup = resp->pduSession[i].DRBnGRanList + j; + + drbSetup->numUpParam = 1; + drbSetup->UpParamList[0].tlAddress = my_addr; + drbSetup->UpParamList[0].teId = newGtpuCreateTunnel(gtpInst, + (ue_id & 0xFFFF), + drb2Setup->id, + drb2Setup->id, + 0xFFFF, // We will set the right value from DU answer + -1, // no qfi + dummy_address, // We will set the right value from DU answer + remote_port, + cu_f1u_data_req, + NULL); + drbSetup->id = drb2Setup->id; + + drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup; + for (int k=0; k < drbSetup->numQosFlowSetup; k++) { + drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id; + } + } + } +} + +void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t instance, ue_id_t ue_id) { + for (int i=0; i < req->numPDUSessionsMod; i++) { + for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) { + DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j; + + transport_layer_addr_t newRemoteAddr; + newRemoteAddr.length = 32; // IPv4 + memcpy(newRemoteAddr.buffer, + &drb_p->DlUpParamList[0].tlAddress, + sizeof(in_addr_t)); + + GtpuUpdateTunnelOutgoingAddressAndTeid(instance, + (ue_id & 0xFFFF), + (ebi_t)drb_p->id, + *(in_addr_t*)&newRemoteAddr.buffer, + drb_p->DlUpParamList[0].teId); + } + } +} + +static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p, + rrc_gNB_ue_context_t *ue_context_p, + e1ap_bearer_setup_req_t *const req, + NR_DRB_ToAddModList_t *DRB_configList, + NR_SRB_ToAddModList_t *SRB_configList, + instance_t instance) { + + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; + + for (int i=0; i < ue_context_p->ue_context.nb_of_pdusessions; i++) { + pdu_session_param_t *pdu = ue_context_p->ue_context.pduSession + i; + create_tunnel_req.pdusession_id[i] = pdu->param.pdusession_id; + create_tunnel_req.incoming_rb_id[i] = i + 1; + create_tunnel_req.outgoing_qfi[i] = req->pduSession[i].DRBnGRanList[0].qosFlows[0].id; + memcpy(&create_tunnel_req.dst_addr[i].buffer, + &pdu->param.upf_addr.buffer, + sizeof(uint8_t)*20); + create_tunnel_req.dst_addr[i].length = pdu->param.upf_addr.length; + create_tunnel_req.outgoing_teid[i] = pdu->param.gtp_teid; + } + create_tunnel_req.num_tunnels = ue_context_p->ue_context.nb_of_pdusessions; + create_tunnel_req.ue_id = ue_context_p->ue_context.rnti; + + int ret = gtpv1u_create_ngu_tunnel(getCxtE1(instance)->gtpInstN3, &create_tunnel_req, &create_tunnel_resp); + + if (ret != 0) { + LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE rnti %ld\n", + create_tunnel_req.ue_id); + return ret; + } + + nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_p, + &create_tunnel_resp); + + uint8_t *kRRCenc = NULL; + uint8_t *kRRCint = NULL; + uint8_t *kUPenc = NULL; + uint8_t *kUPint = NULL; + /* Derive the keys from kgnb */ + if (DRB_configList != NULL) { + nr_derive_key_up_enc(ue_context_p->ue_context.ciphering_algorithm, + ue_context_p->ue_context.kgnb, + &kUPenc); + nr_derive_key_up_int(ue_context_p->ue_context.integrity_algorithm, + ue_context_p->ue_context.kgnb, + &kUPint); + } + + nr_derive_key_rrc_enc(ue_context_p->ue_context.ciphering_algorithm, + ue_context_p->ue_context.kgnb, + &kRRCenc); + nr_derive_key_rrc_int(ue_context_p->ue_context.integrity_algorithm, + ue_context_p->ue_context.kgnb, + &kRRCint); + /* Refresh SRBs/DRBs */ + + LOG_D(NR_RRC,"Configuring PDCP DRBs/SRBs for UE %x\n",ue_context_p->ue_context.rnti); + + nr_pdcp_add_srbs(ctxt_p->enb_flag, ctxt_p->rntiMaybeUEid, + SRB_configList, + (ue_context_p->ue_context.integrity_algorithm << 4) + | ue_context_p->ue_context.ciphering_algorithm, + kRRCenc, + kRRCint); + + nr_pdcp_add_drbs(ctxt_p->enb_flag, ctxt_p->rntiMaybeUEid, + DRB_configList, + (ue_context_p->ue_context.integrity_algorithm << 4) + | ue_context_p->ue_context.ciphering_algorithm, + kUPenc, + kUPint, + get_softmodem_params()->sa ? ue_context_p->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL); + + return ret; +} + +static NR_SRB_ToAddModList_t **generateSRB2_confList(gNB_RRC_UE_t *ue, NR_SRB_ToAddModList_t *SRB_configList, uint8_t xid) +{ + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + + SRB_configList2 = &ue->SRB_configList2[xid]; + if (*SRB_configList2 == NULL) { + *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); + NR_SRB_ToAddMod_t *SRB2_config = CALLOC(1, sizeof(*SRB2_config)); + SRB2_config->srb_Identity = 2; + asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); + asn1cSeqAdd(&SRB_configList->list, SRB2_config); + } + + return SRB_configList2; +} +static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance) { + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)], req->rnti); + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + + fill_DRB_configList(&ctxt, ue_context_p); + + gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; + // Fixme: xid not random, but almost! + NR_SRB_ToAddModList_t **SRB_configList2 = generateSRB2_confList(&ue_context_p->ue_context, ue_context_p->ue_context.SRB_configList, ue_context_p->ue_context.pduSession[0].xid); + // GTP tunnel for UL + int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, ue_context_p->ue_context.DRB_configList, *SRB_configList2, rrc->e1_inst); + if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n"); + + if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) { + rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL); + } else { + e1ap_bearer_setup_resp_t resp; // Used to store teids + int remote_port = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd; + in_addr_t my_addr = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr); + instance_t gtpInst = getCxt(CUtype, instance)->gtpInst; + // GTP tunnel for DL + fill_e1ap_bearer_setup_resp(&resp, req, gtpInst, ue_context_p->ue_context.rnti, remote_port, my_addr); + + prepare_and_send_ue_context_modification_f1(ue_context_p, &resp); + } +} + +static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance) { + instance_t gtpInst = getCxt(CUtype, instance)->gtpInst; + CU_update_UP_DL_tunnel(req, gtpInst, req->rnti); +} + +void cucp_cuup_message_transfer_direct_init(gNB_RRC_INST *rrc) { + rrc->cucp_cuup.bearer_context_setup = cucp_cuup_bearer_context_setup_direct; + rrc->cucp_cuup.bearer_context_mod = cucp_cuup_bearer_context_mod_direct; +} diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c new file mode 100644 index 0000000000..069629db0b --- /dev/null +++ b/openair2/RRC/NR/cucp_cuup_e1ap.c @@ -0,0 +1,61 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * conmnc_digit_lengtht@openairinterface.org + */ + +#include "cucp_cuup_if.h" +#include + +#include "platform_types.h" +#include "nr_rrc_defs.h" + +#include "nr_rrc_proto.h" +#include "nr_rrc_extern.h" +#include "cucp_cuup_if.h" +#include "openair2/COMMON/e1ap_messages_types.h" +#include "UTIL/OSA/osa_defs.h" +#include +#include "common/ran_context.h" + +extern RAN_CONTEXT_t RC; + +static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance) { + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)], req->rnti); + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + + fill_DRB_configList(&ctxt, ue_context_p); + MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_SETUP_REQ); + e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p); + memcpy(bearer_req, req, sizeof(e1ap_bearer_setup_req_t)); + + itti_send_msg_to_task (TASK_CUCP_E1, instance, msg_p); +} + +static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance) { + MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_MODIFICATION_REQ); + e1ap_bearer_setup_req_t *req_msg = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg); + memcpy(req_msg, req, sizeof(*req)); + itti_send_msg_to_task(TASK_CUCP_E1, instance, msg); +} + +void cucp_cuup_message_transfer_e1ap_init(gNB_RRC_INST *rrc) { + rrc->cucp_cuup.bearer_context_setup = cucp_cuup_bearer_context_setup_e1ap; + rrc->cucp_cuup.bearer_context_mod = cucp_cuup_bearer_context_mod_e1ap; +} diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h new file mode 100644 index 0000000000..079a32e850 --- /dev/null +++ b/openair2/RRC/NR/cucp_cuup_if.h @@ -0,0 +1,42 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * conmnc_digit_lengtht@openairinterface.org + */ + +#ifndef CUCP_CUUP_IF_H +#define CUCP_CUUP_IF_H + +#include +#include "platform_types.h" + +struct e1ap_bearer_setup_req_s; +struct e1ap_bearer_setup_resp_s; +typedef void (*cucp_cuup_bearer_context_setup_func_t)(struct e1ap_bearer_setup_req_s *const req, instance_t instance); + +struct gNB_RRC_INST_s; +void cucp_cuup_message_transfer_direct_init(struct gNB_RRC_INST_s *rrc); +void cucp_cuup_message_transfer_e1ap_init(struct gNB_RRC_INST_s *rrc); +void fill_e1ap_bearer_setup_resp(struct e1ap_bearer_setup_resp_s *resp, + struct e1ap_bearer_setup_req_s *const req, + instance_t gtpInst, + ue_id_t ue_id, + int remote_port, + in_addr_t my_addr); +void CU_update_UP_DL_tunnel(struct e1ap_bearer_setup_req_s *const req, instance_t instance, ue_id_t ue_id); +#endif diff --git a/openair2/RRC/NR/nr_rrc_common.c b/openair2/RRC/NR/nr_rrc_common.c index 828e392460..85e9c71eaa 100644 --- a/openair2/RRC/NR/nr_rrc_common.c +++ b/openair2/RRC/NR/nr_rrc_common.c @@ -49,21 +49,14 @@ extern UE_MAC_INST *UE_mac_inst; extern mui_t rrc_gNB_mui; //----------------------------------------------------------------------------- -int rrc_init_nr_global_param(void){ - +void rrc_init_nr_srb_param(NR_LCHAN_DESC *chan) +{ rrc_rlc_register_rrc (rrc_data_ind, NULL); //register with rlc - DCCH_LCHAN_DESC.transport_block_size = 4; - DCCH_LCHAN_DESC.max_transport_blocks = 16; - DCCH_LCHAN_DESC.Delay_class = 1; - DTCH_DL_LCHAN_DESC.transport_block_size = 52; - DTCH_DL_LCHAN_DESC.max_transport_blocks = 20; - DTCH_DL_LCHAN_DESC.Delay_class = 1; - DTCH_UL_LCHAN_DESC.transport_block_size = 52; - DTCH_UL_LCHAN_DESC.max_transport_blocks = 20; - DTCH_UL_LCHAN_DESC.Delay_class = 1; - - return 0; + chan->transport_block_size = 4; + chan->max_transport_blocks = 16; + chan->Delay_class = 1; + return; } //----------------------------------------------------------------------------- diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 6b60d64842..b3026f6a0e 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -43,6 +43,7 @@ #include "common/platform_constants.h" #include "COMMON/platform_types.h" #include "mac_rrc_dl.h" +#include "cucp_cuup_if.h" //#include "COMMON/mac_rrc_primitives.h" @@ -416,7 +417,7 @@ typedef struct rrc_gNB_ue_context_s { // another key for protocol layers but should not be used as a key for RB tree uid_t local_uid; - /* UE id for initial connection to S1AP */ + /* UE id for initial connection to NGAP */ struct gNB_RRC_UE_s ue_context; } rrc_gNB_ue_context_t; @@ -476,6 +477,11 @@ typedef struct nr_mac_rrc_dl_if_s { dl_rrc_message_transfer_func_t dl_rrc_message_transfer; } nr_mac_rrc_dl_if_t; +typedef struct cucp_cuup_if_s { + cucp_cuup_bearer_context_setup_func_t bearer_context_setup; + cucp_cuup_bearer_context_setup_func_t bearer_context_mod; +} cucp_cuup_if_t; + //---NR---(completely change)--------------------- typedef struct gNB_RRC_INST_s { @@ -499,6 +505,9 @@ typedef struct gNB_RRC_INST_s { // RRC configuration gNB_RrcConfigurationReq configuration; + // gNB N3 GTPU instance + instance_t e1_inst; + // other PLMN parameters /// Mobile country code int mcc; @@ -527,6 +536,8 @@ typedef struct gNB_RRC_INST_s { nr_security_configuration_t security; nr_mac_rrc_dl_if_t mac_rrc; + cucp_cuup_if_t cucp_cuup; + } gNB_RRC_INST; #include "nr_rrc_proto.h" //should be put here otherwise compilation error diff --git a/openair2/RRC/NR/nr_rrc_extern.h b/openair2/RRC/NR/nr_rrc_extern.h index 7283b25be0..70493f1010 100644 --- a/openair2/RRC/NR/nr_rrc_extern.h +++ b/openair2/RRC/NR/nr_rrc_extern.h @@ -53,8 +53,7 @@ extern void* bigphys_malloc(int); //uint8_t RACH_TIME_ALLOC; extern uint16_t RACH_FREQ_ALLOC; -//uint8_t NB_RACH; -extern LCHAN_DESC BCCH_LCHAN_DESC,CCCH_LCHAN_DESC,DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; +// uint8_t NB_RACH; extern MAC_MEAS_T BCCH_MEAS_TRIGGER,CCCH_MEAS_TRIGGER,DCCH_MEAS_TRIGGER,DTCH_MEAS_TRIGGER; extern MAC_AVG_T BCCH_MEAS_AVG,CCCH_MEAS_AVG,DCCH_MEAS_AVG, DTCH_MEAS_AVG; @@ -63,7 +62,6 @@ extern UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; extern pthread_mutex_t ue_pf_po_mutex; extern uint16_t reestablish_rnti_map[MAX_MOBILES_PER_ENB][2]; -char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration); #endif diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 0d7e0e7f97..dc32e71aea 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -44,12 +44,7 @@ #include "NR_SecurityConfig.h" #define NR_MAX_SUPPORTED_DL_LAYERS 2 - -int rrc_init_nr_global_param(void); - -void rrc_config_nr_buffer(NR_SRB_INFO* Srb_info, - uint8_t Lchan_type, - uint8_t Role); +void rrc_init_nr_srb_param(NR_LCHAN_DESC *chan); uint16_t mac_rrc_nr_data_req(const module_id_t Mod_idP, const int CC_id, @@ -104,18 +99,6 @@ int generate_CG_Config(gNB_RRC_INST *rrc, NR_RRCReconfiguration_t *reconfig, NR_RadioBearerConfig_t *rbconfig); -void apply_macrlc_config(gNB_RRC_INST *rrc, - rrc_gNB_ue_context_t *const ue_context_pP, - const protocol_ctxt_t *const ctxt_pP ); - -void -rrc_gNB_generate_RRCSetup( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP, - const uint8_t *masterCellGroup, - int masterCellGroup_len, - NR_ServingCellConfigCommon_t *scc); - int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m); void @@ -124,10 +107,7 @@ rrc_gNB_generate_SecurityModeCommand( rrc_gNB_ue_context_t *const ue_context_pP ); - uint8_t -rrc_gNB_get_next_transaction_identifier( - module_id_t gnb_mod_idP -); +unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP); void rrc_gNB_generate_UECapabilityEnquiry( @@ -209,6 +189,23 @@ rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt const NR_DRB_ToReleaseList_t * const drb2release_listP, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); +void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req, + instance_t instance); + +void bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *req, + instance_t instance); + +void ue_cxt_mod_send_e1ap(MessageDef *msg, + instance_t instance); + +void ue_cxt_mod_direct(MessageDef *msg, + instance_t instance); + +void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP); + +void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, + e1ap_bearer_setup_resp_t *e1ap_resp); void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t rntiMaybeUEid, NR_SRB_ToAddModList_t *const srb2add_list, const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kUPint); void nr_pdcp_add_drbs(eNB_flag_t enb_flag, diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index b5a63cdf0d..0e2d5dac29 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -99,6 +99,10 @@ #include #include #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h" +#include "openair2/F1AP/f1ap_common.h" +#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" +#include "cucp_cuup_if.h" #include "BIT_STRING.h" #include "assertions.h" @@ -132,10 +136,12 @@ bool DURecvCb(protocol_ctxt_t *ctxt_pP, return true; } -void openair_nr_rrc_on(const protocol_ctxt_t *const ctxt_pP) { - LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" gNB:OPENAIR NR RRC IN....\n",PROTOCOL_NR_RRC_CTXT_ARGS(ctxt_pP)); - rrc_config_nr_buffer (&RC.nrrrc[ctxt_pP->module_id]->carrier.SI, BCCH, 1); - RC.nrrrc[ctxt_pP->module_id]->carrier.SI.Active = 1; +static void openair_nr_rrc_on(gNB_RRC_INST *rrc) +{ + NR_SRB_INFO *si = &rrc->carrier.SI; + si->Rx_buffer.payload_size = 0; + si->Tx_buffer.payload_size = 0; + si->Active = 1; } ///---------------------------------------------------------------------------------------------------------------/// @@ -193,27 +199,34 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration } } -static void rrc_gNB_mac_rrc_init(gNB_RRC_INST *rrc) +static void rrc_gNB_CU_DU_init(gNB_RRC_INST *rrc) { switch (rrc->node_type) { + case ngran_gNB_CUCP: + mac_rrc_dl_f1ap_init(&rrc->mac_rrc); + cucp_cuup_message_transfer_e1ap_init(rrc); + break; case ngran_gNB_CU: mac_rrc_dl_f1ap_init(&rrc->mac_rrc); + cucp_cuup_message_transfer_direct_init(rrc); break; + case ngran_gNB: + mac_rrc_dl_direct_init(&rrc->mac_rrc); + cucp_cuup_message_transfer_direct_init(rrc); + break; case ngran_gNB_DU: /* silently drop this, as we currently still need the RRC at the DU. As * soon as this is not the case anymore, we can add the AssertFatal() */ //AssertFatal(1==0,"nothing to do for DU\n"); break; - case ngran_gNB: - mac_rrc_dl_direct_init(&rrc->mac_rrc); - break; default: AssertFatal(0 == 1, "Unknown node type %d\n", rrc->node_type); break; } } -char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration) { +static void openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration) +{ protocol_ctxt_t ctxt = { 0 }; gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP]; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gnb_mod_idP, GNB_FLAG_YES, NOT_A_RNTI, 0, 0,gnb_mod_idP); @@ -225,7 +238,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu AssertFatal(configuration!=NULL,"configuration input is null\n"); rrc->module_id = gnb_mod_idP; rrc->Nb_ue = 0; - rrc_gNB_mac_rrc_init(rrc); + rrc_gNB_CU_DU_init(rrc); uid_linear_allocator_init(&rrc->uid_allocator); RB_INIT(&rrc->rrc_ue_head); rrc->initial_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL); @@ -241,13 +254,12 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu rrc->cell_info_configured = 0; LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" Checking release \n",PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt)); init_NR_SI(rrc, configuration); - rrc_init_nr_global_param(); - openair_nr_rrc_on(&ctxt); - return 0; -}//END openair_rrc_gNB_configuration + openair_nr_rrc_on(rrc); + return; +} // END openair_rrc_gNB_configuration - -void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_addition_req_t *m) { +static void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_addition_req_t *m) +{ struct NR_CG_ConfigInfo *cg_configinfo = NULL; asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_CG_ConfigInfo, @@ -272,24 +284,20 @@ void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x dec_rval.consumed, (dec_rval.consumed +7/8)); } - //----------------------------------------------------------------------------- -uint8_t -rrc_gNB_get_next_transaction_identifier( - module_id_t gnb_mod_idP -) +unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP) //----------------------------------------------------------------------------- { - static uint8_t nr_rrc_transaction_identifier[NUMBER_OF_gNB_MAX]; - nr_rrc_transaction_identifier[gnb_mod_idP] = (nr_rrc_transaction_identifier[gnb_mod_idP] + 1) % NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; - LOG_T(NR_RRC, "generated xid is %d\n", nr_rrc_transaction_identifier[gnb_mod_idP]); - return nr_rrc_transaction_identifier[gnb_mod_idP]; + static unsigned int transaction_id[NUMBER_OF_gNB_MAX] = {0}; + // used also in NGAP thread, so need thread safe operation + unsigned int tmp = __atomic_add_fetch(&transaction_id[gnb_mod_idP], 1, __ATOMIC_SEQ_CST); + tmp %= NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; + LOG_T(NR_RRC, "generated xid is %d\n", tmp); + return tmp; } -void apply_macrlc_config(gNB_RRC_INST *rrc, - rrc_gNB_ue_context_t *const ue_context_pP, - const protocol_ctxt_t *const ctxt_pP ) { - +static void apply_macrlc_config(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, const protocol_ctxt_t *const ctxt_pP) +{ NR_CellGroupConfig_t *cgc = get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup : NULL; rrc_mac_config_req_gNB(rrc->module_id, rrc->configuration.pdsch_AntennaPorts, @@ -308,27 +316,18 @@ void apply_macrlc_config(gNB_RRC_INST *rrc, ue_context_pP->ue_context.DRB_configList, NULL, get_softmodem_params()->sa ? cgc->rlc_BearerToAddModList : NULL); - } //----------------------------------------------------------------------------- -void -rrc_gNB_generate_RRCSetup( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP, - const uint8_t *masterCellGroup, - int masterCellGroup_len, - NR_ServingCellConfigCommon_t *scc) +static void rrc_gNB_generate_RRCSetup(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + const uint8_t *masterCellGroup, + int masterCellGroup_len, + NR_ServingCellConfigCommon_t *scc) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, "rrc_gNB_generate_RRCSetup for RNTI %04lx\n", ctxt_pP->rntiMaybeUEid); - // T(T_GNB_RRC_SETUP, - // T_INT(ctxt_pP->module_id), - // T_INT(ctxt_pP->frame), - // T_INT(ctxt_pP->subframe), - // T_INT(ctxt_pP->rnti)); - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; unsigned char buf[1024]; @@ -368,11 +367,7 @@ rrc_gNB_generate_RRCSetup( } //----------------------------------------------------------------------------- -void -rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest( - const protocol_ctxt_t *const ctxt_pP, - const int CC_id -) +static void rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(const protocol_ctxt_t *const ctxt_pP, const int CC_id) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, "generate RRCSetup for RRCReestablishmentRequest \n"); @@ -440,10 +435,7 @@ rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest( rrc_instance_p->mac_rrc.dl_rrc_message_transfer(ctxt_pP->module_id, &dl_rrc); } -void -rrc_gNB_generate_RRCReject( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP) +static void rrc_gNB_generate_RRCReject(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *const ue_context_pP) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, "rrc_gNB_generate_RRCReject \n"); @@ -482,12 +474,7 @@ rrc_gNB_generate_RRCReject( /* * Process the rrc setup complete message from UE (SRB1 Active) */ -void -rrc_gNB_process_RRCSetupComplete( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP, - NR_RRCSetupComplete_IEs_t *rrcSetupComplete -) +static void rrc_gNB_process_RRCSetupComplete(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, NR_RRCSetupComplete_IEs_t *rrcSetupComplete) //----------------------------------------------------------------------------- { LOG_A(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, " "processing NR_RRCSetupComplete from UE (SRB1 Active)\n", @@ -504,22 +491,9 @@ rrc_gNB_process_RRCSetupComplete( } //----------------------------------------------------------------------------- -void -rrc_gNB_generate_defaultRRCReconfiguration( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP -) +static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP) //----------------------------------------------------------------------------- { - uint8_t buffer[RRC_BUF_SIZE]; - int16_t size; - /*NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; - NR_DRB_ToAddModList_t **DRB_configList = NULL; - NR_DRB_ToAddModList_t **DRB_configList2 = NULL; - NR_SRB_ToAddMod_t *SRB2_config = NULL; - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_SDAP_Config_t *sdap_config = NULL;*/ struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = NULL; NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; @@ -527,66 +501,6 @@ rrc_gNB_generate_defaultRRCReconfiguration( uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); /******************** Radio Bearer Config ********************/ - /* Configure SRB2 */ - /*SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; - if (*SRB_configList2) { - free(*SRB_configList2); - } - *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); - memset(*SRB_configList2, 0, sizeof(**SRB_configList2)); - SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - SRB2_config->srb_Identity = 2; - asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); - asn1cSeqAdd(&SRB_configList->list, SRB2_config);*/ - - /* Configure DRB */ - /*DRB_configList = &ue_context_pP->ue_context.DRB_configList; - if (*DRB_configList) { - free(*DRB_configList); - } - *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); - memset(*DRB_configList, 0, sizeof(**DRB_configList)); - - DRB_configList2 = &ue_context_pP->ue_context.DRB_configList2[xid]; - if (*DRB_configList2) { - free(*DRB_configList2); - } - *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); - - DRB_config = CALLOC(1, sizeof(*DRB_config)); - DRB_config->drb_Identity = 1; - DRB_config->cnAssociation = CALLOC(1, sizeof(*DRB_config->cnAssociation)); - DRB_config->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; - // TODO sdap_Config - sdap_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); - memset(sdap_config, 0, sizeof(NR_SDAP_Config_t)); - DRB_config->cnAssociation->choice.sdap_Config = sdap_config; - // TODO pdcp_Config - DRB_config->reestablishPDCP = NULL; - DRB_config->recoverPDCP = NULL; - DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config)); - DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb)); - DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer)); - *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; - DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL)); - *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; - DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL)); - *DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; - DRB_config->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - DRB_config->pdcp_Config->drb->headerCompression.choice.notUsed = 0; - - DRB_config->pdcp_Config->drb->integrityProtection = NULL; - DRB_config->pdcp_Config->drb->statusReportRequired = NULL; - DRB_config->pdcp_Config->drb->outOfOrderDelivery = NULL; - DRB_config->pdcp_Config->moreThanOneRLC = NULL; - - DRB_config->pdcp_Config->t_Reordering = calloc(1, sizeof(*DRB_config->pdcp_Config->t_Reordering)); - *DRB_config->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms100; - DRB_config->pdcp_Config->ext1 = NULL; - - asn1cSeqAdd(&(*DRB_configList)->list, DRB_config); - asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config);*/ dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); @@ -594,7 +508,6 @@ rrc_gNB_generate_defaultRRCReconfiguration( for (int i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); - memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer, ue_context_pP->ue_context.pduSession[i].param.nas_pdu.length); @@ -608,7 +521,6 @@ rrc_gNB_generate_defaultRRCReconfiguration( if (ue_context_pP->ue_context.nas_pdu_flag == 1) { dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); - memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_context_pP->ue_context.nas_pdu.buffer, ue_context_pP->ue_context.nas_pdu.length); @@ -625,21 +537,23 @@ rrc_gNB_generate_defaultRRCReconfiguration( NR_MeasConfig_t *measconfig = get_defaultMeasConfig(&rrc->configuration); gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - memset(buffer, 0, sizeof(buffer)); - size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), - xid, - NULL, //*SRB_configList2, - NULL, //*DRB_configList, - NULL, - NULL, - NULL, - measconfig, - dedicatedNAS_MessageList, - ue_context_pP, - &rrc->carrier, - &rrc->configuration, - NULL, - ue_p->masterCellGroup); + uint8_t buffer[RRC_BUF_SIZE] = {0}; + int size = do_RRCReconfiguration(ctxt_pP, + buffer, + sizeof(buffer), + xid, + NULL, //*SRB_configList2, + NULL, //*DRB_configList, + NULL, + NULL, + NULL, + measconfig, + dedicatedNAS_MessageList, + ue_context_pP, + &rrc->carrier, + &rrc->configuration, + NULL, + ue_p->masterCellGroup); AssertFatal(size > 0, "cannot encode RRCReconfiguration in %s()\n", __func__); LOG_W(RRC, "do_RRCReconfiguration(): size %d\n", size); @@ -647,6 +561,7 @@ rrc_gNB_generate_defaultRRCReconfiguration( xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, ue_p->masterCellGroup); } + // suspicious if it is always malloced before ? free(ue_context_pP->ue_context.nas_pdu.buffer); LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)buffer, size, "[MSG] RRC Reconfiguration\n"); @@ -666,6 +581,8 @@ rrc_gNB_generate_defaultRRCReconfiguration( ue_context_pP->ue_context.rnti); switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { case ngran_gNB_CU: + case ngran_gNB_CUCP: + case ngran_gNB: nr_rrc_data_req(ctxt_pP, DCCH, rrc_gNB_mui++, @@ -682,28 +599,6 @@ rrc_gNB_generate_defaultRRCReconfiguration( AssertFatal(1==0,"nothing to do for DU\n"); break; - case ngran_gNB: - { - LOG_D(NR_RRC, "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", - ctxt_pP->frame, - ctxt_pP->module_id, - size, - ue_context_pP->ue_context.rnti, - rrc_gNB_mui, - ctxt_pP->module_id, - DCCH); - nr_rrc_data_req(ctxt_pP, - DCCH, - rrc_gNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); - // rrc_pdcp_config_asn1_req - // rrc_rlc_config_asn1_req - } - break; - default : LOG_W(NR_RRC, "Unknown node type %d\n", RC.nrrrc[ctxt_pP->module_id]->node_type); } @@ -735,37 +630,22 @@ rrc_gNB_generate_defaultRRCReconfiguration( } } -//----------------------------------------------------------------------------- -void -rrc_gNB_generate_dedicatedRRCReconfiguration( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP, - NR_CellGroupConfig_t *cell_groupConfig_from_DU -) -//----------------------------------------------------------------------------- -{ +void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP) { + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; NR_DRB_ToAddModList_t **DRB_configList = NULL; NR_DRB_ToAddModList_t **DRB_configList2 = NULL; - NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; - struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList - *dedicatedNAS_MessageList = NULL; - NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; - uint8_t buffer[RRC_BUF_SIZE]; - uint16_t size; int qos_flow_index = 0; int pdu_sessions_done = 0; int i; uint8_t drb_id_to_setup_start = 0; uint8_t nb_drb_to_setup = rrc->configuration.drbs; long drb_priority[NGAP_MAX_DRBS_PER_UE]; - NR_CellGroupConfig_t *cellGroupConfig = NULL; uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); - NR_SRB_ToAddModList_t **SRB_configList2 = generateSRB2_confList(ue_p, SRB_configList, xid); - DRB_configList = &ue_context_pP->ue_context.DRB_configList; if (*DRB_configList) { free(*DRB_configList); @@ -780,8 +660,6 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); - dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); - for (i = 0; i < ue_context_pP->ue_context.setup_pdu_sessions; i++) { if (pdu_sessions_done >= ue_context_pP->ue_context.nb_of_pdusessions) { break; @@ -880,11 +758,42 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( asn1cSeqAdd(&(*DRB_configList)->list, DRB_config); asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); } + LOG_D(RRC, "DRB Priority %ld\n", drb_priority[drb_id]); // To supress warning for now } } ue_context_pP->ue_context.pduSession[i].status = PDU_SESSION_STATUS_DONE; ue_context_pP->ue_context.pduSession[i].xid = xid; + } +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_dedicatedRRCReconfiguration( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + NR_CellGroupConfig_t *cell_groupConfig_from_DU +) +//----------------------------------------------------------------------------- +{ + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + long drb_priority[1] = {13}; // For now, we assume only one drb per pdu sessions with a default preiority (will be dynamique in future) + NR_CellGroupConfig_t *cellGroupConfig = NULL; + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + int xid = -1; + + int drb_id_to_setup_start = 1; + NR_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList; + int nb_drb_to_setup = DRB_configList->list.count; + + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = NULL; + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; + dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + + for (int i=0; i < nb_drb_to_setup; i++) { + NR_DRB_ToAddMod_t *DRB_config = DRB_configList->list.array[i]; + if (drb_id_to_setup_start == 1) drb_id_to_setup_start = DRB_config->drb_Identity; if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); @@ -899,6 +808,8 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( // TODO LOG_E(NR_RRC,"no NAS info (pdusession id %d)\n", i); } + + xid = ue_context_pP->ue_context.pduSession[i].xid; } /* If list is empty free the list and reset the address */ @@ -919,10 +830,14 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( cellGroupConfig = cell_groupConfig_from_DU; } + AssertFatal(xid > -1, "Invalid xid %d. No PDU sessions setup to configure.\n", xid); + NR_SRB_ToAddModList_t *SRB_configList2 = NULL; + SRB_configList2 = ue_context_pP->ue_context.SRB_configList2[xid]; + size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), xid, - *SRB_configList2, - *DRB_configList, + SRB_configList2, + DRB_configList, NULL, NULL, NULL, @@ -936,7 +851,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n"); /* Free all NAS PDUs */ - for (i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + for (int i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { /* Free the NAS PDU buffer and invalidate it */ free(ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer); @@ -1208,19 +1123,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( } memset(buffer, 0, sizeof(buffer)); - size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), xid, - NULL, - NULL, - *DRB_Release_configList2, - NULL, - NULL, - NULL, - dedicatedNAS_MessageList, - NULL, - NULL, - NULL, - NULL, - NULL); + size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), xid, NULL, NULL, *DRB_Release_configList2, NULL, NULL, NULL, dedicatedNAS_MessageList, NULL, NULL, NULL, NULL, NULL); ue_context_pP->ue_context.pdu_session_release_command_flag = 1; @@ -1273,10 +1176,6 @@ rrc_gNB_process_RRCReconfigurationComplete( ) { int drb_id; - uint8_t *kRRCenc = NULL; - uint8_t *kRRCint = NULL; - uint8_t *kUPenc = NULL; - uint8_t *kUPint = NULL; NR_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList2[xid]; NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid]; NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid]; @@ -1285,36 +1184,6 @@ rrc_gNB_process_RRCReconfigurationComplete( ue_context_pP->ue_context.ue_reestablishment_timer = 0; - /* Derive the keys from kgnb */ - if (DRB_configList != NULL) { - nr_derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm, - ue_context_pP->ue_context.kgnb, - &kUPenc); - nr_derive_key_up_int(ue_context_pP->ue_context.integrity_algorithm, - ue_context_pP->ue_context.kgnb, - &kUPint); - } - - nr_derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm, - ue_context_pP->ue_context.kgnb, - &kRRCenc); - nr_derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm, - ue_context_pP->ue_context.kgnb, - &kRRCint); - /* Refresh SRBs/DRBs */ - - LOG_D(NR_RRC,"Configuring PDCP DRBs/SRBs for UE %x\n",ue_context_pP->ue_context.rnti); - - nr_pdcp_add_srbs(ctxt_pP->enb_flag, ctxt_pP->rntiMaybeUEid, SRB_configList, (ue_context_pP->ue_context.integrity_algorithm << 4) | ue_context_pP->ue_context.ciphering_algorithm, kRRCenc, kRRCint); - - nr_pdcp_add_drbs(ctxt_pP->enb_flag, - ctxt_pP->rntiMaybeUEid, - DRB_configList, - (ue_context_pP->ue_context.integrity_algorithm << 4) | ue_context_pP->ue_context.ciphering_algorithm, - kUPenc, - kUPint, - get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL); - /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { LOG_D(NR_RRC,"Configuring RLC DRBs/SRBs for UE %x\n",ue_context_pP->ue_context.rnti); @@ -1500,13 +1369,7 @@ rrc_gNB_generate_RRCReestablishment( } //----------------------------------------------------------------------------- -void -rrc_gNB_process_RRCConnectionReestablishmentComplete( - const protocol_ctxt_t *const ctxt_pP, - const rnti_t reestablish_rnti, - rrc_gNB_ue_context_t *ue_context_pP, - const uint8_t xid -) +void rrc_gNB_process_RRCConnectionReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, const rnti_t reestablish_rnti, rrc_gNB_ue_context_t *ue_context_pP, const uint8_t old_xid) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, @@ -1524,12 +1387,12 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( uint8_t buffer[RRC_BUF_SIZE]; uint16_t size; - uint8_t next_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); int ret = 0; ue_context_pP->ue_context.StatusRrc = NR_RRC_CONNECTED; ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED - ue_context_pP->ue_context.reestablishment_xid = next_xid; - SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; + ue_context_pP->ue_context.reestablishment_xid = new_xid; + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[old_xid]; // get old configuration of SRB2 if (*SRB_configList2 != NULL) { @@ -1540,7 +1403,7 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ) { - LOG_D(NR_RRC, "get SRB2_config from (ue_context_pP->ue_context.SRB_configList2[%d])\n", xid); + LOG_D(NR_RRC, "get SRB2_config from (ue_context_pP->ue_context.SRB_configList2[%d])\n", old_xid); SRB2_config = (*SRB_configList2)->list.array[i]; break; } @@ -1550,12 +1413,12 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( // SRB2_config = CALLOC(1, sizeof(*SRB2_config)); // SRB2_config->srb_Identity = 2; - SRB_configList2 = &(ue_context_pP->ue_context.SRB_configList2[next_xid]); - DRB_configList2 = &(ue_context_pP->ue_context.DRB_configList2[next_xid]); + SRB_configList2 = &(ue_context_pP->ue_context.SRB_configList2[new_xid]); + DRB_configList2 = &(ue_context_pP->ue_context.DRB_configList2[new_xid]); if (*SRB_configList2) { free(*SRB_configList2); - LOG_D(NR_RRC, "free(ue_context_pP->ue_context.SRB_configList2[%d])\n", next_xid); + LOG_D(NR_RRC, "free(ue_context_pP->ue_context.SRB_configList2[%d])\n", new_xid); } *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); @@ -1566,8 +1429,7 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList\n", SRB2_config->srb_Identity); - LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList2[%d]\n", - SRB2_config->srb_Identity, next_xid); + LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList2[%d]\n", SRB2_config->srb_Identity, new_xid); } else { // SRB configuration list only contains SRB1. LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); @@ -1575,7 +1437,7 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( if (*DRB_configList2) { free(*DRB_configList2); - LOG_D(NR_RRC, "free(ue_context_pP->ue_context.DRB_configList2[%d])\n", next_xid); + LOG_D(NR_RRC, "free(ue_context_pP->ue_context.DRB_configList2[%d])\n", new_xid); } *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); @@ -1691,27 +1553,29 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( /* TODO parameters yet to process ... */ /* TODO should test if pdu session are Ok before! */ ue_context_pP->ue_context.pduSession[i].status = PDU_SESSION_STATUS_DONE; - ue_context_pP->ue_context.pduSession[i].xid = xid; + ue_context_pP->ue_context.pduSession[i].xid = old_xid; LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_context_pP->ue_context.pduSession[i].status, "PDU_SESSION_STATUS_DONE"); } memset(buffer, 0, sizeof(buffer)); - size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), - xid, + size = do_RRCReconfiguration(ctxt_pP, + buffer, + sizeof(buffer), + old_xid, *SRB_configList2, - DRB_configList, - NULL, - NULL, - NULL, - NULL, // MeasObj_list, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); + DRB_configList, + NULL, + NULL, + NULL, + NULL, // MeasObj_list, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, "[MSG] RRC Reconfiguration\n"); @@ -2135,21 +1999,13 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, // SRB1 ue_context_p->ue_context.Srb1.Active = 1; ue_context_p->ue_context.Srb1.Srb_info.Srb_id = Idx; - memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0], - &DCCH_LCHAN_DESC, - LCHAN_DESC_SIZE); - memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1], - &DCCH_LCHAN_DESC, - LCHAN_DESC_SIZE); + rrc_init_nr_srb_param(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0]); + rrc_init_nr_srb_param(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1]); // SRB2: set it to go through SRB1 with id 1 (DCCH) ue_context_p->ue_context.Srb2.Active = 1; ue_context_p->ue_context.Srb2.Srb_info.Srb_id = Idx; - memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0], - &DCCH_LCHAN_DESC, - LCHAN_DESC_SIZE); - memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1], - &DCCH_LCHAN_DESC, - LCHAN_DESC_SIZE); + rrc_init_nr_srb_param(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0]); + rrc_init_nr_srb_param(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1]); rrc_gNB_generate_RRCReestablishment(ctxt_pP, ue_context_p, 0); @@ -2483,7 +2339,6 @@ rrc_gNB_decode_dcch( nr_rrc_pdcp_config_security(ctxt_pP, ue_context_p, 1); rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); - //rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); break; case NR_UL_DCCH_MessageType__c1_PR_securityModeFailure: LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, @@ -3499,6 +3354,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch } if (ue_context_p->ue_context.established_pdu_sessions_flag == 1) { + fill_DRB_configList(&ctxt, ue_context_p); rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, cellGroupConfig); } else { rrc_gNB_generate_defaultRRCReconfiguration(&ctxt, ue_context_p); @@ -3511,10 +3367,31 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, const char *msg_name, instance_t instance){ - f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); + f1ap_ue_context_setup_t *resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); protocol_ctxt_t ctxt = {.rntiMaybeUEid = resp->rnti, .module_id = instance, .instance = instance, .enb_flag = 1, .eNB_index = instance}; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rntiMaybeUEid); + + e1ap_bearer_setup_req_t req = {0}; + req.numPDUSessionsMod = ue_context_p->ue_context.nb_of_pdusessions; + req.gNB_cu_cp_ue_id = ue_context_p->ue_context.gNB_ue_ngap_id; + req.rnti = ue_context_p->ue_context.rnti; + for (int i=0; i < req.numPDUSessionsMod; i++) { + req.pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length; + for (int j=0; j < resp->drbs_to_be_setup_length; j++) { + f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j; + DRB_nGRAN_to_setup_t *drb_e1 = req.pduSessionMod[i].DRBnGRanModList + j; + + drb_e1->id = drb_f1->drb_id; + drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length; + drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address; + drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid; + } + } + + // send the F1 response message up to update F1-U tunnel info + rrc->cucp_cuup.bearer_context_mod(&req, instance); + NR_CellGroupConfig_t *cellGroupConfig = NULL; if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ @@ -3803,6 +3680,98 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { } } +int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) { + + AssertFatal(req->supported_plmns <= PLMN_LIST_MAX_SIZE, "Supported PLMNs is more than PLMN_LIST_MAX_SIZE\n"); + gNB_RRC_INST *rrc = RC.nrrrc[0]; //TODO: remove hardcoding of RC index here + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, instance, E1AP_SETUP_RESP); + + e1ap_setup_resp_t *resp = &E1AP_SETUP_RESP(msg_p); + resp->transac_id = req->transac_id; + + for (int i=0; i < req->supported_plmns; i++) { + if (rrc->configuration.mcc[i] == req->plmns[i].mcc && + rrc->configuration.mnc[i] == req->plmns[i].mnc) { + LOG_E(NR_RRC, "PLMNs received from CUUP (mcc:%d, mnc:%d) did not match with PLMNs in RRC (mcc:%d, mnc:%d)\n", + req->plmns[i].mcc, req->plmns[i].mnc, rrc->configuration.mcc[i], rrc->configuration.mnc[i]); + return -1; + } + } + + itti_send_msg_to_task(TASK_CUCP_E1, instance, msg_p); + + return 0; +} + +void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, + e1ap_bearer_setup_resp_t *e1ap_resp) { + + /*Generate a UE context modification request message towards the DU to instruct the DU + *for SRB2 and DRB configuration and get the updates on master cell group config from the DU*/ + + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + // TODO: So many hard codings + MessageDef *message_p; + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ); + f1ap_ue_context_setup_t *req=&F1AP_UE_CONTEXT_MODIFICATION_REQ(message_p); + req->rnti = ue_context_p->ue_context.rnti; + req->mcc = RC.nrrrc[ctxt.module_id]->configuration.mcc[0]; + req->mnc = RC.nrrrc[ctxt.module_id]->configuration.mnc[0]; + req->mnc_digit_length = RC.nrrrc[ctxt.module_id]->configuration.mnc_digit_length[0]; + req->nr_cellid = RC.nrrrc[ctxt.module_id]->nr_cellid; + + /*Instruction towards the DU for SRB2 configuration*/ + req->srbs_to_be_setup = malloc(1*sizeof(f1ap_srb_to_be_setup_t)); + req->srbs_to_be_setup_length = 1; + f1ap_srb_to_be_setup_t *SRBs=req->srbs_to_be_setup; + SRBs[0].srb_id = 2; + SRBs[0].lcid = 2; + + /*Instruction towards the DU for DRB configuration and tunnel creation*/ + req->drbs_to_be_setup_length = e1ap_resp->pduSession[0].numDRBSetup; + req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)*req->drbs_to_be_setup_length); + for (int i=0; i < e1ap_resp->pduSession[0].numDRBSetup; i++) { + f1ap_drb_to_be_setup_t *DRBs = req->drbs_to_be_setup + i; + DRBs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id; + DRBs[i].rlc_mode = RLC_MODE_AM; + DRBs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress; + DRBs[i].up_ul_tnl[0].port = RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd; + DRBs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId; + DRBs[i].up_ul_tnl_length = 1; + } + + itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p); +} + +void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) { + // Find the UE context from UE ID and send ITTI message to F1AP to send UE context modification message to DU + + uint16_t ue_initial_id = 0; // Making an invalid UE initial ID + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, resp->gNB_cu_cp_ue_id); + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; + create_tunnel_resp.num_tunnels = resp->numPDUSessions; + for (int i=0; i < resp->numPDUSessions; i++) { + create_tunnel_resp.pdusession_id[i] = resp->pduSession[i].id; + create_tunnel_resp.gnb_NGu_teid[i] = resp->pduSession[i].teId; + memcpy(create_tunnel_resp.gnb_addr.buffer, + &resp->pduSession[i].tlAddress, + sizeof(in_addr_t)); + create_tunnel_resp.gnb_addr.length = sizeof(in_addr_t); // IPv4 byte length + } + + nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ctxt, + &create_tunnel_resp); + + ue_context_p->ue_context.setup_pdu_sessions += resp->numPDUSessions; + + // TODO: SV: combine e1ap_bearer_setup_req_t and e1ap_bearer_setup_resp_t and minimize assignments + prepare_and_send_ue_context_modification_f1(ue_context_p, resp); +} + static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) { DevAssert(measresults->measResultServingMOList.list.count >= 1); @@ -4021,6 +3990,15 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p, msg_name_p, instance); break; + case E1AP_SETUP_REQ: + LOG_I(NR_RRC, "Received E1AP_SETUP_REQ for instance %d\n", (int)instance); + rrc_gNB_process_e1_setup_req(&E1AP_SETUP_REQ(msg_p), instance); + break; + + case E1AP_BEARER_CONTEXT_SETUP_RESP: + LOG_I(NR_RRC, "Received E1AP_BEARER_CONTEXT_SETUP_RESP for instance %d\n", (int)instance); + rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance); + case NGAP_PAGING_IND: rrc_gNB_process_PAGING_IND(msg_p, msg_name_p, instance); break; @@ -4063,6 +4041,7 @@ rrc_gNB_generate_SecurityModeCommand( switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { case ngran_gNB_CU: + case ngran_gNB_CUCP: // create an ITTI message memcpy(ue_context_pP->ue_context.Srb1.Srb_info.Tx_buffer.Payload, buffer, size); ue_context_pP->ue_context.Srb1.Srb_info.Tx_buffer.payload_size = size; @@ -4125,6 +4104,7 @@ rrc_gNB_generate_UECapabilityEnquiry( size); switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { case ngran_gNB_CU: + case ngran_gNB_CUCP: nr_rrc_data_req( ctxt_pP, DCCH, @@ -4352,3 +4332,4 @@ void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe) LOG_D(NR_RRC, "Time in RRC: %u/ %u \n", frame, subframe); itti_send_msg_to_task(TASK_RRC_GNB, ctxt->module_id, message_p); } + diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.c b/openair2/RRC/NR/rrc_gNB_GTPV1U.c index ec220172d0..3fef7bc0ef 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.c +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.c @@ -49,7 +49,6 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, uint8_t *inde_list ) { - rnti_t rnti; int i; struct rrc_gNB_ue_context_s *ue_context_p = NULL; @@ -57,7 +56,6 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RX CREATE_TUNNEL_RESP num tunnels %u \n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->num_tunnels); - rnti = create_tunnel_resp_pP->rnti; ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[ctxt_pP->module_id], ctxt_pP->rntiMaybeUEid); for (i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) { @@ -74,7 +72,6 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( create_tunnel_resp_pP->enb_addr.length); } - (void)rnti; /* avoid gcc warning "set but not used" */ return 0; } else { return -1; @@ -84,10 +81,8 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP ) { - rnti_t rnti; int i; struct rrc_gNB_ue_context_s *ue_context_p = NULL; @@ -95,24 +90,21 @@ nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" RX CREATE_TUNNEL_RESP num tunnels %u \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->num_tunnels); - rnti = create_tunnel_resp_pP->ue_id; ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[ctxt_pP->module_id], ctxt_pP->rntiMaybeUEid); for (i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) { - ue_context_p->ue_context.gnb_gtp_teid[inde_list[i]] = create_tunnel_resp_pP->gnb_NGu_teid[i]; - ue_context_p->ue_context.gnb_gtp_addrs[inde_list[i]] = create_tunnel_resp_pP->gnb_addr; - ue_context_p->ue_context.gnb_gtp_psi[inde_list[i]] = create_tunnel_resp_pP->pdusession_id[i]; - LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, msg index %u, id %u, gtp addr len %d \n", + ue_context_p->ue_context.gnb_gtp_teid[i] = create_tunnel_resp_pP->gnb_NGu_teid[i]; + ue_context_p->ue_context.gnb_gtp_addrs[i] = create_tunnel_resp_pP->gnb_addr; + ue_context_p->ue_context.gnb_gtp_psi[i] = create_tunnel_resp_pP->pdusession_id[i]; + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, id %u, gtp addr len %d \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->gnb_NGu_teid[i], - ue_context_p->ue_context.gnb_gtp_teid[inde_list[i]], - inde_list[i], + ue_context_p->ue_context.gnb_gtp_teid[i], i, create_tunnel_resp_pP->pdusession_id[i], create_tunnel_resp_pP->gnb_addr.length); } - (void)rnti; /* avoid gcc warning "set but not used" */ return 0; } else { return -1; diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.h b/openair2/RRC/NR/rrc_gNB_GTPV1U.h index 748bd98789..03ef050bcf 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.h +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.h @@ -41,8 +41,7 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP ); #endif diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 3eccf0ef37..6f3ebcd06d 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -57,6 +57,7 @@ #include "NGAP_Cause.h" #include "NGAP_CauseRadioNetwork.h" #include "f1ap_messages_types.h" +#include "openair2/E1AP/e1ap_asnc.h" extern RAN_CONTEXT_t RC; @@ -242,7 +243,7 @@ rrc_gNB_NGAP_get_ue_ids( } //------------------------------------------------------------------------------ -static struct rrc_gNB_ue_context_s * +struct rrc_gNB_ue_context_s * rrc_gNB_get_ue_context_from_ngap_ids( const instance_t instanceP, const uint16_t ue_initial_idP, @@ -474,7 +475,6 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( protocol_ctxt_t ctxt={0}; uint8_t pdu_sessions_done = 0; gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp; - uint8_t inde_list[NR_NB_RB_MAX - 3]= {0}; int ret = 0; ue_initial_id = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_initial_id; @@ -495,12 +495,14 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( return (-1); } else { PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).gNB_ue_ngap_id; ue_context_p->ue_context.amf_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).amf_ue_ngap_id; ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nas_pdu_flag; uint8_t nb_pdusessions_tosetup = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_pdusessions; if (nb_pdusessions_tosetup != 0) { + AssertFatal(rrc->node_type != ngran_gNB_CUCP, "PDU sessions in Initial context setup request not handled by E1 yet\n"); gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE) @@ -520,7 +522,6 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( i, create_tunnel_req.outgoing_teid[pdu_sessions_done], create_tunnel_req.pdusession_id[pdu_sessions_done]); - inde_list[pdu_sessions_done] = i; pdu_sessions_done++; if(pdu_sessions_done >= nb_pdusessions_tosetup) { @@ -549,9 +550,8 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( &ctxt, - &create_tunnel_resp, - &inde_list[0]); - ue_context_p->ue_context.setup_pdu_sessions += nb_pdusessions_tosetup; + &create_tunnel_resp); + ue_context_p->ue_context.setup_pdu_sessions += NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_pdusessions; ue_context_p->ue_context.established_pdu_sessions_flag = 1; } @@ -804,6 +804,7 @@ rrc_gNB_process_NGAP_DOWNLINK_NAS( */ switch (RC.nrrrc[ctxt.module_id]->node_type) { case ngran_gNB_CU: + case ngran_gNB_CUCP: /* Transfer data to PDCP */ nr_rrc_data_req ( &ctxt, @@ -945,7 +946,7 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP( } //------------------------------------------------------------------------------ -int +void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( MessageDef *msg_p, const char *msg_name, @@ -953,21 +954,20 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( ) //------------------------------------------------------------------------------ { + gNB_RRC_INST *rrc; uint16_t ue_initial_id; uint32_t gNB_ue_ngap_id; rrc_gNB_ue_context_t *ue_context_p = NULL; protocol_ctxt_t ctxt={0}; - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; - gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; - uint8_t pdu_sessions_done; - uint8_t inde_list[NR_NB_RB_MAX - 3]= {0}; - int ret = 0; - ue_initial_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).ue_initial_id; - gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; + ngap_pdusession_setup_req_t* msg=&NGAP_PDUSESSION_SETUP_REQ(msg_p); + ue_initial_id = msg->ue_initial_id; + gNB_ue_ngap_id = msg->gNB_ue_ngap_id; ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + rrc = RC.nrrrc[ctxt.module_id]; LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u \n", - instance, msg_name, ue_initial_id, gNB_ue_ngap_id); + instance, msg_name, ue_initial_id, gNB_ue_ngap_id); if (ue_context_p == NULL) { MessageDef *msg_fail_p = NULL; @@ -976,110 +976,102 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( NGAP_PDUSESSION_SETUP_REQ(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; // TODO add failure cause when defined! itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p); - return (-1); - } else { - memset(&create_tunnel_req, 0, sizeof(gtpv1u_gnb_create_tunnel_req_t)); - uint8_t nb_pdusessions_tosetup = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup; - pdu_sessions_done = 0; + return ; + } + + ue_context_p->ue_context.nb_of_pdusessions = msg->nb_pdusessions_tosetup; + ue_context_p->ue_context.gNB_ue_ngap_id = msg->gNB_ue_ngap_id; + ue_context_p->ue_context.amf_ue_ngap_id = msg->amf_ue_ngap_id; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); - for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { - if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE) - continue; - ue_context_p->ue_context.pduSession[i].status = PDU_SESSION_STATUS_NEW; - ue_context_p->ue_context.pduSession[i].param = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done]; - create_tunnel_req.pdusession_id[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].pdusession_id; - create_tunnel_req.incoming_rb_id[pdu_sessions_done]= i+1; - create_tunnel_req.outgoing_teid[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].gtp_teid; - create_tunnel_req.outgoing_qfi[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].qos[0].qfi; - memcpy(create_tunnel_req.dst_addr[pdu_sessions_done].buffer, - NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.buffer, - sizeof(uint8_t)*20); - create_tunnel_req.dst_addr[pdu_sessions_done].length = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.length; - LOG_I(NR_RRC,"NGAP PDUSESSION SETUP REQ: local index %d teid %u, pdusession id %d \n", - i, - create_tunnel_req.outgoing_teid[pdu_sessions_done], - create_tunnel_req.pdusession_id[pdu_sessions_done]); - inde_list[pdu_sessions_done] = i; - pdu_sessions_done++; + /* Configurations are referred from rrc_gNB_generate_dedicatedRRCReconfiguration() and + rrc_gNB_process_RRCReconfigurationComplete() - if(pdu_sessions_done >= nb_pdusessions_tosetup) { - break; + At CU-CP we configure the E1 bearer context setup parameters (PDU sessions, DRBs and + QoS flows) same as in these functions. At CU-UP we create PDU Sessions and allocate DRBs. + */ + e1ap_bearer_setup_req_t bearer_req; + + bearer_req.gNB_cu_cp_ue_id = gNB_ue_ngap_id; + bearer_req.rnti = ue_context_p->ue_context.rnti; + bearer_req.cipheringAlgorithm = ue_context_p->ue_context.ciphering_algorithm; + memcpy(bearer_req.encryptionKey, ue_context_p->ue_context.kgnb, sizeof(ue_context_p->ue_context.kgnb)); + bearer_req.integrityProtectionAlgorithm = ue_context_p->ue_context.integrity_algorithm; + memcpy(bearer_req.integrityProtectionKey, ue_context_p->ue_context.kgnb, sizeof(ue_context_p->ue_context.kgnb)); + bearer_req.ueDlAggMaxBitRate = msg->ueAggMaxBitRateDownlink; + + bearer_req.numPDUSessions = msg->nb_pdusessions_tosetup; + + for (int i=0; i < bearer_req.numPDUSessions; i++) { + ue_context_p->ue_context.pduSession[i].param = msg->pdusession_setup_params[i]; + + pdu_session_to_setup_t *pdu = bearer_req.pduSession + i; + pdu->sessionId = msg->pdusession_setup_params[i].pdusession_id; + pdu->sessionType = msg->pdusession_setup_params[i].upf_addr.pdu_session_type; + pdu->sst = msg->allowed_nssai[i].sST; + if (rrc->security.do_drb_integrity) { + pdu->integrityProtectionIndication = E1AP_IntegrityProtectionIndication_required; + } else { + pdu->integrityProtectionIndication = E1AP_IntegrityProtectionIndication_not_needed; + } + + if (rrc->security.do_drb_ciphering) { + pdu->confidentialityProtectionIndication = E1AP_ConfidentialityProtectionIndication_required; + } else { + pdu->confidentialityProtectionIndication = E1AP_ConfidentialityProtectionIndication_not_needed; + } + pdu->teId = msg->pdusession_setup_params[i].gtp_teid; + memcpy(&pdu->tlAddress, + msg->pdusession_setup_params[i].upf_addr.buffer, + sizeof(uint8_t)*4); + + ue_context_p->ue_context.pduSession[i].param = msg->pdusession_setup_params[i]; + ue_context_p->ue_context.nb_of_pdusessions = msg->nb_pdusessions_tosetup; + ue_context_p->ue_context.gNB_ue_ngap_id = msg->gNB_ue_ngap_id; + ue_context_p->ue_context.amf_ue_ngap_id = msg->amf_ue_ngap_id; + pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding + ue_context_p->ue_context.setup_pdu_sessions += pdu->numDRB2Setup; + for (int j=0; j < pdu->numDRB2Setup; j++) { + DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; + + drb->id = i + j + 1; + + drb->defaultDRB = E1AP_DefaultDRB_true; + + drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap); + drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap); + + drb->pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_18; + drb->pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_18; + + drb->discardTimer = E1AP_DiscardTimer_infinity; + drb->reorderingTimer = E1AP_T_Reordering_ms0; + + drb->rLC_Mode = E1AP_RLC_Mode_rlc_am; + + drb->numCellGroups = 1; // assume one cell group associated with a DRB + + for (int k=0; k < drb->numCellGroups; k++) { + cell_group_t *cellGroup = drb->cellGroupList + k; + cellGroup->id = 0; // MCG + } + + drb->numQosFlow2Setup = msg->pdusession_setup_params[i].nb_qos; + for (int k=0; k < drb->numQosFlow2Setup; k++) { + qos_flow_to_setup_t *qos = drb->qosFlows + k; + + qos->id = msg->pdusession_setup_params[i].qos[k].qfi; + qos->fiveQI = msg->pdusession_setup_params[i].qos[k].fiveQI; + qos->fiveQI_type = msg->pdusession_setup_params[i].qos[k].fiveQI_type; + + qos->qoSPriorityLevel = msg->pdusession_setup_params[i].qos[k].allocation_retention_priority.priority_level; + qos->pre_emptionCapability = msg->pdusession_setup_params[i].qos[k].allocation_retention_priority.pre_emp_capability; + qos->pre_emptionVulnerability = msg->pdusession_setup_params[i].qos[k].allocation_retention_priority.pre_emp_vulnerability; } } - - ue_context_p->ue_context.nb_of_pdusessions = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup; - ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; - ue_context_p->ue_context.amf_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).amf_ue_ngap_id; - create_tunnel_req.ue_id = ue_context_p->ue_context.rnti; - create_tunnel_req.num_tunnels = pdu_sessions_done; - - ret = gtpv1u_create_ngu_tunnel( - instance, - &create_tunnel_req, - &create_tunnel_resp); - if (ret != 0) { - LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti); - ue_context_p->ue_context.ue_release_timer_ng = 1; - ue_context_p->ue_context.ue_release_timer_thres_ng = 100; - ue_context_p->ue_context.ue_release_timer = 0; - ue_context_p->ue_context.ue_reestablishment_timer = 0; - ue_context_p->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ - // rrc_gNB_free_UE(ctxt.module_id,ue_context_p); - ue_context_p->ue_context.ul_failure_timer = 0; - return (0); - } - nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - &ctxt, - &create_tunnel_resp, - &inde_list[0]); - ue_context_p->ue_context.setup_pdu_sessions += nb_pdusessions_tosetup; - - // TEST - // ue_context_p->ue_context.pdusession[0].status = PDU_SESSION_STATUS_DONE; - // rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(&ctxt, ue_context_p, 0); - if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)){ - rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL); - } - else{ - /*Generate a UE context modification request message towards the DU to instruct the DU - *for SRB2 and DRB configuration and get the updates on master cell group config from the DU*/ - MessageDef *message_p; - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ); - f1ap_ue_context_setup_t *req=&F1AP_UE_CONTEXT_MODIFICATION_REQ (message_p); - req->rnti = ue_context_p->ue_context.rnti; - req->mcc = RC.nrrrc[ctxt.module_id]->configuration.mcc[0]; - req->mnc = RC.nrrrc[ctxt.module_id]->configuration.mnc[0]; - req->mnc_digit_length = RC.nrrrc[ctxt.module_id]->configuration.mnc_digit_length[0]; - req->nr_cellid = RC.nrrrc[ctxt.module_id]->nr_cellid; - - /*Instruction towards the DU for SRB2 configuration*/ - req->srbs_to_be_setup = malloc(1*sizeof(f1ap_srb_to_be_setup_t)); - req->srbs_to_be_setup_length = 1; - f1ap_srb_to_be_setup_t *SRBs=req->srbs_to_be_setup; - SRBs[0].srb_id = 2; - SRBs[0].lcid = 2; - - /*Instruction towards the DU for DRB configuration and tunnel creation*/ - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req; - memset(&create_tunnel_req, 0, sizeof(gtpv1u_gnb_create_tunnel_req_t)); - req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)); - req->drbs_to_be_setup_length = 1; - f1ap_drb_to_be_setup_t *DRBs=req->drbs_to_be_setup; - LOG_D(RRC, "Length of DRB list:%d \n", req->drbs_to_be_setup_length); - DRBs[0].drb_id = 1; - DRBs[0].rlc_mode = RLC_MODE_AM; - DRBs[0].up_ul_tnl[0].tl_address = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr); - DRBs[0].up_ul_tnl[0].port=RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd; - DRBs[0].up_ul_tnl_length = 1; - DRBs[0].up_dl_tnl[0].tl_address = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.remote_addr); - DRBs[0].up_dl_tnl[0].port=RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd; - DRBs[0].up_dl_tnl_length = 1; - - itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p); - } - return(0); } + + rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance); + return; } //------------------------------------------------------------------------------ diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index a03e4df41f..6c8a861f03 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -101,7 +101,7 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP( uint8_t xid ); -int +void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( MessageDef *msg_p, const char *msg_name, @@ -189,6 +189,13 @@ nr_rrc_pdcp_config_security( const uint8_t send_security_mode_command ); +struct rrc_gNB_ue_context_s * +rrc_gNB_get_ue_context_from_ngap_ids( + const instance_t instanceP, + const uint16_t ue_initial_idP, + const uint32_t gNB_ue_ngap_idP +); + int rrc_gNB_process_PAGING_IND( MessageDef *msg_p, diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 9c3b6aada0..ff8149b83f 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -22,32 +22,6 @@ #include "rrc_gNB_radio_bearers.h" #include "oai_asn1.h" -NR_SRB_ToAddMod_t *generateSRB2() { - NR_SRB_ToAddMod_t *SRB2_config = NULL; - - SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - SRB2_config->srb_Identity = 2; - - return SRB2_config; -} - -NR_SRB_ToAddModList_t **generateSRB2_confList(gNB_RRC_UE_t *ue, - NR_SRB_ToAddModList_t *SRB_configList, - uint8_t xid) { - NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - - SRB_configList2 = &ue->SRB_configList2[xid]; - if (*SRB_configList2 == NULL) { - *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); - memset(*SRB_configList2, 0, sizeof(**SRB_configList2)); - NR_SRB_ToAddMod_t *SRB2_config = generateSRB2(); - asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); - asn1cSeqAdd(&SRB_configList->list, SRB2_config); - } - - return SRB_configList2; -} - NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, const pdu_session_param_t *pduSession, diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index a686fed767..86ab093ced 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -35,10 +35,6 @@ #define GBR_FLOW (1) #define NONGBR_FLOW (0) -NR_SRB_ToAddMod_t *generateSRB2(void); -NR_SRB_ToAddModList_t **generateSRB2_confList(gNB_RRC_UE_t *ue, - NR_SRB_ToAddModList_t *SRB_configList, - uint8_t xid); NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *rrc_ue, uint8_t drb_id, const pdu_session_param_t *pduSession, diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 09e80feccf..e9a22eb578 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -35,6 +35,8 @@ typedef struct { static nr_sdap_entity_info sdap_info; +instance_t *N3GTPUInst = NULL; + nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager(void); void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu) @@ -216,7 +218,8 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, req->ue_id = ue_id; req->bearer_id = pdusession_id; LOG_D(SDAP, "%s() sending message to gtp size %d\n", __func__, size-offset); - itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); + // very very dirty hack gloabl var N3GTPUInst + itti_send_msg_to_task(TASK_GTPV1_U, *N3GTPUInst, message_p); } else { //nrUE /* * TS 37.324 5.2 Data transfer diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index e8ed236fd1..4b5303a5b6 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -51,6 +51,9 @@ * the GTP-U Extension Header. Inside the DL PDU SESSION INFORMATION frame. * TS 38.415 Fig. 5.5.2.1-1 */ + +extern instance_t *N3GTPUInst; + typedef struct nr_sdap_dl_hdr_s { uint8_t QFI:6; uint8_t RQI:1; diff --git a/openair3/MME_APP/mme_app.c b/openair3/MME_APP/mme_app.c index 2c1d524c15..43a5df2ac8 100644 --- a/openair3/MME_APP/mme_app.c +++ b/openair3/MME_APP/mme_app.c @@ -40,7 +40,8 @@ # include "intertask_interface.h" # include "s1ap_eNB.h" -#include "sctp_eNB_task.h" +# include "sctp_eNB_task.h" +# include "openair3/ocp-gtpu/gtp_itf.h" # include "x2ap_eNB.h" # include "x2ap_messages_types.h" diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index ab2503f1d5..47f4b8445d 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -48,10 +48,7 @@ #include "conversions.h" #include "NGAP_NonDynamic5QIDescriptor.h" -static -int ngap_gNB_handle_ng_setup_response(uint32_t assoc_id, - uint32_t stream, - NGAP_NGAP_PDU_t *pdu); +static int ngap_gNB_handle_ng_setup_response(uint32_t ssoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu); static int ngap_gNB_handle_ng_setup_failure(uint32_t assoc_id, uint32_t stream, @@ -188,8 +185,7 @@ void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shut /* If there are no more associated AMF, inform gNB app */ if (amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb == 0) { - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DEREGISTERED_GNB_IND); + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DEREGISTERED_GNB_IND); NGAP_DEREGISTERED_GNB_IND(message_p).nb_amf = 0; itti_send_msg_to_task(TASK_GNB_APP, amf_desc_p->ngap_gNB_instance->instance, message_p); } @@ -206,8 +202,7 @@ void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shut /* If there are no more pending messages, inform gNB app */ if (amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb == 0) { - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_REGISTER_GNB_CNF); + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_REGISTER_GNB_CNF); NGAP_REGISTER_GNB_CNF(message_p).nb_amf = amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb; itti_send_msg_to_task(TASK_GNB_APP, amf_desc_p->ngap_gNB_instance->instance, message_p); } @@ -838,7 +833,6 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, int i; ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_ue_context_t *ue_desc_p = NULL; - MessageDef *message_p = NULL; NGAP_InitialContextSetupRequest_t *container; NGAP_InitialContextSetupRequestIEs_t *ie; NGAP_RAN_UE_NGAP_ID_t ran_ue_ngap_id; @@ -890,20 +884,21 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, ue_desc_p->rx_stream = stream; ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id; - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_INITIAL_CONTEXT_SETUP_REQ); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_INITIAL_CONTEXT_SETUP_REQ); + ngap_initial_context_setup_req_t * msg=&NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p); + msg->ue_initial_id = ue_desc_p->ue_initial_id; ue_desc_p->ue_initial_id = 0; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; + msg->gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; + msg->amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; /* id-UEAggregateMaximumBitRate */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, false); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL), - &(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul)); + &(msg->ue_ambr.br_ul)); asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL), - &(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl)); + &(msg->ue_ambr.br_dl)); } else { NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate\n"); } @@ -914,12 +909,12 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_GUAMI, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mcc, - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mnc, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mnc_len); + TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, msg->guami.mcc, + msg->guami.mnc, msg->guami.mnc_len); - OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFRegionID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_region_id); - OCTET_STRING_TO_INT16(&ie->value.choice.GUAMI.aMFSetID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_set_id); - OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFPointer, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_pointer); + OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFRegionID, msg->guami.amf_region_id); + OCTET_STRING_TO_INT16(&ie->value.choice.GUAMI.aMFSetID, msg->guami.amf_set_id); + OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFPointer, msg->guami.amf_pointer); } else {/* ie != NULL */ return -1; } @@ -928,7 +923,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq, false); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_pdusessions = + msg->nb_of_pdusessions = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; for (i = 0; i < ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; i++) { @@ -938,19 +933,19 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL; item_p = (NGAP_PDUSessionResourceSetupItemCxtReq_t *)ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i]; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID; if (item_p->nAS_PDU != NULL) { /* Only copy NAS pdu if present */ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.length = item_p->nAS_PDU->size; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer = + msg->pdusession_param[i].nas_pdu.length = item_p->nAS_PDU->size; + msg->pdusession_param[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); - memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer, + memcpy(msg->pdusession_param[i].nas_pdu.buffer, item_p->nAS_PDU->buf, item_p->nAS_PDU->size); NGAP_DEBUG("Received NAS message with the PDUSESSION setup procedure\n"); } else { - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.length = 0; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer = NULL; + msg->pdusession_param[i].nas_pdu.length = 0; + msg->pdusession_param[i].nas_pdu.buffer = NULL; } @@ -979,14 +974,14 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; /* Set the transport layer address */ - memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.buffer, + memcpy(msg->pdusession_param[i].upf_addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.length = + msg->pdusession_param[i].upf_addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; /* GTP tunnel endpoint ID */ - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].gtp_teid); + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, msg->pdusession_param[i].gtp_teid); } break; @@ -1001,7 +996,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, /* mandatory PDUSessionType */ case NGAP_ProtocolIE_ID_id_PDUSessionType: - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; + msg->pdusession_param[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; break; /* optional SecurityIndication */ @@ -1021,25 +1016,25 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count > 0); DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count <= NGAP_maxnoofQosFlows); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; + msg->pdusession_param[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; qosIdx++) { qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx]; /* Set the QOS informations */ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + msg->pdusession_param[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){ if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].fiveQI = + msg->pdusession_param[i].qos[qosIdx].fiveQI = (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI; } } - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.priority_level = + msg->pdusession_param[i].qos[qosIdx].allocation_retention_priority.priority_level = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + msg->pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + msg->pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionVulnerability; } } @@ -1051,14 +1046,14 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, break; default: - NGAP_ERROR("could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); + NGAP_ERROR("Not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); return -1; } } } /* for i... */ } else {/* ie != NULL */ - NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq\n"); + NGAP_ERROR("Not found NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq\n"); } /* id-AllowedNSSAI */ @@ -1075,35 +1070,35 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, if (ie == NULL) { NGAP_WARN("AllowedNSSAI not present, forging 2 NSSAI\n"); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_allowed_nssais = 2; + msg->nb_allowed_nssais = 2; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sST = 01; + msg->allowed_nssai[0].sST = 01; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD_flag = 1; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[0] = 01; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[1] = 02; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[2] = 03; + msg->allowed_nssai[0].sD_flag = 1; + msg->allowed_nssai[0].sD[0] = 01; + msg->allowed_nssai[0].sD[1] = 02; + msg->allowed_nssai[0].sD[2] = 03; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sST = 01; + msg->allowed_nssai[1].sST = 01; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD_flag = 1; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[0] = 00;//11; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[1] = 00;//22; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[2] = 01;//33; + msg->allowed_nssai[1].sD_flag = 1; + msg->allowed_nssai[1].sD[0] = 00;//11; + msg->allowed_nssai[1].sD[1] = 00;//22; + msg->allowed_nssai[1].sD[2] = 01;//33; } else { NGAP_INFO("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count; + msg->nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count; for(i = 0; i < ie->value.choice.AllowedNSSAI.list.count; i++) { allow_nssai_item_p = ie->value.choice.AllowedNSSAI.list.array[i]; - OCTET_STRING_TO_INT8(&allow_nssai_item_p->s_NSSAI.sST, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sST); + OCTET_STRING_TO_INT8(&allow_nssai_item_p->s_NSSAI.sST, msg->allowed_nssai[i].sST); if(allow_nssai_item_p->s_NSSAI.sD != NULL) { - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD_flag = 1; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[0] = allow_nssai_item_p->s_NSSAI.sD->buf[0]; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[1] = allow_nssai_item_p->s_NSSAI.sD->buf[1]; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[2] = allow_nssai_item_p->s_NSSAI.sD->buf[2]; + msg->allowed_nssai[i].sD_flag = 1; + msg->allowed_nssai[i].sD[0] = allow_nssai_item_p->s_NSSAI.sD->buf[0]; + msg->allowed_nssai[i].sD[1] = allow_nssai_item_p->s_NSSAI.sD->buf[1]; + msg->allowed_nssai[i].sD[2] = allow_nssai_item_p->s_NSSAI.sD->buf[2]; } } } @@ -1116,13 +1111,13 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_UESecurityCapabilities, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.nRencryption_algorithms = + msg->security_capabilities.nRencryption_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRencryptionAlgorithms); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.nRintegrity_algorithms = + msg->security_capabilities.nRintegrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRintegrityProtectionAlgorithms); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.eUTRAencryption_algorithms = + msg->security_capabilities.eUTRAencryption_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAencryptionAlgorithms); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.eUTRAintegrity_algorithms = + msg->security_capabilities.eUTRAintegrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAintegrityProtectionAlgorithms); } else {/* ie != NULL */ return -1; @@ -1133,7 +1128,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_SecurityKey, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - memcpy(&NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, + memcpy(&msg->security_key, ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); } else {/* ie != NULL */ @@ -1148,11 +1143,11 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_MobilityRestrictionList_t *mobility_rest_list_p = NULL; mobility_rest_list_p = &ie->value.choice.MobilityRestrictionList; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction_flag = 1; + msg->mobility_restriction_flag = 1; TBCD_TO_MCC_MNC(&mobility_rest_list_p->servingPLMN, - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mcc, - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mnc, - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mnc_digit_length); + msg->mobility_restriction.serving_plmn.mcc, + msg->mobility_restriction.serving_plmn.mnc, + msg->mobility_restriction.serving_plmn.mnc_digit_length); } @@ -1162,10 +1157,10 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ if(ie->value.choice.NAS_PDU.size > 0) { - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu_flag = 1; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); - memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.buffer, + msg->nas_pdu_flag = 1; + msg->nas_pdu.length = ie->value.choice.NAS_PDU.size; + msg->nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); + memcpy(msg->nas_pdu.buffer, ie->value.choice.NAS_PDU.buf, ie->value.choice.NAS_PDU.size); } } @@ -1259,7 +1254,6 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, NGAP_RAN_UE_NGAP_ID_t ran_ue_ngap_id; ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_ue_context_t *ue_desc_p = NULL; - MessageDef *message_p = NULL; NGAP_PDUSessionResourceSetupRequest_t *container; NGAP_PDUSessionResourceSetupRequestIEs_t *ie; DevAssert(pdu != NULL); @@ -1313,17 +1307,26 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); } - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_SETUP_REQ); - NGAP_PDUSESSION_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + MessageDef * message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_SETUP_REQ); + ngap_pdusession_setup_req_t * msg=&NGAP_PDUSESSION_SETUP_REQ(message_p); + msg->ue_initial_id = ue_desc_p->ue_initial_id; ue_desc_p->ue_initial_id = 0; - NGAP_PDUSESSION_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; - NGAP_PDUSESSION_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; + msg->gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; + msg->amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; + + /* UE Aggregated Maximum Bitrate */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, true); + asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL), + &msg->ueAggMaxBitRateUplink); + asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL), + &msg->ueAggMaxBitRateDownlink); NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSUReq, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_PDUSESSION_SETUP_REQ(message_p).nb_pdusessions_tosetup = + msg->nb_pdusessions_tosetup = ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; for (int i = 0; i < ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; i++) { @@ -1332,20 +1335,29 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer_p = NULL; NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL; + // PDU session ID item_p = (NGAP_PDUSessionResourceSetupItemSUReq_t *)ie->value.choice.PDUSessionResourceSetupListSUReq.list.array[i]; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID; + // S-NSSAI + OCTET_STRING_TO_INT8(&item_p->s_NSSAI.sST, msg->allowed_nssai[i].sST); + if(item_p->s_NSSAI.sD != NULL) { + msg->allowed_nssai[i].sD_flag = 1; + msg->allowed_nssai[i].sD[0] = item_p->s_NSSAI.sD->buf[0]; + msg->allowed_nssai[i].sD[1] = item_p->s_NSSAI.sD->buf[1]; + msg->allowed_nssai[i].sD[2] = item_p->s_NSSAI.sD->buf[2]; + } // check for the NAS PDU if (item_p->pDUSessionNAS_PDU->size > 0 ) { - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length = item_p->pDUSessionNAS_PDU->size; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionNAS_PDU->size); - memcpy(NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer, + msg->pdusession_setup_params[i].nas_pdu.length = item_p->pDUSessionNAS_PDU->size; + msg->pdusession_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionNAS_PDU->size); + memcpy(msg->pdusession_setup_params[i].nas_pdu.buffer, item_p->pDUSessionNAS_PDU->buf, item_p->pDUSessionNAS_PDU->size); - // NGAP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]); + // NGAP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",msg->pdusession_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]); } else { - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length = 0; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer = NULL; + msg->pdusession_setup_params[i].nas_pdu.length = 0; + msg->pdusession_setup_params[i].nas_pdu.buffer = NULL; NGAP_WARN("NAS PDU is not provided, generate a PDUSESSION_SETUP Failure (TBD) back to AMF \n"); } @@ -1374,10 +1386,10 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, NGAP_GTPTunnel_t *gTPTunnel_p; gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; /* The transport layer address for the IP packets */ - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].gtp_teid); - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.length = + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, msg->pdusession_setup_params[i].gtp_teid); + msg->pdusession_setup_params[i].upf_addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; - memcpy(NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.buffer , + memcpy(msg->pdusession_setup_params[i].upf_addr.buffer , gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); } break; @@ -1392,7 +1404,7 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, /* mandatory PDUSessionType */ case NGAP_ProtocolIE_ID_id_PDUSessionType: - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; + msg->pdusession_setup_params[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; break; /* optional SecurityIndication */ @@ -1412,24 +1424,28 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count > 0); DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count <= NGAP_maxnoofQosFlows); - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; + msg->pdusession_setup_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; qosIdx++){ qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx]; /* Set the QOS informations */ - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + msg->pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){ + msg->pdusession_setup_params[i].qos[qosIdx].fiveQI_type = non_dynamic; if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){ - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI = + msg->pdusession_setup_params[i].qos[qosIdx].fiveQI = (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI; } + } else if (qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_dynamic5QI) + { + msg->pdusession_setup_params[i].qos[qosIdx].fiveQI_type = dynamic; } - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level = + msg->pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + msg->pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + msg->pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionVulnerability; } } @@ -1461,7 +1477,6 @@ int ngap_gNB_handle_paging(uint32_t assoc_id, ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_instance_t *ngap_gNB_instance = NULL; - MessageDef *message_p = NULL; NGAP_Paging_t *container; NGAP_PagingIEs_t *ie; DevAssert(pdu != NULL); @@ -1490,42 +1505,44 @@ int ngap_gNB_handle_paging(uint32_t assoc_id, return -1; } - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PAGING_IND); + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PAGING_IND); + ngap_paging_ind_t * msg=&NGAP_PAGING_IND(message_p); + /* convert NGAP_PagingIEs_t to ngap_paging_ind_t */ /* id-UEIdentityIndexValue : convert UE Identity Index value */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UEPagingIdentity, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - OCTET_STRING_TO_INT16(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFSetID, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id); - OCTET_STRING_TO_INT8(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFPointer, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer); - OCTET_STRING_TO_INT32(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->fiveG_TMSI, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi); + OCTET_STRING_TO_INT16(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFSetID, msg->ue_paging_identity.s_tmsi.amf_set_id); + OCTET_STRING_TO_INT8(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFPointer, msg->ue_paging_identity.s_tmsi.amf_pointer); + OCTET_STRING_TO_INT32(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->fiveG_TMSI, msg->ue_paging_identity.s_tmsi.m_tmsi); NGAP_DEBUG("[SCTP %d] Received Paging Identity amf_set_id %d, amf_pointer %d, m_tmsi %d\n", assoc_id, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi); + msg->ue_paging_identity.s_tmsi.amf_set_id, + msg->ue_paging_identity.s_tmsi.amf_pointer, + msg->ue_paging_identity.s_tmsi.m_tmsi); } else { return -1; } - NGAP_PAGING_IND(message_p).paging_drx = NGAP_PAGING_DRX_256; + msg->paging_drx = NGAP_PAGING_DRX_256; /* id-pagingDRX */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PagingDRX, false); /* optional */ if (ie) { - NGAP_PAGING_IND(message_p).paging_drx = ie->value.choice.PagingDRX; + msg->paging_drx = ie->value.choice.PagingDRX; } else { - NGAP_PAGING_IND(message_p).paging_drx = NGAP_PAGING_DRX_256; + msg->paging_drx = NGAP_PAGING_DRX_256; } - memset (&NGAP_PAGING_IND(message_p).plmn_identity[0], 0, sizeof(plmn_identity_t)*256); - memset (&NGAP_PAGING_IND(message_p).tac[0], 0, sizeof(int16_t)*256); - NGAP_PAGING_IND(message_p).tai_size = 0; + memset (&msg->plmn_identity[0], 0, sizeof(plmn_identity_t)*256); + memset (&msg->tac[0], 0, sizeof(int16_t)*256); + msg->tai_size = 0; /* id-TAIList */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_TAIListForPaging, true); @@ -1536,15 +1553,15 @@ int ngap_gNB_handle_paging(uint32_t assoc_id, for (int i = 0; i < ie->value.choice.TAIListForPaging.list.count; i++) { NGAP_TAIListForPagingItem_t *item_p; item_p = (NGAP_TAIListForPagingItem_t *)ie->value.choice.TAIListForPaging.list.array[i]; - TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNIdentity), NGAP_PAGING_IND(message_p).plmn_identity[i].mcc, - NGAP_PAGING_IND(message_p).plmn_identity[i].mnc, - NGAP_PAGING_IND(message_p).plmn_identity[i].mnc_digit_length); - OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), NGAP_PAGING_IND(message_p).tac[i]); - NGAP_PAGING_IND(message_p).tai_size++; + TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNIdentity), msg->plmn_identity[i].mcc, + msg->plmn_identity[i].mnc, + msg->plmn_identity[i].mnc_digit_length); + OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), msg->tac[i]); + msg->tai_size++; NGAP_DEBUG("[SCTP %d] Received Paging: MCC %d, MNC %d, TAC %d\n", assoc_id, - NGAP_PAGING_IND(message_p).plmn_identity[i].mcc, - NGAP_PAGING_IND(message_p).plmn_identity[i].mnc, - NGAP_PAGING_IND(message_p).tac[i]); + msg->plmn_identity[i].mcc, + msg->plmn_identity[i].mnc, + msg->tac[i]); } } else { return -1; @@ -1552,10 +1569,10 @@ int ngap_gNB_handle_paging(uint32_t assoc_id, //paging parameter values NGAP_DEBUG("[SCTP %d] Received Paging parameters: Paging Identity amf_set_id %d amf_pointer %d m_tmsi %d paging_drx %d paging_priority %d\n",assoc_id, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi, - NGAP_PAGING_IND(message_p).paging_drx, NGAP_PAGING_IND(message_p).paging_priority); + msg->ue_paging_identity.s_tmsi.amf_set_id, + msg->ue_paging_identity.s_tmsi.amf_pointer, + msg->ue_paging_identity.s_tmsi.m_tmsi, + msg->paging_drx, msg->paging_priority); /* send message to RRC */ itti_send_msg_to_task(TASK_RRC_GNB, ngap_gNB_instance->instance, message_p); @@ -1570,7 +1587,6 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, int i, nb_of_pdusessions_failed; ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_ue_context_t *ue_desc_p = NULL; - MessageDef *message_p = NULL; NGAP_PDUSessionResourceModifyRequest_t *container; NGAP_PDUSessionResourceModifyRequestIEs_t *ie; NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; @@ -1617,8 +1633,9 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) { NGAP_WARN("UE context amf_ue_ngap_id is different form that of the message (%ld != %ld)", (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP); - NGAP_PDUSESSION_MODIFY_RESP (message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; + MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP); + ngap_pdusession_modify_resp_t* msg=&NGAP_PDUSESSION_MODIFY_RESP(message_p); + msg->gNB_ue_ngap_id = gnb_ue_ngap_id; NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModReq, true); @@ -1627,32 +1644,32 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, NGAP_PDUSessionResourceModifyItemModReq_t *item_p; item_p = (NGAP_PDUSessionResourceModifyItemModReq_t *)ie->value.choice.PDUSessionResourceModifyListModReq.list.array[nb_of_pdusessions_failed]; - NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].pdusession_id = item_p->pDUSessionID; - NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].cause = NGAP_Cause_PR_radioNetwork; - NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].cause_value = NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID; + msg->pdusessions_failed[nb_of_pdusessions_failed].pdusession_id = item_p->pDUSessionID; + msg->pdusessions_failed[nb_of_pdusessions_failed].cause = NGAP_Cause_PR_radioNetwork; + msg->pdusessions_failed[nb_of_pdusessions_failed].cause_value = NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID; } } else { return -1; } - NGAP_PDUSESSION_MODIFY_RESP(message_p).nb_of_pdusessions_failed = nb_of_pdusessions_failed; - ngap_gNB_pdusession_modify_resp(amf_desc_p->ngap_gNB_instance->instance, - &NGAP_PDUSESSION_MODIFY_RESP(message_p)); + msg->nb_of_pdusessions_failed = nb_of_pdusessions_failed; + ngap_gNB_pdusession_modify_resp(amf_desc_p->ngap_gNB_instance->instance,msg); itti_free(TASK_RRC_GNB,message_p); message_p = NULL; return -1; } - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_MODIFY_REQ); - NGAP_PDUSESSION_MODIFY_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; - NGAP_PDUSESSION_MODIFY_REQ(message_p).amf_ue_ngap_id = amf_ue_ngap_id; - NGAP_PDUSESSION_MODIFY_REQ(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_MODIFY_REQ); + ngap_pdusession_modify_req_t * msg=&NGAP_PDUSESSION_MODIFY_REQ(message_p); + msg->ue_initial_id = ue_desc_p->ue_initial_id; + msg->amf_ue_ngap_id = amf_ue_ngap_id; + msg->gNB_ue_ngap_id = gnb_ue_ngap_id; /* id-PDUSessionResourceModifyListModReq */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModReq, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_PDUSESSION_MODIFY_REQ(message_p).nb_pdusessions_tomodify = + msg->nb_pdusessions_tomodify = ie->value.choice.PDUSessionResourceModifyListModReq.list.count; for (i = 0; i < ie->value.choice.PDUSessionResourceModifyListModReq.list.count; i++) { @@ -1663,17 +1680,17 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, item_p = (NGAP_PDUSessionResourceModifyItemModReq_t *)ie->value.choice.PDUSessionResourceModifyListModReq.list.array[i]; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession_modify_params[i].pdusession_id = item_p->pDUSessionID; // check for the NAS PDU if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0 ) { - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.length = item_p->nAS_PDU->size; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); - memcpy(NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer, + msg->pdusession_modify_params[i].nas_pdu.length = item_p->nAS_PDU->size; + msg->pdusession_modify_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); + memcpy(msg->pdusession_modify_params[i].nas_pdu.buffer, item_p->nAS_PDU->buf, item_p->nAS_PDU->size); } else { - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.length = 0; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer = NULL; + msg->pdusession_modify_params[i].nas_pdu.length = 0; + msg->pdusession_modify_params[i].nas_pdu.buffer = NULL; continue; } @@ -1718,25 +1735,25 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, DevAssert(pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count > 0); DevAssert(pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count <= NGAP_maxnoofQosFlows); - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; + msg->pdusession_modify_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; qosIdx++) { qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[qosIdx]; /* Set the QOS informations */ - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + msg->pdusession_modify_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; if(qosFlowItem_p->qosFlowLevelQosParameters) { if (qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].fiveQI = + msg->pdusession_modify_params[i].qos[qosIdx].fiveQI = qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.choice.nonDynamic5QI->fiveQI; } else if (qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.present == NGAP_QosCharacteristics_PR_dynamic5QI) { // TODO } - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.priority_level = + msg->pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.priority_level = qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.priorityLevelARP; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + msg->pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionCapability; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + msg->pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionVulnerability; } } @@ -1784,7 +1801,6 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, int i; ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_ue_context_t *ue_desc_p = NULL; - MessageDef *message_p = NULL; NGAP_PDUSessionResourceReleaseCommand_t *container; NGAP_PDUSessionResourceReleaseCommandIEs_t *ie; NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; @@ -1841,22 +1857,24 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, NGAP_DEBUG("[SCTP %d] Received pdu session release command for gNB_UE_NGAP_ID %lu amf_ue_ngap_id %lu\n", assoc_id, gnb_ue_ngap_id, amf_ue_ngap_id); - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_RELEASE_COMMAND); - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).amf_ue_ngap_id = amf_ue_ngap_id; + MessageDef * message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_RELEASE_COMMAND); + ngap_pdusession_release_command_t * msg=&NGAP_PDUSESSION_RELEASE_COMMAND(message_p); + + msg->gNB_ue_ngap_id = gnb_ue_ngap_id; + msg->amf_ue_ngap_id = amf_ue_ngap_id; /* id-NAS-PDU */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_NAS_PDU, false); if(ie && ie->value.choice.NAS_PDU.size > 0) { - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); - memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer, + msg->nas_pdu.length = ie->value.choice.NAS_PDU.size; + msg->nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); + memcpy(msg->nas_pdu.buffer, ie->value.choice.NAS_PDU.buf, ie->value.choice.NAS_PDU.size); } else { - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.length = 0; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL; + msg->nas_pdu.length = 0; + msg->nas_pdu.buffer = NULL; } /* id-PDUSessionResourceToReleaseListRelCmd */ @@ -1864,22 +1882,22 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_PDUSessionResourceToReleaseListRelCmd, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nb_pdusessions_torelease = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; + msg->nb_pdusessions_torelease = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) { NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p; item_p = (NGAP_PDUSessionResourceToReleaseItemRelCmd_t *)ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i]; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession_release_params[i].pdusession_id = item_p->pDUSessionID; if(item_p->pDUSessionResourceReleaseCommandTransfer.size > 0) { - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = item_p->pDUSessionResourceReleaseCommandTransfer.size; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionResourceReleaseCommandTransfer.size); - memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer, + msg->pdusession_release_params[i].transfer_length = item_p->pDUSessionResourceReleaseCommandTransfer.size; + msg->pdusession_release_params[i].transfer_buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionResourceReleaseCommandTransfer.size); + memcpy(msg->pdusession_release_params[i].transfer_buffer, item_p->pDUSessionResourceReleaseCommandTransfer.buf, item_p->pDUSessionResourceReleaseCommandTransfer.size); }else { - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = 0; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = NULL; + msg->pdusession_release_params[i].transfer_length = 0; + msg->pdusession_release_params[i].transfer_buffer = NULL; NGAP_ERROR("[NGAP] Received pdu session release command for pDUSessionResourceReleaseCommandTransfer is NULL!\n"); } NGAP_DEBUG("[NGAP] Received pdu session release command for pDUSessionID id %ld\n", item_p->pDUSessionID); diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index 49a0674bdf..14128dd53e 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -617,10 +617,7 @@ sctp_handle_new_association_req( } //------------------------------------------------------------------------------ -static void sctp_send_data( - instance_t instance, - task_id_t task_id, - sctp_data_req_t *sctp_data_req_p) +static void sctp_send_data(sctp_data_req_t *sctp_data_req_p) { struct sctp_cnx_list_elm_s *sctp_cnx = NULL; @@ -660,10 +657,7 @@ static void sctp_send_data( } //------------------------------------------------------------------------------ -static int sctp_close_association( - const instance_t instance, - const task_id_t requestor, - sctp_close_association_t *close_association_p) +static int sctp_close_association(sctp_close_association_t *close_association_p) { struct sctp_cnx_list_elm_s *sctp_cnx = NULL; @@ -1152,10 +1146,8 @@ static void sctp_eNB_process_itti_msg() break; case SCTP_CLOSE_ASSOCIATION: - sctp_close_association(ITTI_MSG_DESTINATION_INSTANCE(received_msg), - ITTI_MSG_ORIGIN_ID(received_msg), - &received_msg->ittiMsg.sctp_close_association); - break; + sctp_close_association(&received_msg->ittiMsg.sctp_close_association); + break; case TERMINATE_MESSAGE: SCTP_WARN("*** Exiting SCTP thread\n"); @@ -1163,9 +1155,7 @@ static void sctp_eNB_process_itti_msg() break; case SCTP_DATA_REQ: { - sctp_send_data(ITTI_MSG_DESTINATION_INSTANCE(received_msg), - ITTI_MSG_ORIGIN_ID(received_msg), - &received_msg->ittiMsg.sctp_data_req); + sctp_send_data(&received_msg->ittiMsg.sctp_data_req); } break; diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 8045e7f635..b598a29c16 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -94,7 +94,6 @@ typedef struct Gtpv1uExtHeader { #define GTP_END_MARKER (254) #define GTP_GPDU (255) - typedef struct gtpv1u_bearer_s { /* TEID used in dl and ul */ teid_t teid_incoming; ///< eNB TEID @@ -127,8 +126,7 @@ class gtpEndPoint { uint8_t foundAddr[20]; int foundAddrLen; int ipVersion; - map ue2te_mapping; - map te2ue_mapping; + map ue2te_mapping; // we use the same port number for source and destination address // this allow using non standard gtp port number (different from 2152) // and so, for example tu run 4G and 5G cores on one system @@ -142,7 +140,7 @@ class gtpEndPoints { pthread_mutex_t gtp_lock=PTHREAD_MUTEX_INITIALIZER; // the instance id will be the Linux socket handler, as this is uniq map instances; - + map te2ue_mapping; gtpEndPoints() { unsigned int seed; fill_random(&seed, sizeof(seed)); @@ -593,22 +591,17 @@ teid_t newGtpuCreateTunnel(instance_t instance, teid_t incoming_teid=gtpv1uNewTeid(); - while ( inst->te2ue_mapping.find(incoming_teid) != inst->te2ue_mapping.end() ) { + while (globGtp.te2ue_mapping.find(incoming_teid) != globGtp.te2ue_mapping.end()) { LOG_W(GTPU, "[%ld] generated a random Teid that exists, re-generating (%x)\n", instance, incoming_teid); incoming_teid=gtpv1uNewTeid(); }; - inst->te2ue_mapping[incoming_teid].ue_id=ue_id; - - inst->te2ue_mapping[incoming_teid].incoming_rb_id= incoming_bearer_id; - - inst->te2ue_mapping[incoming_teid].outgoing_teid= outgoing_teid; - - inst->te2ue_mapping[incoming_teid].callBack=callBack; - - inst->te2ue_mapping[incoming_teid].callBackSDAP = callBackSDAP; - - inst->te2ue_mapping[incoming_teid].pdusession_id = (uint8_t)outgoing_bearer_id; + globGtp.te2ue_mapping[incoming_teid].ue_id = ue_id; + globGtp.te2ue_mapping[incoming_teid].incoming_rb_id = incoming_bearer_id; + globGtp.te2ue_mapping[incoming_teid].outgoing_teid = outgoing_teid; + globGtp.te2ue_mapping[incoming_teid].callBack = callBack; + globGtp.te2ue_mapping[incoming_teid].callBackSDAP = callBackSDAP; + globGtp.te2ue_mapping[incoming_teid].pdusession_id = (uint8_t)outgoing_bearer_id; gtpv1u_bearer_t *tmp=&inst->ue2te_mapping[ue_id].bearers[outgoing_bearer_id]; @@ -641,13 +634,14 @@ teid_t newGtpuCreateTunnel(instance_t instance, pthread_mutex_unlock(&globGtp.gtp_lock); char ip4[INET_ADDRSTRLEN]; char ip6[INET6_ADDRSTRLEN]; - LOG_I(GTPU, "[%ld] Created tunnel for UE ID %lu, teid for DL: %x, teid for UL %x to remote IPv4: %s, IPv6 %s\n", + LOG_I(GTPU, + "[%ld] Created tunnel for UE ID %lu, teid for incoming: %x, teid for outgoing %x to remote IPv4: %s, IPv6 %s\n", instance, ue_id, tmp->teid_incoming, tmp->teid_outgoing, - inet_ntop(AF_INET,(void *)&tmp->outgoing_ip_addr, ip4,INET_ADDRSTRLEN ), - inet_ntop(AF_INET6,(void *)&tmp->outgoing_ip6_addr.s6_addr, ip6, INET6_ADDRSTRLEN)); + inet_ntop(AF_INET, (void *)&tmp->outgoing_ip_addr, ip4, INET_ADDRSTRLEN), + inet_ntop(AF_INET6, (void *)&tmp->outgoing_ip6_addr.s6_addr, ip6, INET6_ADDRSTRLEN)); return incoming_teid; } @@ -795,7 +789,7 @@ int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { for (auto j=ptrUe->second.bearers.begin(); j!=ptrUe->second.bearers.end(); ++j) { - inst->te2ue_mapping.erase(j->second.teid_incoming); + globGtp.te2ue_mapping.erase(j->second.teid_incoming); nb++; } @@ -826,7 +820,7 @@ int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdus if ( ptr2 == ptrUe->second.bearers.end() ) { LOG_E(GTPU,"[%ld] GTP-U instance: delete of not existing tunnel UE ID:RAB: %ld/%x\n", instance, ue_id, pdusession_id[i]); } else { - inst->te2ue_mapping.erase(ptr2->second.teid_incoming); + globGtp.te2ue_mapping.erase(ptr2->second.teid_incoming); nb++; } } @@ -913,9 +907,9 @@ static int Gtpv1uHandleEndMarker(int h, // the socket Linux file handler is the instance id getInstRetInt(h); - auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid)); + auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); - if ( tunnel == inst->te2ue_mapping.end() ) { + if (tunnel == globGtp.te2ue_mapping.end()) { LOG_E(GTPU,"[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, msgHdr->teid); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; @@ -973,10 +967,9 @@ static int Gtpv1uHandleGpdu(int h, pthread_mutex_lock(&globGtp.gtp_lock); // the socket Linux file handler is the instance id getInstRetInt(h); + auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); - auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid)); - - if ( tunnel == inst->te2ue_mapping.end() ) { + if (tunnel == globGtp.te2ue_mapping.end()) { LOG_E(GTPU,"[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, ntohl(msgHdr->teid)); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; @@ -1143,10 +1136,7 @@ static int Gtpv1uHandleGpdu(int h, * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ extensionHeader->length = 1+sizeof(DlDataDeliveryStatus_flagsT)+3+1+1; gtpv1uCreateAndSendMsg( - h, peerIp, peerPort, GTP_GPDU, - inst->te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, - NULL, 0, false, false, 0, 0, NR_RAN_CONTAINER, - extensionHeader->buffer, extensionHeader->length); + h, peerIp, peerPort, GTP_GPDU, globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, NULL, 0, false, false, 0, 0, NR_RAN_CONTAINER, extensionHeader->buffer, extensionHeader->length); } LOG_D(GTPU,"[%d] Received a %d bytes packet for: teid:%x\n", h, @@ -1224,19 +1214,19 @@ void *gtpv1uTask(void *args) { if (message_p != NULL ) { openAddr_t addr= {0}; - - switch (ITTI_MSG_ID(message_p)) { - // DATA TO BE SENT TO UDP + const instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(message_p); + const int msgType = ITTI_MSG_ID(message_p); + LOG_D(GTPU, "GTP-U received %s for instance %ld\n", messages_info[msgType].name, myInstance); + switch (msgType) { + // DATA TO BE SENT TO UDP case GTPV1U_TUNNEL_DATA_REQ: { - gtpv1uSend(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), - >PV1U_TUNNEL_DATA_REQ(message_p), false, false); + gtpv1uSend(compatInst(myInstance), >PV1U_TUNNEL_DATA_REQ(message_p), false, false); } break; case GTPV1U_DU_BUFFER_REPORT_REQ:{ - gtpv1uSendDlDeliveryStatus(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), - >PV1U_DU_BUFFER_REPORT_REQ(message_p)); + gtpv1uSendDlDeliveryStatus(compatInst(myInstance), >PV1U_DU_BUFFER_REPORT_REQ(message_p)); } break; @@ -1248,8 +1238,7 @@ void *gtpv1uTask(void *args) { break; case GTPV1U_ENB_END_MARKER_REQ: - gtpv1uEndTunnel(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), - >PV1U_TUNNEL_DATA_REQ(message_p)); + gtpv1uEndTunnel(compatInst(myInstance), >PV1U_TUNNEL_DATA_REQ(message_p)); itti_free(TASK_GTPV1_U, GTPV1U_TUNNEL_DATA_REQ(message_p).buffer); break; diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index 86d719c200..8729be9fa5 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -93,8 +93,8 @@ extern "C" { gtpCallbackSDAP callBackSDAP); void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, - ue_id_t ue_id, - ebi_t bearer_id, + ue_id_t ue_id, + ebi_t bearer_id, in_addr_t newOutgoingAddr, teid_t newOutgoingTeid); @@ -149,7 +149,7 @@ extern "C" { //RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node; } gtpv1u_ue_data_t; - + #ifdef __cplusplus } #endif From 472e916af62ddcb3ffd70733256f6be0db7fc35f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Feb 2023 18:00:26 +0100 Subject: [PATCH 2/7] Add Dockerfile for nr-cuup --- docker/Dockerfile.nr-cuup.ubuntu18 | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 docker/Dockerfile.nr-cuup.ubuntu18 diff --git a/docker/Dockerfile.nr-cuup.ubuntu18 b/docker/Dockerfile.nr-cuup.ubuntu18 new file mode 100644 index 0000000000..94d1ff5ef7 --- /dev/null +++ b/docker/Dockerfile.nr-cuup.ubuntu18 @@ -0,0 +1,63 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest as gnb-base + +FROM ran-build:latest AS gnb-build + +RUN cp /oai-ran/docker/scripts/gnb_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +FROM ubuntu:bionic as oai-nr-cuup +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + libsctp1 \ + libconfig9 \ + openssl && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /opt/oai-gnb/bin +COPY --from=gnb-build \ + /oai-ran/cmake_targets/ran_build/build/nr-cuup \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +COPY --from=gnb-build \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ + /usr/local/lib/ + +# Create directory for configuration files +WORKDIR /opt/oai-gnb/etc + +WORKDIR /opt/oai-gnb +ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] +CMD ["/opt/oai-gnb/bin/nr-cuup", "-O", "/opt/oai-gnb/etc/gnb.conf"] From e8595334547f47565f86ad62734a33db58473543 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Feb 2023 18:00:02 +0100 Subject: [PATCH 3/7] Build nr-cuup in CI (ubuntu) --- ci-scripts/cls_containerize.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index e02d208945..38305b5b4e 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -360,6 +360,7 @@ class Containerize(): if result is not None: imageNames.append(('oai-enb', 'eNB')) imageNames.append(('oai-gnb', 'gNB')) + imageNames.append(('oai-nr-cuup', 'nr-cuup')) imageNames.append(('oai-lte-ue', 'lteUE')) imageNames.append(('oai-nr-ue', 'nrUE')) if self.host == 'Red Hat': @@ -680,7 +681,7 @@ class Containerize(): orgTag = 'develop' if self.ranAllowMerge: orgTag = 'ci-temp' - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru'] + imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: tagToUse = self.ImageTagToUse(image) mySSH.command(f'docker image tag {image}:{orgTag} {tagToUse}', '\$', 5) @@ -814,7 +815,7 @@ class Containerize(): else: logging.debug('Removing test images locally') - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru'] + imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: cmd = f'docker rmi {self.ImageTagToUse(image)} || true' if lIpAddr != 'none': @@ -856,7 +857,7 @@ class Containerize(): mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) mySSH.command('cp docker-compose.yml ci-docker-compose.yml', '\$', 5) - imagesList = ['oai-enb', 'oai-gnb'] + imagesList = ['oai-enb', 'oai-gnb', 'oai-nr-cuup'] for image in imagesList: imageToUse = self.ImageTagToUse(image) mySSH.command(f'sed -i -e "s#image: {image}:latest#image: {imageToUse}#" ci-docker-compose.yml', '\$', 2) @@ -1066,7 +1067,7 @@ class Containerize(): cmd = 'cd ' + self.yamlPath[0] + ' && cp docker-compose.y*ml docker-compose-ci.yml' subprocess.run(cmd, shell=True) - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru'] + imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: tagToUse = self.ImageTagToUse(image) cmd = f'cd {self.yamlPath[0]} && sed -i -e "s@{image}:develop@{tagToUse}@" docker-compose-ci.yml' @@ -1190,7 +1191,7 @@ class Containerize(): cmd = 'cd ' + self.yamlPath[0] + ' && cp docker-compose.y*ml docker-compose-ci.yml' logging.info(cmd) subprocess.run(cmd, shell=True) - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru'] + imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: tagToUse = self.ImageTagToUse(image) cmd = f'cd {self.yamlPath[0]} && sed -i -e "s@{image}:develop@{tagToUse}@" docker-compose-ci.yml' From 3ec0f5ee68b512218a33d101df4791ea8a9332b5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Feb 2023 12:21:19 +0100 Subject: [PATCH 4/7] Correct E1 config for containers --- .../{gnb-cucp.sa.conf => gnb-cucp.sa.f1.conf} | 35 +-- .../{gnb-cuup.sa.conf => gnb-cuup.sa.f1.conf} | 29 +-- .../gnb-du.band78.106prb.rfsim.conf | 245 ++++++++++++++++++ 3 files changed, 264 insertions(+), 45 deletions(-) rename ci-scripts/conf_files/{gnb-cucp.sa.conf => gnb-cucp.sa.f1.conf} (90%) rename ci-scripts/conf_files/{gnb-cuup.sa.conf => gnb-cuup.sa.f1.conf} (75%) create mode 100644 ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf diff --git a/ci-scripts/conf_files/gnb-cucp.sa.conf b/ci-scripts/conf_files/gnb-cucp.sa.f1.conf similarity index 90% rename from ci-scripts/conf_files/gnb-cucp.sa.conf rename to ci-scripts/conf_files/gnb-cucp.sa.f1.conf index 7932098584..0a2f88495e 100644 --- a/ci-scripts/conf_files/gnb-cucp.sa.conf +++ b/ci-scripts/conf_files/gnb-cucp.sa.f1.conf @@ -2,6 +2,7 @@ Active_gNBs = ( "gNB-OAI"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; Num_Threads_PUSCH = 8; +sa = 1; gNBs = ( @@ -15,27 +16,17 @@ gNBs = // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 1; - plmn_list = ({ - mcc = 208; - mnc = 99; - mnc_length = 2; - snssaiList = ( - { - sst = 1; - sd = 0x1; // 0 false, else true - } - ); - - }); + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); nr_cellid = 12345678L; + force_256qam_off = 1; tr_s_preference = "f1"; local_s_if_name = "lo"; - local_s_address = "127.0.0.4"; - remote_s_address = "127.0.0.3"; + local_s_address = "192.168.72.140"; + remote_s_address = "192.168.72.143"; local_s_portc = 501; local_s_portd = 2152; remote_s_portc = 500; @@ -187,7 +178,7 @@ gNBs = ////////// AMF parameters: - amf_ip_address = ( { ipv4 = "192.168.70.132"; + amf_ip_address = ( { ipv4 = "192.168.71.132"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -198,21 +189,17 @@ gNBs = ( { type = "cp"; - ipv4_cucp = "127.0.0.4"; - port_cucp = 2152; - ipv4_cuup = "127.0.0.5"; - port_cuup = 2152; + ipv4_cucp = "192.168.72.140"; + port_cucp = 38462; + ipv4_cuup = "192.168.72.141"; + port_cuup = 38462; } ) NETWORK_INTERFACES : { - GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; - GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; - GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; - GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/24"; }; } ); diff --git a/ci-scripts/conf_files/gnb-cuup.sa.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf similarity index 75% rename from ci-scripts/conf_files/gnb-cuup.sa.conf rename to ci-scripts/conf_files/gnb-cuup.sa.f1.conf index 9e18459f87..2a57a37273 100644 --- a/ci-scripts/conf_files/gnb-cuup.sa.conf +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf @@ -1,6 +1,7 @@ Active_gNBs = ( "gNB-OAI"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; +sa = 1; gNBs = ( @@ -14,25 +15,14 @@ gNBs = // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 1; - plmn_list = ({ - mcc = 208; - mnc = 99; - mnc_length = 2; - snssaiList = ( - { - sst = 1; - sd = 0x1; // 0 false, else true - } - ); - - }); + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); tr_s_preference = "f1"; local_s_if_name = "lo"; - local_s_address = "127.0.0.4"; - remote_s_address = "127.0.0.3"; + local_s_address = "192.168.72.141"; + remote_s_address = "192.168.72.142"; local_s_portc = 501; local_s_portd = 2152; remote_s_portc = 500; @@ -46,24 +36,21 @@ gNBs = SCTP_OUTSTREAMS = 2; }; - E1_INTERFACE = ( { type = "up"; - ipv4_cucp = "127.0.0.4"; - port_cucp = 2152; - ipv4_cuup = "127.0.0.5"; - port_cuup = 2152; + ipv4_cucp = "192.168.72.140"; + ipv4_cuup = "192.168.72.141"; } ) NETWORK_INTERFACES : { GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; - GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.141/24"; GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; - GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.141/24"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 }; } diff --git a/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf new file mode 100644 index 0000000000..3c2fbe717e --- /dev/null +++ b/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf @@ -0,0 +1,245 @@ +Active_gNBs = ( "du-rfsim"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "du-rfsim"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + min_rxtxtime = 6; + force_256qam_off = 1; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "f1"; + local_n_if_name = "eth0"; + local_n_address = "192.168.72.142"; + remote_n_address = "192.168.72.140"; + local_n_portc = 500; + local_n_portd = 2152; + remote_n_portc = 501; + remote_n_portd = 2152; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 200; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +rfsimulator: { + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs" +} + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + nr_phy_log_level = "info"; + nr_mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + f1ap_log_level = "debug"; + ngap_log_level = "debug"; +}; From 4d10437474fa46603adc2405d07140d88838f8be Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Feb 2023 18:01:07 +0100 Subject: [PATCH 5/7] Add basic docker-compose for E1 --- .../5g_rfsimulator_e1/docker-compose.yaml | 350 ++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml new file mode 100644 index 0000000000..3d4689e912 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -0,0 +1,350 @@ +version: '3.8' +services: + oai-nrf: + container_name: "rfsim5g-oai-nrf" + image: oai-nrf:august-dev + environment: + - NRF_INTERFACE_NAME_FOR_SBI=eth0 + - NRF_INTERFACE_PORT_FOR_SBI=80 + - NRF_INTERFACE_HTTP2_PORT_FOR_SBI=9090 + - NRF_API_VERSION=v1 + - INSTANCE=0 + - PID_DIRECTORY=/var/run + networks: + core_net: + ipv4_address: 192.168.71.130 + volumes: + - ../5g_rfsimulator/nrf-healthcheck.sh:/openair-nrf/bin/nrf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-nrf/bin/nrf-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + + mysql: + container_name: "rfsim5g-mysql" + image: mysql:5.7 + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + core_net: + ipv4_address: 192.168.71.131 + + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oai-amf:august-dev + environment: + - TZ=Europe/paris + - INSTANCE=0 + - PID_DIRECTORY=/var/run + - MCC=208 + - MNC=99 + - REGION_ID=128 + - AMF_SET_ID=1 + - SERVED_GUAMI_MCC_0=208 + - SERVED_GUAMI_MNC_0=99 + - SERVED_GUAMI_REGION_ID_0=128 + - SERVED_GUAMI_AMF_SET_ID_0=1 + - SERVED_GUAMI_MCC_1=460 + - SERVED_GUAMI_MNC_1=11 + - SERVED_GUAMI_REGION_ID_1=10 + - SERVED_GUAMI_AMF_SET_ID_1=1 + - PLMN_SUPPORT_MCC=208 + - PLMN_SUPPORT_MNC=99 + - PLMN_SUPPORT_TAC=0x0001 + - SST_0=1 + - SD_0=0xffffff + - SST_1=1 + - SD_1=1 + - AMF_INTERFACE_NAME_FOR_NGAP=eth0 + - AMF_INTERFACE_NAME_FOR_N11=eth0 + - SMF_INSTANCE_ID_0=1 + - SMF_FQDN_0=oai-smf + - SMF_IPV4_ADDR_0=0.0.0.0 + - SMF_HTTP_VERSION_0=v1 + - SELECTED_0=true + - SMF_INSTANCE_ID_1=2 + - SMF_FQDN_1=oai-smf + - SMF_IPV4_ADDR_1=0.0.0.0 + - SMF_HTTP_VERSION_1=v1 + - SELECTED_1=false + - MYSQL_SERVER=192.168.71.131 + - MYSQL_USER=root + - MYSQL_PASS=linux + - MYSQL_DB=oai_db + - OPERATOR_KEY=c42449363bbad02b66d16bc975d77cc1 + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NF_REGISTRATION=yes + - SMF_SELECTION=yes + - USE_FQDN_DNS=yes + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - EXTERNAL_AUSF=no + - AUSF_IPV4_ADDRESS=0.0.0.0 + - AUSF_PORT=80 + - AUSF_API_VERSION=v1 + - AUSF_FQDN=localhost + depends_on: + - oai-nrf + - mysql + volumes: + - ../5g_rfsimulator/amf-healthcheck.sh:/openair-amf/bin/amf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-amf/bin/amf-healthcheck.sh" + interval: 10s + timeout: 15s + retries: 5 + networks: + core_net: + ipv4_address: 192.168.71.132 + + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oai-smf:august-dev + environment: + - TZ=Europe/Paris + - INSTANCE=0 + - PID_DIRECTORY=/var/run + - SMF_INTERFACE_NAME_FOR_N4=eth0 + - SMF_INTERFACE_NAME_FOR_SBI=eth0 + - SMF_INTERFACE_PORT_FOR_SBI=80 + - SMF_INTERFACE_HTTP2_PORT_FOR_SBI=9090 + - SMF_API_VERSION=v1 + - DEFAULT_DNS_IPV4_ADDRESS=172.21.3.100 + - DEFAULT_DNS_SEC_IPV4_ADDRESS=4.4.4.4 + - AMF_IPV4_ADDRESS=0.0.0.0 + - AMF_PORT=80 + - AMF_API_VERSION=v1 + - AMF_FQDN=oai-amf + - UDM_IPV4_ADDRESS=127.0.0.1 + - UDM_PORT=80 + - UDM_API_VERSION=v1 + - UDM_FQDN=localhost + - UPF_IPV4_ADDRESS=192.168.71.134 + - UPF_FQDN_0=oai-spgwu + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - REGISTER_NRF=yes + - DISCOVER_UPF=yes + - USE_FQDN_DNS=yes + - DNN_NI0=oai + - TYPE0=IPv4 + - DNN_RANGE0=12.1.1.2 - 12.1.1.127 + - NSSAI_SST0=1 + - NSSAI_SD0=0xFFFFFF + - SESSION_AMBR_UL0=200Mbps + - SESSION_AMBR_DL0=400Mbps + - DNN_NI2=oai.ipv4 + depends_on: + - oai-nrf + - oai-amf + volumes: + - ../5g_rfsimulator/smf-healthcheck.sh:/openair-smf/bin/smf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-smf/bin/smf-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + core_net: + ipv4_address: 192.168.71.133 + + oai-spgwu: + container_name: "rfsim5g-oai-spgwu" + image: oai-spgwu-tiny:august-dev + environment: + - TZ=Europe/Paris + - PID_DIRECTORY=/var/run + - SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0 + - SGW_INTERFACE_NAME_FOR_SX=eth0 + - PGW_INTERFACE_NAME_FOR_SGI=eth0 + - NETWORK_UE_NAT_OPTION=yes + - NETWORK_UE_IP=12.1.1.0/24 + - SPGWC0_IP_ADDRESS=192.168.71.133 + - BYPASS_UL_PFCP_RULES=no + - MCC=208 + - MNC=99 + - MNC03=099 + - TAC=1 + - GTP_EXTENSION_HEADER_PRESENT=yes + - GW_ID=1 + - REALM=openairinterface.org + - ENABLE_5G_FEATURES=yes + - REGISTER_NRF=yes + - USE_FQDN_NRF=yes + - UPF_FQDN_5G=oai-spgwu + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - NSSAI_SST_0=1 + - NSSAI_SD_0=0xffffff + - DNN_0=oai + depends_on: + - oai-nrf + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + volumes: + - ../5g_rfsimulator/spgwu-healthcheck.sh:/openair-spgwu-tiny/bin/spgwu-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-spgwu-tiny/bin/spgwu-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + core_net: + ipv4_address: 192.168.71.134 + traffic_net: + ipv4_address: 192.168.73.134 + + oai-ext-dn: + image: ubuntu:bionic + privileged: true + container_name: rfsim5g-oai-ext-dn + entrypoint: /bin/bash -c \ + "apt update; apt install -y procps iptables iproute2 iperf iputils-ping;"\ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.73.134 dev eth0; sleep infinity" + depends_on: + - oai-spgwu + networks: + traffic_net: + ipv4_address: 192.168.73.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.73.134" + interval: 10s + timeout: 5s + retries: 5 + + oai-cucp: + image: oai-gnb:develop + privileged: true + container_name: rfsim5g-oai-cucp + environment: + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + depends_on: + - oai-ext-dn + networks: + core_net: + ipv4_address: 192.168.71.140 + ran_net: + ipv4_address: 192.168.72.140 + volumes: + - ../../conf_files/gnb-cucp.sa.f1.conf:/opt/oai-gnb/etc/mounted.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-cuup: + image: oai-nr-cuup:develop + privileged: true + container_name: rfsim5g-oai-cuup + environment: + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --rfsim + #--log_config.global_log_options level,nocolor,time + depends_on: + - oai-cucp + networks: + core_net: + ipv4_address: 192.168.71.141 + ran_net: + ipv4_address: 192.168.72.141 + volumes: + - ../../conf_files/gnb-cuup.sa.f1.conf:/opt/oai-gnb/etc/mounted.conf + healthcheck: + test: /bin/bash -c "pgrep nr-cuup" + interval: 10s + timeout: 5s + retries: 5 + + oai-du: + image: oai-gnb:develop + privileged: true + container_name: rfsim5g-oai-du + environment: + RFSIMULATOR: server + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + networks: + ran_net: + ipv4_address: 192.168.72.142 + volumes: + - ../../conf_files/gnb-du.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/mounted.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue: + image: oai-nr-ue:develop + privileged: true + container_name: rfsim5g-oai-nr-ue + environment: + RFSIMULATOR: 192.168.72.142 + FULL_IMSI: '208990100001100' + FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'C42449363BBAD02B66D16BC975D77CC1' + DNN: oai + NSSAI_SST: 1 + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --nokrnmod --log_config.global_log_options level,nocolor,time + depends_on: + - oai-du + networks: + ran_net: + ipv4_address: 192.168.72.150 + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + core_net: + driver: bridge + name: rfsim5g-oai-core-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-core" + ran_net: + driver: bridge + name: rfsim5g-oai-ran-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-ran" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic_net-net + ipam: + config: + - subnet: 192.168.73.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" From 616bdf83609e34fe59f34ae0d536dd9b3866f4fa Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 7 Feb 2023 16:47:00 +0100 Subject: [PATCH 6/7] Generalize tshark capture filter, but avoid false positives --- ci-scripts/cls_containerize.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 38305b5b4e..324e718ba1 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -1161,18 +1161,9 @@ class Containerize(): def CaptureOnDockerNetworks(self): cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml config | grep com.docker.network.bridge.name | sed -e "s@^.*name: @@"' networkNames = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) - if re.search('4g.*rfsimulator', self.yamlPath[0]) is not None: - # Excluding any traffic from LTE-UE container (192.168.61.30) - # From the trf-gen, keeping only PING traffic - cmd = 'sudo nohup tshark -f "(host 192.168.61.11 and icmp) or (not host 192.168.61.11 and not host 192.168.61.30 and not arp and not port 53 and not port 2152)"' - elif re.search('5g.*rfsimulator', self.yamlPath[0]) is not None: - # Excluding any traffic from NR-UE containers (192.168.71.150 and 192.168.71.151) - # From the ext-dn, keeping only PING traffic - cmd = 'sudo nohup tshark -f "(host 192.168.72.135 and icmp) or (not host 192.168.72.135 and not host 192.168.71.150 and not host 192.168.71.151 and not arp and not port 53 and not port 2152 and not port 2153)"' - elif re.search('5g_l2sim', self.yamlPath[0]) is not None: - cmd = 'sudo nohup tshark -f "(host 192.168.72.135 and icmp) or (not host 192.168.72.135 and not arp and not port 53 and not port 2152 and not port 2153)"' - else: - return + + # Allow only: control plane RAN (SCTP), HTTP of control in CN (port 80), PFCP traffic (port 8805), MySQL (port 3306) + cmd = 'sudo nohup tshark -f "sctp or port 80 or port 8805 or icmp or port 3306"' for name in networkNames.split('\n'): if re.search('rfsim', name) is not None or re.search('l2sim', name) is not None: cmd += ' -i ' + name From 007dcc63a86ebc5aea03a13c59a4f890309659c2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 6 Feb 2023 17:06:32 +0100 Subject: [PATCH 7/7] 5G E1 RFsim test XML test cases --- .../xml_files/container_5g_e1_rfsim.xml | 131 ++++++++++++++++++ .../xml_files/container_5g_e1_rfsim_down.xml | 45 ++++++ 2 files changed, 176 insertions(+) create mode 100644 ci-scripts/xml_files/container_5g_e1_rfsim.xml create mode 100644 ci-scripts/xml_files/container_5g_e1_rfsim_down.xml diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml new file mode 100644 index 0000000000..7130976dad --- /dev/null +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -0,0 +1,131 @@ + + + rfsim-5gnr-e1 + CUCP-CUUP-DU E1+F1 split + wrench + + 111111 + 100021 + 000020 + 000021 + 000022 + 000023 + 000024 + 020021 + 020022 + 030021 + 100021 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb oai-nr-cuup oai-nr-ue + + + + DeployGenObject + Deploy MySql Database + yaml_files/5g_rfsimulator_e1 + mysql + 1 + + + + DeployGenObject + Deploy OAI 5G CoreNetwork + yaml_files/5g_rfsimulator_e1 + oai-nrf oai-amf oai-smf oai-spgwu oai-ext-dn + 6 + + + + DeployGenObject + Deploy OAI 5G CU-CP RF sim SA + yaml_files/5g_rfsimulator_e1 + oai-cucp + 7 + + + + DeployGenObject + Deploy OAI 5G CU-UP and DU RF sim SA + yaml_files/5g_rfsimulator_e1 + oai-cuup oai-du + 9 + + + + DeployGenObject + Deploy OAI 5G NR-UE RF sim SA + yaml_files/5g_rfsimulator_e1 + oai-nr-ue + 10 + + + + PingFromContainer + Ping ext-dn from NR-UE + rfsim5g-oai-nr-ue + -I oaitun_ue1 -c 20 192.168.73.135 + 5 + + + + PingFromContainer + Ping NR-UE from ext-dn + rfsim5g-oai-ext-dn + -c 20 12.1.1.2 + 5 + + + + IperfFromContainer + Iperf UDP Downlink + rfsim5g-oai-nr-ue + rfsim5g-oai-ext-dn + -B 12.1.1.2 -u -i 1 -s + -c 12.1.1.2 -u -i 1 -t 30 -b 3M + + + + IperfFromContainer + Iperf UDP Uplink + rfsim5g-oai-ext-dn + rfsim5g-oai-nr-ue + -u -i 1 -s + -B 12.1.1.2 -c 192.168.73.135 -u -i 1 -t 30 -b 1M + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_e1 + 1,0,0,0 + 1,0,0,0 + + + diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim_down.xml b/ci-scripts/xml_files/container_5g_e1_rfsim_down.xml new file mode 100644 index 0000000000..a1213c9b9b --- /dev/null +++ b/ci-scripts/xml_files/container_5g_e1_rfsim_down.xml @@ -0,0 +1,45 @@ + + + rfsim-5gnr-down-e1 + CleanUp CUCP-CUUP-DU E1+F1 split + trash + + 100022 + 222222 + + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_e1 + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 0 + + +