From 4236ff2b3ecdaa05a7d084fe0f79e58233a6e916 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Tue, 22 Sep 2020 11:57:31 +0200
Subject: [PATCH] nr: improve x2/rrc for ENDC

This commit introduces several enhancements in X2AP and RRC to deal
with ENDC. The main goal is to deal with UE's on/off and with various
errors.

The following work is included:

    - DC prep and DC overall X2 timers
    - X2 messages for UE release and DC timers' timeout

Open problems:

    - what to do when the UE sends an scg Failure? This commit removes
      the UE. And this removal may not be correctly done
    - UE removal in the gNB's PHY layer (a next commit is coming,
      but it is hackish and will need a rework)
---
 .../enb.band13.tm1.25PRB.usrpb210.conf        |   2 +
 .../conf_files/enb.band13.tm1.50PRB.emtc.conf |   2 +
 .../enb.band17.tm1.25PRB.usrpb210.conf        |   2 +
 .../enb.band17.tm1.mbms.25PRB.usrpb210.conf   |   2 +
 ...d40.tm1.100PRB.FairScheduler.usrpb210.conf |   2 +
 ...nd40.tm1.25PRB.FairScheduler.usrpb210.conf |   2 +
 ...nd40.tm1.50PRB.FairScheduler.usrpb210.conf |   2 +
 ...nd40.tm2.25PRB.FairScheduler.usrpb210.conf |   2 +
 .../enb.band7.tm1.100PRB.usrpb210.conf        |   2 +
 .../enb.band7.tm1.25PRB.slave.usrpb210.conf   |   2 +
 .../enb.band7.tm1.25PRB.usrpb210.conf         |   2 +
 .../enb.band7.tm1.50PRB.usrpb210.conf         |   2 +
 .../enb.band7.tm1.fr1.25PRB.usrpb210.conf     |   2 +
 .../enb.band7.tm2.25PRB.usrpb210.conf         |   2 +
 .../enb.slave.band13.tm1.25PRB.usrpb210.conf  |   2 +
 .../gnb.band78.tm1.fr1.106PRB.usrpb210.conf   |   2 +
 ci-scripts/conf_files/lte-fdd-basic-sim.conf  |   2 +
 .../conf_files/lte-fdd-fembms-basic-sim.conf  |   2 +
 .../conf_files/lte-fdd-mbms-basic-sim.conf    |   2 +
 ci-scripts/conf_files/lte-tdd-basic-sim.conf  |   2 +
 ...d40.tm1.100PRB.FairScheduler.usrpb210.conf |   2 +
 ...nd40.tm1.25PRB.FairScheduler.usrpb210.conf |   2 +
 ...nd40.tm1.50PRB.FairScheduler.usrpb210.conf |   2 +
 ...cc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf |   2 +
 ...rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf |   2 +
 ...rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf |   2 +
 ...cc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf |   2 +
 .../rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf    |   2 +
 .../conf_files/rcc.band7.tm1.nfapi.conf       |   2 +
 .../enb.band38.tm1.usrpb210.tdd.10MHz.conf    |   2 +
 .../enb.band38.tm1.usrpb210.tdd.20MHz.conf    |   2 +
 .../enb.band38.tm1.usrpb210.tdd.5MHz.conf     |   2 +
 .../enb.band7.tm1.usrpb210.fdd.10MHz.conf     |   2 +
 .../enb.band7.tm1.usrpb210.fdd.20MHz.conf     |   2 +
 .../enb.band7.tm1.usrpb210.fdd.5MHz.conf      |   2 +
 .../v2/config/rcc.band7.tm1.if4p5.10MHz.conf  |   2 +
 .../v2/config/rcc.band7.tm1.if4p5.20MHz.conf  |   2 +
 .../v2/config/rcc.band7.tm1.if4p5.5MHz.conf   |   2 +
 ...ru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf |   2 +
 ...ru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf |   2 +
 ...rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf |   2 +
 configuration/bladeRF/enb-band7-5mhz.conf     |   2 +
 doc/testing_gnb_w_cots_ue_resources/enb.conf  |   2 +
 doc/testing_gnb_w_cots_ue_resources/gnb.conf  |   2 +
 executables/nr-gnb.c                          |   1 -
 openair2/COMMON/gtpv1_u_messages_types.h      |   2 +
 openair2/COMMON/x2ap_messages_def.h           |  18 +-
 openair2/COMMON/x2ap_messages_types.h         |  62 +++-
 openair2/ENB_APP/enb_config.c                 |  14 +-
 openair2/GNB_APP/gnb_config.c                 |  14 +-
 openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c    |   4 +-
 .../NR_MAC_gNB/gNB_scheduler_primitives.c     |  31 +-
 openair2/LAYER2/NR_MAC_gNB/mac_proto.h        |   2 +
 openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c     |  11 +-
 openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c    |   2 +-
 openair2/RRC/LTE/rrc_defs.h                   |   5 +-
 openair2/RRC/LTE/rrc_eNB.c                    | 118 ++++++
 openair2/RRC/LTE/rrc_eNB_GTPV1U.c             |   1 +
 openair2/RRC/LTE/rrc_eNB_S1AP.c               |   1 +
 openair2/RRC/LTE/rrc_eNB_UE_context.c         |  17 +
 openair2/RRC/LTE/rrc_eNB_UE_context.h         |   5 +
 openair2/RRC/NR/nr_rrc_proto.h                |   4 +
 openair2/RRC/NR/rrc_gNB.c                     |  51 ++-
 openair2/RRC/NR/rrc_gNB_nsa.c                 |  68 +++-
 openair2/X2AP/x2ap_eNB.c                      | 102 +++--
 openair2/X2AP/x2ap_eNB_decoder.c              |  12 +
 openair2/X2AP/x2ap_eNB_generate_messages.c    | 231 +++++++++++-
 openair2/X2AP/x2ap_eNB_generate_messages.h    |  12 +
 openair2/X2AP/x2ap_eNB_handler.c              | 348 +++++++++++++++---
 openair2/X2AP/x2ap_ids.c                      |  20 +
 openair2/X2AP/x2ap_ids.h                      |   8 +-
 openair2/X2AP/x2ap_timers.c                   |  68 +++-
 openair2/X2AP/x2ap_timers.h                   |   8 +-
 openair3/GTPV1-U/gtpv1u_eNB.c                 |   5 +-
 .../CONF/enb.centos.calisson.conf             |   2 +
 .../CONF/enb.centos.memphis.conf              |   2 +
 .../CONF/enb.centos.nord.conf                 |   2 +
 .../GENERIC-LTE-EPC/CONF/benetel-4g.conf      |   2 +
 .../GENERIC-LTE-EPC/CONF/benetel-5g.conf      |   2 +
 .../CONF/enb.band13.tm1.50PRB.emtc.conf       |   2 +
 .../CONF/enb.band38.tm1.100PRB.usrpx310.conf  |   2 +
 .../CONF/enb.band38.tm1.25PRB.iris030.conf    |   2 +
 .../CONF/enb.band38.tm1.usrpx310.conf         |   2 +
 .../CONF/enb.band42.tm1.25PRB.iris030.conf    |   2 +
 .../CONF/enb.band7.master.conf                |   2 +
 .../CONF/enb.band7.tm1.100PRB.usrpx310.conf   |   2 +
 .../CONF/enb.band7.tm1.25PRB.iris030.conf     |   2 +
 .../enb.band7.tm1.25PRB.usrpb210.replay.conf  |   2 +
 .../enb.band7.tm1.50PRB.usrpb210-d2d.conf     |   2 +
 .../CONF/enb.band7.tm1.50PRB.usrpb210.conf    |   2 +
 ...band7.tm1.50PRB.usrpb210_ue_expansion.conf |   2 +
 .../gnb.band78.106PRB.30kHz,usrpb2x0.conf     |   2 +
 .../CONF/gnb.band78.106PRB.slave.conf         |   2 +
 .../CONF/gnb.band78.slave.conf                |   2 +
 .../CONF/gnb.band78.tm1.217PRB.usrpn300.conf  |   2 +
 .../CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf   |   2 +
 .../CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf  |   2 +
 .../CONF/rcc.band7.tm1.50PRB.nfapi.conf       |   2 +
 .../CONF/rcc.band7.tm1.if4p5.50PRB.conf       |   2 +
 .../CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf    |   2 +
 .../GENERIC-LTE-EPC/CONF/testing_enb.conf     |   2 +
 .../GENERIC-LTE-EPC/CONF/testing_gnb.conf     |   2 +
 .../CONF/testing_gnb_n310.conf                |   2 +
 103 files changed, 1233 insertions(+), 158 deletions(-)

diff --git a/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf
index 2a7783da08b..49926c3e603 100644
--- a/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf
@@ -184,6 +184,8 @@ eNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 ab89d13193b..673c506dfa5 100644
--- a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf
+++ b/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf
@@ -367,6 +367,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf
index d834b23e30a..cf508a1e951 100644
--- a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf
@@ -188,6 +188,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf
index a9ccb9f7839..d26ab5d1b4f 100644
--- a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf
@@ -189,6 +189,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     ///M2
     target_mce_m2_ip_address      = ( { ipv4       = "127.0.0.7";
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 f6a22c83754..55127e1c53b 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 15a7fa6fa84..88e4c886850 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 7d2ee421854..5794310fad8 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf
index 475ffe9218d..5348c25c0e0 100644
--- a/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf
@@ -145,6 +145,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 517c916c859..7ea8839b8ae 100644
--- a/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf
@@ -184,6 +184,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf
index 46ab9660177..36f0fdf7b10 100644
--- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "CI_RCC_IP_ADDR";
                                        ipv6       = "192:168:30::17";
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 6560fa41c5f..b61201440ba 100644
--- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 bdcc201fd99..8a2cedfd055 100644
--- a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf
@@ -192,6 +192,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf
index 5b2c90a714d..27ecaa7ef61 100755
--- a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf
@@ -190,6 +190,8 @@ eNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES : 
     {
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 e045ec4ca9a..08dd3003290 100644
--- a/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf
index c76a664c156..371a6b4610a 100644
--- a/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf
@@ -183,6 +183,8 @@ eNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "CI_RCC_IP_ADDR";
                                        ipv6       = "192:168:30::17";
diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
index 92af74c3002..7a4b5f54c1b 100755
--- a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
@@ -210,6 +210,8 @@ gNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "CI_FR1_CTL_ENB_IP_ADDR";
                                        ipv6       = "192:168:30::17";
diff --git a/ci-scripts/conf_files/lte-fdd-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-basic-sim.conf
index 24a2b400e63..163047d7b96 100644
--- a/ci-scripts/conf_files/lte-fdd-basic-sim.conf
+++ b/ci-scripts/conf_files/lte-fdd-basic-sim.conf
@@ -184,6 +184,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf
index e3adedbf4a8..bb49d68bb45 100644
--- a/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf
+++ b/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf
@@ -185,6 +185,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
  ////////// MCE parameters:
     target_mce_m2_ip_address      = ( { ipv4       = "127.0.0.7";
diff --git a/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf
index 3d5a8591563..2e211d86b8a 100644
--- a/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf
+++ b/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf
@@ -185,6 +185,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
  ////////// MCE parameters:
     target_mce_m2_ip_address      = ( { ipv4       = "127.0.0.7";
diff --git a/ci-scripts/conf_files/lte-tdd-basic-sim.conf b/ci-scripts/conf_files/lte-tdd-basic-sim.conf
index 3afdb5df60c..ad7e9d9f86a 100644
--- a/ci-scripts/conf_files/lte-tdd-basic-sim.conf
+++ b/ci-scripts/conf_files/lte-tdd-basic-sim.conf
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 8ad65b6278c..0547590c294 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
@@ -150,6 +150,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 891301128f4..3441690e6d8 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
@@ -150,6 +150,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 76df9ffde51..23709444bdb 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
@@ -150,6 +150,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 b842480e5d0..33d00b89085 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
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 98a546e8b50..a939c66cba2 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
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 2a8506a6604..473496defac 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
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf b/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf
index b61e5e05b1d..bf2db711522 100644
--- a/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf
+++ b/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf
@@ -155,6 +155,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
 
     ////////// MCE parameters:
diff --git a/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf b/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf
index 5daaa8d13ae..3bcd038d705 100644
--- a/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf
+++ b/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf
@@ -155,6 +155,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
 
     ////////// MCE parameters:
diff --git a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
index 28bfd91560d..ad113d0ffc1 100644
--- a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
+++ b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
@@ -185,6 +185,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 7f920e7e384..7158790b284 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 e5c57ffda55..70819d0e29f 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 17a33805678..7381fefc1a2 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 6721504f366..8eecfa2ac5b 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 4919ad3117c..ce2b71bdd2c 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 c26a0ad698b..11e6e244187 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 ff0d3d7a004..11f6adbb4d0 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 8195b21157e..3bf79f94bf2 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 8b172a7d736..67a2bae08c3 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
@@ -147,6 +147,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 0d9a243b31c..02f29c4c2ed 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
@@ -149,6 +149,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 ac8591841e9..71a479a5126 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
@@ -149,6 +149,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 93bfc2449f9..09958d62e4b 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
@@ -149,6 +149,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/configuration/bladeRF/enb-band7-5mhz.conf b/configuration/bladeRF/enb-band7-5mhz.conf
index df9b1cbc851..9156a74fb0b 100644
--- a/configuration/bladeRF/enb-band7-5mhz.conf
+++ b/configuration/bladeRF/enb-band7-5mhz.conf
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES : 
     {
diff --git a/doc/testing_gnb_w_cots_ue_resources/enb.conf b/doc/testing_gnb_w_cots_ue_resources/enb.conf
index 58e4e868732..35249aac25d 100755
--- a/doc/testing_gnb_w_cots_ue_resources/enb.conf
+++ b/doc/testing_gnb_w_cots_ue_resources/enb.conf
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES : 
     {
diff --git a/doc/testing_gnb_w_cots_ue_resources/gnb.conf b/doc/testing_gnb_w_cots_ue_resources/gnb.conf
index db8aef33ba6..c4a8d512b8e 100755
--- a/doc/testing_gnb_w_cots_ue_resources/gnb.conf
+++ b/doc/testing_gnb_w_cots_ue_resources/gnb.conf
@@ -212,6 +212,8 @@ gNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "192.168.18.199";
                                        ipv6       = "192:168:30::17";
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index 27b0ed08ddb..a0522dd9c9a 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -139,7 +139,6 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
 //#define TICK_TO_US(ts) (ts.diff)
 #define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
 
-
 static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) {
 
   sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe;
diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h
index 054f3f37341..14b6e7c0b17 100644
--- a/openair2/COMMON/gtpv1_u_messages_types.h
+++ b/openair2/COMMON/gtpv1_u_messages_types.h
@@ -98,6 +98,7 @@ typedef struct gtpv1u_enb_delete_tunnel_req_s {
   uint8_t                num_erab;
   ebi_t                  eps_bearer_id[GTPV1U_MAX_BEARERS_PER_UE];
   //teid_t                 enb_S1u_teid;         ///< local SGW S11 Tunnel Endpoint Identifier
+  int                    from_gnb;             ///< Indicates if the message comes from gNB or eNB (1 = comes from gNB, 0 from eNB)
 } gtpv1u_enb_delete_tunnel_req_t;
 
 typedef struct gtpv1u_enb_delete_tunnel_resp_s {
@@ -170,4 +171,5 @@ typedef struct {
   in_addr_t             enb_ip_address_for_S1u_S12_S4_up;
   tcp_udp_port_t        enb_port_for_S1u_S12_S4_up;
 } Gtpv1uS1Req;
+
 #endif /* GTPV1_U_MESSAGES_TYPES_H_ */
diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h
index 8438fd1037c..23c87fcc9d3 100644
--- a/openair2/COMMON/x2ap_messages_def.h
+++ b/openair2/COMMON/x2ap_messages_def.h
@@ -48,10 +48,18 @@ MESSAGE_DEF(X2AP_HANDOVER_CANCEL                , MESSAGE_PRIORITY_MED, x2ap_han
 /* handover messages X2AP <-> S1AP */
 MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE             , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t        , x2ap_ue_context_release)
 
-/*Senb bearer addition messages X2AP <-> RRC */
+/* Senb bearer addition messages X2AP <-> RRC */
 MESSAGE_DEF(X2AP_SENB_ADDITION_REQ              , MESSAGE_PRIORITY_MED, x2ap_senb_addition_req_t         , x2ap_senb_addition_req)
 
-/*SGnb bearer addition messages X2AP <-> RRC */
-MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ              , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_t         , x2ap_ENDC_sgnb_addition_req)
-MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ_ACK              , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_ACK_t         , x2ap_ENDC_sgnb_addition_req_ACK)
-MESSAGE_DEF(X2AP_ENDC_SGNB_RECONF_COMPLETE              , MESSAGE_PRIORITY_MED, x2ap_ENDC_reconf_complete_t         , x2ap_ENDC_sgnb_reconf_complete)
+/* SGnb bearer addition messages X2AP <-> RRC */
+MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ         , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_t    , x2ap_ENDC_sgnb_addition_req)
+MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ_ACK     , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_ACK_t, x2ap_ENDC_sgnb_addition_req_ACK)
+MESSAGE_DEF(X2AP_ENDC_SGNB_RECONF_COMPLETE      , MESSAGE_PRIORITY_MED, x2ap_ENDC_reconf_complete_t      , x2ap_ENDC_sgnb_reconf_complete)
+
+/* SGnb UE releases ('request' is for enb starting the process, 'required' for gnb) */
+MESSAGE_DEF(X2AP_ENDC_SGNB_RELEASE_REQUEST      , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_release_request_t , x2ap_ENDC_sgnb_release_request)
+MESSAGE_DEF(X2AP_ENDC_SGNB_RELEASE_REQUIRED     , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_release_required_t, x2ap_ENDC_sgnb_release_required)
+
+/* ENDC timers' timeout X2AP <-> RRC */
+MESSAGE_DEF(X2AP_ENDC_DC_PREP_TIMEOUT           , MESSAGE_PRIORITY_MED, x2ap_ENDC_dc_prep_timeout_t      , x2ap_ENDC_dc_prep_timeout)
+MESSAGE_DEF(X2AP_ENDC_DC_OVERALL_TIMEOUT        , MESSAGE_PRIORITY_MED, x2ap_ENDC_dc_overall_timeout_t   , x2ap_ENDC_dc_overall_timeout)
diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h
index f0743e60a52..3d40febc0d2 100644
--- a/openair2/COMMON/x2ap_messages_types.h
+++ b/openair2/COMMON/x2ap_messages_types.h
@@ -25,22 +25,32 @@
 #include "s1ap_messages_types.h"
 #include "LTE_PhysCellId.h"
 
+typedef enum {
+  X2AP_CAUSE_T_DC_PREP_TIMEOUT,
+  X2AP_CAUSE_T_DC_OVERALL_TIMEOUT,
+  X2AP_CAUSE_RADIO_CONNECTION_WITH_UE_LOST,
+} x2ap_cause_t;
+
 //-------------------------------------------------------------------------------------------//
 // Defines to access message fields.
 
-#define X2AP_REGISTER_ENB_REQ(mSGpTR)           		(mSGpTR)->ittiMsg.x2ap_register_enb_req
-#define X2AP_SETUP_REQ(mSGpTR)                  		(mSGpTR)->ittiMsg.x2ap_setup_req
-#define X2AP_SETUP_RESP(mSGpTR)                 		(mSGpTR)->ittiMsg.x2ap_setup_resp
-#define X2AP_HANDOVER_REQ(mSGpTR)               		(mSGpTR)->ittiMsg.x2ap_handover_req
-#define X2AP_HANDOVER_REQ_ACK(mSGpTR)           		(mSGpTR)->ittiMsg.x2ap_handover_req_ack
-#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_SENB_ADDITION_REQ(mSGpTR)              	(mSGpTR)->ittiMsg.x2ap_senb_addition_req
-#define X2AP_ENDC_SGNB_ADDITION_REQ(mSGpTR)         	(mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req
-#define X2AP_ENDC_SGNB_ADDITION_REQ_ACK(mSGpTR)         (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req_ACK
-#define X2AP_ENDC_SGNB_RECONF_COMPLETE(mSGpTR)          (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_reconf_complete
+#define X2AP_REGISTER_ENB_REQ(mSGpTR)                           (mSGpTR)->ittiMsg.x2ap_register_enb_req
+#define X2AP_SETUP_REQ(mSGpTR)                                  (mSGpTR)->ittiMsg.x2ap_setup_req
+#define X2AP_SETUP_RESP(mSGpTR)                                 (mSGpTR)->ittiMsg.x2ap_setup_resp
+#define X2AP_HANDOVER_REQ(mSGpTR)                               (mSGpTR)->ittiMsg.x2ap_handover_req
+#define X2AP_HANDOVER_REQ_ACK(mSGpTR)                           (mSGpTR)->ittiMsg.x2ap_handover_req_ack
+#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_SENB_ADDITION_REQ(mSGpTR)                          (mSGpTR)->ittiMsg.x2ap_senb_addition_req
+#define X2AP_ENDC_SGNB_ADDITION_REQ(mSGpTR)                     (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req
+#define X2AP_ENDC_SGNB_ADDITION_REQ_ACK(mSGpTR)                 (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req_ACK
+#define X2AP_ENDC_SGNB_RECONF_COMPLETE(mSGpTR)                  (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_reconf_complete
+#define X2AP_ENDC_SGNB_RELEASE_REQUEST(mSGpTR)                  (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_release_request
+#define X2AP_ENDC_SGNB_RELEASE_REQUIRED(mSGpTR)                 (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_release_required
+#define X2AP_ENDC_DC_PREP_TIMEOUT(mSGpTR)                       (mSGpTR)->ittiMsg.x2ap_ENDC_dc_prep_timeout
+#define X2AP_ENDC_DC_OVERALL_TIMEOUT(mSGpTR)                    (mSGpTR)->ittiMsg.x2ap_ENDC_dc_overall_timeout
 
 #define X2AP_MAX_NB_ENB_IP_ADDRESS 2
 
@@ -144,6 +154,8 @@ typedef struct x2ap_register_enb_req_s {
   /* timers (unit: millisecond) */
   int t_reloc_prep;
   int tx2_reloc_overall;
+  int t_dc_prep;
+  int t_dc_overall;
 } x2ap_register_enb_req_t;
 
 typedef struct x2ap_subframe_process_s {
@@ -357,6 +369,8 @@ typedef struct x2ap_ENDC_sgnb_addition_req_ACK_s {
 
   int SgNB_ue_x2_id;
 
+  int gnb_x2_assoc_id;  // to be stored in the rrc's ue context, used when sending 'sgnb reconfiguration complete'
+
   /* used for X2AP->RRC in source eNB */
   int rnti;
 
@@ -384,16 +398,26 @@ typedef struct x2ap_ENDC_sgnb_addition_req_ACK_s {
 
 typedef struct x2ap_ENDC_reconf_complete_s {
   int MeNB_ue_x2_id;
-
   int SgNB_ue_x2_id;
-  LTE_PhysCellId_t target_physCellId;
+  int gnb_x2_assoc_id;
+} x2ap_ENDC_reconf_complete_t;
 
-  x2ap_sgNB_reconf_response_information_t reconf_response;
+typedef struct x2ap_ENDC_sgnb_release_request_s {
+  int          rnti;
+  x2ap_cause_t cause;
+  int          assoc_id;
+} x2ap_ENDC_sgnb_release_request_t;
 
-  uint8_t rrc_buffer[4096 /* arbitrary, big enough */];
-  int rrc_buffer_size;
+typedef struct x2ap_ENDC_sgnb_release_required_s {
+  int gnb_rnti;
+} x2ap_ENDC_sgnb_release_required_t;
 
-} x2ap_ENDC_reconf_complete_t;
+typedef struct x2ap_ENDC_dc_prep_timeout_s {
+  int rnti;
+} x2ap_ENDC_dc_prep_timeout_t;
 
+typedef struct x2ap_ENDC_dc_overall_timeout_s {
+  int rnti;
+} x2ap_ENDC_dc_overall_timeout_t;
 
 #endif /* X2AP_MESSAGES_TYPES_H_ */
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 4c6a7885c3e..ce91402586f 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -2731,20 +2731,28 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
             {
               int t_reloc_prep = 0;
               int tx2_reloc_overall = 0;
+              int t_dc_prep = 0;
+              int t_dc_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 }
+                { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 },
+                { "t_dc_prep", "t_dc_prep", 0, iptr:&t_dc_prep, defintval:0, TYPE_INT, 0 },
+                { "t_dc_overall", "t_dc_overall", 0, iptr:&t_dc_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");
+                  tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000 ||
+                  t_dc_prep <= 0 || t_dc_prep > 10000 ||
+                  t_dc_overall <= 0 || t_dc_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] and [0 < t_dc_prep <= 10000] and [0 < t_dc_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;
+              X2AP_REGISTER_ENB_REQ (msg_p).t_dc_prep = t_dc_prep;
+              X2AP_REGISTER_ENB_REQ (msg_p).t_dc_overall = t_dc_overall;
             }
             // SCTP SETTING
             X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 716134ad8ab..8c8e78bbd0a 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -1123,20 +1123,28 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) {
             {
               int t_reloc_prep = 0;
               int tx2_reloc_overall = 0;
+              int t_dc_prep = 0;
+              int t_dc_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 }
+                { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 },
+                { "t_dc_prep", "t_dc_prep", 0, iptr:&t_dc_prep, defintval:0, TYPE_INT, 0 },
+                { "t_dc_overall", "t_dc_overall", 0, iptr:&t_dc_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");
+                  tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000 ||
+                  t_dc_prep <= 0 || t_dc_prep > 10000 ||
+                  t_dc_overall <= 0 || t_dc_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] and [0 < t_dc_prep <= 10000] and [0 < t_dc_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;
+              X2AP_REGISTER_ENB_REQ (msg_p).t_dc_prep = t_dc_prep;
+              X2AP_REGISTER_ENB_REQ (msg_p).t_dc_overall = t_dc_overall;
             }
             // SCTP SETTING
             X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index 1c36c474d83..a3c9b84cf58 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -441,11 +441,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
 
   pdcp_run(&ctxt);
-  //rrc_rx_tx(&ctxt, CC_id);
-  /* send tick to RLC every ms */
+  /* send tick to RLC and RRC every ms */
   if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) {
     void nr_rlc_tick(int frame, int subframe);
     nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
+    nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
   }
 
   dlsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].dlsch_in_slot_bitmap;  // static bitmap signaling which slot in a tdd period contains dlsch
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index f4ec142da19..fb5ea1698ab 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -1454,7 +1454,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
         UE_list->num_UEs);
   dump_nr_ue_list(UE_list, 0);
 
-  for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
+  for (i = 0; i < MAX_MOBILES_PER_GNB; i++) {
     if (UE_list->active[i] == TRUE)
       continue;
 
@@ -1492,6 +1492,35 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
   return -1;
 }
 
+void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti)
+{
+  int UE_id;
+  int i;
+  NR_UE_list_t *UE_list = &RC.nrmac[mod_id]->UE_list;
+
+  for (i = 0; i < MAX_MOBILES_PER_GNB; i++) {
+    if (UE_list->active[i] != TRUE)
+      continue;
+    if (UE_list->rnti[i] != rnti)
+      continue;
+
+    /* UE found, remove it */
+    UE_id = i;
+    UE_list->num_UEs--;
+    UE_list->fiveG_connected[UE_id] = FALSE;
+    UE_list->active[UE_id] = FALSE;
+    UE_list->rnti[UE_id] = 0;
+    free(UE_list->UE_sched_ctrl[UE_id].sched_pucch);
+    free(UE_list->UE_sched_ctrl[UE_id].sched_pusch);
+    memset((void *) &UE_list->UE_sched_ctrl[UE_id],
+           0,
+           sizeof(NR_UE_sched_ctrl_t));
+    LOG_I(MAC, "[gNB %d] Remove NR UE_id %d : rnti %x\n",
+          mod_id,
+          UE_id,
+          rnti);
+  }
+}
 
 uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) {
   // al values passed to this function are x10
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 7caf1baed57..d83d544755e 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -265,6 +265,8 @@ int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP);
 
 int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP);
 
+void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti);
+
 int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
                      int bwp_id,
                      int coreset_id,
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
index c8b385bbfcd..29605029d6c 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
@@ -854,7 +854,12 @@ uint64_t get_pdcp_optmask(void)
 boolean_t pdcp_remove_UE(
   const protocol_ctxt_t *const  ctxt_pP)
 {
-  TODO;
+  int rnti = ctxt_pP->rnti;
+
+  nr_pdcp_manager_lock(nr_pdcp_ue_manager);
+  nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager, rnti);
+  nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
+
   return 1;
 }
 
@@ -897,9 +902,9 @@ printf("pdcp_data_req called size %d\n", sdu_buffer_size);
     rb = ue->drb[rb_id - 1];
 
   if (rb == NULL) {
-    LOG_E(PDCP, "%s:%d:%s: fatal: no DRB found (rnti %d, rb_id %ld)\n",
+    LOG_E(PDCP, "%s:%d:%s: no DRB found (rnti %d, rb_id %ld)\n",
           __FILE__, __LINE__, __FUNCTION__, rnti, rb_id);
-    exit(1);
+    return 0;
   }
 
   rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP);
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c
index 09f1e4f599e..d4db8d84842 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c
@@ -117,7 +117,7 @@ void nr_rlc_manager_remove_ue(nr_rlc_ue_manager_t *_m, int rnti)
       break;
 
   if (i == m->ue_count) {
-    LOG_D(RLC, "%s:%d:%s: warning: ue %d not found\n",
+    LOG_W(RLC, "%s:%d:%s: warning: ue %d not found\n",
           __FILE__, __LINE__, __FUNCTION__,
           rnti);
     return;
diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h
index c498e3c6fe3..2be605a5deb 100644
--- a/openair2/RRC/LTE/rrc_defs.h
+++ b/openair2/RRC/LTE/rrc_defs.h
@@ -271,7 +271,8 @@ typedef enum UE_STATE_e {
   RRC_RECONFIGURED,
   RRC_HO_EXECUTION,
   RRC_NR_NSA,
-  RRC_NR_NSA_RECONFIGURED
+  RRC_NR_NSA_RECONFIGURED,
+  RRC_NR_NSA_DELETED
 } UE_STATE_t;
 
 typedef enum HO_STATE_e {
@@ -591,6 +592,8 @@ typedef struct eNB_RRC_UE_s {
 
   uint8_t                            Status; // RRC status, type enum UE_STATE_t
   rnti_t                             rnti;
+  int                                gnb_rnti;     //RNTI of the UE at the gNB if in ENDC connection
+  int                                gnb_x2_assoc_id;
   uint64_t                           random_ue_identity;
 
 
diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c
index a6775bbf8a4..466113584cc 100644
--- a/openair2/RRC/LTE/rrc_eNB.c
+++ b/openair2/RRC/LTE/rrc_eNB.c
@@ -4648,6 +4648,8 @@ rrc_eNB_process_MeasurementReport(
     if ((ue_context_pP->ue_context.Status != RRC_NR_NSA) && (ue_context_pP->ue_context.Status != RRC_NR_NSA_RECONFIGURED)) {
       MessageDef      *msg;
       ue_context_pP->ue_context.Status = RRC_NR_NSA;
+      ue_context_pP->ue_context.gnb_rnti = -1;         // set when receiving X2AP_ENDC_SGNB_ADDITION_REQ_ACK
+      ue_context_pP->ue_context.gnb_x2_assoc_id = -1;  // set when receiving X2AP_ENDC_SGNB_ADDITION_REQ_ACK
 
       if(is_en_dc_supported(ue_context_pP->ue_context.UE_Capability)) {
         /** to add gNB as Secondary node CG-ConfigInfo to be added as per 36.423 r15 **/
@@ -5006,6 +5008,7 @@ void rrc_eNB_handover_ue_context_release(
   msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
   memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
   GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
+  GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0;
 
   for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
     GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
@@ -6948,6 +6951,32 @@ rrc_eNB_generate_RRCConnectionSetup(
   }
 }
 
+//-----------------------------------------------------------------------------
+void rrc_eNB_process_reconfiguration_complete_endc(const protocol_ctxt_t *const ctxt_pP,
+        rrc_eNB_ue_context_t *const ue_context_p)
+//-----------------------------------------------------------------------------
+{
+  MessageDef *msg_p;
+
+  msg_p = itti_alloc_new_message (TASK_RRC_ENB, X2AP_ENDC_SGNB_RECONF_COMPLETE);
+
+  /* MeNB_ue_x2_id is unknown, set to 0.
+   * This is not correct but X2 id in the eNB is only 12 bits,
+   * so unfortunately we can't use rnti.
+   * To be corrected if needed.
+   * As of today, when stopping t_dc_prep we remove the UE
+   * from X2. To keep the id until the 'reconfiguration complete' message is received
+   * needs a rethink/rewrite of this logic. For simplicity, let's
+   * keep it as is. The only problem we can get is if/when we
+   * interoperate with a non-OAI gNB. The OAI gNB does not
+   * care about MeNB_ue_x2_id.
+   */
+  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).MeNB_ue_x2_id   = 0;
+  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).SgNB_ue_x2_id   = ue_context_p->ue_context.gnb_rnti;
+  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).gnb_x2_assoc_id = ue_context_p->ue_context.gnb_x2_assoc_id;
+  itti_send_msg_to_task (TASK_X2AP, ctxt_pP->instance, msg_p);
+}
+
 void setup_ngran_CU(eNB_RRC_INST *rrc) {
 }
 
@@ -7849,6 +7878,8 @@ rrc_eNB_decode_dcch(
                             ue_context_p->ue_context.Status = RRC_NR_NSA_RECONFIGURED;
                             /*Trigger E-RAB Modification Indication */
                             rrc_eNB_send_E_RAB_Modification_Indication(ctxt_pP, ue_context_p);
+                            /* send reconfiguration complete to gNB */
+                            rrc_eNB_process_reconfiguration_complete_endc(ctxt_pP, ue_context_p);
                           }
                         }
                       }
@@ -7909,6 +7940,7 @@ rrc_eNB_decode_dcch(
               msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
               memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
               GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
+              GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0;
 
               for(i = 0; i < NB_RB_MAX; i++) {
                 if(xid == ue_context_p->ue_context.e_rab[i].xid) {
@@ -8439,6 +8471,17 @@ rrc_eNB_decode_dcch(
                       ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions.
                       choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15->failureType_r15);
                 xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)ul_dcch_msg);
+
+                /* TODO: scg failure indication, what to do? Let's remove the UE for now.
+                 * We could re-establish DRB?
+                 * Also, the way to remove is to start ue_release_timer_rrc and
+                 * send RRCConnectionRelease to the UE, maybe it's not good/correct.
+                 */
+                if (ue_context_p != NULL) {
+                  ue_context_p->ue_context.ue_release_timer_thres_rrc = 100;
+                  ue_context_p->ue_context.ue_release_timer_rrc = 1;
+                  rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p);
+                }
               }
             }
           }
@@ -8989,6 +9032,19 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
       ue_to_be_removed[cur_ue]->ue_context.ue_reestablishment_timer = 0;
     }
 
+    /* remove UE from gNB if UE is in NSA mode */
+    if (ue_to_be_removed[cur_ue]->ue_context.Status == RRC_NR_NSA ||
+        ue_to_be_removed[cur_ue]->ue_context.Status == RRC_NR_NSA_RECONFIGURED) {
+      MessageDef *message_p;
+      message_p = itti_alloc_new_message(TASK_RRC_ENB, X2AP_ENDC_SGNB_RELEASE_REQUEST);
+      X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).rnti = ue_to_be_removed[cur_ue]->ue_context.gnb_rnti;
+      X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).assoc_id = ue_to_be_removed[cur_ue]->ue_context.gnb_x2_assoc_id;
+      X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).cause = X2AP_CAUSE_RADIO_CONNECTION_WITH_UE_LOST;
+      itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, message_p);
+      /* set state to RRC_NR_NSA_DELETED to avoid sending X2AP_ENDC_SGNB_RELEASE_REQUEST again later */
+      ue_to_be_removed[cur_ue]->ue_context.Status = RRC_NR_NSA_DELETED;
+    }
+
     rrc_eNB_free_UE(ctxt_pP->module_id, ue_to_be_removed[cur_ue]);
 
     if (ue_to_be_removed[cur_ue]->ue_context.ul_failure_timer >= 20000) {
@@ -9106,6 +9162,10 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP,
 
   if (ue_context) {
     ue_context->ue_context.nb_of_modify_endc_e_rabs = m->nb_e_rabs_admitted_tobeadded;
+
+    ue_context->ue_context.gnb_rnti = m->SgNB_ue_x2_id;
+    ue_context->ue_context.gnb_x2_assoc_id = m->gnb_x2_assoc_id;
+
     int j=0;
 
     while(j < m->nb_e_rabs_admitted_tobeadded) {
@@ -9143,6 +9203,54 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP,
   }
 }
 
+void rrc_eNB_process_ENDC_DC_prep_timeout(module_id_t module_id, x2ap_ENDC_dc_prep_timeout_t *m)
+{
+  rrc_eNB_ue_context_t *ue_context;
+
+  ue_context = rrc_eNB_get_ue_context(RC.rrc[module_id], m->rnti);
+  if (ue_context == NULL) {
+    LOG_E(RRC, "receiving DC prep timeout for unknown UE rnti %d\n", m->rnti);
+    return;
+  }
+
+  if (ue_context->ue_context.Status != RRC_NR_NSA) {
+    LOG_E(RRC, "receiving DC prep timeout for UE rnti %d not in state RRC_NR_NSA\n", m->rnti);
+    return;
+  }
+
+  LOG_I(RRC, "DC prep timeout for UE rnti %d, put back to RRC_RECONFIGURED mode\n", m->rnti);
+  ue_context->ue_context.Status = RRC_RECONFIGURED;
+}
+
+void rrc_eNB_process_ENDC_sgNB_release_required(module_id_t module_id, x2ap_ENDC_sgnb_release_required_t *m)
+{
+  rrc_eNB_ue_context_t *ue_context;
+  protocol_ctxt_t      ctxt;
+
+  ue_context = rrc_eNB_find_ue_context_from_gnb_rnti(RC.rrc[module_id], m->gnb_rnti);
+  if (ue_context == NULL) {
+    LOG_E(RRC, "receiving ENDC SgNB Release Required for unknown UE (with gNB's rnti %d)\n", m->gnb_rnti);
+    return;
+  }
+
+  /* TODO: what to do? release the UE? if yes, how? Or re-establish bearers in LTE?
+   * Or something else?
+   * The following removes the UE, maybe it's not correct at all.
+   */
+  ue_context->ue_context.ue_release_timer_thres_rrc = 100;
+  ue_context->ue_context.ue_release_timer_rrc = 1;
+
+  ue_context->ue_context.Status = RRC_NR_NSA_DELETED;
+
+  PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
+                                module_id,  /* TODO: should be 'instance' */
+                                ENB_FLAG_YES,
+                                ue_context->ue_context.rnti,
+                                0, 0);
+
+  rrc_eNB_generate_RRCConnectionRelease(&ctxt, ue_context);
+}
+
 //-----------------------------------------------------------------------------
 void *rrc_enb_process_itti_msg(void *notUsed) {
   MessageDef                         *msg_p;
@@ -9426,6 +9534,16 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
       break;
     }
 
+    case X2AP_ENDC_DC_PREP_TIMEOUT: {
+      rrc_eNB_process_ENDC_DC_prep_timeout(ENB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_DC_PREP_TIMEOUT(msg_p));
+      break;
+    }
+
+    case X2AP_ENDC_SGNB_RELEASE_REQUIRED: {
+      rrc_eNB_process_ENDC_sgNB_release_required(ENB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_SGNB_RELEASE_REQUIRED(msg_p));
+      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/RRC/LTE/rrc_eNB_GTPV1U.c b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
index 1025d46f626..5c25d2dbcff 100644
--- a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
+++ b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
@@ -189,6 +189,7 @@ void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(
   MessageDef *msg = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
   memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg)));
   GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).rnti = ue_context_pP->ue_context.rnti;
+  GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).from_gnb = 0;
   GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).num_erab = ue_context_pP->ue_context.nb_of_e_rabs;
   for (int e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_e_rabs; e_rab++) {
     const rb_id_t gtp_ebi = ue_context_pP->ue_context.enb_gtp_ebi[e_rab];
diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c
index 9f92be366bd..4be9a50b325 100644
--- a/openair2/RRC/LTE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c
@@ -1751,6 +1751,7 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms
       msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
       memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
       GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
+      GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0;
 
       for(i = 0; i < NB_RB_MAX; i++) {
         if(xid == ue_context_p->ue_context.e_rab[i].xid) {
diff --git a/openair2/RRC/LTE/rrc_eNB_UE_context.c b/openair2/RRC/LTE/rrc_eNB_UE_context.c
index 197aedae517..2cc89adf156 100644
--- a/openair2/RRC/LTE/rrc_eNB_UE_context.c
+++ b/openair2/RRC/LTE/rrc_eNB_UE_context.c
@@ -173,6 +173,23 @@ rrc_eNB_get_ue_context(
 }
 
 
+//------------------------------------------------------------------------------
+struct rrc_eNB_ue_context_s *
+rrc_eNB_find_ue_context_from_gnb_rnti(
+  eNB_RRC_INST *rrc_instance_pP,
+  int gnb_rnti)
+//------------------------------------------------------------------------------
+{
+  struct rrc_eNB_ue_context_s   *ue_context_p = NULL;
+  RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(rrc_instance_pP->rrc_ue_head)) {
+    if (ue_context_p->ue_context.gnb_rnti == gnb_rnti) {
+      return ue_context_p;
+    }
+  }
+  return NULL;
+}
+
+
 //------------------------------------------------------------------------------
 void rrc_eNB_remove_ue_context(
   const protocol_ctxt_t *const ctxt_pP,
diff --git a/openair2/RRC/LTE/rrc_eNB_UE_context.h b/openair2/RRC/LTE/rrc_eNB_UE_context.h
index e22f517d501..c6420ca9367 100644
--- a/openair2/RRC/LTE/rrc_eNB_UE_context.h
+++ b/openair2/RRC/LTE/rrc_eNB_UE_context.h
@@ -73,6 +73,11 @@ rrc_eNB_get_ue_context(
   rnti_t rntiP
 );
 
+struct rrc_eNB_ue_context_s *
+rrc_eNB_find_ue_context_from_gnb_rnti(
+  eNB_RRC_INST *rrc_instance_pP,
+  int gnb_rnti);
+
 void rrc_eNB_remove_ue_context(
   const protocol_ctxt_t* const ctxt_pP,
   eNB_RRC_INST*                rrc_instance_pP,
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 317282c8148..3a6bbfd5a31 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -69,6 +69,8 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,LTE_UE_CapabilityRAT_ContainerL
 
 void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m);
 
+void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti);
+
 void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
 				     NR_CellGroupConfig_t *secondaryCellGroup,
 				     int scg_id,
@@ -97,3 +99,5 @@ int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2
    \param void *args_p Pointer on arguments to start the task. */
 void *rrc_gnb_task(void *args_p);
 
+/* Trigger RRC periodic processing. To be called once per ms. */
+void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe);
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 5721d05aee5..757724765e2 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -301,6 +301,26 @@ void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x
   parse_CG_ConfigInfo(rrc,cg_configinfo,m);
 }
 
+void rrc_gNB_process_release_request(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_release_request_t *m)
+{
+  gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP];
+  rrc_remove_nsa_user(rrc, m->rnti);
+}
+
+void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC_dc_overall_timeout_t *m)
+{
+  gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP];
+  rrc_remove_nsa_user(rrc, m->rnti);
+}
+
+void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
+  MessageDef *msg;
+
+  /* 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);
+}
+
 ///---------------------------------------------------------------------------------------------------------------///
 ///---------------------------------------------------------------------------------------------------------------///
 void *rrc_gnb_task(void *args_p) {
@@ -319,7 +339,10 @@ void *rrc_gnb_task(void *args_p) {
     itti_receive_msg(TASK_RRC_GNB, &msg_p);
     msg_name_p = ITTI_MSG_NAME(msg_p);
     instance = ITTI_MSG_INSTANCE(msg_p);
-    LOG_I(NR_RRC,"Received message %s\n",msg_name_p);
+
+    /* RRC_SUBFRAME_PROCESS is sent every subframe, do not log it */
+    if (ITTI_MSG_ID(msg_p) != RRC_SUBFRAME_PROCESS)
+      LOG_I(NR_RRC,"Received message %s\n",msg_name_p);
 
     switch (ITTI_MSG_ID(msg_p)) {
       case TERMINATE_MESSAGE:
@@ -333,6 +356,10 @@ void *rrc_gnb_task(void *args_p) {
 
       /* Messages from MAC */
 
+      case RRC_SUBFRAME_PROCESS:
+        nr_rrc_subframe_process(&RRC_SUBFRAME_PROCESS(msg_p).ctxt, RRC_SUBFRAME_PROCESS(msg_p).CC_id);
+        break;
+
       /* Messages from PDCP */
 
       /*
@@ -406,6 +433,20 @@ void *rrc_gnb_task(void *args_p) {
         LOG_I(NR_RRC, "Handling of reconfiguration complete message at RRC gNB is pending \n");
         break;
 
+      case X2AP_ENDC_SGNB_RELEASE_REQUEST:
+        LOG_I(NR_RRC, "Received ENDC sgNB release request from X2AP \n");
+        rrc_gNB_process_release_request(GNB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_SGNB_RELEASE_REQUEST(msg_p));
+        break;
+
+      case X2AP_ENDC_DC_OVERALL_TIMEOUT:
+        rrc_gNB_process_dc_overall_timeout(GNB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_DC_OVERALL_TIMEOUT(msg_p));
+        break;
+
+      /* Messages from GTP */
+      case GTPV1U_ENB_DELETE_TUNNEL_RESP:
+        /* nothing to do? */
+        break;
+
       default:
         LOG_E(NR_RRC, "[gNB %d] Received unexpected message %s\n", instance, msg_name_p);
         break;
@@ -417,3 +458,11 @@ void *rrc_gnb_task(void *args_p) {
   }
 }
 
+void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe)
+{
+  MessageDef *message_p;
+  message_p = itti_alloc_new_message(TASK_RRC_GNB, RRC_SUBFRAME_PROCESS);
+  RRC_SUBFRAME_PROCESS(message_p).ctxt  = *ctxt;
+  RRC_SUBFRAME_PROCESS(message_p).CC_id = CC_id;
+  itti_send_msg_to_task(TASK_RRC_GNB, ctxt->module_id, message_p);
+}
diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c
index 78f39c16d72..7b7647a7465 100644
--- a/openair2/RRC/NR/rrc_gNB_nsa.c
+++ b/openair2/RRC/NR/rrc_gNB_nsa.c
@@ -27,8 +27,6 @@
  * \company Eurecom
  * \email: raymond.knopp@eurecom.fr
  */
-#ifndef RRC_GNB_NSA_C
-#define RRC_GNB_NSA_C
 
 #include "nr_rrc_defs.h"
 #include "NR_RRCReconfiguration.h"
@@ -247,15 +245,21 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
       LOG_W(RRC, "No E-RAB to be added received from SgNB Addition Request message \n");
   }
 
-  //X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size
-  // Send to X2 entity to transport to MeNB
-  asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config,
-                            NULL,
-                            (void *)CG_Config,
-                            X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer,
-                            1024);
-  X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3;
-  itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding
+  if (m != NULL) {
+    X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).MeNB_ue_x2_id = m->ue_x2_id;
+    X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).SgNB_ue_x2_id = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
+
+    //X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size
+    // Send to X2 entity to transport to MeNB
+    asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config,
+                              NULL,
+                              (void *)CG_Config,
+                              X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer,
+                              1024);
+    X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3;
+    itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding
+  }
+
   rrc->Nb_ue++;
   // configure MAC and RLC
   rrc_mac_config_req_gNB(rrc->module_id,
@@ -290,5 +294,45 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
 
 }
 
+void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) {
+  protocol_ctxt_t      ctxt;
+  rrc_gNB_ue_context_t *ue_context;
+  MessageDef           *msg_delete_tunnels_p;
+  int                  e_rab;
+
+  LOG_D(RRC, "calling rrc_remove_nsa_user rnti %d\n", rnti);
+  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, rnti, 0, 0, rrc->module_id);
+
+  ue_context = rrc_gNB_get_ue_context(rrc, rnti);
+  if (ue_context == NULL) {
+    LOG_W(RRC, "rrc_remove_nsa_user: rnti %d not found\n", rnti);
+    return;
+  }
+
+  pdcp_remove_UE(&ctxt);
 
-#endif
+  rrc_rlc_remove_ue(&ctxt);
+
+  mac_remove_nr_ue(rrc->module_id, rnti);
+
+  /* delete gtp tunnel */
+  msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_GNB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
+  memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
+  GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = rnti;
+  GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 1;
+
+  LOG_D(RRC, "ue_context->ue_context.nb_of_e_rabs %d\n", ue_context->ue_context.nb_of_e_rabs);
+  for (e_rab = 0; e_rab < ue_context->ue_context.nb_of_e_rabs; e_rab++) {
+    GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
+      ue_context->ue_context.gnb_gtp_ebi[e_rab];
+    // erase data
+    ue_context->ue_context.gnb_gtp_teid[e_rab] = 0;
+    memset(&ue_context->ue_context.gnb_gtp_addrs[e_rab], 0, sizeof(ue_context->ue_context.gnb_gtp_addrs[e_rab]));
+    ue_context->ue_context.gnb_gtp_ebi[e_rab] = 0;
+  }
+
+  itti_send_msg_to_task(TASK_GTPV1_U, rrc->module_id, msg_delete_tunnels_p);
+
+  /* remove context */
+  rrc_gNB_remove_ue_context(&ctxt, rrc, ue_context);
+}
diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c
index bd772727470..4789efeebe8 100644
--- a/openair2/X2AP/x2ap_eNB.c
+++ b/openair2/X2AP/x2ap_eNB.c
@@ -305,7 +305,9 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
     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);
+                     x2ap_register_eNB->tx2_reloc_overall,
+                     x2ap_register_eNB->t_dc_prep,
+                     x2ap_register_eNB->t_dc_overall);
 
     for (int i = 0; i< x2ap_register_eNB->num_cc; i++) {
       new_instance->eutra_band[i]              = x2ap_register_eNB->eutra_band[i];
@@ -476,7 +478,10 @@ void x2ap_eNB_handle_sgNB_add_req(instance_t instance,
   }
   /* id_source is ue_id, id_target is unknown yet */
   x2ap_set_ids(id_manager, ue_id, x2ap_ENDC_sgnb_addition_req->rnti, ue_id, -1);
-  x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_PREPARE);
+  x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_ENB_PREPARE);
+  x2ap_set_dc_prep_timer(id_manager, ue_id,
+                         x2ap_timer_get_tti(&instance_p->timers));
+  x2ap_id_set_target(id_manager, ue_id, x2ap_eNB_data);
 
   x2ap_eNB_generate_ENDC_x2_SgNB_addition_request(instance_p, x2ap_ENDC_sgnb_addition_req,
       x2ap_eNB_data, ue_id);
@@ -498,9 +503,6 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance,
   x2ap_eNB_instance_t *instance_p;
   x2ap_eNB_data_t     *target;
   int                 ue_id;
-  /*int source_assoc_id = x2ap_ENDC_sgnb_addition_req_ACK->source_assoc_id;
-  int                 id_source;
-  int                 id_target;*/
 
   instance_p = x2ap_eNB_get_instance(instance);
   DevAssert(instance_p != NULL);
@@ -514,22 +516,15 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance,
     X2AP_ERROR("could not allocate a new X2AP UE ID\n");
     exit(1);
   }
-  /* id_source is ue_id, id_target is unknown yet */
-  x2ap_set_ids(id_manager, ue_id, x2ap_ENDC_sgnb_addition_req_ACK->rnti, ue_id,
-      x2ap_ENDC_sgnb_addition_req_ACK->MeNB_ue_x2_id);
-  x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_SOURCE_OVERALL);
-	
-
-  /*target = x2ap_get_eNB(NULL, source_assoc_id, 0);
-  DevAssert(target != NULL);*/
-
-  // rnti is a new information, save it
-
-  /*ue_id     = x2ap_handover_req_ack->x2_id_target;
-  id_source = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
-  id_target = ue_id;
-  x2ap_set_ids(&instance_p->id_manager, ue_id, x2ap_handover_req_ack->rnti, id_source, id_target);*/
-
+  /* id_Source is MeNB_ue_x2_id, id_target is rnti (rnti is SgNB_ue_x2_id) */
+  x2ap_set_ids(id_manager, ue_id,
+      x2ap_ENDC_sgnb_addition_req_ACK->SgNB_ue_x2_id,
+      x2ap_ENDC_sgnb_addition_req_ACK->MeNB_ue_x2_id,
+      x2ap_ENDC_sgnb_addition_req_ACK->SgNB_ue_x2_id);
+  x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_GNB_OVERALL);
+  x2ap_set_dc_overall_timer(id_manager, ue_id,
+                            x2ap_timer_get_tti(&instance_p->timers));
+  x2ap_id_set_target(id_manager, ue_id, target);
 
   x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK(instance_p, target,
       x2ap_ENDC_sgnb_addition_req_ACK, ue_id);
@@ -540,27 +535,24 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance,
  * @param	: IN instance, IN x2ap_reconf_complete
 **/ 
 static
-void x2ap_eNB_trigger_sgnb_reconfiguration_complete(instance_t instance, 
-    x2ap_ENDC_reconf_complete_t *x2ap_reconf_complete) 
+void x2ap_eNB_trigger_sgnb_reconfiguration_complete(instance_t instance,
+    x2ap_ENDC_reconf_complete_t *x2ap_reconf_complete)
 {
-  x2ap_eNB_instance_t *instance_p = NULL;
-  x2ap_eNB_data_t     *target = NULL;
-  int id_source = -1;
-  int id_target = -1;
-  LTE_PhysCellId_t target_pci;
-	
+  x2ap_eNB_instance_t *instance_p;
+  x2ap_eNB_data_t     *target;
+  int                 id_source;
+  int                 id_target;
+
   instance_p = x2ap_eNB_get_instance(instance);
   DevAssert(instance_p != NULL);
   DevAssert(x2ap_reconf_complete != NULL);
-  
-  target_pci = x2ap_reconf_complete->target_physCellId;
-  target = x2ap_is_eNB_pci_in_list(target_pci);
+
+  target = x2ap_get_eNB(NULL,x2ap_reconf_complete->gnb_x2_assoc_id, 0);
   DevAssert(target != NULL);
-	
+
   id_source = x2ap_reconf_complete->MeNB_ue_x2_id;
   id_target = x2ap_reconf_complete->SgNB_ue_x2_id;
   x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(instance_p, target, id_source, id_target);
-
 }
 
 
@@ -589,6 +581,34 @@ void x2ap_eNB_ue_context_release(instance_t instance,
   x2ap_release_id(&instance_p->id_manager, ue_id);
 }
 
+static
+void x2ap_eNB_handle_sgNB_release_request(instance_t instance,
+    x2ap_ENDC_sgnb_release_request_t *x2ap_release_req)
+{
+  x2ap_eNB_instance_t *instance_p;
+  x2ap_eNB_data_t     *target;
+
+  instance_p = x2ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+  DevAssert(x2ap_release_req != NULL);
+
+  if (x2ap_release_req->rnti == -1 ||
+      x2ap_release_req->assoc_id == -1) {
+    X2AP_WARN("x2ap_eNB_handle_sgNB_release_request: bad rnti or assoc_id, do not send release request to gNB\n");
+    return;
+  }
+
+  target = x2ap_get_eNB(NULL, x2ap_release_req->assoc_id, 0);
+  DevAssert(target != NULL);
+
+  /* id_source is not used by oai's gNB so it's not big deal. For
+   * interoperability with other gNBs things may need to be refined.
+   */
+  x2ap_eNB_generate_ENDC_x2_SgNB_release_request(instance_p, target,
+                                                 0, x2ap_release_req->rnti,
+                                                 x2ap_release_req->cause);
+}
+
 void *x2ap_task(void *arg) {
   MessageDef *received_msg = NULL;
   int         result;
@@ -640,10 +660,16 @@ void *x2ap_task(void *arg) {
     	LOG_I(X2AP, "Received elements for X2AP_ENDC_SGNB_ADDITION_REQ_ACK \n");
     	break;
 
-	  case X2AP_ENDC_SGNB_RECONF_COMPLETE:
-		x2ap_eNB_trigger_sgnb_reconfiguration_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
-		    &X2AP_ENDC_SGNB_RECONF_COMPLETE(received_msg));
-		break;
+      case X2AP_ENDC_SGNB_RECONF_COMPLETE:
+        x2ap_eNB_trigger_sgnb_reconfiguration_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                          &X2AP_ENDC_SGNB_RECONF_COMPLETE(received_msg));
+        break;
+
+      case X2AP_ENDC_SGNB_RELEASE_REQUEST:
+        x2ap_eNB_handle_sgNB_release_request(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                          &X2AP_ENDC_SGNB_RELEASE_REQUEST(received_msg));
+        break;
+
       case SCTP_INIT_MSG_MULTI_CNF:
         x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
                                                 &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c
index 3762bc06dcc..6d7897bf144 100644
--- a/openair2/X2AP/x2ap_eNB_decoder.c
+++ b/openair2/X2AP/x2ap_eNB_decoder.c
@@ -69,6 +69,14 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
         	X2AP_INFO("X2AP_ProcedureCode_id_sgNBReconfigurationCompletion message!\n");
         break;
 
+    case X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease:
+      X2AP_INFO("X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease message!\n");
+      break;
+
+    case X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease:
+      X2AP_INFO("X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease message!\n");
+      break;
+
     default:
       X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
                   (int)pdu->choice.initiatingMessage.procedureCode);
@@ -103,6 +111,10 @@ static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu)
     	X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
     	break;
 
+    case X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease:
+      X2AP_INFO("meNBinitiatedSgNBRelease successful outcome!\n");
+      break;
+
     default:
       X2AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
                   (int)pdu->choice.successfulOutcome.procedureCode);
diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c
index a96fa14f48e..8c6a27a6224 100644
--- a/openair2/X2AP/x2ap_eNB_generate_messages.c
+++ b/openair2/X2AP/x2ap_eNB_generate_messages.c
@@ -1668,8 +1668,6 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in
 		uint32_t  len;
 		int       ret = 0;
 
-		int MeNB_UE_X2AP_id = x2ap_sgnb_addition_req_ACK->MeNB_ue_x2_id;
-		int SgNB_UE_X2AP_id = ue_id;
 		int e_rabs_admitted_tobeadded = x2ap_sgnb_addition_req_ACK->nb_e_rabs_admitted_tobeadded;
 		long int pDCPatSgNB = X2AP_EN_DC_ResourceConfiguration__pDCPatSgNB_present;
 		long int mCGresources = X2AP_EN_DC_ResourceConfiguration__mCGresources_not_present;
@@ -1694,7 +1692,7 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in
 		ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
 		ie->criticality= X2AP_Criticality_reject;
 		ie->value.present = X2AP_SgNBAdditionRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
-		ie->value.choice.UE_X2AP_ID = MeNB_UE_X2AP_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+		ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
 		ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
 
 		// SgNB_UE_X2AP_id
@@ -1702,7 +1700,7 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in
 		ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
 		ie->criticality= X2AP_Criticality_reject;
 		ie->value.present = X2AP_SgNBAdditionRequestAcknowledge_IEs__value_PR_SgNB_UE_X2AP_ID;
-		ie->value.choice.UE_X2AP_ID = SgNB_UE_X2AP_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+		ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_target(&instance_p->id_manager, ue_id);
 		ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
 
 		ie = (X2AP_SgNBAdditionRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBAdditionRequestAcknowledge_IEs_t));
@@ -1792,7 +1790,7 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(
 	ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
 	ie->criticality= X2AP_Criticality_reject;
 	ie->value.present = X2AP_SgNBReconfigurationComplete_IEs__value_PR_UE_X2AP_ID;
-	ie->value.choice.UE_X2AP_ID = ue_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+	ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
 	ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
 
 	ie = (X2AP_SgNBReconfigurationComplete_IEs_t *)calloc(1, sizeof(X2AP_SgNBReconfigurationComplete_IEs_t));
@@ -1821,3 +1819,226 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(
 	return ret;
 
 }
+
+int x2ap_eNB_generate_ENDC_x2_SgNB_release_request(
+  x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
+  int x2_id_source, int x2_id_target, x2ap_cause_t cause)
+{
+  X2AP_X2AP_PDU_t                        pdu;
+  X2AP_SgNBReleaseRequest_t     *out;
+  X2AP_SgNBReleaseRequest_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(x2ap_eNB_data_p != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease;
+  pdu.choice.initiatingMessage.criticality = X2AP_Criticality_ignore;
+  pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_SgNBReleaseRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.SgNBReleaseRequest;
+
+  ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
+  ie->criticality= X2AP_Criticality_reject;
+  ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = x2_id_source;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2_id_target != -1) {
+    ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t));
+    ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
+    ie->criticality= X2AP_Criticality_reject;
+    ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_SgNB_UE_X2AP_ID;
+    ie->value.choice.SgNB_UE_X2AP_ID = x2_id_target;
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_Cause;
+  ie->criticality= X2AP_Criticality_ignore;
+  ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_Cause;
+  switch (cause) {
+  case X2AP_CAUSE_T_DC_PREP_TIMEOUT:
+    ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
+    ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_tDCprep_expiry;
+    break;
+  case X2AP_CAUSE_RADIO_CONNECTION_WITH_UE_LOST:
+    ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
+    ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_radio_connection_with_UE_lost;
+    break;
+  default:
+    X2AP_ERROR("%s: unhandled cause %d\n", __FUNCTION__, cause);
+    exit(1);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode ENDC X2 SgNB_release_request message\n");
+    return -1;
+  }
+
+  x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge(
+  x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
+  int menb_ue_x2ap_id, int sgnb_ue_x2ap_id)
+{
+  X2AP_X2AP_PDU_t                          pdu;
+  X2AP_SgNBReleaseRequestAcknowledge_t     *out;
+  X2AP_SgNBReleaseRequestAcknowledge_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(x2ap_eNB_data_p != NULL);
+
+  x2ap_eNB_data_p->state = X2AP_ENB_STATE_WAITING;
+
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease;
+  pdu.choice.successfulOutcome.criticality = X2AP_Criticality_ignore;
+  pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_SgNBReleaseRequestAcknowledge;
+  out = &pdu.choice.successfulOutcome.value.choice.SgNBReleaseRequestAcknowledge;
+
+  ie = (X2AP_SgNBReleaseRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequestAcknowledge_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
+  ie->criticality= X2AP_Criticality_ignore;
+  ie->value.present = X2AP_SgNBReleaseRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = menb_ue_x2ap_id;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  ie = (X2AP_SgNBReleaseRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequestAcknowledge_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
+  ie->criticality= X2AP_Criticality_ignore;
+  ie->value.present = X2AP_SgNBReleaseRequestAcknowledge_IEs__value_PR_SgNB_UE_X2AP_ID;
+  ie->value.choice.SgNB_UE_X2AP_ID = sgnb_ue_x2ap_id;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode ENDC X2 SgNB Release Request Acknowledge\n");
+    return -1;
+  }
+
+  x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int x2ap_eNB_generate_ENDC_x2_SgNB_release_required(
+  x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
+  int x2_id_source, int x2_id_target, x2ap_cause_t cause)
+{
+  X2AP_X2AP_PDU_t                pdu;
+  X2AP_SgNBReleaseRequired_t     *out;
+  X2AP_SgNBReleaseRequired_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(x2ap_eNB_data_p != NULL);
+
+  /* Prepare the X2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease;
+  pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_SgNBReleaseRequired;
+  out = &pdu.choice.initiatingMessage.value.choice.SgNBReleaseRequired;
+
+  ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
+  ie->criticality= X2AP_Criticality_reject;
+  ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = x2_id_source;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
+  ie->criticality= X2AP_Criticality_reject;
+  ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_SgNB_UE_X2AP_ID;
+  ie->value.choice.SgNB_UE_X2AP_ID = x2_id_target;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_Cause;
+  ie->criticality= X2AP_Criticality_ignore;
+  ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_Cause;
+  switch (cause) {
+  case X2AP_CAUSE_T_DC_OVERALL_TIMEOUT:
+    ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
+    ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_tDCoverall_expiry;
+    break;
+  default:
+    X2AP_ERROR("%s: unhandled cause %d\n", __FUNCTION__, cause);
+    exit(1);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode ENDC X2 SgNB_release_request message\n");
+    return -1;
+  }
+
+  x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm(
+  x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
+  int menb_ue_x2ap_id, int sgnb_ue_x2ap_id)
+{
+  X2AP_X2AP_PDU_t               pdu;
+  X2AP_SgNBReleaseConfirm_t     *out;
+  X2AP_SgNBReleaseConfirm_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(x2ap_eNB_data_p != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease;
+  pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_SgNBReleaseConfirm;
+  out = &pdu.choice.successfulOutcome.value.choice.SgNBReleaseConfirm;
+
+  ie = (X2AP_SgNBReleaseConfirm_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseConfirm_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
+  ie->criticality= X2AP_Criticality_ignore;
+  ie->value.present = X2AP_SgNBReleaseConfirm_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = menb_ue_x2ap_id;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  ie = (X2AP_SgNBReleaseConfirm_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseConfirm_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
+  ie->criticality= X2AP_Criticality_ignore;
+  ie->value.present = X2AP_SgNBReleaseConfirm_IEs__value_PR_SgNB_UE_X2AP_ID;
+  ie->value.choice.SgNB_UE_X2AP_ID = sgnb_ue_x2ap_id;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode ENDC X2 SgNB Release Request Acknowledge\n");
+    return -1;
+  }
+
+  x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.h b/openair2/X2AP/x2ap_eNB_generate_messages.h
index 3dfccc0e520..a920020b811 100644
--- a/openair2/X2AP/x2ap_eNB_generate_messages.h
+++ b/openair2/X2AP/x2ap_eNB_generate_messages.h
@@ -77,4 +77,16 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in
 int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(
   x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, int ue_id, int SgNB_ue_id);
 
+int x2ap_eNB_generate_ENDC_x2_SgNB_release_request(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
+                                                   int x2_id_source, int x2_id_target, x2ap_cause_t cause);
+
+int x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
+                                                               int menb_ue_x2ap_id, int sgnb_ue_x2ap_id);
+
+int x2ap_eNB_generate_ENDC_x2_SgNB_release_required(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
+                                                    int x2_id_source, int x2_id_target, x2ap_cause_t cause);
+
+int x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
+                                                   int menb_ue_x2ap_id, int sgnb_ue_x2ap_id);
+
 #endif /*  X2AP_ENB_GENERATE_MESSAGES_H_ */
diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c
index 1c6c98cd81e..e34d642b500 100644
--- a/openair2/X2AP/x2ap_eNB_handler.c
+++ b/openair2/X2AP/x2ap_eNB_handler.c
@@ -132,6 +132,29 @@ int x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete (instance_t instance,
                                           uint32_t stream,
                                           X2AP_X2AP_PDU_t *pdu);
 
+static
+int x2ap_gNB_handle_ENDC_sGNB_release_request(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu);
+
+static
+int x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu);
+
+static
+int x2ap_gNB_handle_ENDC_sGNB_release_required(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu);
+
+static
+int x2ap_gNB_handle_ENDC_sGNB_release_confirm(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu);
 
 /* Handlers matrix. Only eNB related procedure present here. Placement of callback functions according to X2AP_ProcedureCode.h */
 x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
@@ -166,8 +189,9 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
   { x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete, 0, 0 }, /*X2AP_ProcedureCode_id_sgNBReconfigurationCompletion*/
   { 0, 0, 0 },
   { 0, 0, 0 },
-  { 0, 0, 0 },
-  { 0, 0, 0 },
+  { x2ap_gNB_handle_ENDC_sGNB_release_request, x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge, 0 }, /* meNBinitiatedSgNBRelease */
+  { x2ap_gNB_handle_ENDC_sGNB_release_required, x2ap_gNB_handle_ENDC_sGNB_release_confirm, 0 }, /* sgNBinitiatedSgNBRelease */
+
   { 0, 0, 0 },
   { 0, 0, 0 },
   { 0, 0, 0 },
@@ -1641,8 +1665,6 @@ int x2ap_gNB_handle_ENDC_sGNB_addition_request (instance_t instance,
                                           uint32_t stream,
                                           X2AP_X2AP_PDU_t *pdu)
 {
-
-
   X2AP_SgNBAdditionRequest_t             *x2SgNBAdditionRequest;
   X2AP_SgNBAdditionRequest_IEs_t         *ie;
 
@@ -1823,6 +1845,8 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
 	  //Allocate an ITTI X2AP_SGNB_ADDITION_REQ message instead
 	  msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_ADDITION_REQ_ACK);
 
+	  X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).gnb_x2_assoc_id = assoc_id;
+
 	  /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
 	  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBAdditionRequestAcknowledge_IEs_t, ie, x2SgNBAdditionRequest_ack,
 			  X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true);
@@ -1923,6 +1947,9 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
 
 	  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
 
+          /* remove UE from x2, DC preparation is over */
+          x2ap_release_id(&instance_p->id_manager, ue_id);
+
 	  return 0;
 }
 
@@ -1930,78 +1957,289 @@ static
 int x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete (instance_t instance,
                                           uint32_t assoc_id,
                                           uint32_t stream,
-                                          X2AP_X2AP_PDU_t *pdu) {
+                                          X2AP_X2AP_PDU_t *pdu)
+{
+  X2AP_SgNBReconfigurationComplete_t     *x2SgNBReconfigurationComplete;
+  X2AP_SgNBReconfigurationComplete_IEs_t *ie;
 
-	X2AP_SgNBReconfigurationComplete_t               *x2SgNBReconfigurationComplete;
-	X2AP_SgNBReconfigurationComplete_IEs_t           *ie;
+  x2ap_eNB_instance_t                    *instance_p;
+  x2ap_eNB_data_t                        *x2ap_eNB_data;
+  MessageDef                             *msg;
 
-	x2ap_eNB_instance_t                *instance_p;
-	x2ap_eNB_data_t                    *x2ap_eNB_data;
-	MessageDef                         *msg;
+  int                                    id_target;
+  int                                    ue_id;
 
-		  DevAssert (pdu != NULL);
-		  x2SgNBReconfigurationComplete = &pdu->choice.initiatingMessage.value.choice.SgNBReconfigurationComplete;
+  DevAssert (pdu != NULL);
+  x2SgNBReconfigurationComplete = &pdu->choice.initiatingMessage.value.choice.SgNBReconfigurationComplete;
 
-		  /*if (stream == 0) {
-		    X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n");
-		    // TODO: send a x2 failure response
-		    return 0;
-		  }*/
+  /*if (stream == 0) {
+    X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n");
+    // TODO: send a x2 failure response
+    return 0;
+  }*/
 
-		  X2AP_DEBUG ("Received X2 SgNB Reconfiguration complete message\n");
+  X2AP_DEBUG ("Received X2 SgNB Reconfiguration complete message\n");
 
-		  x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
-		  DevAssert(x2ap_eNB_data != NULL);
+  x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
+  DevAssert(x2ap_eNB_data != NULL);
 
-		  X2AP_INFO("X2AP Association id: %d \n",assoc_id);
+  X2AP_INFO("X2AP Association id: %d \n",assoc_id);
 
-		  instance_p = x2ap_eNB_get_instance(instance);
-		  DevAssert(instance_p != NULL);
+  instance_p = x2ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
 
-		  //Allocate an ITTI X2AP_sGNB_reconfiguration_complete message
-		  msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RECONF_COMPLETE);
+  //Allocate an ITTI X2AP_sGNB_reconfiguration_complete message
+  msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RECONF_COMPLETE);
 
-		  /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
-		  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
-				  X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true);
-		  if (ie == NULL ) {
-		    X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
-		    return -1;
-		  }
+  /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
+      X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true);
+  if (ie == NULL ) {
+    X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    return -1;
+  }
 
-		  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).MeNB_ue_x2_id = ie->value.choice.UE_X2AP_ID;
+  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).MeNB_ue_x2_id = ie->value.choice.UE_X2AP_ID;
 
 
-		  /* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */
-		  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
-				  X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true);
-		  if (ie == NULL ) {
-			  X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
-			  return -1;
-		  }
+  /* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
+      X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true);
+  if (ie == NULL ) {
+    X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    return -1;
+  }
 
-		  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).SgNB_ue_x2_id = ie->value.choice.SgNB_UE_X2AP_ID;
+  id_target = ie->value.choice.SgNB_UE_X2AP_ID;
+  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).SgNB_ue_x2_id = id_target;
 
+  ue_id = x2ap_find_id_from_id_target(&instance_p->id_manager, id_target);
+  if (ue_id == -1) {
+    X2AP_WARN("incorrect/unknown X2AP IDs for UE (SgNB_UE_X2AP_ID %d), ignoring sGNB reconfiguration complete\n",
+              id_target);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
+    return 0;
+  }
 
-		  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
-				  X2AP_ProtocolIE_ID_id_ResponseInformationSgNBReconfComp, true);
-		  if (ie == NULL ) {
-			  X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
-			  return -1;
-		  }
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
+      X2AP_ProtocolIE_ID_id_ResponseInformationSgNBReconfComp, true);
+  if (ie == NULL ) {
+    X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    return -1;
+  }
 
-		  if(ie->value.choice.ResponseInformationSgNBReconfComp.present == X2AP_ResponseInformationSgNBReconfComp_PR_success_SgNBReconfComp){
-			  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).reconf_response = X2AP_RECONF_RESPONSE_SUCCESS;
-		  }
-		  else {
-			  X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).reconf_response = X2AP_RECONF_RESPONSE_REJECT;
-		  }
+  if (ie->value.choice.ResponseInformationSgNBReconfComp.present != X2AP_ResponseInformationSgNBReconfComp_PR_success_SgNBReconfComp){
+    X2AP_ERROR("%s %d: fatal: unsuccessfulSgNB Reconfiguration Complete\n",__FILE__,__LINE__);
+    exit(1);
+  }
 
-		  itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
+  x2ap_release_id(&instance_p->id_manager, ue_id);
 
+  itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
 
-	return 0;
+  return 0;
 }
 
+static
+int x2ap_gNB_handle_ENDC_sGNB_release_request(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu)
+{
+  /* the logic in this function is the following: when receiving a release
+   * request, the UE may exist in X2. Or not. If it's not in X2, it can
+   * nevertheless be in RRC.
+   * The release request message may contain the gNB id. Or not. It's better
+   * to look for the UE using the gNB rather than the eNB id. So if we have
+   * the gNB id we use it. If not, we use the eNB id.
+   */
+  X2AP_SgNBReleaseRequest_t     *req;
+  X2AP_SgNBReleaseRequest_IEs_t *ie;
+
+  x2ap_eNB_instance_t           *instance_p;
+  x2ap_eNB_data_t               *x2ap_eNB_data;
+  MessageDef                    *msg;
+
+  int                           id_source;
+  int                           id_target;
+  int                           rnti;
+  int                           ue_id;
+
+  DevAssert (pdu != NULL);
+  req = &pdu->choice.initiatingMessage.value.choice.SgNBReleaseRequest;
+
+  /*if (stream == 0) {
+    X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n");
+    // TODO: send a x2 failure response
+    return 0;
+  }*/
+
+  X2AP_DEBUG ("Received X2 SgNB Release Request message\n");
 
+  x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
+  DevAssert(x2ap_eNB_data != NULL);
 
+  X2AP_INFO("X2AP Association id: %d \n",assoc_id);
+
+  instance_p = x2ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequest_IEs_t, ie, req,
+                             X2AP_ProtocolIE_ID_id_MeNB_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_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequest_IEs_t, ie, req,
+                             X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, false);
+  if (ie != NULL)
+    id_target = ie->value.choice.SgNB_UE_X2AP_ID;
+  else
+    id_target = -1;
+
+  /* find ue_id, preferably from id_target if id_target is known */
+  ue_id = -1;
+  if (id_target != -1)
+    ue_id = x2ap_find_id_from_id_target(&instance_p->id_manager, id_target);
+  if (ue_id == -1)
+    ue_id = x2ap_find_id_from_id_source(&instance_p->id_manager, id_source);
+
+  if (ue_id == -1) {
+    X2AP_WARN("%s %d: no UE found for id_source %d id_target %d\n",
+              __FILE__, __LINE__, id_source, id_target);
+  }
+
+  /* the UE may not exist in X2 anymore but exist in RRC
+   * in which case its rnti is simply the id_target
+   */
+  if (ue_id != -1) {
+    rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
+
+    /* remove ue_id */
+    x2ap_release_id(&instance_p->id_manager, ue_id);
+  } else {
+    rnti = id_target;
+  }
+
+  if (rnti != -1) {
+    msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RELEASE_REQUEST);
+
+    X2AP_ENDC_SGNB_RELEASE_REQUEST(msg).rnti = rnti;
+
+    itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
+  }
+
+  /* this call should maybe not be here, we should check that the
+   * SgNB Release Request message has been executed properly
+   */
+  x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge(instance_p, x2ap_eNB_data,
+                                                             id_source,
+                                                             rnti != -1 ? rnti : 0);
+
+  return 0;
+}
+
+static
+int x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu)
+{
+  /* nothing to do - may change at some point */
+  X2AP_INFO("received release request acknowledge\n");
+  return 0;
+}
+
+static
+int x2ap_gNB_handle_ENDC_sGNB_release_required(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu)
+{
+  /* the logic in this function is the following: when receiving a release
+   * required we don't care about the UE in X2. We simply send a message
+   * to RRC with the SgNB id (which is SgNB's RNTI). RRC will look for the
+   * UE using this RNTI and deal with it. In the meanwhile the X2 layer
+   * immediately replies with "release confirm" no matter what happens
+   * in RRC.
+   */
+  X2AP_SgNBReleaseRequired_t     *req;
+  X2AP_SgNBReleaseRequired_IEs_t *ie;
+
+  x2ap_eNB_instance_t           *instance_p;
+  x2ap_eNB_data_t               *x2ap_eNB_data;
+  MessageDef                    *msg;
+
+  int                           id_source;
+  int                           id_target;
+  int                           gnb_rnti;
+
+  DevAssert (pdu != NULL);
+  req = &pdu->choice.initiatingMessage.value.choice.SgNBReleaseRequired;
+
+  /*if (stream == 0) {
+    X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n");
+    // TODO: send a x2 failure response
+    return 0;
+  }*/
+
+  X2AP_DEBUG ("Received X2 SgNB Release Required message\n");
+
+  x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
+  DevAssert(x2ap_eNB_data != NULL);
+
+  X2AP_INFO("X2AP Association id: %d \n",assoc_id);
+
+  instance_p = x2ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequired_IEs_t, ie, req,
+                             X2AP_ProtocolIE_ID_id_MeNB_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_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequired_IEs_t, ie, req,
+                             X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true);
+  if (ie == NULL ) {
+    X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    return -1;
+  }
+
+  id_target = ie->value.choice.SgNB_UE_X2AP_ID;
+
+  gnb_rnti = id_target;
+
+  msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RELEASE_REQUIRED);
+  X2AP_ENDC_SGNB_RELEASE_REQUIRED(msg).gnb_rnti = gnb_rnti;
+  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+
+  /* this call should maybe not be here, we should check that the
+   * SgNB Release Required message has been executed properly
+   */
+  x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm(instance_p, x2ap_eNB_data,
+                                                 id_source, id_target);
+
+  return 0;
+}
+
+static
+int x2ap_gNB_handle_ENDC_sGNB_release_confirm(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu)
+{
+  /* nothing to do - may change at some point */
+  X2AP_INFO("received release confirm\n");
+  return 0;
+}
diff --git a/openair2/X2AP/x2ap_ids.c b/openair2/X2AP/x2ap_ids.c
index 02f1bbfc0e1..0750ba5bc93 100644
--- a/openair2/X2AP/x2ap_ids.c
+++ b/openair2/X2AP/x2ap_ids.c
@@ -70,6 +70,16 @@ int x2ap_find_id_from_id_source(x2ap_id_manager *m, int id_source)
   return -1;
 }
 
+int x2ap_find_id_from_id_target(x2ap_id_manager *m, int id_target)
+{
+  int i;
+  for (i = 0; i < X2AP_MAX_IDS; i++)
+    if (m->ids[i].rnti != -1 &&
+        m->ids[i].id_target == id_target)
+      return i;
+  return -1;
+}
+
 int x2ap_find_id_from_rnti(x2ap_id_manager *m, int rnti)
 {
   int i;
@@ -107,6 +117,16 @@ 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;
 }
 
+void x2ap_set_dc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time)
+{
+  m->ids[ue_id].t_dc_prep_start = time;
+}
+
+void x2ap_set_dc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time)
+{
+  m->ids[ue_id].t_dc_overall_start = time;
+}
+
 int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id)
 {
   return m->ids[ue_id].id_source;
diff --git a/openair2/X2AP/x2ap_ids.h b/openair2/X2AP/x2ap_ids.h
index f2670f3612b..26d97f73c88 100644
--- a/openair2/X2AP/x2ap_ids.h
+++ b/openair2/X2AP/x2ap_ids.h
@@ -38,7 +38,8 @@ typedef enum {
   X2ID_STATE_SOURCE_PREPARE,
   X2ID_STATE_SOURCE_OVERALL,
   X2ID_STATE_TARGET,
-  X2ID_STATE_NSA_PREPARE,
+  X2ID_STATE_NSA_ENB_PREPARE,
+  X2ID_STATE_NSA_GNB_OVERALL,
 } x2id_state_t;
 
 typedef struct {
@@ -55,6 +56,8 @@ typedef struct {
   /* timers */
   uint64_t      t_reloc_prep_start;
   uint64_t      tx2_reloc_overall_start;
+  uint64_t      t_dc_prep_start;
+  uint64_t      t_dc_overall_start;
 } x2ap_id;
 
 typedef struct {
@@ -66,6 +69,7 @@ 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_id_target(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);
@@ -73,6 +77,8 @@ void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state);
 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);
+void x2ap_set_dc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time);
+void x2ap_set_dc_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);
diff --git a/openair2/X2AP/x2ap_timers.c b/openair2/X2AP/x2ap_timers.c
index a0a7b61ad70..29e887504f2 100644
--- a/openair2/X2AP/x2ap_timers.c
+++ b/openair2/X2AP/x2ap_timers.c
@@ -28,11 +28,17 @@
 #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)
+void x2ap_timers_init(x2ap_timers_t *t,
+    int t_reloc_prep,
+    int tx2_reloc_overall,
+    int t_dc_prep,
+    int t_dc_overall)
 {
   t->tti               = 0;
   t->t_reloc_prep      = t_reloc_prep;
   t->tx2_reloc_overall = tx2_reloc_overall;
+  t->t_dc_prep         = t_dc_prep;
+  t->t_dc_overall      = t_dc_overall;
 }
 
 void x2ap_check_timers(instance_t instance)
@@ -59,14 +65,17 @@ void x2ap_check_timers(instance_t instance)
 
   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 ||
+        m->ids[i].state == X2ID_STATE_SOURCE_OVERALL)
+      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;
+      goto lte_handover_timeout;
     }
 
     if (m->ids[i].state == X2ID_STATE_SOURCE_OVERALL &&
@@ -74,13 +83,62 @@ void x2ap_check_timers(instance_t instance)
       LOG_I(X2AP, "X2 timeout reloc overall\n");
       /* tx2_reloc_overall timed out */
       cause = X2AP_TX2_RELOC_OVERALL_TIMEOUT;
-      goto timeout;
+      goto lte_handover_timeout;
+    }
+
+    if (m->ids[i].state == X2ID_STATE_NSA_ENB_PREPARE &&
+        t->tti > m->ids[i].t_dc_prep_start + t->t_dc_prep) {
+      int id_source;
+      int id_target;
+
+      LOG_I(X2AP, "X2 timeout DC prep\n");
+      /* t_dc_prep timed out */
+      target = x2ap_id_get_target(m, i);
+      id_source = x2ap_id_get_id_source(m, i);
+      id_target = x2ap_id_get_id_target(m, i);
+      x2ap_eNB_generate_ENDC_x2_SgNB_release_request(instance_p, target,
+                                                     id_source, id_target,
+                                                     X2AP_CAUSE_T_DC_PREP_TIMEOUT);
+
+      /* inform RRC of timeout */
+      msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_DC_PREP_TIMEOUT);
+      X2AP_ENDC_DC_PREP_TIMEOUT(msg).rnti  = x2ap_id_get_rnti(m, i);
+      itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+
+      /* remove UE from X2AP */
+      x2ap_release_id(m, i);
+
+      continue;
+    }
+
+    if (m->ids[i].state == X2ID_STATE_NSA_GNB_OVERALL &&
+        t->tti > m->ids[i].t_dc_overall_start + t->t_dc_overall) {
+      int id_source;
+      int id_target;
+
+      LOG_I(X2AP, "X2 timeout DC overall\n");
+      /* t_dc_overall timed out */
+      target = x2ap_id_get_target(m, i);
+      id_source = x2ap_id_get_id_source(m, i);
+      id_target = x2ap_id_get_id_target(m, i);
+      x2ap_eNB_generate_ENDC_x2_SgNB_release_required(instance_p, target,
+              id_source, id_target, X2AP_CAUSE_T_DC_OVERALL_TIMEOUT);
+
+      /* inform RRC of timeout */
+      msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_DC_OVERALL_TIMEOUT);
+      X2AP_ENDC_DC_OVERALL_TIMEOUT(msg).rnti  = x2ap_id_get_rnti(m, i);
+      itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
+
+      /* remove UE from X2AP */
+      x2ap_release_id(m, i);
+
+      continue;
     }
 
     /* no timeout -> check next UE */
     continue;
 
-timeout:
+lte_handover_timeout:
     /* inform target about timeout */
     target = x2ap_id_get_target(m, i);
     x2ap_eNB_generate_x2_handover_cancel(instance_p, target, i, cause);
diff --git a/openair2/X2AP/x2ap_timers.h b/openair2/X2AP/x2ap_timers.h
index d4579422d59..f32b73e87ba 100644
--- a/openair2/X2AP/x2ap_timers.h
+++ b/openair2/X2AP/x2ap_timers.h
@@ -36,9 +36,15 @@ typedef struct {
   /* timer values (unit: TTI, ie. millisecond when in realtime) */
   int      t_reloc_prep;
   int      tx2_reloc_overall;
+  int      t_dc_prep;
+  int      t_dc_overall;
 } x2ap_timers_t;
 
-void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall);
+void x2ap_timers_init(x2ap_timers_t *t,
+    int t_reloc_prep,
+    int tx2_reloc_overall,
+    int t_dc_prep,
+    int t_dc_overall);
 void x2ap_check_timers(instance_t instance);
 uint64_t x2ap_timer_get_tti(x2ap_timers_t *t);
 
diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c
index f095cce67de..1e2954ba954 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB.c
+++ b/openair3/GTPV1-U/gtpv1u_eNB.c
@@ -1184,7 +1184,10 @@ int gtpv1u_delete_s1u_tunnel(
     "0 GTPV1U_ENB_DELETE_TUNNEL_RESP rnti %x teid %x",
     GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti,
     teid_eNB);
-  return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p);
+  if (req_pP->from_gnb)
+    return itti_send_msg_to_task(TASK_RRC_GNB, instanceP, message_p);
+  else
+    return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p);
 }
 
 
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 d619ab29580..e1360c1f454 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
@@ -43,6 +43,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES : 
     {
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 558676e99b2..84c669571c2 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
@@ -55,6 +55,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES : 
     {
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 9a4a8634191..bc41de1874f 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
@@ -42,6 +42,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES : 
     {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf
index 716bfd3b6bc..0e3b9fffdff 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf
index 27fc90e5e30..5e02f16b027 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf
@@ -214,6 +214,8 @@ gNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "127.0.0.1";
                                        ipv6       = "192:168:30::17";
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 a761579018a..67044f38d91 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
@@ -367,6 +367,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_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 f248f515b89..e044c186b9a 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
@@ -148,6 +148,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 dee6c298a7b..5a547622abe 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
@@ -184,6 +184,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 231581574ae..27826e5ce2c 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
@@ -148,6 +148,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 54c12835ef3..5df0f107ea6 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
@@ -184,6 +184,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.master.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.master.conf
index c0decd362f9..cb50cccf2b9 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.master.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.master.conf
@@ -183,6 +183,8 @@ eNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 feab0d69260..245e4ecf94a 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
@@ -151,6 +151,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 1a0466aad33..86b481f9d85 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
@@ -184,6 +184,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 753c2d8b5c2..1eb5da6a181 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
@@ -185,6 +185,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 20646681d2c..a929c439be5 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
@@ -185,6 +185,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 d6f44e2b96a..43288ba3241 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
@@ -185,6 +185,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 8971633ce02..92f2d4e6f14 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
@@ -152,6 +152,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf
index ff8e2617832..1cd16d08319 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf
@@ -203,6 +203,8 @@ gNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "192.168.12.196";
                                        ipv6       = "192:168:30::17";
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf
index 81796ada2c8..dfae41f0a6b 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf
@@ -214,6 +214,8 @@ gNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "192.168.12.188";
                                        ipv6       = "192:168:30::17";
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf
index 771f5d18397..dcdfa003a26 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf
@@ -203,6 +203,8 @@ gNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "192.168.12.188";
                                        ipv6       = "192:168:30::17";
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
index 9420c488ec0..0659641607e 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
@@ -208,6 +208,8 @@ gNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "192.168.12.108";
                                        ipv6       = "192:168:30::17";
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 d2c1aac31ee..e05c64b4e83 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
@@ -154,6 +154,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 7c2c2e01709..1ef71bedc28 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
@@ -154,6 +154,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 723147daeb6..9ce9f28cc25 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
@@ -185,6 +185,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 13fd5fdb758..30cb852a284 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
@@ -154,6 +154,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
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 b72e4c59d7b..519305b68d8 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
@@ -155,6 +155,8 @@ eNBs =
     enable_x2 = "no";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES :
     {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf
index 4c0d346360e..4f4cbfd8236 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf
@@ -187,6 +187,8 @@ eNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
 
     NETWORK_INTERFACES : 
     {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
index 2eed408b53c..fd1b62fd3dc 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
@@ -214,6 +214,8 @@ gNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "192.168.18.199";
                                        ipv6       = "192:168:30::17";
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf
index f30c9284484..6a3f008ec1a 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf
@@ -212,6 +212,8 @@ gNBs =
     enable_x2 = "yes";
     t_reloc_prep      = 1000;      /* unit: millisecond */
     tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
     target_enb_x2_ip_address      = (
                                      { ipv4       = "192.168.18.199";
                                        ipv6       = "192:168:30::17";
-- 
GitLab