From c44dcefd1691d6ddd6725929d2be06f12a1167cb Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 16 Jun 2023 19:39:22 +0200 Subject: [PATCH 01/87] Document environment variables used by OAI programs --- doc/README.md | 1 + doc/environment-variables.md | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 doc/environment-variables.md diff --git a/doc/README.md b/doc/README.md index 6abca52f0b..25696d8237 100644 --- a/doc/README.md +++ b/doc/README.md @@ -20,6 +20,7 @@ - [GET_SOURCES.md](./GET_SOURCES.md): how to download the sources - [BUILD.md](./BUILD.md): how to build the sources - [clang-format.md](./clang-format.md): how to format the code +- [environment-variables.md](./environment-variables.md): the environment variables used by OAI There is some general information in the [OpenAirInterface Gitlab Wiki](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/home) diff --git a/doc/environment-variables.md b/doc/environment-variables.md new file mode 100644 index 0000000000..5b2ae52030 --- /dev/null +++ b/doc/environment-variables.md @@ -0,0 +1,21 @@ +# Environment variables + +OAI uses/supports a number of environment variables, documented in the following: + +- `NFAPI_TRACE_LEVEL`: set the nfapi custom logging framework's log level; can be one of `error`, `warn`, `note`, `info`, `debug` +- `NR_AWGN_RESULTS_DIR`: directory containing BLER curves for L2simulator channel modelling in SISO case +- `NR_MIMO2x2_AWGN_RESULTS_DIR`: directory containing BLER curves for L2simulator channel modelling in 2x2 MIMO case +- `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) +- `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` +- `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation +- `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) +- `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) +- `gdbStacks`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread +- `threadPoolMeasurements`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) + +Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: +- `HOST`: alternative host to connect to, for CLI, if neither `REMADDR` nor `SSH_CLIENT` are defined +- `REMADDR`: host to connect to, for CLI client +- `SSH_CLIENT`: alternative host to connect to, for CLI, if `REMADDR` is not defined +- `USER`: user name in the command-line interface +- `rftestInputFile`: input file for the `calibration_test` tool From 01d1a47adfb9da2efee6ad1050d8d8e3a52b4494 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 16 Jun 2023 19:40:13 +0200 Subject: [PATCH 02/87] Remove commented code that uses getenv(): it might be confusing if reactivated --- openair1/PHY/CODING/TESTBENCH/polartest.c | 2 -- openair1/SIMULATION/LTE_PHY/dlsim.c | 2 -- openair1/SIMULATION/LTE_PHY/dlsim_tm4.c | 2 -- openair1/SIMULATION/LTE_PHY/dlsim_tm7.c | 2 -- openair1/SIMULATION/LTE_PHY/mbmssim.c | 2 -- openair1/SIMULATION/LTE_PHY/ulsim.c | 3 --- 6 files changed, 13 deletions(-) diff --git a/openair1/PHY/CODING/TESTBENCH/polartest.c b/openair1/PHY/CODING/TESTBENCH/polartest.c index 7c1534ca51..462ad53a6e 100644 --- a/openair1/PHY/CODING/TESTBENCH/polartest.c +++ b/openair1/PHY/CODING/TESTBENCH/polartest.c @@ -128,8 +128,6 @@ int main(int argc, char *argv[]) char fileName[512], currentTimeInfo[25]; char folderName[] = "."; FILE *logFile = NULL; - /*folderName=getenv("HOME"); - strcat(folderName,"/Desktop/polartestResults");*/ if (logFlag){ time (¤tTime); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index c7e4f27f70..88e8727245 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -1019,8 +1019,6 @@ int main(int argc, char **argv) { hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); //mkdir(dirname,0777); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c index 9a086e1a7f..2f26be3d84 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c @@ -887,8 +887,6 @@ int main(int argc, char **argv) hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); //mkdir(dirname,0777); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c index 030a6b6cc6..84480dfdde 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c @@ -649,8 +649,6 @@ int main(int argc, char **argv) { hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); //mkdir(dirname,0777); diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index accb6004f8..331b16b9bf 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -1147,8 +1147,6 @@ int main(int argc, char **argv) { hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); //mkdir(dirname,0777); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index a9f8ca823e..70622b2120 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -653,9 +653,6 @@ int main(int argc, char **argv) { hostname[1023] = '\0'; gethostname(hostname, 1023); printf("Hostname: %s\n", hostname); - //char dirname[FILENAME_MAX]; - //sprintf(dirname, "%s//SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname); - //mkdir(dirname, 0777); sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_antrx%d_channel%s_tx%d.csv", N_RB_DL,mcs,n_rx,channel_model_input,transmission_m); time_meas_fd = fopen(time_meas_fname,"w"); From ba11dfba4ec735ca0742cdd15cc7e012125d5c2f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:18:26 +0200 Subject: [PATCH 03/87] Rename env var gdbStacks to OAI_GDBSTACKS - make it clear that it belongs to OAI - follow convention of uppercase name --- common/utils/assertions.h | 2 +- doc/environment-variables.md | 2 +- docker/scripts/enb_entrypoint.sh | 2 +- docker/scripts/gnb-aw2s_entrypoint.sh | 2 +- docker/scripts/gnb_entrypoint.sh | 2 +- docker/scripts/lte_ru_entrypoint.sh | 2 +- docker/scripts/lte_ue_entrypoint.sh | 2 +- docker/scripts/nr_ue_entrypoint.sh | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/utils/assertions.h b/common/utils/assertions.h index 3424392e7a..453e853aec 100644 --- a/common/utils/assertions.h +++ b/common/utils/assertions.h @@ -33,7 +33,7 @@ #define OAI_EXIT_ASSERT 1 #define _Assert_Exit_ \ - if (getenv("gdbStacks")) { \ + if (getenv("OAI_GDBSTACKS")) { \ char tmp [1000]; \ sprintf(tmp,"gdb -ex='set confirm off' -ex 'thread apply all bt' -ex q -p %d < /dev/null", getpid()); \ __attribute__((unused)) int dummy=system(tmp); \ diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 5b2ae52030..9137533e8a 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -7,10 +7,10 @@ OAI uses/supports a number of environment variables, documented in the following - `NR_MIMO2x2_AWGN_RESULTS_DIR`: directory containing BLER curves for L2simulator channel modelling in 2x2 MIMO case - `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` +- `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation - `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) -- `gdbStacks`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread - `threadPoolMeasurements`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: diff --git a/docker/scripts/enb_entrypoint.sh b/docker/scripts/enb_entrypoint.sh index aadd8b71d1..cda5793ab3 100755 --- a/docker/scripts/enb_entrypoint.sh +++ b/docker/scripts/enb_entrypoint.sh @@ -26,7 +26,7 @@ elif [[ -v USE_N3XX ]]; then fi # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting eNB soft modem" diff --git a/docker/scripts/gnb-aw2s_entrypoint.sh b/docker/scripts/gnb-aw2s_entrypoint.sh index b03e214ce1..752e3005ed 100755 --- a/docker/scripts/gnb-aw2s_entrypoint.sh +++ b/docker/scripts/gnb-aw2s_entrypoint.sh @@ -15,7 +15,7 @@ echo "== Configuration file:" cat $CONFIGFILE # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting gNB soft modem with AW2S" diff --git a/docker/scripts/gnb_entrypoint.sh b/docker/scripts/gnb_entrypoint.sh index ef268b1143..230f3f0f7d 100755 --- a/docker/scripts/gnb_entrypoint.sh +++ b/docker/scripts/gnb_entrypoint.sh @@ -27,7 +27,7 @@ elif [[ -v USE_N3XX ]]; then fi # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting gNB soft modem" diff --git a/docker/scripts/lte_ru_entrypoint.sh b/docker/scripts/lte_ru_entrypoint.sh index 4ce5615482..0305cf27ff 100755 --- a/docker/scripts/lte_ru_entrypoint.sh +++ b/docker/scripts/lte_ru_entrypoint.sh @@ -26,7 +26,7 @@ elif [[ -v USE_N3XX ]]; then fi # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting eNB soft modem" diff --git a/docker/scripts/lte_ue_entrypoint.sh b/docker/scripts/lte_ue_entrypoint.sh index a8d0f8fd1a..f88692a957 100755 --- a/docker/scripts/lte_ue_entrypoint.sh +++ b/docker/scripts/lte_ue_entrypoint.sh @@ -52,7 +52,7 @@ if [[ -f "$CONFIGFILE" ]]; then fi # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting LTE UE soft modem" diff --git a/docker/scripts/nr_ue_entrypoint.sh b/docker/scripts/nr_ue_entrypoint.sh index 840a8ae729..e84386276a 100755 --- a/docker/scripts/nr_ue_entrypoint.sh +++ b/docker/scripts/nr_ue_entrypoint.sh @@ -33,7 +33,7 @@ while [[ $# -gt 0 ]]; do done # enable printing of stack traces on assert -export gdbStacks=1 +export OAI_GDBSTACKS=1 echo "==================================" echo "== Starting NR UE soft modem" From 49703eee7b1a2a806d59ba445745ad8e2713d78c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:19:41 +0200 Subject: [PATCH 04/87] Rename threadPoolMeasurements to OAI_THREADPOOLMEASUREMENTS - make it clear that it belongs to OAI - follow convention of uppercase name --- common/utils/threadPool/thread-pool.c | 2 +- common/utils/threadPool/thread-pool.md | 4 ++-- doc/environment-variables.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index 5531a3aed3..1a2fafdbf8 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -106,7 +106,7 @@ void *one_thread(void *arg) { void initNamedTpool(char *params,tpool_t *pool, bool performanceMeas, char *name) { memset(pool,0,sizeof(*pool)); - char *measr=getenv("threadPoolMeasurements"); + char *measr=getenv("OAI_THREADPOOLMEASUREMENTS"); pool->measurePerf=performanceMeas; // force measurement if the output is defined pool->measurePerf |= measr!=NULL; diff --git a/common/utils/threadPool/thread-pool.md b/common/utils/threadPool/thread-pool.md index 311857ff3e..02dd9e0387 100644 --- a/common/utils/threadPool/thread-pool.md +++ b/common/utils/threadPool/thread-pool.md @@ -182,7 +182,7 @@ Returns the total number of jobs that were aborted, i.e., waiting for execution ## Performance measurements -A performance measurement is integrated: the pool will automacillay fill timestamps if you set the environement variable `threadPoolMeasurements` to a valid file name. The following measurements will be written to Linux pipe on a per-job basis: +A performance measurement is integrated: the pool will automacillay fill timestamps if you set the environement variable `OAI_THREADPOOLMEASUREMENTS` to a valid file name. The following measurements will be written to Linux pipe on a per-job basis: * `creationTime`: time the request is push to the pool; * `startProcessingTime`: time a worker start to run on the job @@ -193,6 +193,6 @@ The `measurement_display` tool to read the Linux pipe and display it in ASCII is In the cmake build directory, type `make/ninja measurement_display`. Use as follows: ``` -sudo threadPoolMeasurements=tpool.meas ./nr-softmodem ... +sudo OAI_THREADPOOLMEASUREMENTS=tpool.meas ./nr-softmodem ... ./measurement_display tpool.meas ``` diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 9137533e8a..9439ebd64c 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -8,10 +8,10 @@ OAI uses/supports a number of environment variables, documented in the following - `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` - `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread +- `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation - `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) -- `threadPoolMeasurements`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: - `HOST`: alternative host to connect to, for CLI, if neither `REMADDR` nor `SSH_CLIENT` are defined From 710bfdbf048d699bcc72eeb06e9aef19be19330c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:45:52 +0200 Subject: [PATCH 05/87] Introduce env var OAI_RNGSEED can be used to set a random number generator (RNG) seed uniformly from command line --- doc/environment-variables.md | 1 + openair1/SIMULATION/TOOLS/rangen_double.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 9439ebd64c..30742b3892 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -8,6 +8,7 @@ OAI uses/supports a number of environment variables, documented in the following - `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` - `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread +- `OAI_RNGSEED`: overwrites any seed for random number generators (RNG) in simulators - `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation - `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) diff --git a/openair1/SIMULATION/TOOLS/rangen_double.c b/openair1/SIMULATION/TOOLS/rangen_double.c index 9c10275c17..80bb33fc6a 100644 --- a/openair1/SIMULATION/TOOLS/rangen_double.c +++ b/openair1/SIMULATION/TOOLS/rangen_double.c @@ -55,6 +55,8 @@ void randominit(unsigned long seed_init) unsigned long seed = seed_init; if (seed_init == 0) fill_random(&seed, sizeof(seed)); + if (getenv("OAI_RNGSEED")) + seed = atoi(getenv("OAI_RNGSEED")); printf("Initializing random number generator, seed %lu\n", seed); // initialize uniformrandom RNG From 7a3aaca1ef4fecf476f9d78b40704fa90f56916f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 22 Jun 2023 12:18:54 +0200 Subject: [PATCH 06/87] Print warning if RFSIMULATOR environment variable is used --- radio/rfsimulator/simulator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 4db78e9659..1175d9ec42 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -312,6 +312,9 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { /* for compatibility keep environment variable usage */ if ( getenv("RFSIMULATOR") != NULL ) { rfsimulator->ip=getenv("RFSIMULATOR"); + LOG_W(HW, "The RFSIMULATOR environment variable is deprecated and support will be removed in the future. Instead, add parameter --rfsimulator.serveraddr %s to set the server address. Note: the default is \"server\"; for the gNB/eNB, you don't have to set any configuration.\n", rfsimulator->ip); + LOG_I(HW, "Remove RFSIMULATOR environment variable to get rid of this message and the sleep.\n"); + sleep(10); } if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || From 04247d501d5972e0598e7c7e8a0c261b9abaf43e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 22 Jun 2023 12:37:26 +0200 Subject: [PATCH 07/87] Remove RFSIMULATOR environment variable from repository --- .../4g_rfsimulator_fdd_05MHz/docker-compose.yml | 4 +--- .../docker-compose.yml | 4 +--- .../4g_rfsimulator_fdd_10MHz/docker-compose.yml | 4 +--- .../4g_rfsimulator_fdd_20MHz/docker-compose.yml | 4 +--- .../4g_rfsimulator_fembms/docker-compose.yml | 4 +--- .../4g_rfsimulator_mbms/docker-compose.yml | 4 +--- .../4g_rfsimulator_tdd_05MHz/docker-compose.yml | 4 +--- .../5g_f1_rfsimulator/docker-compose.yaml | 5 +---- .../5g_fdd_rfsimulator/docker-compose.yaml | 4 +--- ci-scripts/yaml_files/5g_rfsimulator/README.md | 3 +-- .../5g_rfsimulator/docker-compose.yaml | 7 ++----- .../5g_rfsimulator_24prb/docker-compose.yaml | 4 +--- .../5g_rfsimulator_2x2/docker-compose.yaml | 4 +--- .../docker-compose.yaml | 4 +--- .../5g_rfsimulator_e1/docker-compose.yaml | 4 +--- .../docker-compose.yaml | 4 +--- .../5g_rfsimulator_fr2_32prb/docker-compose.yaml | 4 +--- .../5g_rfsimulator_tdd_dora/docker-compose.yaml | 4 +--- .../5g_rfsimulator_u0_25prb/docker-compose.yaml | 4 +--- doc/E1-design.md | 2 +- doc/NR_SA_Tutorial_OAI_nrUE.md | 2 +- doc/RUNMODEM.md | 4 ++-- doc/RUN_NR_NFAPI.md | 2 +- doc/RUN_NR_PRS.md | 12 ++++++++---- doc/RUN_NR_multiple_BWPs.md | 4 ++-- doc/SystemX-tutorial-design.md | 7 ++----- doc/environment-variables.md | 1 - radio/rfsimulator/README.md | 16 +++++++--------- radio/rfsimulator/simulator.c | 8 -------- 29 files changed, 44 insertions(+), 93 deletions(-) diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml index ca005e9568..7acbc62bd7 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml @@ -188,7 +188,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.25prb.rfsim.conf:/opt/oai-enb/etc/enb.conf @@ -209,8 +208,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml index bb0bb9f982..8c79cbeca2 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml @@ -10,7 +10,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time --noS1 volumes: - ../../conf_files/enb.band7.25prb.rfsim.nos1.conf:/opt/oai-enb/etc/enb.conf @@ -31,8 +30,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time --noS1 + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time --noS1 volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml index 1ba0178949..b26fd4cac2 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml @@ -188,7 +188,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.50prb.rfsim.conf:/opt/oai-enb/etc/enb.conf @@ -209,8 +208,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 50 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 50 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml index edde78480e..128eafaf5d 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml @@ -188,7 +188,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.100prb.rfsim.conf:/opt/oai-enb/etc/enb.conf @@ -209,8 +208,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 100 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 100 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml index f568989f3f..8da7c4041c 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml @@ -10,7 +10,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --noS1 --eNBs.[0].component_carriers.[0].mbms_dedicated_serving_cell ENABLE --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf @@ -29,8 +28,7 @@ services: ipv4_address: 192.168.61.30 environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsim --noS1 --log_config.global_log_options level,nocolor,time --noS1 + USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsim --noS1 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time --noS1 volumes: - ../../conf_files/lteue.usim-mbs.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml index 5dc9ae1a04..159943a76a 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml @@ -10,7 +10,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --noS1 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf @@ -34,8 +33,7 @@ services: environment: TZ: Europe/Paris HOSTNAME: oai_ue0 - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsim --noS1 --log_config.global_log_options level,nocolor,time --noS1 + USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsim --noS1 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time --noS1 volumes: - ../../conf_files/lteue.usim-mbs.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml index 18ab587731..b592997edc 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml @@ -188,7 +188,6 @@ services: ipv4_address: 192.168.61.20 environment: TZ: Europe/Paris - RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/enb.band38.25prb.rfsim.conf:/opt/oai-enb/etc/enb.conf @@ -209,8 +208,7 @@ services: - "10000" environment: TZ: Europe/Paris - RFSIMULATOR: 192.168.61.20 - USE_ADDITIONAL_OPTIONS: --rfsim -T -C 2605000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -T -C 2605000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --rfsimulator.serveraddr 192.168.61.20 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/lteue.usim-ci.conf:/opt/oai-lte-ue/etc/ue_usim.conf healthcheck: diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index dd2a1b2cdd..dd8c62d97d 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-cu environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -186,7 +185,6 @@ services: privileged: true container_name: rfsim5g-oai-du environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-cu @@ -205,8 +203,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.142 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --rfsimulator.serveraddr 192.168.71.142 --log_config.global_log_options level,nocolor,time depends_on: - oai-du networks: diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index 42fe53b2b9..93da3f9f0f 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -186,8 +185,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 --band 66 -C 2169080000 --CO -400000000 --ssb 378 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 --band 66 -C 2169080000 --CO -400000000 --ssb 378 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md index b516e93813..a018c085d6 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -244,13 +244,12 @@ Create entry for Second UE in docker-compose.yaml file as follows: privileged: true container_name: rfsim5g-oai-nr-ue2 environment: - RFSIMULATOR: 192.168.71.140 FULL_IMSI: '208990100001101' FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' OPC: 'C42449363BBAD02B66D16BC975D77CC1' DNN: oai NSSAI_SST: 1 - USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index e4129adee2..21792e35bf 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -186,8 +185,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -206,8 +204,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue2 environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index f076cf2db0..c0c61b4e3b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -186,8 +185,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index 4d3e8b7dde..cd5c28b9ff 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -187,8 +186,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --uicc0.imsi 208990100001100 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --uicc0.imsi 208990100001100 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml index e43bc0e0d9..7d2270b7c9 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml @@ -6,7 +6,6 @@ services: container_name: rfsim5g-oai-du network_mode: "host" environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --MACRLCs.[0].local_n_address 172.21.16.109 --MACRLCs.[0].remote_n_address 172.21.6.22 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/gnb-du.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf @@ -21,8 +20,7 @@ services: container_name: rfsim5g-oai-nr-ue network_mode: "host" environment: - RFSIMULATOR: 127.0.0.1 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 208990100001140 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 208990100001140 --rfsimulator.serveraddr 127.0.0.1 --log_config.global_log_options level,nocolor,time depends_on: - oai-du volumes: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index b44822b3e8..71f00f96c2 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -212,7 +212,6 @@ services: privileged: true container_name: rfsim5g-oai-du environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time networks: ran_net: @@ -230,8 +229,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.72.142 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --rfsimulator.serveraddr 192.168.72.142 --log_config.global_log_options level,nocolor,time depends_on: - oai-du networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml index b654f06d12..7c17f96957 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml @@ -5,7 +5,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --phy-test --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time networks: public_net: @@ -24,8 +23,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --phy-test --rfsim --noS1 --rrc_config_path etc/rrc/ --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --phy-test --rfsim --noS1 --rrc_config_path etc/rrc/ --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index eef67d713b..2f36192188 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -5,7 +5,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time networks: public_net: @@ -24,8 +23,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --rrc_config_path etc/rrc/ --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --rrc_config_path etc/rrc/ --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml index ed2af44fbb..1a83cd6678 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml @@ -5,7 +5,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time networks: public_net: @@ -24,8 +23,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --rrc_config_path etc/rrc/ --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --rrc_config_path etc/rrc/ --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index f2c90fa7c7..14a989934b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -167,7 +167,6 @@ services: privileged: true container_name: rfsim5g-oai-gnb environment: - RFSIMULATOR: server USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn @@ -187,8 +186,7 @@ services: privileged: true container_name: rfsim5g-oai-nr-ue environment: - RFSIMULATOR: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152250000 --CO -400000000 --ssb 76 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152250000 --CO -400000000 --ssb 76 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/doc/E1-design.md b/doc/E1-design.md index 90e0807793..6f9e8f4edd 100644 --- a/doc/E1-design.md +++ b/doc/E1-design.md @@ -96,7 +96,7 @@ You need to use `--rfsim` if you are running the test with rfsimulator. OAI UE: ``` -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --rfsimulator.serveraddr 127.0.0.1 ``` # 3. Configuration file IP addresses of network functions diff --git a/doc/NR_SA_Tutorial_OAI_nrUE.md b/doc/NR_SA_Tutorial_OAI_nrUE.md index 0d0ec23346..81c861bdfa 100644 --- a/doc/NR_SA_Tutorial_OAI_nrUE.md +++ b/doc/NR_SA_Tutorial_OAI_nrUE.md @@ -168,7 +168,7 @@ Run OAI nrUE with RFsimulator cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1 ``` ### 5.2.1 Ping test diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index d32758b1a2..dde31cbd2f 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -166,8 +166,8 @@ In do-ra mode it is possible to mimic the reception of UE Capabilities at gNB by To run using the RFsimulator: ```bash -sudo RFSIMULATOR=gnb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD +sudo ./nr-uesoftmodem --do-ra --rfsim --rfsimulator.serveraddr 127.0.0.1 --parallel-config PARALLEL_SINGLE_THREAD ``` Using USRPs: diff --git a/doc/RUN_NR_NFAPI.md b/doc/RUN_NR_NFAPI.md index e294703d44..503fead0ed 100644 --- a/doc/RUN_NR_NFAPI.md +++ b/doc/RUN_NR_NFAPI.md @@ -31,7 +31,7 @@ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfap ``` ### UE command ``` -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d +sudo ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d --rfsimulator.serveraddr 127.0.0.1 ``` ## Procedure to run NR nFAPI using Hardware (tested with USRP x310) diff --git a/doc/RUN_NR_PRS.md b/doc/RUN_NR_PRS.md index 5cdb47c04b..64e754cb0f 100644 --- a/doc/RUN_NR_PRS.md +++ b/doc/RUN_NR_PRS.md @@ -71,7 +71,7 @@ If **N310 USRPs** are used, then run above command `without -E option` i.e witho To run using **rfsimulator**, execute following command: -```sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band78.fr1.106PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --rfsim --phy-test``` +```sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band78.fr1.106PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --rfsim --phy-test``` ## FR2 test In FR2 mode, we need RF beamforming module to transmit signal in mmWave frequency range. **X310 USRPs** can be used with BasicTx daughtercard to transmit baseband signal at **Intermediate Frequncy(IF)** and then RF beamforming module would perform beamforming and the upconversion to FR2 frequencies. IF can be specified using `if_freq` in the RU section of gNB config. @@ -83,7 +83,7 @@ If RF beamforming module is NOT present, gNB can still be launched with USRP alo To run using **rfsimulator**, execute following command: -```sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band261.fr2.64PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --rfsim --phy-test``` +```sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.sa.band261.fr2.64PRB.prs.usrpx310.conf --parallel-config PARALLEL_SINGLE_THREAD --noS1 --rfsim --phy-test``` ## Multiple gNB scenario PRS is primarily used for positioning and localization of the UE with multiple gNBs transmitting simultaneously. OAI PRS implementation supports multiple gNB transmission provided all the gNBs are tightely synchronized using GPSDO clock. Therefore before running this scenario, make sure the USRPs has built-in GPSDO and the GPS antennas are connected with good satellite visibility. Also every time a gNB is launched, wait until `GPS LOCKED` is printed on the terminal during gNB startup. If USRP fails to lock with GPSDO, try again until its locked. @@ -112,7 +112,9 @@ If **N310 USRPs** are used, then run above command `without -E option` i.e witho To run using **rfsimulator** with local ETH IF `127.0.0.1`, execute following command: -```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr1.106prb.conf``` +``` +sudo ./nr-uesoftmodem --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr1.106prb.conf --rfsimulator.serveraddr 127.0.0.1 +``` ## FR2 test Like gNB, RF beamforming module is receiving at mmWave frequencies and then **X310 USRPs** with BasicRx daughtercard to receive the signal at intermediate frequncy(IF) from RF beamforming module. IF can be specified using `--if_freq` option in nrUE command line. @@ -124,7 +126,9 @@ If RF beamforming module is NOT present, nrUE can still be launched with USRP al To run using **rfsimulator** with local ETH IF `127.0.0.1`, execute following command: -```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr2.64prb.conf``` +``` +sudo ./nr-uesoftmodem --rfsim --phy-test --noS1 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr2.64prb.conf --rfsimulator.serveraddr 127.0.0.1 +``` ## Multiple gNB scenario In nrUE prs config file, change `Active_gNBs` to the actual number of gNBs launched. Also verify the parameter in `prs_config` sections of nrUE config is matching with that of gNB config used. And launch nrUE using one of the above commands depending on FR1/FR2 test scenario. diff --git a/doc/RUN_NR_multiple_BWPs.md b/doc/RUN_NR_multiple_BWPs.md index 80a0515b56..c6b497043a 100644 --- a/doc/RUN_NR_multiple_BWPs.md +++ b/doc/RUN_NR_multiple_BWPs.md @@ -47,5 +47,5 @@ Each dedicated BWP must have: ## UE command: ``` - sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 208990000000001 -``` \ No newline at end of file + sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 208990000000001 --rfsimulator.serveraddr 127.0.0.1 +``` diff --git a/doc/SystemX-tutorial-design.md b/doc/SystemX-tutorial-design.md index 804658fd4d..62761417bc 100644 --- a/doc/SystemX-tutorial-design.md +++ b/doc/SystemX-tutorial-design.md @@ -133,14 +133,11 @@ Usage with RFsimulator: **gNB** ```bash -sudo RFSIMULATOR=server ./nr-softmodem -O \ -../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf \ ---parallel-config PARALLEL\_SINGLE\_THREAD +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL\_SINGLE\_THREAD ``` **nrUE** ```bash -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C \ -3510000000 -d +sudo ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000 -d --rfsimulator.serveraddr 127.0.0.1 ``` diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 30742b3892..31520b0a2d 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -11,7 +11,6 @@ OAI uses/supports a number of environment variables, documented in the following - `OAI_RNGSEED`: overwrites any seed for random number generators (RNG) in simulators - `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation -- `RFSIMULATOR`: the RFsimulator's work mode, can be either `server` (for server mode) or a valid IP address (for client mode) - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: diff --git a/radio/rfsimulator/README.md b/radio/rfsimulator/README.md index 357e70e5a6..e8baff472c 100644 --- a/radio/rfsimulator/README.md +++ b/radio/rfsimulator/README.md @@ -57,8 +57,6 @@ The RF simulator is using the configuration module, and its parameters are defin | modelname | Name of the channel model to apply on received iqs when the `chanmod` option is enabled | AWGN | | IQfile | Path to the file to be used to store iqs, when the `saviq` option is enabled | /tmp/rfsimulator.iqs | -Setting the env variable RFSIMULATOR can be used instead of using the serveraddr parameter; it is to preserve compatibility with previous version. - ## How to use the RF simulator options To define and use a channel model, the configuration file needs to include a channel configuration file. To do this, add `@include "channelmod_rfsimu.conf"` to the end of the configuration file, and place the channel configuration file in the same directory. An example channel configuration file `channelmod_rfsimu.conf` is in `ci-scripts/conf_files`. @@ -81,7 +79,7 @@ set the model with: Example run: ```bash -sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN ``` where `@include "channelmod_rfsimu.conf"` has been added at the end of the file, and `ci-scripts/conf_files/channelmod_rfsimu.conf` copied to `targets/PROJECTS/GENERIC-LTE-EPC/CONF/`. @@ -90,11 +88,11 @@ where `@include "channelmod_rfsimu.conf"` has been added at the end of the file, For the UE, it should be set to the IP address of the eNB. For example: ```bash -sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 +sudo ./lte-uesoftmodem -C 2685000000 -r 50 --rfsimulator.serveraddr 192.168.2.200 ``` For the eNB, use a valid configuration file setup for the USRP board tests and start the softmodem as usual, **but**, adding the `--rfsim` option. ```bash -sudo RFSIMULATOR=enb ./lte-softmodem -O --rfsim +sudo ./lte-softmodem -O --rfsim ``` Except this, the UE and the eNB can be used as if the RF is real. noS1 mode can also be used with the RF simulator. @@ -115,13 +113,13 @@ make rfsimulator ### Launch gNB in one window ```bash -sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test ``` ### Launch UE in another window ```bash -sudo RFSIMULATOR= ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . +sudo ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . --rfsimulator.serveraddr ``` Notes: @@ -131,7 +129,7 @@ Notes: 3. The --rrc_config_path parameter SHALL specify where the 2 RAW files are located (`rbconfig.raw` and `reconfig.raw`). - If you are running on the same machine and launched the 2 executables (`nr-softmodem` and `nr-uesoftmodem`) from the same directory, nothing has to be done. - If you launched the 2 executables from 2 different folders, just point to the location where you launched the `nr-softmodem`: - * `sudo RFSIMULATOR= ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path /the/path/where/you/launched/nr-softmodem` + * `sudo ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path /the/path/where/you/launched/nr-softmodem --rfsimulator.serveraddr ` - If you are not running on the same machine or launched the 2 executables from 2 different folders, you need to **COPY** the 2 raw files * `scp usera@machineA:/the/path/where/you/launched/nr-softmodem/r*config.raw userb@machineB:/the/path/where/you/will/launch/nr-uesoftmodem/` * Obviously this operation SHALL be done before launching the `nr-uesoftmodem` executable. @@ -203,7 +201,7 @@ to add a lot of noise: Example run commands: ```bash -sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN ``` # Real time control and monitoring diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 1175d9ec42..1a4e05c20d 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -219,14 +219,6 @@ static void socketError(rfsimulator_state_t *bridge, int sock) { } } -#define helpTxt "\ -\x1b[31m\ -rfsimulator: error: you have to run one UE and one eNB\n\ -For this, export RFSIMULATOR=enb (eNB case) or \n\ - RFSIMULATOR= (UE case)\n\ - or use rfsimulator.serveraddr configuration option\n\ -\x1b[m" - enum blocking_t { notBlocking, blocking From 40640f943e345a8653ef49cc5f112c9b7dd45172 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 24 Jun 2023 18:41:16 +0200 Subject: [PATCH 08/87] Add RFsimulator server option to rfsim configs --- ci-scripts/conf_files/enb.band38.25prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/enb.band7.100prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/enb.band7.25prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf | 4 ++++ ci-scripts/conf_files/enb.band7.50prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf | 4 ++++ ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf | 4 ++++ ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf | 4 ++++ ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf | 4 ++++ ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf | 4 ++++ ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf | 4 ++++ 11 files changed, 44 insertions(+) diff --git a/ci-scripts/conf_files/enb.band38.25prb.rfsim.conf b/ci-scripts/conf_files/enb.band38.25prb.rfsim.conf index 79f4fce746..e19cd4d68a 100644 --- a/ci-scripts/conf_files/enb.band38.25prb.rfsim.conf +++ b/ci-scripts/conf_files/enb.band38.25prb.rfsim.conf @@ -208,6 +208,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/enb.band7.100prb.rfsim.conf b/ci-scripts/conf_files/enb.band7.100prb.rfsim.conf index 71fbc663fe..3c0b994017 100644 --- a/ci-scripts/conf_files/enb.band7.100prb.rfsim.conf +++ b/ci-scripts/conf_files/enb.band7.100prb.rfsim.conf @@ -241,6 +241,10 @@ RUs = } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { diff --git a/ci-scripts/conf_files/enb.band7.25prb.rfsim.conf b/ci-scripts/conf_files/enb.band7.25prb.rfsim.conf index 71e9029c4b..c5d8383860 100644 --- a/ci-scripts/conf_files/enb.band7.25prb.rfsim.conf +++ b/ci-scripts/conf_files/enb.band7.25prb.rfsim.conf @@ -241,6 +241,10 @@ RUs = } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { diff --git a/ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf b/ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf index 71e9029c4b..c5d8383860 100644 --- a/ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf +++ b/ci-scripts/conf_files/enb.band7.25prb.rfsim.nos1.conf @@ -241,6 +241,10 @@ RUs = } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { diff --git a/ci-scripts/conf_files/enb.band7.50prb.rfsim.conf b/ci-scripts/conf_files/enb.band7.50prb.rfsim.conf index 4e037ab3da..abfc3887cd 100644 --- a/ci-scripts/conf_files/enb.band7.50prb.rfsim.conf +++ b/ci-scripts/conf_files/enb.band7.50prb.rfsim.conf @@ -241,6 +241,10 @@ RUs = } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf index e98896ac5d..e0b5dc7257 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf @@ -374,6 +374,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf index e460fb0a4d..7603148fb7 100644 --- a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf @@ -234,6 +234,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf index f4f65fe8dc..5bf2525092 100644 --- a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf @@ -212,6 +212,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf index 453b03910b..ab6c6b2467 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf @@ -221,6 +221,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf index 9728977d21..ff1651c89a 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf @@ -254,6 +254,10 @@ THREAD_STRUCT = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen diff --git a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf index 9a6efada5b..a90174f3b7 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf @@ -219,6 +219,10 @@ RUs = ( } ); +rfsimulator: { + serveraddr = "server"; +}; + THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" From 2ce109cd633eeaea7756c8f5a18ba422054d42cc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 24 Jun 2023 18:41:38 +0200 Subject: [PATCH 09/87] Remove RFsimulator server option from non-rfsim configs --- .../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf | 7 ------- ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf | 9 --------- .../conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf | 9 --------- 3 files changed, 25 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 8234a17020..26b2a4f111 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -217,13 +217,6 @@ THREAD_STRUCT = ( worker_config = "WORKER_ENABLE"; } ); -rfsimulator: { -serveraddr = "server"; - serverport = "4043"; - options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; - IQfile = "/tmp/rfsimulator.iqs" -} log_config : { diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf index 16cc70ca4b..d208d098af 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf @@ -226,15 +226,6 @@ THREAD_STRUCT = ( } ); -rfsimulator : -{ - serveraddr = "server"; - serverport = "4043"; - options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; - IQfile = "/tmp/rfsimulator.iqs"; -}; - security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen diff --git a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf index a90174f3b7..485f395019 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf @@ -232,15 +232,6 @@ THREAD_STRUCT = ( } ); -rfsimulator : -{ - serveraddr = "server"; - serverport = "4043"; - options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; - IQfile = "/tmp/rfsimulator.iqs"; -}; - security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen From 9ea0ef666e41d6d658de6fde794b139e006674f5 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Sat, 1 Jul 2023 10:05:07 +0100 Subject: [PATCH 10/87] Add support for NR band n48 --- openair2/GNB_APP/gnb_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index f5ce7121cc..3d1a766b44 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -115,6 +115,7 @@ const sync_raster_t sync_raster[] = { {40, 0, 5756, 1, 5995}, {41, 0, 6246, 3, 6717}, {41, 1, 6252, 3, 6714}, + {48, 1, 7884, 1, 7982}, {50, 0, 3584, 1, 3787}, {51, 0, 3572, 1, 3574}, {66, 0, 5279, 1, 5494}, From 57a3f9fe2f56b97d471217a010f06f5b9dc83dc6 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Mon, 3 Jul 2023 07:48:03 +0100 Subject: [PATCH 11/87] Bugfix when deleting a SDAP entity that is not the first one on the list and prevents segfault when removing the last one on the list Fix delete entity function, a SDAP entity is a combination of a UE and PDUSession, we cannot just simply delete the first entity for a UE --- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 28 ++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index e81490630c..a0c8f10ada 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -468,23 +468,21 @@ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id) return NULL; } -void delete_nr_sdap_entity(ue_id_t ue_id) +int nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) { - nr_sdap_entity_t *entityPtr, *entityPrev = NULL; - entityPtr = sdap_info.sdap_entity_llist; - - if (entityPtr->ue_id == ue_id) { - sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; - free(entityPtr); - } else { - while (entityPtr->ue_id != ue_id && entityPtr->next_entity != NULL) { - entityPrev = entityPtr; - entityPtr = entityPtr->next_entity; - } - - if (entityPtr->ue_id != ue_id) { - entityPrev->next_entity = entityPtr->next_entity; + nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; + int pos = 0; + while (entityPtr != NULL) { + if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { + if (pos == 0) { + sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; + } + LOG_I(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); free(entityPtr); + return 1; } + entityPtr = entityPtr->next_entity; + pos++; } + return 0; } From 62d33ce523a7a1ae837078d4a3ef648fc68b5199 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Mon, 3 Jul 2023 09:40:34 +0100 Subject: [PATCH 12/87] Add function to remove all SDAP entities for a UE --- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index a0c8f10ada..bc3ea0ad9d 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -486,3 +486,23 @@ int nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) } return 0; } + +void nr_sdap_delete_ue_entities(ue_id_t ue_id) +{ + nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; + int pos = 0; + while (entityPtr != NULL) { + if (entityPtr->ue_id == ue_id) { + if (pos == 0) { + sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; + } + LOG_I(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); + nr_sdap_entity_t *entityPrev = entityPtr; + free(entityPtr); + entityPtr = entityPrev->next_entity; + } else { + entityPtr = entityPtr->next_entity; + } + pos++; + } +} From 2500138feafaebdcd5cfc11c792cb98405a1a942 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 7 Jun 2023 18:35:01 +0200 Subject: [PATCH 13/87] Fixup: copying via cls_cmd only supports absolute paths --- ci-scripts/cls_cmd.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_cmd.py b/ci-scripts/cls_cmd.py index 1e4c12e854..30f00cdb02 100644 --- a/ci-scripts/cls_cmd.py +++ b/ci-scripts/cls_cmd.py @@ -118,11 +118,14 @@ class LocalCmd(Cmd): def getBefore(self): return self.cp.stdout - def copyin(self, scpIp, scpUser, scpPw, src, tgt): - self.run(f'cp -r {src} {tgt}') + def copyin(self, src, tgt, recursive=False): + if src[0] != '/' or tgt[0] != '/': + raise Exception('support only absolute file paths!') + opt = '-r' if recursive else '' + self.run(f'cp {opt} {src} {tgt}') - def copyout(self, scpIp, scpUser, scpPw, src, tgt): - self.run(f'cp -r {src} {tgt}') + def copyout(self, src, tgt, recursive=False): + self.copyin(src, tgt, recursive) class RemoteCmd(Cmd): def __init__(self, hostname, d=None): From 9f55d7121cbc42c3783da68402eaf4867808fa92 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 7 Jun 2023 18:41:27 +0200 Subject: [PATCH 14/87] Refactor Ping to use %cn_ip% for address to ping, or hardcoded --- ci-scripts/cls_oaicitest.py | 43 +++++++++---------- .../container_lte_b200_fdd_05Mhz_tm1.xml | 2 +- ...lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml | 4 +- .../container_lte_b200_fdd_10Mhz_tm1.xml | 2 +- .../container_lte_b200_fdd_10Mhz_tm1_cdrx.xml | 2 +- .../container_lte_b200_fdd_20Mhz_tm1.xml | 2 +- .../container_lte_b200_tdd_05Mhz_tm1.xml | 2 +- .../container_lte_b200_tdd_05Mhz_tm2.xml | 2 +- .../container_lte_b200_tdd_10Mhz_tm1.xml | 2 +- .../container_lte_b200_tdd_20Mhz_tm1.xml | 2 +- ...e_b200_tdd_20Mhz_tm1_default_scheduler.xml | 2 +- .../container_lte_n3xx_tdd_2x2_tm1.xml | 4 +- .../container_lte_n3xx_tdd_2x2_tm2.xml | 4 +- .../xml_files/container_nsa_b200_quectel.xml | 8 ++-- .../xml_files/container_sa_aw2s_asue.xml | 4 +- .../xml_files/container_sa_b200_quectel.xml | 4 +- .../container_sa_f1_b200_quectel.xml | 8 ++-- ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml | 4 +- .../fr1_nsa_2x2_quectel_attach_detach.xml | 2 +- ci-scripts/xml_files/fr1_nsa_quectel.xml | 4 +- .../fr1_nsa_quectel_attach_detach.xml | 4 +- ci-scripts/xml_files/fr1_nsa_quectel_long.xml | 4 +- ci-scripts/xml_files/fr1_sa_oaiue_b200.xml | 4 +- ci-scripts/xml_files/fr1_sa_oaiue_n310.xml | 4 +- ci-scripts/xml_files/fr1_sa_oaiue_x300.xml | 4 +- ci-scripts/xml_files/fr1_sa_quectel.xml | 4 +- .../xml_files/fr1_sa_quectel_162prb.xml | 2 +- .../xml_files/fr1_sa_quectel_stages.xml | 2 +- 28 files changed, 66 insertions(+), 69 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index ed04b34aef..97eaed8ba5 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -511,37 +511,34 @@ class OaiCiTest(): return (False, f"UE {ue.getName()} has no IP address") ping_log_file = f'ping_{self.testCase_id}_{ue.getName()}.log' ping_time = re.findall("-c *(\d+)",str(self.ping_args)) - #target address is different depending on EPC type - if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): - Target = EPC.MmeIPAddress - elif re.match('OAICN5G', EPC.Type, re.IGNORECASE): - Target = EPC.MmeIPAddress - elif re.match('OC-OAI-CN5G', EPC.Type, re.IGNORECASE): - Target = "172.21.6.100" - else: - Target = EPC.IPAddress + local_ping_log_file = f'{os.getcwd()}/{ping_log_file}' + # if has pattern %cn_ip%, replace with core IP address, else we assume the IP is present + if re.search('%cn_ip%', self.ping_args): + #target address is different depending on EPC type + if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): + self.ping_args = re.sub('%cn_ip%', EPC.MmeIPAddress, self.ping_args) + elif re.match('OAICN5G', EPC.Type, re.IGNORECASE): + self.ping_args = re.sub('%cn_ip%', EPC.MmeIPAddress, self.ping_args) + elif re.match('OC-OAI-CN5G', EPC.Type, re.IGNORECASE): + self.ping_args = re.sub('%cn_ip%', '172.21.6.100', self.ping_args) + else: + self.ping_args = re.sub('%cn_ip%', EPC.IPAddress, self.ping_args) #ping from module NIC rather than IP address to make sure round trip is over the air interface = f'-I {ue.getIFName()}' if ue.getIFName() else '' - ping_cmd = f'{ue.getCmdPrefix()} ping {interface} {self.ping_args} {Target} &> /tmp/{ping_log_file}' + ping_cmd = f'{ue.getCmdPrefix()} ping {interface} {self.ping_args} 2>&1 | tee /tmp/{ping_log_file}' cmd = cls_cmd.getConnection(ue.getHost()) response = cmd.run(ping_cmd, timeout=int(ping_time[0])*1.5) if response.returncode != 0: - ping_status = -1 - else: - #copy the ping log file to have it locally for analysis (ping stats) - cmd.copyin(src=f'/tmp/{ping_log_file}', tgt=ping_log_file) - - cmd.close() - - # TIMEOUT CASE - ue_header = f'UE {ue.getName()} ({ueIP})' - if ping_status < 0: message = ue_header + ': ping crashed: TIMEOUT?' logging.error('\u001B[1;37;41m ' + message + ' \u001B[0m') return (False, message) - #search is done on cat result - logging.debug('Analyzing Ping log file : ' + os.getcwd() + '/' + ping_log_file) - with open(ping_log_file, 'r') as f: + + #copy the ping log file to have it locally for analysis (ping stats) + cmd.copyin(src=f'/tmp/{ping_log_file}', tgt=local_ping_log_file) + cmd.close() + + ue_header = f'UE {ue.getName()} ({ueIP})' + with open(local_ping_log_file, 'r') as f: ping_output = "".join(f.readlines()) result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', ping_output) if result is None: diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml index 0023edd171..7d43346bd6 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml @@ -110,7 +110,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml index bf8cb5e256..34bee784a4 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml @@ -148,7 +148,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 @@ -156,7 +156,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml index ea89f4193a..040211347b 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml @@ -104,7 +104,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Ping ping (10MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml index 788a1759dc..dc6df2da57 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml @@ -97,7 +97,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Ping ping (10MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml index 4fef927a3b..8015a54f43 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml @@ -103,7 +103,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Ping ping (20MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 5 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml index eb11412ef5..1aaa731b93 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml @@ -111,7 +111,7 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml index 887b5dab9b..c3a0b2ef89 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml @@ -101,7 +101,7 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm2.xml Ping ping (5MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml index 3874ff7028..e82564338f 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml @@ -101,7 +101,7 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml Ping ping (10MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml index 77e00d72ac..3e558f0ac3 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml @@ -101,7 +101,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml Ping ping (20MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml index fd454f13e2..645de59565 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml @@ -103,7 +103,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml Ping ping (20MHz - 20 sec) - -c 20 + -c 20 %cn_ip% 25 adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml index 480825bede..49cd79783a 100644 --- a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml @@ -102,7 +102,7 @@ Ping Ping: 20 pings nrmodule2_quectel - -c 20 + -c 20 %cn_ip% 1 60 @@ -111,7 +111,7 @@ Ping Ping: 100 pings, size 1024 nrmodule2_quectel - -c 100 -s 1024 -i 0,2 + -c 100 -s 1024 -i 0,2 %cn_ip% 1 60 diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml index b3dc7efab7..a9ed0b2bea 100644 --- a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml @@ -102,7 +102,7 @@ Ping Ping: 20 pings nrmodule2_quectel - -c 20 + -c 20 %cn_ip% 1 60 @@ -111,7 +111,7 @@ Ping Ping: 100 pings, size 1024 nrmodule2_quectel - -c 100 -s 1024 -i 0,2 + -c 100 -s 1024 -i 0,2 %cn_ip% 1 60 diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml index ee264b6c43..6a2f31aac2 100644 --- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -151,7 +151,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 15 @@ -160,7 +160,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 15 @@ -169,7 +169,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 15 @@ -178,7 +178,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 15 diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 7959718eb0..8241d2da83 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -123,7 +123,7 @@ Ping Ping: 20pings in 20sec, multi-ue amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 - -c 20 + -c 20 %cn_ip% 1 25 @@ -132,7 +132,7 @@ Ping Ping: 100pings in 20sec, multi-ue amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 30 diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml index 97b77e2499..9d36b76084 100644 --- a/ci-scripts/xml_files/container_sa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml @@ -113,7 +113,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 15 @@ -122,7 +122,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 15 diff --git a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml index 3fab62b265..a00a575a81 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml @@ -119,7 +119,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 25 @@ -128,7 +128,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 110 @@ -137,7 +137,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 110 @@ -146,7 +146,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 110 diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml index 185d637218..78787d34fa 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml @@ -144,7 +144,7 @@ Ping Ping: 20pings in 20sec nrmodule2_quectel - -c 20 + -c 20 %cn_ip% 5 @@ -152,7 +152,7 @@ Ping Ping: 100pings in 20sec nrmodule2_quectel - -c 100 -i 0,2 + -c 100 -i 0,2 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml index d1515898ff..37a80058d3 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml @@ -144,7 +144,7 @@ Ping Ping: 20pings in 20sec nrmodule2_quectel - -c 20 + -c 20 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_nsa_quectel.xml b/ci-scripts/xml_files/fr1_nsa_quectel.xml index 962b3eef7e..e300bd7f1c 100644 --- a/ci-scripts/xml_files/fr1_nsa_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel.xml @@ -141,7 +141,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 1 15 @@ -150,7 +150,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 15 diff --git a/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml index 593e2d326d..732dd3bb7d 100644 --- a/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml @@ -109,7 +109,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 50 @@ -117,7 +117,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 50 diff --git a/ci-scripts/xml_files/fr1_nsa_quectel_long.xml b/ci-scripts/xml_files/fr1_nsa_quectel_long.xml index 89825cdbf2..a37cbb4d72 100644 --- a/ci-scripts/xml_files/fr1_nsa_quectel_long.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel_long.xml @@ -106,7 +106,7 @@ Ping Ping: 20pings in 20sec idefix - -c 20 + -c 20 %cn_ip% 50 @@ -114,7 +114,7 @@ Ping Ping: 100pings in 20sec idefix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 50 diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml b/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml index 454cd1486b..97a6404c55 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml @@ -79,7 +79,7 @@ Ping Ping from CN to UE: 20pings in 20sec - -c 20 + -c 20 %cn_ip% 5 @@ -87,7 +87,7 @@ Ping Ping from CN to UE: 100pings in 20sec oai_ue_obelix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml index 7105828be4..00c3431aa0 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml @@ -95,7 +95,7 @@ Ping Ping from CN to UE: 20pings in 20sec oai_ue_obelix - -c 20 + -c 20 %cn_ip% 5 @@ -103,7 +103,7 @@ Ping Ping from CN to UE: 100pings in 20sec oai_ue_obelix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml b/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml index fcc6088096..315674c9e6 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml @@ -80,7 +80,7 @@ Ping Ping from CN to UE: 20pings in 20sec oai_ue_obelix - -c 20 + -c 20 %cn_ip% 5 @@ -88,7 +88,7 @@ Ping Ping from CN to UE: 100pings in 20sec oai_ue_obelix - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 5 diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml index b13de6f3ef..5fd276e6ce 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel.xml @@ -114,7 +114,7 @@ Ping Ping: 40pings in 40sec nrmodule2_quectel - -c 40 + -c 40 %cn_ip% 1 10 @@ -123,7 +123,7 @@ Ping Ping: 100pings in 20sec nrmodule2_quectel - -c 100 -i 0,2 + -c 100 -i 0,2 %cn_ip% 1 10 diff --git a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml index d1c250862d..507e9b1b92 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml @@ -111,7 +111,7 @@ Ping Ping: 40pings in 40sec nrmodule2_quectel - -c 40 + -c 40 %cn_ip% 1 20 diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml index 94cf5d71ef..006526e177 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml @@ -119,7 +119,7 @@ Ping Ping: 40pings in 40sec nrmodule2_quectel - -c 40 + -c 40 %cn_ip% 1 20 From 2880be7282fa792cbefb00e54eef4ecad2774a7c Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Tue, 13 Jun 2023 11:52:36 +0200 Subject: [PATCH 15/87] Rename UENetworkScript to NetworkScript in ci_ueinfra --- ci-scripts/ci_ueinfra.yaml | 30 +++++++++++++++--------------- ci-scripts/cls_module_ue.py | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index 8a6c76645a..bd2442cf16 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -4,7 +4,7 @@ idefix: TermScript: sudo -S killall --signal SIGKILL quectel-CM AttachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 wup DetachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 detach - UENetworkScript: ip a show dev wwan0 + NetworkScript: ip a show dev wwan0 IF: wwan0 MTU: 1500 Trace: True @@ -15,7 +15,7 @@ nrmodule2_quectel: TermScript: sudo -S killall --signal SIGKILL quectel-CM AttachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 wup DetachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 detach - UENetworkScript: ip a show dev wwan0 + NetworkScript: ip a show dev wwan0 IF: wwan0 MTU: 1500 LogStore: /media/ci_qlogs @@ -29,7 +29,7 @@ adb_ue_1: CheckStatusScript: /home/oaicicd/ci_ctl_adb.sh check R3CM40LZPHT DataEnableScript: adb -s R3CM40LZPHT shell "svc data enable" DataDisableScript: adb -s R3CM40LZPHT shell "svc data disable" - UENetworkScript: adb -s R3CM40LZPHT shell "ip address show | grep rmnet_data0" + NetworkScript: adb -s R3CM40LZPHT shell "ip address show | grep rmnet_data0" CmdPrefix: adb -s R3CM40LZPHT shell MTU: 1500 LogStore: /media/usb-drive/ci_adb_1-logs @@ -42,7 +42,7 @@ adb_ue_2: CheckStatusScript: /home/oaicicd/ci_ctl_adb.sh check 5200c00db4413517 DataEnableScript: adb -s 5200c00db4413517 shell "svc data enable" DataDisableScript: adb -s 5200c00db4413517 shell "svc data disable" - UENetworkScript: adb -s 5200c00db4413517 shell "ip address show | grep rmnet" + NetworkScript: adb -s 5200c00db4413517 shell "ip address show | grep rmnet" CmdPrefix: adb -s 5200c00db4413517 shell MTU: 1500 LogStore: /media/usb-drive/ci_adb_2-logs @@ -55,74 +55,74 @@ amarisoft_ue_1: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":1}' - UENetworkScript: ip netns exec ue1 ip a show dev pdn0 + NetworkScript: ip netns exec ue1 ip a show dev pdn0 CmdPrefix: ip netns exec ue1 MTU: 1500 amarisoft_ue_2: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":2}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":2}' - UENetworkScript: ip netns exec ue2 ip a show dev pdn0 + NetworkScript: ip netns exec ue2 ip a show dev pdn0 CmdPrefix: ip netns exec ue2 MTU: 1500 amarisoft_ue_3: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":3}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":3}' - UENetworkScript: ip netns exec ue3 ip a show dev pdn0 + NetworkScript: ip netns exec ue3 ip a show dev pdn0 CmdPrefix: ip netns exec ue3 MTU: 1500 amarisoft_ue_4: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":4}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":4}' - UENetworkScript: ip netns exec ue4 ip a show dev pdn0 + NetworkScript: ip netns exec ue4 ip a show dev pdn0 CmdPrefix: ip netns exec ue4 MTU: 1500 amarisoft_ue_5: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":5}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":5}' - UENetworkScript: ip netns exec ue5 ip a show dev pdn0 + NetworkScript: ip netns exec ue5 ip a show dev pdn0 CmdPrefix: ip netns exec ue5 MTU: 1500 amarisoft_ue_6: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":6}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":6}' - UENetworkScript: ip netns exec ue6 ip a show dev pdn0 + NetworkScript: ip netns exec ue6 ip a show dev pdn0 CmdPrefix: ip netns exec ue6 MTU: 1500 amarisoft_ue_7: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":7}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":7}' - UENetworkScript: ip netns exec ue7 ip a show dev pdn0 + NetworkScript: ip netns exec ue7 ip a show dev pdn0 CmdPrefix: ip netns exec ue7 MTU: 1500 amarisoft_ue_8: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":8}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":8}' - UENetworkScript: ip netns exec ue8 ip a show dev pdn0 + NetworkScript: ip netns exec ue8 ip a show dev pdn0 CmdPrefix: ip netns exec ue8 MTU: 1500 amarisoft_ue_9: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":9}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":9}' - UENetworkScript: ip netns exec ue9 ip a show dev pdn0 + NetworkScript: ip netns exec ue9 ip a show dev pdn0 CmdPrefix: ip netns exec ue9 MTU: 1500 amarisoft_ue_10: Host: amariue AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":10}' DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":10}' - UENetworkScript: ip netns exec ue10 ip a show dev pdn0 + NetworkScript: ip netns exec ue10 ip a show dev pdn0 CmdPrefix: ip netns exec ue10 MTU: 1500 oai_ue_obelix: Host: obelix - UENetworkScript: ip a show dev oaitun_ue1 + NetworkScript: ip a show dev oaitun_ue1 IF: oaitun_ue1 diff --git a/ci-scripts/cls_module_ue.py b/ci-scripts/cls_module_ue.py index 26a2d1c242..19dac1044d 100644 --- a/ci-scripts/cls_module_ue.py +++ b/ci-scripts/cls_module_ue.py @@ -54,7 +54,7 @@ class Module_UE: "detach": m.get('DetachScript'), "initialize": m.get('InitScript'), "terminate": m.get('TermScript'), - "getNetwork": m.get('UENetworkScript'), + "getNetwork": m.get('NetworkScript'), "check": m.get('CheckStatusScript'), "dataEnable": m.get('DataEnableScript'), "dataDisable": m.get('DataDisableScript'), From aac010ea18e6d2247572cadd5c4b32868f6ea7f4 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Tue, 13 Jun 2023 11:56:56 +0200 Subject: [PATCH 16/87] Add 5grfsim, 4grfsim, l2sim5g, l2sim4g interface details in ci_ueinfra --- ci-scripts/ci_ueinfra.yaml | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index bd2442cf16..2aa3952fcb 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -126,3 +126,59 @@ oai_ue_obelix: Host: obelix NetworkScript: ip a show dev oaitun_ue1 IF: oaitun_ue1 + +rfsim5g_gnb_nos1: + Host: localhost + NetworkScript: docker exec rfsim5g-oai-gnb ip a show dev oaitun_enb1 + CmdPrefix: docker exec rfsim5g-oai-gnb + IF: oaitun_enb1 + +rfsim5g_ue: + Host: localhost + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue1 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue1 + +rfsim5g_ext_dn: + Host: localhost + NetworkScript: docker exec rfsim5g-oai-ext-dn ip a show dev eth0 + CmdPrefix: docker exec rfsim5g-oai-ext-dn + +rfsim4g_ue: + Host: localhost + NetworkScript: docker exec rfsim4g-oai-lte-ue0 ip a show dev oaitun_ue1 + CmdPrefix: docker exec rfsim4g-oai-lte-ue0 + IF: oaitun_ue1 + +rfsim4g_ext_dn: + Host: localhost + NetworkScript: docker exec rfsim4g-trf-gen ip a show dev eth0 + CmdPrefix: docker exec rfsim4g-trf-gen + +rfsim4g_enb_nos1: + Host: localhost + NetworkScript: docker exec rfsim4g-oai-enb ip a show dev oaitun_enb1 + CmdPrefix: docker exec rfsim4g-oai-enb + IF: oaitun_enb1 + +l2sim5g_ue: + Host: localhost + NetworkScript: docker exec l2sim-oai-nr-ue0 ip a show dev oaitun_ue1 + CmdPrefix: docker exec l2sim-oai-nr-ue0 + IF: oaitun_ue1 + +l2sim5g_ext_dn: + Host: localhost + NetworkScript: docker exec l2sim-oai-ext-dn ip a show dev eth0 + CmdPrefix: docker exec l2sim-oai-ext-dn + +l2sim4g_ue: + Host: localhost + NetworkScript: docker exec l2sim4g-oai-lte-ue1 ip a show dev oaitun_ue1 + CmdPrefix: docker exec l2sim4g-oai-lte-ue1 + IF: oaitun_ue1 + +l2sim4g_ext_dn: + Host: localhost + NetworkScript: docker exec l2sim4g-trf-gen ip a show dev eth0 + CmdPrefix: docker exec l2sim4g-trf-gen From 54d2b887b8f2f84cc69d84b8bec65649c1b4c4d9 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Mon, 3 Jul 2023 14:41:21 +0200 Subject: [PATCH 17/87] Use Ping instead of PingFromContainer in simulator tests Affected tests: - 5G RFsim TDD do-ra - 5g-rfsim-fdd - 5g-rfsim - 5grfsim-e1 - 5grfsim-24prb - 5grfsim-fr2-32prb - 5grfsim-fdd-phytest - 5grfsim-u0-25prb - 5grfsim-2x2 - 5grfsim-f1 - 5grfsim-f1-accelleran - 4g-l2sim-tdd - 4g-rfsim-fdd-05mhz - 4g-rfsim-fdd-05mhz-nos1 - 4g-rfsim-fdd-10mhz - 4g-rfsim-fdd-20mhz - 4g-rfsim-tdd-05mhz - 5g-l2sim --- .../xml_files/container_4g_l2sim_tdd.xml | 16 +++++----- .../container_4g_rfsim_fdd_05MHz.xml | 16 +++++----- .../container_4g_rfsim_fdd_05MHz_noS1.xml | 16 +++++----- .../container_4g_rfsim_fdd_10MHz.xml | 16 +++++----- .../container_4g_rfsim_fdd_20MHz.xml | 16 +++++----- .../container_4g_rfsim_tdd_05MHz.xml | 16 +++++----- .../xml_files/container_5g_e1_rfsim.xml | 16 +++++----- .../xml_files/container_5g_f1_rfsim.xml | 16 +++++----- .../xml_files/container_5g_fdd_rfsim.xml | 16 +++++----- .../xml_files/container_5g_l2sim_tdd.xml | 16 +++++----- ci-scripts/xml_files/container_5g_rfsim.xml | 32 +++++++++---------- .../xml_files/container_5g_rfsim_24prb.xml | 16 +++++----- .../xml_files/container_5g_rfsim_2x2.xml | 16 +++++----- .../container_5g_rfsim_f1_accelleran.xml | 8 ++--- .../container_5g_rfsim_fdd_phytest.xml | 16 +++++----- .../container_5g_rfsim_fr2_32prb.xml | 16 +++++----- .../xml_files/container_5g_rfsim_tdd_dora.xml | 16 +++++----- .../xml_files/container_5g_rfsim_u0_25prb.xml | 16 +++++----- 18 files changed, 148 insertions(+), 148 deletions(-) diff --git a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml index 419ede8cbb..22f4a8be3a 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml @@ -89,19 +89,19 @@ - PingFromContainer + Ping Ping trf-gen from LTE-UE 1 - l2sim4g-oai-lte-ue1 - -I oaitun_ue1 -c 20 192.168.61.11 - 0 + l2sim4g_ue + -c 20 192.168.61.11 + 0 - PingFromContainer + Ping Ping LTE-UE 1 from trf-gen - l2sim4g-trf-gen - -c 20 12.0.0.2 - 0 + l2sim4g_ext_dn + -c 20 12.0.0.2 + 0 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml index a776b85c2c..37d53e09e4 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml @@ -95,19 +95,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 192.168.61.11 - 5 + rfsim4g_ue + -c 20 192.168.61.11 + 5 - PingFromContainer + Ping Ping LTE-UE from Traffic-Gen - rfsim4g-trf-gen - -c 20 12.0.0.2 - 5 + rfsim4g_ext_dn + -c 20 12.0.0.2 + 5 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml index e70d954a22..5a6189dced 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml @@ -75,19 +75,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 10.0.1.1 - 5 + rfsim4g_ue + -c 20 10.0.1.1 + 5 - PingFromContainer + Ping Ping LTE-UE from eNB - rfsim4g-oai-enb - -I oaitun_enb1 -c 20 10.0.1.2 - 5 + rfsim4g_enb_nos1 + -c 20 10.0.1.2 + 5 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml index 6b88816c4a..e6c3e1f965 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml @@ -95,19 +95,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 192.168.61.11 - 5 + rfsim4g_ue + -c 20 192.168.61.11 + 5 - PingFromContainer + Ping Ping LTE-UE from Traffic-Gen - rfsim4g-trf-gen - -c 20 12.0.0.2 - 5 + rfsim4g_ext_dn + -c 20 12.0.0.2 + 5 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml index e33554c8ce..86b217a2a4 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml @@ -95,19 +95,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 192.168.61.11 - 5 + rfsim4g_ue + -c 20 192.168.61.11 + 5 - PingFromContainer + Ping Ping LTE-UE from Traffic-Gen - rfsim4g-trf-gen - -c 20 12.0.0.2 - 5 + rfsim4g_ext_dn + -c 20 12.0.0.2 + 5 diff --git a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml index c39679e063..862e9cca52 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml @@ -96,19 +96,19 @@ - PingFromContainer + Ping Ping Traffic-Gen from LTE-UE - rfsim4g-oai-lte-ue0 - -I oaitun_ue1 -c 20 192.168.61.11 - 5 + rfsim4g_ue + -c 20 192.168.61.11 + 5 - PingFromContainer + Ping Ping LTE-UE from Traffic-Gen - rfsim4g-trf-gen - -c 20 12.0.0.2 - 5 + rfsim4g_ext_dn + -c 20 12.0.0.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml index 7130976dad..e37ba4cf96 100644 --- a/ci-scripts/xml_files/container_5g_e1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -87,19 +87,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.73.135 - 5 + rfsim5g_ue + -c 20 192.168.73.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 8a7549da91..86d369e526 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -87,19 +87,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index e1dc8f0d60..e2d1e3c287 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -80,19 +80,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_l2sim_tdd.xml b/ci-scripts/xml_files/container_5g_l2sim_tdd.xml index e2631d6e05..6abadf2f4c 100644 --- a/ci-scripts/xml_files/container_5g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_5g_l2sim_tdd.xml @@ -87,19 +87,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - l2sim-oai-nr-ue0 - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + l2sim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - l2sim-oai-ext-dn - -c 20 12.1.1.2 - 5 + l2sim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 86e5159264..4923177ee5 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -91,35 +91,35 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 - PingFromContainer + Ping Ping ext-dn from Second NR-UE - rfsim5g-oai-nr-ue2 - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping Second NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.3 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.3 + 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index fea7e03e5e..f124176209 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -80,19 +80,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 -i0.2 192.168.72.135 - 5 + rfsim5g_ue + -c 20 -i0.2 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 -i0.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 -i0.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 5c5b5a8d8b..b178fe0df7 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -80,19 +80,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml index d727fdfd1e..d1433db738 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml @@ -58,11 +58,11 @@ - PingFromContainer + Ping Test Connectivity (ping) - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 12.1.1.1 - 0 + rfsim5g_ue + -c 20 12.1.1.1 + 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index 4d86cd69ef..1ad3158d20 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -62,19 +62,19 @@ - PingFromContainer + Ping Ping gNB from NR-UE - rfsim5g-oai-nr-ue - -c20 -i0.2 10.0.1.1 - 0 + rfsim5g_ue + -c20 -i0.2 10.0.1.1 + 0 - PingFromContainer + Ping Ping NR-UE from gNB - rfsim5g-oai-gnb - -c20 -i0.2 10.0.1.2 - 0 + rfsim5g_gnb_nos1 + -c20 -i0.2 10.0.1.2 + 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index b6209e871c..19bb89518a 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -60,19 +60,19 @@ - PingFromContainer + Ping Ping gNB from NR-UE - rfsim5g-oai-nr-ue - -c20 -i0.2 10.0.1.1 - 0 + rfsim5g_ue + -c20 -i0.2 10.0.1.1 + 0 - PingFromContainer + Ping Ping NR-UE from gNB - rfsim5g-oai-gnb - -c20 -i0.2 10.0.1.2 - 0 + rfsim5g_gnb_nos1 + -c20 -i0.2 10.0.1.2 + 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml index 095986b751..e7b0e7903d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -60,19 +60,19 @@ - PingFromContainer + Ping Ping gNB from NR-UE - rfsim5g-oai-nr-ue - -c20 -i0.2 10.0.1.1 - 0 + rfsim5g_ue + -c20 -i0.2 10.0.1.1 + 0 - PingFromContainer + Ping Ping NR-UE from gNB - rfsim5g-oai-gnb - -c20 -i0.2 10.0.1.2 - 0 + rfsim5g_gnb_nos1 + -c20 -i0.2 10.0.1.2 + 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index b030f5d423..e9e9374cf1 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -80,19 +80,19 @@ - PingFromContainer + Ping Ping ext-dn from NR-UE - rfsim5g-oai-nr-ue - -I oaitun_ue1 -c 20 192.168.72.135 - 5 + rfsim5g_ue + -c 20 192.168.72.135 + 5 - PingFromContainer + Ping Ping NR-UE from ext-dn - rfsim5g-oai-ext-dn - -c 20 12.1.1.2 - 5 + rfsim5g_ext_dn + -c 20 12.1.1.2 + 5 From d0aa233aaf73add0a18721c0072f91afe62db84f Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Mon, 12 Jun 2023 17:11:22 +0200 Subject: [PATCH 18/87] Remove PingFromContainer definition and portions where it is called in main.py --- ci-scripts/cls_containerize.py | 56 ---------------------------------- ci-scripts/main.py | 15 --------- ci-scripts/xml_class_list.yml | 1 - 3 files changed, 72 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 520876ad06..813b14ce22 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -1341,62 +1341,6 @@ class Containerize(): HTML.CreateHtmlTestRowQueue(self.pingOptions, 'OK', [message]) - def PingFromContainer(self, HTML, RAN, UE): - myCmd = cls_cmd.LocalCmd() - self.exitStatus = 0 - ymlPath = self.yamlPath[0].split('/') - logPath = '../cmake_targets/log/' + ymlPath[1] - cmd = f'mkdir -p {logPath}' - myCmd.run(cmd, silent=True) - - cmd = f'docker exec {self.pingContName} /bin/bash -c "ping {self.pingOptions}" 2>&1 | tee {logPath}/ping_{HTML.testCase_id}.log' - pingStatus = myCmd.run(cmd, timeout=100, reportNonZero=False) - myCmd.close() - - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', pingStatus.stdout) - if result is None: - self.PingExit(HTML, RAN, UE, False, 'Packet Loss Not Found') - return - - packetloss = result.group('packetloss') - if float(packetloss) == 100: - self.PingExit(HTML, RAN, UE, False, 'Packet Loss is 100%') - return - - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', pingStatus.stdout) - if result is None: - self.PingExit(HTML, RAN, UE, False, 'Ping RTT_Min RTT_Avg RTT_Max Not Found!') - return - - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - - message = 'ping result\n' - message += ' ' + pal_msg + '\n' - message += ' ' + min_msg + '\n' - message += ' ' + avg_msg + '\n' - message += ' ' + max_msg + '\n' - packetLossOK = True - if float(packetloss) > float(self.pingLossThreshold): - message += '\nPacket Loss too high' - packetLossOK = False - elif float(packetloss) > 0: - message += '\nPacket Loss is not 0%' - self.PingExit(HTML, RAN, UE, packetLossOK, message) - - if packetLossOK: - logging.debug('\u001B[1;37;44m ping result \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - logging.info('\u001B[1m Ping Test PASS\u001B[0m') - def PingExit(self, HTML, RAN, UE, status, message): if status: HTML.CreateHtmlTestRowQueue(self.pingOptions, 'OK', [message]) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 97bc6fbef1..898dfca6d8 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -374,17 +374,6 @@ def GetParametersFromXML(action): if (string_field is not None): CONTAINERS.ran_checkers['u_retx_th'] = [float(x) for x in string_field.split(',')] - elif action == 'PingFromContainer': - string_field = test.findtext('container_name') - if (string_field is not None): - CONTAINERS.pingContName = string_field - string_field = test.findtext('options') - if (string_field is not None): - CONTAINERS.pingOptions = string_field - string_field = test.findtext('loss_threshold') - if (string_field is not None): - CONTAINERS.pingLossThreshold = string_field - elif action == 'IperfFromContainer': string_field = test.findtext('server_container_name') if (string_field is not None): @@ -881,10 +870,6 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CONTAINERS.UndeployGenObject(HTML, RAN, CiTestObj) if CONTAINERS.exitStatus==1: RAN.prematureExit = True - elif action == 'PingFromContainer': - CONTAINERS.PingFromContainer(HTML, RAN, CiTestObj) - if CONTAINERS.exitStatus==1: - RAN.prematureExit = True elif action == 'IperfFromContainer': CONTAINERS.IperfFromContainer(HTML, RAN, CiTestObj) if CONTAINERS.exitStatus==1: diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 1f7b1afdbe..116ad769c1 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -40,7 +40,6 @@ - Deploy_Run_PhySim - DeployGenObject - UndeployGenObject - - PingFromContainer - IperfFromContainer - StatsFromGenObject - LicenceAndFormattingCheck From 0807b1d99b54b5acd5ce0f4524a8603a1f8f5b33 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 9 Jun 2023 14:23:24 +0200 Subject: [PATCH 19/87] CI: docs for nrUE pipeline --- doc/TESTBenches.md | 11 ++++++ .../5g-nrue-bench.pdf | Bin 0 -> 138821 bytes .../5g-nrue-bench.png | Bin 0 -> 24001 bytes .../5g-nrue-bench.tex | 36 ++++++++++++++++++ doc/testbenches_doc_resources/openshift.png | Bin 0 -> 9309 bytes 5 files changed, 47 insertions(+) create mode 100644 doc/testbenches_doc_resources/5g-nrue-bench.pdf create mode 100644 doc/testbenches_doc_resources/5g-nrue-bench.png create mode 100644 doc/testbenches_doc_resources/5g-nrue-bench.tex create mode 100644 doc/testbenches_doc_resources/openshift.png diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 300d9cd56a..1641e0160a 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -61,6 +61,14 @@ Note: The available resources, and their current usage, is indicated here: [PDF version](testbenches_doc_resources/5g-aw2s-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/5g-aw2s-bench.tex) if you want to modify to reflect your setup +### 5G UE OTA Testbench + +**Purpose**: Over-the-air 5G tests with OAI UE + +![OAI UE Testbench](testbenches_doc_resources/5g-nrue-bench.png) + +[PDF version](testbenches_doc_resources/5g-nrue-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/5g-nrue-bench.tex) if you want to modify to reflect your setup + ### 4G Testbench(es) **Purpose**: 4G/LTE testbenches @@ -121,6 +129,9 @@ Webhook - [RAN-SA-B200-Module-SABOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-SA-B200-Module-SABOX-Container/) - ofqot + B200, idefix + Quectel, nepes w/ sabox - basic SA test (20 MHz TDD), F1, reestablishment, ... +- [RAN-SA-OAIUE-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-OAIUE-CN5G/) + - 5G-NR SA test setup: gNB on avra(RHEL9.2) + N310, OAIUE on caracal(RHEL9.1) + N310, OAI CN5G + - OpenShift cluster for CN deployment and container images for gNB and UE deployment - [RAN-Ubuntu18-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/) - obelix: Ubuntu 20 image build using docker (Note: builds U20 images while pipeline is named U18!) diff --git a/doc/testbenches_doc_resources/5g-nrue-bench.pdf b/doc/testbenches_doc_resources/5g-nrue-bench.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7e461807c11ac0a0235f690318ab8234d2ab398a GIT binary patch literal 138821 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 w z0I<(_>~W4rw86u3^5jYWT&^HA%r7XAjJ*@0dD-!t5aII+7XkwZ-acijn@;h{35ke^c=_d* z-+ue;OP4N{l$4+-C*YuXWD?O~2(S~XMuNW>9p&wsoBsa2yAR&Kd&ki!uE^^$b>w7c@7S?DOceUg+xt5@I!QXgpi8f&^V}wbR<$*NbSK2{|!v_?v+^uF0}as5MF7#bOVz zG1F(dILbCbv7g^M1WHDl$96`MUh zmo8oM+%r#Z+^`XDvwrP50Dt(0TRaie!zJLq_m(Z;p`mZ=*_C$gRL-sIw{tR;3fbt0 zv%{dfos&^fmUH6Wy&T_l*;zM%fy0IZz|df5Q?<63j2*BR{Oa>hKmOnGpgu%i9asw*#0>?va~tYv%8Ls+4XsYQWoWQpuW7BRs)UW31;e|k zv%_pM0steorlrT&*#RKmgqm#!vNLbCG&hSI>fx7G*Hpu2mN-=51x47-4@QH|c^rRE zfM1Y5hZn>N4hrN1z&9gfWA+_9aPjh`!s6oEh6aFfLIALCG&YKI&xUbO1J!|rvedAE zuhpUSQ5>t&LtLb0bfus44wE1V;C|>{5CeSwy?d}N`ryHb4+zPB@4b7t6&E%3qH(u2 zKzkb+fCW?^r>FtRx8tFQHpj4SV5HaPM5<1=)r3_YZCh81y1l7I#|&D+l~by0TFv&u z0I<{8PS;Oe*v?F>F0QP7ea}9Ah%h89JUlvv&~?hbjw+{Hsg#&)K-W`Zlahb-$j?@; zSuKo+oHS|D+D#q_+qR?LQdk1EZ(qJ@HSp~~K?qW5)~^eViCwX3Wn_GOEFI4divno+|9_~XE_5#Zy=)I5=B?lbdYjX>i$A|j#^64$I-=Z3I7h-fl?Jl-?E{N=o- z=L7gpcALC-$qU|r0h6apcK7rQi-|^HjzySY5dwC&!VL~4I?SO%htkv2D=RCBeO<5D z!>h?o5@3LxJum5R=rDh0+4O$^U1tv1;;2*_0A_$(K+}%)c4=cHY@f3-Z{EC-4jX6q zbYSZO)3`K99E^YiO%f>(b@==m+YRk{JpenLT2*UrPxr4r`vg!!*V>$Z;rQXV-z+K2 ziwF%34GBq#ixM}8`}+DBpF0uTu{blpi1`Cd<0>Aj2frK$b6tI1QBmQ=i)m-hp1ySX z;*DFkDyphvaye`{%-v?-i*O0pi`(VL%`PW904yhXML3;SDxSJ4qOqCdT%m+`L?p z8$k5@fqrvF+VPL>-x(dY=HI%klGi${W*_$z#}2=J=|WmVZB>xJA3!&O=*55K zblpkBuvL?$`>f*x1>r(`d#< zogaUAPu(nbI_)1m_~4swegjm$w7dj9HHHd{1>oO= z>%5948R_k{;-jfa78e)86Yv5#fdN4Qc*>PuATQ9L#~#HVJa0C0Oa2L@85rLpJb9CG5`Jtun=H><`}$%`*1>jAF}1!$N(%W4pKvjI?gex zW0FIFcPM7c5;01m45T+s$p#W`F-czQEnX12>{3hDFB!?5|w2Zq}Sx z{LrwdgoKFLShxiIpE7NVcVHm!_E~f0_;R^`?Q`eP=fK+GHhICKg#kR?Q}gBp@_2%X za6xz&t;2|dLqgz@#>dC+-o5+e$&)1bOQ}?{CuIMEjEhT2O3b`*0~QPT;E?REL7G&Pd@yDV z6M%9}U0q2q>Jk9^KQf zmJZl@jvYRfot0HwSO{eGm2F$SHg7?|?%}yk#K(b^Pew!VX>dD&z@a7PaS#V z=)u=6UpV#B(#0_mLPc}4wZHGvkM4i4Oj68*0}oOh&_}pMLVuhYw0hi{Vib z-5b!cqOt;BeFEtu9E@4c;QOsDayWA`E?1T0s9PFM?dskx{oRrNdt-yvo{oF(jppa( zAazu$>1;RPT;(q0g6y@}as8H*Q0Wo4v?0@CfoHh6xw%Q+Bv;6ltt}F%xVpL$2*$}% zC*FMXwS>f2zJMFV2?#>i9)#dMn8QKl%;1b$H%S>~WO#&7_c2Vr;Xm^IQ5xhiw;v;a z5&UJu{11@c*=aQ3c5F2|=y+H&V7`&4I=yJP3F;Fg;cuiP16P^RIs)+W0dBU%k`5yO zsQQmc3rg2P$(cAU838_;hcY}cG}hDSsH&Af;`3^!O1 z5*i*J6%`d5hm&Ej4uiP*R>ar|)TeBXPDq?FbLNV*Yk~x#Ns}jS+_VY4j~wZVN%5(v zK&=D#0z{{A0)Qww=9kYuD~ybcPD+YNP62G^g~E#Ph^L>QhZl@y9*$FafyuAkxRK0DU9$Y8S&z;E-ah{qKcDx^{J`Mg$y3}G zEqMV}6CS|0NQ5eW$ZNrFI3)@p=}Te+_6a)7zu1)Y zKTlnM_%Ir~T2=67ZtpU6F(K`!1r?Jj(uHcJBOvW`h+|x~lx#EGBpg@5G(V?`MxFgVCX+$s zuv#Sb)j8SOVzIaz>)5A`y-Tnic=*qsn6rAt3IO(v>o>f(bgBDB_f77b$UzXE%jM$h zo^S%&hZFwo+SP0DPd(PIS+nr@=YhAwEuWq@Z{AZ+`1$ypK5;ZRBkkBbdyX91$M^S4 zJ9a?Vsu&w_{^sj1zx@28&p!SD;QhnL{NlAK#Ebnf=`qKwvcZd2-?W+3fl9IyPu)}JErQg`m zWinE;uKN2(qB8Mh(mEWnV(Rp|g8aO~+qtl+mY0>tWs+8$_eH5rw?++N;d!GmJXTN9YF(FpjVnXB{91%?SA!h47;^ z$Wz+;-Me>3k(UPcCJqaF8+5@s4kTZ#B0|2NSPn>dW)H!9%=1yk2AL6w-@s%CarZss zvIcsOjhS~5?Z>^hco>$mMWrjRs)LhmO%mfFr(zVwUhVQdQlpe`dQ5&vMe??n`9dKY zS{)S=9Uq@ar>~>*UCi6#lT#8>Qqc^H$Vi;}<@Unz7em4#<~;f+PZ)yK^{uIJ8I_ng zWs2LXwd(?c1(POC^7Qfs+>Qj|9UmXJbt};L0D-`d%X4#^?7n3SQ0|vjuLin~TToH6 z(ne3uY15|(!ovaBpMCCG92XFc$0Wr9w!0yFq~L{ROQ+A69uOQn_nD`knm>;lBAhvA z_J%E6P;zfX1Ts2`MDVwSgoW|=!O_vtJ9g|ic<|um%a?&lF%73|2m8Z14BHO_!2Z|D zrvKaMI&*Y)_o&rcAnC9rXJP^H6&p4G+D^p^b-nK8*dnmhLX&(fzNaojGAP8hW}q`+CgvRpsb+;qWo!V;>kK6-fe& z%BfPd!fsq+`k-^{vISyicMRv6k1R-EOC4S~qUhwRxnCB@Q1wfUov zUOHYLpuW4?4DUU2cXv)sHj$u9%Szy5P7C{v?3`?@3ifvz^k!2h;F}Rvopw~;hldA@ zvG8`Dua7ri`-&G|od5XjB?}h-Z-42<7oUD?`io1J0BEmTvFh2mj{#{1#D>dND^|ca z;Uv5r%Qzn7^zuUf8cKxUyk*_mwZ1++B}I9+v#wq~f8vc@JL)U)V3Fz2E1M-XJtpm! zzxt%N$2dIf5Z6~;xp=O;ybLI7ZeEV5%R~yn0B#N92EZ`lha_?bA@J}KQ#LiWt7K|< zU0&K-Iq&$l-AekxS@Zp;mhV35{rzu0|Kjrxube-zf8QHv=g$@u7XdcILJ5q$569*c z-cBOg$R-Wm1h5IJsVtLA>m?1VH$OxGN25&W7(=p(qU9WG$Xb;S&s~e>yn{nB;&w}kojIaZLDz@c}0oubx z34U*RWp!C)4aRm?{j{Q*K3&wEDx0QV%|PlpZc0K3oSd9Yf*eyR(vA=wEA4T~Dbr`p zT)%lU!0DvPKU=+iebV+F!J%Qmx8at6y1}8LJQ4Chu2{WV5FRoA>G=S#0QhhMZsW

~FwDb9KadCV0?0NUycW>RgRa;xD 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

E#X8$mq^I8 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 8OGa(wI=z}AUq2GijR+ngBbZ?`0E6o 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 Y^&tfKP$pLrCL;xd(^0IGS2gJV4OV+H$^ZZW literal 0 HcmV?d00001 diff --git a/doc/testbenches_doc_resources/5g-nrue-bench.png b/doc/testbenches_doc_resources/5g-nrue-bench.png new file mode 100644 index 0000000000000000000000000000000000000000..c167591592ad4219ad349bb7ef111d4745ee1412 GIT binary patch literal 24001 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 ^z)b4-7dIG~9~JSo>=zJhes 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 Date: Fri, 9 Jun 2023 14:53:51 +0200 Subject: [PATCH 20/87] Configuration files for nrUE created --- .../5g_sa_n310_nrue/docker-compose.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml diff --git a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml new file mode 100644 index 0000000000..2a12e4cd51 --- /dev/null +++ b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.8' +services: + oai-nr-ue: + image: oai-nr-ue:latest + privileged: true + network_mode: host + container_name: oai-nr-ue + #entrypoint: /bin/bash -c "sleep infinity" + environment: + TZ: Europe/Paris + USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.20.2 -r 106 --numerology 1 --band 78 -C 3511200000 --sa --ue-fo-compensation --nokrnmod 1 --ue-txgain 0 --ue-rxgain 65 --tune-offset 20000000 --log_config.global_log_options level,nocolor,time --uicc0.imsi 208970000000111 --uicc0.nssai_sd 16777215 + volumes: + - ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 From 1f181a5956be64c84d1da8937dc38c72b3c3a041 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 9 Jun 2023 15:19:24 +0200 Subject: [PATCH 21/87] Configuration files for gNB created --- .../gnb.sa.band78.106prb.n310.7ds2u.conf | 270 ++++++++++++++++++ .../5g_sa_n310_gnb/docker-compose.yml | 17 ++ 2 files changed, 287 insertions(+) create mode 100644 ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf create mode 100644 ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf new file mode 100644 index 0000000000..cffa15e110 --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -0,0 +1,270 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ({sst = 1;}); }); + + nr_cellid = 12345678L + + ////////// Physical parameters: + + min_rxtxtime = 5; + do_SRS = 0; + force_256qam_off = 1; + pdsch_AntennaPorts_N1 = 1; + pdsch_AntennaPorts_XP = 1; + pusch_AntennaPorts = 1; + + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + dl_frequencyBand = 78; + absoluteFrequencySSB = 634080; + dl_absoluteFrequencyPointA = 632808; + #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=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; +# 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 = 12; + 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 = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#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 = -70; +# 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=spar e1 + 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 = "172.21.6.100"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "eno33np0"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.124/22"; + GNB_INTERFACE_NAME_FOR_NGU = "eno33np0"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.124/22"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 180; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; + ul_max_mcs = 16; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + #pucch0_dtx_threshold = 150; +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + sf_extension = 0 + sdr_addrs = "addr=192.168.80.52,clock_source=internal,time_source=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"; +} +); + +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 ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + f1ap_log_level ="debug"; + gtpu_log_level ="info"; +}; + diff --git a/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml new file mode 100644 index 0000000000..30cef6b62b --- /dev/null +++ b/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.8' +services: + oai-gnb: + image: oai-gnb:latest + privileged: true + network_mode: "host" + container_name: oai-gnb + environment: + TZ: Europe/Paris + USE_ADDITIONAL_OPTIONS: --sa --tune-offset 20000000 --log_config.global_log_options level,nocolor,time + volumes: + - ../../conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 From a648b9ed26e0b9cb2ea93bc8e4c170ae67f6282f Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 11:12:23 +0200 Subject: [PATCH 22/87] Add caracal OAIUE to UE infra --- ci-scripts/ci_ueinfra.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index 8a6c76645a..6bfcc86af2 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -126,3 +126,11 @@ oai_ue_obelix: Host: obelix UENetworkScript: ip a show dev oaitun_ue1 IF: oaitun_ue1 + +oai_ue_caracal: + Host: caracal + AttachScript: 'docker start oai-nr-ue' + DetachScript: 'docker stop oai-nr-ue' + UENetworkScript: ip a show dev oaitun_ue1 + IF: oaitun_ue1 + MTU: 1500 From cc71018ef7215af08f9414bbe602f905e638b2f1 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 11:32:22 +0200 Subject: [PATCH 23/87] Define server where to pull OC images - if the server is not specified in the xml file, eNBIPAddress is taken --- ci-scripts/cls_cluster.py | 8 +++++--- ci-scripts/main.py | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 56c60f7551..24b0c8902e 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -82,6 +82,7 @@ class Cluster: self.ranTargetBranch = "" self.cmd = None self.imageToPull = '' + self.testSvrId = None def _recreate_entitlements(self): # recreating entitlements, don't care if deletion fails @@ -195,12 +196,13 @@ class Cluster: self.cmd.run(f'oc delete -f {filename}') def PullClusterImage(self, HTML, RAN): + if self.testSvrId == None: self.testSvrId = self.eNBIPAddress if self.imageToPull == '': HELP.GenericHelp(CONST.Version) - HELP.EPCSrvHelp(self.imageToPull) - sys.exit('Insufficient eNB Parameters') + sys.exit('Insufficient Parameter') + logging.debug(f'Pull OC image {self.imageToPull} to server {self.testSvrId}') self.testCase_id = HTML.testCase_id - cmd = cls_cmd.getConnection(self.eNBIPAddress) + cmd = cls_cmd.getConnection(self.testSvrId) succeeded = OC_login(cmd, self.OCUserName, self.OCPassword, CI_OC_RAN_NAMESPACE) if not succeeded: logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 97bc6fbef1..4fdde98774 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -431,10 +431,12 @@ def GetParametersFromXML(action): RAN.command = test.findtext('command') RAN.command_fail = test.findtext('command_fail') in ['True', 'true', 'Yes', 'yes'] elif action == 'Pull_Cluster_Image': - # CLUSTER.imageToPull.clear() string_field = test.findtext('images_to_pull') if (string_field is not None): CLUSTER.imageToPull = string_field.split() + string_field = test.findtext('test_svr_id') + if (string_field is not None): + CLUSTER.testSvrId = string_field else: logging.warning(f"unknown action {action} from option-parsing point-of-view") From 8ec1e639c0c072707e7f3884ed67adbbadf9eaff Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 11:45:44 +0200 Subject: [PATCH 24/87] Bind interface IP address in iperf3 test --- ci-scripts/cls_oaicitest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index ed04b34aef..14c3f2ac5a 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -1062,7 +1062,7 @@ class OaiCiTest(): cmd = cls_cmd.getConnection(ue.getHost()) cmd.run(f'rm /tmp/{server_filename}', reportNonZero=False) port = f'{5002+idx}' - cmd.run(f'{ue.getCmdPrefix()} iperf3 -c {cn_target_ip} -p {port} {iperf_opt} --get-server-output &> /tmp/{server_filename}', timeout=iperf_time*1.5) + cmd.run(f'{ue.getCmdPrefix()} iperf3 -B {ue.getIP()} -c {cn_target_ip} -p {port} {iperf_opt} --get-server-output &> /tmp/{server_filename}', timeout=iperf_time*1.5) cmd.copyin(f'/tmp/{server_filename}', server_filename) cmd.close() if udpIperf: From 0f3ff028ac78ddd72c33adbb8acd24e93d2b7cad Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 11:55:52 +0200 Subject: [PATCH 25/87] Modifications in cls_containerize to support deployment of oai-nr-ue - add oai-nr-ue to image list - add oai-nr-ue sync message to check - skip oai-nr-ue log analysis in undeployemnt stage - add UE log analysis --- ci-scripts/cls_containerize.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 520876ad06..f26fdc01cb 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -52,7 +52,7 @@ import cls_cmd import sshconnection as SSH import helpreadme as HELP import constants as CONST - +import cls_oaicitest #----------------------------------------------------------- # Helper functions used here and in other classes # (e.g., cls_cluster.py) @@ -838,7 +838,7 @@ class Containerize(): mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) mySSH.command('cp docker-compose.y*ml ci-docker-compose.yml', '\$', 5) - imagesList = ['oai-enb', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s'] + imagesList = ['oai-enb', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue'] for image in imagesList: imageTag = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge) mySSH.command(f'sed -i -e "s#image: {image}:latest#image: oai-ci/{imageTag}#" ci-docker-compose.yml', '\$', 2) @@ -877,6 +877,7 @@ class Containerize(): else: time.sleep(10) cnt += 1 + mySSH.command('docker inspect --format="ImageUsed: {{.Config.Image}}" ' + containerName, '\$', 5) for stdoutLine in mySSH.getBefore().split('\n'): if stdoutLine.count('ImageUsed: oai-ci'): @@ -903,7 +904,7 @@ class Containerize(): cnt = 0 while (cnt < 20): mySSH.command('docker logs ' + containerName + ' | egrep --text --color=never -i "wait|sync|Starting"', '\$', 30) - result = re.search('got sync|Starting F1AP at CU', mySSH.getBefore()) + result = re.search('got sync|Starting F1AP at CU|Got sync', mySSH.getBefore()) if result is None: time.sleep(6) cnt += 1 @@ -993,7 +994,6 @@ class Containerize(): mySSH.command('docker volume prune --force', '\$', 20) mySSH.close() - # Analyzing log file! files = ','.join([f'{s}-{HTML.testCase_id}' for s in services]) if len(services) > 1: @@ -1005,6 +1005,15 @@ class Containerize(): HTML.htmleNBFailureMsg='Could not copy logfile to analyze it!' HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.exitStatus = 1 + elif 'oai-nr-ue' in services: + self.exitStatus == 0 + logging.debug('\u001B[1m Analyzing UE logfile ' + filename + ' \u001B[0m') + logStatus = cls_oaicitest.OaiCiTest().AnalyzeLogFile_UE(f'{filename}', HTML, RAN) + if (logStatus < 0): + fullStatus = False + HTML.CreateHtmlTestRow('UE log Analysis', 'KO', logStatus) + else: + HTML.CreateHtmlTestRow('UE log Analysis', 'OK', CONST.ALL_PROCESSES_OK) else: for svcName in services: filename = f'{svcName}-{HTML.testCase_id}.log' From 5cd74ddf72dfe6b2a30252565dd3665829052dc1 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 12:03:46 +0200 Subject: [PATCH 26/87] Add xml files for OAIUE test and cleanup --- .../xml_files/container_sa_n310_nrue.xml | 146 ++++++++++++++++++ .../container_sa_n310_nrue_cleanup.xml | 46 ++++++ 2 files changed, 192 insertions(+) create mode 100644 ci-scripts/xml_files/container_sa_n310_nrue.xml create mode 100644 ci-scripts/xml_files/container_sa_n310_nrue_cleanup.xml diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml new file mode 100644 index 0000000000..309b2860f7 --- /dev/null +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -0,0 +1,146 @@ + + + TEST-5G-NRUE + 40 MHz TDD SA + tasks + 1 + + 010000 010001 + 020000 020001 + 000001 + 001000 + 002000 + 000100 + 000200 + 040001 040000 + + + + + Pull_Cluster_Image + Pull Images from Cluster + oai-gnb + avra + + + + Pull_Cluster_Image + Pull Images from Cluster + oai-nr-ue + caracal + + + + Custom_Command + Reboot USRP N310 + avra + ssh root@192.168.80.52 reboot ; sleep 45 + + + + Custom_Command + Reboot USRP N310 + caracal + ssh root@192.168.20.2 reboot ; sleep 45 + + + + Deploy_Object + Deploy gNB (TDD/Band78/40MHz/N310) in a container + ci-scripts/yaml_files/5g_sa_n310_gnb + 0 + 0 + + + + Deploy_Object + Deploy nrUE (TDD/Band78/40MHz/N310) in a container + ci-scripts/yaml_files/5g_sa_n310_nrue + 1 + 1 + + + + Attach_UE + Attach OAIUE + oai_ue_caracal + + + + Iperf + iperf (DL/20Mbps/UDP)(30 sec)(single-ue profile) + -u -b 20M -t 30 -i 1 -R + IPERF3 + oai_ue_caracal + 25 + 80 + + + + Iperf + iperf (UL/5Mbps/UDP)(30 sec)(single-ue profile) + -u -b 5M -t 30 -i 1 + IPERF3 + oai_ue_caracal + 25 + 80 + + + + Ping + Ping: 20pings in 20sec + oai_ue_caracal + -c 20 + 1 + 25 + + + + Ping + Ping: 100pings in 20sec + oai_ue_caracal + -c 100 -i 0.2 + 1 + 30 + + + + Undeploy_Object + Undeploy gNB + ci-scripts/yaml_files/5g_sa_n310_gnb + 0 + 0 + 20,100,100,100 + 20,100,100,100 + + + + Undeploy_Object + Undeploy nr UE + ci-scripts/yaml_files/5g_sa_n310_nrue + 1 + 1 + + + diff --git a/ci-scripts/xml_files/container_sa_n310_nrue_cleanup.xml b/ci-scripts/xml_files/container_sa_n310_nrue_cleanup.xml new file mode 100644 index 0000000000..0bac1e010b --- /dev/null +++ b/ci-scripts/xml_files/container_sa_n310_nrue_cleanup.xml @@ -0,0 +1,46 @@ + + + test-aw2s-cleanup + CleanUp of test servers + trash + + 111111 + 222222 + + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 0 + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 1 + + + + From fb7343284262575e358cd0d3727ef9b004bf9d50 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 15 Jun 2023 20:02:42 +0200 Subject: [PATCH 27/87] Jenkinsfile for oaiue pipeline created --- ci-scripts/Jenkinsfile-nrue | 242 ++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 ci-scripts/Jenkinsfile-nrue diff --git a/ci-scripts/Jenkinsfile-nrue b/ci-scripts/Jenkinsfile-nrue new file mode 100644 index 0000000000..ab5fe0747d --- /dev/null +++ b/ci-scripts/Jenkinsfile-nrue @@ -0,0 +1,242 @@ +#!/bin/groovy +/* + * 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 + */ + +// Location of the executor node +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the resource +def lockResources = [] +if (params.LockResources != null && params.LockResources.trim().length() > 0) + params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]} + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess = false +def eNB_TargetBranch + +// Flags +def scmEvent = false +def upstreamEvent = false + +//------------------------------------------------------------------------------- +// Pipeline start +pipeline { + agent { + label pythonExecutor + } + options { + timestamps() + ansiColor('xterm') + lock(extra: lockResources) + } + + stages { + stage ('Verify Parameters') { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + + JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"' + JOB_TIMESTAMP = JOB_TIMESTAMP.trim() + + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + if (params.LockResources == null) { + echo "no LockResources given" + allParametersPresent = false + } + if (params.eNB_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB_Credentials == null) { + allParametersPresent = false + } + if (params.eNB1_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB1_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB1_Credentials == null) { + allParametersPresent = false + } + // the following 4 parameters should be pushed by the master trigger + // if not present, take the job GIT variables (used for developing) + if (params.eNB_Repository == null) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_mergeRequest != null) { + eNB_AllowMergeRequestProcess = params.eNB_mergeRequest + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + if (params.OC_Credentials == null) { + allParametersPresent = false + } + if (params.OC_ProjectName == null) { + allParametersPresent = false + } + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + + stage ("Deploy and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + } + } + } + } + } + stage ("Log Collection") { + steps { + script { + dir ('ci-scripts') { + // Zipping all archived log files + sh "mkdir test_logs" + sh "mv *.log* test_logs || true" + sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/" + sh "rm -rf *test_log*/" + if (fileExists("test_logs_${env.BUILD_ID}.zip")) { + archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip" + } + if (fileExists("test_logs_CN.zip")){ + sh "mv test_logs_CN.zip test_logs_CN_${env.BUILD_ID}.zip" + archiveArtifacts artifacts: "test_logs_CN_${env.BUILD_ID}.zip" + } + if (fileExists("test_results.html")) { + sh "mv test_results.html test_results-${env.JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html" + } + } + } + } + } + } +} From 99e0291dbdf32141ce542680c9ae0510559c06d9 Mon Sep 17 00:00:00 2001 From: mir Date: Tue, 4 Jul 2023 22:33:05 +0200 Subject: [PATCH 28/87] Fix bug --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index d92c0124f1..cb53e682b6 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -934,7 +934,10 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1); - totalDecode += nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); + int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); + if(tasks_added > 0) + totalDecode += tasks_added; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); } } From cd3ecd61f48dc990f1046d721924c03e73855243 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 5 Jul 2023 06:55:22 +0000 Subject: [PATCH 29/87] Clang format --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index cb53e682b6..b97bf1748e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -935,7 +935,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1); int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); - if(tasks_added > 0) + if (tasks_added > 0) totalDecode += tasks_added; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); From 7a2790ba68e8577c6ba3962217e8ed576e82be25 Mon Sep 17 00:00:00 2001 From: Angelo Athanassopoulos Date: Wed, 5 Jul 2023 23:28:45 +0200 Subject: [PATCH 30/87] NR SDAP - Bugfix for entity deletion This commit fixes the implementation for removing either a single SDAP entity or all the SDAP entities of a UE. --- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 85 ++++++++++++++++++-------- openair2/SDAP/nr_sdap/nr_sdap_entity.h | 20 +++++- 2 files changed, 77 insertions(+), 28 deletions(-) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index bc3ea0ad9d..25254e0905 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -468,41 +468,74 @@ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id) return NULL; } -int nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) +bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) { nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; - int pos = 0; - while (entityPtr != NULL) { - if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { - if (pos == 0) { - sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; - } - LOG_I(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); - free(entityPtr); - return 1; - } - entityPtr = entityPtr->next_entity; - pos++; + nr_sdap_entity_t *entityPrev = NULL; + bool ret = false; + int upperBound = 0; + + if (entityPtr == NULL && (pdusession_id) * (pdusession_id - NGAP_MAX_PDU_SESSION) > 0) { + LOG_W(SDAP, "SDAP entities not established or Invalid range of pdusession_id [0, 256].\n"); + return ret; } - return 0; + LOG_D(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); + + if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { + sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; + free(entityPtr); + LOG_D(SDAP, "Successfully deleted Entity.\n"); + ret = true; + } else { + while ((entityPtr->ue_id != ue_id || entityPtr->pdusession_id != pdusession_id) && entityPtr->next_entity != NULL + && upperBound < SDAP_MAX_NUM_OF_ENTITIES) { + entityPrev = entityPtr; + entityPtr = entityPtr->next_entity; + upperBound++; + } + + if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { + entityPrev->next_entity = entityPtr->next_entity; + free(entityPtr); + LOG_D(SDAP, "Successfully deleted Entity.\n"); + ret = true; + } + } + LOG_W(SDAP, "Entity does not exist or it was not found.\n"); + return ret; } -void nr_sdap_delete_ue_entities(ue_id_t ue_id) +bool nr_sdap_delete_ue_entities(ue_id_t ue_id) { nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; - int pos = 0; - while (entityPtr != NULL) { - if (entityPtr->ue_id == ue_id) { - if (pos == 0) { - sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; - } - LOG_I(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); - nr_sdap_entity_t *entityPrev = entityPtr; + nr_sdap_entity_t *entityPrev = NULL; + int upperBound = 0; + bool ret = false; + + if (entityPtr == NULL && (ue_id) * (ue_id - SDAP_MAX_UE_ID) > 0) { + LOG_W(SDAP, "SDAP entities not established or Invalid range of ue_id [0, 65536]\n"); + return ret; + } + + /* Handle scenario where ue_id matches the head of the list */ + while (entityPtr != NULL && entityPtr->ue_id == ue_id && upperBound < NGAP_MAX_DRBS_PER_UE) { + sdap_info.sdap_entity_llist = entityPtr->next_entity; + free(entityPtr); + entityPtr = sdap_info.sdap_entity_llist; + ret = true; + } + + while (entityPtr != NULL && upperBound < SDAP_MAX_NUM_OF_ENTITIES) { + if (entityPtr->ue_id != ue_id) { + entityPrev = entityPtr; + entityPtr = entityPtr->next_entity; + } else { + entityPrev->next_entity = entityPtr->next_entity; free(entityPtr); entityPtr = entityPrev->next_entity; - } else { - entityPtr = entityPtr->next_entity; + LOG_D(SDAP, "Successfully deleted Entity.\n"); + ret = true; } - pos++; } + return ret; } diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index 4b5303a5b6..b90da9d380 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -44,6 +44,8 @@ #define SDAP_CTRL_PDU_MAP_DEF_DRB (0) #define SDAP_CTRL_PDU_MAP_RULE_DRB (1) #define SDAP_MAX_PDU (9000) +#define SDAP_MAX_NUM_OF_ENTITIES (NGAP_MAX_DRBS_PER_UE * MAX_MOBILES_PER_ENB) +#define SDAP_MAX_UE_ID (65536) /* * The values of QoS Flow ID (QFI) and Reflective QoS Indication, @@ -167,7 +169,21 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap /* Entity Handling Related Functions */ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id); -/* Entity Handling Related Functions */ -void delete_nr_sdap_entity(ue_id_t ue_id); +/** + * @brief Function to delete a single SDAP Entity based on the ue_id and pdusession_id. + * @note 1. SDAP entities may have the same ue_id. + * @note 2. SDAP entities may have the same pdusession_id, but not with the same ue_id. + * @note 3. The combination of ue_id and pdusession_id, is unique for each SDAP entity. + * @param[in] ue_id Unique identifier for the User Equipment. ID Range [0, 65536]. + * @param[in] pdusession_id Unique identifier for the Packet Data Unit Session. ID Range [0, 256]. + * @return True, if successfully deleted entity, false otherwise. + */ +bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id); +/** + * @brief Function to delete all SDAP Entities based on the ue_id. + * @param[in] ue_id Unique identifier for the User Equipment. ID Range [0, 65536]. + * @return True, it deleted at least one entity, false otherwise. + */ +bool nr_sdap_delete_ue_entities(ue_id_t ue_id); #endif From 26be073ff9ed0a8a910b879b7e7e8c60edce69ed Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 6 Jul 2023 10:22:15 +0200 Subject: [PATCH 31/87] CI: AW2S pipeline - disable retransmissions check --- ci-scripts/xml_files/container_sa_aw2s_asue.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 7959718eb0..d736dd69f0 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -161,8 +161,6 @@ ci-scripts/yaml_files/sa_aw2s_gnb 0 0 - 20,100,100,100 - 20,100,100,100 From 3256606285c525e4611ea6f82c61f5d04e5ae398 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 16 Jun 2023 21:04:41 +0200 Subject: [PATCH 32/87] Remove unused includes - openair2/ENB_APP/CONTROL_MODULES: this directory does not exist anymore - openair2/UTIL/{OMG,CLI,OMV}: not used anywhere --- CMakeLists.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 214a16b79a..89dc638787 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -753,22 +753,14 @@ include_directories("${OPENAIR3_DIR}/ocp-gtpu") include_directories("${OPENAIR3_DIR}/M3AP") include_directories("${OPENAIR3_DIR}/MME_APP") include_directories("${OPENAIR_DIR}/radio/COMMON") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP") -include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/S1AP") include_directories("${OPENAIR2_DIR}/UTIL/OSA") include_directories("${OPENAIR2_DIR}/UTIL/MEM") include_directories("${OPENAIR2_DIR}/UTIL/LISTS") include_directories("${OPENAIR2_DIR}/UTIL/FIFO") include_directories("${OPENAIR2_DIR}/UTIL/MATH") include_directories("${OPENAIR2_DIR}/UTIL/TIMER") -include_directories("${OPENAIR2_DIR}/UTIL/OMG") 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("${OPENAIR_DIR}") ########### From 11f4bd9c32ca3fc7ba56021b7190342ef2709ae1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:06:20 +0200 Subject: [PATCH 33/87] Remove cmake NAS_NETLINK option This option is almost not referenced anywhere, and not documented. Remove it to avoid problems in the future. --- CMakeLists.txt | 1 - openair2/COMMON/platform_types.h | 5 ----- 2 files changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89dc638787..37895b1299 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -629,7 +629,6 @@ include_directories ("${OPENAIR_DIR}/radio/COMMON") ############################################################## add_boolean_option(OAI_NW_DRIVER_TYPE_ETHERNET False "????" ON) -add_boolean_option(NAS_NETLINK False "useless ??? Must be True to compile nasmesh driver without rtai ????" ON) add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????" ON) add_boolean_option(UE_EXPANSION False "enable UE_EXPANSION with max 256 UE" ON) diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h index c3d5999b62..6c388c3cd0 100644 --- a/openair2/COMMON/platform_types.h +++ b/openair2/COMMON/platform_types.h @@ -30,13 +30,8 @@ #ifndef __PLATFORM_TYPES_H__ #define __PLATFORM_TYPES_H__ -#if !defined(NAS_NETLINK) #include #include -#else -#include -typedef void * intptr_t; -#endif //----------------------------------------------------------------------------- // GENERIC ACCESS STRATUM TYPES From 7ebdaf35c588625f8eecc4b381a16c4500a4de31 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:06:40 +0200 Subject: [PATCH 34/87] Remove cmake ENB_MODE option ENB_MODE is a cmake option to swap the order of include directories. This has historical reasons; before OAI used cmake, it was very sensitive to the order of includes. Nowadays, the order does not matter. Remove this option, and fix the compilation issues that arise while doing so. --- CMakeLists.txt | 23 +++++----------------- cmake_targets/at_commands/CMakeLists.txt | 1 - common/utils/T/check_vcd.c | 1 - openair2/F1AP/f1ap_common.h | 25 +++++++++--------------- openair2/M2AP/m2ap_MCE_defs.h | 1 + openair2/M2AP/m2ap_common.h | 19 ++++++------------ openair2/M2AP/m2ap_eNB_defs.h | 1 + openair2/X2AP/x2ap_common.h | 17 +++++----------- openair3/M3AP/m3ap_MCE_defs.h | 1 + openair3/M3AP/m3ap_MME_defs.h | 1 + openair3/M3AP/m3ap_common.h | 19 ++++++------------ openair3/NGAP/ngap_common.h | 9 --------- openair3/S1AP/s1ap_common.h | 22 +++++++-------------- openair3/SCTP/sctp_common.h | 14 ++++--------- 14 files changed, 46 insertions(+), 108 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 37895b1299..b2be224013 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -636,11 +636,6 @@ add_boolean_option(PHY_TX_THREAD False "enable UE_EXPANSION w add_boolean_option(PRE_SCD_THREAD False "enable UE_EXPANSION with max 256 UE" ON) add_boolean_option(UESIM_EXPANSION False "enable UESIM_EXPANSION with max 256 UE" ON) -######################## -# Include order -########################## -add_boolean_option(ENB_MODE True "Swap the include directories between openair2 and openair3" ON) - ########################## # SCHEDULING/REAL-TIME/PERF options ########################## @@ -701,19 +696,11 @@ include_directories("${OPENAIR_BIN_DIR}") # Legacy exact order include_directories("${OPENAIR_DIR}/executables") -if(ENB_MODE) - include_directories("${OPENAIR2_DIR}/COMMON") - include_directories("${OPENAIR2_DIR}/UTIL") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") - include_directories("${OPENAIR3_DIR}/COMMON") - include_directories("${OPENAIR3_DIR}/UTILS") -else() - include_directories("${OPENAIR3_DIR}/COMMON") - include_directories("${OPENAIR3_DIR}/UTILS") - include_directories("${OPENAIR2_DIR}/COMMON") - include_directories("${OPENAIR2_DIR}/UTIL") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") -endif() +include_directories("${OPENAIR2_DIR}/COMMON") +include_directories("${OPENAIR2_DIR}/UTIL") +include_directories("${OPENAIR2_DIR}/UTIL/LOG") +include_directories("${OPENAIR3_DIR}/COMMON") +include_directories("${OPENAIR3_DIR}/UTILS") include_directories("${NFAPI_DIR}/nfapi/public_inc") include_directories("${NFAPI_DIR}/common/public_inc") include_directories("${NFAPI_DIR}/pnf/public_inc") diff --git a/cmake_targets/at_commands/CMakeLists.txt b/cmake_targets/at_commands/CMakeLists.txt index 9e16576ba9..cda9163c9b 100755 --- a/cmake_targets/at_commands/CMakeLists.txt +++ b/cmake_targets/at_commands/CMakeLists.txt @@ -103,7 +103,6 @@ set (FIRMWARE_VERSION "No svn information") add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") add_boolean_option(LINUX True "????") -add_boolean_option(ENB_MODE True "????") # to avoid backtrace ########################## # NAS LAYER OPTIONS diff --git a/common/utils/T/check_vcd.c b/common/utils/T/check_vcd.c index 4a21e4d2f5..33ca58f947 100644 --- a/common/utils/T/check_vcd.c +++ b/common/utils/T/check_vcd.c @@ -15,7 +15,6 @@ /* VCD specific defines and includes * If the codebase changes, it may need to be updated */ -#define ENB_MODE #define ENABLE_USE_CPU_EXECUTION_TIME #include "../LOG/vcd_signal_dumper.c" diff --git a/openair2/F1AP/f1ap_common.h b/openair2/F1AP/f1ap_common.h index 2ae6352464..ff492820d7 100644 --- a/openair2/F1AP/f1ap_common.h +++ b/openair2/F1AP/f1ap_common.h @@ -340,6 +340,8 @@ #include "F1AP_Cells-To-Be-Broadcast-Item.h" #include "F1AP_QCI.h" +#include "f1ap_default_values.h" + #include "conversions.h" #include "platform_types.h" #include "common/utils/LOG/log.h" @@ -359,22 +361,13 @@ #include "assertions.h" -#if defined(ENB_MODE) - #include "common/utils/LOG/log.h" - #include "f1ap_default_values.h" - #define F1AP_ERROR(x, args...) LOG_E(F1AP, x, ##args) - #define F1AP_WARN(x, args...) LOG_W(F1AP, x, ##args) - #define F1AP_TRAF(x, args...) LOG_I(F1AP, x, ##args) - #define F1AP_INFO(x, args...) LOG_I(F1AP, x, ##args) - #define F1AP_DEBUG(x, args...) LOG_I(F1AP, x, ##args) -#else - //# include "mme_default_values.h" - #define F1AP_ERROR(x, args...) do { fprintf(stdout, "[F1AP][E]"x, ##args); } while(0) - #define F1AP_WARN(x, args...) do { fprintf(stdout, "[F1AP][W]"x, ##args); } while(0) - #define F1AP_TRAF(x, args...) do { fprintf(stdout, "[F1AP][T]"x, ##args); } while(0) - #define F1AP_INFO(x, args...) do { fprintf(stdout, "[F1AP][I]"x, ##args); } while(0) - #define F1AP_DEBUG(x, args...) do { fprintf(stdout, "[F1AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#include "f1ap_default_values.h" +#define F1AP_ERROR(x, args...) LOG_E(F1AP, x, ##args) +#define F1AP_WARN(x, args...) LOG_W(F1AP, x, ##args) +#define F1AP_TRAF(x, args...) LOG_I(F1AP, x, ##args) +#define F1AP_INFO(x, args...) LOG_I(F1AP, x, ##args) +#define F1AP_DEBUG(x, args...) LOG_I(F1AP, x, ##args) //Forward declaration #define F1AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ diff --git a/openair2/M2AP/m2ap_MCE_defs.h b/openair2/M2AP/m2ap_MCE_defs.h index 73183e89c2..dc8f9ff5ee 100644 --- a/openair2/M2AP/m2ap_MCE_defs.h +++ b/openair2/M2AP/m2ap_MCE_defs.h @@ -33,6 +33,7 @@ #include "sctp_eNB_defs.h" +#include "m2ap_default_values.h" #include "m2ap_ids.h" //looks X2AP specific for HO #include "m2ap_timers.h" diff --git a/openair2/M2AP/m2ap_common.h b/openair2/M2AP/m2ap_common.h index c144c78dcf..7981eaa2a5 100644 --- a/openair2/M2AP/m2ap_common.h +++ b/openair2/M2AP/m2ap_common.h @@ -52,19 +52,12 @@ extern int asn1_xer_print; -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# include "m2ap_default_values.h" -# define M2AP_INFO(x, args...) LOG_I(M2AP, x, ##args) -# define M2AP_ERROR(x, args...) LOG_E(M2AP, x, ##args) -# define M2AP_WARN(x, args...) LOG_W(M2AP, x, ##args) -# define M2AP_DEBUG(x, args...) LOG_D(M2AP, x, ##args) -#else -# define M2AP_INFO(x, args...) do { fprintf(stdout, "[M2AP][I]"x, ##args); } while(0) -# define M2AP_ERROR(x, args...) do { fprintf(stdout, "[M2AP][E]"x, ##args); } while(0) -# define M2AP_WARN(x, args...) do { fprintf(stdout, "[M2AP][W]"x, ##args); } while(0) -# define M2AP_DEBUG(x, args...) do { fprintf(stdout, "[M2AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#include "m2ap_default_values.h" +#define M2AP_INFO(x, args...) LOG_I(M2AP, x, ##args) +#define M2AP_ERROR(x, args...) LOG_E(M2AP, x, ##args) +#define M2AP_WARN(x, args...) LOG_W(M2AP, x, ##args) +#define M2AP_DEBUG(x, args...) LOG_D(M2AP, x, ##args) #define M2AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ do {\ diff --git a/openair2/M2AP/m2ap_eNB_defs.h b/openair2/M2AP/m2ap_eNB_defs.h index 0b30c33d80..4cc409400e 100644 --- a/openair2/M2AP/m2ap_eNB_defs.h +++ b/openair2/M2AP/m2ap_eNB_defs.h @@ -33,6 +33,7 @@ #include "sctp_eNB_defs.h" +#include "m2ap_default_values.h" #include "m2ap_ids.h" //looks X2AP specific for HO #include "m2ap_timers.h" diff --git a/openair2/X2AP/x2ap_common.h b/openair2/X2AP/x2ap_common.h index e35fd30adf..9535e9fb69 100644 --- a/openair2/X2AP/x2ap_common.h +++ b/openair2/X2AP/x2ap_common.h @@ -49,18 +49,11 @@ extern int asn1_xer_print; -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# define X2AP_INFO(x, args...) LOG_I(X2AP, x, ##args) -# define X2AP_ERROR(x, args...) LOG_E(X2AP, x, ##args) -# define X2AP_WARN(x, args...) LOG_W(X2AP, x, ##args) -# define X2AP_DEBUG(x, args...) LOG_D(X2AP, x, ##args) -#else -# define X2AP_INFO(x, args...) do { fprintf(stdout, "[X2AP][I]"x, ##args); } while(0) -# define X2AP_ERROR(x, args...) do { fprintf(stdout, "[X2AP][E]"x, ##args); } while(0) -# define X2AP_WARN(x, args...) do { fprintf(stdout, "[X2AP][W]"x, ##args); } while(0) -# define X2AP_DEBUG(x, args...) do { fprintf(stdout, "[X2AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#define X2AP_INFO(x, args...) LOG_I(X2AP, x, ##args) +#define X2AP_ERROR(x, args...) LOG_E(X2AP, x, ##args) +#define X2AP_WARN(x, args...) LOG_W(X2AP, x, ##args) +#define X2AP_DEBUG(x, args...) LOG_D(X2AP, x, ##args) #define X2AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ do {\ diff --git a/openair3/M3AP/m3ap_MCE_defs.h b/openair3/M3AP/m3ap_MCE_defs.h index 4dcb2b4db0..c90ba38a66 100644 --- a/openair3/M3AP/m3ap_MCE_defs.h +++ b/openair3/M3AP/m3ap_MCE_defs.h @@ -33,6 +33,7 @@ #include "sctp_eNB_defs.h" +#include "m3ap_default_values.h" #include "m3ap_ids.h" //looks X2AP specific for HO #include "m3ap_timers.h" diff --git a/openair3/M3AP/m3ap_MME_defs.h b/openair3/M3AP/m3ap_MME_defs.h index 6608587cc3..7d3186915f 100644 --- a/openair3/M3AP/m3ap_MME_defs.h +++ b/openair3/M3AP/m3ap_MME_defs.h @@ -33,6 +33,7 @@ #include "sctp_eNB_defs.h" +#include "m3ap_default_values.h" #include "m3ap_ids.h" //looks X2AP specific for HO #include "m3ap_timers.h" diff --git a/openair3/M3AP/m3ap_common.h b/openair3/M3AP/m3ap_common.h index cf2189a243..5d40b29363 100644 --- a/openair3/M3AP/m3ap_common.h +++ b/openair3/M3AP/m3ap_common.h @@ -50,19 +50,12 @@ extern int asn1_xer_print; -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# include "m3ap_default_values.h" -# define M3AP_INFO(x, args...) LOG_I(M3AP, x, ##args) -# define M3AP_ERROR(x, args...) LOG_E(M3AP, x, ##args) -# define M3AP_WARN(x, args...) LOG_W(M3AP, x, ##args) -# define M3AP_DEBUG(x, args...) LOG_D(M3AP, x, ##args) -#else -# define M3AP_INFO(x, args...) do { fprintf(stdout, "[M3AP][I]"x, ##args); } while(0) -# define M3AP_ERROR(x, args...) do { fprintf(stdout, "[M3AP][E]"x, ##args); } while(0) -# define M3AP_WARN(x, args...) do { fprintf(stdout, "[M3AP][W]"x, ##args); } while(0) -# define M3AP_DEBUG(x, args...) do { fprintf(stdout, "[M3AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#include "m3ap_default_values.h" +#define M3AP_INFO(x, args...) LOG_I(M3AP, x, ##args) +#define M3AP_ERROR(x, args...) LOG_E(M3AP, x, ##args) +#define M3AP_WARN(x, args...) LOG_W(M3AP, x, ##args) +#define M3AP_DEBUG(x, args...) LOG_D(M3AP, x, ##args) #define M3AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ do {\ diff --git a/openair3/NGAP/ngap_common.h b/openair3/NGAP/ngap_common.h index 8de2542766..41f6093c08 100644 --- a/openair3/NGAP/ngap_common.h +++ b/openair3/NGAP/ngap_common.h @@ -96,7 +96,6 @@ extern int asn_debug; extern int asn1_xer_print; -#if defined(ENB_MODE) # include "common/utils/LOG/log.h" # include "ngap_gNB_default_values.h" # define NGAP_ERROR(x, args...) LOG_E(NGAP, x, ##args) @@ -104,14 +103,6 @@ extern int asn1_xer_print; # define NGAP_TRAF(x, args...) LOG_I(NGAP, x, ##args) # define NGAP_INFO(x, args...) LOG_I(NGAP, x, ##args) # define NGAP_DEBUG(x, args...) LOG_I(NGAP, x, ##args) -#else -# include "amf_default_values.h" -# define NGAP_ERROR(x, args...) do { fprintf(stdout, "[NGAP][E]"x, ##args); } while(0) -# define NGAP_WARN(x, args...) do { fprintf(stdout, "[NGAP][W]"x, ##args); } while(0) -# define NGAP_TRAF(x, args...) do { fprintf(stdout, "[NGAP][T]"x, ##args); } while(0) -# define NGAP_INFO(x, args...) do { fprintf(stdout, "[NGAP][I]"x, ##args); } while(0) -# define NGAP_DEBUG(x, args...) do { fprintf(stdout, "[NGAP][D]"x, ##args); } while(0) -#endif #define NGAP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ do { \ diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h index bdfc9b9f6f..65baea44c6 100644 --- a/openair3/S1AP/s1ap_common.h +++ b/openair3/S1AP/s1ap_common.h @@ -52,21 +52,13 @@ extern int asn1_xer_print; -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# include "s1ap_eNB_default_values.h" -# define S1AP_ERROR(x, args...) LOG_E(S1AP, x, ##args) -# define S1AP_WARN(x, args...) LOG_W(S1AP, x, ##args) -# define S1AP_TRAF(x, args...) LOG_I(S1AP, x, ##args) -# define S1AP_INFO(x, args...) LOG_I(S1AP, x, ##args) -# define S1AP_DEBUG(x, args...) LOG_I(S1AP, x, ##args) -#else -# define S1AP_ERROR(x, args...) do { fprintf(stdout, "[S1AP][E]"x, ##args); } while(0) -# define S1AP_WARN(x, args...) do { fprintf(stdout, "[S1AP][W]"x, ##args); } while(0) -# define S1AP_TRAF(x, args...) do { fprintf(stdout, "[S1AP][T]"x, ##args); } while(0) -# define S1AP_INFO(x, args...) do { fprintf(stdout, "[S1AP][I]"x, ##args); } while(0) -# define S1AP_DEBUG(x, args...) do { fprintf(stdout, "[S1AP][D]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#include "s1ap_eNB_default_values.h" +#define S1AP_ERROR(x, args...) LOG_E(S1AP, x, ##args) +#define S1AP_WARN(x, args...) LOG_W(S1AP, x, ##args) +#define S1AP_TRAF(x, args...) LOG_I(S1AP, x, ##args) +#define S1AP_INFO(x, args...) LOG_I(S1AP, x, ##args) +#define S1AP_DEBUG(x, args...) LOG_I(S1AP, x, ##args) #define S1AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ diff --git a/openair3/SCTP/sctp_common.h b/openair3/SCTP/sctp_common.h index 024feb8b09..3708ae52a0 100644 --- a/openair3/SCTP/sctp_common.h +++ b/openair3/SCTP/sctp_common.h @@ -34,16 +34,10 @@ #include #include -#if defined(ENB_MODE) -# include "common/utils/LOG/log.h" -# define SCTP_ERROR(x, args...) LOG_E(SCTP, x, ##args) -# define SCTP_DEBUG(x, args...) LOG_D(SCTP, x, ##args) -# define SCTP_WARN(x, args...) LOG_W(SCTP, x, ##args) -#else -# define SCTP_ERROR(x, args...) do { fprintf(stderr, "[SCTP][E]"x, ##args); } while(0) -# define SCTP_DEBUG(x, args...) do { fprintf(stdout, "[SCTP][D]"x, ##args); } while(0) -# define SCTP_WARN(x, args...) do { fprintf(stdout, "[SCTP][W]"x, ##args); } while(0) -#endif +#include "common/utils/LOG/log.h" +#define SCTP_ERROR(x, args...) LOG_E(SCTP, x, ##args) +#define SCTP_DEBUG(x, args...) LOG_D(SCTP, x, ##args) +#define SCTP_WARN(x, args...) LOG_W(SCTP, x, ##args) int sctp_set_init_opt(int sd, uint16_t instreams, uint16_t outstreams, uint16_t max_attempts, uint16_t init_timeout); From 5b534c957ffd3731a85c57db5088da8dee740765 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:07:23 +0200 Subject: [PATCH 35/87] Remove unused cmake options and commented code - LINUX: option to optionally set a sighandler for certain simulators, no practical relevance - LINUX_LIST: not used anywhere - DEBUG_DLSCH: referenced in the code, but those files have a separate (commented) line `#define DEBUG_DLSCH`; probably never used - LINK_ENB_PDCP_TO_IP_DRIVER, LINK_ENB_PDCP_TO_GTPV1U: commented in cmake, although they are referenced. It is likely that code behaves unexpected if re-enabled; we therefore remove these options to avoid future problems - Remove some more commented code --- CMakeLists.txt | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2be224013..644360da7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -642,8 +642,6 @@ add_boolean_option(UESIM_EXPANSION False "enable UESIM_EXPANSIO add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME False "Add data in vcd traces: disable it if perf issues" ON) add_boolean_option(ENABLE_VCD False "always true now, time measurements of proc calls and var displays" ON) add_boolean_option(ENABLE_VCD_FIFO False "time measurements of proc calls and var displays sent to FIFO (one more thread)" ON) -add_boolean_option(LINUX False "used in weird memcpy() in pdcp.c ???" ON) -add_boolean_option(LINUX_LIST False "used only in lists.c: either use OAI implementation of lists or Linux one (should be ON, but it is False" ON) ########################## # PHY options @@ -653,7 +651,6 @@ add_integer_option(MAX_NUM_CCs 1 "????" ON) add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator" ON) add_boolean_option(DEBUG_PHY False "Enable PHY layer debugging options" ON) add_boolean_option(DEBUG_PHY_PROC False "Enable debugging of PHY layer procedures" ON) -add_boolean_option(DEBUG_DLSCH False "Enable debugging of DLSCH physical layer channel" ON) add_boolean_option(MEX False "Enabling compilation with mex" ON) ########################## @@ -664,22 +661,10 @@ add_boolean_option(NAS_BUILT_IN_UE True "UE NAS layer present in this e add_boolean_option(NAS_UE True "NAS UE INSTANCE (<> NAS_MME)" ON) -########################## -# PDCP LAYER OPTIONS -########################## -#add_boolean_option(LINK_ENB_PDCP_TO_IP_DRIVER False "For eNB, PDCP communicate with a IP driver") -#add_boolean_option(LINK_ENB_PDCP_TO_GTPV1U True "For eNB, PDCP communicate with GTP-U protocol (eNB<->S-GW)") - ########################## # RRC LAYER OPTIONS ########################## -add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the RLC mode to AM for the default bearer, otherwise it is UM." ON) - - -########################## -# S1AP LAYER OPTIONS -########################## -# none +add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the LTE RLC mode to AM for the default bearer, otherwise it is UM." ON) # add the binary tree to the search path for include files ####################################################### @@ -1340,12 +1325,6 @@ set(NR_PDCP_SRC ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c - #hack: include these files to compile the nr phy simulators - #these files should not be here, will be removed at some point when the - #computation is done directly inside nr_pdcp_integrity_nia1.c instead - #of reusing code of osa_stream_eia.c - #${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c - #${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c ) set(NR_SDAP_SRC From cd6dd99d439a5d748d5bcfe0f990332bcad7618b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 08:32:41 +0200 Subject: [PATCH 36/87] Remove CMakeLists.txt reference to openpgm: it is not used --- CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 644360da7e..5b27b251d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,13 +88,6 @@ elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") endif (${RF_BOARD} STREQUAL "OAI_USRP") -pkg_search_module(OPENPGM openpgm-5.1 openpgm-5.2) -if(NOT ${OPENPGM_FOUND}) - message("PACKAGE openpgm-5.1 is required by binaries such as oaisim: will fail later if this target is built") -else() - include_directories(${OPENPGM_INCLUDE_DIRS}) -endif() - pkg_search_module(XPM xpm) if(NOT ${XPM_FOUND}) message("PACKAGE xpm not found: some targets will fail") From 439b6027cfc734debcd53b5406d8ab44c390903c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 08:32:55 +0200 Subject: [PATCH 37/87] Remove CMakeLists.txt reference to xpm: it is not used --- CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b27b251d2..8c189c5e7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,13 +88,6 @@ elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") endif (${RF_BOARD} STREQUAL "OAI_USRP") -pkg_search_module(XPM xpm) -if(NOT ${XPM_FOUND}) - message("PACKAGE xpm not found: some targets will fail") -else() - include_directories(${XPM_INCLUDE_DIRS}) -endif() - # Atlas is required by some packages, but not found in pkg-config # So, here are some hacks here. Hope this gets fixed in future! if(EXISTS "/usr/include/atlas/cblas.h" OR EXISTS "/usr/include/cblas.h") From 25edebb593e48e3a2352ee30a424114ae3415fbc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 08:52:05 +0200 Subject: [PATCH 38/87] Refactor CMakeLists.txt OpenSSL handling First, we do not include openssl globally using `include_directories()`, as most modules don't need it. Further, it is linked into SECURITY, and removed from all other targets (they don't need it, only SECURITY). Finally, remove a header include in NR PDCP that is not needed --- CMakeLists.txt | 21 +++++++++---------- .../LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c | 1 - 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c189c5e7b..da0e80fff1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,6 @@ include("cmake_targets/macros.cmake") ################################### include(FindPkgConfig) -pkg_search_module(OPENSSL openssl REQUIRED) -include_directories(${OPENSSL_INCLUDE_DIRS}) - pkg_search_module(CONFIG libconfig REQUIRED) include_directories(${CONFIG_INCLUDE_DIRS}) @@ -759,8 +756,10 @@ set(SECURITY_SRC ${OPENAIR3_DIR}/SECU/nas_stream_eia2.c ) +pkg_check_modules(OpenSSL openssl REQUIRED) add_library(SECURITY ${SECURITY_SRC} $) target_include_directories(SECURITY PRIVATE ${OPENAIR_DIR}/common/utils/ds/) +target_link_libraries(SECURITY PRIVATE ${OpenSSL_LIBRARIES}) # Physical Channel Procedures Scheduling ################################" @@ -2117,7 +2116,7 @@ target_link_libraries(lte-softmodem PRIVATE ${NAS_UE_LIB} ITTI SIMU SIMU_ETH -Wl,--end-group z dl) -target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp) +target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) target_link_libraries(lte-softmodem PRIVATE ${T_LIB}) target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2178,7 +2177,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE ${NAS_UE_LIB} ITTI ${ATLAS_LIBRARIES} -Wl,--end-group z dl) -target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${ATLAS_LIBRARIES}) +target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp ${ATLAS_LIBRARIES}) target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2219,7 +2218,7 @@ target_link_libraries(nr-softmodem PRIVATE x2ap f1ap m2ap m3ap e1ap -Wl,--end-group z dl) -target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${ATLAS_LIBRARIES}) +target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp ${ATLAS_LIBRARIES}) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2281,7 +2280,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE ITTI ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH -Wl,--end-group z dl) -target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${ATLAS_LIBRARIES}) target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2420,7 +2419,7 @@ add_executable(nr_dlsim ) target_link_libraries(nr_dlsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2432,7 +2431,7 @@ add_executable(nr_prachsim ${SHLIB_LOADER_SOURCES}) target_link_libraries(nr_prachsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl) + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl) target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_ulschsim @@ -2469,7 +2468,7 @@ endif() target_link_libraries(nr_ulsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2507,7 +2506,7 @@ foreach(myExe s1ap ${OPENAIR3_DIR}/TEST/test_${myExe}.c ) target_link_libraries (test_${myExe} - -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} CONFIG_LIB + -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} CONFIG_LIB ) endforeach(myExe) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c index a005bbbdf6..3dbf15136b 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "openair3/SECU/secu_defs.h" #include "openair3/SECU/key_nas_deriver.h" From 25f2a48265e529d459b68bbbc2d732d56bc61ed3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:15:05 +0200 Subject: [PATCH 39/87] Remove targets/Makerules: it is not used --- targets/Makerules | 59 ----------------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 targets/Makerules diff --git a/targets/Makerules b/targets/Makerules deleted file mode 100644 index 3488c54762..0000000000 --- a/targets/Makerules +++ /dev/null @@ -1,59 +0,0 @@ -CC = gcc -MPICC = gcc #mpicc -RM_F_V = rm -f -v -PWD = $(shell pwd) -export CC -export MPICC -export RM_F_V -export PWD - -OBJS_DIR := $(PWD)/objs - -SVN_REV := $(shell svnversion -n .) -DATE_REV := $(shell date '+%F %T') - -NUM_CORES:=$(shell cat /proc/cpuinfo | grep processor | wc -l) - -OPENSSL_FOUND := $(shell if pkg-config --exists openssl; then echo "1" ; else echo "0"; fi) -ifeq ($(OPENSSL_FOUND), 1) -OPENSSL_LIBS := $(shell pkg-config --libs openssl) -#else -#@echo "package openssl not installed" -endif - -PGM_FOUND := $(shell if pkg-config --exists openpgm-5.1; then echo "1" ; else echo "0"; fi) -ifeq ($(PGM_FOUND), 1) -PGM_CFLAGS := $(shell pkg-config --cflags openpgm-5.1) -PGM_LIBS := $(shell pkg-config --libs openpgm-5.1) -#else -#@echo "package pgm not installed" -endif - -LIBXML2_FOUND := $(shell if pkg-config --exists libxml-2.0; then echo "1" ; else echo "0"; fi) -ifeq ($(LIBXML2_FOUND), 1) -LIBXML2_CFLAGS := $(shell pkg-config --cflags libxml-2.0) -LIBXML2_LIBS := $(shell pkg-config --libs libxml-2.0) -#else -#@echo "package libxml2 not installed" -endif - -XPM_FOUND := $(shell if pkg-config --exists xpm; then echo "1" ; else echo "0"; fi) -ifeq ($(XPM_FOUND), 1) -XPM_LIBS := $(shell pkg-config --libs xpm) -#else -#@echo "package xmp not installed" -endif - -LIBBLAS_FOUND := $(shell if [ -f /usr/include/cblas.h ]; then echo "1"; else echo "0"; fi) -ifeq ($(LIBBLAS_FOUND), 1) -LIBBLAS_LIBS := -lblas -else -$(error "libblas not found, please install it") -endif - -#Export common libs -LIBS = \ - -lm \ - $(LIBBLAS_LIBS) \ - $(LIBXML2_LIBS) \ - $(XPM_LIBS) From be4c03c90cfdf5ca033f27f6659919d2f210bf20 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:13:41 +0200 Subject: [PATCH 40/87] Properly check and link (C)BLAS and LAPACKE dependencies Instead of using the adhoc code for checking and including (globally!) BLAS/LAPACKE, use PkgConfig to correctly identify libs (see deleted comment: "Hope this gets fixed in future!" -- you are welcome). Next, only link into those libraries that need it (PHY_UE, SIMU). Note that only RHEL also needs cblas, so it is a non-REQUIREd dependency that is only linked in if available. Further, take out linking into all other modules, as they don't need it. In the source code, take out preprocessor directives to correctly include headers -- that is cmake's job, which it does just fine now. --- CMakeLists.txt | 85 ++++++------------- .../PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c | 10 +-- .../linear_preprocessing_rec.c | 5 -- 3 files changed, 30 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da0e80fff1..18d46ffdda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,42 +85,6 @@ elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") endif (${RF_BOARD} STREQUAL "OAI_USRP") -# Atlas is required by some packages, but not found in pkg-config -# So, here are some hacks here. Hope this gets fixed in future! -if(EXISTS "/usr/include/atlas/cblas.h" OR EXISTS "/usr/include/cblas.h") - include_directories("/usr/include/atlas") - LINK_DIRECTORIES("/usr/lib/lapack") - LINK_DIRECTORIES("/usr/lib64") - LINK_DIRECTORIES("/usr/lib64/atlas") #Added because atlas libraries in CentOS 7 are here! - - if(EXISTS "/usr/lib64/libblas.so" OR EXISTS "/usr/lib/libblas.so") #Case for CentOS7 - list(APPEND ATLAS_LIBRARIES blas) - - else() # Case for Ubuntu - list(APPEND ATLAS_LIBRARIES cblas) - endif() - - if(EXISTS "/usr/lib/atlas/libtatlas.so" OR EXISTS "/usr/lib64/atlas/libtatlas.so") #Case for CentOS7 - list(APPEND ATLAS_LIBRARIES tatlas) - else() - list(APPEND ATLAS_LIBRARIES atlas) #Case for Ubuntu - endif() - - list(APPEND ATLAS_LIBRARIES lapack) - -# for ubuntu 17.10, directories are different -elseif(EXISTS "/usr/include/x86_64-linux-gnu/cblas.h") - - include_directories("/usr/include/x86_64-linux-gnu") - LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") - list(APPEND ATLAS_LIBRARIES cblas) - list(APPEND ATLAS_LIBRARIES atlas) - list(APPEND ATLAS_LIBRARIES lapack) - -else() - message("No Blas/Atlas libs found, some targets will fail") -endif() - ######################################################### # Base directories, compatible with legacy OAI building # ######################################################### @@ -1228,8 +1192,16 @@ target_link_libraries(PHY_COMMON PRIVATE asn1_lte_rrc_hdrs) add_library(PHY ${PHY_SRC}) target_link_libraries(PHY PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +pkg_check_modules(blas REQUIRED blas) +pkg_check_modules(lapacke REQUIRED lapacke) + add_library(PHY_UE ${PHY_SRC_UE}) target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +# RHEL needs also cblas, but Ubuntu does not have it. So `cblas_LIBRARIES` will +# be empty for Ubuntu, a no-op +pkg_check_modules(cblas cblas) +target_link_libraries(PHY_UE PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES}) +target_include_directories(PHY_UE PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS}) add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) @@ -1971,6 +1943,8 @@ set (SIMUSRC ) add_library(SIMU STATIC ${SIMUSRC} ) target_include_directories(SIMU PUBLIC ${OPENAIR1_DIR}/SIMULATION/TOOLS ${OPENAIR1_DIR}/SIMULATION/RF) +target_link_libraries(SIMU PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES}) +target_include_directories(SIMU PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS}) # Qt-based scope add_boolean_option(ENABLE_NRQTSCOPE OFF "Build the Qt-Scope" OFF) @@ -2001,15 +1975,12 @@ include_directories("${NFAPI_DIR}/nfapi/inc") include_directories("${NFAPI_DIR}/sim_common/inc") include_directories("${NFAPI_DIR}/pnf_sim/inc") -list(APPEND ATLAS_LIBRARIES lapack lapacke) - - add_library(rfsimulator MODULE ${OPENAIR_DIR}/radio/rfsimulator/simulator.c ${OPENAIR_DIR}/radio/rfsimulator/apply_channelmod.c ${OPENAIR1_DIR}/PHY/TOOLS/signal_energy.c ) -target_link_libraries(rfsimulator PRIVATE SIMU ${ATLAS_LIBRARIES}) +target_link_libraries(rfsimulator PRIVATE SIMU) add_library(oai_iqplayer MODULE ${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c @@ -2174,10 +2145,10 @@ target_link_libraries(lte-uesoftmodem PRIVATE lte_rrc nr_rrc s1ap x2ap m2ap m3ap SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB - ${NAS_UE_LIB} ITTI ${ATLAS_LIBRARIES} + ${NAS_UE_LIB} ITTI -Wl,--end-group z dl) -target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp ${ATLAS_LIBRARIES}) +target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2218,7 +2189,7 @@ target_link_libraries(nr-softmodem PRIVATE x2ap f1ap m2ap m3ap e1ap -Wl,--end-group z dl) -target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp ${ATLAS_LIBRARIES}) +target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2277,10 +2248,10 @@ target_link_libraries(nr-uesoftmodem PRIVATE nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_NR_LIB - ITTI ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH + ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH -Wl,--end-group z dl) -target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES}) target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2310,7 +2281,7 @@ add_executable(dlsim_tm4 ) target_link_libraries (dlsim_tm4 -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY ITTI -Wl,--end-group - pthread m rt CONFIG_LIB ${ATLAS_LIBRARIES} ${T_LIB} + pthread m rt CONFIG_LIB ${T_LIB} ) add_executable(rftest @@ -2331,7 +2302,7 @@ add_executable(polartest ) target_link_libraries(polartest PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_COMMON PHY_NR_UE CONFIG_LIB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} dl + m pthread dl ) add_executable(smallblocktest @@ -2343,7 +2314,7 @@ add_executable(smallblocktest target_link_libraries(smallblocktest PRIVATE -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} dl + m pthread dl ) @@ -2360,7 +2331,7 @@ if (ENABLE_LDPC_CUDA) endif() target_link_libraries(ldpctest PRIVATE -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} dl + m pthread dl ) add_executable(nr_dlschsim @@ -2372,7 +2343,7 @@ add_executable(nr_dlschsim ) target_link_libraries(nr_dlschsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_dlschsim PRIVATE asn1_nr_rrc_hdrs) @@ -2385,7 +2356,7 @@ add_executable(nr_pbchsim ) target_link_libraries(nr_pbchsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2400,7 +2371,7 @@ add_executable(nr_pucchsim ) target_link_libraries(nr_pucchsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_pucchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2419,7 +2390,7 @@ add_executable(nr_dlsim ) target_link_libraries(nr_dlsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2431,7 +2402,7 @@ add_executable(nr_prachsim ${SHLIB_LOADER_SOURCES}) target_link_libraries(nr_prachsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl) + m pthread ${T_LIB} ITTI dl) target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_ulschsim @@ -2444,7 +2415,7 @@ add_executable(nr_ulschsim ) target_link_libraries(nr_ulschsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2468,7 +2439,7 @@ endif() target_link_libraries(nr_ulsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl ) target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2485,7 +2456,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr ) target_link_libraries (${myExe} PRIVATE -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU ITTI -Wl,--end-group - pthread m rt CONFIG_LIB ${ATLAS_LIBRARIES} ${T_LIB} dl + pthread m rt CONFIG_LIB ${T_LIB} dl ) target_link_libraries(${myExe} PRIVATE asn1_lte_rrc_hdrs) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c index fb0484a5f9..416a5dbf39 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c @@ -41,14 +41,8 @@ #include #include #include -#if defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1796 && RHEL_RELEASE_CODE != 2403 - #include - #include -#else - #include - #include -#endif -#include +#include +#include #include "linear_preprocessing_rec.h" //#define DEBUG_MMSE diff --git a/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c b/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c index 83c74389cf..59da43e564 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c @@ -14,13 +14,8 @@ data storage. */ #include #include #include -#if defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= 1796 && RHEL_RELEASE_CODE != 2403 -#include -#include -#else #include #include -#endif //#define DEBUG_PREPROC From 28ec4944a54656d8103abcd6ad8557020d99e029 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 08:58:01 +0200 Subject: [PATCH 41/87] Fix minimal_stub.c It uses definitions from stdlib.h, so include it. --- common/utils/minimal_stub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/utils/minimal_stub.c b/common/utils/minimal_stub.c index be9c1b399d..64f2e3faa9 100644 --- a/common/utils/minimal_stub.c +++ b/common/utils/minimal_stub.c @@ -1,3 +1,5 @@ +#include + #ifndef T_TRACER int T_stdout; #endif From 387f5e4118b530baf2b8d89f0fc511d1d2cc67c6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:15:53 +0200 Subject: [PATCH 42/87] Make shlib_loader OBJECT library to prevent multiple compilations Including sources in targets makes that file being compiled multiple times. Instead, define an OBJECT library (i.e., it is only compiled, but not linked), and link it into each target that uses it. --- CMakeLists.txt | 68 ++++++++---------------- cmake_targets/at_commands/CMakeLists.txt | 2 - 2 files changed, 23 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d46ffdda..2ae2cdaca4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -450,10 +450,11 @@ add_library(CONFIG_LIB target_link_libraries(CONFIG_LIB PRIVATE dl UTIL) add_library(params_libconfig MODULE ${CONFIG_ROOTDIR}/libconfig/config_libconfig.c) target_link_libraries(params_libconfig config) + # shared library loader -set (SHLIB_LOADER_SOURCES - ${OPENAIR_DIR}/common/utils/load_module_shlib.c -) +add_library(shlib_loader OBJECT common/utils/load_module_shlib.c) +target_link_libraries(shlib_loader PRIVATE CONFIG_LIB) + # include RF devices / transport protocols library modules ###################################################################### @@ -1910,11 +1911,6 @@ set (NBIOT_SOURCES ) add_library(NB_IoT MODULE ${NBIOT_SOURCES} ) -# shared library loader -set (SHLIB_LOADER_SOURCES - ${OPENAIR_DIR}/common/utils/load_module_shlib.c - ) - add_library(LIB_5GNAS_GNB ${NAS_SRC}/COMMON/nr_common.c ${NAS_SRC}/gNB/network_process_nas.c @@ -2076,7 +2072,6 @@ add_executable(lte-softmodem ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) add_dependencies(lte-softmodem oai_iqplayer) @@ -2084,7 +2079,7 @@ target_link_libraries(lte-softmodem PRIVATE -Wl,--start-group lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB - ${NAS_UE_LIB} ITTI SIMU SIMU_ETH + ${NAS_UE_LIB} ITTI SIMU SIMU_ETH shlib_loader -Wl,--end-group z dl) target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) @@ -2101,12 +2096,10 @@ add_executable(oairu ${OPENAIR_DIR}/executables/main_ru.c ${T_SOURCE} ${OPENAIR_DIR}/common/utils/lte/prach_utils.c - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(oairu PRIVATE -Wl,--start-group - SCHED_RU_LIB - PHY_COMMON PHY_RU UTIL + SCHED_RU_LIB PHY_COMMON PHY_RU UTIL shlib_loader -Wl,--end-group z dl) target_link_libraries(oairu PRIVATE pthread m CONFIG_LIB rt ${T_LIB}) @@ -2134,7 +2127,6 @@ add_executable(lte-uesoftmodem ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) if (NOT ${NOS1}) @@ -2145,7 +2137,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE lte_rrc nr_rrc s1ap x2ap m2ap m3ap SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB - ${NAS_UE_LIB} ITTI + ${NAS_UE_LIB} ITTI shlib_loader -Wl,--end-group z dl) target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) @@ -2178,7 +2170,6 @@ add_executable(nr-softmodem ${PHY_INTERFACE_DIR}/queue_t.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr-softmodem PRIVATE @@ -2186,7 +2177,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 SECURITY ITTI ${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 SIMU_ETH - x2ap f1ap m2ap m3ap e1ap + x2ap f1ap m2ap m3ap e1ap shlib_loader -Wl,--end-group z dl) target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) @@ -2212,13 +2203,12 @@ add_executable(nr-cuup ${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 SIMU_ETH - z sctp dl pthread) + z sctp dl pthread shlib_loader) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) # nr-uesoftmodem is UE implementation @@ -2240,7 +2230,6 @@ add_executable(nr-uesoftmodem ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr-uesoftmodem PRIVATE @@ -2248,7 +2237,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_NR_LIB - ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH + ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH shlib_loader -Wl,--end-group z dl) target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES}) @@ -2289,16 +2278,14 @@ add_executable(rftest ${OPENAIR_DIR}/openair1/PHY/TOOLS/calibration_scope.c ${OPENAIR_DIR}/radio/COMMON/common_lib.c ${OPENAIR_DIR}/executables/softmodem-common.c - ${SHLIB_LOADER_SOURCES} ) -target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL pthread dl m ${T_LIB} ) +target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL pthread dl m ${T_LIB} shlib_loader) target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) add_executable(polartest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(polartest PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_COMMON PHY_NR_UE CONFIG_LIB -Wl,--end-group @@ -2309,12 +2296,11 @@ add_executable(smallblocktest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/smallblocktest.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(smallblocktest PRIVATE -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group - m pthread dl + m pthread dl shlib_loader ) @@ -2322,7 +2308,6 @@ add_executable(ldpctest ${PHY_NR_CODINGIF} ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) add_dependencies( ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_parityCheck) @@ -2330,8 +2315,8 @@ if (ENABLE_LDPC_CUDA) add_dependencies(ldpctest ldpc_cuda) endif() target_link_libraries(ldpctest PRIVATE - -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group - m pthread dl + -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group + m pthread dl shlib_loader ) add_executable(nr_dlschsim @@ -2339,11 +2324,10 @@ add_executable(nr_dlschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_dlschsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_dlschsim PRIVATE asn1_nr_rrc_hdrs) @@ -2352,11 +2336,10 @@ add_executable(nr_pbchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_pbchsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2367,11 +2350,10 @@ add_executable(nr_pucchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_pucchsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_pucchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2386,11 +2368,10 @@ add_executable(nr_dlsim ${NFAPI_USER_DIR}/gnb_ind_vars.c ${PHY_INTERFACE_DIR}/queue_t.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_dlsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2399,10 +2380,10 @@ add_executable(nr_prachsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES}) +) target_link_libraries(nr_prachsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -lz -Wl,--end-group - m pthread ${T_LIB} ITTI dl) + m pthread ${T_LIB} ITTI dl shlib_loader) target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_ulschsim @@ -2411,11 +2392,10 @@ add_executable(nr_ulschsim ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${PHY_INTERFACE_DIR}/queue_t.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_ulschsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2430,7 +2410,6 @@ add_executable(nr_ulsim ${NFAPI_USER_DIR}/gnb_ind_vars.c ${PHY_INTERFACE_DIR}/queue_t.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ) if (ENABLE_LDPC_T1) @@ -2439,7 +2418,7 @@ endif() target_link_libraries(nr_ulsim PRIVATE -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group - m pthread ${T_LIB} ITTI dl + m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2451,12 +2430,11 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} ${NFAPI_USER_DIR}/nfapi.c ) target_link_libraries (${myExe} PRIVATE -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU ITTI -Wl,--end-group - pthread m rt CONFIG_LIB ${T_LIB} dl + pthread m rt CONFIG_LIB ${T_LIB} dl shlib_loader ) target_link_libraries(${myExe} PRIVATE asn1_lte_rrc_hdrs) diff --git a/cmake_targets/at_commands/CMakeLists.txt b/cmake_targets/at_commands/CMakeLists.txt index cda9163c9b..3891af37ab 100755 --- a/cmake_targets/at_commands/CMakeLists.txt +++ b/cmake_targets/at_commands/CMakeLists.txt @@ -102,8 +102,6 @@ find_package(Threads REQUIRED) set (FIRMWARE_VERSION "No svn information") add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") -add_boolean_option(LINUX True "????") - ########################## # NAS LAYER OPTIONS ########################## From 187519052161a34beffd7c95a7b756908eb786a9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 17 Jun 2023 09:24:08 +0200 Subject: [PATCH 43/87] Repair rftest - needs forms library, so link it - fix warnings --- CMakeLists.txt | 2 +- openair1/PHY/TOOLS/calibration_test.c | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ae2cdaca4..1083c18c57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2279,7 +2279,7 @@ add_executable(rftest ${OPENAIR_DIR}/radio/COMMON/common_lib.c ${OPENAIR_DIR}/executables/softmodem-common.c ) -target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL pthread dl m ${T_LIB} shlib_loader) +target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB} shlib_loader) target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) add_executable(polartest diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c index 5d03d68c57..4dc3d658fe 100644 --- a/openair1/PHY/TOOLS/calibration_test.c +++ b/openair1/PHY/TOOLS/calibration_test.c @@ -50,7 +50,6 @@ int main(int argc, char **argv) { int N_RB=50; - int subCarrierFreq=30e3; int sampling_rate=30.72e6; int DFT=2048; int TxAdvanceInDFTSize=12; @@ -325,17 +324,8 @@ int main(int argc, char **argv) { while(!oai_exit) { for (int i=0; i Date: Sat, 17 Jun 2023 17:05:30 +0200 Subject: [PATCH 44/87] CONFIG_LIB: do not include libconfig headers globally Use target_include_directories() only on relevant targets. Remove from some targets that don't use the config module. --- CMakeLists.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1083c18c57..63b69e6c3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,6 @@ include("cmake_targets/macros.cmake") ################################### include(FindPkgConfig) -pkg_search_module(CONFIG libconfig REQUIRED) -include_directories(${CONFIG_INCLUDE_DIRS}) - pkg_search_module(CRYPTO libcrypto REQUIRED) include_directories(${CRYPTO_INCLUDE_DIRS}) @@ -440,16 +437,20 @@ target_link_libraries(f1ap PRIVATE ngap nr_rrc) add_list1_option(NB_ANTENNAS_RX "4" "Number of antennas in reception" "1" "2" "4") add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4") -#NOKIA config enhancement set (CONFIG_ROOTDIR ${OPENAIR_DIR}/common/config) add_library(CONFIG_LIB ${CONFIG_ROOTDIR}/config_load_configmodule.c ${CONFIG_ROOTDIR}/config_userapi.c ${CONFIG_ROOTDIR}/config_cmdline.c ) + +# CONFIG_LIB is a wrapper around a particular config implementation, default is +# libconfig in params_libconfig below +pkg_check_modules(libconfig REQUIRED libconfig) target_link_libraries(CONFIG_LIB PRIVATE dl UTIL) add_library(params_libconfig MODULE ${CONFIG_ROOTDIR}/libconfig/config_libconfig.c) -target_link_libraries(params_libconfig config) +target_include_directories(params_libconfig PRIVATE ${libconfig_INCLUDE_DIRS}) +target_link_libraries(params_libconfig PRIVATE ${libconfig_LIBRARIES}) # shared library loader add_library(shlib_loader OBJECT common/utils/load_module_shlib.c) @@ -1234,7 +1235,7 @@ set(PHY_MEX_UE ${OPENAIR_DIR}/common/utils/T/T.c ${OPENAIR_DIR}/common/utils/T/local_tracer.c ) -add_library(PHY_MEX ${PHY_MEX_UE} ${CONFIG_LIB}) +add_library(PHY_MEX ${PHY_MEX_UE}) target_link_libraries(PHY_MEX PRIVATE asn1_lte_rrc_hdrs) #Layer 2 library @@ -2029,7 +2030,7 @@ add_library(minimal_lib ${OPENAIR_DIR}/common/utils/minimal_stub.c ${T_SOURCE} ) -target_link_libraries(minimal_lib pthread dl ${T_LIB} CONFIG_LIB) +target_link_libraries(minimal_lib pthread dl ${T_LIB}) add_executable(nfapi_test ${OPENAIR_DIR}/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c @@ -2047,7 +2048,7 @@ target_link_libraries (measurement_display minimal_lib) add_executable(test5Gnas ${OPENAIR_DIR}/openair3/TEST/test5Gnas.c ) -target_link_libraries (test5Gnas LIB_5GNAS_GNB CONFIG_LIB minimal_lib ) +target_link_libraries (test5Gnas LIB_5GNAS_GNB minimal_lib ) # lte-softmodem is both eNB and UE implementation @@ -2279,7 +2280,7 @@ add_executable(rftest ${OPENAIR_DIR}/radio/COMMON/common_lib.c ${OPENAIR_DIR}/executables/softmodem-common.c ) -target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB} shlib_loader) +target_link_libraries(rftest PRIVATE minimal_lib PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB} shlib_loader) target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) add_executable(polartest @@ -2299,7 +2300,7 @@ add_executable(smallblocktest ) target_link_libraries(smallblocktest PRIVATE - -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group + -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group m pthread dl shlib_loader ) From 47da0a024d443c3a2b7d56cf83aaae5782e4cf9a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 07:18:49 +0200 Subject: [PATCH 45/87] Remove libcrypto, correctly search and link libcrypt - libcrypto is not used - we use libcrypt, so correctly check for it, and link to the corresponding targets --- CMakeLists.txt | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 63b69e6c3c..952fdc0d3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,6 @@ include("cmake_targets/macros.cmake") ################################### include(FindPkgConfig) -pkg_search_module(CRYPTO libcrypto REQUIRED) -include_directories(${CRYPTO_INCLUDE_DIRS}) - # Check if asn1c is installed, and check if it supports all options we need # a user can provide ASN1C_EXEC to override an asn1c to use (e.g., parallel # installation) @@ -291,6 +288,9 @@ add_library(nr_rrc ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c) target_link_libraries(nr_rrc PUBLIC asn1_nr_rrc asn1_lte_rrc) +# S1AP and NGAP need crypt library +pkg_check_modules(libcrypt REQUIRED libcrypt) + # S1AP ############## set(S1AP_DIR ${OPENAIR3_DIR}/S1AP) @@ -312,6 +312,8 @@ add_library(s1ap ) target_link_libraries(s1ap PUBLIC asn1_s1ap) target_link_libraries(s1ap PRIVATE nr_rrc asn1_nr_rrc_hdrs lte_rrc) +target_include_directories(s1ap PRIVATE ${libcrypt_INCLUDE_DIRS}) +target_link_libraries(s1ap PUBLIC ${libcrypt_LIBRARIES}) # NGAP ############## @@ -333,6 +335,8 @@ add_library(ngap ) target_link_libraries(ngap PUBLIC asn1_ngap) target_link_libraries(ngap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_include_directories(ngap PRIVATE ${libcrypt_INCLUDE_DIRS}) +target_link_libraries(ngap PRIVATE ${libcrypt_LIBRARIES}) #M2AP ############## @@ -1920,7 +1924,7 @@ add_library(LIB_5GNAS_GNB ) target_include_directories(LIB_5GNAS_GNB PRIVATE ${OPENAIR_DIR}/common/utils/ds/) -target_link_libraries(LIB_5GNAS_GNB PRIVATE SECURITY ${CRYPTO_LIBRARIES}) +target_link_libraries(LIB_5GNAS_GNB PRIVATE SECURITY) target_link_libraries(LIB_5GNAS_GNB PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) # Simulation library @@ -2083,7 +2087,7 @@ target_link_libraries(lte-softmodem PRIVATE ${NAS_UE_LIB} ITTI SIMU SIMU_ETH shlib_loader -Wl,--end-group z dl) -target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) +target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(lte-softmodem PRIVATE ${T_LIB}) target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2141,7 +2145,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE ${NAS_UE_LIB} ITTI shlib_loader -Wl,--end-group z dl) -target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) +target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2181,7 +2185,7 @@ target_link_libraries(nr-softmodem PRIVATE x2ap f1ap m2ap m3ap e1ap shlib_loader -Wl,--end-group z dl) -target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} sctp) +target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2241,7 +2245,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH shlib_loader -Wl,--end-group z dl) -target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES}) +target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt) target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2456,7 +2460,7 @@ foreach(myExe s1ap ${OPENAIR3_DIR}/TEST/test_${myExe}.c ) target_link_libraries (test_${myExe} - -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} CONFIG_LIB + -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt CONFIG_LIB ) endforeach(myExe) From 52cb72c0eed2a14383aee28f99efbd6c02a75eb1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 03:41:27 +0200 Subject: [PATCH 46/87] build_oai: allow to only build radio/transport libraries --- cmake_targets/build_oai | 101 +++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 58 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 1d4c55da20..a548cd8ced 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -569,66 +569,51 @@ function main() { #################################################### # Build RF device and transport protocol libraries # #################################################### - if [ "$eNB" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$RU" = "1" -o "$nrUE" = "1" ] ; then + if [ "$HW" != "None" ] ; then + rm -f liboai_device.so - # build RF device libraries - if [ "$HW" != "None" ] ; then - rm -f liboai_device.so + if [ "$HW" == "OAI_USRP" ] ; then + compilations $BUILD_DIR oai_usrpdevif.txt oai_usrpdevif + ln -sf liboai_usrpdevif.so liboai_device.so + echo "liboai_device.so symlinks to liboai_usrpdevif.so" + elif [ "$HW" == "OAI_BLADERF" ] ; then + compilations $BUILD_DIR oai_bladerfdevif.txt oai_bladerfdevif + ln -sf liboai_bladerfdevif.so liboai_device.so + echo "liboai_device.so symlinks liboai_bladerfdevif.so" + elif [ "$HW" == "OAI_LMSSDR" ] ; then + compilations $BUILD_DIR oai_lmssdrdevif.txt oai_lmssdrdevif + ln -sf liboai_lmssdrdevif.so liboai_device.so + echo "liboai_device.so symlinks to liboai_lmssdrdevif.so" + elif [ "$HW" == "OAI_IRIS" ] ; then + compilations $BUILD_DIR oai_irisdevif.txt oai_irisdevif + ln -s liboai_irisdevif.so liboai_device.so + echo "liboai_device.so symlinks to liboai_irisdevif.so" + elif [ "$HW" == "OAI_AW2SORI" ] ; then + compilations $BUILD_DIR aw2sori_transpro.txt aw2sori_transpro + ln -sf libaw2sori_transpro.so libthirdparty_transpro.so + echo "libthirdparty_transpro.so symlinks to libaw2sori_transpro.so" + else + echo_fatal "illegal HW option $HW" + fi + fi - if [ "$HW" == "OAI_USRP" ] ; then - compilations $BUILD_DIR oai_usrpdevif.txt oai_usrpdevif - - ln -sf liboai_usrpdevif.so liboai_device.so - echo_info "liboai_device.so is linked to USRP device library" - elif [ "$HW" == "OAI_BLADERF" ] ; then - if [ -f "/usr/include/libbladeRF.h" ] ; then - compilations $BUILD_DIR oai_bladerfdevif.txt oai_bladerfdevif - fi - - ln -sf liboai_bladerfdevif.so liboai_device.so - echo_info "liboai_device.so is linked to BLADERF device library" - elif [ "$HW" == "OAI_LMSSDR" ] ; then -# if [ -f "/usr/include/libbladeRF.h" ] ; then - compilations $BUILD_DIR oai_lmssdrdevif.txt oai_lmssdrdevif -# fi - - ln -sf liboai_lmssdrdevif.so liboai_device.so - echo_info "liboai_device.so is linked to LMSSDR device library" - elif [ "$HW" == "OAI_IRIS" ] ; then - compilations $BUILD_DIR oai_irisdevif.txt oai_irisdevif - - ln -s liboai_irisdevif.so liboai_device.so - echo_info "liboai_device.so is linked to IRIS device library" - elif [ "$HW" == "OAI_AW2SORI" ] ; then - compilations $BUILD_DIR aw2sori_transpro.txt aw2sori_transpro - - ln -sf libaw2sori_transpro.so libthirdparty_transpro.so - echo_info "build libthirdparty_transpro.so for AW2SORI fronthaul" - else - echo_info "liboai_device.so is not linked to any device library" - fi - fi - - #build transport protocol libraries (currently only ETHERNET is available) - if [ "$SKIP_SHARED_LIB_FLAG" = "False" ]; then - echo_info "Building transport protocol libraries" - rm -f liboai_transpro.so - if [ "$TP" == "Ethernet" ]; then - compilations $BUILD_DIR oai_eth_transpro.txt oai_eth_transpro - ln -sf liboai_eth_transpro.so liboai_transpro.so - echo_info "liboai_transpro.so is linked to ETHERNET transport" - fi - if [ "$TP" == "benetel4g" ]; then - compilations $BUILD_DIR benetel_4g.txt benetel4g - ln -sf libbenetel_4g.so liboai_transpro.so - echo_info "liboai_transpro.so is linked to BENETEL4G transport" - fi - if [ "$TP" == "benetel5g" ]; then - compilations $BUILD_DIR benetel_5g.txt benetel_5g - ln -sf libbenetel_5g.so liboai_transpro.so - echo_info "liboai_transpro.so is linked to BENETEL4G transport" - fi - fi + if [ "$TP" != "None" ]; then + rm -f liboai_transpro.so + if [ "$TP" == "Ethernet" ]; then + compilations $BUILD_DIR oai_eth_transpro.txt oai_eth_transpro + ln -sf liboai_eth_transpro.so liboai_transpro.so + echo_info "liboai_transpro.so symlinks to liboai_eth_transpro.so" + elif [ "$TP" == "benetel4g" ]; then + compilations $BUILD_DIR benetel_4g.txt benetel4g + ln -sf libbenetel_4g.so liboai_transpro.so + echo_info "liboai_transpro.so symlinks to libbenetel_4g.so" + elif [ "$TP" == "benetel5g" ]; then + compilations $BUILD_DIR benetel_5g.txt benetel_5g + ln -sf libbenetel_5g.so liboai_transpro.so + echo_info "liboai_transpro.so symlinks to libbenetel_5g.so" + else + echo_fatal "illegal TP option $TP" + fi fi ################### From ddf549b1f38093dc127aef1ba46233bc7b9a668c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jan 2023 08:13:45 +0100 Subject: [PATCH 47/87] Move radio CMakeLists.txt to subdirectory - move following radios: AW2S, BladeRF, IRIS, LMSSDR, RFsimulator, USRP - move following transports: Ethernet, benetel4g, benetel5g - for each: create independent cmake variable to switch compilation on/off, in order: OAI_AW2S, OAI_BLADERF, OAI_IRIS, OAI_LMSSDR, OAI_SIMU, OAI_USRP, OAI_ETHERNET, OAI_BENETEL4G, OAI_BENETEL5G - Remove RF_BOARD variable, allows to compile multiple boards at once - where applicable: remove USERSPACE/LIB in path, i.e., move files up to directories, as all are userspace libraries Note that with the above, it is now mandatory to enable a radio implementation before compiling it, e.g., for USRP: ./build_oai -w USRP cmake .. -DOAI_USRP=ON && ninja oai_usrpdevif --- CMakeLists.txt | 132 +----------------- cmake_targets/build_oai | 38 ++--- doc/Doxyfile | 10 +- executables/lte-ru.c | 2 +- executables/lte-softmodem.c | 2 +- executables/lte-uesoftmodem.c | 2 +- executables/main_ru.c | 2 +- executables/nr-ru.c | 2 +- executables/nr-softmodem.c | 2 +- executables/nr-uesoftmodem.c | 2 +- executables/ru_control.c | 2 +- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 2 +- openair2/ENB_APP/NB_IoT_config.c | 2 +- openair2/ENB_APP/enb_config.c | 2 +- openair2/GNB_APP/gnb_config.c | 2 +- openair2/MCE_APP/mce_config.c | 2 +- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 2 +- openair2/PHY_INTERFACE/phy_stub_UE.c | 2 +- openair3/MME_APP/mme_config.c | 2 +- radio/AW2SORI/CMakeLists.txt | 13 ++ radio/BLADERF/CMakeLists.txt | 4 + .../BLADERF/{USERSPACE/LIB => }/bladerf_lib.c | 0 .../BLADERF/{USERSPACE/LIB => }/bladerf_lib.h | 0 radio/CMakeLists.txt | 34 +++++ radio/ETHERNET/CMakeLists.txt | 9 ++ radio/ETHERNET/benetel/4g/CMakeLists.txt | 17 +++ radio/ETHERNET/benetel/5g/CMakeLists.txt | 16 +++ radio/ETHERNET/benetel/CMakeLists.txt | 9 ++ radio/ETHERNET/{USERSPACE/LIB => }/eth_raw.c | 0 radio/ETHERNET/{USERSPACE/LIB => }/eth_udp.c | 0 .../ETHERNET/{USERSPACE/LIB => }/ethernet.md | 0 .../{USERSPACE/LIB => }/ethernet_lib.c | 0 .../{USERSPACE/LIB => }/ethernet_lib.h | 0 radio/ETHERNET/{USERSPACE/LIB => }/if_defs.h | 2 +- radio/IRIS/CMakeLists.txt | 5 + radio/IRIS/{USERSPACE/LIB => }/iris_lib.cpp | 0 radio/LMSSDR/CMakeLists.txt | 5 + radio/LMSSDR/{USERSPACE/LIB => }/lms_lib.cpp | 0 .../LMSSDR/{USERSPACE/LIB => }/sodera_lib.cpp | 0 radio/USRP/CMakeLists.txt | 7 + radio/USRP/{USERSPACE/LIB => }/usrp_lib.cpp | 0 radio/rfsimulator/CMakeLists.txt | 11 ++ 42 files changed, 166 insertions(+), 178 deletions(-) create mode 100644 radio/AW2SORI/CMakeLists.txt create mode 100644 radio/BLADERF/CMakeLists.txt rename radio/BLADERF/{USERSPACE/LIB => }/bladerf_lib.c (100%) rename radio/BLADERF/{USERSPACE/LIB => }/bladerf_lib.h (100%) create mode 100644 radio/CMakeLists.txt create mode 100644 radio/ETHERNET/CMakeLists.txt create mode 100644 radio/ETHERNET/benetel/4g/CMakeLists.txt create mode 100644 radio/ETHERNET/benetel/5g/CMakeLists.txt create mode 100644 radio/ETHERNET/benetel/CMakeLists.txt rename radio/ETHERNET/{USERSPACE/LIB => }/eth_raw.c (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/eth_udp.c (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/ethernet.md (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/ethernet_lib.c (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/ethernet_lib.h (100%) rename radio/ETHERNET/{USERSPACE/LIB => }/if_defs.h (98%) create mode 100644 radio/IRIS/CMakeLists.txt rename radio/IRIS/{USERSPACE/LIB => }/iris_lib.cpp (100%) create mode 100644 radio/LMSSDR/CMakeLists.txt rename radio/LMSSDR/{USERSPACE/LIB => }/lms_lib.cpp (100%) rename radio/LMSSDR/{USERSPACE/LIB => }/sodera_lib.cpp (100%) create mode 100644 radio/USRP/CMakeLists.txt rename radio/USRP/{USERSPACE/LIB => }/usrp_lib.cpp (100%) create mode 100644 radio/rfsimulator/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 952fdc0d3a..788deb761a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,30 +55,6 @@ check_option(${ASN1C_EXEC} -no-gen-JER ASN1C_EXEC) check_option(${ASN1C_EXEC} -no-gen-BER ASN1C_EXEC) check_option(${ASN1C_EXEC} -no-gen-OER ASN1C_EXEC) -#uhd 4.0 and iris installs by default in /usr/local -include_directories("/usr/local/include/") -#use native cmake method as this package is not in pkg-config -add_list2_option(RF_BOARD "None" "RF head type" "None" "OAI_USRP" "OAI_BLADERF" "OAI_LMSSDR" "OAI_SIMU") -if (${RF_BOARD} STREQUAL "OAI_USRP") - find_package(Boost REQUIRED) - -elseif (${RF_BOARD} STREQUAL "OAI_IRIS") - include_directories("radio/IRIS/USERSPACE/LIB/") - - set(HW_SOURCE ${HW_SOURCE} - radio/IRIS/USERSPACE/LIB/iris_lib.cpp) - LINK_DIRECTORIES("/usr/local/lib") - set(option_HW_lib "-lSoapySDR -rdynamic -ldl") - -elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") - include_directories("radio/AW2SORI") - set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_DIR}/radio/AW2SORI/ARCH/AW2SORI/oaiori.c) - LINK_DIRECTORIES("/usr/local/lib") - set(openair_HW_lib "-shared -fPIC -msse4 -g -ggdb -lori") - -endif (${RF_BOARD} STREQUAL "OAI_USRP") - ######################################################### # Base directories, compatible with legacy OAI building # ######################################################### @@ -460,101 +436,6 @@ target_link_libraries(params_libconfig PRIVATE ${libconfig_LIBRARIES}) add_library(shlib_loader OBJECT common/utils/load_module_shlib.c) target_link_libraries(shlib_loader PRIVATE CONFIG_LIB) -# include RF devices / transport protocols library modules -###################################################################### - -set(HWLIB_USRP_SOURCE - ${OPENAIR_DIR}/radio/USRP/USERSPACE/LIB/usrp_lib.cpp - ) -add_library(oai_usrpdevif MODULE ${HWLIB_USRP_SOURCE} ) -target_include_directories(oai_usrpdevif PRIVATE - "${OPENAIR_DIR}/radio/USRP/USERSPACE/LIB/" - ${Boost_INCLUDE_DIR} -) -target_link_libraries(oai_usrpdevif uhd) - -include_directories("${OPENAIR_DIR}/radio/BLADERF/USERSPACE/LIB/") -set(HWLIB_BLADERF_SOURCE - ${OPENAIR_DIR}/radio/BLADERF/USERSPACE/LIB/bladerf_lib.c - ) -add_library(oai_bladerfdevif MODULE ${HWLIB_BLADERF_SOURCE} ) -target_link_libraries(oai_bladerfdevif bladeRF) - -include_directories("${OPENAIR_DIR}/radio/LMSSDR/USERSPACE/LIB/") - -set(HWLIB_LMSSDR_SOURCE - ${OPENAIR_DIR}/radio/LMSSDR/USERSPACE/LIB/lms_lib.cpp - ) -add_library(oai_lmssdrdevif MODULE ${HWLIB_LMSSDR_SOURCE} ) -target_include_directories(oai_lmssdrdevif PRIVATE /usr/local/include/lime) -target_link_libraries(oai_lmssdrdevif LimeSuite ) - - -include_directories("${OPENAIR_DIR}/radio/ETHERNET/USERSPACE/LIB/") -set(TPLIB_ETHERNET_SOURCE - ${OPENAIR_DIR}/radio/ETHERNET/USERSPACE/LIB/ethernet_lib.c - ${OPENAIR_DIR}/radio/ETHERNET/USERSPACE/LIB/eth_udp.c - ${OPENAIR_DIR}/radio/ETHERNET/USERSPACE/LIB/eth_raw.c - ) -add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} ) - -include_directories("${OPENAIR_DIR}/radio/AW2SORI/") -link_directories("/usr/local/lib") -set(HWLIB_AW2SORI_SOURCE - ${OPENAIR_DIR}/radio/AW2SORI/oaiori.c - ) -add_library(aw2sori_transpro MODULE ${HWLIB_AW2SORI_SOURCE}) -target_compile_options(aw2sori_transpro PRIVATE -shared -fPIC -msse4 -g -ggdb -DLITE_COMPILATION) -target_link_libraries(aw2sori_transpro libori.so) - -include_directories("${OPENAIR_DIR}/radio/IRIS/USERSPACE/LIB/") -set(option_HWIRISLIB_lib "-l SoapySDR") -set(HWLIB_IRIS_SOURCE - ${OPENAIR_DIR}/radio/IRIS/USERSPACE/LIB/iris_lib.cpp - ) -add_library(oai_irisdevif MODULE ${HWLIB_IRIS_SOURCE}) -target_include_directories(oai_irisdevif PRIVATE /usr/local/lib/SoapySDR/modules0.7/) -target_link_libraries(oai_irisdevif SoapySDR) - -# Benetel 4G library -###################################################################### - - -include_directories ("/usr/include/dpdk") - -set(HWLIB_BENETEL_4G_SOURCE - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/benetel.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/shared_buffers.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/low.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/low_dpdk.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/4g/dpdk_driver.c - ) -add_library(benetel_4g MODULE ${HWLIB_BENETEL_4G_SOURCE} ) - -set_target_properties(benetel_4g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") - -SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") -target_link_libraries(benetel_4g PRIVATE ${DPDK_LIBS}) -target_link_libraries(benetel_4g PRIVATE pthread dl rt m numa) - -# Benetel 5G library -###################################################################### - -set(HWLIB_BENETEL_5G_SOURCE - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/benetel.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/shared_buffers.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/low.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/low_dpdk.c - ${OPENAIR_DIR}/radio/ETHERNET/benetel/5g/dpdk_driver.c - ) -add_library(benetel_5g MODULE ${HWLIB_BENETEL_5G_SOURCE} ) - -set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") - -SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") -target_link_libraries(benetel_5g PRIVATE ${DPDK_LIBS}) -target_link_libraries(benetel_5g PRIVATE pthread dl rt m numa) - ########################################################## # LDPC offload library @@ -1976,13 +1857,6 @@ include_directories("${NFAPI_DIR}/nfapi/inc") include_directories("${NFAPI_DIR}/sim_common/inc") include_directories("${NFAPI_DIR}/pnf_sim/inc") -add_library(rfsimulator MODULE - ${OPENAIR_DIR}/radio/rfsimulator/simulator.c - ${OPENAIR_DIR}/radio/rfsimulator/apply_channelmod.c - ${OPENAIR1_DIR}/PHY/TOOLS/signal_energy.c - ) -target_link_libraries(rfsimulator PRIVATE SIMU) - add_library(oai_iqplayer MODULE ${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c ) @@ -2040,11 +1914,6 @@ add_executable(nfapi_test ${OPENAIR_DIR}/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c ) -add_executable(replay_node - ${OPENAIR_DIR}/radio/rfsimulator/stored_node.c - ) -target_link_libraries (replay_node minimal_lib) - add_executable(measurement_display ${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c) target_link_libraries (measurement_display minimal_lib) @@ -2583,3 +2452,4 @@ add_subdirectory(doc) add_subdirectory(openair1) add_subdirectory(openair2) add_subdirectory(openair3) +add_subdirectory(radio) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index a548cd8ced..02379e197c 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -282,19 +282,27 @@ function main() { case "$2" in "USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "SIMU" | "AW2SORI") HW="OAI_"$2 + CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON" ;; "None") HW="None" ;; *) - echo_fatal "Unknown HW type $HW: exit..." + echo_fatal "Unknown HW type $2: exit..." esac - echo_info "Setting hardware to: $HW" - #CMAKE_CMD="$CMAKE_CMD -DRF_BOARD=\"${HW}\"" - CMAKE_CMD="$CMAKE_CMD -DRF_BOARD=${HW}" shift 2;; -t | --transport) - TP=$2 + case "$2" in + "Ethernet" | "benetel4g" | "benetel5g") + TP=$2 + CMAKE_CMD="$CMAKE_CMD -DOAI_${2^^}=ON" # ^^ makes uppercase + ;; + "None") + HW="None" + ;; + *) + echo_fatal "Unknown TP type $2; exit..." + esac shift 2;; -P | --phy_simulators) SIMUS_PHY=1 @@ -436,26 +444,6 @@ function main() { fi fi - ######################################################## - # Check validity of HW and TP parameters for eNB / gNB # - ######################################################## - # to be discussed - - if [ "$eNB" = "1" -o "$gNB" = "1" ] ; then - if [ "$HW" = "None" -a "$TP" = "None" ] ; then - echo_info "No local radio head and no transport protocol selected" - fi - if [ "$HW" = "None" ] ; then - echo_info "No radio head has been selected (HW set to $HW)" - fi - if [ "$TP" = "None" ] ; then - echo_info "No transport protocol has been selected (TP set to $TP)" - fi - fi - - echo_info "RF HW set to $HW" - # If the user doesn't specify the Linux scheduler to use, we set a value - ####################################################### # Setting and printing OAI envs, we should check here # ####################################################### diff --git a/doc/Doxyfile b/doc/Doxyfile index aba95ed7ec..f60031541a 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -874,11 +874,11 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/rfsimulator/rfsimulator.h \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/rfsimulator/simulator.c \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/rfsimulator/apply_channelmod.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/if_defs.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/ethernet_lib.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/eth_udp.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/USERSPACE/LIB/eth_raw.c \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/if_defs.h \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/ethernet_lib.c \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/eth_udp.c \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/ethernet_lib.h \ +@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/eth_raw.c \ @CMAKE_CURRENT_SOURCE_DIR@/../common/config/config_cmdline.c \ @CMAKE_CURRENT_SOURCE_DIR@/../common/config/config_paramdesc.h \ @CMAKE_CURRENT_SOURCE_DIR@/../common/config/config_userapi.h \ diff --git a/executables/lte-ru.c b/executables/lte-ru.c index d18e928802..b7734aa9ed 100644 --- a/executables/lte-ru.c +++ b/executables/lte-ru.c @@ -60,7 +60,7 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" /* these variables have to be defined before including ENB_APP/enb_paramdef.h */ static int DEFBANDS[] = {7}; diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 371735110c..1a9060c04c 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -48,7 +48,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index a28c268148..d5b47a198c 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -49,7 +49,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all diff --git a/executables/main_ru.c b/executables/main_ru.c index 2de9ba5d12..b0532024c5 100644 --- a/executables/main_ru.c +++ b/executables/main_ru.c @@ -46,7 +46,7 @@ #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" #include "PHY/phy_vars.h" #include "PHY/phy_extern.h" diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 857557c9e5..c9d3dab560 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -38,7 +38,7 @@ #include "rt_profiling.h" #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 13ea4b94ee..5381d8579d 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -40,7 +40,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 7896e57145..523038aae3 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -38,7 +38,7 @@ #include "common/utils/nr/nr_common.h" #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "openair1/PHY/MODULATION/nr_modulation.h" diff --git a/executables/ru_control.c b/executables/ru_control.c index db8c24be3f..b7d71be89f 100644 --- a/executables/ru_control.c +++ b/executables/ru_control.c @@ -54,7 +54,7 @@ #include "radio/COMMON/common_lib.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index ca641e4bc0..6fdcfbd96f 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -38,7 +38,7 @@ //#include "SCHED/sched_eNB.h" lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "common/utils/LOG/vcd_signal_dumper.h" const uint8_t lin2alaw_if4p5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85}; diff --git a/openair2/ENB_APP/NB_IoT_config.c b/openair2/ENB_APP/NB_IoT_config.c index 2936549da7..8e6a2fac46 100644 --- a/openair2/ENB_APP/NB_IoT_config.c +++ b/openair2/ENB_APP/NB_IoT_config.c @@ -39,7 +39,7 @@ #include "SystemInformationBlockType2.h" #include "PHY/phy_extern.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "common/config/config_userapi.h" #include "RRC_config_tools.h" #include "RRC_paramsvalues.h" diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index ea2b9f9543..1be541a2bc 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -47,7 +47,7 @@ #include "LAYER2/MAC/mac_proto.h" #include "PHY/phy_extern.h" #include "PHY/INIT/phy_init.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" #include "executables/lte-softmodem.h" diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 1d4a14ad8d..974e5d95b3 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -51,7 +51,7 @@ // #include "LAYER2/MAC/extern.h" // #include "LAYER2/MAC/proto.h" #include "PHY/INIT/nr_phy_init.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" #include "nr_pdcp/nr_pdcp_oai_api.h" diff --git a/openair2/MCE_APP/mce_config.c b/openair2/MCE_APP/mce_config.c index ec192582a8..c0e4c3f73c 100644 --- a/openair2/MCE_APP/mce_config.c +++ b/openair2/MCE_APP/mce_config.c @@ -45,7 +45,7 @@ #include "LAYER2/MAC/mac_proto.h" #include "PHY/phy_extern.h" #include "PHY/INIT/phy_init.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 1459d97dc6..0f2dbde947 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -45,7 +45,7 @@ #include "openair2/RRC/NR_UE/rrc_vars.h" #include "openair2/GNB_APP/L1_nr_paramdef.h" #include "openair2/GNB_APP/gnb_paramdef.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" #include #include "openair2/GNB_APP/MACRLC_nr_paramdef.h" diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index dfc82fa017..4584f42f3d 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -27,7 +27,7 @@ #include "openair2/PHY_INTERFACE/phy_stub_UE.h" #include "openair2/ENB_APP/L1_paramdef.h" #include "openair2/ENB_APP/enb_paramdef.h" -#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "radio/ETHERNET/if_defs.h" #include "common/config/config_load_configmodule.h" #include "common/config/config_userapi.h" #include diff --git a/openair3/MME_APP/mme_config.c b/openair3/MME_APP/mme_config.c index b05d78510a..b1138b0a64 100644 --- a/openair3/MME_APP/mme_config.c +++ b/openair3/MME_APP/mme_config.c @@ -45,7 +45,7 @@ #include "LAYER2/MAC/mac_proto.h" #include "PHY/phy_extern.h" #include "PHY/INIT/phy_init.h" -#include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" +#include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" diff --git a/radio/AW2SORI/CMakeLists.txt b/radio/AW2SORI/CMakeLists.txt new file mode 100644 index 0000000000..d055b374ac --- /dev/null +++ b/radio/AW2SORI/CMakeLists.txt @@ -0,0 +1,13 @@ +find_library(ori NAMES "libori.so" REQUIRED) +if(NOT ori) + message(FATAL_ERROR "cannot locate libori.so, required to build aw2sori_transpro") +endif() +# force that oai_eth_transpro is built as well, as aw2sori_transpro requires it +if(NOT OAI_ETHERNET) + message(FATAL_ERROR "aw2sori_transpro requires oai_eth_transpro, please enable OAI_ETHERNET (-DOAI_ETHERNET=ON for cmake, or ./build_oai -t Ethernet)") +endif() + +add_library(aw2sori_transpro MODULE oaiori.c) +target_compile_options(aw2sori_transpro PRIVATE -shared -fPIC -msse4 -g -ggdb -DLITE_COMPILATION) +target_link_libraries(aw2sori_transpro PRIVATE ori oai_eth_transpro) +set_target_properties(aw2sori_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/BLADERF/CMakeLists.txt b/radio/BLADERF/CMakeLists.txt new file mode 100644 index 0000000000..d7a7fc7162 --- /dev/null +++ b/radio/BLADERF/CMakeLists.txt @@ -0,0 +1,4 @@ +pkg_check_modules(bladeRF REQUIRED libbladeRF) +add_library(oai_bladerfdevif MODULE bladerf_lib.c) +target_link_libraries(oai_bladerfdevif PRIVATE bladeRF) +set_target_properties(oai_bladerfdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/BLADERF/USERSPACE/LIB/bladerf_lib.c b/radio/BLADERF/bladerf_lib.c similarity index 100% rename from radio/BLADERF/USERSPACE/LIB/bladerf_lib.c rename to radio/BLADERF/bladerf_lib.c diff --git a/radio/BLADERF/USERSPACE/LIB/bladerf_lib.h b/radio/BLADERF/bladerf_lib.h similarity index 100% rename from radio/BLADERF/USERSPACE/LIB/bladerf_lib.h rename to radio/BLADERF/bladerf_lib.h diff --git a/radio/CMakeLists.txt b/radio/CMakeLists.txt new file mode 100644 index 0000000000..937d8039f9 --- /dev/null +++ b/radio/CMakeLists.txt @@ -0,0 +1,34 @@ +add_boolean_option(OAI_AW2SORI OFF "Activate OAI's AW2S driver" OFF) +if(OAI_AW2SORI) + add_subdirectory(AW2SORI) +endif() + +add_boolean_option(OAI_ETHERNET OFF "Activate OAI's Ethernet transport driver" OFF) +if(OAI_ETHERNET) + add_subdirectory(ETHERNET) +endif() + +add_boolean_option(OAI_BLADERF OFF "Activate OAI's BladeRF driver" OFF) +if(OAI_BLADERF) + add_subdirectory(BLADERF) +endif() + +add_boolean_option(OAI_IRIS OFF "Activate OAI's IRIS/SoapySDR driver" OFF) +if(OAI_IRIS) + add_subdirectory(IRIS) +endif() + +add_boolean_option(OAI_LMSSDR OFF "Activate OAI's LimeSDR driver" OFF) +if(OAI_LMSSDR) + add_subdirectory(LMSSDR) +endif() + +add_boolean_option(OAI_SIMU ON "Activate OAI's rfsimulator driver" OFF) +if(OAI_SIMU) + add_subdirectory(rfsimulator) +endif() + +add_boolean_option(OAI_USRP OFF "Activate OAI's USRP driver" OFF) +if(OAI_USRP) + add_subdirectory(USRP) +endif() diff --git a/radio/ETHERNET/CMakeLists.txt b/radio/ETHERNET/CMakeLists.txt new file mode 100644 index 0000000000..aa2b14ef12 --- /dev/null +++ b/radio/ETHERNET/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(oai_eth_transpro MODULE + ethernet_lib.c + eth_udp.c + eth_raw.c +) +target_include_directories(oai_eth_transpro PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +set_target_properties(oai_eth_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +add_subdirectory(benetel) diff --git a/radio/ETHERNET/benetel/4g/CMakeLists.txt b/radio/ETHERNET/benetel/4g/CMakeLists.txt new file mode 100644 index 0000000000..b0f180719c --- /dev/null +++ b/radio/ETHERNET/benetel/4g/CMakeLists.txt @@ -0,0 +1,17 @@ +pkg_check_modules(libdpdk REQUIRED libdpdk=20.05.0) + +add_library(benetel_4g MODULE + benetel.c + shared_buffers.c + low.c + low_dpdk.c + dpdk_driver.c +) + +target_compile_definitions(benetel_4g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") + +SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") +target_include_directories(benetel_4g PRIVATE ${libdpdk_INCLUDE_DIRS}) +target_link_libraries(benetel_4g PRIVATE ${libdpdk_LIBRARIES}) +target_link_libraries(benetel_4g PRIVATE pthread dl rt m numa) +set_target_properties(benetel_4g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/benetel/5g/CMakeLists.txt b/radio/ETHERNET/benetel/5g/CMakeLists.txt new file mode 100644 index 0000000000..da957acb5b --- /dev/null +++ b/radio/ETHERNET/benetel/5g/CMakeLists.txt @@ -0,0 +1,16 @@ +pkg_check_modules(libdpdk REQUIRED libdpdk=20.05.0) + +add_library(benetel_5g MODULE + benetel.c + shared_buffers.c + low.c + low_dpdk.c + dpdk_driver.c +) + +SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") +target_include_directories(benetel_5g PRIVATE ${libdpdk_INCLUDE_DIRS}) +target_link_libraries(benetel_5g PRIVATE ${libdpdk_LIBRARIES}) +target_link_libraries(benetel_5g PRIVATE pthread dl rt m numa) +set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") +set_target_properties(benetel_5g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/benetel/CMakeLists.txt b/radio/ETHERNET/benetel/CMakeLists.txt new file mode 100644 index 0000000000..1a95d1ec2c --- /dev/null +++ b/radio/ETHERNET/benetel/CMakeLists.txt @@ -0,0 +1,9 @@ +add_boolean_option(OAI_BENETEL4G OFF "Activate OAI's Benetel 4G radio driver" OFF) +if(OAI_BENETEL4G) + add_subdirectory(4g) +endif() + +add_boolean_option(OAI_BENETEL5G OFF "Activate OAI's Benetel 5G radio driver" OFF) +if(OAI_BENETEL5G) + add_subdirectory(5g) +endif() diff --git a/radio/ETHERNET/USERSPACE/LIB/eth_raw.c b/radio/ETHERNET/eth_raw.c similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/eth_raw.c rename to radio/ETHERNET/eth_raw.c diff --git a/radio/ETHERNET/USERSPACE/LIB/eth_udp.c b/radio/ETHERNET/eth_udp.c similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/eth_udp.c rename to radio/ETHERNET/eth_udp.c diff --git a/radio/ETHERNET/USERSPACE/LIB/ethernet.md b/radio/ETHERNET/ethernet.md similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/ethernet.md rename to radio/ETHERNET/ethernet.md diff --git a/radio/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/radio/ETHERNET/ethernet_lib.c similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/ethernet_lib.c rename to radio/ETHERNET/ethernet_lib.c diff --git a/radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/radio/ETHERNET/ethernet_lib.h similarity index 100% rename from radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h rename to radio/ETHERNET/ethernet_lib.h diff --git a/radio/ETHERNET/USERSPACE/LIB/if_defs.h b/radio/ETHERNET/if_defs.h similarity index 98% rename from radio/ETHERNET/USERSPACE/LIB/if_defs.h rename to radio/ETHERNET/if_defs.h index 4df5014bc0..e2acf78a5c 100644 --- a/radio/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/radio/ETHERNET/if_defs.h @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file radio/ETHERNET/USERSPACE/LIB/if_defs.h +/*! \file radio/ETHERNET/if_defs.h * \brief * \author S. Sandeep Kumar, Raymond Knopp * \date 2016 diff --git a/radio/IRIS/CMakeLists.txt b/radio/IRIS/CMakeLists.txt new file mode 100644 index 0000000000..cd12bf09bb --- /dev/null +++ b/radio/IRIS/CMakeLists.txt @@ -0,0 +1,5 @@ +find_package(SoapySDR REQUIRED) + +add_library(oai_irisdevif MODULE iris_lib.cpp) +target_link_libraries(oai_irisdevif PRIVATE SoapySDR) +set_target_properties(oai_irisdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/IRIS/USERSPACE/LIB/iris_lib.cpp b/radio/IRIS/iris_lib.cpp similarity index 100% rename from radio/IRIS/USERSPACE/LIB/iris_lib.cpp rename to radio/IRIS/iris_lib.cpp diff --git a/radio/LMSSDR/CMakeLists.txt b/radio/LMSSDR/CMakeLists.txt new file mode 100644 index 0000000000..d93b84f6f1 --- /dev/null +++ b/radio/LMSSDR/CMakeLists.txt @@ -0,0 +1,5 @@ +find_package(LimeSuite REQUIRED) + +add_library(oai_lmssdrdevif MODULE lms_lib.cpp) +target_link_libraries(oai_lmssdrdevif LimeSuite ) +set_target_properties(oai_lmssdrdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/radio/LMSSDR/lms_lib.cpp similarity index 100% rename from radio/LMSSDR/USERSPACE/LIB/lms_lib.cpp rename to radio/LMSSDR/lms_lib.cpp diff --git a/radio/LMSSDR/USERSPACE/LIB/sodera_lib.cpp b/radio/LMSSDR/sodera_lib.cpp similarity index 100% rename from radio/LMSSDR/USERSPACE/LIB/sodera_lib.cpp rename to radio/LMSSDR/sodera_lib.cpp diff --git a/radio/USRP/CMakeLists.txt b/radio/USRP/CMakeLists.txt new file mode 100644 index 0000000000..bcdf2b6a23 --- /dev/null +++ b/radio/USRP/CMakeLists.txt @@ -0,0 +1,7 @@ +#find_package(Boost REQUIRED) +find_package(UHD REQUIRED) + +add_library(oai_usrpdevif MODULE usrp_lib.cpp) +#target_include_directories(oai_usrpdevif PRIVATE Boost::boost) +target_link_libraries(oai_usrpdevif uhd) +set_target_properties(oai_usrpdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/USRP/USERSPACE/LIB/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp similarity index 100% rename from radio/USRP/USERSPACE/LIB/usrp_lib.cpp rename to radio/USRP/usrp_lib.cpp diff --git a/radio/rfsimulator/CMakeLists.txt b/radio/rfsimulator/CMakeLists.txt new file mode 100644 index 0000000000..512383dcc2 --- /dev/null +++ b/radio/rfsimulator/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(rfsimulator MODULE + simulator.c + apply_channelmod.c + ../../openair1/PHY/TOOLS/signal_energy.c +) +target_link_libraries(rfsimulator PRIVATE SIMU) +target_link_libraries(rfsimulator PRIVATE asn1_nr_rrc asn1_lte_rrc) +set_target_properties(rfsimulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +add_executable(replay_node stored_node.c) +target_link_libraries (replay_node minimal_lib) From 557e3ba8003b8ac4404c83164077b4ecd7f0c86c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 05:56:37 +0200 Subject: [PATCH 48/87] Make ethernet off by default in build_oai If it was one, build_oai without parameters would attempt to build the ethernet library. However, this is unexpected, and will lead to an error (as it is by default off in CMake). Set it to off, and build it where required. --- cmake_targets/build_oai | 2 +- docker/Dockerfile.build.rhel9 | 2 +- docker/Dockerfile.build.rocky | 2 +- docker/Dockerfile.build.ubuntu20 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 02379e197c..63bc83845d 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -41,7 +41,7 @@ XFORMS="True" SKIP_SHARED_LIB_FLAG="False" PRINT_STATS="False" HW="None" -TP="Ethernet" +TP="None" EPC=0 VERBOSE_CI=0 VERBOSE_COMPILE=0 diff --git a/docker/Dockerfile.build.rhel9 b/docker/Dockerfile.build.rhel9 index 3aa94d3ade..1a12843ea4 100644 --- a/docker/Dockerfile.build.rhel9 +++ b/docker/Dockerfile.build.rhel9 @@ -35,4 +35,4 @@ COPY . . RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP --verbose-ci --noavx512 -c + ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP -t Ethernet --verbose-ci --noavx512 -c diff --git a/docker/Dockerfile.build.rocky b/docker/Dockerfile.build.rocky index 1522844601..468869b277 100644 --- a/docker/Dockerfile.build.rocky +++ b/docker/Dockerfile.build.rocky @@ -35,4 +35,4 @@ COPY . . RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP --verbose-ci --noavx512 -c + ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP -t Ethernet --verbose-ci --noavx512 -c diff --git a/docker/Dockerfile.build.ubuntu20 b/docker/Dockerfile.build.ubuntu20 index fd4de7c22a..8186ca06f4 100644 --- a/docker/Dockerfile.build.ubuntu20 +++ b/docker/Dockerfile.build.ubuntu20 @@ -35,4 +35,4 @@ COPY . . RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" -w USRP --verbose-ci --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror + ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" -w USRP -t Ethernet --verbose-ci --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror From b896da85e7ca047d25e0d8a388b59e8a2450c719 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 03:41:10 +0200 Subject: [PATCH 49/87] Harmonize build_oai color output --- cmake_targets/build_oai | 7 +++---- cmake_targets/tools/build_helper | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 63bc83845d..b1debfbf7d 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -448,11 +448,11 @@ function main() { # Setting and printing OAI envs, we should check here # ####################################################### - cecho "OPENAIR_DIR = $OPENAIR_DIR" $green + echo "OPENAIR_DIR = $OPENAIR_DIR" if [ "$CLEAN_ALL" = "1" ] ; then clean_all_files - echo_info "Erased all previously producted files" + echo "Erased all previously producted files" fi dlog=$OPENAIR_DIR/cmake_targets/log @@ -512,11 +512,10 @@ function main() { # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, # e.g., cmake_targets/ran_build/build, hence the ../../.. CMAKE_CMD="$CMAKE_CMD ../../.." - echo_info "running $CMAKE_CMD" + echo_info "Running \"$CMAKE_CMD\"" eval $CMAKE_CMD if [[ "$execlist" != "" ]]; then - echo_info "Compiling $execlist..." compilations $BUILD_DIR all.txt $execlist fi diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 52ae420081..9d1e03dec4 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -222,6 +222,7 @@ compilations() { shift 1 local targets=$@ cd $OPENAIR_DIR/cmake_targets/$dir/build + cecho "Running \"$MAKE_CMD $targets\"" $green echo_info "Log file for compilation is being written to: $dlog/$logfile" set +e { From 4db08dc68a281fa065d266c5e67b5a498108be97 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 04:13:32 +0200 Subject: [PATCH 50/87] Simplify compilations build helper Instead of using ninja/make directly, there is a cmake command option to trigger the build using whatever build tool has been configured. Use it; if there is a mismatch, there will also be a clearer cmake error. Remove build_oai's --build-coverity: we don't use it, and it can trivially be added if required (probably, most users would run it by hand anyway). Add an error if the compilations function is not called with the right noumber of arguments. --- cmake_targets/build_oai | 22 +--------------------- cmake_targets/tools/build_helper | 26 ++++++++------------------ 2 files changed, 9 insertions(+), 39 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index b1debfbf7d..8c9dbccda8 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -49,11 +49,9 @@ RUN_GROUP=0 TEST_CASE_GROUP="" BUILD_DIR=ran_build BUILD_DOXYGEN=0 -BUILD_COVERITY_SCAN=0 DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" -MAKE_CMD=make BUILD_ECLIPSE=0 NR="False" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer" @@ -340,10 +338,6 @@ function main() { BUILD_DOXYGEN=1 echo_info "Will build doxygen support" shift;; - --build-coverity-scan) - BUILD_COVERITY_SCAN=1 - echo_info "Will build Coverity-Scan objects for upload" - shift;; --disable-T-Tracer) CMAKE_CMD="$CMAKE_CMD -DT_TRACER=False" echo_info "Disabling the T tracer" @@ -409,7 +403,6 @@ function main() { shift;; --ninja) CMAKE_CMD="$CMAKE_CMD -GNinja" - MAKE_CMD=ninja shift;; --sanitize) CMAKE_CMD="$CMAKE_CMD -DSANITIZE_ADDRESS=True -DSANITIZE_UNDEFINED=True" @@ -431,19 +424,6 @@ function main() { esac done - ################################### - # Check if cov-build is installed # - ################################### - if [ "$BUILD_COVERITY_SCAN" == "1" ] ; then - echo_info "Checking cov-build is installed" - IS_INSTALLED=`which cov-build | grep -c cov-build || true` - if [ $IS_INSTALLED -eq 1 ] ; then - echo_info "Found cov-build" - else - echo_fatal "Did NOT find cov-build in PATH!" - fi - fi - ####################################################### # Setting and printing OAI envs, we should check here # ####################################################### @@ -612,7 +592,7 @@ function main() { echo_info "Doxygen generation log is located here: $doxygen_log" echo_info "Generating Doxygen files....please wait" ( - $MAKE_CMD doc + cmake --build . --target doc ) >& $doxygen_log fi diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 9d1e03dec4..d12c63486b 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -216,36 +216,26 @@ check_errors() { } compilations() { + [[ $# -gt 2 ]] || echo_fatal "compilations needs more than three arguments" local dir=$1 shift 1 local logfile=$1 shift 1 local targets=$@ + local verbose=$([ "$VERBOSE_COMPILE" == "1" ] && echo "-v" || echo "") + echo cd $OPENAIR_DIR/cmake_targets/$dir/build cd $OPENAIR_DIR/cmake_targets/$dir/build - cecho "Running \"$MAKE_CMD $targets\"" $green - echo_info "Log file for compilation is being written to: $dlog/$logfile" + echo_info "Running \"cmake --build . $verbose --target $targets -- -j$(nproc)\"" $green + echo "Log file for compilation is being written to: $dlog/$logfile" set +e { - if [ "$BUILD_COVERITY_SCAN" == "1" ]; then - COV_SCAN_PREFIX="cov-build --dir cov-int" - else - COV_SCAN_PREFIX="" - fi - if [ "$MAKE_CMD" != "" ]; then - $MAKE_CMD $targets - else - if [ "$VERBOSE_COMPILE" == "1" ]; then - $COV_SCAN_PREFIX make -j`nproc` $targets VERBOSE=$VERBOSE_COMPILE - else - $COV_SCAN_PREFIX make -j`nproc` $targets - fi - fi + cmake --build . $verbose --target $targets -- -j$(nproc) ret=$? } > $dlog/$logfile 2>&1 if [ "$VERBOSE_CI" == "1" ]; then - echo_info "====== Start of log for $logfile ======" + echo "====== Start of log for $logfile ======" cat $dlog/$logfile - echo_info "====== End of log for $logfile ======" + echo "====== End of log for $logfile ======" fi check_warnings "$dlog/$logfile" if [[ $ret -eq 0 ]]; then From b90a469131adde6e8eaba05c1e99eb89b5f724b2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 07:55:15 +0200 Subject: [PATCH 51/87] Correctly build AW2S in dockerfile --- docker/Dockerfile.gNB.aw2s.rhel9 | 4 ++-- docker/Dockerfile.gNB.aw2s.rocky | 4 ++-- docker/Dockerfile.gNB.aw2s.ubuntu20 | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/Dockerfile.gNB.aw2s.rhel9 b/docker/Dockerfile.gNB.aw2s.rhel9 index 6985ab2108..c6bd086827 100644 --- a/docker/Dockerfile.gNB.aw2s.rhel9 +++ b/docker/Dockerfile.gNB.aw2s.rhel9 @@ -34,8 +34,8 @@ COPY ./libori.so /usr/local/lib # build AW2S fronthaul lib WORKDIR /oai-ran RUN /bin/sh oaienv && \ - cd cmake_targets/ran_build/build && \ - ninja aw2sori_transpro + cd cmake_targets/ && \ + ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable FROM registry.access.redhat.com/ubi9/ubi:latest as oai-gnb-aw2s diff --git a/docker/Dockerfile.gNB.aw2s.rocky b/docker/Dockerfile.gNB.aw2s.rocky index 26eabc535f..f13a6f244f 100644 --- a/docker/Dockerfile.gNB.aw2s.rocky +++ b/docker/Dockerfile.gNB.aw2s.rocky @@ -35,8 +35,8 @@ COPY ./libori.so /usr/local/lib # build AW2S fronthaul lib WORKDIR /oai-ran RUN /bin/sh oaienv && \ - cd cmake_targets/ran_build/build && \ - ninja aw2sori_transpro + cd cmake_targets/ && \ + ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable FROM $BASE_IMAGE as oai-gnb-aw2s diff --git a/docker/Dockerfile.gNB.aw2s.ubuntu20 b/docker/Dockerfile.gNB.aw2s.ubuntu20 index 642076163b..321876638d 100644 --- a/docker/Dockerfile.gNB.aw2s.ubuntu20 +++ b/docker/Dockerfile.gNB.aw2s.ubuntu20 @@ -34,8 +34,8 @@ COPY ./libori.so /usr/local/lib/ # build AW2S fronthaul lib WORKDIR /oai-ran RUN /bin/sh oaienv && \ - cd cmake_targets/ran_build/build && \ - ninja aw2sori_transpro + cd cmake_targets/ && \ + ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable FROM ubuntu:bionic as oai-gnb-aw2s From 0163a52b7adf79a73d904db05fdd8ba02ab57079 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 18 Jun 2023 10:40:32 +0200 Subject: [PATCH 52/87] Add libcblas for docker containers --- docker/Dockerfile.eNB.rhel9 | 1 + docker/Dockerfile.gNB.aw2s.rhel9 | 1 + docker/Dockerfile.gNB.rhel9 | 1 + docker/Dockerfile.lteRU.rhel9 | 1 + docker/Dockerfile.lteUE.rhel9 | 1 + docker/Dockerfile.nr-cuup.rhel9 | 1 + docker/Dockerfile.nrUE.rhel9 | 1 + docker/Dockerfile.phySim.rhel9 | 1 + 8 files changed, 8 insertions(+) diff --git a/docker/Dockerfile.eNB.rhel9 b/docker/Dockerfile.eNB.rhel9 index daf2c6c022..7883f8560a 100644 --- a/docker/Dockerfile.eNB.rhel9 +++ b/docker/Dockerfile.eNB.rhel9 @@ -72,6 +72,7 @@ COPY --from=enb-build \ COPY --from=enb-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libboost_chrono.so.1.75.0 \ diff --git a/docker/Dockerfile.gNB.aw2s.rhel9 b/docker/Dockerfile.gNB.aw2s.rhel9 index c6bd086827..863f126be6 100644 --- a/docker/Dockerfile.gNB.aw2s.rhel9 +++ b/docker/Dockerfile.gNB.aw2s.rhel9 @@ -75,6 +75,7 @@ COPY --from=gnb-base \ /lib64/libconfig.so.11 \ /lib64/libforms.so.2 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/ diff --git a/docker/Dockerfile.gNB.rhel9 b/docker/Dockerfile.gNB.rhel9 index 74916d7888..fc6a6c5975 100644 --- a/docker/Dockerfile.gNB.rhel9 +++ b/docker/Dockerfile.gNB.rhel9 @@ -73,6 +73,7 @@ COPY --from=gnb-base \ /lib64/libconfig.so.11 \ /lib64/libforms.so.2 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libboost_chrono.so.1.75.0 \ diff --git a/docker/Dockerfile.lteRU.rhel9 b/docker/Dockerfile.lteRU.rhel9 index e0b126c9b7..81741441ab 100644 --- a/docker/Dockerfile.lteRU.rhel9 +++ b/docker/Dockerfile.lteRU.rhel9 @@ -66,6 +66,7 @@ COPY --from=ru-build \ COPY --from=ru-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libboost_chrono.so.1.75.0 \ diff --git a/docker/Dockerfile.lteUE.rhel9 b/docker/Dockerfile.lteUE.rhel9 index 2b74ed0b0b..1ba07477c1 100644 --- a/docker/Dockerfile.lteUE.rhel9 +++ b/docker/Dockerfile.lteUE.rhel9 @@ -73,6 +73,7 @@ COPY --from=lte-ue-build \ COPY --from=lte-ue-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libboost_chrono.so.1.75.0 \ diff --git a/docker/Dockerfile.nr-cuup.rhel9 b/docker/Dockerfile.nr-cuup.rhel9 index 9a45f7156a..5ae63a0e48 100644 --- a/docker/Dockerfile.nr-cuup.rhel9 +++ b/docker/Dockerfile.nr-cuup.rhel9 @@ -61,6 +61,7 @@ COPY --from=gnb-build \ COPY --from=gnb-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/ diff --git a/docker/Dockerfile.nrUE.rhel9 b/docker/Dockerfile.nrUE.rhel9 index 53b179a935..445cc807b8 100644 --- a/docker/Dockerfile.nrUE.rhel9 +++ b/docker/Dockerfile.nrUE.rhel9 @@ -78,6 +78,7 @@ COPY --from=nr-ue-build \ COPY --from=nr-ue-base \ /lib64/libconfig.so.11 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/liblapacke.so.3 \ /lib64/libforms.so.2 \ diff --git a/docker/Dockerfile.phySim.rhel9 b/docker/Dockerfile.phySim.rhel9 index 145c3b3c2c..223a5bb68a 100644 --- a/docker/Dockerfile.phySim.rhel9 +++ b/docker/Dockerfile.phySim.rhel9 @@ -83,6 +83,7 @@ COPY --from=phy-sim-build \ /lib64/libXau.so.6 \ /lib64/libforms.so.2 \ /lib64/libblas.so.3 \ + /lib64/libcblas.so.3 \ /lib64/liblapack.so.3 \ /lib64/libexslt.so.0 \ /lib64/libxslt.so.1 \ From 00e3c5acddeb242eff551645c0fe3762308f92ed Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 20 Jun 2023 08:52:31 +0200 Subject: [PATCH 53/87] Run ldconfig to find libparams_libconfig.so in nr-cuup container --- docker/Dockerfile.nr-cuup.ubuntu20 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/Dockerfile.nr-cuup.ubuntu20 b/docker/Dockerfile.nr-cuup.ubuntu20 index f26be9c21c..222a4dd361 100644 --- a/docker/Dockerfile.nr-cuup.ubuntu20 +++ b/docker/Dockerfile.nr-cuup.ubuntu20 @@ -52,6 +52,8 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ /usr/local/lib/ +RUN ldconfig && ldd /opt/oai-gnb/bin/nr-cuup + # Create directory for configuration files WORKDIR /opt/oai-gnb/etc From 639ee53578e426751b4244961e42751519315fde Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 13:08:28 +0200 Subject: [PATCH 54/87] Configuration files for gNB: cleanup of config file --- .../conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index cffa15e110..a1e66c7ade 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -229,15 +229,6 @@ RUs = ( } ); -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"; -} -); - security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen From cde71c8d0f379e5ffa82aea4a826173d2c9baf6c Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 13:15:36 +0200 Subject: [PATCH 55/87] Add pipeline to Jenkins container parent --- ci-scripts/Jenkinsfile-GitLab-Container | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 8d52bc9f8e..c066333eaa 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -464,6 +464,26 @@ pipeline { } } } + stage ("SA-OAIUE-CN5G") { + when { expression {do5Gtest} } + steps { + script { + triggerCN5GSlaveJob ('RAN-SA-OAIUE-CN5G', 'RAN-SA-OAIUE-CN5G') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-SA-OAIUE-CN5G') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } } } stage ("DockerHub-Push") { From 288e62898b0bdb0569111d25914cc00cd064a2d2 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 13:20:07 +0200 Subject: [PATCH 56/87] Update of UE infra file - removal of obelix UE, network script renamed --- ci-scripts/ci_ueinfra.yaml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index 6bfcc86af2..2d19af7729 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -121,16 +121,10 @@ amarisoft_ue_10: UENetworkScript: ip netns exec ue10 ip a show dev pdn0 CmdPrefix: ip netns exec ue10 MTU: 1500 - -oai_ue_obelix: - Host: obelix - UENetworkScript: ip a show dev oaitun_ue1 - IF: oaitun_ue1 - oai_ue_caracal: Host: caracal AttachScript: 'docker start oai-nr-ue' DetachScript: 'docker stop oai-nr-ue' - UENetworkScript: ip a show dev oaitun_ue1 + NetworkScript: ip a show dev oaitun_ue1 IF: oaitun_ue1 MTU: 1500 From 1db0fb07ab7ea6bc951d422372649f45f8743eb6 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 13:28:38 +0200 Subject: [PATCH 57/87] Configuration files for nrUE: update of uesoftmodem options --- ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml index 2a12e4cd51..038ea51532 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml @@ -8,7 +8,7 @@ services: #entrypoint: /bin/bash -c "sleep infinity" environment: TZ: Europe/Paris - USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.20.2 -r 106 --numerology 1 --band 78 -C 3511200000 --sa --ue-fo-compensation --nokrnmod 1 --ue-txgain 0 --ue-rxgain 65 --tune-offset 20000000 --log_config.global_log_options level,nocolor,time --uicc0.imsi 208970000000111 --uicc0.nssai_sd 16777215 + USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.20.2 -r 106 --numerology 1 --band 78 -C 3511200000 --sa --ue-fo-compensation --ue-rxgain 65 --tune-offset 20000000 --log_config.global_log_options level,nocolor,time --uicc0.imsi 208970000000111 --uicc0.nssai_sd 16777215 volumes: - ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: From 70ad480a291f05dfb1511f8e84cf287c57da1292 Mon Sep 17 00:00:00 2001 From: mir Date: Fri, 19 May 2023 16:48:02 +0200 Subject: [PATCH 58/87] Add basic E2 agent through git submodule - Add E2 agent that leverages FlexRIC e2ap library - Add documentation in openair2/E2AP/README.md - Currently, statistics exported are random --- .gitmodules | 4 + CMakeLists.txt | 30 +++ cmake_targets/build_oai | 6 + executables/nr-softmodem.c | 53 +++++ openair2/E2AP/CMakeLists.txt | 98 +++++++++ openair2/E2AP/RAN_FUNCTION/CMakeLists.txt | 12 ++ .../RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt | 17 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c | 24 +++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h | 13 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c | 24 +++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h | 12 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c | 31 +++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h | 13 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c | 25 +++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h | 13 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c | 47 +++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h | 13 ++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c | 39 ++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h | 13 ++ .../E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt | 7 + openair2/E2AP/RAN_FUNCTION/O-RAN/README.md | 3 + .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 189 ++++++++++++++++++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h | 13 ++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c | 108 ++++++++++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h | 15 ++ openair2/E2AP/RAN_FUNCTION/init_ran_func.c | 73 +++++++ openair2/E2AP/RAN_FUNCTION/init_ran_func.h | 32 +++ openair2/E2AP/README.md | 153 ++++++++++++++ openair2/E2AP/e2_agent_arg.h | 35 ++++ openair2/E2AP/flexric | 1 + openair2/ENB_APP/enb_config.c | 22 ++ openair2/ENB_APP/enb_config.h | 5 + openair2/ENB_APP/enb_paramdef.h | 29 +++ openair2/GNB_APP/gnb_config.c | 20 ++ openair2/GNB_APP/gnb_config.h | 5 + .../gnb.sa.band78.fr1.106PRB.usrpb210.conf | 5 + 36 files changed, 1202 insertions(+) create mode 100644 .gitmodules create mode 100644 openair2/E2AP/CMakeLists.txt create mode 100644 openair2/E2AP/RAN_FUNCTION/CMakeLists.txt create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c create mode 100644 openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/README.md create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c create mode 100644 openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h create mode 100644 openair2/E2AP/RAN_FUNCTION/init_ran_func.c create mode 100644 openair2/E2AP/RAN_FUNCTION/init_ran_func.h create mode 100644 openair2/E2AP/README.md create mode 100644 openair2/E2AP/e2_agent_arg.h create mode 160000 openair2/E2AP/flexric diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..6d85cbb418 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "openair2/E2AP/flexric"] + path = openair2/E2AP/flexric + url = https://gitlab.eurecom.fr/mosaic5g/flexric.git + branch = remotes/origin/mir_dev diff --git a/CMakeLists.txt b/CMakeLists.txt index 110a10bf04..c495fb52cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,6 +328,18 @@ endif() # asn1c skeletons need this add_definitions(-DHAVE_NETINET_IN_H) +######################### +##### E2 AGENT +######################### +#add_boolean_option() does not work -- why? +set(E2_AGENT "OFF" CACHE STRING "O-RAN-compliant E2 Agent") +set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF") + +if(E2_AGENT) + set(E2AP_DIR ${OPENAIR2_DIR}/E2AP) + add_subdirectory ("${E2AP_DIR}") +endif() + ################################################## # ASN.1 grammar C code generation & dependencies # ################################################## @@ -1567,6 +1579,11 @@ add_library(L2 ) target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap) target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +if(E2_AGENT) + target_link_libraries(L2 PUBLIC e2_agent e2_ran_func) + target_compile_definitions(L2 PRIVATE E2_AGENT) +endif() + add_library(MAC_NR ${MAC_NR_SRC}) target_link_libraries(MAC_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) @@ -1597,6 +1614,11 @@ add_library(e1_pdcp_if target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap) +if(E2_AGENT) + target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func) + target_compile_definitions(L2_NR PRIVATE E2_AGENT) +endif() + add_library(L2_LTE_NR ${L2_RRC_SRC} @@ -2174,6 +2196,10 @@ target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYP target_link_libraries(lte-softmodem PRIVATE ${T_LIB}) target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +if(E2_AGENT) + target_compile_definitions(lte-softmodem PRIVATE E2_AGENT) +endif() + add_executable(oairu ${OPENAIR_DIR}/executables/lte-ru.c ${OPENAIR_DIR}/executables/ru_control.c @@ -2285,6 +2311,10 @@ 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) +if(E2_AGENT) + target_compile_definitions(nr-softmodem PRIVATE E2_AGENT) +endif() + add_executable(nr-cuup executables/nr-cuup.c diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 1d4c55da20..0639385a1a 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -78,6 +78,8 @@ Options: Pass the supplied option verbatim to cmake. -d | --build-dir Sets build directory (will be /cmake_targets//build) +--build-e2 + Enable the the E2 Agent -I | --install-external-packages Installs required packages such as LibXML, asn1.1 compiler, ... This option will require root password @@ -197,6 +199,10 @@ function main() { -d | --build-dir) BUILD_DIR=$2 shift 2;; + --build-e2 ) + CMAKE_CMD="$CMAKE_CMD -DE2_AGENT=ON" + shift + ;; -I | --install-external-packages) INSTALL_EXTERNAL=1 echo_info "Will install external packages" diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 13ea4b94ee..8f55024ef4 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -82,6 +82,12 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "openair2/E1AP/e1ap_common.h" #include "openair2/E1AP/e1ap_api.h" +#ifdef E2_AGENT +#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h" +#include "openair2/E2AP/RAN_FUNCTION/init_ran_func.h" +#endif + + pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex @@ -683,6 +689,53 @@ int main( int argc, char **argv ) { config_sync_var=0; + + + +#ifdef E2_AGENT + +////////////////////////////////// +////////////////////////////////// +//// Init the E2 Agent + + sm_io_ag_ran_t io = init_ran_func_ag(); + fr_args_t args = init_fr_args(0, NULL); + + // OAI Wrapper + e2_agent_args_t oai_args = RCconfig_NR_E2agent(); + if(oai_args.sm_dir != NULL) + memcpy(args.libs_dir, oai_args.sm_dir, 128); + + sleep(1); + const gNB_RRC_INST* rrc = RC.nrrrc[0]; + assert(rrc != NULL && "rrc cannot be NULL"); + + const int mcc = rrc->configuration.mcc[0]; + const int mnc = rrc->configuration.mnc[0]; + const int mnc_digit_len = rrc->configuration.mnc_digit_length[0]; + const ngran_node_t node_type = rrc->node_type; + int nb_id = 0; + int cu_du_id = 0; + if (node_type == ngran_gNB) { + nb_id = rrc->configuration.cell_identity; + } else if (node_type == ngran_gNB_DU) { + cu_du_id = rrc->node_id + 1; // Hack to avoid been 0 + nb_id = rrc->configuration.cell_identity; + } else if (node_type == ngran_gNB_CU) { + cu_du_id = rrc->node_id + 1; + nb_id = rrc->configuration.cell_identity; + } else { + LOG_E(NR_RRC, "not supported ran type detect\n"); + } + + printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id); + + init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args); +// } + +#endif // E2_AGENT + + if (NFAPI_MODE==NFAPI_MODE_PNF) { wait_nfapi_init("main?"); } diff --git a/openair2/E2AP/CMakeLists.txt b/openair2/E2AP/CMakeLists.txt new file mode 100644 index 0000000000..865eac5ffa --- /dev/null +++ b/openair2/E2AP/CMakeLists.txt @@ -0,0 +1,98 @@ +# Check that the submodule exists or init+update if not +if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/flexric/CMakeLists.txt) + message(STATUS "E2AP submoduled not detected, therefore $git submodule init && git submodule update.") + execute_process(COMMAND git submodule init) + execute_process(COMMAND git submodule update) +else() + message(STATUS "E2AP submodule detected.") +endif() + +if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/flexric/CMakeLists.txt) + message(FATAL_ERROR "The submodules for E2 agent were not downloaded!") +endif() + + +set(BUILDING_LIBRARY "STATIC" CACHE STRING "Static or dynamic library") +set_property(CACHE BUILDING_LIBRARY PROPERTY STRINGS "STATIC" "DYNAMIC") +message(STATUS "Selected LIBRARY TYPE: ${BUILDING_LIBRARY}") + + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +if(BUILDING_LIBRARY STREQUAL "STATIC") + add_compile_options("-W;-Wall;-Wextra;-g;-Wno-unused-result;") +elseif(BUILDING_LIBRARY STREQUAL "DYNAMIC") + # -fPIC flag + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + add_compile_options("-W;-Wall;-Wextra;-g") +else() + message(FATAL_ERROR "Unknown building type. Either choose a static or a dynamic library") +endif() + + +set(E2AP_ENCODING "ASN" CACHE STRING "The E2AP encoding to use") +set_property(CACHE E2AP_ENCODING PROPERTY STRINGS "ASN" "FLATBUFFERS") +message(STATUS "Selected E2AP_ENCODING: ${E2AP_ENCODING}") + + +####### +## Service Models +####### + +add_definitions(-DSERVICE_MODEL_DIR_PATH="${SM_DIR_PATH}/") + +# KPM service Model encoding definitions +set(SM_ENCODING_KPM "ASN" CACHE STRING "The KPM SM encoding to use") +set_property(CACHE SM_ENCODING_KPM PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected KPM SM_ENCODING: ${SM_ENCODING_KPM}") + +# RC service Model encoding definitions +set(SM_ENCODING_RC "ASN" CACHE STRING "The RC SM encoding to use") +set_property(CACHE SM_ENCODING_RC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected RC SM_ENCODING: ${SM_ENCODING_RC}") + +# MAC Service Model +set(SM_ENCODING_MAC "PLAIN" CACHE STRING "The MAC SM encoding to use") +set_property(CACHE SM_ENCODING_MAC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected MAC SM_ENCODING: ${SM_ENCODING_MAC}") + +# RLC Service Model +set(SM_ENCODING_RLC "PLAIN" CACHE STRING "The RLC SM encoding to use") +set_property(CACHE SM_ENCODING_RLC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected RLC SM_ENCODING: ${SM_ENCODING_RLC}") + +# PDCP Service Model +set(SM_ENCODING_PDCP "PLAIN" CACHE STRING "The PDCP SM encoding to use") +set_property(CACHE SM_ENCODING_PDCP PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected PDCP SM_ENCODING: ${SM_ENCODING_PDCP}") + +# SLICE Service Model +set(SM_ENCODING_SLICE "PLAIN" CACHE STRING "The SLICE SM encoding to use") +set_property(CACHE SM_ENCODING_SLICE PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS") +message(STATUS "Selected SLICE SM_ENCODING: ${SM_ENCODING_SLICE}") + +# GTP Service Model +set(SM_ENCODING_GTP "PLAIN" CACHE STRING "The GTP SM encoding to use") +set_property(CACHE SM_ENCODING_GTP PROPERTY STRINGS "PLAIN") +message(STATUS "Selected GTP SM_ENCODING: ${SM_ENCODING_GTP}") + +######## +### Flatbuffer +######## +set(FlatCC_INCLUDE_DIR "" CACHE STRING "The Flatbuffers include directory") +set(FlatCC_LIB_DIR "" CACHE STRING "The Flatbuffers lib directory") + +if(E2AP_ENCODING STREQUAL "FLATBUFFERS") + find_library(FlatCC + NAMES flatccrt_d + HINTS ${FlatCC_LIB_DIR} + ) +endif() + +include_directories(flexric/src) +add_subdirectory(flexric/src/agent) +add_subdirectory(flexric/src/lib) +add_subdirectory(flexric/src/sm) +add_subdirectory(flexric/src/util) +add_subdirectory(RAN_FUNCTION) + diff --git a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt new file mode 100644 index 0000000000..ef92ddb0be --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt @@ -0,0 +1,12 @@ +add_subdirectory(CUSTOMIZED) +add_subdirectory(O-RAN) + +add_library(e2_ran_func STATIC + init_ran_func.c + ) + +target_link_libraries(e2_ran_func + PUBLIC + e2_ran_func_cust + e2_ran_func_oran + ) diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt new file mode 100644 index 0000000000..b165e1589b --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(e2_ran_func_cust STATIC + ran_func_gtp.c + ran_func_mac.c + ran_func_pdcp.c + ran_func_rlc.c + ran_func_slice.c + ran_func_tc.c + # For testing purposes + ../../flexric/test/rnd/fill_rnd_data_gtp.c + ../../flexric/test/rnd/fill_rnd_data_tc.c + ../../flexric/test/rnd/fill_rnd_data_mac.c + ../../flexric/test/rnd/fill_rnd_data_rlc.c + ../../flexric/test/rnd/fill_rnd_data_pdcp.c + ../../flexric/test/rnd/fill_rnd_data_slice.c + ../../flexric/src/util/time_now_us.c + ) + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c new file mode 100644 index 0000000000..bd8b8b5881 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -0,0 +1,24 @@ +#include "ran_func_gtp.h" +#include "../../flexric/test/rnd/fill_rnd_data_gtp.h" +#include + +void read_gtp_sm(void * data) +{ + assert(data != NULL); + + gtp_ind_data_t* gtp = (gtp_ind_data_t*)(data); + fill_gtp_ind_data(gtp); +} + +void read_gtp_setup_sm(void* data) +{ + assert(data != NULL); + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_gtp_sm(void const* src) +{ + assert(src != NULL); + assert(0 !=0 && "Not supported"); +} + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h new file mode 100644 index 0000000000..6e88200401 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_gtp_sm(void*); + +void read_gtp_setup_sm(void*); + +sm_ag_if_ans_t write_ctrl_gtp_sm(void const*); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c new file mode 100644 index 0000000000..4b150e71ed --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -0,0 +1,24 @@ +#include "ran_func_mac.h" +#include "../../flexric/test/rnd/fill_rnd_data_mac.h" +#include + +void read_mac_sm(void* data) +{ + assert(data != NULL); + + mac_ind_data_t* mac = (mac_ind_data_t*)data; + fill_mac_ind_data(mac); +} + +void read_mac_setup_sm(void* data) +{ + assert(data != NULL); + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_mac_sm(void const* data) +{ + assert(data != NULL); + assert(0 !=0 && "Not supported"); +} + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h new file mode 100644 index 0000000000..26ae184b37 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h @@ -0,0 +1,12 @@ +#ifndef SM_MAC_READ_WRITE_AGENT_H +#define SM_MAC_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_mac_sm(void*); + +void read_mac_setup_sm(void*); + +sm_ag_if_ans_t write_ctrl_mac_sm(void const*); + +#endif diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c new file mode 100644 index 0000000000..14bb2400f7 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c @@ -0,0 +1,31 @@ +#include "ran_func_pdcp.h" +#include "../../flexric/test/rnd/fill_rnd_data_pdcp.h" +#include + +void read_pdcp_sm(void* data) +{ + assert(data != NULL); + //assert(data->type == PDCP_STATS_V0); + + pdcp_ind_data_t* pdcp = (pdcp_ind_data_t*)data; + fill_pdcp_ind_data(pdcp); +} + +void read_pdcp_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == PDCP_AGENT_IF_E2_SETUP_ANS_V0 ); + + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_pdcp_sm(void const* data) +{ + assert(data != NULL); +// assert(data->type == PDCP_CTRL_REQ_V0 ); + assert(0 !=0 && "Not supported"); + sm_ag_if_ans_t ans = {0}; + return ans; +} + + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h new file mode 100644 index 0000000000..12dcaaf16b --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_pdcp_sm(void*); + +void read_pdcp_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_pdcp_sm(void const* data); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c new file mode 100644 index 0000000000..9a2a661175 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c @@ -0,0 +1,25 @@ +#include "ran_func_rlc.h" +#include "../../flexric/test/rnd/fill_rnd_data_rlc.h" + +void read_rlc_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == RLC_STATS_V0); + + rlc_ind_data_t* rlc = (rlc_ind_data_t*)data; + fill_rlc_ind_data(rlc); +} + +void read_rlc_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == RLC_AGENT_IF_E2_SETUP_ANS_V0 ); + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_rlc_sm(void const* data) +{ + (void)data; + assert(0!=0 && "Not supported"); +} + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h new file mode 100644 index 0000000000..c442cd7825 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_rlc_sm(void*); + +void read_rlc_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_rlc_sm(void const* data); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c new file mode 100644 index 0000000000..764cddf28f --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c @@ -0,0 +1,47 @@ +#include "ran_func_slice.h" +#include "../../flexric/test/rnd/fill_rnd_data_slice.h" +#include +#include + +void read_slice_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == SLICE_STATS_V0); + + slice_ind_data_t* slice = (slice_ind_data_t*)data; + fill_slice_ind_data(slice); +} + +void read_slice_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == SLICE_AGENT_IF_E2_SETUP_ANS_V0 ); + + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_slice_sm(void const* data) +{ + assert(data != NULL); +// assert(data->type == SLICE_CTRL_REQ_V0); + + slice_ctrl_req_data_t const* slice_req_ctrl = (slice_ctrl_req_data_t const* )data; // &data->slice_req_ctrl; + slice_ctrl_msg_t const* msg = &slice_req_ctrl->msg; + + if(msg->type == SLICE_CTRL_SM_V0_ADD){ + printf("[E2 Agent]: SLICE CONTROL ADD rx\n"); + } else if (msg->type == SLICE_CTRL_SM_V0_DEL){ + printf("[E2 Agent]: SLICE CONTROL DEL rx\n"); + } else if (msg->type == SLICE_CTRL_SM_V0_UE_SLICE_ASSOC){ + printf("[E2 Agent]: SLICE CONTROL ASSOC rx\n"); + } else { + assert(0!=0 && "Unknown msg_type!"); + } + + sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0}; + ans.ctrl_out.type = SLICE_AGENT_IF_CTRL_ANS_V0; + return ans; + +} + + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h new file mode 100644 index 0000000000..0c26d63120 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_slice_sm(void*); + +void read_slice_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_slice_sm(void const* data); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c new file mode 100644 index 0000000000..ca3997da7b --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c @@ -0,0 +1,39 @@ +#include "ran_func_tc.h" +#include "../../flexric/test/rnd/fill_rnd_data_tc.h" +#include + +void read_tc_sm(void* data) +{ + assert(data != NULL); + //assert(data->type == TC_STATS_V0); + + tc_ind_data_t* tc = (tc_ind_data_t*)data; + fill_tc_ind_data(tc); +} + +void read_tc_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == TC_AGENT_IF_E2_SETUP_ANS_V0 ); + + assert(0 !=0 && "Not supported"); +} + +sm_ag_if_ans_t write_ctrl_tc_sm(void const* data) +{ + assert(data != NULL); +// assert(data->type == TC_CTRL_REQ_V0 ); + + tc_ctrl_req_data_t const* ctrl = (tc_ctrl_req_data_t const*)data; + + tc_ctrl_msg_e const t = ctrl->msg.type; + + assert(t == TC_CTRL_SM_V0_CLS || t == TC_CTRL_SM_V0_PLC + || t == TC_CTRL_SM_V0_QUEUE || t ==TC_CTRL_SM_V0_SCH + || t == TC_CTRL_SM_V0_SHP || t == TC_CTRL_SM_V0_PCR); + + sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0}; + ans.ctrl_out.type = TC_AGENT_IF_CTRL_ANS_V0; + return ans; +} + diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h new file mode 100644 index 0000000000..526d564b1b --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_TC_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_TC_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_tc_sm(void*); + +void read_tc_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_tc_sm(void const* data); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt new file mode 100644 index 0000000000..49624dc302 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(e2_ran_func_oran STATIC + ran_func_kpm.c + ran_func_rc.c + # For testing purposes + ../../flexric/test/rnd/fill_rnd_data_kpm.c + ../../flexric/test/rnd/fill_rnd_data_rc.c + ) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md b/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md new file mode 100644 index 0000000000..358f22a692 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md @@ -0,0 +1,3 @@ +RAN Functions as defined by O-RAN + + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c new file mode 100644 index 0000000000..daedef70e7 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -0,0 +1,189 @@ +#include "ran_func_kpm.h" +#include "../../flexric/test/rnd/fill_rnd_data_kpm.h" +#include "../../flexric/src/util/time_now_us.h" +#include +#include + +static +gnb_e2sm_t fill_gnb_data(void) +{ + gnb_e2sm_t gnb = {0}; + + // 6.2.3.16 + // Mandatory + // AMF UE NGAP ID + gnb.amf_ue_ngap_id = 112358132134; // % 2^40; + + // Mandatory + //GUAMI 6.2.3.17 + gnb.guami.plmn_id = (e2sm_plmn_t) {.mcc = 505, .mnc = 1, .mnc_digit_len = 2}; + + gnb.guami.amf_region_id = (rand() % 2^8) + 0; + gnb.guami.amf_set_id = (rand() % 2^10) + 0; + gnb.guami.amf_ptr = (rand() % 2^6) + 0; + + return gnb; +} + +static +ue_id_e2sm_t fill_ue_id_data(void) +{ + ue_id_e2sm_t ue_id_data = {0}; + + ue_id_data.type = GNB_UE_ID_E2SM; + ue_id_data.gnb = fill_gnb_data(); + + return ue_id_data; +} + +static +kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1(void) +{ + kpm_ind_msg_format_1_t msg_frm_1 = {0}; + + // Measurement Data + uint32_t num_drbs = 2; + msg_frm_1.meas_data_lst_len = num_drbs; // (rand() % 65535) + 1; + msg_frm_1.meas_data_lst = calloc(msg_frm_1.meas_data_lst_len, sizeof(*msg_frm_1.meas_data_lst)); + assert(msg_frm_1.meas_data_lst != NULL && "Memory exhausted" ); + + for (size_t i = 0; i < msg_frm_1.meas_data_lst_len; i++){ + // Measurement Record + msg_frm_1.meas_data_lst[i].meas_record_len = 1; // (rand() % 65535) + 1; + msg_frm_1.meas_data_lst[i].meas_record_lst = calloc(msg_frm_1.meas_data_lst[i].meas_record_len, sizeof(meas_record_lst_t)); + assert(msg_frm_1.meas_data_lst[i].meas_record_lst != NULL && "Memory exhausted" ); + + for (size_t j = 0; j < msg_frm_1.meas_data_lst[i].meas_record_len; j++){ + msg_frm_1.meas_data_lst[i].meas_record_lst[j].value = REAL_MEAS_VALUE; // rand()%END_MEAS_VALUE; + msg_frm_1.meas_data_lst[i].meas_record_lst[j].real_val = (rand() % 256) + 0.1; + } + } + + // Measurement Information - OPTIONAL + msg_frm_1.meas_info_lst_len = num_drbs; + msg_frm_1.meas_info_lst = calloc(msg_frm_1.meas_info_lst_len, sizeof(meas_info_format_1_lst_t)); + assert(msg_frm_1.meas_info_lst != NULL && "Memory exhausted" ); + + for (size_t i = 0; i < msg_frm_1.meas_info_lst_len; i++) { + // Measurement Type + msg_frm_1.meas_info_lst[i].meas_type.type = ID_MEAS_TYPE; + // DRB ID + msg_frm_1.meas_info_lst[i].meas_type.id = i; + + // Label Information + msg_frm_1.meas_info_lst[i].label_info_lst_len = 1; + msg_frm_1.meas_info_lst[i].label_info_lst = calloc(msg_frm_1.meas_info_lst[i].label_info_lst_len, sizeof(label_info_lst_t)); + assert(msg_frm_1.meas_info_lst[i].label_info_lst != NULL && "Memory exhausted" ); + + for (size_t j = 0; j < msg_frm_1.meas_info_lst[i].label_info_lst_len; j++) { + msg_frm_1.meas_info_lst[i].label_info_lst[j].noLabel = malloc(sizeof(enum_value_e)); + *msg_frm_1.meas_info_lst[i].label_info_lst[j].noLabel = TRUE_ENUM_VALUE; + } + } + + return msg_frm_1; +} + +static +kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_sta(void) +{ + kpm_ind_msg_format_3_t msg_frm_3 = {0}; + + uint32_t num_ues = 1; + msg_frm_3.ue_meas_report_lst_len = num_ues; // (rand() % 65535) + 1; + + msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t)); + assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted"); + + for (size_t i = 0; i < msg_frm_3.ue_meas_report_lst_len; i++) + { + msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst = fill_ue_id_data(); + msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1(); + } + + return msg_frm_3; +} + +static +kpm_ric_ind_hdr_format_1_t fill_kpm_ind_hdr_frm_1(void) +{ + kpm_ric_ind_hdr_format_1_t hdr_frm_1 = {0}; + + hdr_frm_1.collectStartTime = time_now_us(); + + hdr_frm_1.fileformat_version = NULL; + + hdr_frm_1.sender_name = calloc(1, sizeof(byte_array_t)); + hdr_frm_1.sender_name->buf = calloc(strlen("My OAI-MONO") + 1, sizeof(char)); + memcpy(hdr_frm_1.sender_name->buf, "My OAI-MONO", strlen("My OAI-MONO")); + hdr_frm_1.sender_name->len = strlen("My OAI-MONO"); + + hdr_frm_1.sender_type = calloc(1, sizeof(byte_array_t)); + hdr_frm_1.sender_type->buf = calloc(strlen("MONO") + 1, sizeof(char)); + memcpy(hdr_frm_1.sender_type->buf, "MONO", strlen("MONO")); + hdr_frm_1.sender_type->len = strlen("MONO"); + + hdr_frm_1.vendor_name = calloc(1, sizeof(byte_array_t)); + hdr_frm_1.vendor_name->buf = calloc(strlen("OAI") + 1, sizeof(char)); + memcpy(hdr_frm_1.vendor_name->buf, "OAI", strlen("OAI")); + hdr_frm_1.vendor_name->len = strlen("OAI"); + + return hdr_frm_1; +} + +static +kpm_ind_hdr_t fill_kpm_ind_hdr_sta(void) +{ + kpm_ind_hdr_t hdr = {0}; + + hdr.type = FORMAT_1_INDICATION_HEADER; + hdr.kpm_ric_ind_hdr_format_1 = fill_kpm_ind_hdr_frm_1(); + + return hdr; +} + +void read_kpm_sm(void* data) +{ + assert(data != NULL); + //assert(data->type == KPM_STATS_V3_0); + + kpm_rd_ind_data_t* kpm = (kpm_rd_ind_data_t*)data; + + assert(kpm->act_def!= NULL && "Cannot be NULL"); + if(kpm->act_def->type == FORMAT_4_ACTION_DEFINITION){ + + if(kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond_type == CQI_TEST_COND_TYPE + && *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond == GREATERTHAN_TEST_COND){ + printf("Matching condition: UEs with CQI greater than %ld \n", *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.int_value ); + } + + printf("Parameter to report: %s \n", kpm->act_def->frm_4.action_def_format_1.meas_info_lst->meas_type.name.buf); + + kpm->ind.hdr = fill_kpm_ind_hdr_sta(); + // 7.8 Supported RIC Styles and E2SM IE Formats + // Format 4 corresponds to indication message 3 + kpm->ind.msg.type = FORMAT_3_INDICATION_MESSAGE; + kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_sta(); + } else { + kpm->ind.hdr = fill_kpm_ind_hdr(); + kpm->ind.msg = fill_kpm_ind_msg(); + } +} + +void read_kpm_setup_sm(void* e2ap) +{ + assert(e2ap != NULL); +// assert(e2ap->type == KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0); + + kpm_e2_setup_t* kpm = (kpm_e2_setup_t*)(e2ap); + kpm->ran_func_def = fill_kpm_ran_func_def(); +} + +sm_ag_if_ans_t write_ctrl_kpm_sm(void const* src) +{ + assert(0 !=0 && "Not supported"); + (void)src; + sm_ag_if_ans_t ans = {0}; + return ans; +} + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h new file mode 100644 index 0000000000..cec10e06ad --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h @@ -0,0 +1,13 @@ +#ifndef RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_kpm_sm(void*); + +void read_kpm_setup_sm(void*); + +sm_ag_if_ans_t write_ctrl_kpm_sm(void const* src); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c new file mode 100644 index 0000000000..5c6777d5a3 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c @@ -0,0 +1,108 @@ +#include "ran_func_rc.h" +#include "../../flexric/test/rnd/fill_rnd_data_rc.h" +#include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h" +#include "../../flexric/src/sm/rc_sm/ie/ir/ran_param_list.h" +#include +#include +#include +#include + +void read_rc_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == RAN_CTRL_STATS_V1_03); + assert(0!=0 && "Not implemented"); +} + +void read_rc_setup_sm(void* data) +{ + assert(data != NULL); +// assert(data->type == RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0); + rc_e2_setup_t* rc = (rc_e2_setup_t*)data; + rc->ran_func_def = fill_rc_ran_func_def(); +} + +sm_ag_if_ans_t write_ctrl_rc_sm(void const* data) +{ + assert(data != NULL); +// assert(data->type == RAN_CONTROL_CTRL_V1_03 ); + + rc_ctrl_req_data_t const* ctrl = (rc_ctrl_req_data_t const*)data; + if(ctrl->hdr.format == FORMAT_1_E2SM_RC_CTRL_HDR){ + if(ctrl->hdr.frmt_1.ric_style_type == 1 && ctrl->hdr.frmt_1.ctrl_act_id == 2){ + printf("QoS flow mapping configuration \n"); + e2sm_rc_ctrl_msg_frmt_1_t const* frmt_1 = &ctrl->msg.frmt_1; + for(size_t i = 0; i < frmt_1->sz_ran_param; ++i){ + seq_ran_param_t const* rp = frmt_1->ran_param; + if(rp[i].ran_param_id == 1){ + assert(rp[i].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE ); + printf("DRB ID %ld \n", rp[i].ran_param_val.flag_true->int_ran); + } else if(rp[i].ran_param_id == 2){ + assert(rp[i].ran_param_val.type == LIST_RAN_PARAMETER_VAL_TYPE); + printf("List of QoS Flows to be modified \n"); + for(size_t j = 0; j < ctrl->msg.frmt_1.ran_param[i].ran_param_val.lst->sz_lst_ran_param; ++j){ + lst_ran_param_t const* lrp = rp[i].ran_param_val.lst->lst_ran_param; + // The following assertion should be true, but there is a bug in the std + // check src/sm/rc_sm/enc/rc_enc_asn.c:1085 and src/sm/rc_sm/enc/rc_enc_asn.c:984 + // assert(lrp[j].ran_param_id == 3); + assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_id == 4) ; + assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE); + + int64_t qfi = lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.flag_true->int_ran; + assert(qfi > -1 && qfi < 65); + + assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_id == 5); + assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.type == ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE); + int64_t dir = lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.flag_false->int_ran; + assert(dir == 0 || dir == 1); + printf("qfi = %ld dir %ld \n", qfi, dir); + } + } + } + } + } + + sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0}; + ans.ctrl_out.type = RAN_CTRL_V1_3_AGENT_IF_CTRL_ANS_V0; + return ans; +} + +static +void* emulate_rrc_msg(void* ptr) +{ + uint32_t* ric_id = (uint32_t*)ptr; + for(size_t i = 0; i < 5; ++i){ + usleep(rand()%4000); + rc_ind_data_t* d = calloc(1, sizeof(rc_ind_data_t)); + assert(d != NULL && "Memory exhausted"); + *d = fill_rnd_rc_ind_data(); + async_event_agent_api(*ric_id, d); + printf("Event for RIC Req ID %u generated\n", *ric_id); + } + + free(ptr); + return NULL; +} + +static +pthread_t t_ran_ctrl; + +sm_ag_if_ans_t write_subs_rc_sm(void const* src) +{ + assert(src != NULL); // && src->type == RAN_CTRL_SUBS_V1_03); + + wr_rc_sub_data_t* wr_rc = (wr_rc_sub_data_t*)src; + printf("ric req id %d \n", wr_rc->ric_req_id); + + uint32_t* ptr = malloc(sizeof(uint32_t)); + assert(ptr != NULL); + *ptr = wr_rc->ric_req_id; + + int rc = pthread_create(&t_ran_ctrl, NULL, emulate_rrc_msg, ptr); + assert(rc == 0); + + sm_ag_if_ans_t ans = {0}; + + return ans; +} + diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h new file mode 100644 index 0000000000..64f11c8068 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h @@ -0,0 +1,15 @@ +#ifndef RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H +#define RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H + +#include "../../flexric/src/agent/e2_agent_api.h" + +void read_rc_sm(void *); + +void read_rc_setup_sm(void* data); + +sm_ag_if_ans_t write_ctrl_rc_sm(void const* data); + +sm_ag_if_ans_t write_subs_rc_sm(void const* src); + +#endif + diff --git a/openair2/E2AP/RAN_FUNCTION/init_ran_func.c b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c new file mode 100644 index 0000000000..bc60d139de --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c @@ -0,0 +1,73 @@ +#include "init_ran_func.h" +#include "../flexric/src/agent/e2_agent_api.h" +#include "CUSTOMIZED/ran_func_mac.h" +#include "CUSTOMIZED/ran_func_rlc.h" +#include "CUSTOMIZED/ran_func_pdcp.h" +#include "CUSTOMIZED/ran_func_slice.h" +#include "CUSTOMIZED/ran_func_tc.h" +#include "CUSTOMIZED/ran_func_gtp.h" +#include "O-RAN/ran_func_kpm.h" +#include "O-RAN/ran_func_rc.h" + +static +void init_read_ind_tbl(read_ind_fp (*read_ind_tbl)[SM_AGENT_IF_READ_V0_END]) +{ + (*read_ind_tbl)[MAC_STATS_V0] = read_mac_sm; + (*read_ind_tbl)[RLC_STATS_V0] = read_rlc_sm ; + (*read_ind_tbl)[PDCP_STATS_V0] = read_pdcp_sm ; + (*read_ind_tbl)[SLICE_STATS_V0] = read_slice_sm ; + (*read_ind_tbl)[TC_STATS_V0] = read_tc_sm ; + (*read_ind_tbl)[GTP_STATS_V0] = read_gtp_sm ; + (*read_ind_tbl)[KPM_STATS_V3_0] = read_kpm_sm ; + (*read_ind_tbl)[RAN_CTRL_STATS_V1_03] = read_rc_sm; +} + +static +void init_read_setup_tbl(read_e2_setup_fp (*read_setup_tbl)[SM_AGENT_IF_E2_SETUP_ANS_V0_END]) +{ + (*read_setup_tbl)[MAC_AGENT_IF_E2_SETUP_ANS_V0] = read_mac_setup_sm; + (*read_setup_tbl)[RLC_AGENT_IF_E2_SETUP_ANS_V0] = read_rlc_setup_sm ; + (*read_setup_tbl)[PDCP_AGENT_IF_E2_SETUP_ANS_V0] = read_pdcp_setup_sm ; + (*read_setup_tbl)[SLICE_AGENT_IF_E2_SETUP_ANS_V0] = read_slice_setup_sm ; + (*read_setup_tbl)[TC_AGENT_IF_E2_SETUP_ANS_V0] = read_tc_setup_sm ; + (*read_setup_tbl)[GTP_AGENT_IF_E2_SETUP_ANS_V0] = read_gtp_setup_sm ; + (*read_setup_tbl)[KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0] = read_kpm_setup_sm ; + (*read_setup_tbl)[RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0] = read_rc_setup_sm; +} + +static +void init_write_ctrl( write_ctrl_fp (*write_ctrl_tbl)[SM_AGENT_IF_WRITE_CTRL_V0_END]) +{ + (*write_ctrl_tbl)[MAC_CTRL_REQ_V0] = write_ctrl_mac_sm; + (*write_ctrl_tbl)[RLC_CTRL_REQ_V0] = write_ctrl_rlc_sm; + (*write_ctrl_tbl)[PDCP_CTRL_REQ_V0] = write_ctrl_pdcp_sm; + (*write_ctrl_tbl)[SLICE_CTRL_REQ_V0] = write_ctrl_slice_sm; + (*write_ctrl_tbl)[TC_CTRL_REQ_V0] = write_ctrl_tc_sm; + (*write_ctrl_tbl)[GTP_CTRL_REQ_V0] = write_ctrl_gtp_sm; + (*write_ctrl_tbl)[RAN_CONTROL_CTRL_V1_03] = write_ctrl_rc_sm; +} + +static +void init_write_subs(write_subs_fp (*write_subs_tbl)[SM_AGENT_IF_WRITE_SUBS_V0_END]) +{ + (*write_subs_tbl)[MAC_SUBS_V0] = NULL; + (*write_subs_tbl)[RLC_SUBS_V0] = NULL; + (*write_subs_tbl)[PDCP_SUBS_V0] = NULL; + (*write_subs_tbl)[SLICE_SUBS_V0] = NULL; + (*write_subs_tbl)[TC_SUBS_V0] = NULL; + (*write_subs_tbl)[GTP_SUBS_V0] = NULL; + (*write_subs_tbl)[KPM_SUBS_V3_0] = NULL; + (*write_subs_tbl)[RAN_CTRL_SUBS_V1_03] = write_subs_rc_sm; +} + +sm_io_ag_ran_t init_ran_func_ag(void) +{ + sm_io_ag_ran_t io = {0}; + init_read_ind_tbl(&io.read_ind_tbl); + init_read_setup_tbl(&io.read_setup_tbl); + init_write_ctrl(&io.write_ctrl_tbl); + init_write_subs(&io.write_subs_tbl); + + return io; +} + diff --git a/openair2/E2AP/RAN_FUNCTION/init_ran_func.h b/openair2/E2AP/RAN_FUNCTION/init_ran_func.h new file mode 100644 index 0000000000..3b7d10f506 --- /dev/null +++ b/openair2/E2AP/RAN_FUNCTION/init_ran_func.h @@ -0,0 +1,32 @@ +/* + * 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 RAN_FUNC_INIT_E2_H +#define RAN_FUNC_INIT_E2_H + +#include "../flexric/src/sm/sm_io.h" + +sm_io_ag_ran_t init_ran_func_ag(void); + +#endif + diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md new file mode 100644 index 0000000000..ce8bf0dd7a --- /dev/null +++ b/openair2/E2AP/README.md @@ -0,0 +1,153 @@ +

+ OAI +

+ +

+ License + Supported OS Ubuntu 18 + Supported OS Ubuntu 20 + Supported OS Ubuntu 22 + Supported OS RHEL8 + Supported OS RELH9 + Supported OS Fedora 37 +

+ +

+ +

+ +

+ Docker Pulls + Docker Pulls + Docker Pulls + Docker Pulls +

+ + + +# OpenAirInterface License # + + * [OAI License Model](http://www.openairinterface.org/?page_id=101) + * [OAI License v1.1 on our website](http://www.openairinterface.org/?page_id=698) + +It is distributed under **OAI Public License V1.1**. + +The license information is distributed under [LICENSE](LICENSE) file in the same directory. + +Please see [NOTICE](NOTICE.md) file for third party software that is included in the sources. + +# Overview + +This tutorial describes the steps of deployment 5G OAI RAN, with integrated E2 agent, with FlexRIC, O-RAN compliant nearRT-RIC. + +# 1. Installation + +## 1.1 Install prerequisites + +- A *recent* CMake (at least v3.15). + + On Ubuntu, you might want to use [this PPA](https://apt.kitware.com/) to install an up-to-date version. + +- SWIG (at least v.4.0). + + We use SWIG as an interface generator to enable the multi-language feature (i.e., C/C++ and Python) for the xApps. Please, check your SWIG version (i.e, `swig + -version`) and install it from scratch if necessary as described here: https://swig.org/svn.html or via the code below: + + ```bash + git clone https://github.com/swig/swig.git + cd swig + ./autogen.sh + ./configure --prefix=/usr/ + make + make install + ``` + +- Flatbuffer encoding(optional). + + We also provide a flatbuffers encoding/decoding scheme as alternative to ASN.1. In case that you want to use it follow the + instructions at https://github.com/dvidelabs/flatcc and provide the path for the lib and include when selecting it at `ccmake ..` from the build directory + +## 1.2 Download the required dependencies. + +Below an example of how to install it in ubuntu +```bash +sudo apt install libsctp-dev python3.8 cmake-curses-gui libpcre2-dev python-dev +``` + +# 2. Deployment + +## 2.1 OAI RAN + +### 2.1.1 Clone the OAI repository +```bash +git clone https://gitlab.eurecom.fr/oai/openairinterface5g oai +cd oai/ +``` + +### 2.1.2 Build OAI +```bash +cd cmake_targets/ +./build_oai -I -w SIMU --gNB --nrUE --build-e2 --ninja +``` +If the flexric folder is empty, try manually the following commands + +```bash +git submodule init +git submodule update +``` + + * -I option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. + * -w option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from liboai_device.so to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using -w SIMU option, but is also built during any softmodem build. + * --gNB is to build the nr-softmodem and nr-cuup executables and all required shared libraries + * --nrUE is to build the nr-uesoftmodem executable and all required shared libraries + * --ninja is to use the ninja build tool, which speeds up compilation + * --build-e2 option is to use the E2 agent, integrated within gNB. + +## 2.2 FlexRIC + +### 2.2.1 Clone the FlexRIC repository +```bash +git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric +cd flexric/ +git checkout mir_dev +``` + +### 2.2.2 Build FlexRIC +```bash +mkdir build && cd build && cmake .. && make +``` + +### 2.2.3 Installation of Service Models (SMs) +```bash +sudo make install +``` + +By default the service model libraries will be installed in the path /usr/local/lib/flexric while the configuration file in `/usr/local/etc/flexric`. + + * Note: currently, only xApp KPM v03.00 and RC v01.03 (xapp_kpm_rc) is supported to communicate with the integrated E2 agent in OAI. If you are interested in custom SMs (MAC, RLC, PDCP, GTP, TC and SLICE), please follow the instructions at https://gitlab.eurecom.fr/mosaic5g/flexric. + +# 3. Start the process + +* start the gNB +```bash +cd oai/cmake_targets/ran_build/build +sudo ./nr-softmodem RFSIMULATOR=server -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa +``` + +* start the nrUE +```bash +cd oai/cmake_targets/ran_build/build +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa --uicc0.imsi 001010000000001 +``` + +* start the nearRT-RIC +```bash +cd flexric +./build/examples/ric/nearRT-RIC +``` + +* start the KPM+RC xApp +```bash +cd flexric +./build/examples/xApp/c/kpm_rc/xapp_kpm_rc +``` diff --git a/openair2/E2AP/e2_agent_arg.h b/openair2/E2AP/e2_agent_arg.h new file mode 100644 index 0000000000..b719c32d97 --- /dev/null +++ b/openair2/E2AP/e2_agent_arg.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 + * + * 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 E2_AGENT_ARGS_H +#define E2_AGENT_ARGS_H + +#include + +// Wrapper for OAI +typedef struct{ + const char *ip; + const char *sm_dir; +} e2_agent_args_t; + +#endif + + diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric new file mode 160000 index 0000000000..ef00d05a3f --- /dev/null +++ b/openair2/E2AP/flexric @@ -0,0 +1 @@ +Subproject commit ef00d05a3f673d04bbc003f4ae479ead467bd8ea diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 26606a9c5c..b05dcf4f76 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2929,3 +2929,25 @@ void read_config_and_init(void) { RCconfig_RRC(enb_id, RC.rrc[enb_id]); } } + +#ifdef E2_AGENT + +e2_agent_args_t RCconfig_E2agent(void) +{ + paramdef_t e2agent_params[] = E2AGENT_PARAMS_DESC; + int ret = config_get(e2agent_params, sizeof(e2agent_params) / sizeof(paramdef_t), CONFIG_STRING_E2AGENT); + if (ret < 0) { + LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters\n", CONFIG_STRING_E2AGENT); + return (e2_agent_args_t) {0}; + } + return (e2_agent_args_t) { + .ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr, + .port = *e2agent_params[E2AGENT_CONFIG_PORT_IDX].u16ptr, + .sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr, + }; +} + + +#endif + + diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 67b4fb45e7..5abb7df2c9 100644 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -116,6 +116,11 @@ void read_config_and_init(void); int RCconfig_X2(MessageDef *msg_p, uint32_t i); int RCconfig_M2(MessageDef *msg_p, uint32_t i); +#ifdef E2_AGENT +#include "openair2/E2AP/e2_agent_arg.h" +e2_agent_args_t RCconfig_E2agent(void); +#endif + void fill_SL_configuration(RrcConfigurationReq *RRCcfg, ccparams_sidelink_t *SLconfig, int cell_idx, int cc_idx, char *config_fname); void fill_eMTC_configuration(RrcConfigurationReq *RRCcfg, ccparams_eMTC_t *eMTCconfig, int cell_idx, int cc_idx, char *config_fname, char *brparamspath); diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index e37c5388d0..34fcc6ad2c 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -1317,6 +1317,35 @@ typedef struct srb1_params_s { #define CONFIG_HLP_PARALLEL "PARALLEL_SINGLE_THREAD, PARALLEL_RU_L1_SPLIT, or PARALLEL_RU_L1_TRX_SPLIT(RU_L1_TRX_SPLIT by defult)\n" /*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#ifdef E2_AGENT + +/* E2 Agent configuration */ +#define CONFIG_STRING_E2AGENT "e2_agent" + +#define E2AGENT_CONFIG_IP "ip" +//#define E2AGENT_CONFIG_PORT "port" +#define E2AGENT_CONFIG_SMDIR "sm_dir" + +static const char* const e2agent_config_ip_default = NULL; +static const char* const e2agent_config_smdir_default = NULL; +//static const uint16_t e2agent_config_port_default = 36421; + +#define E2AGENT_PARAMS_DESC { \ + {E2AGENT_CONFIG_IP, "RIC IP address", 0, strptr:NULL, defstrval:(char*)e2agent_config_ip_default, TYPE_STRING, 0}, \ + {E2AGENT_CONFIG_SMDIR, "Directory with SMs to load", 0, strptr:NULL, defstrval:(char*)e2agent_config_smdir_default, TYPE_STRING, 0}, \ +} +/* +// {E2AGENT_CONFIG_PORT, "RIC port", 0, u16ptr:NULL, defuintval:e2agent_config_port_default, TYPE_UINT16, 0}, \ +} +*/ + +#define E2AGENT_CONFIG_IP_IDX 0 +#define E2AGENT_CONFIG_SMDIR_IDX 1 +//#define E2AGENT_CONFIG_PORT_IDX 2 + +#endif // E2_AGENT + + #include "enb_paramdef_emtc.h" #include "enb_paramdef_sidelink.h" #include "enb_paramdef_mce.h" diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 9db7cc5067..87f2c07d21 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2259,3 +2259,23 @@ void nr_read_config_and_init(void) { nr_pdcp_layer_init(); } } + +#ifdef E2_AGENT + +e2_agent_args_t RCconfig_NR_E2agent(void) +{ + paramdef_t e2agent_params[] = E2AGENT_PARAMS_DESC; + int ret = config_get(e2agent_params, sizeof(e2agent_params) / sizeof(paramdef_t), CONFIG_STRING_E2AGENT); + if (ret < 0) { + LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters from FlexRIC\n", CONFIG_STRING_E2AGENT); + return (e2_agent_args_t) { 0 }; + } + e2_agent_args_t dst = {0}; + if(e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL) + dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr; + if(e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL) + dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr; + return dst; +} + +#endif // E2_AGENT diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index 3089753cff..0a23ebea74 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -110,5 +110,10 @@ void nr_read_config_and_init(void); MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process); ngran_node_t get_node_type(void); +#ifdef E2_AGENT +#include "openair2/E2AP/e2_agent_arg.h" +e2_agent_args_t RCconfig_NR_E2agent(void); +#endif // E2_AGENT + #endif /* GNB_CONFIG_H_ */ /** @} */ diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 7d5d49fe87..01210a0663 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -266,3 +266,8 @@ log_config : f1ap_log_level ="debug"; }; +e2_agent = { + address = "127.0.0.1"; + #sm_dir = "/path/where/the/SMs/are/located/" + sm_dir = "/usr/local/lib/flexric/" +}; From 126e7bb432733bd92f0bac8247e893e0243564ce Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 7 Jun 2023 10:45:48 +0200 Subject: [PATCH 59/87] Reference E2 agent tutorial in doc/README.md --- doc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/README.md b/doc/README.md index 6abca52f0b..f65f6f6ac0 100644 --- a/doc/README.md +++ b/doc/README.md @@ -43,6 +43,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// - [How to run OAI-VNF and OAI-PNF](./RUN_NR_NFAPI.md) _Note: does not work currently_ - [How to use the positioning reference signal (PRS)](./RUN_NR_PRS.md) - [How to use device-to-device communication (D2D, 4G)](./d2d_emulator_setup.txt) +- [How to run with E2 agent](../openair2/E2AP/README.md) Legacy unmaintained files: - `L2NFAPI_NOS1.md`, `L2NFAPI_S1.md`: old L2simulator, not valid anymore From 483c5436e54d9c9e9496e9ebaef7e118685b601c Mon Sep 17 00:00:00 2001 From: mir Date: Fri, 16 Jun 2023 14:37:55 +0200 Subject: [PATCH 60/87] gitlink to FlexRIC was updated --- openair2/E2AP/README.md | 4 ++-- openair2/E2AP/flexric | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index ce8bf0dd7a..822880f2b2 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -109,12 +109,12 @@ git submodule update ```bash git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric cd flexric/ -git checkout mir_dev +git checkout d3ff879135d036632d7938c2085dbf4577759225 ``` ### 2.2.2 Build FlexRIC ```bash -mkdir build && cd build && cmake .. && make +mkdir build && cd build && cmake .. && make -j8 ``` ### 2.2.3 Installation of Service Models (SMs) diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric index ef00d05a3f..d3ff879135 160000 --- a/openair2/E2AP/flexric +++ b/openair2/E2AP/flexric @@ -1 +1 @@ -Subproject commit ef00d05a3f673d04bbc003f4ae479ead467bd8ea +Subproject commit d3ff879135d036632d7938c2085dbf4577759225 From bb3d8b82015eba1dcaf71f500b878a801e14da7a Mon Sep 17 00:00:00 2001 From: mir Date: Mon, 19 Jun 2023 16:20:22 +0200 Subject: [PATCH 61/87] near_ric_ip_addr added. The config needs to be defined in OAI's config file --- executables/nr-softmodem.c | 10 ++++++---- openair2/ENB_APP/enb_paramdef.h | 2 +- openair2/GNB_APP/gnb_config.c | 9 ++++++--- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 8f55024ef4..1b0ff90708 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -697,14 +697,16 @@ int main( int argc, char **argv ) { ////////////////////////////////// ////////////////////////////////// //// Init the E2 Agent - + sm_io_ag_ran_t io = init_ran_func_ag(); - fr_args_t args = init_fr_args(0, NULL); // OAI Wrapper e2_agent_args_t oai_args = RCconfig_NR_E2agent(); - if(oai_args.sm_dir != NULL) - memcpy(args.libs_dir, oai_args.sm_dir, 128); + AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} "); + AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\""); + + fr_args_t args = {.ip = oai_args.ip}; // init_fr_args(0, NULL); + memcpy(args.libs_dir, oai_args.sm_dir, 128); sleep(1); const gNB_RRC_INST* rrc = RC.nrrrc[0]; diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 34fcc6ad2c..58eebba278 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -1322,7 +1322,7 @@ typedef struct srb1_params_s { /* E2 Agent configuration */ #define CONFIG_STRING_E2AGENT "e2_agent" -#define E2AGENT_CONFIG_IP "ip" +#define E2AGENT_CONFIG_IP "near_ric_ip_addr" //#define E2AGENT_CONFIG_PORT "port" #define E2AGENT_CONFIG_SMDIR "sm_dir" diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 87f2c07d21..2314cd2bf2 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2271,10 +2271,13 @@ e2_agent_args_t RCconfig_NR_E2agent(void) return (e2_agent_args_t) { 0 }; } e2_agent_args_t dst = {0}; - if(e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL) - dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr; - if(e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL) + + if (e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL) dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr; + + if (e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL) + dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr; + return dst; } diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 01210a0663..3b7fadf3bc 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -267,7 +267,7 @@ log_config : }; e2_agent = { - address = "127.0.0.1"; + near_ric_ip_addr = "127.0.0.1"; #sm_dir = "/path/where/the/SMs/are/located/" sm_dir = "/usr/local/lib/flexric/" }; From 31b7d7c432e162212892446689adcecd30ead8b2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 5 Jul 2023 07:01:28 +0000 Subject: [PATCH 62/87] !2173: Favor --rfsimulator.serveraddr "server" over RFSIMULATOR=server --- openair2/E2AP/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index 822880f2b2..2ff52e8605 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -131,13 +131,13 @@ By default the service model libraries will be installed in the path /usr/local/ * start the gNB ```bash cd oai/cmake_targets/ran_build/build -sudo ./nr-softmodem RFSIMULATOR=server -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa --rfsimulator.serveraddr server ``` * start the nrUE ```bash cd oai/cmake_targets/ran_build/build -sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa --uicc0.imsi 001010000000001 +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1 ``` * start the nearRT-RIC From 1f14195543a83506a7f03db619b1b1c98fe246e2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 7 Jul 2023 13:47:05 +0200 Subject: [PATCH 63/87] Move inclusion of openair2/E2AP where it belongs --- CMakeLists.txt | 6 ------ openair2/CMakeLists.txt | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c495fb52cc..05ebd0b10c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,15 +331,9 @@ add_definitions(-DHAVE_NETINET_IN_H) ######################### ##### E2 AGENT ######################### -#add_boolean_option() does not work -- why? set(E2_AGENT "OFF" CACHE STRING "O-RAN-compliant E2 Agent") set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF") -if(E2_AGENT) - set(E2AP_DIR ${OPENAIR2_DIR}/E2AP) - add_subdirectory ("${E2AP_DIR}") -endif() - ################################################## # ASN.1 grammar C code generation & dependencies # ################################################## diff --git a/openair2/CMakeLists.txt b/openair2/CMakeLists.txt index 563d343420..117d18412b 100644 --- a/openair2/CMakeLists.txt +++ b/openair2/CMakeLists.txt @@ -1,4 +1,7 @@ add_subdirectory(E1AP) +if(E2_AGENT) + add_subdirectory(E2AP) +endif() add_subdirectory(F1AP) add_subdirectory(M2AP) add_subdirectory(X2AP) From 97904c6db0b381216431cf98350ce9d7b493fdac Mon Sep 17 00:00:00 2001 From: mir Date: Wed, 5 Jul 2023 09:51:05 +0200 Subject: [PATCH 64/87] Simplify README --- openair2/E2AP/README.md | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index 2ff52e8605..095d802877 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -1,30 +1,3 @@ -

- OAI -

- -

- License - Supported OS Ubuntu 18 - Supported OS Ubuntu 20 - Supported OS Ubuntu 22 - Supported OS RHEL8 - Supported OS RELH9 - Supported OS Fedora 37 -

- -

- -

- -

- Docker Pulls - Docker Pulls - Docker Pulls - Docker Pulls -

- - - # OpenAirInterface License # * [OAI License Model](http://www.openairinterface.org/?page_id=101) @@ -96,12 +69,12 @@ git submodule init git submodule update ``` - * -I option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. - * -w option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from liboai_device.so to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using -w SIMU option, but is also built during any softmodem build. - * --gNB is to build the nr-softmodem and nr-cuup executables and all required shared libraries - * --nrUE is to build the nr-uesoftmodem executable and all required shared libraries - * --ninja is to use the ninja build tool, which speeds up compilation - * --build-e2 option is to use the E2 agent, integrated within gNB. + * `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. + * `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using `-w SIMU` option, but is also built during any softmodem build. + * `--gNB` is to build the `nr-softmodem` and `nr-cuup` executables and all required shared libraries + * `--nrUE` is to build the `nr-uesoftmodem` executable and all required shared libraries + * `--ninja` is to use the ninja build tool, which speeds up compilation + * `--build-e2` option is to use the E2 agent, integrated within gNB. ## 2.2 FlexRIC From 8d90178d57de605e7e6e8e2deb571929757a13cc Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 16:19:12 +0200 Subject: [PATCH 65/87] Modifications in cls_containerize: add comment --- ci-scripts/cls_containerize.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index f26fdc01cb..c9023a6513 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -1005,6 +1005,7 @@ class Containerize(): HTML.htmleNBFailureMsg='Could not copy logfile to analyze it!' HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.exitStatus = 1 + # use function for UE log analysis, when oai-nr-ue container is used elif 'oai-nr-ue' in services: self.exitStatus == 0 logging.debug('\u001B[1m Analyzing UE logfile ' + filename + ' \u001B[0m') From a0d9beb0dd4fd2daa6c635ae8025bd851a6b94b5 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 7 Jul 2023 16:22:54 +0200 Subject: [PATCH 66/87] CI: docs for nrUE pipeline: update --- doc/TESTBenches.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 1641e0160a..35aebfe1aa 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -145,9 +145,6 @@ Webhook - [RAN-SA-Module-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-Module-CN5G/) - asterix + N310 (gNB), nrmodule2 + Quectel, porcepix w/ OAI 5GC - NR 2x2 (standalone) -- [RAN-SA-OAIUE-N310-X300-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-OAIUE-N310-X300-CN5G/) - - asterix + N310 (gNB), obelix + N310 or X300 (5G UE), porcepix w/ OAI 5GC - - OTA test with OAIUE using both N310 and X300 - [RAN-SA-AmariS-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-AmariS-CN5G/) - asterix + N310, amariue (1x UE), porcepix w/ OAI 5GC - Amarisoft UE simulator: expected to be increased to more UEs From ed7b675330a330e7de43eadfe4409441fb7cf9dd Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 26 Jun 2023 15:46:11 +0200 Subject: [PATCH 67/87] remove redundant copies of pdu sessions list --- executables/nr-cuup.c | 3 +- openair2/E1AP/e1ap_api.c | 3 +- openair2/RRC/NR/cucp_cuup_direct.c | 12 +- openair2/RRC/NR/cucp_cuup_e1ap.c | 9 +- openair2/RRC/NR/cucp_cuup_if.h | 2 +- openair2/RRC/NR/nr_rrc_defs.h | 3 - openair2/RRC/NR/nr_rrc_proto.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 304 ++++++++++++----------------- openair2/RRC/NR/rrc_gNB_NGAP.c | 5 +- 9 files changed, 138 insertions(+), 205 deletions(-) diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 6fcf5b7ea3..ffa50a766b 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -111,9 +111,10 @@ f1ap_cudu_inst_t *getCxt(F1_t isCU, instance_t instanceP) return NULL; } -void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, uint8_t xid) +NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) { abort(); + return NULL; } int main(int argc, char **argv) diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c index 15f05fb3ed..cf167f64e8 100644 --- a/openair2/E1AP/e1ap_api.c +++ b/openair2/E1AP/e1ap_api.c @@ -114,7 +114,8 @@ static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req, // Create N3 tunnel int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, nr_pdcp_data_req_drb, sdap_data_req); 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", + LOG_E(NR_RRC, + "drb_config_N3gtpu_create=>gtpv1u_create_ngu_tunnel failed, cannot set up GTP tunnel for data transmissions of UE %ld\n", create_tunnel_req.ue_id); return ret; } diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c index 347e9fbff5..49f95c82f7 100644 --- a/openair2/RRC/NR/cucp_cuup_direct.c +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -125,7 +125,8 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p, sdap_data_req); 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", + LOG_E(NR_RRC, + "drb_config_gtpu_create=>gtpv1u_create_ngu_tunnel failed, cannot set up GTP tunnel for data transmissions of UE %ld\n", create_tunnel_req.ue_id); return ret; } @@ -160,14 +161,13 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p, return ret; } -static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) +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_by_rnti(RC.nrrrc[instance], req->rnti); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; protocol_ctxt_t ctxt = {0}; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0); - fill_DRB_configList(&ctxt, ue_context_p, xid); e1ap_bearer_setup_resp_t resp = {0}; resp.numPDUSessions = req->numPDUSessions; for (int i = 0; i < resp.numPDUSessions; ++i) { @@ -184,7 +184,8 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; // GTP tunnel for UL - int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, UE->DRB_configList, rrc->e1_inst); + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(UE); + int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, DRB_configList, rrc->e1_inst); if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n"); // Used to store teids: if monolithic, will simply be NULL @@ -203,7 +204,8 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const 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, uint8_t xid) { +static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance) +{ // only update GTP tunnels if it is really a CU if (!NODE_IS_CU(RC.nrrrc[0]->node_type)) return; diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c index 390ab232a7..200729ec11 100644 --- a/openair2/RRC/NR/cucp_cuup_e1ap.c +++ b/openair2/RRC/NR/cucp_cuup_e1ap.c @@ -36,13 +36,8 @@ extern RAN_CONTEXT_t RC; -static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) +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_by_rnti(RC.nrrrc[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, xid); 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)); @@ -50,7 +45,7 @@ static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const r 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, uint8_t xid) +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); diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h index ed4702b4b2..079a32e850 100644 --- a/openair2/RRC/NR/cucp_cuup_if.h +++ b/openair2/RRC/NR/cucp_cuup_if.h @@ -27,7 +27,7 @@ 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, uint8_t xid); +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); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 390347362d..e72624527c 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -237,9 +237,6 @@ typedef enum { typedef struct gNB_RRC_UE_s { uint8_t primaryCC_id; - NR_DRB_ToAddModList_t *DRB_configList; - NR_DRB_ToAddModList_t *DRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; - NR_DRB_ToReleaseList_t *DRB_Release_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; drb_t established_drbs[NGAP_MAX_DRBS_PER_UE]; uint8_t DRB_active[NGAP_MAX_DRBS_PER_UE]; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 504aced681..fd9f38a3fb 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -156,7 +156,7 @@ void ue_cxt_mod_send_e1ap(MessageDef *msg, 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, uint8_t xid); +NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue); void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index fbaf2364c2..0113792030 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -113,7 +113,77 @@ mui_t rrc_gNB_mui = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// +NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) +{ + gNB_RRC_INST *rrc = RC.nrrrc[0]; + if (ue->nb_of_pdusessions == 0) + return NULL; + int nb_drb_to_setup = rrc->configuration.drbs; + long drb_priority[NGAP_MAX_DRBS_PER_UE] = {0}; + uint8_t drb_id_to_setup_start = 0; + NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); + for (int i = 0; i < ue->nb_of_pdusessions; i++) { + if (ue->pduSession[i].status >= PDU_SESSION_STATUS_DONE) { + continue; + } + LOG_I(NR_RRC, "adding rnti %x pdusession %d, nb drb %d\n", ue->rnti, ue->pduSession[i].param.pdusession_id, nb_drb_to_setup); + for (long drb_id_add = 1; drb_id_add <= nb_drb_to_setup; drb_id_add++) { + uint8_t drb_id; + // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping + for (int qos_flow_index = 0; qos_flow_index < ue->pduSession[i].param.nb_qos; qos_flow_index++) { + switch (ue->pduSession[i].param.qos[qos_flow_index].fiveQI) { + case 1 ... 4: /* GBR */ + drb_id = next_available_drb(ue, &ue->pduSession[i], GBR_FLOW); + break; + case 5 ... 9: /* Non-GBR */ + if (rrc->configuration.drbs > 1) { /* Force the creation from gNB Conf file */ + LOG_W(NR_RRC, "Adding %d DRBs, from gNB config file (not decided by 5GC\n", rrc->configuration.drbs); + drb_id = next_available_drb(ue, &ue->pduSession[i], GBR_FLOW); + } else { + drb_id = next_available_drb(ue, &ue->pduSession[i], NONGBR_FLOW); + } + break; + default: + LOG_E(NR_RRC, "not supported 5qi %lu\n", ue->pduSession[i].param.qos[qos_flow_index].fiveQI); + ue->pduSession[i].status = PDU_SESSION_STATUS_FAILED; + continue; + } + drb_priority[drb_id - 1] = ue->pduSession[i].param.qos[qos_flow_index].allocation_retention_priority.priority_level; + if (drb_priority[drb_id - 1] < 0 || drb_priority[drb_id - 1] > NGAP_PRIORITY_LEVEL_NO_PRIORITY) { + LOG_E(NR_RRC, "invalid allocation_retention_priority.priority_level %ld set to _NO_PRIORITY\n", drb_priority[drb_id - 1]); + drb_priority[drb_id - 1] = NGAP_PRIORITY_LEVEL_NO_PRIORITY; + } + + if (drb_is_active(ue, drb_id)) { /* Non-GBR flow using the same DRB or a GBR flow with no available DRBs*/ + nb_drb_to_setup--; + } else { + generateDRB(ue, + drb_id, + &ue->pduSession[i], + rrc->configuration.enable_sdap, + rrc->security.do_drb_integrity, + rrc->security.do_drb_ciphering); + NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue->established_drbs[drb_id - 1]); + if (drb_id_to_setup_start == 0) + drb_id_to_setup_start = DRB_config->drb_Identity; + asn1cSeqAdd(&DRB_configList->list, DRB_config); + } + LOG_D(RRC, "DRB Priority %ld\n", drb_priority[drb_id]); // To supress warning for now + } + } + } + if (DRB_configList->list.count == 0) { + free(DRB_configList); + return NULL; + } + return DRB_configList; +} + +static void freeDRBlist(NR_DRB_ToAddModList_t *list) +{ + return; +} static void nr_rrc_addmod_srbs(int rnti, const NR_SRB_INFO_TABLE_ENTRY *srb_list, const int nb_srb, @@ -338,7 +408,9 @@ static void apply_macrlc_config(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const u gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; nr_rrc_mac_update_cellgroup(ue_p->rnti, cgc); nr_rrc_addmod_srbs(ctxt_pP->rntiMaybeUEid, ue_p->Srb, maxSRBs, cgc->rlc_BearerToAddModList); - nr_rrc_addmod_drbs(ctxt_pP->rntiMaybeUEid, ue_p->DRB_configList, cgc->rlc_BearerToAddModList); + NR_DRB_ToAddModList_t *DRBs = fill_DRB_configList(ue_p); + nr_rrc_addmod_drbs(ctxt_pP->rntiMaybeUEid, DRBs, cgc->rlc_BearerToAddModList); + freeDRBlist(DRBs); } void apply_macrlc_config_reest(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, const protocol_ctxt_t *const ctxt_pP, ue_id_t ue_id) @@ -591,83 +663,18 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co } } -void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, uint8_t xid) -{ - gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - int qos_flow_index = 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]; - - if (!ue_p->DRB_configList) - ue_p->DRB_configList = CALLOC(1, sizeof(*ue_p->DRB_configList)); - if (!ue_p->DRB_configList2[xid]) - ue_p->DRB_configList2[xid] = CALLOC(1, sizeof(**ue_p->DRB_configList2)); - - for (i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].status >= PDU_SESSION_STATUS_DONE) { - continue; - } - LOG_I(NR_RRC, "adding rnti %x pdusession %d, nb drb %d, xid %d\n", ue_p->rnti, ue_p->pduSession[i].param.pdusession_id, nb_drb_to_setup, xid); - for(long drb_id_add = 1; drb_id_add <= nb_drb_to_setup; drb_id_add++){ - uint8_t drb_id; - // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping - for (qos_flow_index = 0; qos_flow_index < ue_p->pduSession[i].param.nb_qos; qos_flow_index++) { - switch (ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI) { - case 1 ... 4: /* GBR */ - drb_id = next_available_drb(ue_p, &ue_p->pduSession[i], GBR_FLOW); - break; - case 5 ... 9: /* Non-GBR */ - if(rrc->configuration.drbs > 1) /* Force the creation from gNB Conf file - Should be used only in noS1 mode and rfsim for testing purposes. */ - drb_id = next_available_drb(ue_p, &ue_p->pduSession[i], GBR_FLOW); - else - drb_id = next_available_drb(ue_p, &ue_p->pduSession[i], NONGBR_FLOW); - break; - - default: - LOG_E(NR_RRC, "not supported 5qi %lu\n", ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI); - ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED; - continue; - } - drb_priority[drb_id - 1] = ue_p->pduSession[i].param.qos[qos_flow_index].allocation_retention_priority.priority_level; - if (drb_priority[drb_id - 1] < 0 || drb_priority[drb_id - 1] > NGAP_PRIORITY_LEVEL_NO_PRIORITY) { - LOG_E(NR_RRC, "invalid allocation_retention_priority.priority_level %ld set to _NO_PRIORITY\n", drb_priority[drb_id - 1]); - drb_priority[drb_id - 1] = NGAP_PRIORITY_LEVEL_NO_PRIORITY; - } - - if(drb_is_active(ue_p, drb_id)){ /* Non-GBR flow using the same DRB or a GBR flow with no available DRBs*/ - nb_drb_to_setup--; - } else { - generateDRB(ue_p, drb_id, &ue_p->pduSession[i], rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering); - NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue_p->established_drbs[drb_id-1]); - if (drb_id_to_setup_start == 0) - drb_id_to_setup_start = DRB_config->drb_Identity; - asn1cSeqAdd(&ue_p->DRB_configList->list, DRB_config); - asn1cSeqAdd(&ue_p->DRB_configList2[xid]->list, DRB_config); - } - LOG_D(RRC, "DRB Priority %ld\n", drb_priority[drb_id]); // To supress warning for now - } - } - - ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; - ue_p->pduSession[i].xid = xid; - } -} - //----------------------------------------------------------------------------- void rrc_gNB_generate_dedicatedRRCReconfiguration(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]; - int xid = -1; + uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); int drb_id_to_setup_start = 1; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList; - int nb_drb_to_setup = DRB_configList->list.count; - + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); + int nb_drb_to_setup = DRB_configList ? DRB_configList->list.count : 0; + ue_p->xids[xid] = RRC_PDUSESSION_ESTABLISH; 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)); @@ -681,7 +688,10 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c if (ue_p->pduSession[j].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_p->pduSession[j].param.nas_pdu.buffer, ue_p->pduSession[j].param.nas_pdu.length); + OCTET_STRING_fromBuf(dedicatedNAS_Message, + (char *)ue_p->pduSession[j].param.nas_pdu.buffer, + ue_p->pduSession[j].param.nas_pdu.length); + ue_p->pduSession[j].status = PDU_SESSION_STATUS_DONE; asn1cSeqAdd(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); LOG_I(NR_RRC, "add NAS info with size %d (pdusession idx %d)\n", ue_p->pduSession[j].param.nas_pdu.length, j); @@ -690,7 +700,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c LOG_E(NR_RRC, "no NAS info (pdusession idx %d)\n", j); } - xid = ue_p->pduSession[j].xid; + ue_p->pduSession[j].xid = xid; } /* If list is empty free the list and reset the address */ @@ -701,7 +711,6 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c NR_CellGroupConfig_t *cellGroupConfig = ue_p->masterCellGroup; - AssertFatal(xid > -1, "Invalid xid %d. No PDU sessions setup to configure.\n", xid); uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); int size = do_RRCReconfiguration(ctxt_pP, @@ -730,7 +739,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c ue_p->pduSession[i].param.nas_pdu.buffer = NULL; } } - + freeDRBlist(DRB_configList); LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCReconfiguration (bytes %d, UE RNTI %x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti); 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", @@ -763,19 +772,15 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( rrc_gNB_ue_context_t *ue_context_pP) //----------------------------------------------------------------------------- { - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_DRB_ToAddModList_t *DRB_configList2 = NULL; - struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList - *dedicatedNAS_MessageList = NULL; + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); int qos_flow_index = 0; uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - ue_p->xids[xid] = RRC_DEDICATED_RECONF; + ue_p->xids[xid] = RRC_PDUSESSION_MODIFY; - DRB_configList2 = CALLOC(1, sizeof(NR_DRB_ToAddModList_t)); - memset(DRB_configList2, 0, sizeof(NR_DRB_ToAddModList_t)); - - dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = + CALLOC(1, sizeof(*dedicatedNAS_MessageList)); + NR_DRB_ToAddMod_t *DRB_config = NULL; for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { // bypass the new and already configured pdu sessions @@ -830,7 +835,6 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( ue_p->pduSession[i].cause_value = NGAP_CauseRadioNetwork_not_supported_5QI_value; continue; } - LOG_I(NR_RRC, "PDU SESSION ID %ld, DRB ID %ld (index %d), QOS flow %d, 5QI %ld \n", DRB_config->cnAssociation->choice.sdap_Config->pdu_Session, @@ -840,7 +844,7 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI); } - asn1cSeqAdd(&DRB_configList2->list, DRB_config); + asn1cSeqAdd(&DRB_configList->list, DRB_config); ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; ue_p->pduSession[i].xid = xid; @@ -862,21 +866,21 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( uint8_t buffer[RRC_BUF_SIZE]; int size = do_RRCReconfiguration(ctxt_pP, - buffer, - RRC_BUF_SIZE, - xid, - NULL, - DRB_configList2, - NULL, - NULL, - NULL, - NULL, - dedicatedNAS_MessageList, - NULL, - NULL, - NULL, - NULL, - NULL); + buffer, + RRC_BUF_SIZE, + xid, + NULL, + DRB_configList, + NULL, + NULL, + NULL, + NULL, + dedicatedNAS_MessageList, + NULL, + NULL, + NULL, + NULL, + NULL); LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); /* Free all NAS PDUs */ @@ -922,37 +926,23 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( uint8_t *nas_buffer) //----------------------------------------------------------------------------- { - int i; - NR_DRB_ToReleaseList_t **DRB_Release_configList2 = NULL; - NR_DRB_Identity_t *DRB_release; - struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList - *dedicatedNAS_MessageList = NULL; - NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - DRB_Release_configList2 = &ue_p->DRB_Release_configList2[xid]; - if (*DRB_Release_configList2) { - free(*DRB_Release_configList2); - } + NR_DRB_ToReleaseList_t *DRB_Release_configList2 = CALLOC(sizeof(*DRB_Release_configList2), 1); - *DRB_Release_configList2 = CALLOC(1, sizeof(**DRB_Release_configList2)); - for(i = 0; i < NB_RB_MAX; i++) { + for (int i = 0; i < NB_RB_MAX; i++) { if ((ue_p->pduSession[i].status == PDU_SESSION_STATUS_TORELEASE) && ue_p->pduSession[i].xid == xid) { - DRB_release = CALLOC(1, sizeof(NR_DRB_Identity_t)); - *DRB_release = i+1; - asn1cSeqAdd(&(*DRB_Release_configList2)->list, DRB_release); + asn1cSequenceAdd(DRB_Release_configList2->list, NR_DRB_Identity_t, DRB_release); + *DRB_release = i + 1; } } /* If list is empty free the list and reset the address */ + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = NULL; if (nas_length > 0) { - dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); - dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); - memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); - OCTET_STRING_fromBuf(dedicatedNAS_Message, - (char *)nas_buffer, - nas_length); - asn1cSeqAdd(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); + dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList)); + asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, dedicatedNAS_Message); + OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)nas_buffer, nas_length); LOG_I(NR_RRC,"add NAS info with size %d\n", nas_length); } else { LOG_W(NR_RRC,"dedlicated NAS list is empty\n"); @@ -965,7 +955,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( xid, NULL, NULL, - *DRB_Release_configList2, + DRB_Release_configList2, NULL, NULL, NULL, @@ -1019,10 +1009,7 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co uint8_t kUPenc[16] = {0}; uint8_t kUPint[16] = {0}; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList2[xid]; - NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_p->DRB_Release_configList2[xid]; - NR_DRB_Identity_t *drb_id_p = NULL; - // uint8_t nr_DRB2LCHAN[8]; + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); /* Derive the keys from kgnb */ if (DRB_configList != NULL) { @@ -1127,25 +1114,8 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co } // end if (DRB_configList->list.array[i]) } // end for (int i = 0; i < DRB_configList->list.count; i++) - free(DRB_configList); - ue_p->DRB_configList2[xid] = NULL; } // end if DRB_configList != NULL - - if(DRB_Release_configList2 != NULL) { - for (int i = 0; i < DRB_Release_configList2->list.count; i++) { - if (DRB_Release_configList2->list.array[i]) { - drb_id_p = DRB_Release_configList2->list.array[i]; - drb_id = *drb_id_p; - - if (ue_p->DRB_active[drb_id] == 1) { - ue_p->DRB_active[drb_id] = 0; - } - } - } - - free(DRB_Release_configList2); - ue_p->DRB_Release_configList2[xid] = NULL; - } + freeDRBlist(DRB_configList); } //----------------------------------------------------------------------------- @@ -1219,35 +1189,6 @@ void rrc_gNB_generate_RRCReestablishment(const protocol_ctxt_t *ctxt_pP, nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); } -/// @brief Function used in RRCReestablishmentComplete procedure to reestablish the DRBs -/// that the UE previously had, it gets the information from the established_drbs -/// struct. -/// @param new_xid The new RRC transaction id. -void RRCReestablishmentComplete_fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP, - const uint8_t new_xid) -{ - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_DRB_ToAddModList_t **DRB_configList2 = &(ue_p->DRB_configList2[new_xid]); - - if (*DRB_configList2) { - free(*DRB_configList2); - LOG_D(NR_RRC, "RRC Reestablishment - free(ue_p->DRB_configList2[%d])\n", new_xid); - } - - *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - - for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { - if (ue_p->established_drbs[i].status != DRB_INACTIVE) { - ue_p->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; - DRB_config = generateDRB_ASN1(&ue_p->established_drbs[i]); - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); - asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); - } - } -} - /// @brief Function used in RRCReestablishmentComplete procedure to update the NGU Tunnels. /// @param reestablish_rnti is the old C-RNTI void RRCReestablishmentComplete_update_ngu_tunnel(const protocol_ctxt_t *const ctxt_pP, @@ -1349,7 +1290,6 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx nr_rrc_pdcp_config_security(ctxt_pP, ue_context_pP, send_security_mode_command); LOG_D(NR_RRC, "RRC Reestablishment - set security successfully \n"); } - RRCReestablishmentComplete_fill_DRB_configList(ctxt_pP, ue_context_pP, new_xid); RRCReestablishmentComplete_update_ngu_tunnel(ctxt_pP, ue_context_pP, reestablish_rnti); RRCReestablishmentComplete_nas_pdu_update(ue_context_pP, xid); @@ -1377,11 +1317,11 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx asn1cSeqAdd(&cellGroupConfig->rlc_BearerToAddModList->list, ue_p->masterCellGroup->rlc_BearerToAddModList->list.array[i]); for (i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { - cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = - CALLOC(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC)); - *cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = NR_RLC_BearerConfig__reestablishRLC_true; + asn1cCallocOne(cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC, + NR_RLC_BearerConfig__reestablishRLC_true); } + NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, true); int size = do_RRCReconfiguration(ctxt_pP, @@ -1389,7 +1329,7 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx RRC_BUF_SIZE, new_xid, SRBs, - ue_p->DRB_configList2[new_xid], + DRB_configList, NULL, NULL, NULL, @@ -1401,7 +1341,7 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx NULL, cellGroupConfig); freeSRBlist(SRBs); - + freeDRBlist(DRB_configList); LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); RRCReestablishmentComplete_nas_pdu_free(ue_context_pP); @@ -2364,7 +2304,7 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i // send the F1 response message up to update F1-U tunnel info // it seems the rrc transaction id (xid) is not needed here - rrc->cucp_cuup.bearer_context_mod(&req, instance, 0); + rrc->cucp_cuup.bearer_context_mod(&req, instance); } if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index cb763f0583..f0a7f3b90f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -278,9 +278,6 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) static int decodePDUSessionResourceSetup(pdusession_t *session) { NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL; - for (int i=0; ipdusessionTransfer.length; i++) - printf("%02x:",session->pdusessionTransfer.buffer[i]); - printf("\n"); asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; asn_dec_rval_t dec_rval = aper_decode(&st, &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, (void **)&pdusessionTransfer, session->pdusessionTransfer.buffer, session->pdusessionTransfer.length, 0, 0); @@ -819,7 +816,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins } int xid = rrc_gNB_get_next_transaction_identifier(instance); UE->xids[xid] = RRC_PDUSESSION_ESTABLISH; - rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance, xid); + rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance); return; } From 7e7b3c13f1ab1ae664982b6f8a16ddbe9ac5b2e3 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 6 Jul 2023 09:01:04 +0100 Subject: [PATCH 68/87] Fix multiple PDUSessions --- openair2/E1AP/e1ap.c | 9 ++- openair2/RRC/NR/rrc_gNB.c | 80 ++++++++++++++++--------- openair2/RRC/NR/rrc_gNB_NGAP.c | 8 ++- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 10 ++++ 4 files changed, 77 insertions(+), 30 deletions(-) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 6c33ddf973..7a1954f714 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -589,7 +589,14 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_beare 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->dRB_ID = ieC6_1->pDU_Session_ID; + LOG_W(E1AP, + "%s: %d Current implementation configures one DRB per PDUSession, ieC6_1->pDU_Session_ID %ld, ieC6_1_1->dRB_ID %ld\n", + __FUNCTION__, + __LINE__, + ieC6_1->pDU_Session_ID, + ieC6_1_1->dRB_ID); ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB; ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sDAP_Header_UL; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 0113792030..a23c260612 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -113,6 +113,44 @@ mui_t rrc_gNB_mui = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// + +static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) +{ + if (!ue->Srb[1].Active) { + LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); + return NULL; + } + NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); + for (int i = 0; i < maxSRBs; i++) { + if (ue->Srb[i].Active) { + asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); + srb->srb_Identity = i; + if (reestablish && i == 2) { + asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); + } + } + } + return list; +} + +static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) +{ + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); + + for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if (ue->established_drbs[i].status != DRB_INACTIVE) { + ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; + DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); + if (reestablish) { + asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + } + asn1cSeqAdd(&DRB_configList->list, DRB_config); + } + } + return DRB_configList; +} + NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) { gNB_RRC_INST *rrc = RC.nrrrc[0]; @@ -374,24 +412,6 @@ unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP) return tmp; } -static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) -{ - if (!ue->Srb[1].Active) { - LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); - return NULL; - } - NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); - for (int i = 0; i < maxSRBs; i++) - if (ue->Srb[i].Active) { - asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); - srb->srb_Identity = i; - if (reestablish && i == 2) { - asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); - } - } - return list; -} - static void freeSRBlist(NR_SRB_ToAddModList_t *l) { if (l) { @@ -702,6 +722,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c ue_p->pduSession[j].xid = xid; } + freeDRBlist(DRB_configList); /* If list is empty free the list and reset the address */ if (dedicatedNAS_MessageList->list.count == 0) { @@ -709,16 +730,27 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c dedicatedNAS_MessageList = NULL; } + /* Free all NAS PDUs */ + for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { + if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_p->pduSession[i].param.nas_pdu.buffer); + ue_p->pduSession[i].param.nas_pdu.buffer = NULL; + } + } + NR_CellGroupConfig_t *cellGroupConfig = ue_p->masterCellGroup; uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); + NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); + int size = do_RRCReconfiguration(ctxt_pP, buffer, RRC_BUF_SIZE, xid, SRBs, - DRB_configList, + DRBs, NULL, NULL, NULL, @@ -731,15 +763,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c cellGroupConfig); LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n"); freeSRBlist(SRBs); - /* Free all NAS PDUs */ - for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { - /* Free the NAS PDU buffer and invalidate it */ - free(ue_p->pduSession[i].param.nas_pdu.buffer); - ue_p->pduSession[i].param.nas_pdu.buffer = NULL; - } - } - freeDRBlist(DRB_configList); + freeDRBlist(DRBs); LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCReconfiguration (bytes %d, UE RNTI %x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti); 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", diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index f0a7f3b90f..fd31004a17 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -778,7 +778,13 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins for (int j=0; j < pdu->numDRB2Setup; j++) { DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; - drb->id = i + j + UE->nb_of_pdusessions; + drb->id = session->pdusession_id; + LOG_W(NR_RRC, + "%s: %d Current implementation configures one DRB per PDUSession, session->pdusession_id %d, drb->id %ld\n", + __FUNCTION__, + __LINE__, + session->pdusession_id, + drb->id); drb->defaultDRB = E1AP_DefaultDRB_true; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 9e6e7961d6..57dcd35a9b 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -147,6 +147,16 @@ uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession { uint8_t drb_id; + drb_id = pdusession->param.pdusession_id; + LOG_W(NR_RRC, + "%s: %d Current implementation configures one DRB per PDUSession, pdusession_id %d, drb_id %d\n", + __FUNCTION__, + __LINE__, + pdusession->param.pdusession_id, + drb_id); + + return drb_id; + if(!is_gbr) { /* Find if Non-GBR DRB exists in the same PDU Session */ for (drb_id = 0; drb_id < NGAP_MAX_DRBS_PER_UE; drb_id++) if (pdusession->param.used_drbs[drb_id] == DRB_ACTIVE_NONGBR) From 1fdf71e1db5bf12abc0bca6f380dbe468d53b60e Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 6 Jul 2023 19:45:10 +0200 Subject: [PATCH 69/87] Address review comments --- openair2/RRC/NR/cucp_cuup_direct.c | 2 ++ openair2/RRC/NR/rrc_gNB.c | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c index 49f95c82f7..9c4e6462a4 100644 --- a/openair2/RRC/NR/cucp_cuup_direct.c +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -187,6 +187,8 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(UE); int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, DRB_configList, rrc->e1_inst); if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n"); + // the code is very badly organized, it is not possible here to call freeDRBlist() + ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList,DRB_configList ); // Used to store teids: if monolithic, will simply be NULL if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a23c260612..05df1da23c 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -133,7 +133,10 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) return list; } -static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) +// not clear what this function do against fill_DRB_configList() +// it sets reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true +// else it should probably be removed and merged into fill_DRB_configList +static NR_DRB_ToAddModList_t *createDRBlistReestablish(gNB_RRC_UE_t *ue) { NR_DRB_ToAddMod_t *DRB_config = NULL; NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); @@ -142,9 +145,6 @@ static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) if (ue->established_drbs[i].status != DRB_INACTIVE) { ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); - if (reestablish) { - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); - } asn1cSeqAdd(&DRB_configList->list, DRB_config); } } @@ -220,6 +220,7 @@ NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) static void freeDRBlist(NR_DRB_ToAddModList_t *list) { + //ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, list); return; } static void nr_rrc_addmod_srbs(int rnti, @@ -743,7 +744,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); - NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); + NR_DRB_ToAddModList_t *DRBs = createDRBlistReestablish(ue_p); int size = do_RRCReconfiguration(ctxt_pP, buffer, From 4deb58339b20fe6393dd10900cb547506b5bbc01 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Fri, 7 Jul 2023 11:01:04 +0100 Subject: [PATCH 70/87] Fix multiple PDUSessions after review, now DRBs are configured sequentially, no matter what PDUSession id we receive --- openair2/E1AP/e1ap.c | 9 +- openair2/RRC/NR/rrc_gNB.c | 112 ++++++++++++------------ openair2/RRC/NR/rrc_gNB_NGAP.c | 8 +- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 18 +--- 4 files changed, 63 insertions(+), 84 deletions(-) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 7a1954f714..6c33ddf973 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -589,14 +589,7 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_beare 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 = ieC6_1->pDU_Session_ID; - LOG_W(E1AP, - "%s: %d Current implementation configures one DRB per PDUSession, ieC6_1->pDU_Session_ID %ld, ieC6_1_1->dRB_ID %ld\n", - __FUNCTION__, - __LINE__, - ieC6_1->pDU_Session_ID, - ieC6_1_1->dRB_ID); + 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; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 05df1da23c..776c6b9275 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -114,43 +114,6 @@ mui_t rrc_gNB_mui = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// -static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) -{ - if (!ue->Srb[1].Active) { - LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); - return NULL; - } - NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); - for (int i = 0; i < maxSRBs; i++) { - if (ue->Srb[i].Active) { - asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); - srb->srb_Identity = i; - if (reestablish && i == 2) { - asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); - } - } - } - return list; -} - -// not clear what this function do against fill_DRB_configList() -// it sets reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true -// else it should probably be removed and merged into fill_DRB_configList -static NR_DRB_ToAddModList_t *createDRBlistReestablish(gNB_RRC_UE_t *ue) -{ - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); - - for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { - if (ue->established_drbs[i].status != DRB_INACTIVE) { - ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; - DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); - asn1cSeqAdd(&DRB_configList->list, DRB_config); - } - } - return DRB_configList; -} - NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue) { gNB_RRC_INST *rrc = RC.nrrrc[0]; @@ -413,6 +376,42 @@ unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP) return tmp; } +static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) +{ + if (!ue->Srb[1].Active) { + LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); + return NULL; + } + NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); + for (int i = 0; i < maxSRBs; i++) + if (ue->Srb[i].Active) { + asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); + srb->srb_Identity = i; + if (reestablish && i == 2) { + asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); + } + } + return list; +} + +static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) +{ + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); + + for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if (ue->established_drbs[i].status != DRB_INACTIVE) { + DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); + if (reestablish) { + ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; + asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + } + asn1cSeqAdd(&DRB_configList->list, DRB_config); + } + } + return DRB_configList; +} + static void freeSRBlist(NR_SRB_ToAddModList_t *l) { if (l) { @@ -744,7 +743,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); - NR_DRB_ToAddModList_t *DRBs = createDRBlistReestablish(ue_p); + NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); int size = do_RRCReconfiguration(ctxt_pP, buffer, @@ -1034,7 +1033,7 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co uint8_t kUPenc[16] = {0}; uint8_t kUPint[16] = {0}; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); + NR_DRB_ToAddModList_t *DRB_configList = createDRBlist(ue_p, false); /* Derive the keys from kgnb */ if (DRB_configList != NULL) { @@ -1048,18 +1047,20 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co /* Refresh SRBs/DRBs */ LOG_D(NR_RRC, "Configuring PDCP DRBs/SRBs for UE %04x\n", ue_p->rnti); ue_id_t reestablish_ue_id = 0; - if (DRB_configList && DRB_configList->list.array[0]->reestablishPDCP && *DRB_configList->list.array[0]->reestablishPDCP == NR_DRB_ToAddMod__reestablishPDCP_true) { - for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { - nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &(RC.nrrrc[ctxt_pP->module_id])->nr_reestablish_rnti_map[i]; - if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) { - ue_context_pP->ue_context.ue_reconfiguration_after_reestablishment_counter++; - reestablish_ue_id = nr_reestablish_rnti_map[i].c_rnti; - LOG_D(NR_RRC, "Removing reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", i, nr_reestablish_rnti_map->ue_id, nr_reestablish_rnti_map->c_rnti); - // clear current C-RNTI from map - nr_reestablish_rnti_map->ue_id = 0; - nr_reestablish_rnti_map->c_rnti = 0; - break; - } + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &(RC.nrrrc[ctxt_pP->module_id])->nr_reestablish_rnti_map[i]; + if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) { + ue_context_pP->ue_context.ue_reconfiguration_after_reestablishment_counter++; + reestablish_ue_id = nr_reestablish_rnti_map[i].c_rnti; + LOG_D(NR_RRC, + "Removing reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", + i, + nr_reestablish_rnti_map->ue_id, + nr_reestablish_rnti_map->c_rnti); + // clear current C-RNTI from map + nr_reestablish_rnti_map->ue_id = 0; + nr_reestablish_rnti_map->c_rnti = 0; + break; } } NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); @@ -1346,15 +1347,16 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx NR_RLC_BearerConfig__reestablishRLC_true); } - NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(ue_p); - uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, true); + NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, true); + + uint8_t buffer[RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ctxt_pP, buffer, RRC_BUF_SIZE, new_xid, SRBs, - DRB_configList, + DRBs, NULL, NULL, NULL, @@ -1366,7 +1368,7 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx NULL, cellGroupConfig); freeSRBlist(SRBs); - freeDRBlist(DRB_configList); + freeDRBlist(DRBs); LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); RRCReestablishmentComplete_nas_pdu_free(ue_context_pP); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index fd31004a17..f0a7f3b90f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -778,13 +778,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins for (int j=0; j < pdu->numDRB2Setup; j++) { DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; - drb->id = session->pdusession_id; - LOG_W(NR_RRC, - "%s: %d Current implementation configures one DRB per PDUSession, session->pdusession_id %d, drb->id %ld\n", - __FUNCTION__, - __LINE__, - session->pdusession_id, - drb->id); + drb->id = i + j + UE->nb_of_pdusessions; drb->defaultDRB = E1AP_DefaultDRB_true; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 57dcd35a9b..4c5c50fb00 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -147,25 +147,15 @@ uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession { uint8_t drb_id; - drb_id = pdusession->param.pdusession_id; - LOG_W(NR_RRC, - "%s: %d Current implementation configures one DRB per PDUSession, pdusession_id %d, drb_id %d\n", - __FUNCTION__, - __LINE__, - pdusession->param.pdusession_id, - drb_id); - - return drb_id; - - if(!is_gbr) { /* Find if Non-GBR DRB exists in the same PDU Session */ + if (0 /*!is_gbr*/) { /* Find if Non-GBR DRB exists in the same PDU Session */ for (drb_id = 0; drb_id < NGAP_MAX_DRBS_PER_UE; drb_id++) if (pdusession->param.used_drbs[drb_id] == DRB_ACTIVE_NONGBR) - return drb_id+1; + return drb_id + 1; } /* GBR Flow or a Non-GBR DRB does not exist in the same PDU Session, find an available DRB */ for (drb_id = 0; drb_id < NGAP_MAX_DRBS_PER_UE; drb_id++) - if(ue->DRB_active[drb_id] == DRB_INACTIVE) - return drb_id+1; + if (ue->DRB_active[drb_id] == DRB_INACTIVE) + return drb_id + 1; /* From this point, we need to handle the case that all DRBs are already used by the UE. */ LOG_E(RRC, "Error - All the DRBs are used - Handle this\n"); return DRB_INACTIVE; From cfc7a70f9a205726414e83e822e2eeb42c5df6f0 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 26 Jun 2023 09:30:53 +0200 Subject: [PATCH 71/87] bugfix in ue msg3 scheduler --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b60e0199a2..52b5bd75dd 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1459,7 +1459,7 @@ int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, uint8_t is_Msg3, frame_t curren DURATION_RX_TO_TX); *slot_tx = (current_slot + k2 + delta) % nr_slots_per_frame[mu]; - if (current_slot + k2 + delta > nr_slots_per_frame[mu]){ + if (current_slot + k2 + delta >= nr_slots_per_frame[mu]){ *frame_tx = (current_frame + 1) % 1024; } else { *frame_tx = current_frame; From 0449ab7908c741ff5ab9517877651617492b347f Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 9 Jun 2023 10:25:07 +0200 Subject: [PATCH 72/87] further cleanup of config files for CI --- ...gnb.band261.32PRB.rfsim.phytest-dora.conf} | 0 ...gnb.band66.106prb.rfsim.phytest-dora.conf} | 0 ...gnb.band78.106PRB.rfsim.phytest-dora.conf} | 0 ...b.band78.106PRB.usrpn300.phytest-dora.conf | 260 ++++++++++++++++++ ....band78.162PRB.usrpn300.phytest-dora.conf} | 0 ...b.band78.sa.106PRB.2x2.usrpn310.asue.conf} | 0 ...=> gnb.band78.sa.106PRB.2x2.usrpn310.conf} | 0 ....band78.sa.106PRB.ddsuu.2x2.usrpn310.conf} | 0 ...=> gnb.band78.sa.162PRB.2x2.usrpn310.conf} | 0 ...10.conf => gnb.sa.band78.24PRB.rfsim.conf} | 0 .../gnb.band78.tm1.fr1.106PRB.usrpn310.conf | 0 .../xml_files/fr1_sa_amarisoft_ue_1x.xml | 2 +- ci-scripts/xml_files/fr1_sa_oaiue_n310.xml | 2 +- ci-scripts/xml_files/fr1_sa_quectel.xml | 2 +- .../xml_files/fr1_sa_quectel_162prb.xml | 2 +- .../xml_files/fr1_sa_quectel_stages.xml | 2 +- ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml | 2 +- .../gnb_nr_ue_usrp_run_multi_thread.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run.xml | 2 +- .../xml_files/gnb_phytest_usrp_run_60.xml | 2 +- .../xml_files/gnb_phytest_usrp_run_60_2x2.xml | 2 +- .../5g_rfsimulator_24prb/docker-compose.yaml | 2 +- .../docker-compose.yaml | 2 +- .../docker-compose.yaml | 2 +- .../docker-compose.yaml | 2 +- 25 files changed, 274 insertions(+), 14 deletions(-) rename ci-scripts/conf_files/{gnb.band261.tm1.32PRB.usrpn300.conf => gnb.band261.32PRB.rfsim.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band66.tm1.106PRB.usrpn300.conf => gnb.band66.106prb.rfsim.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.tm1.106PRB.usrpn300.conf => gnb.band78.106PRB.rfsim.phytest-dora.conf} (100%) create mode 100644 ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf rename ci-scripts/conf_files/{gnb.band78.tm1.162PRB.usrpn300.conf => gnb.band78.162PRB.usrpn300.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.sa.fr1.106PRB.2x2.usrpn310.asue.conf => gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf => gnb.band78.sa.106PRB.2x2.usrpn310.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.sa.fr1.106PRB.ddsuu.2x2.usrpn310.conf => gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf => gnb.band78.sa.162PRB.2x2.usrpn310.conf} (100%) rename ci-scripts/conf_files/{gnb.sa.band78.fr1.24PRB.usrpb210.conf => gnb.sa.band78.24PRB.rfsim.conf} (100%) rename ci-scripts/conf_files/{ => untested}/gnb.band78.tm1.fr1.106PRB.usrpn310.conf (100%) diff --git a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf rename to ci-scripts/conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf rename to ci-scripts/conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf rename to ci-scripts/conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf new file mode 100644 index 0000000000..453b03910b --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf @@ -0,0 +1,260 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 99; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + min_rxtxtime = 6; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #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=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; +# 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 = 6368; +# 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 = -118; +#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 = 15; +#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; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + port = 36412 ; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; +} +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 50; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +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 ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + }; + diff --git a/ci-scripts/conf_files/gnb.band78.tm1.162PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.tm1.162PRB.usrpn300.conf rename to ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.asue.conf b/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.asue.conf rename to ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.ddsuu.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.ddsuu.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf diff --git a/ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf similarity index 100% rename from ci-scripts/conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf rename to ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpn310.conf rename to ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf diff --git a/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml b/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml index c34fa34cf1..c00e47223a 100644 --- a/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml +++ b/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml @@ -87,7 +87,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.asue.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml index 7105828be4..ec99cedf94 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml @@ -68,7 +68,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml index b13de6f3ef..c23ae0b540 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel.xml @@ -86,7 +86,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.ddsuu.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml index d1c250862d..0544c82de2 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml @@ -70,7 +70,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml index 94cf5d71ef..0b840b7782 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml @@ -91,7 +91,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml index dd2b15a4f2..53636de6a1 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml @@ -33,7 +33,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test --log_config.global_log_options level,nocolor,time NR diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml index 7c9d689e44..af48f00d5a 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml @@ -33,7 +33,7 @@ Initialize_eNB Initialize gNB USRP (Tx-Write-Threading enabled) - -O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time NR diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml index 382efbdd9e..c98796890f 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.default.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml index 24b0854224..3d91d55dfa 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.tm1.162PRB.usrpn300.conf --phy-test -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.1x1.60.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml index 29d284886c..6231f45169 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.tm1.162PRB.usrpn300.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.60.2x2.yaml NR 192.168.20.2 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index f076cf2db0..600f34cbc2 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -175,7 +175,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.sa.band78.fr1.24PRB.usrpb210.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band78.24PRB.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml index b654f06d12..d93a4b1051 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band66.tm1.106PRB.usrpn300.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index eef67d713b..63293cf628 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band261.tm1.32PRB.usrpn300.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml index ed2af44fbb..b3afb48e8d 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band78.tm1.106PRB.usrpn300.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" From 8048ea485b4c406526cba965d6b3071efdefa7aa Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 9 Jun 2023 11:10:29 +0200 Subject: [PATCH 73/87] Remove old unused config file of gNB and XML for Amarisoft ue test --- ...nb.band78.sa.106PRB.2x2.usrpn310.asue.conf | 282 ------------------ .../xml_files/fr1_sa_amarisoft_ue_1x.xml | 124 -------- 2 files changed, 406 deletions(-) delete mode 100644 ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf delete mode 100644 ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml diff --git a/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf b/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf deleted file mode 100644 index a723e3a4b7..0000000000 --- a/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf +++ /dev/null @@ -1,282 +0,0 @@ -Active_gNBs = ( "gNB-OAI"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -gNBs = -( - { - ////////// Identification parameters: - gNB_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 = 97; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0x010203 }) }); - - nr_cellid = 12345678L - -# tr_s_preference = "local_mac" - - ////////// Physical parameters: - - pusch_AntennaPorts = 2; - pdsch_AntennaPorts_XP = 2; - ul_prbblacklist = "51,52,53,54" - do_SRS = 0; - do_CSIRS = 1; - - servingCellConfigCommon = ( - { - #spCellConfigCommon - - physCellId = 0; - -# downlinkConfigCommon - #frequencyInfoDL - # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 - #absoluteFrequencySSB = 620640; - # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 - absoluteFrequencySSB = 621312; - # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 - #absoluteFrequencySSB = 634080; - # this is 3600.48 MHz - #absoluteFrequencySSB = 640032; - #dl_frequencyBand = 78; - # this is 3301.68 MHz - #dl_absoluteFrequencyPointA = 620112; - # this is 3300.60 MHz - dl_absoluteFrequencyPointA = 620040; - # this is 3502.56 MHz - #dl_absoluteFrequencyPointA = 633552; - # this is 3600.48 MHz - #dl_absoluteFrequencyPointA = 640032; - #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=0,L=106 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 28875; -# 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 = 12; - preambleReceivedTargetPower = -104; -#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 = 3; -#oneHalf (0..15) 4,8,12,16,...60,64 - ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; -#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 = "CI_MME_IP_ADDR"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - NETWORK_INTERFACES : - { - - GNB_INTERFACE_NAME_FOR_NG_AMF = "em1"; - GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR"; - GNB_INTERFACE_NAME_FOR_NGU = "em1"; - GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - - } -); - -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 220; - pucch_TargetSNRx10 = 220; - ulsch_max_frame_inactivity = 10; - } -); - -L1s = ( -{ - num_cc = 1; - tr_n_preference = "local_mac"; - prach_dtx_threshold = 200; -# pucch0_dtx_threshold = 150; -} -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 2 - nb_rx = 2 - att_tx = 0 - att_rx = 0; - bands = [78]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 75; - eNB_instances = [0]; - ##beamforming 1x2 matrix: 1 layer x 2 antennas - bf_weights = [0x00007fff, 0x0000]; - ##beamforming 1x4 matrix: 1 layer x 4 antennas - #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; - ## beamforming 2x2 matrix: - # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; - ## beamforming 4x4 matrix: - #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; - sf_extension = 0 - sdr_addrs = "mgmt_addr=172.21.19.14,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=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"; - } -); - -security = { - # preferred ciphering algorithms - # the first one of the list that an UE supports in chosen - # valid values: nea0, nea1, nea2, nea3 - ciphering_algorithms = ( "nea2" ); - - # preferred integrity algorithms - # the first one of the list that an UE supports in chosen - # valid values: nia0, nia1, nia2, nia3 - integrity_algorithms = ( "nia1", "nia2" ); - - # 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 = "yes"; -}; - - log_config : - { - global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="info"; - pdcp_log_level ="info"; - rrc_log_level ="info"; - f1ap_log_level ="info"; - }; diff --git a/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml b/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml deleted file mode 100644 index c00e47223a..0000000000 --- a/ci-scripts/xml_files/fr1_sa_amarisoft_ue_1x.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - TEST-SA-FR1-Tab1 - SA Ping DL UL with 1 AS UE - tasks - 1 - - 100000 - 010000 - 040000 - 010001 - 010002 - 050000 - 010100 - 010200 - 011111 - 080000 - 200000 - - - - - Custom_Command - Disable Sleep States - asterix - sudo cpupower idle-set -D 0 - - - Custom_Command - Enable Sleep States - asterix - sudo cpupower idle-set -E - - - - Initialize_UE - Initialize AS-UE Scenario - amarisoft_ue - - - Attach_UE - Attach UE - amarisoft_ue_1 - - - Attach_UE - Attach UE - amarisoft_ue_2 - - - Detach_UE - Detach UE - amarisoft_ue_1 - - - Detach_UE - Detach UE - amarisoft_ue_2 - - - Terminate_UE - Terminate UE - amarisoft_ue - - - - Initialize_eNB - Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.asue.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time - 0 - 0 - nr - yes - yes - datalog_rt_stats.2x2.yaml - 172.21.19.14 - numactl --cpunodebind=netdev:ens2f0np0 --membind=netdev:ens2f0np0 - - - - Ping - Ping Log Analysis - amarisoft_ue_1 amarisoft_ue_2 - 1 - - - - IdleSleep - Sleep - 5 - - - - - Terminate_eNB - Terminate gNB - 0 - 0 - nr - - - - From 0409dcf5ee84c4bd3679c842153a1b747c603311 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 9 Jun 2023 12:18:56 +0200 Subject: [PATCH 74/87] Rename sa-2x2-usrpn310 config and correct in XMLs using the same --- ....2x2.usrpn310.conf => gnb.sa.band78.106prb.usrp310.2x2.conf} | 0 ci-scripts/xml_files/fr1_sa_oaiue_n310.xml | 2 +- ci-scripts/xml_files/fr1_sa_quectel_stages.xml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename ci-scripts/conf_files/{gnb.band78.sa.106PRB.2x2.usrpn310.conf => gnb.sa.band78.106prb.usrp310.2x2.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml index ec99cedf94..73cb246391 100644 --- a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml +++ b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml @@ -68,7 +68,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf --gNBs.[0].min_rxtxtime 5 --sa --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --gNBs.[0].min_rxtxtime 5 --log_config.global_log_options level,nocolor,time 0 0 nr diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml index 0b840b7782..8900462ad1 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml @@ -91,7 +91,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr From 23c1d4e63cdb34484eac0409762a4ada88131db1 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 9 Jun 2023 12:26:41 +0200 Subject: [PATCH 75/87] Rename sa-2x2-ddsuu config file and correct in XML file using the same --- ...rpn310.conf => gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf} | 0 ci-scripts/xml_files/fr1_sa_quectel.xml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ci-scripts/conf_files/{gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf => gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml index c23ae0b540..33a817f2e8 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel.xml @@ -86,7 +86,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.106PRB.ddsuu.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr From 8f4ccdcf3c857e940cbc3420890e3ec2dca1f324 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 9 Jun 2023 12:30:30 +0200 Subject: [PATCH 76/87] Rename sa-162prb config file and correct in XML using it --- ...2x2.usrpn310.conf => gnb.sa.band78.162prb.usrpn310.2x2.conf} | 0 ci-scripts/xml_files/fr1_sa_quectel_162prb.xml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ci-scripts/conf_files/{gnb.band78.sa.162PRB.2x2.usrpn310.conf => gnb.sa.band78.162prb.usrpn310.2x2.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf rename to ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf diff --git a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml index 0544c82de2..0a60cb5d7a 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml @@ -70,7 +70,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.sa.162PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf --sa -q --usrp-tx-thread-config 1 --tune-offset 30000000 --thread-pool 1,3,5,7,9,11,13,15 --log_config.global_log_options level,nocolor,time 0 0 nr From 7e6124bb54bc580d4dde096d94321eb02dfd8026 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 9 Jun 2023 18:01:13 +0200 Subject: [PATCH 77/87] Cleanup in rfsim config files --- .../gnb.nsa.band78.106prb.usrpb200.conf | 2 +- .../gnb.sa.band78.106prb.rfsim.2x2.conf | 4 ++-- .../conf_files/gnb.sa.band78.106prb.rfsim.conf | 18 ------------------ .../gnb.sa.band78.106prb.usrp310.2x2.conf | 14 -------------- ...nb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf | 1 - .../gnb.sa.band78.162prb.usrpn310.2x2.conf | 3 --- .../conf_files/gnb.sa.band78.24PRB.rfsim.conf | 2 +- .../gnb.sa.band78.51prb.usrpb200.conf | 2 -- 8 files changed, 4 insertions(+), 42 deletions(-) diff --git a/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf index 53b81d0ae1..46b0c4f8d4 100644 --- a/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf @@ -29,7 +29,7 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) - absoluteFrequencySSB = 641272; //641032; #641968; 641968=start of ssb at 3600MHz + 82 RBs 641032=center of SSB at center of cell + absoluteFrequencySSB = 641272; dl_frequencyBand = 78; # this is 3600 MHz dl_absoluteFrequencyPointA = 640000; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf index cc70829aae..60b1e92f9e 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf @@ -32,10 +32,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 - absoluteFrequencySSB = 621312; # 641280 + absoluteFrequencySSB = 621312; dl_frequencyBand = 78; # this is 3300.60 MHz - dl_absoluteFrequencyPointA = 620040; # 640008 + dl_absoluteFrequencyPointA = 620040; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf index 9728977d21..61ec78328c 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf @@ -23,11 +23,7 @@ gNBs = ////////// Physical parameters: - #pusch_TargetSNRx10 = 200; - #pucch_TargetSNRx10 = 200; - ul_prbblacklist = "51,52,53,54" min_rxtxtime = 6; - do_SRS = 1; servingCellConfigCommon = ( { @@ -37,23 +33,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 - #absoluteFrequencySSB = 620640; # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 absoluteFrequencySSB = 621312; - # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 - #absoluteFrequencySSB = 634080; - # this is 3600.48 MHz - #absoluteFrequencySSB = 640032; - #dl_frequencyBand = 78; - # this is 3301.68 MHz - #dl_absoluteFrequencyPointA = 620112; # this is 3300.60 MHz dl_absoluteFrequencyPointA = 620040; - # this is 3502.56 MHz - #dl_absoluteFrequencyPointA = 633552; - # this is 3600.48 MHz - #dl_absoluteFrequencyPointA = 640032; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -208,7 +191,6 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200; - ulsch_max_frame_inactivity = 1; } ); diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf index f5c0e23670..480bb45637 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf @@ -25,7 +25,6 @@ gNBs = pdsch_AntennaPorts_XP = 2; pusch_AntennaPorts = 2; - do_SRS = 0; servingCellConfigCommon = ( { @@ -35,23 +34,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 - #absoluteFrequencySSB = 620640; # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 absoluteFrequencySSB = 621312; - # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 - #absoluteFrequencySSB = 634080; - # this is 3600.48 MHz - #absoluteFrequencySSB = 640032; - #dl_frequencyBand = 78; - # this is 3301.68 MHz - #dl_absoluteFrequencyPointA = 620112; # this is 3300.60 MHz dl_absoluteFrequencyPointA = 620040; - # this is 3502.56 MHz - #dl_absoluteFrequencyPointA = 633552; - # this is 3600.48 MHz - #dl_absoluteFrequencyPointA = 640032; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf index e8fc796b61..c77399bbed 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf @@ -25,7 +25,6 @@ gNBs = pusch_AntennaPorts = 2; ul_prbblacklist = "51,52,53,54" - do_SRS = 0; servingCellConfigCommon = ( { diff --git a/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf index ec443b174a..a24f45f024 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf @@ -25,10 +25,7 @@ gNBs = pdsch_AntennaPorts_XP = 2; pusch_AntennaPorts = 2; - #pusch_TargetSNRx10 = 200; - #pucch_TargetSNRx10 = 200; ul_prbblacklist = "79,80,81,82" - do_SRS = 0; servingCellConfigCommon = ( { diff --git a/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf index 9a6efada5b..d188c1c8a3 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf @@ -17,7 +17,7 @@ gNBs = ////////// Physical parameters: - sib1_tda = 15; + sib1_tda = 15; min_rxtxtime = 6; servingCellConfigCommon = ( diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf index 16cc70ca4b..f94ba38eb5 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf @@ -17,8 +17,6 @@ gNBs = ////////// Physical parameters: - do_CSIRS = 0; - do_SRS = 0; servingCellConfigCommon = ( { From c357f96120b511a5120414eba7e03494b90426ad Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Mon, 12 Jun 2023 08:48:49 +0200 Subject: [PATCH 78/87] Rename config file for 5g-l2sim --- ...band78.106prb.l2sim.conf => gnb.sa.band78.106prb.l2sim.conf} | 0 ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ci-scripts/conf_files/{gnb.band78.106prb.l2sim.conf => gnb.sa.band78.106prb.l2sim.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.106prb.l2sim.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.l2sim.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.106prb.l2sim.conf rename to ci-scripts/conf_files/gnb.sa.band78.106prb.l2sim.conf diff --git a/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml b/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml index db77cdae53..86c678c811 100644 --- a/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml @@ -174,7 +174,7 @@ services: - oai-spgwu - oai-amf volumes: - - ../../conf_files/gnb.band78.106prb.l2sim.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band78.106prb.l2sim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s From 6c241ec759c4db2a6ea7d606df48373cccb28bd8 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Mon, 12 Jun 2023 08:54:43 +0200 Subject: [PATCH 79/87] Rename config file nsa-2x2 --- ...RB.usrpn310.conf => gnb.nsa.band78.106PRB.usrpn310.2x2.conf} | 0 ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml | 2 +- ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename ci-scripts/conf_files/{gnb.band78.nsa_2x2.106PRB.usrpn310.conf => gnb.nsa.band78.106PRB.usrpn310.2x2.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf b/ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf rename to ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml index 185d637218..5b84f7e43f 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml @@ -113,7 +113,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time,line_num,function 1 1 nr diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml index d1515898ff..8e96dea441 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml @@ -118,7 +118,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time,line_num,function 1 1 nr From 12a3045bec575bd8f8b113e9f18dadecbc4ee07b Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Wed, 14 Jun 2023 16:21:27 +0200 Subject: [PATCH 80/87] Config files: make them lowercase Changes for: - phytest-dora config file - rfsim-phytest-dora-106prb - phytest-dora-106prb-usrpn300 - lte-2x2-tm1 - lte-2x2-tm2 - NSA-2x2 - 4g-rfsim-mbms-fembms - 5grfsim-fr2-32prb - nsa-2x2-quectel - 5g-rfsim-24prb - test xml --- ....usrpn310.conf => enb.band38.lte_2x2.100prb.usrpn310.conf} | 0 ...pn310.conf => enb.band38.lte_2x2_tm2.100prb.usrpn310.conf} | 0 ....usrpn310.conf => enb.band38.nsa_2x2.100prb.usrpn310.conf} | 0 ...RB.rfsim.mbms.conf => enb.band7.tm1.25prb.rfsim.mbms.conf} | 0 ....50PRB.usrpb210.conf => enb.band7.tm1.50prb.usrpb210.conf} | 0 ...st-dora.conf => gnb.band261.32prb.rfsim.phytest-dora.conf} | 0 ...st-dora.conf => gnb.band78.106prb.rfsim.phytest-dora.conf} | 0 ...dora.conf => gnb.band78.106prb.usrpn300.phytest-dora.conf} | 0 ...dora.conf => gnb.band78.162prb.usrpn300.phytest-dora.conf} | 0 ...pn310.2x2.conf => gnb.nsa.band78.106prb.usrpn310.2x2.conf} | 0 ...band78.24PRB.rfsim.conf => gnb.sa.band78.24prb.rfsim.conf} | 0 ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml | 4 ++-- ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml | 4 ++-- ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml | 2 +- ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml | 2 +- ci-scripts/xml_files/test_case_list_template.xml | 2 +- .../yaml_files/4g_rfsimulator_fembms/docker-compose.yml | 2 +- ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml | 2 +- .../yaml_files/5g_rfsimulator_24prb/docker-compose.yaml | 2 +- .../yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml | 2 +- .../yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml | 2 +- ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml | 2 +- ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml | 2 +- doc/RUNMODEM.md | 2 +- openair1/SIMULATION/TOOLS/DOC/rtusage.md | 2 +- 28 files changed, 19 insertions(+), 19 deletions(-) rename ci-scripts/conf_files/{enb.band38.lte_2x2.100PRB.usrpn310.conf => enb.band38.lte_2x2.100prb.usrpn310.conf} (100%) rename ci-scripts/conf_files/{enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf => enb.band38.lte_2x2_tm2.100prb.usrpn310.conf} (100%) rename ci-scripts/conf_files/{enb.band38.nsa_2x2.100PRB.usrpn310.conf => enb.band38.nsa_2x2.100prb.usrpn310.conf} (100%) rename ci-scripts/conf_files/{enb.band7.tm1.25PRB.rfsim.mbms.conf => enb.band7.tm1.25prb.rfsim.mbms.conf} (100%) rename ci-scripts/conf_files/{enb.band7.tm1.50PRB.usrpb210.conf => enb.band7.tm1.50prb.usrpb210.conf} (100%) rename ci-scripts/conf_files/{gnb.band261.32PRB.rfsim.phytest-dora.conf => gnb.band261.32prb.rfsim.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.106PRB.rfsim.phytest-dora.conf => gnb.band78.106prb.rfsim.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.106PRB.usrpn300.phytest-dora.conf => gnb.band78.106prb.usrpn300.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.band78.162PRB.usrpn300.phytest-dora.conf => gnb.band78.162prb.usrpn300.phytest-dora.conf} (100%) rename ci-scripts/conf_files/{gnb.nsa.band78.106PRB.usrpn310.2x2.conf => gnb.nsa.band78.106prb.usrpn310.2x2.conf} (100%) rename ci-scripts/conf_files/{gnb.sa.band78.24PRB.rfsim.conf => gnb.sa.band78.24prb.rfsim.conf} (100%) diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf rename to ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf rename to ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf diff --git a/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf similarity index 100% rename from ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf rename to ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf b/ci-scripts/conf_files/enb.band7.tm1.25prb.rfsim.mbms.conf similarity index 100% rename from ci-scripts/conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf rename to ci-scripts/conf_files/enb.band7.tm1.25prb.rfsim.mbms.conf diff --git a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.50prb.usrpb210.conf similarity index 100% rename from ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf rename to ci-scripts/conf_files/enb.band7.tm1.50prb.usrpb210.conf diff --git a/ci-scripts/conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf b/ci-scripts/conf_files/gnb.band261.32prb.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band261.32prb.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf similarity index 100% rename from ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf diff --git a/ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf similarity index 100% rename from ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf rename to ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf diff --git a/ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf similarity index 100% rename from ci-scripts/conf_files/gnb.sa.band78.24PRB.rfsim.conf rename to ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml index 5b84f7e43f..325c5108d9 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml @@ -100,7 +100,7 @@ Initialize_eNB Initialize eNB - -O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time,line_num,function 0 0 lte @@ -113,7 +113,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time,line_num,function 1 1 nr diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml index 8e96dea441..f5f4b1e549 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml @@ -105,7 +105,7 @@ Initialize_eNB Initialize eNB - -O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time,line_num,function 0 0 lte @@ -118,7 +118,7 @@ Initialize_eNB Initialize gNB - -O ci-scripts/conf_files/gnb.nsa.band78.106PRB.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time,line_num,function + -O ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time,line_num,function 1 1 nr diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml index 53636de6a1..1c4faaf99f 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml @@ -33,7 +33,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf --phy-test --log_config.global_log_options level,nocolor,time NR diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml index af48f00d5a..2122f8651c 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml @@ -33,7 +33,7 @@ Initialize_eNB Initialize gNB USRP (Tx-Write-Threading enabled) - -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf --phy-test --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time NR diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml index c98796890f..83e7d23f04 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.106PRB.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.default.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml index 3d91d55dfa..31be6e8ac4 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.1x1.60.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml index 6231f45169..09dbbd7757 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.162PRB.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.60.2x2.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/test_case_list_template.xml b/ci-scripts/xml_files/test_case_list_template.xml index eecdfe80b9..fddf8ad0e4 100644 --- a/ci-scripts/xml_files/test_case_list_template.xml +++ b/ci-scripts/xml_files/test_case_list_template.xml @@ -42,7 +42,7 @@ Initialize_eNB Initialize eNB (FDD/Band1/5MHz/info) - -O enb.band7.tm1.50PRB.usrpb210.conf --log_config.global_log_options level,nocolor,time + -O enb.band7.tm1.50prb.usrpb210.conf --log_config.global_log_options level,nocolor,time diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml index f568989f3f..47e38ba08c 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml @@ -13,7 +13,7 @@ services: RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --noS1 --eNBs.[0].component_carriers.[0].mbms_dedicated_serving_cell ENABLE --log_config.global_log_options level,nocolor,time volumes: - - ../../conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf + - ../../conf_files/enb.band7.tm1.25prb.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf healthcheck: test: /bin/bash -c "pgrep lte-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml index 5dc9ae1a04..81a85ff246 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml @@ -13,7 +13,7 @@ services: RFSIMULATOR: enb USE_ADDITIONAL_OPTIONS: --rfsim --noS1 --log_config.global_log_options level,nocolor,time volumes: - - ../../conf_files/enb.band7.tm1.25PRB.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf + - ../../conf_files/enb.band7.tm1.25prb.rfsim.mbms.conf:/opt/oai-enb/etc/enb.conf healthcheck: test: /bin/bash -c "pgrep lte-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 600f34cbc2..a113203d05 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -175,7 +175,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.sa.band78.24PRB.rfsim.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band78.24prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index 63293cf628..349b07f2b4 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band261.32PRB.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band261.32prb.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml index b3afb48e8d..3f58340d1b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml @@ -11,7 +11,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.band78.106PRB.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf - rrc.config:/opt/oai-gnb/ healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml index 9655cca180..8a7f4693ec 100644 --- a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml @@ -8,7 +8,7 @@ services: TZ: Europe/Paris USE_ADDITIONAL_OPTIONS: --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 volumes: - - ../../conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf:/opt/oai-enb/etc/enb.conf + - ../../conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf:/opt/oai-enb/etc/enb.conf network_mode: "host" healthcheck: test: /bin/bash -c "pgrep lte-softmodem" diff --git a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml index 84711b0a3c..1f54e7e380 100644 --- a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml @@ -8,7 +8,7 @@ services: TZ: Europe/Paris USE_ADDITIONAL_OPTIONS: --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 volumes: - - ../../conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf:/opt/oai-enb/etc/enb.conf + - ../../conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf:/opt/oai-enb/etc/enb.conf network_mode: "host" healthcheck: test: /bin/bash -c "pgrep lte-softmodem" diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index d32758b1a2..e25400a0a6 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -61,7 +61,7 @@ This setup requires an EPC, an OAI eNB and gNB, and a COTS Phone. A dedicated pa ### Launch eNB ```bash -sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50prb.usrpb210.conf ``` ### Launch gNB diff --git a/openair1/SIMULATION/TOOLS/DOC/rtusage.md b/openair1/SIMULATION/TOOLS/DOC/rtusage.md index 059d02a307..5e1bd1b1da 100644 --- a/openair1/SIMULATION/TOOLS/DOC/rtusage.md +++ b/openair1/SIMULATION/TOOLS/DOC/rtusage.md @@ -27,7 +27,7 @@ Several model lists can be defined in the oai configuration file. One, defined b Channel simulation parameters can also be specified on the command line: ```bash -./lte-softmodem -O ../../../ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf --noS1 --rfsim --rfsimulator.options chanmod --rfsimulator.serveraddr enb --telnetsrv --channelmod.modellist modellist_rfsimu_2 --channelmod.modellist_rfsimu_2.[1].offset 120 +./lte-softmodem -O ../../../ci-scripts/conf_files/enb.band7.tm1.50prb.usrpb210.conf --noS1 --rfsim --rfsimulator.options chanmod --rfsimulator.serveraddr enb --telnetsrv --channelmod.modellist modellist_rfsimu_2 --channelmod.modellist_rfsimu_2.[1].offset 120 ``` ### Using the telnet server to modify channel simulator parameters The telnet server includes a `channelmod` command which can be used to dynamically modify some channel model parameters. This command is only available when channel simulation is enabled (via `rfsimulator.options chanmod` option when running the rfsimulator. `channelmod` command has its own help: From c8f78a232fac3db846a097d9116f5bdd4fb4f694 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Fri, 23 Jun 2023 00:53:11 +0200 Subject: [PATCH 81/87] Move unused config to untested folder --- .../conf_files/{ => untested}/enb.band13.tm1.25PRB.usrpb210.conf | 0 .../conf_files/{ => untested}/enb.band13.tm1.50PRB.emtc.conf | 0 .../conf_files/{ => untested}/enb.band17.tm1.25PRB.usrpb210.conf | 0 .../{ => untested}/enb.band17.tm1.mbms.25PRB.usrpb210.conf | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename ci-scripts/conf_files/{ => untested}/enb.band13.tm1.25PRB.usrpb210.conf (100%) rename ci-scripts/conf_files/{ => untested}/enb.band13.tm1.50PRB.emtc.conf (100%) rename ci-scripts/conf_files/{ => untested}/enb.band17.tm1.25PRB.usrpb210.conf (100%) rename ci-scripts/conf_files/{ => untested}/enb.band17.tm1.mbms.25PRB.usrpb210.conf (100%) diff --git a/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/untested/enb.band13.tm1.25PRB.usrpb210.conf similarity index 100% rename from ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf rename to ci-scripts/conf_files/untested/enb.band13.tm1.25PRB.usrpb210.conf diff --git a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf b/ci-scripts/conf_files/untested/enb.band13.tm1.50PRB.emtc.conf similarity index 100% rename from ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf rename to ci-scripts/conf_files/untested/enb.band13.tm1.50PRB.emtc.conf diff --git a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/untested/enb.band17.tm1.25PRB.usrpb210.conf similarity index 100% rename from ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf rename to ci-scripts/conf_files/untested/enb.band17.tm1.25PRB.usrpb210.conf diff --git a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf b/ci-scripts/conf_files/untested/enb.band17.tm1.mbms.25PRB.usrpb210.conf similarity index 100% rename from ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf rename to ci-scripts/conf_files/untested/enb.band17.tm1.mbms.25PRB.usrpb210.conf From ff337b02af25efb5765d57a537adc59f886f6383 Mon Sep 17 00:00:00 2001 From: Dhanuja Elizabeth Thomas Date: Thu, 15 Jun 2023 12:00:00 +0200 Subject: [PATCH 82/87] Remove unused UE conf, clean up documentation --- ci-scripts/conf_files/lteue.usim.conf | 153 ------------------------- ci-scripts/conf_files/nr-ue-sim.conf | 7 -- ci-scripts/conf_files/nr-ue.nfapi.conf | 37 ------ ci-scripts/conf_files/ue.nfapi.conf | 37 ------ doc/L2NFAPI.md | 2 +- doc/L2NFAPI_NOS1.md | 8 +- doc/L2NFAPI_S1.md | 8 +- docker/Dockerfile.nrUE.rhel9 | 3 - docker/Dockerfile.nrUE.rocky | 4 - docker/Dockerfile.nrUE.ubuntu20 | 3 - 10 files changed, 9 insertions(+), 253 deletions(-) delete mode 100644 ci-scripts/conf_files/lteue.usim.conf delete mode 100644 ci-scripts/conf_files/nr-ue-sim.conf delete mode 100644 ci-scripts/conf_files/nr-ue.nfapi.conf delete mode 100644 ci-scripts/conf_files/ue.nfapi.conf diff --git a/ci-scripts/conf_files/lteue.usim.conf b/ci-scripts/conf_files/lteue.usim.conf deleted file mode 100644 index e9b02e9b1f..0000000000 --- a/ci-scripts/conf_files/lteue.usim.conf +++ /dev/null @@ -1,153 +0,0 @@ -# List of known PLMNS -PLMN: { - PLMN0: { - FULLNAME="OpenAirInterface"; - SHORTNAME="OAICN"; - MNC="96"; - MCC="208"; - }; -}; - -UE0: -{ - USER: { - IMEI="356113022094149"; - MANUFACTURER="OAI"; - MODEL="LTE SoftModem"; - PIN="0000"; - }; - - SIM: { - MSIN="0100001111"; - USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; - OPC="e734f8734007d6c5ce7a0508809e7e9c"; - MSISDN="33611123456"; - }; - - # Home PLMN Selector with Access Technology - HPLMN= "20896"; - - # User controlled PLMN Selector with Access Technology - UCPLMN_LIST = (); - - # Operator PLMN List - OPLMN_LIST = ("20896"); - - # Operator controlled PLMN Selector with Access Technology - OCPLMN_LIST = (); - - # Forbidden plmns - FPLMN_LIST = (); - - # Equivalent home plmns - EHPLMN_LIST = (); - -}; - -UE1: -{ - USER: { - IMEI="356113022094149"; - MANUFACTURER="OAI"; - MODEL="LTE SoftModem"; - PIN="0000"; - }; - - SIM: { - MSIN="0100001111"; - USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; - OPC="e734f8734007d6c5ce7a0508809e7e9c"; - MSISDN="33611123456"; - }; - - # Home PLMN Selector with Access Technology - HPLMN= "20896"; - - # User controlled PLMN Selector with Access Technology - UCPLMN_LIST = (); - - # Operator PLMN List - OPLMN_LIST = ("20896"); - - # Operator controlled PLMN Selector with Access Technology - OCPLMN_LIST = (); - - # Forbidden plmns - FPLMN_LIST = (); - - # Equivalent home plmns - EHPLMN_LIST = (); - -}; - -UE2: -{ - USER: { - IMEI="356113022094149"; - MANUFACTURER="OAI"; - MODEL="LTE SoftModem"; - PIN="0000"; - }; - - SIM: { - MSIN="0100001111"; - USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; - OPC="e734f8734007d6c5ce7a0508809e7e9c"; - MSISDN="33611123456"; - }; - - # Home PLMN Selector with Access Technology - HPLMN= "20896"; - - # User controlled PLMN Selector with Access Technology - UCPLMN_LIST = (); - - # Operator PLMN List - OPLMN_LIST = ("20896"); - - # Operator controlled PLMN Selector with Access Technology - OCPLMN_LIST = (); - - # Forbidden plmns - FPLMN_LIST = (); - - # Equivalent home plmns - EHPLMN_LIST = (); - -}; - -UE3: -{ - USER: { - IMEI="356113022094149"; - MANUFACTURER="OAI"; - MODEL="LTE SoftModem"; - PIN="0000"; - }; - - SIM: { - MSIN="0100001111"; - USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; - OPC="e734f8734007d6c5ce7a0508809e7e9c"; - MSISDN="33611123456"; - }; - - # Home PLMN Selector with Access Technology - HPLMN= "20896"; - - # User controlled PLMN Selector with Access Technology - UCPLMN_LIST = (); - - # Operator PLMN List - OPLMN_LIST = ("20896"); - - # Operator controlled PLMN Selector with Access Technology - OCPLMN_LIST = (); - - # Forbidden plmns - FPLMN_LIST = (); - - # Equivalent home plmns - EHPLMN_LIST = (); - -}; diff --git a/ci-scripts/conf_files/nr-ue-sim.conf b/ci-scripts/conf_files/nr-ue-sim.conf deleted file mode 100644 index 884430bf39..0000000000 --- a/ci-scripts/conf_files/nr-ue-sim.conf +++ /dev/null @@ -1,7 +0,0 @@ -uicc0 = { - imsi = "@FULL_IMSI@"; - key = "@FULL_KEY@"; - opc= "@OPC@"; - dnn= "@DNN@"; - nssai_sst=@NSSAI_SST@; -} diff --git a/ci-scripts/conf_files/nr-ue.nfapi.conf b/ci-scripts/conf_files/nr-ue.nfapi.conf deleted file mode 100644 index 90798702cf..0000000000 --- a/ci-scripts/conf_files/nr-ue.nfapi.conf +++ /dev/null @@ -1,37 +0,0 @@ -log_config = { - global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="info"; - pdcp_log_level ="info"; - rrc_log_level ="info"; -}; - - -L1s = ( - { - num_cc = 1; - tr_n_preference = "nfapi"; - local_n_if_name = "ens3"; - remote_n_address = "127.0.0.1"; //Proxy IP - local_n_address = "127.0.0.1"; - local_n_portc = 50600; - remote_n_portc = 50601; - local_n_portd = 50610; - remote_n_portd = 50611; - } -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 90 - att_rx = 0; - bands = [7,38,42,43]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 125; - } -); diff --git a/ci-scripts/conf_files/ue.nfapi.conf b/ci-scripts/conf_files/ue.nfapi.conf deleted file mode 100644 index 09ad7529b1..0000000000 --- a/ci-scripts/conf_files/ue.nfapi.conf +++ /dev/null @@ -1,37 +0,0 @@ -log_config = { - global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="info"; - pdcp_log_level ="info"; - rrc_log_level ="info"; -}; - - -L1s = ( - { - num_cc = 1; - tr_n_preference = "nfapi"; - local_n_if_name = "ens3"; - remote_n_address = "CI_ENB_IP_ADDR"; - local_n_address = "CI_UE_IP_ADDR"; - local_n_portc = 50000; - remote_n_portc = 50001; - local_n_portd = 50010; - remote_n_portd = 50011; - } -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 90 - att_rx = 0; - bands = [7,38,42,43]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 125; - } -); diff --git a/doc/L2NFAPI.md b/doc/L2NFAPI.md index e87f9f270c..d7bba0bfeb 100644 --- a/doc/L2NFAPI.md +++ b/doc/L2NFAPI.md @@ -64,7 +64,7 @@ $ sudo -E ./nr-softmodem -O ../ci-scripts/conf_files/episci/proxy_rcc.band78.tm1 ``` ### Start UE ```bash -$ sudo -E ./nr-uesoftmodem -O ../ci-scripts/conf_files/episci/proxy_nr-ue.nfapi.conf --nfapi STANDALONE_PNF --node-number 2 --sa --emulate-l1 +$ sudo -E ./nr-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --nfapi STANDALONE_PNF --node-number 2 --sa --emulate-l1 ``` ### EpiSci's Documentation A more detailed tutorial is available on the [EpiSci GitHub Repository](https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy#readme). diff --git a/doc/L2NFAPI_NOS1.md b/doc/L2NFAPI_NOS1.md index 10d0c2a577..b65aaef3ba 100644 --- a/doc/L2NFAPI_NOS1.md +++ b/doc/L2NFAPI_NOS1.md @@ -191,7 +191,7 @@ Last, the S1 interface shall be properly set. ```bash $ ssh sudousername@machineB cd ue_folder -# Edit ci-scripts/conf_files/ue.nfapi.conf with your preferred editor +# Edit ci-scripts/conf_files/nrue.uicc.conf with your preferred editor ``` Verify the nFAPI interface setup on the loopback interface. @@ -246,9 +246,9 @@ In the second terminal (the one you used to build the UE): $ ssh sudousername@machineC cd ue_folder/cmake_targets # Test 64 UEs, 1 thread in FDD mode -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 # Test 64 UEs, 1 thread in TDD mode -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 -T 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 -T 1 > ue.log 2>&1 # The "-T 1" option means TDD config ``` @@ -262,7 +262,7 @@ For example, running with 4 UEs: ```bash $ ssh sudousername@machineC cd ue_folder/cmake_targets -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 sleep 10 ifconfig ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX diff --git a/doc/L2NFAPI_S1.md b/doc/L2NFAPI_S1.md index e7faec106f..a8b287ddf3 100644 --- a/doc/L2NFAPI_S1.md +++ b/doc/L2NFAPI_S1.md @@ -196,7 +196,7 @@ Last, the S1 interface shall be properly set. ```bash $ ssh sudousername@machineB cd ue_folder -# Edit ci-scripts/conf_files/ue.nfapi.conf with your preferred editor +# Edit ci-scripts/conf_files/nrue.uicc.conf with your preferred editor ``` Verify the nFAPI interface setup on the loopback interface. @@ -252,9 +252,9 @@ In the second terminal (the one you used to build the UE): $ ssh sudousername@machineC cd ue_folder/cmake_targets # Test 64 UEs, 1 thread in FDD mode -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 # Test 64 UEs, 1 thread in TDD mode -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 -T 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 -T 1 > ue.log 2>&1 # The "-T 1" option means TDD config ``` @@ -268,7 +268,7 @@ For example, running with 4 UEs: ```bash $ ssh sudousername@machineC cd ue_folder/cmake_targets -sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 > ue.log 2>&1 sleep 10 ifconfig ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX diff --git a/docker/Dockerfile.nrUE.rhel9 b/docker/Dockerfile.nrUE.rhel9 index 53b179a935..b142847c8e 100644 --- a/docker/Dockerfile.nrUE.rhel9 +++ b/docker/Dockerfile.nrUE.rhel9 @@ -59,9 +59,6 @@ COPY --from=nr-ue-build \ ./ COPY ./docker/scripts/nr_ue_entrypoint.sh ./entrypoint.sh WORKDIR /opt/oai-nr-ue/etc -COPY --from=nr-ue-build \ - /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf \ - ./ COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ diff --git a/docker/Dockerfile.nrUE.rocky b/docker/Dockerfile.nrUE.rocky index f0cc4b5788..cb07b2eb6a 100644 --- a/docker/Dockerfile.nrUE.rocky +++ b/docker/Dockerfile.nrUE.rocky @@ -63,10 +63,6 @@ COPY --from=nr-ue-build \ ./ WORKDIR /opt/oai-nr-ue/etc -COPY --from=nr-ue-build \ - /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf \ - /oai-ran/docker/etc/nr-ue.nfapi.conf \ - ./ COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ diff --git a/docker/Dockerfile.nrUE.ubuntu20 b/docker/Dockerfile.nrUE.ubuntu20 index c298394abd..a4b63d3cef 100644 --- a/docker/Dockerfile.nrUE.ubuntu20 +++ b/docker/Dockerfile.nrUE.ubuntu20 @@ -65,9 +65,6 @@ COPY --from=nr-ue-build \ COPY ./docker/scripts/nr_ue_entrypoint.sh ./entrypoint.sh WORKDIR /opt/oai-nr-ue/etc -COPY --from=nr-ue-build \ - /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf \ - ./ COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ From c25ee6fd322f07db085041b1897a0f1f42abcd00 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Jun 2023 08:35:37 +0200 Subject: [PATCH 83/87] Move symlink creation to radio/transport device to cmake --- cmake_targets/build_oai | 19 ------------------- radio/AW2SORI/CMakeLists.txt | 3 +++ radio/BLADERF/CMakeLists.txt | 3 +++ radio/ETHERNET/CMakeLists.txt | 3 +++ radio/ETHERNET/benetel/4g/CMakeLists.txt | 3 +++ radio/ETHERNET/benetel/5g/CMakeLists.txt | 3 +++ radio/IRIS/CMakeLists.txt | 3 +++ radio/LMSSDR/CMakeLists.txt | 3 +++ radio/USRP/CMakeLists.txt | 3 +++ 9 files changed, 24 insertions(+), 19 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 8c9dbccda8..3580edac1b 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -537,47 +537,28 @@ function main() { # Build RF device and transport protocol libraries # #################################################### if [ "$HW" != "None" ] ; then - rm -f liboai_device.so - if [ "$HW" == "OAI_USRP" ] ; then compilations $BUILD_DIR oai_usrpdevif.txt oai_usrpdevif - ln -sf liboai_usrpdevif.so liboai_device.so - echo "liboai_device.so symlinks to liboai_usrpdevif.so" elif [ "$HW" == "OAI_BLADERF" ] ; then compilations $BUILD_DIR oai_bladerfdevif.txt oai_bladerfdevif - ln -sf liboai_bladerfdevif.so liboai_device.so - echo "liboai_device.so symlinks liboai_bladerfdevif.so" elif [ "$HW" == "OAI_LMSSDR" ] ; then compilations $BUILD_DIR oai_lmssdrdevif.txt oai_lmssdrdevif - ln -sf liboai_lmssdrdevif.so liboai_device.so - echo "liboai_device.so symlinks to liboai_lmssdrdevif.so" elif [ "$HW" == "OAI_IRIS" ] ; then compilations $BUILD_DIR oai_irisdevif.txt oai_irisdevif - ln -s liboai_irisdevif.so liboai_device.so - echo "liboai_device.so symlinks to liboai_irisdevif.so" elif [ "$HW" == "OAI_AW2SORI" ] ; then compilations $BUILD_DIR aw2sori_transpro.txt aw2sori_transpro - ln -sf libaw2sori_transpro.so libthirdparty_transpro.so - echo "libthirdparty_transpro.so symlinks to libaw2sori_transpro.so" else echo_fatal "illegal HW option $HW" fi fi if [ "$TP" != "None" ]; then - rm -f liboai_transpro.so if [ "$TP" == "Ethernet" ]; then compilations $BUILD_DIR oai_eth_transpro.txt oai_eth_transpro - ln -sf liboai_eth_transpro.so liboai_transpro.so - echo_info "liboai_transpro.so symlinks to liboai_eth_transpro.so" elif [ "$TP" == "benetel4g" ]; then compilations $BUILD_DIR benetel_4g.txt benetel4g - ln -sf libbenetel_4g.so liboai_transpro.so - echo_info "liboai_transpro.so symlinks to libbenetel_4g.so" elif [ "$TP" == "benetel5g" ]; then compilations $BUILD_DIR benetel_5g.txt benetel_5g - ln -sf libbenetel_5g.so liboai_transpro.so - echo_info "liboai_transpro.so symlinks to libbenetel_5g.so" else echo_fatal "illegal TP option $TP" fi diff --git a/radio/AW2SORI/CMakeLists.txt b/radio/AW2SORI/CMakeLists.txt index d055b374ac..e02d8a2721 100644 --- a/radio/AW2SORI/CMakeLists.txt +++ b/radio/AW2SORI/CMakeLists.txt @@ -11,3 +11,6 @@ add_library(aw2sori_transpro MODULE oaiori.c) target_compile_options(aw2sori_transpro PRIVATE -shared -fPIC -msse4 -g -ggdb -DLITE_COMPILATION) target_link_libraries(aw2sori_transpro PRIVATE ori oai_eth_transpro) set_target_properties(aw2sori_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET aw2sori_transpro POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink libaw2sori_transpro.so libthirdparty_transpro.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/BLADERF/CMakeLists.txt b/radio/BLADERF/CMakeLists.txt index d7a7fc7162..551cc8ef1d 100644 --- a/radio/BLADERF/CMakeLists.txt +++ b/radio/BLADERF/CMakeLists.txt @@ -2,3 +2,6 @@ pkg_check_modules(bladeRF REQUIRED libbladeRF) add_library(oai_bladerfdevif MODULE bladerf_lib.c) target_link_libraries(oai_bladerfdevif PRIVATE bladeRF) set_target_properties(oai_bladerfdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_bladerfdevif POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_bladerfdevif.so liboai_device.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/CMakeLists.txt b/radio/ETHERNET/CMakeLists.txt index aa2b14ef12..52aebdcc1a 100644 --- a/radio/ETHERNET/CMakeLists.txt +++ b/radio/ETHERNET/CMakeLists.txt @@ -5,5 +5,8 @@ add_library(oai_eth_transpro MODULE ) target_include_directories(oai_eth_transpro PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) set_target_properties(oai_eth_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_eth_transpro POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_eth_transpro.so liboai_transpro.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_subdirectory(benetel) diff --git a/radio/ETHERNET/benetel/4g/CMakeLists.txt b/radio/ETHERNET/benetel/4g/CMakeLists.txt index b0f180719c..164e33eb28 100644 --- a/radio/ETHERNET/benetel/4g/CMakeLists.txt +++ b/radio/ETHERNET/benetel/4g/CMakeLists.txt @@ -15,3 +15,6 @@ target_include_directories(benetel_4g PRIVATE ${libdpdk_INCLUDE_DIRS}) target_link_libraries(benetel_4g PRIVATE ${libdpdk_LIBRARIES}) target_link_libraries(benetel_4g PRIVATE pthread dl rt m numa) set_target_properties(benetel_4g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET benetel_4g POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink libbenetel_4g.so liboai_transpro.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/benetel/5g/CMakeLists.txt b/radio/ETHERNET/benetel/5g/CMakeLists.txt index da957acb5b..cdad594ce3 100644 --- a/radio/ETHERNET/benetel/5g/CMakeLists.txt +++ b/radio/ETHERNET/benetel/5g/CMakeLists.txt @@ -14,3 +14,6 @@ target_link_libraries(benetel_5g PRIVATE ${libdpdk_LIBRARIES}) target_link_libraries(benetel_5g PRIVATE pthread dl rt m numa) set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") set_target_properties(benetel_5g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET benetel_5g POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink libbenetel_5g.so liboai_transpro.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/IRIS/CMakeLists.txt b/radio/IRIS/CMakeLists.txt index cd12bf09bb..edc7c7568a 100644 --- a/radio/IRIS/CMakeLists.txt +++ b/radio/IRIS/CMakeLists.txt @@ -3,3 +3,6 @@ find_package(SoapySDR REQUIRED) add_library(oai_irisdevif MODULE iris_lib.cpp) target_link_libraries(oai_irisdevif PRIVATE SoapySDR) set_target_properties(oai_irisdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_irisdevif POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_irisdevif.so liboai_device.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/LMSSDR/CMakeLists.txt b/radio/LMSSDR/CMakeLists.txt index d93b84f6f1..2df5c9a01f 100644 --- a/radio/LMSSDR/CMakeLists.txt +++ b/radio/LMSSDR/CMakeLists.txt @@ -3,3 +3,6 @@ find_package(LimeSuite REQUIRED) add_library(oai_lmssdrdevif MODULE lms_lib.cpp) target_link_libraries(oai_lmssdrdevif LimeSuite ) set_target_properties(oai_lmssdrdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_lmssdrdevif POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_lmssdrdevif.so liboai_device.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/USRP/CMakeLists.txt b/radio/USRP/CMakeLists.txt index bcdf2b6a23..4aef8b1f8d 100644 --- a/radio/USRP/CMakeLists.txt +++ b/radio/USRP/CMakeLists.txt @@ -5,3 +5,6 @@ add_library(oai_usrpdevif MODULE usrp_lib.cpp) #target_include_directories(oai_usrpdevif PRIVATE Boost::boost) target_link_libraries(oai_usrpdevif uhd) set_target_properties(oai_usrpdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_command(TARGET oai_usrpdevif POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_usrpdevif.so liboai_device.so + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) From 5f58ccb56c02cc60e96ad8c3ee1920cb78e2eb83 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Jun 2023 09:02:37 +0200 Subject: [PATCH 84/87] Remove unused build_oai variables --- cmake_targets/build_oai | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 3580edac1b..ecf281ad58 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -37,12 +37,8 @@ set_openair_env gen_nvram_path=$OPENAIR_DIR/cmake_targets/ran_build/build conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -XFORMS="True" -SKIP_SHARED_LIB_FLAG="False" -PRINT_STATS="False" HW="None" TP="None" -EPC=0 VERBOSE_CI=0 VERBOSE_COMPILE=0 RUN_GROUP=0 @@ -52,12 +48,8 @@ BUILD_DOXYGEN=0 DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" -BUILD_ECLIPSE=0 -NR="False" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer" RU=0 -CMAKE_C_FLAGS=() -CMAKE_CXX_FLAGS=() function print_help() { echo_info " @@ -81,9 +73,6 @@ Options: This option will require root password --install-optional-packages Install useful but not mandatory packages such as valgrind --i | --install-system-files - Install OpenAirInterface required files in Linux system - This option will require root password -g | --run-with-gdb 0 ]]; then CMAKE_CMD="$CMAKE_CMD -DCMAKE_C_FLAGS=\"${CMAKE_C_FLAGS[*]}\""; fi - if [[ ${#CMAKE_CXX_FLAGS[@]} > 0 ]]; then CMAKE_CMD="$CMAKE_CMD -DCMAKE_CXX_FLAGS=\"${CMAKE_CXX_FLAGS[*]}\""; fi # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, # e.g., cmake_targets/ran_build/build, hence the ../../.. From 306b4974ad2b008a8edbc8e795b7ad1d849ef7f3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Jun 2023 09:57:45 +0200 Subject: [PATCH 85/87] Simplify build_oai --- cmake_targets/build_oai | 179 +++++++++++++++------------------------- 1 file changed, 68 insertions(+), 111 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index ecf281ad58..5405af9b28 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -37,8 +37,7 @@ set_openair_env gen_nvram_path=$OPENAIR_DIR/cmake_targets/ran_build/build conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -HW="None" -TP="None" +HW="" VERBOSE_CI=0 VERBOSE_COMPILE=0 RUN_GROUP=0 @@ -49,7 +48,7 @@ DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer" -RU=0 +TARGET_LIST="" function print_help() { echo_info " @@ -226,22 +225,27 @@ function main() { shift;; --eNB) eNB=1 + TARGET_LIST="$TARGET_LIST lte-softmodem" echo_info "Will compile eNB" shift;; --gNB) gNB=1 + TARGET_LIST="$TARGET_LIST nr-softmodem nr-cuup" echo_info "Will compile gNB" shift;; --RU) RU=1 + TARGET_LIST="$TARGET_LIST oairu" echo_info "Will compile RRU" shift;; --UE) UE=1 + TARGET_LIST="$TARGET_LIST lte-uesoftmodem" echo_info "Will compile UE" shift;; --nrUE) nrUE=1 + TARGET_LIST="$TARGET_LIST nr-uesoftmodem" echo_info "Will compile NR UE" shift;; --mu) @@ -255,38 +259,48 @@ function main() { gen_nvram_path=$(readlink -f "$2") shift 2;; --UE-ip) - UE_ip=1 - echo_info "Will compile UE" + TARGET_LIST="$TARGET_LIST ue_ip" shift;; -w | --hardware) - # Use OAI_USRP as the key word USRP is used inside UHD driver case "$2" in - "USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "SIMU" | "AW2SORI") + "USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "SIMU") HW="OAI_"$2 + TARGET_LIST="$TARGET_LIST oai_${2,,}devif" # ,, makes lowercase + CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON" + ;; + "AW2SORI") + HW="OAI_"$2 + TARGET_LIST="$TARGET_LIST aw2sori_transpro" CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON" ;; "None") - HW="None" ;; *) - echo_fatal "Unknown HW type $2: exit..." + echo_fatal "Unknown hardware type $2: exit..." + ;; esac shift 2;; -t | --transport) case "$2" in - "Ethernet" | "benetel4g" | "benetel5g") - TP=$2 + "Ethernet") + TARGET_LIST="$TARGET_LIST oai_eth_transpro" + CMAKE_CMD="$CMAKE_CMD -DOAI_${2^^}=ON" # ^^ makes uppercase + ;; + "benetel4g" | "benetel5g") + TARGET_LIST="$TARGET_LIST $2" CMAKE_CMD="$CMAKE_CMD -DOAI_${2^^}=ON" # ^^ makes uppercase ;; "None") - HW="None" ;; *) - echo_fatal "Unknown TP type $2; exit..." + echo_fatal "Unknown transport type $2; exit..." + ;; esac shift 2;; -P | --phy_simulators) SIMUS_PHY=1 + # TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim + TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim" echo_info "Will compile dlsim, ulsim, ..." shift;; -s | --check) @@ -347,26 +361,19 @@ function main() { echo_info "Enabling build eclipse project support" shift 1;; --build-lib) - BUILD_OPTLIB="" if [ "$2" == "all" ] ; then - BUILD_OPTLIB="$OPTIONAL_LIBRARIES" + TARGET_LIST="$TARGET_LIST $OPTIONAL_LIBRARIES" + for lib in $OPTIONAL_LIBRARIES; do CMAKE_CMD="$CMAKE_CMD -DENABLE_${lib^^}=ON"; done echo_info "Enabling build of all optional shared libraries ($OPTIONAL_LIBRARIES)" else - for alib in $2 ; do - for oklib in $OPTIONAL_LIBRARIES ; do - if [ "$alib" = "$oklib" ] ; then - BUILD_OPTLIB="$BUILD_OPTLIB $alib" - echo_info "Enabling build of lib${alib}.so" - fi - done + for reqlib in $2; do + lib=$(echo $OPTIONAL_LIBRARIES | tr ' ' '\n' | grep -w $reqlib) # search given parameter in list + [[ $? -ne 0 ]] && echo_fatal "Unknown optional library in $reqlib, valid libraries are $OPTIONAL_LIBRARIES" + TARGET_LIST="$TARGET_LIST $lib" # will append the found library + CMAKE_CMD="$CMAKE_CMD -DENABLE_${lib^^}=ON" + echo_info "Enabling build of optional shared library $lib" done - if [ "${BUILD_OPTLIB## }" != "$2" ] ; then - echo_fatal "Unknown optional library in $2, valid libraries are $OPTIONAL_LIBRARIES" - fi fi - for oklib in $BUILD_OPTLIB ; do - CMAKE_CMD="$CMAKE_CMD -DENABLE_${oklib^^}=ON" - done shift 2;; --noavx512) CMAKE_CMD="$CMAKE_CMD -DAVX512=OFF" @@ -444,96 +451,46 @@ function main() { check_install_additional_tools fi - execlist="" - [[ "$eNB" == "1" ]] && execlist="$execlist lte-softmodem" - [[ "$gNB" == "1" ]] && execlist="$execlist nr-softmodem nr-cuup" - [[ "$RU" == "1" ]] && execlist="$execlist oairu" - [[ "$UE" == 1 ]] && execlist="$execlist lte-uesoftmodem" - [[ "$nrUE" == 1 ]] && execlist="$execlist nr-uesoftmodem" - # TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim - [[ "$SIMUS_PHY" == "1" ]] && execlist="$execlist dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim" - [[ "$BUILD_OPTLIB" != "" ]] && execlist="$execlist $BUILD_OPTLIB" - [[ "$execlist" != "" ]] && execlist="$execlist params_libconfig coding rfsimulator" - DIR=$OPENAIR_DIR/cmake_targets [ "$CLEAN" = "1" ] && rm -rf $DIR/$BUILD_DIR/build - mkdir -p $DIR/$BUILD_DIR/build - cd $DIR/$BUILD_DIR/build - - # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, - # e.g., cmake_targets/ran_build/build, hence the ../../.. - CMAKE_CMD="$CMAKE_CMD ../../.." - echo_info "Running \"$CMAKE_CMD\"" - eval $CMAKE_CMD - - if [[ "$execlist" != "" ]]; then - compilations $BUILD_DIR all.txt $execlist - fi - - if [ "$UE" = 1 ] ; then - - echo_info "Compiling UE specific part" - - if [ "$UE_ip" = 1 ] - then - echo_info "Building ue_ip module" - compilations $BUILD_DIR ue_ip.txt ue_ip - else - echo_info "Bypassing ue_ip build" - fi #IS_CONTAINER - -# mkdir -p $DIR/at_commands/build -# cd $DIR/at_commands/build -# eval $CMAKE_CMD -# compilations at_commands at_nas_ue - - [ "$CLEAN" = "1" ] && rm -rf $DIR/nas_sim_tools/build - mkdir -p $DIR/nas_sim_tools/build - cd $DIR/nas_sim_tools/build - - eval $CMAKE_CMD .. - compilations nas_sim_tools usim.txt usim - compilations nas_sim_tools nvram.txt nvram - compilations nas_sim_tools conf2uedata.txt conf2uedata - - # generate USIM data - if [ -f conf2uedata ]; then - install_nas_tools $conf_nvram_path $DIR/$BUILD_DIR/build "$DIR/$BUILD_DIR/build/conf2uedata.txt" - else - echo_warning "not generated UE NAS files: binaries not found" + if [[ $TARGET_LIST != "" ]]; then + # add some default libraries that should always be built + # for eNB, gNB, UEs, simulators + if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then + TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts" fi - fi - #################################################### - # Build RF device and transport protocol libraries # - #################################################### - if [ "$HW" != "None" ] ; then - if [ "$HW" == "OAI_USRP" ] ; then - compilations $BUILD_DIR oai_usrpdevif.txt oai_usrpdevif - elif [ "$HW" == "OAI_BLADERF" ] ; then - compilations $BUILD_DIR oai_bladerfdevif.txt oai_bladerfdevif - elif [ "$HW" == "OAI_LMSSDR" ] ; then - compilations $BUILD_DIR oai_lmssdrdevif.txt oai_lmssdrdevif - elif [ "$HW" == "OAI_IRIS" ] ; then - compilations $BUILD_DIR oai_irisdevif.txt oai_irisdevif - elif [ "$HW" == "OAI_AW2SORI" ] ; then - compilations $BUILD_DIR aw2sori_transpro.txt aw2sori_transpro - else - echo_fatal "illegal HW option $HW" - fi - fi + mkdir -p $DIR/$BUILD_DIR/build + cd $DIR/$BUILD_DIR/build - if [ "$TP" != "None" ]; then - if [ "$TP" == "Ethernet" ]; then - compilations $BUILD_DIR oai_eth_transpro.txt oai_eth_transpro - elif [ "$TP" == "benetel4g" ]; then - compilations $BUILD_DIR benetel_4g.txt benetel4g - elif [ "$TP" == "benetel5g" ]; then - compilations $BUILD_DIR benetel_5g.txt benetel_5g - else - echo_fatal "illegal TP option $TP" + # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, + # e.g., cmake_targets/ran_build/build, hence the ../../.. + CMAKE_CMD="$CMAKE_CMD ../../.." + echo_info "Running \"$CMAKE_CMD\"" + eval $CMAKE_CMD + compilations $BUILD_DIR all.txt $TARGET_LIST + + if [ "$UE" = 1 ] ; then + + echo_info "Compiling UE specific part" + + [ "$CLEAN" = "1" ] && rm -rf $DIR/nas_sim_tools/build + mkdir -p $DIR/nas_sim_tools/build + cd $DIR/nas_sim_tools/build + + eval $CMAKE_CMD .. + compilations nas_sim_tools usim.txt usim + compilations nas_sim_tools nvram.txt nvram + compilations nas_sim_tools conf2uedata.txt conf2uedata + + # generate USIM data + if [ -f conf2uedata ]; then + install_nas_tools $conf_nvram_path $DIR/$BUILD_DIR/build "$DIR/$BUILD_DIR/build/conf2uedata.txt" + else + echo_warning "not generated UE NAS files: binaries not found" + fi fi fi From 079866bf4f0562de31818930f45bd40c40992628 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Jul 2023 11:21:38 +0200 Subject: [PATCH 86/87] Check for libforms for building scopes --- openair1/PHY/TOOLS/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openair1/PHY/TOOLS/CMakeLists.txt b/openair1/PHY/TOOLS/CMakeLists.txt index 0def967792..8acd528617 100644 --- a/openair1/PHY/TOOLS/CMakeLists.txt +++ b/openair1/PHY/TOOLS/CMakeLists.txt @@ -29,6 +29,13 @@ #* \warning #*/ +find_library(forms NAMES forms) +if(NOT forms) + message(FATAL_ERROR "required library forms not found for building scopes") +else() + message(STATUS "libforms library, required for scopes, found at ${forms}") +endif() + include_directories ("/usr/include/X11") add_library(xforms_common OBJECT lte_phy_scope.c From 9dd27e60f92bf31ad88ad80f04e53ef5c36ea1ec Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 10 Jul 2023 08:57:18 +0200 Subject: [PATCH 87/87] Fix after merging ssh asterix into integration; conflict from ls --- ci-scripts/xml_files/container_sa_n310_nrue.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml index 309b2860f7..ce7dd26b6d 100644 --- a/ci-scripts/xml_files/container_sa_n310_nrue.xml +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -111,7 +111,7 @@ Ping Ping: 20pings in 20sec oai_ue_caracal - -c 20 + -c 20 %cn_ip% 1 25 @@ -120,7 +120,7 @@ Ping Ping: 100pings in 20sec oai_ue_caracal - -c 100 -i 0.2 + -c 100 -i 0.2 %cn_ip% 1 30