From 9456fe584a3292c66c6111488dd68478abd08246 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 11 Mar 2019 12:09:38 +0100 Subject: [PATCH 1/3] x2ap: timers, cleanup This commit introduces X2AP timers (t_reloc_prep, tx2_reloc_overall). You need to set the values in the configuration file. X2AP can be enabled or disabled in the configuration file too (disabled by default). Some deadcode was removed. --- .../conf_files/enb.band13.tm1.50PRB.emtc.conf | 5 + ...d40.tm1.100PRB.FairScheduler.usrpb210.conf | 5 + ...nd40.tm1.25PRB.FairScheduler.usrpb210.conf | 5 + ...nd40.tm1.50PRB.FairScheduler.usrpb210.conf | 5 + .../enb.band7.tm1.100PRB.usrpb210.conf | 5 + .../enb.band7.tm1.25PRB.usrpb210.conf | 5 + .../enb.band7.tm1.50PRB.usrpb210.conf | 5 + .../enb.band7.tm2.25PRB.usrpb210.conf | 5 + ci-scripts/conf_files/lte-fdd-basic-sim.conf | 5 + ci-scripts/conf_files/lte-tdd-basic-sim.conf | 5 + ...d40.tm1.100PRB.FairScheduler.usrpb210.conf | 5 + ...nd40.tm1.25PRB.FairScheduler.usrpb210.conf | 5 + ...nd40.tm1.50PRB.FairScheduler.usrpb210.conf | 5 + ...cc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf | 5 + ...rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf | 5 + ...rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf | 5 + .../conf_files/rcc.band7.tm1.nfapi.conf | 5 + cmake_targets/CMakeLists.txt | 1 + .../enb.band38.tm1.usrpb210.tdd.10MHz.conf | 5 + .../enb.band38.tm1.usrpb210.tdd.20MHz.conf | 5 + .../enb.band38.tm1.usrpb210.tdd.5MHz.conf | 5 + .../enb.band7.tm1.usrpb210.fdd.10MHz.conf | 5 + .../enb.band7.tm1.usrpb210.fdd.20MHz.conf | 5 + .../enb.band7.tm1.usrpb210.fdd.5MHz.conf | 5 + .../v2/config/rcc.band7.tm1.if4p5.10MHz.conf | 5 + .../v2/config/rcc.band7.tm1.if4p5.20MHz.conf | 5 + .../v2/config/rcc.band7.tm1.if4p5.5MHz.conf | 5 + ...ru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf | 5 + ...ru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf | 5 + ...rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf | 5 + configuration/bladeRF/enb-band7-5mhz.conf | 5 + openair2/COMMON/x2ap_messages_def.h | 2 + openair2/COMMON/x2ap_messages_types.h | 19 + openair2/ENB_APP/enb_app.c | 12 +- openair2/ENB_APP/enb_config.c | 22 + openair2/RRC/LTE/rrc_defs.h | 3 +- openair2/RRC/LTE/rrc_eNB.c | 972 +++--------------- openair2/X2AP/x2ap_eNB.c | 46 + openair2/X2AP/x2ap_eNB.h | 2 + openair2/X2AP/x2ap_eNB_decoder.c | 6 + openair2/X2AP/x2ap_eNB_defs.h | 3 +- openair2/X2AP/x2ap_eNB_generate_messages.c | 84 ++ openair2/X2AP/x2ap_eNB_generate_messages.h | 5 + openair2/X2AP/x2ap_eNB_handler.c | 135 ++- openair2/X2AP/x2ap_ids.c | 36 + openair2/X2AP/x2ap_ids.h | 39 +- openair2/X2AP/x2ap_timers.c | 105 ++ openair2/X2AP/x2ap_timers.h | 45 + targets/COMMON/create_tasks.c | 11 +- .../CONF/enb.centos.calisson.conf | 5 + .../CONF/enb.centos.memphis.conf | 5 + .../CONF/enb.centos.nord.conf | 5 + .../CONF/enb.band13.tm1.50PRB.emtc.conf | 5 + .../CONF/enb.band38.tm1.100PRB.usrpx310.conf | 5 + .../CONF/enb.band38.tm1.25PRB.iris030.conf | 5 + .../CONF/enb.band38.tm1.usrpx310.conf | 5 + .../CONF/enb.band42.tm1.25PRB.iris030.conf | 5 + .../CONF/enb.band7.tm1.100PRB.usrpx310.conf | 5 + .../CONF/enb.band7.tm1.25PRB.iris030.conf | 5 + .../enb.band7.tm1.25PRB.usrpb210.replay.conf | 5 + .../enb.band7.tm1.50PRB.usrpb210-d2d.conf | 5 + .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 5 + ...band7.tm1.50PRB.usrpb210_ue_expansion.conf | 5 + .../CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf | 5 + .../CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf | 5 + .../CONF/rcc.band7.tm1.50PRB.nfapi.conf | 5 + .../CONF/rcc.band7.tm1.if4p5.50PRB.conf | 5 + .../CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf | 5 + 68 files changed, 936 insertions(+), 857 deletions(-) create mode 100644 openair2/X2AP/x2ap_timers.c create mode 100644 openair2/X2AP/x2ap_timers.h diff --git a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf b/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf index e3d3402c1c..4ee44fd415 100644 --- a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf +++ b/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf @@ -360,6 +360,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf index b6028a8152..1fc3114754 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf index 10cbd04e9a..2ef30ea4c2 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf index c79dbf1ac0..fbbade22f3 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf index 2c2ca635a6..c119e2f1c0 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf @@ -178,6 +178,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf index 4dd8c1ee22..a0d3ba6d06 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf @@ -178,6 +178,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf index cae47b152c..87beafad6b 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf @@ -178,6 +178,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf index 4e5510b0d4..5097a4f145 100644 --- a/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf @@ -181,6 +181,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/lte-fdd-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-basic-sim.conf index 594e3299db..22bb6608e0 100644 --- a/ci-scripts/conf_files/lte-fdd-basic-sim.conf +++ b/ci-scripts/conf_files/lte-fdd-basic-sim.conf @@ -178,6 +178,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { diff --git a/ci-scripts/conf_files/lte-tdd-basic-sim.conf b/ci-scripts/conf_files/lte-tdd-basic-sim.conf index da330d2379..a376f45453 100644 --- a/ci-scripts/conf_files/lte-tdd-basic-sim.conf +++ b/ci-scripts/conf_files/lte-tdd-basic-sim.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf index 285b7eaf9f..d39f1e0620 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf @@ -144,6 +144,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf index 62e7fb48a4..0ae17356de 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf @@ -144,6 +144,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf index f99b701b8e..c58f05c82f 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf @@ -144,6 +144,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf index 6c80a4f7cf..393588064b 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf @@ -181,6 +181,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf index f4be50810c..7c2ab85186 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf @@ -181,6 +181,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf index 48c8370b4b..77019a466e 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf @@ -181,6 +181,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf index c2a86f079e..40fba82f9c 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf @@ -179,6 +179,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "ens3"; diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 3f2041089f..95fc2cc150 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -471,6 +471,7 @@ add_library(X2AP_ENB ${X2AP_DIR}/x2ap_eNB_management_procedures.c ${X2AP_DIR}/x2ap_eNB_generate_messages.c ${X2AP_DIR}/x2ap_ids.c + ${X2AP_DIR}/x2ap_timers.c ) add_dependencies(X2AP_ENB rrc_flag x2_flag) diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf index 398b763888..d99ca88807 100644 --- a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf index 46b6484737..86c54a82f7 100644 --- a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf index 93b82773e6..dad0ab5a23 100644 --- a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf index b412b00e52..369b6184fd 100644 --- a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf index f0d688903a..14ae99c80c 100644 --- a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf index 929c91fffb..9302ac7c58 100644 --- a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf index 98358eb269..0ae9e659b4 100644 --- a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf index bc31e051e5..1d22c19ec8 100644 --- a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf index 2cfc227e67..3f35175ff4 100644 --- a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf @@ -141,6 +141,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf index 9b135a9498..0a6a8cccc6 100644 --- a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf @@ -143,6 +143,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf index 9f84057299..7ffdd063a6 100644 --- a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf @@ -143,6 +143,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf index 7197e93322..409fa49910 100644 --- a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf @@ -143,6 +143,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; diff --git a/configuration/bladeRF/enb-band7-5mhz.conf b/configuration/bladeRF/enb-band7-5mhz.conf index 6e07b8d949..127c865422 100644 --- a/configuration/bladeRF/enb-band7-5mhz.conf +++ b/configuration/bladeRF/enb-band7-5mhz.conf @@ -181,6 +181,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h index 65fa9c801d..2a040c8000 100644 --- a/openair2/COMMON/x2ap_messages_def.h +++ b/openair2/COMMON/x2ap_messages_def.h @@ -32,6 +32,7 @@ MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgT /* eNB application layer -> X2AP messages */ MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req) +MESSAGE_DEF(X2AP_SUBFRAME_PROCESS , MESSAGE_PRIORITY_MED, x2ap_subframe_process_t , x2ap_subframe_process) /* X2AP -> eNB application layer messages */ MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf) @@ -40,6 +41,7 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_der /* handover messages X2AP <-> RRC */ MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req) MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack) +MESSAGE_DEF(X2AP_HANDOVER_CANCEL , MESSAGE_PRIORITY_MED, x2ap_handover_cancel_t , x2ap_handover_cancel) /* handover messages X2AP <-> S1AP */ MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t , x2ap_ue_context_release) diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index 38429b712e..708430b8b2 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -34,6 +34,7 @@ #define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf #define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind #define X2AP_UE_CONTEXT_RELEASE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ue_context_release +#define X2AP_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_cancel #define X2AP_MAX_NB_ENB_IP_ADDRESS 2 @@ -48,6 +49,16 @@ typedef struct x2ap_ue_context_release_s { int source_assoc_id; } x2ap_ue_context_release_t; +typedef enum { + X2AP_T_RELOC_PREP_TIMEOUT, + X2AP_TX2_RELOC_OVERALL_TIMEOUT +} x2ap_handover_cancel_cause_t; + +typedef struct x2ap_handover_cancel_s { + int rnti; + x2ap_handover_cancel_cause_t cause; +} x2ap_handover_cancel_t; + typedef struct x2ap_register_enb_req_s { /* Unique eNB_id to identify the eNB within EPC. * For macro eNB ids this field should be 20 bits long. @@ -105,8 +116,16 @@ typedef struct x2ap_register_enb_req_s { /* eNB port for X2C*/ uint32_t enb_port_for_X2C; + + /* timers (unit: millisecond) */ + int t_reloc_prep; + int tx2_reloc_overall; } x2ap_register_enb_req_t; +typedef struct x2ap_subframe_process_s { + /* nothing, we simply use the module ID in the header */ +} x2ap_subframe_process_t; + //-------------------------------------------------------------------------------------------// // X2AP -> eNB application layer messages typedef struct x2ap_register_enb_cnf_s { diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 8d128c03e2..cba0211c51 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -151,8 +151,8 @@ void *eNB_app_task(void *args_p) { uint32_t register_enb_pending=0; uint32_t registered_enb; long enb_register_retry_timer_id; - uint32_t x2_register_enb_pending; - uint32_t x2_registered_enb; + uint32_t x2_register_enb_pending = 0; + uint32_t x2_registered_enb = 0; long x2_enb_register_retry_timer_id; uint32_t enb_id; MessageDef *msg_p = NULL; @@ -188,9 +188,11 @@ void *eNB_app_task(void *args_p) { register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p); } - /* Try to register each eNB with each other */ - x2_registered_enb = 0; - x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end); + if (is_x2ap_enabled()) { + /* Try to register each eNB with each other */ + x2_registered_enb = 0; + x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end); + } do { // Wait for a message diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index d4439ab349..c4e85c269a 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2053,6 +2053,28 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { } } + // timers + { + int t_reloc_prep = 0; + int tx2_reloc_overall = 0; + + paramdef_t p[] = { + { "t_reloc_prep", "t_reloc_prep", 0, iptr:&t_reloc_prep, defintval:0, TYPE_INT, 0 }, + { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 } + }; + + config_get(p, sizeof(p)/sizeof(paramdef_t), aprefix); + + if (t_reloc_prep <= 0 || t_reloc_prep > 10000 || + tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000) { + LOG_E(X2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000]\n"); + exit(1); + } + + X2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep; + X2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall; + } + // SCTP SETTING X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 22a9332a58..b576a7e933 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -344,7 +344,8 @@ typedef enum HO_STATE_e { HO_REQUEST, HO_ACK, HO_CONFIGURED, - HO_RELEASE + HO_RELEASE, + HO_CANCEL } HO_STATE_t; typedef enum SL_TRIGGER_e { diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index c69888b0c1..0c1e737d23 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -63,6 +63,7 @@ #include "LTE_PeriodicBSR-Timer-r12.h" #include "LTE_RetxBSR-Timer-r12.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "x2ap_eNB.h" #include "T.h" @@ -850,9 +851,7 @@ rrc_eNB_free_UE( LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ sent for RNTI %x, cause 21, radio connection with ue lost\n", enb_mod_idP, rnti); -#if defined(ENABLE_USE_MME) rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21); -#endif // send cause 21: radio connection with ue lost /* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered) * If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before @@ -868,9 +867,7 @@ rrc_eNB_free_UE( LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ sent for RNTI %x, cause 20, user inactivity\n", enb_mod_idP, rnti); -#if defined(ENABLE_USE_MME) rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 20); -#endif // send cause 20: user inactivity return; } @@ -1043,9 +1040,7 @@ rrc_eNB_process_RRCConnectionSetupComplete( if (EPC_MODE_ENABLED == 1) { // Forward message to S1AP layer -#if defined(ENABLE_USE_MME) rrc_eNB_send_S1AP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcConnectionSetupComplete); -#endif } else { // RRC loop back (no S1AP), send SecurityModeCommand to UE rrc_eNB_generate_SecurityModeCommand(ctxt_pP, ue_context_pP); @@ -1342,6 +1337,7 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete( /* for no gcc warnings */ (void)dedicatedInfoNas; LTE_C_RNTI_t *cba_RNTI = NULL; + int x2_enabled; uint8_t next_xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); ue_context_pP->ue_context.Status = RRC_CONNECTED; ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED @@ -1752,6 +1748,8 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete( dedicatedInfoNASList = NULL; } + x2_enabled = is_x2ap_enabled(); + // send LTE_RRCConnectionReconfiguration memset(buffer, 0, RRC_BUF_SIZE); size = do_RRCConnectionReconfiguration(ctxt_pP, @@ -1762,14 +1760,14 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete( (LTE_DRB_ToReleaseList_t *)NULL, // DRB2_list, (struct LTE_SPS_Config *)NULL, // maybe ue_context_pP->ue_context.sps_Config, (struct LTE_PhysicalConfigDedicated *)ue_context_pP->ue_context.physicalConfigDedicated, -#ifdef EXMIMO_IOT - NULL, NULL, NULL,NULL, -#else - (LTE_MeasObjectToAddModList_t *)MeasObj_list, // MeasObj_list, - (LTE_ReportConfigToAddModList_t *)ReportConfig_list, // ReportConfig_list, - (LTE_QuantityConfig_t *)quantityConfig, //quantityConfig, +//#ifdef EXMIMO_IOT +// NULL, NULL, NULL,NULL, +//#else + x2_enabled ? (LTE_MeasObjectToAddModList_t *)MeasObj_list : NULL, // MeasObj_list, + x2_enabled ? (LTE_ReportConfigToAddModList_t *)ReportConfig_list : NULL, // ReportConfig_list, + x2_enabled ? (LTE_QuantityConfig_t *)quantityConfig : NULL, //quantityConfig, (LTE_MeasIdToAddModList_t *)NULL, -#endif +//#endif (LTE_MAC_MainConfig_t *)ue_context_pP->ue_context.mac_MainConfig, (LTE_MeasGapConfig_t *)NULL, (LTE_MobilityControlInfo_t *)NULL, @@ -2655,6 +2653,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t *cons /* for no gcc warnings */ (void)dedicatedInfoNas; LTE_C_RNTI_t *cba_RNTI = NULL; + int x2_enabled; uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id, #ifdef CBA //struct PUSCH_CBAConfigDedicated_vlola *pusch_CBAConfigDedicated_vlola; @@ -3159,6 +3158,8 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t *cons dedicatedInfoNASList = NULL; } + x2_enabled = is_x2ap_enabled(); + memset(buffer, 0, RRC_BUF_SIZE); size = do_RRCConnectionReconfiguration(ctxt_pP, buffer, @@ -3171,10 +3172,10 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t *cons //#ifdef EXMIMO_IOT // NULL, NULL, NULL,NULL, //#else - (LTE_MeasObjectToAddModList_t *)MeasObj_list, - (LTE_ReportConfigToAddModList_t *)ReportConfig_list, - (LTE_QuantityConfig_t *)quantityConfig, - (LTE_MeasIdToAddModList_t *)MeasId_list, + x2_enabled ? (LTE_MeasObjectToAddModList_t *)MeasObj_list : NULL, + x2_enabled ? (LTE_ReportConfigToAddModList_t *)ReportConfig_list : NULL, + x2_enabled ? (LTE_QuantityConfig_t *)quantityConfig : NULL, + x2_enabled ? (LTE_MeasIdToAddModList_t *)MeasId_list : NULL, //#endif (LTE_MAC_MainConfig_t *)mac_MainConfig, (LTE_MeasGapConfig_t *)NULL, @@ -3285,6 +3286,7 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt /* for no gcc warnings */ (void)dedicatedInfoNas; LTE_C_RNTI_t *cba_RNTI = NULL; + int x2_enabled; uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id, #ifdef CBA //struct PUSCH_CBAConfigDedicated_vlola *pusch_CBAConfigDedicated_vlola; @@ -3652,6 +3654,8 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt dedicatedInfoNASList = NULL; } + x2_enabled = is_x2ap_enabled(); + memset(buffer, 0, RRC_BUF_SIZE); size = do_RRCConnectionReconfiguration(ctxt_pP, buffer, @@ -3664,10 +3668,10 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt // #ifdef EXMIMO_IOT // NULL, NULL, NULL,NULL, // #else - (LTE_MeasObjectToAddModList_t *)MeasObj_list, - (LTE_ReportConfigToAddModList_t *)ReportConfig_list, - (LTE_QuantityConfig_t *)quantityConfig, - (LTE_MeasIdToAddModList_t *)MeasId_list, + x2_enabled ? (LTE_MeasObjectToAddModList_t *)MeasObj_list : NULL, + x2_enabled ? (LTE_ReportConfigToAddModList_t *)ReportConfig_list : NULL, + x2_enabled ? (LTE_QuantityConfig_t *)quantityConfig : NULL, + x2_enabled ? (LTE_MeasIdToAddModList_t *)MeasId_list : NULL, // #endif (LTE_MAC_MainConfig_t *)mac_MainConfig, (LTE_MeasGapConfig_t *)NULL, @@ -3914,6 +3918,10 @@ rrc_eNB_process_MeasurementReport( if (!(measResults2->measId == 4)) return; + /* if X2AP is disabled, do nothing */ + if (!is_x2ap_enabled()) + return; + LOG_D(RRC, "A3 event is triggered...\n"); /* if the UE is not in handover mode, start handover procedure */ @@ -4126,10 +4134,9 @@ void rrc_eNB_process_handoverCommand( ue_context->ue_context.handover_info->size = size; } -#if defined(ENABLE_USE_MME) void rrc_eNB_handover_ue_context_release( -protocol_ctxt_t *const ctxt_pP, -struct rrc_eNB_ue_context_s *ue_context_p) { + protocol_ctxt_t *const ctxt_pP, + struct rrc_eNB_ue_context_s *ue_context_p) { int e_rab = 0; //MessageDef *msg_release_p = NULL; MessageDef *msg_delete_tunnels_p = NULL; @@ -4162,7 +4169,16 @@ struct rrc_eNB_ue_context_s *ue_context_p) { rrc_eNB_S1AP_remove_ue_ids(RC.rrc[ctxt_pP->module_id], rrc_ue_s1ap_ids); } } -#endif /* defined(ENABLE_USE_MME) */ + +/* This function may be incorrect. */ +void rrc_eNB_handover_cancel( + protocol_ctxt_t *const ctxt_pP, + struct rrc_eNB_ue_context_s *ue_context_p) { + int s1_cause = 1; /* 1 = tx2relocoverall-expiry */ + + rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(ctxt_pP->module_id, ue_context_p, + S1AP_CAUSE_RADIO_NETWORK, s1_cause); +} void check_handovers( @@ -4293,6 +4309,7 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct /* for no gcc warnings */ (void)dedicatedInfoNas; LTE_C_RNTI_t *cba_RNTI = NULL; + int x2_enabled; uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id, #ifdef CBA //struct PUSCH_CBAConfigDedicated_vlola *pusch_CBAConfigDedicated_vlola; @@ -5049,6 +5066,9 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct } #endif + + x2_enabled = is_x2ap_enabled(); + memset(buffer, 0, RRC_BUF_SIZE); char rrc_buf[1000 /* arbitrary, should be big enough, has to be less than size of return buf by a few bits/bytes */]; int rrc_size; @@ -5063,10 +5083,10 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct //#ifdef EXMIMO_IOT // NULL, NULL, NULL,NULL, //#else - (LTE_MeasObjectToAddModList_t *)MeasObj_list, - (LTE_ReportConfigToAddModList_t *)ReportConfig_list, - (LTE_QuantityConfig_t *)quantityConfig, - (LTE_MeasIdToAddModList_t *)MeasId_list, + x2_enabled ? (LTE_MeasObjectToAddModList_t *)MeasObj_list : NULL, + x2_enabled ? (LTE_ReportConfigToAddModList_t *)ReportConfig_list : NULL, + x2_enabled ? (LTE_QuantityConfig_t *)quantityConfig : NULL, + x2_enabled ? (LTE_MeasIdToAddModList_t *)MeasId_list : NULL, //#endif (LTE_MAC_MainConfig_t *)mac_MainConfig, (LTE_MeasGapConfig_t *)NULL, @@ -5168,20 +5188,21 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc , 0, 0 #endif ); -#if defined(ENABLE_USE_MME) - rrc_eNB_process_security ( - ctxt_pP, - ue_context_p, - &ue_context_p->ue_context.security_capabilities); - process_eNB_security_key ( - ctxt_pP, - ue_context_p, - ue_context_p->ue_context.kenb); - rrc_pdcp_config_security( - ctxt_pP, - ue_context_p, - FALSE); -#endif + + if (EPC_MODE_ENABLED) { + rrc_eNB_process_security ( + ctxt_pP, + ue_context_p, + &ue_context_p->ue_context.security_capabilities); + process_eNB_security_key ( + ctxt_pP, + ue_context_p, + ue_context_p->ue_context.kenb); + rrc_pdcp_config_security( + ctxt_pP, + ue_context_p, + FALSE); + } // Add a new user (called during the HO procedure) LOG_I(RRC, "rrc_eNB_target_add_ue_handover module_id %d rnti %d\n", ctxt_pP->module_id, ctxt_pP->rnti); @@ -5229,788 +5250,6 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc #endif } -#if 0 -// 5.3.5.4 LTE_RRCConnectionReconfiguration including the mobilityControlInfo to prepare the UE handover -//----------------------------------------------------------------------------- -void -rrc_eNB_generate_RRCConnectionReconfiguration_handover( - const protocol_ctxt_t *const ctxt_pP, - rrc_eNB_ue_context_t *const ue_context_pP, - uint8_t *const nas_pdu, - const uint32_t nas_length -) -//----------------------------------------------------------------------------- -{ - T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), - T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); - uint8_t buffer[RRC_BUF_SIZE]; - int i; - uint8_t rv[2]; - uint16_t Idx; - // configure SRB1/SRB2, PhysicalConfigDedicated, LTE_MAC_MainConfig for UE - eNB_RRC_INST *rrc_inst = RC.rrc[ctxt_pP->module_id]; - struct LTE_PhysicalConfigDedicated **physicalConfigDedicated = &ue_context_pP->ue_context.physicalConfigDedicated; - struct LTE_SRB_ToAddMod *SRB2_config; - struct LTE_SRB_ToAddMod__rlc_Config *SRB2_rlc_config; - struct LTE_SRB_ToAddMod__logicalChannelConfig *SRB2_lchan_config; - struct LTE_LogicalChannelConfig__ul_SpecificParameters *SRB2_ul_SpecificParameters; - LTE_LogicalChannelConfig_t *SRB1_logicalChannelConfig = NULL; - LTE_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; // not used in this context: may be removed - LTE_SRB_ToAddModList_t *SRB_configList2; - struct LTE_DRB_ToAddMod *DRB_config; - struct LTE_RLC_Config *DRB_rlc_config; - struct LTE_PDCP_Config *DRB_pdcp_config; - struct LTE_PDCP_Config__rlc_UM *PDCP_rlc_UM; - struct LTE_LogicalChannelConfig *DRB_lchan_config; - struct LTE_LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters; - LTE_DRB_ToAddModList_t *DRB_configList2; - LTE_MAC_MainConfig_t *mac_MainConfig; - LTE_MeasObjectToAddModList_t *MeasObj_list; - LTE_MeasObjectToAddMod_t *MeasObj; - LTE_ReportConfigToAddModList_t *ReportConfig_list; - LTE_ReportConfigToAddMod_t *ReportConfig_per, *ReportConfig_A1, - *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5; - LTE_MeasIdToAddModList_t *MeasId_list; - LTE_MeasIdToAddMod_t *MeasId0, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5; - LTE_QuantityConfig_t *quantityConfig; - LTE_MobilityControlInfo_t *mobilityInfo; - // HandoverCommand_t handoverCommand; - //uint8_t sourceModId = - // get_adjacent_cell_mod_id(ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->sourcePhysCellId); -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - long *sr_ProhibitTimer_r9; -#endif - long *logicalchannelgroup, *logicalchannelgroup_drb; - long *maxHARQ_Tx, *periodicBSR_Timer; - // LTE_RSRP_Range_t *rsrp; - struct LTE_MeasConfig__speedStatePars *Sparams; - LTE_CellsToAddMod_t *CellToAdd; - LTE_CellsToAddModList_t *CellsToAddModList; - // srb 1: for HO - struct LTE_SRB_ToAddMod *SRB1_config; - struct LTE_SRB_ToAddMod__rlc_Config *SRB1_rlc_config; - struct LTE_SRB_ToAddMod__logicalChannelConfig *SRB1_lchan_config; - struct LTE_LogicalChannelConfig__ul_SpecificParameters *SRB1_ul_SpecificParameters; - // phy config dedicated - LTE_PhysicalConfigDedicated_t *physicalConfigDedicated2; - struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList; - protocol_ctxt_t ctxt; - LOG_D(RRC, "[eNB %d] Frame %d: handover preparation: get the newSourceUEIdentity (C-RNTI): ", - ctxt_pP->module_id, ctxt_pP->frame); - - for (i = 0; i < 2; i++) { - rv[i] = taus() & 0xff; - LOG_D(RRC, " %x.", rv[i]); - } - - LOG_D(RRC, "[eNB %d] Frame %d : handover reparation: add target eNB SRB1 and PHYConfigDedicated reconfiguration\n", - ctxt_pP->module_id, ctxt_pP->frame); - // 1st: reconfigure SRB - SRB_configList2 = CALLOC(1, sizeof(*SRB_configList)); - SRB1_config = CALLOC(1, sizeof(*SRB1_config)); - SRB1_config->srb_Identity = 1; - SRB1_rlc_config = CALLOC(1, sizeof(*SRB1_rlc_config)); - SRB1_config->rlc_Config = SRB1_rlc_config; - SRB1_rlc_config->present = LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue; - SRB1_rlc_config->choice.explicitValue.present = LTE_RLC_Config_PR_am; - SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.t_PollRetransmit = LTE_T_PollRetransmit_ms15; - SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollPDU = LTE_PollPDU_p8; - SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollByte = LTE_PollByte_kB1000; - SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.maxRetxThreshold = LTE_UL_AM_RLC__maxRetxThreshold_t16; - SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_Reordering = LTE_T_Reordering_ms35; - SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_StatusProhibit = LTE_T_StatusProhibit_ms10; - SRB1_lchan_config = CALLOC(1, sizeof(*SRB1_lchan_config)); - SRB1_config->logicalChannelConfig = SRB1_lchan_config; - SRB1_lchan_config->present = LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue; - SRB1_ul_SpecificParameters = CALLOC(1, sizeof(*SRB1_ul_SpecificParameters)); - SRB1_lchan_config->choice.explicitValue.ul_SpecificParameters = SRB1_ul_SpecificParameters; - SRB1_ul_SpecificParameters->priority = 1; - //assign_enum(&SRB1_ul_SpecificParameters->prioritisedBitRate,LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity); - SRB1_ul_SpecificParameters->prioritisedBitRate = - LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - //assign_enum(&SRB1_ul_SpecificParameters->bucketSizeDuration,LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50); - SRB1_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - logicalchannelgroup = CALLOC(1, sizeof(long)); - *logicalchannelgroup = 0; - SRB1_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup; - ASN_SEQUENCE_ADD(&SRB_configList2->list, SRB1_config); - //2nd: now reconfigure phy config dedicated - physicalConfigDedicated2 = CALLOC(1, sizeof(*physicalConfigDedicated2)); - *physicalConfigDedicated = physicalConfigDedicated2; - physicalConfigDedicated2->pdsch_ConfigDedicated = - CALLOC(1, sizeof(*physicalConfigDedicated2->pdsch_ConfigDedicated)); - physicalConfigDedicated2->pucch_ConfigDedicated = - CALLOC(1, sizeof(*physicalConfigDedicated2->pucch_ConfigDedicated)); - physicalConfigDedicated2->pusch_ConfigDedicated = - CALLOC(1, sizeof(*physicalConfigDedicated2->pusch_ConfigDedicated)); - physicalConfigDedicated2->uplinkPowerControlDedicated = - CALLOC(1, sizeof(*physicalConfigDedicated2->uplinkPowerControlDedicated)); - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH = - CALLOC(1, sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH)); - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH = - CALLOC(1, sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH)); - physicalConfigDedicated2->cqi_ReportConfig = NULL; //CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig)); - physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated)); - physicalConfigDedicated2->antennaInfo = CALLOC(1, sizeof(*physicalConfigDedicated2->antennaInfo)); - physicalConfigDedicated2->schedulingRequestConfig = - CALLOC(1, sizeof(*physicalConfigDedicated2->schedulingRequestConfig)); - // PDSCH - //assign_enum(&physicalConfigDedicated2->pdsch_ConfigDedicated->p_a, - // PDSCH_ConfigDedicated__p_a_dB0); - physicalConfigDedicated2->pdsch_ConfigDedicated->p_a = LTE_PDSCH_ConfigDedicated__p_a_dB0; - // PUCCH - physicalConfigDedicated2->pucch_ConfigDedicated->ackNackRepetition.present = - LTE_PUCCH_ConfigDedicated__ackNackRepetition_PR_release; - physicalConfigDedicated2->pucch_ConfigDedicated->ackNackRepetition.choice.release = 0; - physicalConfigDedicated2->pucch_ConfigDedicated->tdd_AckNackFeedbackMode = NULL; //PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing; - // Pusch_config_dedicated - physicalConfigDedicated2->pusch_ConfigDedicated->betaOffset_ACK_Index = 0; // 2.00 - physicalConfigDedicated2->pusch_ConfigDedicated->betaOffset_RI_Index = 0; // 1.25 - physicalConfigDedicated2->pusch_ConfigDedicated->betaOffset_CQI_Index = 8; // 2.25 - // UplinkPowerControlDedicated - physicalConfigDedicated2->uplinkPowerControlDedicated->p0_UE_PUSCH = 0; // 0 dB - //assign_enum(&physicalConfigDedicated2->uplinkPowerControlDedicated->deltaMCS_Enabled, - // UplinkPowerControlDedicated__deltaMCS_Enabled_en1); - physicalConfigDedicated2->uplinkPowerControlDedicated->deltaMCS_Enabled = - LTE_UplinkPowerControlDedicated__deltaMCS_Enabled_en1; - physicalConfigDedicated2->uplinkPowerControlDedicated->accumulationEnabled = 1; // should be TRUE in order to have 0dB power offset - physicalConfigDedicated2->uplinkPowerControlDedicated->p0_UE_PUCCH = 0; // 0 dB - physicalConfigDedicated2->uplinkPowerControlDedicated->pSRS_Offset = 0; // 0 dB - physicalConfigDedicated2->uplinkPowerControlDedicated->filterCoefficient = - CALLOC(1, sizeof(*physicalConfigDedicated2->uplinkPowerControlDedicated->filterCoefficient)); - // assign_enum(physicalConfigDedicated2->uplinkPowerControlDedicated->filterCoefficient,FilterCoefficient_fc4); // fc4 dB - *physicalConfigDedicated2->uplinkPowerControlDedicated->filterCoefficient = LTE_FilterCoefficient_fc4; // fc4 dB - // TPC-PDCCH-Config - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->present = LTE_TPC_PDCCH_Config_PR_setup; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_Index.present = LTE_TPC_Index_PR_indexOfFormat3; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_Index.choice.indexOfFormat3 = 1; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.buf = CALLOC(1, 2); - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.size = 2; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.buf[0] = 0x12; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.buf[1] = 0x34 + ue_context_pP->local_uid; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.bits_unused = 0; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->present = LTE_TPC_PDCCH_Config_PR_setup; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_Index.present = LTE_TPC_Index_PR_indexOfFormat3; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_Index.choice.indexOfFormat3 = 1; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.buf = CALLOC(1, 2); - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.size = 2; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.buf[0] = 0x22; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.buf[1] = 0x34 + ue_context_pP->local_uid; - physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.bits_unused = 0; - //AntennaInfoDedicated - physicalConfigDedicated2->antennaInfo = CALLOC(1, sizeof(*physicalConfigDedicated2->antennaInfo)); - physicalConfigDedicated2->antennaInfo->present = LTE_PhysicalConfigDedicated__antennaInfo_PR_explicitValue; - physicalConfigDedicated2->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.present = - LTE_AntennaInfoDedicated__ue_TransmitAntennaSelection_PR_release; - physicalConfigDedicated2->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.release = 0; - // SchedulingRequestConfig - physicalConfigDedicated2->schedulingRequestConfig->present = LTE_SchedulingRequestConfig_PR_setup; - physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = ue_context_pP->local_uid; - - if (rrc_inst->carrier[0].sib1->tdd_Config==NULL) { // FD - physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 5 + (ue_context_pP->local_uid % - 10); // Isr = 5 (every 10 subframes, offset=2+UE_id mod3) - } else { - switch (rrc_inst->carrier[0].sib1->tdd_Config->subframeAssignment) { - case 1: - physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7 + (ue_context_pP->local_uid & 1) + (( - ue_context_pP->local_uid & 3) >> 1) * 5; // Isr = 5 (every 10 subframes, offset=2 for UE0, 3 for UE1, 7 for UE2, 8 for UE3 , 2 for UE4 etc..) - break; - - case 3: - physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7 + (ue_context_pP->local_uid % - 3); // Isr = 5 (every 10 subframes, offset=2 for UE0, 3 for UE1, 3 for UE2, 2 for UE3 , etc..) - break; - - case 4: - physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7 + (ue_context_pP->local_uid & - 1); // Isr = 5 (every 10 subframes, offset=2 for UE0, 3 for UE1, 3 for UE2, 2 for UE3 , etc..) - break; - - default: - physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7; // Isr = 5 (every 10 subframes, offset=2 for all UE0 etc..) - break; - } - } - - // assign_enum(&physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax, - //SchedulingRequestConfig__setup__dsr_TransMax_n4); - // assign_enum(&physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax = SchedulingRequestConfig__setup__dsr_TransMax_n4; - physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax = - LTE_SchedulingRequestConfig__setup__dsr_TransMax_n4; - LOG_D(RRC, - "handover_config [FRAME %05d][RRC_eNB][MOD %02d][][--- MAC_CONFIG_REQ (SRB1 UE %x) --->][MAC_eNB][MOD %02d][]\n", - ctxt_pP->frame, ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ctxt_pP->module_id); - rrc_mac_config_req_eNB( - ctxt_pP->module_id, - ue_context_pP->ue_context.primaryCC_id, - 0,0,0,0,0, -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - 0, -#endif - ue_context_pP->ue_context.rnti, - (LTE_BCCH_BCH_Message_t *) NULL, - (LTE_RadioResourceConfigCommonSIB_t *) NULL, -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - (LTE_RadioResourceConfigCommonSIB_t *) NULL, -#endif - ue_context_pP->ue_context.physicalConfigDedicated, -#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - (LTE_SCellToAddMod_r10_t *)NULL, - //(struct LTE_PhysicalConfigDedicatedSCell_r10 *)NULL, -#endif - (LTE_MeasObjectToAddMod_t **) NULL, - ue_context_pP->ue_context.mac_MainConfig, - 1, - SRB1_logicalChannelConfig, - ue_context_pP->ue_context.measGapConfig, - (LTE_TDD_Config_t *) NULL, - (LTE_MobilityControlInfo_t *) NULL, - (LTE_SchedulingInfoList_t *) NULL, - 0, - NULL, - NULL, - (LTE_MBSFN_SubframeConfigList_t *) NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - , 0, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) NULL -#endif -#if (LTE_RRC_VERSION >= MAKE_VERSION(13, 0, 0)) - , - (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL -#endif - ); - // Configure target eNB SRB2 - /// SRB2 - SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - SRB_configList2 = CALLOC(1, sizeof(*SRB_configList2)); - memset(SRB_configList2, 0, sizeof(*SRB_configList2)); - SRB2_config->srb_Identity = 2; - SRB2_rlc_config = CALLOC(1, sizeof(*SRB2_rlc_config)); - SRB2_config->rlc_Config = SRB2_rlc_config; - SRB2_rlc_config->present = LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue; - SRB2_rlc_config->choice.explicitValue.present = LTE_RLC_Config_PR_am; - SRB2_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.t_PollRetransmit = LTE_T_PollRetransmit_ms15; - SRB2_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollPDU = LTE_PollPDU_p8; - SRB2_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollByte = LTE_PollByte_kB1000; - SRB2_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.maxRetxThreshold = LTE_UL_AM_RLC__maxRetxThreshold_t32; - SRB2_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_Reordering = LTE_T_Reordering_ms35; - SRB2_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_StatusProhibit = LTE_T_StatusProhibit_ms10; - SRB2_lchan_config = CALLOC(1, sizeof(*SRB2_lchan_config)); - SRB2_config->logicalChannelConfig = SRB2_lchan_config; - SRB2_lchan_config->present = LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue; - SRB2_ul_SpecificParameters = CALLOC(1, sizeof(*SRB2_ul_SpecificParameters)); - SRB2_ul_SpecificParameters->priority = 1; - SRB2_ul_SpecificParameters->prioritisedBitRate = - LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - SRB2_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - // LCG for CCCH and DCCH is 0 as defined in 36331 - logicalchannelgroup = CALLOC(1, sizeof(long)); - *logicalchannelgroup = 0; - SRB2_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup; - SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters = SRB2_ul_SpecificParameters; - ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); - ASN_SEQUENCE_ADD(&SRB_configList2->list, SRB2_config); - // Configure target eNB DRB - DRB_configList2 = CALLOC(1, sizeof(*DRB_configList2)); - /// DRB - DRB_config = CALLOC(1, sizeof(*DRB_config)); - //DRB_config->drb_Identity = (LTE_DRB_Identity_t) 1; //allowed values 1..32 - // NN: this is the 1st DRB for this ue, so set it to 1 - DRB_config->drb_Identity = (LTE_DRB_Identity_t) 1; // (ue_mod_idP+1); //allowed values 1..32 - DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); - *(DRB_config->logicalChannelIdentity) = (long)3; - DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config)); - DRB_config->rlc_Config = DRB_rlc_config; - DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional; - DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35; - DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config)); - DRB_config->pdcp_Config = DRB_pdcp_config; - DRB_pdcp_config->discardTimer = NULL; - DRB_pdcp_config->rlc_AM = NULL; - PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM)); - DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; - PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; - DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed; - DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); - DRB_config->logicalChannelConfig = DRB_lchan_config; - DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); - DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; - DRB_ul_SpecificParameters->priority = 2; // lower priority than srb1, srb2 - DRB_ul_SpecificParameters->prioritisedBitRate = - LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - DRB_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM) - logicalchannelgroup_drb = CALLOC(1, sizeof(long)); - *logicalchannelgroup_drb = 1; - DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb; - ASN_SEQUENCE_ADD(&DRB_configList2->list, DRB_config); - mac_MainConfig = CALLOC(1, sizeof(*mac_MainConfig)); - ue_context_pP->ue_context.mac_MainConfig = mac_MainConfig; - mac_MainConfig->ul_SCH_Config = CALLOC(1, sizeof(*mac_MainConfig->ul_SCH_Config)); - maxHARQ_Tx = CALLOC(1, sizeof(long)); - *maxHARQ_Tx = LTE_MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; - mac_MainConfig->ul_SCH_Config->maxHARQ_Tx = maxHARQ_Tx; - periodicBSR_Timer = CALLOC(1, sizeof(long)); - *periodicBSR_Timer = LTE_PeriodicBSR_Timer_r12_sf64; - mac_MainConfig->ul_SCH_Config->periodicBSR_Timer = periodicBSR_Timer; - mac_MainConfig->ul_SCH_Config->retxBSR_Timer = LTE_RetxBSR_Timer_r12_sf320; - mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // FALSE - mac_MainConfig->drx_Config = NULL; - mac_MainConfig->phr_Config = CALLOC(1, sizeof(*mac_MainConfig->phr_Config)); - mac_MainConfig->phr_Config->present = LTE_MAC_MainConfig__phr_Config_PR_setup; - mac_MainConfig->phr_Config->choice.setup.periodicPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; // sf20 = 20 subframes - mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; // sf20 = 20 subframes - mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = LTE_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; // Value dB1 =1 dB, dB3 = 3 dB -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - sr_ProhibitTimer_r9 = CALLOC(1, sizeof(long)); - *sr_ProhibitTimer_r9 = 0; // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2= 2*SR - mac_MainConfig->ext1 = CALLOC(1, sizeof(struct LTE_MAC_MainConfig__ext1)); - mac_MainConfig->ext1->sr_ProhibitTimer_r9 = sr_ProhibitTimer_r9; - //sps_RA_ConfigList_rlola = NULL; -#endif - // Measurement ID list - MeasId_list = CALLOC(1, sizeof(*MeasId_list)); - memset((void *)MeasId_list, 0, sizeof(*MeasId_list)); - MeasId0 = CALLOC(1, sizeof(*MeasId0)); - MeasId0->measId = 1; - MeasId0->measObjectId = 1; - MeasId0->reportConfigId = 1; - ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId0); - MeasId1 = CALLOC(1, sizeof(*MeasId1)); - MeasId1->measId = 2; - MeasId1->measObjectId = 1; - MeasId1->reportConfigId = 2; - ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId1); - MeasId2 = CALLOC(1, sizeof(*MeasId2)); - MeasId2->measId = 3; - MeasId2->measObjectId = 1; - MeasId2->reportConfigId = 3; - ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId2); - MeasId3 = CALLOC(1, sizeof(*MeasId3)); - MeasId3->measId = 4; - MeasId3->measObjectId = 1; - MeasId3->reportConfigId = 4; - ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId3); - MeasId4 = CALLOC(1, sizeof(*MeasId4)); - MeasId4->measId = 5; - MeasId4->measObjectId = 1; - MeasId4->reportConfigId = 5; - ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId4); - MeasId5 = CALLOC(1, sizeof(*MeasId5)); - MeasId5->measId = 6; - MeasId5->measObjectId = 1; - MeasId5->reportConfigId = 6; - ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId5); - // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list; - // Add one EUTRA Measurement Object - MeasObj_list = CALLOC(1, sizeof(*MeasObj_list)); - memset((void *)MeasObj_list, 0, sizeof(*MeasObj_list)); - // Configure MeasObject - MeasObj = CALLOC(1, sizeof(*MeasObj)); - memset((void *)MeasObj, 0, sizeof(*MeasObj)); - MeasObj->measObjectId = 1; - MeasObj->measObject.present = LTE_MeasObjectToAddMod__measObject_PR_measObjectEUTRA; - MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 36090; - MeasObj->measObject.choice.measObjectEUTRA.allowedMeasBandwidth = LTE_AllowedMeasBandwidth_mbw25; - MeasObj->measObject.choice.measObjectEUTRA.presenceAntennaPort1 = 1; - MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf = CALLOC(1, sizeof(uint8_t)); - MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0; - MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; - MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; - MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; - - // Add adjacent cell lists (6 per eNB) - for (i = 0; i < 6; i++) { - CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); - CellToAdd->cellIndex = i + 1; - CellToAdd->physCellId = get_adjacent_cell_id(ctxt_pP->module_id, i); - CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; - ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); - } - - ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); - // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; - // Report Configurations for periodical, A1-A5 events - ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); - ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); - ReportConfig_A1 = CALLOC(1, sizeof(*ReportConfig_A1)); - ReportConfig_A2 = CALLOC(1, sizeof(*ReportConfig_A2)); - ReportConfig_A3 = CALLOC(1, sizeof(*ReportConfig_A3)); - ReportConfig_A4 = CALLOC(1, sizeof(*ReportConfig_A4)); - ReportConfig_A5 = CALLOC(1, sizeof(*ReportConfig_A5)); - ReportConfig_per->reportConfigId = 1; - ReportConfig_per->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.present = - LTE_ReportConfigEUTRA__triggerType_PR_periodical; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.choice.periodical.purpose = - LTE_ReportConfigEUTRA__triggerType__periodical__purpose_reportStrongestCells; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; - ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_per); - ReportConfig_A1->reportConfigId = 2; - ReportConfig_A1->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.present = - LTE_ReportConfigEUTRA__triggerType_PR_event; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = - LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA1; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1. - a1_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1. - a1_Threshold.choice.threshold_RSRP = 10; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; - ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; - ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A1); - ReportConfig_A2->reportConfigId = 3; - ReportConfig_A2->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.present = - LTE_ReportConfigEUTRA__triggerType_PR_event; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = - LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA2; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA2. - a2_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA2. - a2_Threshold.choice.threshold_RSRP = 10; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; - ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; - ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A2); - ReportConfig_A3->reportConfigId = 4; - ReportConfig_A3->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.present = - LTE_ReportConfigEUTRA__triggerType_PR_event; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = - LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA3; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset = - 10; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. - eventA3.reportOnLeave = 1; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; - ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; - ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A3); - ReportConfig_A4->reportConfigId = 5; - ReportConfig_A4->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.present = - LTE_ReportConfigEUTRA__triggerType_PR_event; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = - LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA4; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA4. - a4_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA4. - a4_Threshold.choice.threshold_RSRP = 10; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; - ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; - ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A4); - ReportConfig_A5->reportConfigId = 6; - ReportConfig_A5->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.present = - LTE_ReportConfigEUTRA__triggerType_PR_event; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = - LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA5; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. - eventA5.a5_Threshold1.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. - eventA5.a5_Threshold2.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. - eventA5.a5_Threshold1.choice.threshold_RSRP = 10; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. - eventA5.a5_Threshold2.choice.threshold_RSRP = 10; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; - ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; - ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); - Sparams = CALLOC(1, sizeof(*Sparams)); - Sparams->present = LTE_MeasConfig__speedStatePars_PR_setup; - Sparams->choice.setup.timeToTrigger_SF.sf_High = LTE_SpeedStateScaleFactors__sf_Medium_oDot75; - Sparams->choice.setup.timeToTrigger_SF.sf_Medium = LTE_SpeedStateScaleFactors__sf_High_oDot5; - Sparams->choice.setup.mobilityStateParameters.n_CellChangeHigh = 10; - Sparams->choice.setup.mobilityStateParameters.n_CellChangeMedium = 5; - Sparams->choice.setup.mobilityStateParameters.t_Evaluation = LTE_MobilityStateParameters__t_Evaluation_s60; - Sparams->choice.setup.mobilityStateParameters.t_HystNormal = LTE_MobilityStateParameters__t_HystNormal_s120; - quantityConfig = CALLOC(1, sizeof(*quantityConfig)); - memset((void *)quantityConfig, 0, sizeof(*quantityConfig)); - quantityConfig->quantityConfigEUTRA = CALLOC(1, sizeof(*quantityConfig->quantityConfigEUTRA)); - memset((void *)quantityConfig->quantityConfigEUTRA, 0, sizeof(*quantityConfig->quantityConfigEUTRA)); - quantityConfig->quantityConfigCDMA2000 = NULL; - quantityConfig->quantityConfigGERAN = NULL; - quantityConfig->quantityConfigUTRA = NULL; - quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = - CALLOC(1, sizeof(*quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP)); - quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = - CALLOC(1, sizeof(*quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ)); - *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = LTE_FilterCoefficient_fc4; - *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = LTE_FilterCoefficient_fc4; - /* mobilityinfo */ - mobilityInfo = CALLOC(1, sizeof(*mobilityInfo)); - memset((void *)mobilityInfo, 0, sizeof(*mobilityInfo)); - mobilityInfo->targetPhysCellId = - (LTE_PhysCellId_t) two_tier_hexagonal_cellIds[ue_context_pP->ue_context.handover_info->modid_t]; - LOG_D(RRC, "[eNB %d] Frame %d: handover preparation: targetPhysCellId: %ld mod_id: %d ue: %x \n", - ctxt_pP->module_id, - ctxt_pP->frame, - mobilityInfo->targetPhysCellId, - ctxt_pP->module_id, - ue_context_pP->ue_context.rnti); - mobilityInfo->additionalSpectrumEmission = CALLOC(1, sizeof(*mobilityInfo->additionalSpectrumEmission)); - *mobilityInfo->additionalSpectrumEmission = 1; //Check this value! - mobilityInfo->t304 = LTE_MobilityControlInfo__t304_ms50; // need to configure an appropriate value here - // New UE Identity (C-RNTI) to identify an UE uniquely in a cell - mobilityInfo->newUE_Identity.size = 2; - mobilityInfo->newUE_Identity.bits_unused = 0; - mobilityInfo->newUE_Identity.buf = rv; - mobilityInfo->newUE_Identity.buf[0] = rv[0]; - mobilityInfo->newUE_Identity.buf[1] = rv[1]; - //memset((void *)&mobilityInfo->radioResourceConfigCommon,(void *)&rrc_inst->sib2->radioResourceConfigCommon,sizeof(RadioResourceConfigCommon_t)); - //memset((void *)&mobilityInfo->radioResourceConfigCommon,0,sizeof(RadioResourceConfigCommon_t)); - // Configuring radioResourceConfigCommon - mobilityInfo->radioResourceConfigCommon.rach_ConfigCommon = - CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.rach_ConfigCommon)); - memcpy((void *)mobilityInfo->radioResourceConfigCommon.rach_ConfigCommon, - (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.rach_ConfigCommon, sizeof(LTE_RACH_ConfigCommon_t)); - mobilityInfo->radioResourceConfigCommon.prach_Config.prach_ConfigInfo = - CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.prach_Config.prach_ConfigInfo)); - memcpy((void *)mobilityInfo->radioResourceConfigCommon.prach_Config.prach_ConfigInfo, - (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.prach_Config.prach_ConfigInfo, - sizeof(LTE_PRACH_ConfigInfo_t)); - mobilityInfo->radioResourceConfigCommon.prach_Config.rootSequenceIndex = - rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.prach_Config.rootSequenceIndex; - mobilityInfo->radioResourceConfigCommon.pdsch_ConfigCommon = - CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.pdsch_ConfigCommon)); - memcpy((void *)mobilityInfo->radioResourceConfigCommon.pdsch_ConfigCommon, - (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.pdsch_ConfigCommon, sizeof(LTE_PDSCH_ConfigCommon_t)); - memcpy((void *)&mobilityInfo->radioResourceConfigCommon.pusch_ConfigCommon, - (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.pusch_ConfigCommon, sizeof(LTE_PUSCH_ConfigCommon_t)); - mobilityInfo->radioResourceConfigCommon.phich_Config = NULL; - mobilityInfo->radioResourceConfigCommon.pucch_ConfigCommon = - CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.pucch_ConfigCommon)); - memcpy((void *)mobilityInfo->radioResourceConfigCommon.pucch_ConfigCommon, - (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.pucch_ConfigCommon, sizeof(LTE_PUCCH_ConfigCommon_t)); - mobilityInfo->radioResourceConfigCommon.soundingRS_UL_ConfigCommon = - CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.soundingRS_UL_ConfigCommon)); - memcpy((void *)mobilityInfo->radioResourceConfigCommon.soundingRS_UL_ConfigCommon, - (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon, - sizeof(LTE_SoundingRS_UL_ConfigCommon_t)); - mobilityInfo->radioResourceConfigCommon.uplinkPowerControlCommon = - CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.uplinkPowerControlCommon)); - memcpy((void *)mobilityInfo->radioResourceConfigCommon.uplinkPowerControlCommon, - (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.uplinkPowerControlCommon, - sizeof(LTE_UplinkPowerControlCommon_t)); - mobilityInfo->radioResourceConfigCommon.antennaInfoCommon = NULL; - mobilityInfo->radioResourceConfigCommon.p_Max = NULL; // CALLOC(1,sizeof(*mobilityInfo->radioResourceConfigCommon.p_Max)); - //memcpy((void *)mobilityInfo->radioResourceConfigCommon.p_Max,(void *)rrc_inst->sib1->p_Max,sizeof(P_Max_t)); - mobilityInfo->radioResourceConfigCommon.tdd_Config = NULL; //CALLOC(1,sizeof(LTE_TDD_Config_t)); - //memcpy((void *)mobilityInfo->radioResourceConfigCommon.tdd_Config,(void *)rrc_inst->sib1->tdd_Config,sizeof(LTE_TDD_Config_t)); - mobilityInfo->radioResourceConfigCommon.ul_CyclicPrefixLength = - rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.ul_CyclicPrefixLength; - //End of configuration of radioResourceConfigCommon - mobilityInfo->carrierFreq = CALLOC(1, sizeof(*mobilityInfo->carrierFreq)); //CALLOC(1,sizeof(CarrierFreqEUTRA_t)); 36090 - mobilityInfo->carrierFreq->dl_CarrierFreq = 36090; - mobilityInfo->carrierFreq->ul_CarrierFreq = NULL; - mobilityInfo->carrierBandwidth = CALLOC(1, sizeof( - *mobilityInfo->carrierBandwidth)); //CALLOC(1,sizeof(struct LTE_CarrierBandwidthEUTRA)); LTE_AllowedMeasBandwidth_mbw25 - mobilityInfo->carrierBandwidth->dl_Bandwidth = LTE_CarrierBandwidthEUTRA__dl_Bandwidth_n25; - mobilityInfo->carrierBandwidth->ul_Bandwidth = NULL; - mobilityInfo->rach_ConfigDedicated = NULL; - // store the srb and drb list for ho management, mainly in case of failure - memcpy(ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.srb_ToAddModList, - (void *)SRB_configList2, - sizeof(LTE_SRB_ToAddModList_t)); - memcpy((void *)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToAddModList, - (void *)DRB_configList2, - sizeof(LTE_DRB_ToAddModList_t)); - ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToReleaseList = NULL; - memcpy((void *)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig, - (void *)mac_MainConfig, - sizeof(LTE_MAC_MainConfig_t)); - memcpy((void *)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.physicalConfigDedicated, - (void *)ue_context_pP->ue_context.physicalConfigDedicated, - sizeof(LTE_PhysicalConfigDedicated_t)); - /* memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.sps_Config, - (void *)rrc_inst->sps_Config[ue_mod_idP], - sizeof(SPS_Config_t)); - */ - LOG_I(RRC, "[eNB %d] Frame %d: adding new UE\n", - ctxt_pP->module_id, ctxt_pP->frame); - //Idx = (ue_mod_idP * NB_RB_MAX) + DCCH; - Idx = DCCH; - // SRB1 - ue_context_pP->ue_context.Srb1.Active = 1; - ue_context_pP->ue_context.Srb1.Srb_info.Srb_id = Idx; - memcpy(&ue_context_pP->ue_context.Srb1.Srb_info.Lchan_desc[0], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE); - memcpy(&ue_context_pP->ue_context.Srb1.Srb_info.Lchan_desc[1], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE); - // SRB2 - ue_context_pP->ue_context.Srb2.Active = 1; - ue_context_pP->ue_context.Srb2.Srb_info.Srb_id = Idx; - memcpy(&ue_context_pP->ue_context.Srb2.Srb_info.Lchan_desc[0], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE); - memcpy(&ue_context_pP->ue_context.Srb2.Srb_info.Lchan_desc[1], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE); - LOG_I(RRC, "[eNB %d] CALLING RLC CONFIG SRB1 (rbid %d) for UE %x\n", - ctxt_pP->module_id, Idx, ue_context_pP->ue_context.rnti); - // rrc_pdcp_config_req (enb_mod_idP, frameP, 1, CONFIG_ACTION_ADD, idx, UNDEF_SECURITY_MODE); - // rrc_rlc_config_req(enb_mod_idP,frameP,1,CONFIG_ACTION_ADD,Idx,SIGNALLING_RADIO_BEARER,Rlc_info_am_config); - rrc_pdcp_config_asn1_req(&ctxt, - ue_context_pP->ue_context.SRB_configList, - (LTE_DRB_ToAddModList_t *) NULL, (LTE_DRB_ToReleaseList_t *) NULL, 0xff, NULL, NULL, NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - , (LTE_PMCH_InfoList_r9_t *) NULL -#endif - ,NULL); - rrc_rlc_config_asn1_req(&ctxt, - ue_context_pP->ue_context.SRB_configList, - (LTE_DRB_ToAddModList_t *) NULL, (LTE_DRB_ToReleaseList_t *) NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - , (LTE_PMCH_InfoList_r9_t *) NULL - , 0, 0 -#endif - ); - /* Initialize NAS list */ - dedicatedInfoNASList = NULL; - // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; - memset(buffer, 0, RRC_BUF_SIZE); - int size=do_RRCConnectionReconfiguration( - ctxt_pP, - buffer, - rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id), //Transaction_id, - SRB_configList2, - DRB_configList2, - NULL, // DRB2_list, - NULL, //*sps_Config, - ue_context_pP->ue_context.physicalConfigDedicated, - MeasObj_list, - ReportConfig_list, - NULL, //quantityConfig, - MeasId_list, - mac_MainConfig, - NULL, - mobilityInfo, - Sparams, - NULL, - NULL, - dedicatedInfoNASList, - (LTE_SL_CommConfig_r12_t *)NULL, - (LTE_SL_DiscConfig_r12_t *)NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - , NULL // SCellToAddMod_r10_t -#endif - ); - - if (size <= 0) - LOG_E(RRC, - "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate LTE_RRCConnectionReconfiguration for handover (bytes %d, UE rnti %x) failed\n", - ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); - else - LOG_I(RRC, - "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate LTE_RRCConnectionReconfiguration for handover (bytes %d, UE rnti %x)\n", - ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); - - // to be updated if needed - /*if (RC.rrc[ctxt_pP->module_id]->SRB1_config[ue_mod_idP]->logicalChannelConfig) { - if (RC.rrc[ctxt_pP->module_id]->SRB1_config[ue_mod_idP]->logicalChannelConfig->present == LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) { - SRB1_logicalChannelConfig = &RC.rrc[ctxt_pP->module_id]->SRB1_config[ue_mod_idP]->logicalChannelConfig->choice.explicitValue; - } - else { - SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue; - } - } - else { - SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue; - } - */ - LOG_D(RRC, - "[FRAME %05d][RRC_eNB][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration_handover to UE %x MUI %d) --->][PDCP][MOD %02d][RB %02d]\n", - ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH); - //rrc_rlc_data_req(ctxt_pP->module_id,frameP, 1,(ue_mod_idP*NB_RB_MAX)+DCCH,rrc_eNB_mui++,0,size,(char*)buffer); - //pdcp_data_req (ctxt_pP->module_id, frameP, 1, (ue_mod_idP * NB_RB_MAX) + DCCH,rrc_eNB_mui++, 0, size, (char *) buffer, 1); - rrc_mac_config_req_eNB( - ctxt_pP->module_id, - ue_context_pP->ue_context.primaryCC_id, - 0,0,0,0,0, -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - 0, -#endif - ue_context_pP->ue_context.rnti, - (LTE_BCCH_BCH_Message_t *) NULL, - (LTE_RadioResourceConfigCommonSIB_t *) NULL, -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - (LTE_RadioResourceConfigCommonSIB_t *) NULL, -#endif - ue_context_pP->ue_context.physicalConfigDedicated, -#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - (LTE_SCellToAddMod_r10_t *)NULL, - //(struct LTE_PhysicalConfigDedicatedSCell_r10 *)NULL, -#endif - (LTE_MeasObjectToAddMod_t **) NULL, - ue_context_pP->ue_context.mac_MainConfig, - 1, - SRB1_logicalChannelConfig, - ue_context_pP->ue_context.measGapConfig, - (LTE_TDD_Config_t *) NULL, - (LTE_MobilityControlInfo_t *) mobilityInfo, - (LTE_SecurityConfigHO_t *)NULL, - (LTE_SchedulingInfoList_t *) NULL, 0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - , 0, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) NULL -#endif -#if (LTE_RRC_VERSION >= MAKE_VERSION(13, 0, 0)) - , - (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL -#endif - ); - /* - handoverCommand.criticalExtensions.present = HandoverCommand__criticalExtensions_PR_c1; - handoverCommand.criticalExtensions.choice.c1.present = HandoverCommand__criticalExtensions__c1_PR_handoverCommand_r8; - handoverCommand.criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage.buf = buffer; - handoverCommand.criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage.size = size; - */ - //#warning "COMPILATION PROBLEM" -#ifdef PROBLEM_COMPILATION_RESOLVED - - if (sourceModId != 0xFF) { - memcpy(RC.rrc[sourceModId].handover_info[RC.rrc[ctxt_pP->module_id]->handover_info[ue_mod_idP]->ueid_s]->buf, - (void *)buffer, size); - RC.rrc[sourceModId].handover_info[RC.rrc[ctxt_pP->module_id]->handover_info[ue_mod_idP]->ueid_s]->size = size; - RC.rrc[sourceModId].handover_info[RC.rrc[ctxt_pP->module_id]->handover_info[ue_mod_idP]->ueid_s]->ho_complete = - 0xF1; - //RC.rrc[ctxt_pP->module_id]->handover_info[ue_mod_idP]->ho_complete = 0xFF; - LOG_D(RRC, "[eNB %d] Frame %d: setting handover complete to 0xF1 for (%d,%d) and to 0xFF for (%d,%d)\n", - ctxt_pP->module_id, - ctxt_pP->frame, - sourceModId, - RC.rrc[ctxt_pP->module_id]->handover_info[ue_mod_idP]->ueid_s, - ctxt_pP->module_id, - ue_mod_idP); - } else - LOG_W(RRC, - "[eNB %d] Frame %d: rrc_eNB_generate_RRCConnectionReconfiguration_handover: Could not find source eNB mod_id.\n", - ctxt_pP->module_id, ctxt_pP->frame); - -#endif -} -#endif - - //----------------------------------------------------------------------------- /* * TODO: * add function description @@ -7579,13 +6818,9 @@ rrc_eNB_decode_dcch( } if (EPC_MODE_ENABLED) { - if (EPC_MODE_ENABLED == 1) { -#if defined(ENABLE_USE_MME) - rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP, - ue_context_p, - ul_dcch_msg); -#endif - } + rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP, + ue_context_p, + ul_dcch_msg); } else { ue_context_p->ue_context.nb_of_e_rabs = 1; @@ -7632,11 +6867,9 @@ rrc_eNB_decode_dcch( sdu_sizeP); if (EPC_MODE_ENABLED == 1) { -#if defined(ENABLE_USE_MME) rrc_eNB_send_S1AP_UPLINK_NAS(ctxt_pP, ue_context_p, ul_dcch_msg); -#endif } break; @@ -7784,8 +7017,18 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) double estimated_distance = 0; protocol_ctxt_t ctxt; #endif + MessageDef *msg; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX, VCD_FUNCTION_IN); - check_handovers(ctxt_pP); // counter, get the value and aggregate + + if (is_x2ap_enabled()) { + /* send a tick to x2ap */ + msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_SUBFRAME_PROCESS); + itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg); + + check_handovers(ctxt_pP); // counter, get the value and aggregate + } + // check for UL failure or for UE to be released RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) { ctxt_pP->rnti = ue_context_p->ue_id_rnti; @@ -7845,15 +7088,21 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) } } -#if defined(ENABLE_USE_MME) if (ue_context_p->ue_context.handover_info != NULL) { if (ue_context_p->ue_context.handover_info->state == HO_RELEASE) { ue_to_be_removed = ue_context_p; rrc_eNB_handover_ue_context_release(ctxt_pP, ue_context_p); break; //break RB_FOREACH (why to break ?) } + if (ue_context_p->ue_context.handover_info->state == HO_CANCEL) { + rrc_eNB_handover_cancel(ctxt_pP, ue_context_p); + /* freeing handover_info and setting it to NULL to let + * RRC wait for MME to later on release the UE + */ + free(ue_context_p->ue_context.handover_info); + ue_context_p->ue_context.handover_info = NULL; + } } -#endif pthread_mutex_lock(&rrc_release_freelist); @@ -8145,7 +7394,9 @@ void *rrc_enb_process_itti_msg(void *notUsed) { if (ue != NULL && ue->ue_context.ue_release_timer_rrc > 0 - && (ue->ue_context.handover_info == NULL || ue->ue_context.handover_info->state != HO_RELEASE)) { + && (ue->ue_context.handover_info == NULL || + (ue->ue_context.handover_info->state != HO_RELEASE && + ue->ue_context.handover_info->state != HO_CANCEL))) { ue->ue_context.ue_release_timer_rrc = ue->ue_context.ue_release_timer_thres_rrc; } @@ -8193,6 +7444,51 @@ void *rrc_enb_process_itti_msg(void *notUsed) { break; } + case X2AP_HANDOVER_CANCEL: { + struct rrc_eNB_ue_context_s *ue_context_p = NULL; + char *cause; + switch (X2AP_HANDOVER_CANCEL(msg_p).cause) { + case X2AP_T_RELOC_PREP_TIMEOUT: + cause = "T_RelocPrep timeout"; + break; + case X2AP_TX2_RELOC_OVERALL_TIMEOUT: + cause = "Tx2_RelocOverall timeout"; + break; + default: + /* cannot come here */ + exit(1); + } + ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], X2AP_HANDOVER_CANCEL(msg_p).rnti); + if (ue_context_p != NULL && + ue_context_p->ue_context.handover_info != NULL) { + LOG_I(RRC, "[eNB %d] eNB receives X2 HANDOVER CANCEL for rnti %x, cause %s [%s]\n", + instance, + X2AP_HANDOVER_CANCEL(msg_p).rnti, + cause, + msg_name_p); + if (X2AP_HANDOVER_CANCEL(msg_p).cause == X2AP_T_RELOC_PREP_TIMEOUT) { + /* for prep timeout, simply return to normal state */ + /* TODO: be sure that it's correct to set Status to RRC_RECONFIGURED */ + ue_context_p->ue_context.Status = RRC_RECONFIGURED; + /* TODO: be sure free is enough here (check memory leaks) */ + free(ue_context_p->ue_context.handover_info); + ue_context_p->ue_context.handover_info = NULL; + } else { + /* for overall timeout, remove UE entirely */ + ue_context_p->ue_context.handover_info->state = HO_CANCEL; + } + } else { + char *failure_cause; + if (ue_context_p == NULL) + failure_cause = "no UE found"; + else + failure_cause = "UE not in handover"; + LOG_W(RRC, "[eNB %d] cannot process (%s) X2 HANDOVER CANCEL for rnti %x, cause %s, ignoring\n", + instance, failure_cause, X2AP_HANDOVER_CANCEL(msg_p).rnti, cause); + } + break; + } + /* Messages from eNB app */ case RRC_CONFIGURATION_REQ: LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p,&RRC_CONFIGURATION_REQ(msg_p)); diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index c05495a0c4..8b11e469b2 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -41,6 +41,7 @@ #include "x2ap_eNB_generate_messages.h" #include "x2ap_common.h" #include "x2ap_ids.h" +#include "x2ap_timers.h" #include "queue.h" #include "assertions.h" @@ -301,6 +302,9 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, new_instance->num_cc = x2ap_register_eNB->num_cc; x2ap_id_manager_init(&new_instance->id_manager); + x2ap_timers_init(&new_instance->timers, + x2ap_register_eNB->t_reloc_prep, + x2ap_register_eNB->tx2_reloc_overall); for (int i = 0; i< x2ap_register_eNB->num_cc; i++) { new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i]; @@ -402,6 +406,10 @@ void x2ap_eNB_handle_handover_req(instance_t instance, } /* id_source is ue_id, id_target is unknown yet */ x2ap_set_ids(id_manager, ue_id, x2ap_handover_req->rnti, ue_id, -1); + x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_SOURCE_PREPARE); + x2ap_set_reloc_prep_timer(id_manager, ue_id, + x2ap_timer_get_tti(&instance_p->timers)); + x2ap_id_set_target(id_manager, ue_id, target); x2ap_eNB_generate_x2_handover_request(instance_p, target, x2ap_handover_req, ue_id); } @@ -480,6 +488,10 @@ void *x2ap_task(void *arg) { itti_exit_task(); break; + case X2AP_SUBFRAME_PROCESS: + x2ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg)); + break; + case X2AP_REGISTER_ENB_REQ: x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), &X2AP_REGISTER_ENB_REQ(received_msg)); @@ -534,4 +546,38 @@ void *x2ap_task(void *arg) { return NULL; } +#include "common/config/config_userapi.h" +int is_x2ap_enabled(void) +{ + static volatile int config_loaded = 0; + static volatile int enabled = 0; + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + + if (pthread_mutex_lock(&mutex)) goto mutex_error; + + if (config_loaded) { + if (pthread_mutex_unlock(&mutex)) goto mutex_error; + return enabled; + } + + char *enable_x2 = NULL; + paramdef_t p[] = { + { "enable_x2", "yes/no", 0, strptr:&enable_x2, defstrval:"", TYPE_STRING, 0 } + }; + + /* TODO: do it per module - we check only first eNB */ + config_get(p, sizeof(p)/sizeof(paramdef_t), "eNBs.[0]"); + if (enable_x2 != NULL && strcmp(enable_x2, "yes") == 0) + enabled = 1; + + config_loaded = 1; + + if (pthread_mutex_unlock(&mutex)) goto mutex_error; + + return enabled; + +mutex_error: + LOG_E(X2AP, "mutex error\n"); + exit(1); +} diff --git a/openair2/X2AP/x2ap_eNB.h b/openair2/X2AP/x2ap_eNB.h index 5433a89088..afa6f11b8e 100644 --- a/openair2/X2AP/x2ap_eNB.h +++ b/openair2/X2AP/x2ap_eNB.h @@ -46,6 +46,8 @@ int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p, void *x2ap_task(void *arg); +int is_x2ap_enabled(void); + #endif /* X2AP_H_ */ /** diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c index a5b19fe2cc..3604aa03c8 100644 --- a/openair2/X2AP/x2ap_eNB_decoder.c +++ b/openair2/X2AP/x2ap_eNB_decoder.c @@ -48,11 +48,17 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu) //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu); X2AP_INFO("x2ap_eNB_decode_initiating_message!\n"); break; + case X2AP_ProcedureCode_id_uEContextRelease: //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu); X2AP_INFO("x2ap_eNB_decode_initiating_message!\n"); break; + case X2AP_ProcedureCode_id_handoverCancel: + //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu); + X2AP_INFO("x2ap_eNB_decode_initiating_message!\n"); + break; + default: X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage.procedureCode); diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h index 3356a101b4..cd6a7e1385 100644 --- a/openair2/X2AP/x2ap_eNB_defs.h +++ b/openair2/X2AP/x2ap_eNB_defs.h @@ -34,6 +34,7 @@ #include "sctp_eNB_defs.h" #include "x2ap_ids.h" +#include "x2ap_timers.h" #ifndef X2AP_ENB_DEFS_H_ #define X2AP_ENB_DEFS_H_ @@ -63,7 +64,6 @@ typedef enum { X2AP_ENB_STATE_MAX, } x2ap_eNB_state_t; - /* Served PLMN identity element */ struct plmn_identity_s { uint16_t mcc; @@ -184,6 +184,7 @@ typedef struct x2ap_eNB_instance_s { int multi_sd; x2ap_id_manager id_manager; + x2ap_timers_t timers; } x2ap_eNB_instance_t; typedef struct { diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c index c13469d5d4..53ec8574fd 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.c +++ b/openair2/X2AP/x2ap_eNB_generate_messages.c @@ -718,3 +718,87 @@ int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_instance_t *instance_p, x2 return ret; } + +int x2ap_eNB_generate_x2_handover_cancel (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int x2_ue_id, + x2ap_handover_cancel_cause_t cause) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_HandoverCancel_t *out; + X2AP_HandoverCancel_IEs_t *ie; + int ue_id; + int id_source; + int id_target; + + uint8_t *buffer; + uint32_t len; + int ret = 0; + + DevAssert(instance_p != NULL); + DevAssert(x2ap_eNB_data_p != NULL); + + ue_id = x2_ue_id; + id_source = ue_id; + id_target = x2ap_id_get_id_target(&instance_p->id_manager, ue_id); + + /* Prepare the X2AP handover cancel message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_handoverCancel; + pdu.choice.initiatingMessage.criticality = X2AP_Criticality_ignore; + pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_HandoverCancel; + out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel; + + /* mandatory */ + ie = (X2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(X2AP_HandoverCancel_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_HandoverCancel_IEs__value_PR_UE_X2AP_ID; + ie->value.choice.UE_X2AP_ID = id_source; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (id_target != -1) { + ie = (X2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(X2AP_HandoverCancel_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID; + ie->criticality = X2AP_Criticality_ignore; + ie->value.present = X2AP_HandoverCancel_IEs__value_PR_UE_X2AP_ID_1; + ie->value.choice.UE_X2AP_ID_1 = id_target; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* mandatory */ + ie = (X2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(X2AP_HandoverCancel_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_Cause; + ie->criticality = X2AP_Criticality_ignore; + ie->value.present = X2AP_HandoverCancel_IEs__value_PR_Cause; + switch (cause) { + case X2AP_T_RELOC_PREP_TIMEOUT: + ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork; + ie->value.choice.Cause.choice.radioNetwork = + X2AP_CauseRadioNetwork_trelocprep_expiry; + break; + case X2AP_TX2_RELOC_OVERALL_TIMEOUT: + ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork; + ie->value.choice.Cause.choice.radioNetwork = + X2AP_CauseRadioNetwork_tx2relocoverall_expiry; + break; + default: + /* we can't come here */ + X2AP_ERROR("unhandled cancel cause\n"); + exit(1); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode X2 Handover Cancel\n"); + abort(); + return -1; + } + + MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id); + + x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1); + + return ret; +} diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.h b/openair2/X2AP/x2ap_eNB_generate_messages.h index 059d213277..659966fff6 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.h +++ b/openair2/X2AP/x2ap_eNB_generate_messages.h @@ -55,5 +55,10 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_instance_t *instance_p, int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, x2ap_ue_context_release_t *x2ap_ue_context_release); + +int x2ap_eNB_generate_x2_handover_cancel (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int x2_ue_id, + x2ap_handover_cancel_cause_t cause); + #endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */ diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index 9da9278741..96ffac162e 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -78,10 +78,16 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, uint32_t stream, X2AP_X2AP_PDU_t *pdu); +static +int x2ap_eNB_handle_handover_cancel (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + /* Handlers matrix. Only eNB related procedure present here */ x2ap_message_decoded_callback x2ap_messages_callback[][3] = { { x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */ - { 0, 0, 0 }, /* handoverCancel */ + { x2ap_eNB_handle_handover_cancel, 0, 0 }, /* handoverCancel */ { 0, 0, 0 }, /* loadIndication */ { 0, 0, 0 }, /* errorIndication */ { 0, 0, 0 }, /* snStatusTransfer */ @@ -631,6 +637,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, } /* rnti is unknown yet, must not be set to -1, 0 is fine */ x2ap_set_ids(&instance_p->id_manager, ue_id, 0, ie->value.choice.UE_X2AP_ID, ue_id); + x2ap_id_set_state(&instance_p->id_manager, ue_id, X2ID_STATE_TARGET); X2AP_HANDOVER_REQ(msg).x2_id = ue_id; @@ -775,15 +782,19 @@ int x2ap_eNB_handle_handover_response (instance_t instance, ue_id = id_source; - if (id_source != x2ap_id_get_id_source(&instance_p->id_manager, ue_id)) { - X2AP_ERROR("incorrect X2AP IDs for UE (old ID %d new ID %d)\n", id_source, id_target); - exit(1); + if (ue_id != x2ap_find_id_from_id_source(&instance_p->id_manager, id_source)) { + X2AP_WARN("incorrect/unknown X2AP IDs for UE (old ID %d new ID %d), ignoring handover response\n", + id_source, id_target); + return 0; } rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id); /* id_target is a new information, store it */ x2ap_set_ids(&instance_p->id_manager, ue_id, rnti, id_source, id_target); + x2ap_id_set_state(&instance_p->id_manager, ue_id, X2ID_STATE_SOURCE_OVERALL); + x2ap_set_reloc_overall_timer(&instance_p->id_manager, ue_id, + x2ap_timer_get_tti(&instance_p->timers)); X2AP_HANDOVER_REQ_ACK(msg).rnti = rnti; @@ -859,13 +870,19 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, id_target = ie->value.choice.UE_X2AP_ID_1; ue_id = id_source; + if (ue_id != x2ap_find_id_from_id_source(&instance_p->id_manager, id_source)) { + X2AP_WARN("incorrect/unknown X2AP IDs for UE (old ID %d new ID %d), ignoring UE context release\n", + id_source, id_target); + return 0; + } if (id_target != x2ap_id_get_id_target(&instance_p->id_manager, ue_id)) { - X2AP_ERROR("UE context release: bad id_target for UE %x (id_source %d) expected %d got %d\n", + X2AP_ERROR("UE context release: bad id_target for UE %x (id_source %d) expected %d got %d, ignoring message\n", x2ap_id_get_rnti(&instance_p->id_manager, ue_id), id_source, x2ap_id_get_id_target(&instance_p->id_manager, ue_id), id_target); + return 0; } X2AP_UE_CONTEXT_RELEASE(msg).rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id); @@ -876,3 +893,111 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, return 0; } + +static +int x2ap_eNB_handle_handover_cancel (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + X2AP_HandoverCancel_t *x2HandoverCancel; + X2AP_HandoverCancel_IEs_t *ie; + + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; + int ue_id; + int id_source; + int id_target; + x2ap_handover_cancel_cause_t cause; + + DevAssert (pdu != NULL); + x2HandoverCancel = &pdu->choice.initiatingMessage.value.choice.HandoverCancel; + + if (stream == 0) { + X2AP_ERROR ("Received new x2 handover cancel on stream == 0\n"); + return 0; + } + + X2AP_DEBUG ("Received a new X2 handover cancel\n"); + + x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); + DevAssert(x2ap_eNB_data != NULL); + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverCancel_IEs_t, ie, x2HandoverCancel, + X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true); + + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + id_source = ie->value.choice.UE_X2AP_ID; + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverCancel_IEs_t, ie, x2HandoverCancel, + X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID, false); + + if (ie == NULL ) { + X2AP_INFO("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + id_target = -1; + } else + id_target = ie->value.choice.UE_X2AP_ID_1; + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverCancel_IEs_t, ie, x2HandoverCancel, + X2AP_ProtocolIE_ID_id_Cause, true); + + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + if (ie->value.present != X2AP_HandoverCancel_IEs__value_PR_Cause || + ie->value.choice.Cause.present != X2AP_Cause_PR_radioNetwork || + !(ie->value.choice.Cause.choice.radioNetwork == + X2AP_CauseRadioNetwork_trelocprep_expiry || + ie->value.choice.Cause.choice.radioNetwork == + X2AP_CauseRadioNetwork_tx2relocoverall_expiry)) { + X2AP_ERROR("%s %d: Cause not supported (only T_reloc_prep and TX2_reloc_overall handled)\n",__FILE__,__LINE__); + return -1; + } + + switch (ie->value.choice.Cause.choice.radioNetwork) { + case X2AP_CauseRadioNetwork_trelocprep_expiry: + cause = X2AP_T_RELOC_PREP_TIMEOUT; + break; + case X2AP_CauseRadioNetwork_tx2relocoverall_expiry: + cause = X2AP_TX2_RELOC_OVERALL_TIMEOUT; + break; + default: /* can't come here */ exit(1); + } + + ue_id = x2ap_find_id_from_id_source(&instance_p->id_manager, id_source); + if (ue_id == -1) { + X2AP_WARN("Handover cancel: UE not found (id_source = %d), ignoring message\n", id_source); + return 0; + } + + if (id_target != -1 && + id_target != x2ap_id_get_id_target(&instance_p->id_manager, ue_id)) { + X2AP_ERROR("Handover cancel: bad id_target for UE %x (id_source %d) expected %d got %d\n", + x2ap_id_get_rnti(&instance_p->id_manager, ue_id), + id_source, + x2ap_id_get_id_target(&instance_p->id_manager, ue_id), + id_target); + exit(1); + } + + msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_CANCEL); + + X2AP_HANDOVER_CANCEL(msg).rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id); + X2AP_HANDOVER_CANCEL(msg).cause = cause; + + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + + x2ap_release_id(&instance_p->id_manager, ue_id); + + return 0; +} diff --git a/openair2/X2AP/x2ap_ids.c b/openair2/X2AP/x2ap_ids.c index b5607821fe..02f1bbfc0e 100644 --- a/openair2/X2AP/x2ap_ids.c +++ b/openair2/X2AP/x2ap_ids.c @@ -60,6 +60,16 @@ int x2ap_find_id(x2ap_id_manager *m, int id_source, int id_target) return -1; } +int x2ap_find_id_from_id_source(x2ap_id_manager *m, int id_source) +{ + int i; + for (i = 0; i < X2AP_MAX_IDS; i++) + if (m->ids[i].rnti != -1 && + m->ids[i].id_source == id_source) + return i; + return -1; +} + int x2ap_find_id_from_rnti(x2ap_id_manager *m, int rnti) { int i; @@ -76,6 +86,27 @@ void x2ap_set_ids(x2ap_id_manager *m, int ue_id, int rnti, int id_source, int id m->ids[ue_id].id_target = id_target; } +/* real type of target is x2ap_eNB_data_t * */ +void x2ap_id_set_target(x2ap_id_manager *m, int ue_id, void *target) +{ + m->ids[ue_id].target = target; +} + +void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state) +{ + m->ids[ue_id].state = state; +} + +void x2ap_set_reloc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time) +{ + m->ids[ue_id].t_reloc_prep_start = time; +} + +void x2ap_set_reloc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time) +{ + m->ids[ue_id].tx2_reloc_overall_start = time; +} + int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id) { return m->ids[ue_id].id_source; @@ -90,3 +121,8 @@ int x2ap_id_get_rnti(x2ap_id_manager *m, int ue_id) { return m->ids[ue_id].rnti; } + +void *x2ap_id_get_target(x2ap_id_manager *m, int ue_id) +{ + return m->ids[ue_id].target; +} diff --git a/openair2/X2AP/x2ap_ids.h b/openair2/X2AP/x2ap_ids.h index 2232308f73..3d2799e8c4 100644 --- a/openair2/X2AP/x2ap_ids.h +++ b/openair2/X2AP/x2ap_ids.h @@ -22,12 +22,38 @@ #ifndef X2AP_IDS_H_ #define X2AP_IDS_H_ +#include + +/* maximum number of simultaneous handovers, do not set too high */ #define X2AP_MAX_IDS 16 +/* + * state: + * - when starting handover in source, UE is in state X2ID_STATE_SOURCE_PREPARE + * - after receiving HO_ack in source, UE is in state X2ID_STATE_SOURCE_OVERALL + * - in target, UE is in state X2ID_STATE_TARGET + * The state is used to check timers. + */ +typedef enum { + X2ID_STATE_SOURCE_PREPARE, + X2ID_STATE_SOURCE_OVERALL, + X2ID_STATE_TARGET +} x2id_state_t; + typedef struct { - int rnti; /* -1 when free */ - int id_source; - int id_target; + int rnti; /* -1 when free */ + int id_source; + int id_target; + + /* the target eNB. Real type is x2ap_eNB_data_t * */ + void *target; + + /* state: needed to check timers */ + x2id_state_t state; + + /* timers */ + uint64_t t_reloc_prep_start; + uint64_t tx2_reloc_overall_start; } x2ap_id; typedef struct { @@ -38,10 +64,17 @@ void x2ap_id_manager_init(x2ap_id_manager *m); int x2ap_allocate_new_id(x2ap_id_manager *m); void x2ap_release_id(x2ap_id_manager *m, int id); int x2ap_find_id(x2ap_id_manager *, int id_source, int id_target); +int x2ap_find_id_from_id_source(x2ap_id_manager *, int id_source); int x2ap_find_id_from_rnti(x2ap_id_manager *, int rnti); void x2ap_set_ids(x2ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target); +void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state); +/* real type of target is x2ap_eNB_data_t * */ +void x2ap_id_set_target(x2ap_id_manager *m, int ue_id, void *target); +void x2ap_set_reloc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time); +void x2ap_set_reloc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time); int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id); int x2ap_id_get_id_target(x2ap_id_manager *m, int ue_id); int x2ap_id_get_rnti(x2ap_id_manager *m, int ue_id); +void *x2ap_id_get_target(x2ap_id_manager *m, int ue_id); #endif /* X2AP_IDS_H_ */ diff --git a/openair2/X2AP/x2ap_timers.c b/openair2/X2AP/x2ap_timers.c new file mode 100644 index 0000000000..a0a7b61ad7 --- /dev/null +++ b/openair2/X2AP/x2ap_timers.c @@ -0,0 +1,105 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "x2ap_timers.h" +#include "assertions.h" +#include "PHY/defs_common.h" /* TODO: try to not include this */ +#include "x2ap_messages_types.h" +#include "x2ap_eNB_defs.h" +#include "x2ap_ids.h" +#include "x2ap_eNB_management_procedures.h" +#include "x2ap_eNB_generate_messages.h" + +void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall) +{ + t->tti = 0; + t->t_reloc_prep = t_reloc_prep; + t->tx2_reloc_overall = tx2_reloc_overall; +} + +void x2ap_check_timers(instance_t instance) +{ + x2ap_eNB_instance_t *instance_p; + x2ap_timers_t *t; + x2ap_id_manager *m; + int i; + x2ap_handover_cancel_cause_t cause; + void *target; + MessageDef *msg; + int x2_ongoing; + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + + t = &instance_p->timers; + m = &instance_p->id_manager; + + /* increment subframe count */ + t->tti++; + + x2_ongoing = 0; + + for (i = 0; i < X2AP_MAX_IDS; i++) { + if (m->ids[i].rnti == -1) continue; + x2_ongoing++; + + if (m->ids[i].state == X2ID_STATE_SOURCE_PREPARE && + t->tti > m->ids[i].t_reloc_prep_start + t->t_reloc_prep) { + LOG_I(X2AP, "X2 timeout reloc prep\n"); + /* t_reloc_prep timed out */ + cause = X2AP_T_RELOC_PREP_TIMEOUT; + goto timeout; + } + + if (m->ids[i].state == X2ID_STATE_SOURCE_OVERALL && + t->tti > m->ids[i].tx2_reloc_overall_start + t->tx2_reloc_overall) { + LOG_I(X2AP, "X2 timeout reloc overall\n"); + /* tx2_reloc_overall timed out */ + cause = X2AP_TX2_RELOC_OVERALL_TIMEOUT; + goto timeout; + } + + /* no timeout -> check next UE */ + continue; + +timeout: + /* inform target about timeout */ + target = x2ap_id_get_target(m, i); + x2ap_eNB_generate_x2_handover_cancel(instance_p, target, i, cause); + + /* inform RRC of cancellation */ + msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_CANCEL); + X2AP_HANDOVER_CANCEL(msg).rnti = x2ap_id_get_rnti(m, i); + X2AP_HANDOVER_CANCEL(msg).cause = cause; + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + + /* remove UE from X2AP */ + x2ap_release_id(m, i); + } + + if (x2_ongoing && t->tti % 1000 == 0) + LOG_I(X2AP, "X2 has %d process ongoing\n", x2_ongoing); +} + +uint64_t x2ap_timer_get_tti(x2ap_timers_t *t) +{ + return t->tti; +} diff --git a/openair2/X2AP/x2ap_timers.h b/openair2/X2AP/x2ap_timers.h new file mode 100644 index 0000000000..d4579422d5 --- /dev/null +++ b/openair2/X2AP/x2ap_timers.h @@ -0,0 +1,45 @@ +/* + * 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 X2AP_TIMERS_H_ +#define X2AP_TIMERS_H_ + +#include +#include "platform_types.h" + +typedef struct { + /* incremented every TTI (every millisecond when in realtime). + * Used to check timers. + * 64 bits gives us more than 500 million years of (realtime) processing. + * It should be enough. + */ + uint64_t tti; + + /* timer values (unit: TTI, ie. millisecond when in realtime) */ + int t_reloc_prep; + int tx2_reloc_overall; +} x2ap_timers_t; + +void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall); +void x2ap_check_timers(instance_t instance); +uint64_t x2ap_timer_get_tti(x2ap_timers_t *t); + +#endif /* X2AP_TIMERS_H_ */ diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c index 4fc2551e15..d2dd90b2b4 100644 --- a/targets/COMMON/create_tasks.c +++ b/targets/COMMON/create_tasks.c @@ -53,10 +53,13 @@ int create_tasks(uint32_t enb_nb) { if (EPC_MODE_ENABLED) { if (enb_nb > 0) { - if (itti_create_task (TASK_X2AP, x2ap_task, NULL) < 0) { - LOG_E(X2AP, "Create task for X2AP failed\n"); - return -1; - } + if (is_x2ap_enabled()) { + if (itti_create_task (TASK_X2AP, x2ap_task, NULL) < 0) { + LOG_E(X2AP, "Create task for X2AP failed\n"); + return -1; + } + } else + LOG_I(X2AP, "X2AP is disabled.\n"); if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) { LOG_E(SCTP, "Create task for SCTP failed\n"); diff --git a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.calisson.conf b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.calisson.conf index 86131b3e8e..df60ee7fa8 100644 --- a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.calisson.conf +++ b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.calisson.conf @@ -37,6 +37,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.memphis.conf b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.memphis.conf index e87a37f9fb..f5dce0a178 100644 --- a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.memphis.conf +++ b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.memphis.conf @@ -49,6 +49,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.nord.conf b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.nord.conf index af4f4236a7..d75837ff97 100644 --- a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.nord.conf +++ b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.nord.conf @@ -36,6 +36,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.emtc.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.emtc.conf index a69daff48e..81946ddf7a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.emtc.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.emtc.conf @@ -360,6 +360,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.100PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.100PRB.usrpx310.conf index 8c080b7d10..60142d8fe6 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.100PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.100PRB.usrpx310.conf @@ -142,6 +142,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.25PRB.iris030.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.25PRB.iris030.conf index 77993457ab..372c853b29 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.25PRB.iris030.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.25PRB.iris030.conf @@ -178,6 +178,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eno1"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpx310.conf index 83954a00d5..993acae34e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpx310.conf @@ -142,6 +142,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band42.tm1.25PRB.iris030.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band42.tm1.25PRB.iris030.conf index 764d7886e2..c55c58e1a7 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band42.tm1.25PRB.iris030.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band42.tm1.25PRB.iris030.conf @@ -178,6 +178,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eno1"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf index 728492ee83..ac417c7e3a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf @@ -145,6 +145,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.iris030.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.iris030.conf index ca85c6538f..5882c1b168 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.iris030.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.iris030.conf @@ -178,6 +178,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.replay.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.replay.conf index 823c5fb1c3..a683326639 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.replay.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.replay.conf @@ -179,6 +179,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf index 476d4903f1..5e750cb626 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf @@ -179,6 +179,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index 83834bfeca..142b962598 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -179,6 +179,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf index 403e5f24f5..497db9a306 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf @@ -146,6 +146,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf index 7eb16a3b7a..ae2ba73782 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf @@ -148,6 +148,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf index 47047e5626..f7be9e28d9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf @@ -148,6 +148,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "vboxnet0"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf index 472d84c7e2..9d71b10740 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf @@ -179,6 +179,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { #ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.conf index d989ac8b10..ec20ac3abf 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.conf @@ -148,6 +148,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf index 79bd48cd0c..5e5b191a0f 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf @@ -147,6 +147,11 @@ eNBs = } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; From 1fa9c322fbb63d39a96e245edf1b048cfbde83da Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 14 Mar 2019 14:58:30 +0100 Subject: [PATCH 2/3] x2: update feature set --- doc/FEATURE_SET.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 29163fd832..4f2ec177ad 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -127,6 +127,8 @@ The X2AP layer is based on **3GPP 36.423** v14.6.0 and implements the following - X2 Setup Failure - Handover Request - Handover Request Acknowledge + - X2 timers (t_reloc_prep, tx2_reloc_overall) + - Handover Cancel ## eNB Advanced Features ## From 0a459545cbb02dcb786e7fed2d425256510b8990 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Thu, 14 Mar 2019 15:49:47 +0100 Subject: [PATCH 3/3] Update FEATURE_SET.md --- doc/FEATURE_SET.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 4f2ec177ad..3dd3605fb3 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -127,6 +127,7 @@ The X2AP layer is based on **3GPP 36.423** v14.6.0 and implements the following - X2 Setup Failure - Handover Request - Handover Request Acknowledge + - UE Context Release - X2 timers (t_reloc_prep, tx2_reloc_overall) - Handover Cancel