From 53d741f20dbf619a93a678976dfa51fc217071a2 Mon Sep 17 00:00:00 2001
From: Bing-Kai Hong <Bing-Kai.Hong@eurecom.fr>
Date: Thu, 20 Sep 2018 18:56:40 +0200
Subject: [PATCH] Generate the DCCH and send from pdcp

---
 openair2/F1AP/f1ap_cu_rrc_message_transfer.c  |  14 +-
 openair2/F1AP/f1ap_du_rrc_message_transfer.c  | 313 +++++-----
 openair2/F1AP/f1ap_du_task.c                  |   5 +-
 openair2/F1AP/f1ap_handlers.c                 |   2 +-
 openair2/LAYER2/PDCP_v10.1.0/pdcp.c           | 111 ++--
 .../LAYER2/RLC/AM_v9.3.0/#rlc_am_receiver.c#  | 534 ++++++++++++++++++
 openair2/LAYER2/RLC/rlc_mac.c                 |   4 +-
 openair2/RRC/LTE/L2_interface_common.c        |   6 +
 openair2/RRC/LTE/rrc_eNB.c                    |   6 +-
 openair2/RRC/LTE/rrc_eNB_S1AP.c               |   1 -
 targets/COMMON/create_tasks.c                 |   4 +
 targets/RT/USER/lte-softmodem.c               |  10 +
 12 files changed, 824 insertions(+), 186 deletions(-)
 create mode 100644 openair2/LAYER2/RLC/AM_v9.3.0/#rlc_am_receiver.c#

diff --git a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c
index 1b30602cdf..5ddb6fb187 100644
--- a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c
+++ b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c
@@ -264,7 +264,7 @@ int CU_send_DL_RRC_MESSAGE_TRANSFER(instance_t                instance,
     //ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority = 123L;
     ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
   }
-
+ 
   /* encode */
   if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
     LOG_E(CU_F1AP, "Failed to encode F1 setup request\n");
@@ -365,15 +365,17 @@ int CU_handle_UL_RRC_MESSAGE_TRANSFER(instance_t       instance,
   */
   protocol_ctxt_t ctxt;
   ctxt.module_id = instance;
+  ctxt.instance = instance;
   ctxt.rnti = f1ap_get_rnti_by_cu_id(&f1ap_cu_ue[instance],cu_ue_f1ap_id);
   ctxt.enb_flag = 1;
   mem_block_t *mb = get_free_mem_block(ie->value.choice.RRCContainer.size,__func__);
   memcpy((void*)mb->data,(void*)ie->value.choice.RRCContainer.buf,ie->value.choice.RRCContainer.size);
+  LOG_I(CU_F1AP, "Calling pdcp_data_ind for UE RNTI %x srb_id %lu with size %d (DCCH) \n", ctxt.rnti, srb_id, ie->value.choice.RRCContainer.size);
   pdcp_data_ind (&ctxt,
-		 1,
-		 0,
-		 srb_id,
-		 ie->value.choice.RRCContainer.size,
-		 mb);
+     1, // srb_flag
+     0, // embms_flag
+     srb_id,
+     ie->value.choice.RRCContainer.size,
+     mb);
   return 0;
 }
diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c
index 63066a4b8d..12d599bc39 100644
--- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c
+++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c
@@ -175,153 +175,208 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
   // decode RRC Container and act on the message type
   AssertFatal(srb_id<3,"illegal srb_id\n");
 
+  protocol_ctxt_t ctxt;
+  ctxt.rnti      = f1ap_get_rnti_by_du_id(&f1ap_du_ue[instance],du_ue_f1ap_id);
+  ctxt.module_id = instance;
+  ctxt.instance  = instance;
+  ctxt.enb_flag  = 1;
+
   if (srb_id == 0) {
     DL_CCCH_Message_t* dl_ccch_msg=NULL;
     asn_dec_rval_t dec_rval;
     dec_rval = uper_decode(NULL,
-			   &asn_DEF_DL_CCCH_Message,
-			   (void**)&dl_ccch_msg,
-			   ie->value.choice.RRCContainer.buf,
-			   rrc_dl_sdu_len,0,0);
+         &asn_DEF_DL_CCCH_Message,
+         (void**)&dl_ccch_msg,
+         ie->value.choice.RRCContainer.buf,
+         rrc_dl_sdu_len,0,0);
     switch (dl_ccch_msg->message.choice.c1.present) {
-      
-    case DL_CCCH_MessageType__c1_PR_NOTHING:
-      LOG_I(RRC, "Received PR_NOTHING on DL-CCCH-Message\n");
-      break;
-      
-    case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishment:
-      LOG_I(RRC,
-	    "Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishment\n");
-      break;
-      
-    case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishmentReject:
-      LOG_I(RRC,
-	    "Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishmentReject\n");
-      break;
-
-    case DL_CCCH_MessageType__c1_PR_rrcConnectionReject:
-      LOG_I(RRC,
-	    "Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n");
-      break;
-
-    case DL_CCCH_MessageType__c1_PR_rrcConnectionSetup:
+
+      case DL_CCCH_MessageType__c1_PR_NOTHING:
+        LOG_I(RRC, "Received PR_NOTHING on DL-CCCH-Message\n");
+        break;
+
+      case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishment:
+        LOG_I(RRC,
+        "Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishment\n");
+        break;
+
+      case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishmentReject:
+        LOG_I(RRC,
+        "Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishmentReject\n");
+        break;
+
+      case DL_CCCH_MessageType__c1_PR_rrcConnectionReject:
+        LOG_I(RRC,
+        "Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n");
+        break;
+
+      case DL_CCCH_MessageType__c1_PR_rrcConnectionSetup:
       {
-	LOG_I(RRC,
-	      "Logical Channel DL-CCCH (SRB0), Received RRCConnectionSetup DU_ID %x/RNTI %x\n",  
-	      du_ue_f1ap_id,
-	      f1ap_get_rnti_by_du_id(&f1ap_du_ue[instance],du_ue_f1ap_id));
-	// Get configuration
-
-	RRCConnectionSetup_t* rrcConnectionSetup = &dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup;
-	//	eNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
-	AssertFatal(rrcConnectionSetup!=NULL,"rrcConnectionSetup is null\n");
-	RadioResourceConfigDedicated_t* radioResourceConfigDedicated = &rrcConnectionSetup->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r8.radioResourceConfigDedicated;
-	
-	// get SRB logical channel information
-	SRB_ToAddModList_t *SRB_configList;
-	SRB_ToAddMod_t *SRB1_config;
-	LogicalChannelConfig_t *SRB1_logicalChannelConfig;  //,*SRB2_logicalChannelConfig;
-	SRB_configList                 = radioResourceConfigDedicated->srb_ToAddModList;
-
-	AssertFatal(SRB_configList!=NULL,"SRB_configList is null\n");
-	for (int cnt = 0; cnt < (SRB_configList)->list.count; cnt++) {
-	  if ((SRB_configList)->list.array[cnt]->srb_Identity == 1) {
-	    SRB1_config = (SRB_configList)->list.array[cnt];
-	    
-	    if (SRB1_config->logicalChannelConfig) {
-	      if (SRB1_config->logicalChannelConfig->present ==
-		  SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
-		SRB1_logicalChannelConfig = &SRB1_config->logicalChannelConfig->choice.explicitValue;
-	      } else {
-		SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
-	      }
-	    } else {
-	      SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
-	    }
-	    
-	    
-	  }
-	}
-
-	protocol_ctxt_t ctxt;
-	ctxt.rnti      = f1ap_get_rnti_by_du_id(&f1ap_du_ue[instance],du_ue_f1ap_id);
-        ctxt.module_id = instance;
-	ctxt.enb_flag  = 1;
-	rrc_rlc_config_asn1_req(&ctxt,
-				SRB_configList,
-				(DRB_ToAddModList_t*) NULL,
-				(DRB_ToReleaseList_t*) NULL
+        LOG_I(RRC,
+          "Logical Channel DL-CCCH (SRB0), Received RRCConnectionSetup DU_ID %x/RNTI %x\n",  
+          du_ue_f1ap_id,
+          f1ap_get_rnti_by_du_id(&f1ap_du_ue[instance],du_ue_f1ap_id));
+          // Get configuration
+
+        RRCConnectionSetup_t* rrcConnectionSetup = &dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup;
+        //	eNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
+        AssertFatal(rrcConnectionSetup!=NULL,"rrcConnectionSetup is null\n");
+        RadioResourceConfigDedicated_t* radioResourceConfigDedicated = &rrcConnectionSetup->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r8.radioResourceConfigDedicated;
+
+        // get SRB logical channel information
+        SRB_ToAddModList_t *SRB_configList;
+        SRB_ToAddMod_t *SRB1_config;
+        LogicalChannelConfig_t *SRB1_logicalChannelConfig;  //,*SRB2_logicalChannelConfig;
+        SRB_configList                 = radioResourceConfigDedicated->srb_ToAddModList;
+
+        AssertFatal(SRB_configList!=NULL,"SRB_configList is null\n");
+        for (int cnt = 0; cnt < (SRB_configList)->list.count; cnt++) {
+          if ((SRB_configList)->list.array[cnt]->srb_Identity == 1) {
+            SRB1_config = (SRB_configList)->list.array[cnt];
+
+            if (SRB1_config->logicalChannelConfig) {
+              if (SRB1_config->logicalChannelConfig->present ==
+                SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
+                SRB1_logicalChannelConfig = &SRB1_config->logicalChannelConfig->choice.explicitValue;
+              } else {
+                SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
+              }
+            } else {
+              SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
+            }
+          }
+        } // for
+        rrc_rlc_config_asn1_req(&ctxt,
+          SRB_configList,
+          (DRB_ToAddModList_t*) NULL,
+          (DRB_ToReleaseList_t*) NULL
 #if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
-				, (PMCH_InfoList_r9_t *) NULL,
-				0,0
+          , (PMCH_InfoList_r9_t *) NULL,
+          0,0
 #   endif
-				);
-	
-	// This should be somewhere in the f1ap_cudu_ue_inst_t
-	int macrlc_instance = 0; 
-
-	rnti_t rnti = f1ap_get_rnti_by_du_id(&f1ap_du_ue[0],du_ue_f1ap_id);
-	struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[macrlc_instance],rnti);
-      
-	eNB_RRC_UE_t *ue_p = &ue_context_p->ue_context; 
-	AssertFatal(ue_p->Srb0.Active == 1,"SRB0 is not active\n");
-
-	memcpy((void*)ue_p->Srb0.Tx_buffer.Payload,
-	       (void*)ie->value.choice.RRCContainer.buf,
-	       rrc_dl_sdu_len);
-
-	ue_p->Srb0.Tx_buffer.payload_size = rrc_dl_sdu_len;
-
-        rrc_mac_config_req_eNB(
-			       macrlc_instance,
-			       0, //primaryCC_id,
-			       0,0,0,0,0,
+          );
+
+      // This should be somewhere in the f1ap_cudu_ue_inst_t
+      int macrlc_instance = 0; 
+
+      rnti_t rnti = f1ap_get_rnti_by_du_id(&f1ap_du_ue[0],du_ue_f1ap_id);
+      struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[macrlc_instance],rnti);
+        
+      eNB_RRC_UE_t *ue_p = &ue_context_p->ue_context; 
+      AssertFatal(ue_p->Srb0.Active == 1,"SRB0 is not active\n");
+
+      memcpy((void*)ue_p->Srb0.Tx_buffer.Payload,
+             (void*)ie->value.choice.RRCContainer.buf,
+             rrc_dl_sdu_len);
+
+      ue_p->Srb0.Tx_buffer.payload_size = rrc_dl_sdu_len;
+
+      rrc_mac_config_req_eNB(
+          macrlc_instance,
+          0, //primaryCC_id,
+          0,0,0,0,0,
 #if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
-			       0,
+          0,
 #endif
-			       rnti,
-			       (BCCH_BCH_Message_t *) NULL,
-			       (RadioResourceConfigCommonSIB_t *) NULL,
+          rnti,
+          (BCCH_BCH_Message_t *) NULL,
+          (RadioResourceConfigCommonSIB_t *) NULL,
 #if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
-			       (RadioResourceConfigCommonSIB_t *) NULL,
+          (RadioResourceConfigCommonSIB_t *) NULL,
 #endif
-			       radioResourceConfigDedicated->physicalConfigDedicated,
+          radioResourceConfigDedicated->physicalConfigDedicated,
 #if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
-			       (SCellToAddMod_r10_t *)NULL,
-			       //(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
+          (SCellToAddMod_r10_t *)NULL,
+          //(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
 #endif
-			       (MeasObjectToAddMod_t **) NULL,
-			       radioResourceConfigDedicated->mac_MainConfig,
-			       1,
-			       SRB1_logicalChannelConfig,
-			       NULL, // measGapConfig,
-			       (TDD_Config_t *) NULL,
-			       NULL,
-			       (SchedulingInfoList_t *) NULL,
-			       0, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL
+          (MeasObjectToAddMod_t **) NULL,
+          radioResourceConfigDedicated->mac_MainConfig,
+          1,
+          SRB1_logicalChannelConfig,
+          NULL, // measGapConfig,
+          (TDD_Config_t *) NULL,
+          NULL,
+          (SchedulingInfoList_t *) NULL,
+          0, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL
 #if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
-			       , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL
+          , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL
 #endif
 #if (RRC_VERSION >= MAKE_VERSION(13, 0, 0))
-			       ,
-			       (SystemInformationBlockType1_v1310_IEs_t *)NULL
+          ,
+          (SystemInformationBlockType1_v1310_IEs_t *)NULL
 #endif
-			       );
-	  break;
-
-    default:
-      AssertFatal(1==0,
-		  "Unknown message\n");
-      break;
-      }
-
-    }
-  }
-  else if (srb_id == 1){ 
+          );
+          break;
+      } // case
 
-  }
-
-  else if (srb_id == 2){
+      default:
+        AssertFatal(1==0,
+        "Unknown message\n");
+        break;
+    }// switch case
+  } else if (srb_id == 1) { 
+//     rrc_rlc_config_asn1_req(&ctxt,
+//         SRB_configList,
+//         (DRB_ToAddModList_t*) NULL,
+//         (DRB_ToReleaseList_t*) NULL
+// #if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+//         , (PMCH_InfoList_r9_t *) NULL,
+//         0,0
+// #   endif
+//         );
+
+    LOG_I(DU_F1AP, "Received DL RRC Transfer on srb_id 1\n");
+    rlc_op_status_t    rlc_status;
+    boolean_t          ret             = TRUE;
+    mem_block_t       *pdcp_pdu_p      = NULL; 
+    pdcp_pdu_p = get_free_mem_block(rrc_dl_sdu_len, __func__);
+    memset(&pdcp_pdu_p->data[0], 0, rrc_dl_sdu_len);
+    memcpy(&pdcp_pdu_p->data[0], ie->value.choice.RRCContainer.buf, rrc_dl_sdu_len);
+
+    if (pdcp_pdu_p != NULL) {
+      rlc_status = rlc_data_req(&ctxt
+                                , 1
+                                , MBMS_FLAG_NO
+                                , srb_id
+                                , 0
+                                , 0
+                                , rrc_dl_sdu_len
+                                , pdcp_pdu_p
+#ifdef Rel14
+                                ,NULL
+                                ,NULL
+#endif
+                                );
+      switch (rlc_status) {
+        case RLC_OP_STATUS_OK:
+          LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
+          ret=TRUE;
+          break;
+
+        case RLC_OP_STATUS_BAD_PARAMETER:
+          LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
+          ret= FALSE;
+          break;
+
+        case RLC_OP_STATUS_INTERNAL_ERROR:
+          LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
+          ret= FALSE;
+          break;
+
+        case RLC_OP_STATUS_OUT_OF_RESSOURCES:
+          LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
+          ret= FALSE;
+          break;
+
+        default:
+          LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
+          ret= FALSE;
+          break;
+      } // switch case
+      return ret; 
+    } // if pdcp_pdu_p
+  
+  } else if (srb_id == 2) {
 
   }
 #endif
@@ -336,7 +391,6 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(const protocol_ctxt_t* const ctxt_pP,
                                     ) {
 
 
-
   rnti_t     rnti      = ctxt_pP->rnti;
 
   F1AP_F1AP_PDU_t                pdu;
@@ -402,6 +456,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(const protocol_ctxt_t* const ctxt_pP,
     LOG_E(DU_F1AP, "Failed to encode F1 setup request\n");
     return -1;
   }
+  LOG_W(DU_F1AP, "DU_send_UL_RRC_MESSAGE_TRANSFER on SRB %d for UE %x \n", rb_idP, rnti);
 
   du_f1ap_itti_send_sctp_data_req(instance, f1ap_du_data->assoc_id, buffer, len, f1ap_du_data->default_sctp_stream_id);
   return 0;
diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c
index bcd14cfa36..64450a1ae7 100644
--- a/openair2/F1AP/f1ap_du_task.c
+++ b/openair2/F1AP/f1ap_du_task.c
@@ -175,8 +175,9 @@ void *F1AP_DU_task(void *arg) {
 
      case F1AP_UL_RRC_MESSAGE: // from rrc
         LOG_I(DU_F1AP, "DU Task Received F1AP_UL_RRC_MESSAGE\n");
-        DU_send_UL_RRC_MESSAGE_TRANSFER(ITTI_MESSAGE_GET_INSTANCE(received_msg),
-                                        &F1AP_UL_RRC_MESSAGE(received_msg));
+        AssertFatal (1 == 0, "Should not be here!\n" );
+        //DU_send_UL_RRC_MESSAGE_TRANSFER(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+         //                               &F1AP_UL_RRC_MESSAGE(received_msg));
         break;
 
       case TERMINATE_MESSAGE:
diff --git a/openair2/F1AP/f1ap_handlers.c b/openair2/F1AP/f1ap_handlers.c
index 6d957e4ad6..b192cde0de 100644
--- a/openair2/F1AP/f1ap_handlers.c
+++ b/openair2/F1AP/f1ap_handlers.c
@@ -119,7 +119,7 @@ int f1ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
   }
 
   /* Calling the right handler */
-  LOG_I(DU_F1AP, "Calling handler with instance %d\n",instance);
+  LOG_I(F1AP, "Calling handler with instance %d\n",instance);
   ret = (*f1ap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1])
         (instance, assoc_id, stream, &pdu);
   ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_F1AP_F1AP_PDU, &pdu);
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index 3b4983a59d..bec37e1a29 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -49,9 +49,7 @@
 #include "platform_constants.h"
 #include "common/utils/LOG/vcd_signal_dumper.h"
 #include "msc.h"
-
-
-
+#include "common/ngran_types.h"
 
 #if defined(ENABLE_SECURITY)
 # include "UTIL/OSA/osa_defs.h"
@@ -411,53 +409,75 @@ boolean_t pdcp_data_req(
       free_mem_block(pdcp_pdu_p, __FUNCTION__);
       rlc_status = ack_result;
     }
-
-    else
+    else // SRB
 #endif /*UETARGET*/ 
     {
-      //It should never get here
-      rlc_status = rlc_data_req(ctxt_pP
-                              , srb_flagP
-                              , MBMS_FLAG_NO
-                              , rb_idP
-                              , muiP
-                              , confirmP
-                              , pdcp_pdu_size
-                              , pdcp_pdu_p
-      #ifdef Rel14
-                              ,NULL
-                              ,NULL
-      #endif
-                              );
-    }
-
-  }
+     LOG_I(PDCP, "Sending F1AP_DL_RRC_MESSAGE with ITTI\n");
 
-  switch (rlc_status) {
-  case RLC_OP_STATUS_OK:
-    LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
-    ret=TRUE;
-    break;
+      //It should never get here
+      if ((RC.rrc[ctxt_pP->module_id]->node_type  == ngran_eNB_CU)   ||
+        (RC.rrc[ctxt_pP->module_id]->node_type   == ngran_ng_eNB_CU)||
+        (RC.rrc[ctxt_pP->module_id]->node_type   == ngran_gNB_CU)  ) {
+        // DL transfer
+        MessageDef                            *message_p;
+        // Note: the acyual task must be TASK_PDCP_ENB, but this task is not created
+        message_p = itti_alloc_new_message (TASK_PDCP_ENB, F1AP_DL_RRC_MESSAGE);
+        F1AP_DL_RRC_MESSAGE (message_p).rrc_container =  &pdcp_pdu_p->data[0] ;
+        F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = pdcp_pdu_size;
+        F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id  = 0;  
+        F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id  = 0;
+        F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id  = 0xFFFFFFFF; // unknown
+        F1AP_DL_RRC_MESSAGE (message_p).rnti = ctxt_pP->rnti;
+        F1AP_DL_RRC_MESSAGE (message_p).srb_id = rb_idP;
+        F1AP_DL_RRC_MESSAGE (message_p).execute_duplication      = 1;
+        F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc      = 0;
+        itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p);
+        //CU_send_DL_RRC_MESSAGE_TRANSFER(ctxt_pP->module_id, message_p);
+        LOG_I(PDCP, "Send F1AP_DL_RRC_MESSAGE with ITTI\n");
+        ret=TRUE;
+
+      } else{
+        rlc_status = rlc_data_req(ctxt_pP
+                                  , srb_flagP
+                                  , MBMS_FLAG_NO
+                                  , rb_idP
+                                  , muiP
+                                  , confirmP
+                                  , pdcp_pdu_size
+                                  , pdcp_pdu_p
+#ifdef Rel14
+                                  ,NULL
+                                  ,NULL
+#endif
+                                  );
+        switch (rlc_status) {
+          case RLC_OP_STATUS_OK:
+            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
+            ret=TRUE;
+            break;
 
-  case RLC_OP_STATUS_BAD_PARAMETER:
-    LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
-    ret= FALSE;
-    break;
+          case RLC_OP_STATUS_BAD_PARAMETER:
+            LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
+            ret= FALSE;
+            break;
 
-  case RLC_OP_STATUS_INTERNAL_ERROR:
-    LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
-    ret= FALSE;
-    break;
+          case RLC_OP_STATUS_INTERNAL_ERROR:
+            LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
+            ret= FALSE;
+            break;
 
-  case RLC_OP_STATUS_OUT_OF_RESSOURCES:
-    LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
-    ret= FALSE;
-    break;
+          case RLC_OP_STATUS_OUT_OF_RESSOURCES:
+            LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
+            ret= FALSE;
+            break;
 
-  default:
-    LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
-    ret= FALSE;
-    break;
+          default:
+            LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
+            ret= FALSE;
+            break;
+        } // switch case
+      }
+    }
   }
 
   if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
@@ -978,6 +998,8 @@ void pdcp_update_stats(const protocol_ctxt_t* const  ctxt_pP){
     
   }
 }
+
+
 //-----------------------------------------------------------------------------
 void
 pdcp_run (
@@ -1020,6 +1042,7 @@ pdcp_run (
           RRC_DCCH_DATA_REQ (msg_p).frame, 
 	  0,
 	  RRC_DCCH_DATA_REQ (msg_p).eNB_index);
+
         LOG_I(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
               PROTOCOL_CTXT_ARGS(&ctxt),
               ITTI_MSG_NAME (msg_p),
@@ -1030,6 +1053,8 @@ pdcp_run (
               RRC_DCCH_DATA_REQ (msg_p).confirmp,
               RRC_DCCH_DATA_REQ (msg_p).mode);
 
+        log_dump(PDCP, RRC_DCCH_DATA_REQ (msg_p).sdu_p, RRC_DCCH_DATA_REQ (msg_p).sdu_size, LOG_DUMP_CHAR,"[MSG] pdcp run\n");
+
         result = pdcp_data_req (&ctxt,
                                 SRB_FLAG_YES,
                                 RRC_DCCH_DATA_REQ (msg_p).rb_id,
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/#rlc_am_receiver.c# b/openair2/LAYER2/RLC/AM_v9.3.0/#rlc_am_receiver.c#
new file mode 100644
index 0000000000..e6a7929024
--- /dev/null
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/#rlc_am_receiver.c#
@@ -0,0 +1,534 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#define RLC_AM_MODULE 1
+#define RLC_AM_RECEIVER_C 1
+#include "platform_types.h"
+//-----------------------------------------------------------------------------
+#include "assertions.h"
+#include "msc.h"
+#include "rlc.h"
+#include "rlc_am.h"
+#include "list.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "common/utils/LOG/log.h"
+
+
+//-----------------------------------------------------------------------------
+signed int
+rlc_am_get_data_pdu_infos(
+  const protocol_ctxt_t* const ctxt_pP,
+  const rlc_am_entity_t* const rlc_pP,
+  rlc_am_pdu_sn_10_t* header_pP,
+  int16_t total_sizeP,
+  rlc_am_pdu_info_t* pdu_info_pP)
+{
+    memset(pdu_info_pP, 0, sizeof (rlc_am_pdu_info_t));
+
+    int16_t          sum_li = 0;
+    pdu_info_pP->d_c = header_pP->b1 >> 7;
+    pdu_info_pP->num_li = 0;
+
+//Assertion(eNB)_PRAN_DesignDocument_annex No.766
+  if(pdu_info_pP->d_c == 0)
+  {
+     LOG_E(RLC, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id);
+     return -2;
+  }
+/*
+    AssertFatal (pdu_info_pP->d_c != 0, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id);
+*/
+    pdu_info_pP->rf  = (header_pP->b1 >> 6) & 0x01;
+    pdu_info_pP->p   = (header_pP->b1 >> 5) & 0x01;
+    pdu_info_pP->fi  = (header_pP->b1 >> 3) & 0x03;
+    pdu_info_pP->e   = (header_pP->b1 >> 2) & 0x01;
+    pdu_info_pP->sn  = header_pP->b2 +  (((uint16_t)(header_pP->b1 & 0x03)) << 8);
+
+    pdu_info_pP->header_size  = 2;
+
+    if (pdu_info_pP->rf) {
+      pdu_info_pP->lsf = (header_pP->data[0] >> 7) & 0x01;
+      pdu_info_pP->so  = header_pP->data[1] +  (((uint16_t)(header_pP->data[0] & 0x7F)) << 8);
+      pdu_info_pP->payload = &header_pP->data[2];
+      pdu_info_pP->header_size  += 2;
+    } else {
+      pdu_info_pP->payload = &header_pP->data[0];
+    }
+
+    if (pdu_info_pP->e) {
+      rlc_am_e_li_t      *e_li;
+      unsigned int li_length_in_bytes  = 1;
+      unsigned int li_to_read          = 1;
+
+      if (pdu_info_pP->rf) {
+        e_li = (rlc_am_e_li_t*)(&header_pP->data[2]);
+      } else {
+        e_li = (rlc_am_e_li_t*)(header_pP->data);
+      }
+
+      while (li_to_read)  {
+        li_length_in_bytes = li_length_in_bytes ^ 3;
+
+        if (li_length_in_bytes  == 2) {
+          pdu_info_pP->li_list[pdu_info_pP->num_li] = ((uint16_t)(e_li->b1 << 4)) & 0x07F0;
+          pdu_info_pP->li_list[pdu_info_pP->num_li] |= (((uint8_t)(e_li->b2 >> 4)) & 0x000F);
+          li_to_read = e_li->b1 & 0x80;
+          pdu_info_pP->header_size  += 2;
+        } else {
+          pdu_info_pP->li_list[pdu_info_pP->num_li] = ((uint16_t)(e_li->b2 << 8)) & 0x0700;
+          pdu_info_pP->li_list[pdu_info_pP->num_li] |=  e_li->b3;
+          li_to_read = e_li->b2 & 0x08;
+          e_li++;
+          pdu_info_pP->header_size  += 1;
+        }
+
+        sum_li += pdu_info_pP->li_list[pdu_info_pP->num_li];
+        pdu_info_pP->num_li = pdu_info_pP->num_li + 1;
+
+        if (pdu_info_pP->num_li > RLC_AM_MAX_SDU_IN_PDU) {
+          LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[GET PDU INFO]  SN %04d TOO MANY LIs ",
+                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
+                pdu_info_pP->sn);
+          return -2;
+        }
+      }
+
+      if (li_length_in_bytes  == 2) {
+        pdu_info_pP->payload = &e_li->b3;
+      } else {
+        pdu_info_pP->payload = &e_li->b1;
+      }
+    }
+
+    pdu_info_pP->payload_size = total_sizeP - pdu_info_pP->header_size;
+
+    if (pdu_info_pP->payload_size > sum_li) {
+      pdu_info_pP->hidden_size = pdu_info_pP->payload_size - sum_li;
+    }
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+void
+rlc_am_display_data_pdu_infos(
+  const protocol_ctxt_t* const ctxt_pP,
+  rlc_am_entity_t * const rlc_pP,
+  rlc_am_pdu_info_t* pdu_info_pP)
+{
+  int num_li;
+
+  if (pdu_info_pP->d_c) {
+    if (pdu_info_pP->rf) {
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] RX DATA PDU SN %04d FI %1d SO %05d LSF %01d POLL %1d ",
+            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
+            pdu_info_pP->sn,
+            pdu_info_pP->fi,
+            pdu_info_pP->so,
+            pdu_info_pP->lsf, pdu_info_pP->p);
+    } else {
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] RX DATA PDU SN %04d FI %1d POLL %1d ",
+            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
+            pdu_info_pP->sn,
+            pdu_info_pP->fi,
+            pdu_info_pP->p);
+    }
+
+    for (num_li = 0; num_li < pdu_info_pP->num_li; num_li++) {
+      LOG_D(RLC, "LI %05d ",  pdu_info_pP->li_list[num_li]);
+    }
+
+    if (pdu_info_pP->hidden_size > 0) {
+      LOG_D(RLC, "hidden size %05d ",  pdu_info_pP->hidden_size);
+    }
+
+    LOG_D(RLC, "\n");
+  } else {
+    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] ERROR RX CONTROL PDU\n",
+          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
+  }
+}
+// assumed the sn of the tb_p is equal to VR(MS)
+//-----------------------------------------------------------------------------
+void
+rlc_am_rx_update_vr_ms(
+  const protocol_ctxt_t* const ctxt_pP,
+  rlc_am_entity_t * const rlc_pP,
+  mem_block_t* tb_pP)
+{
+  //rlc_am_pdu_info_t* pdu_info_p        = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
+  rlc_am_pdu_info_t* pdu_info_cursor_p = NULL;
+  mem_block_t*       cursor_p;
+
+  cursor_p = tb_pP;
+
+  if (cursor_p) {
+    do {
+      pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
+
+      if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) ||
+          (rlc_pP->vr_ms != pdu_info_cursor_p->sn)) {
+
+#if TRACE_RLC_AM_RX
+        LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(MS)] UPDATED VR(MS) %04d -> %04d\n",
+              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
+              rlc_pP->vr_ms, pdu_info_cursor_p->sn);
+#endif
+
+        return;
+      }
+
+      rlc_pP->vr_ms = RLC_AM_NEXT_SN(pdu_info_cursor_p->sn);
+      cursor_p = cursor_p->next;
+    } while ((cursor_p != NULL) && (rlc_pP->vr_ms != rlc_pP->vr_h));
+
+  }
+}
+// assumed the sn of the tb_p is equal to VR(R)
+//-----------------------------------------------------------------------------
+void
+rlc_am_rx_update_vr_r(
+  const protocol_ctxt_t* const ctxt_pP,
+  rlc_am_entity_t * const rlc_pP,
+  mem_block_t* tb_pP)
+{
+  rlc_am_pdu_info_t* pdu_info_cursor_p = NULL;
+  mem_block_t*       cursor_p;
+
+  cursor_p = tb_pP;
+
+  if (cursor_p) {
+    do {
+      pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
+
+      if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) ||
+          (rlc_pP->vr_r != pdu_info_cursor_p->sn)) {
+        return;
+      }
+
+#if TRACE_RLC_AM_RX
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(R)] UPDATED VR(R) %04d -> %04d\n",
+            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
+            rlc_pP->vr_r,
+            (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK);
+#endif
+
+      if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.rf == 1) {
+        if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.lsf == 1) {
+          rlc_pP->vr_r = (rlc_pP->vr_r + 1) & RLC_AM_SN_MASK;
+        }
+      } else  {
+        rlc_pP->vr_r = (rlc_pP->vr_r + 1) & RLC_AM_SN_MASK;
+      }
+
+      cursor_p = cursor_p->next;
+    } while (cursor_p != NULL);
+
+    //rlc_pP->vr_r = (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK;
+  }
+}
+//-----------------------------------------------------------------------------
+void
+rlc_am_receive_routing (
+  const protocol_ctxt_t* const ctxt_pP,
+  rlc_am_entity_t * const rlc_pP,
+  struct mac_data_ind data_indP)
+{
+  mem_block_t           *tb_p             = NULL;
+  uint8_t               *first_byte_p     = NULL;
+  sdu_size_t             tb_size_in_bytes;
+  RLC_AM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
+
+  while ((tb_p = list_remove_head (&data_indP.data))) {
+    first_byte_p = ((struct mac_tb_ind *) (tb_p->data))->data_ptr;
+    tb_size_in_bytes = ((struct mac_tb_ind *) (tb_p->data))->size;
+
+    if (tb_size_in_bytes > 0) {
+      if ((*first_byte_p & 0x80) == 0x80) {
+        rlc_pP->stat_rx_data_bytes += tb_size_in_bytes;
+        rlc_pP->stat_rx_data_pdu   += 1;
+        rlc_am_receive_process_data_pdu (ctxt_pP, rlc_pP, tb_p, first_byte_p, tb_size_in_bytes);
+      } else {
+        rlc_pP->stat_rx_control_bytes += tb_size_in_bytes;
+        rlc_pP->stat_rx_control_pdu += 1;
+        rlc_am_receive_process_control_pdu (ctxt_pP, rlc_pP, tb_p, &first_byte_p, &tb_size_in_bytes);
+        // Test if remaining bytes not processed (up to know, highest probability is bug in MAC)
+//Assertion(eNB)_PRAN_DesignDocument_annex No.767
+  if(tb_size_in_bytes != 0)
+  {
+     LOG_E(RLC, "Remaining %d bytes following a control PDU\n",
+             tb_size_in_bytes);
+  }
+/*
+        AssertFatal( tb_size_in_bytes == 0,
+                     "Remaining %d bytes following a control PDU",
+                     tb_size_in_bytes);
+*/
+      }
+
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RX ROUTING] VR(R)=%03d VR(MR)=%03d\n",
+            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
+            rlc_pP->vr_r,
+            rlc_pP->vr_mr);
+    }
+  } // end while
+  RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
+}
+//-----------------------------------------------------------------------------
+void
+rlc_am_receive_process_data_pdu (
+  const protocol_ctxt_t* const ctxt_pP,
+  rlc_am_entity_t * const rlc_pP,
+  mem_block_t* tb_pP,
+  uint8_t* first_byte_pP,
+  uint16_t tb_size_in_bytesP)
+{
+  // 5.1.3.2 Receive operations
+  // 5.1.3.2.1 General
+  // The receiving side of an AM RLC entity shall maintain a receiving window according to state variables VR(R) and
+  // VR(MR) as follows:
+  //     - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
+  //     - a SN falls outside of the receiving window otherwise.
+  //
+  // When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity shall:
+  // - either discard the received RLC data PDU or place it in the reception buffer (see sub clause 5.1.3.2.2);
+  // - if the received RLC data PDU was placed in the reception buffer:
+  //     - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop t-Reordering as
+  //       needed (see sub clause 5.1.3.2.3).
+  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
+  //     - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
+
+
+  // 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
+  // When a RLC data PDU is received from lower layer, where the RLC data PDU contains byte segment numbers y to z of
+  // an AMD PDU with SN = x, the receiving side of an AM RLC entity shall:
+  //     - if x falls outside of the receiving window; or
+  //     - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
+  //         - discard the received RLC data PDU;
+  //     - else:
+  //         - place the received RLC data PDU in the reception buffer;
+  //         - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
+  //             - discard the duplicate byte segments.
+  rlc_am_pdu_info_t*  pdu_info_p         = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
+  rlc_am_pdu_sn_10_t* rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)first_byte_pP;
+  rlc_am_rx_pdu_status_t pdu_status		= RLC_AM_DATA_PDU_STATUS_OK;
+  boolean_t		reassemble = false;
+
+  if (rlc_am_get_data_pdu_infos(ctxt_pP,rlc_pP, rlc_am_pdu_sn_10_p, tb_size_in_bytesP, pdu_info_p) >= 0) {
+
+    ((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received = 0;
+
+      if (RLC_AM_SN_IN_WINDOW(pdu_info_p->sn, rlc_pP->vr_r)) {
+
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%04d] VR(R) %04d VR(H) %04d VR(MR) %04d VR(MS) %04d VR(X) %04d\n",
+            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
+            pdu_info_p->sn,
+            rlc_pP->vr_r,
+            rlc_pP->vr_h,
+            rlc_pP->vr_mr,
+            rlc_pP->vr_ms,
+            rlc_pP->vr_x);
+
+      pdu_status = rlc_am_rx_list_check_duplicate_insert_pdu(ctxt_pP, rlc_pP,tb_pP);
+      if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) {
+        rlc_pP->stat_rx_data_pdu_dropped     += 1;
+        rlc_pP->stat_rx_data_bytes_dropped   += tb_size_in_bytesP;
+        LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  PDU DISCARDED CAUSE=%d SN=%d\n",
+              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_status,pdu_info_p->sn);
+#if RLC_STOP_ON_LOST_PDU
+        AssertFatal( 0 == 1,
+                     PROTOCOL_RLC_AM_CTXT_FMT" LOST PDU DETECTED\n",
+                     PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
+#endif
+      } else {
+        // 5.1.3.2.3
+        // Actions when a RLC data PDU is placed in the reception buffer
+        //
+        // When a RLC data PDU with SN = x is placed in the reception buffer, the receiving side of an AM RLC entity shall:
+        //     - if x >= VR(H)
+        //         - update VR(H) to x+ 1;
+        //
+        //     - if all byte segments of the AMD PDU with SN = VR(MS) are received:
+        //         - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for which not all byte segments
+        //           have been received;
+        //
+        //     - if x = VR(R):
+        //         - if all byte segments of the AMD PDU with SN = VR(R) are received:
+        //             - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which not all byte segments
+        //               have been received;
+        //             - update VR(MR) to the updated VR(R) + AM_Window_Size;
+        //
+        //         - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside of the receiving
+        //           window and in-sequence byte segments of the AMD PDU with SN = VR(R), remove RLC headers when
+        //           doing so and deliver the reassembled RLC SDUs to upper layer in sequence if not delivered before;
+        //
+        //     - if t-Reordering is running:
+        //         - if VR(X) = VR(R); or
+        //         - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
+        //             - stop and reset t-Reordering;
+        //
+        //     - if t-Reordering is not running (includes the case t-Reordering is stopped due to actions above):
+        //         - if VR (H) > VR(R):
+        //             - start t-Reordering;
+        //             - set VR(X) to VR(H).
+
+
+#if TRACE_RLC_AM_RX
+        LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  RX LIST AFTER INSERTION:\n",
+              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
+        rlc_am_rx_list_display(rlc_pP, "rlc_am_receive_process_data_pdu AFTER INSERTION ");
+#endif
+
+        /* 1) Update vrH if sn >= vrH */
+        if (RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) >= RLC_AM_DIFF_SN(rlc_pP->vr_h,rlc_pP->vr_r))
+        {
+        	rlc_pP->vr_h = RLC_AM_NEXT_SN(pdu_info_p->sn);
+        }
+
+        rlc_am_rx_check_all_byte_segments(ctxt_pP, rlc_pP, tb_pP);
+
+        /* 2) Reordering Window Processing: Update vr_ms if sn = vr_ms and all bytes received for sn */
+        if ((pdu_info_p->sn == rlc_pP->vr_ms) && (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received)) {
+          rlc_am_rx_update_vr_ms(ctxt_pP, rlc_pP,  tb_pP);
+        }
+
+        if (pdu_info_p->sn == rlc_pP->vr_r) {
+mem_block_t*       cursor_p                    = rlc_pP->receiver_buffer.head;
+rlc_am_rx_pdu_management_t * pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data);
+if( (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received) == (pdu_cursor_mgnt_p->all_segments_received)){
+          if (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received) {
+            rlc_am_rx_update_vr_r(ctxt_pP, rlc_pP, tb_pP);
+            rlc_pP->vr_mr = (rlc_pP->vr_r + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
+          }
+          reassemble = rlc_am_rx_check_vr_reassemble(ctxt_pP, rlc_pP);
+          //TODO : optimization : check whether a reassembly is needed by looking at LI, FI, SO, etc...
+}else{
+  LOG_E(RLC, "BAD all_segments_received!!! discard buffer!!!\n");
+  /* Discard received block if out of window, duplicate or header error */
+  free_mem_block (tb_pP, __func__);
+}
+        }
+
+        //FNA: fix check VrX out of receiving window
+        if ((rlc_pP->t_reordering.running) || ((rlc_pP->t_reordering.ms_duration == 0) && (rlc_pP->vr_x != RLC_SN_UNDEFINED))) {
+          if ((rlc_pP->vr_x == rlc_pP->vr_r) || (!(RLC_AM_SN_IN_WINDOW(rlc_pP->vr_x, rlc_pP->vr_r)) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
+            rlc_am_stop_and_reset_timer_reordering(ctxt_pP, rlc_pP);
+            rlc_pP->vr_x = RLC_SN_UNDEFINED;
+          }
+        }
+
+        if (!(rlc_pP->t_reordering.running)) {
+          if (rlc_pP->vr_h != rlc_pP->vr_r) { // - if VR (H) > VR(R) translated to - if VR (H) != VR(R)
+            rlc_pP->vr_x = rlc_pP->vr_h;
+            if (rlc_pP->t_reordering.ms_duration != 0) {
+                rlc_am_start_timer_reordering(ctxt_pP, rlc_pP);
+            }
+            else {
+            	/* specific case for no timer reordering configured */
+            	/* reordering window directly advances with vrH */
+            	rlc_pP->vr_ms = rlc_pP->vr_h;
+
+				/* Trigger a Status and clear any existing Delay Flag */
+				RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_T_REORDERING);
+				RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
+				rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
+            }
+          }
+        }
+      }
+
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%04d] NEW VR(R) %04d VR(H) %04d  VR(MS) %04d  VR(MR) %04d VR(X) %04d reassemble=%d\n",
+            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
+            pdu_info_p->sn,
+            rlc_pP->vr_r,
+            rlc_pP->vr_h,
+            rlc_pP->vr_ms,
+            rlc_pP->vr_mr,
+            rlc_pP->vr_x,
+            reassemble);
+      } else {
+      rlc_pP->stat_rx_data_pdu_out_of_window     += 1;
+      rlc_pP->stat_rx_data_bytes_out_of_window   += tb_size_in_bytesP;
+      pdu_status = RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW;
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  PDU OUT OF RX WINDOW, DISCARDED, SN=%d\n",
+            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn);
+    }
+
+      /* 3) Check for triggering a Tx Status PDU if a poll is received or if a pending status was delayed */
+      if ((pdu_info_p->p) && (pdu_status < RLC_AM_DATA_PDU_STATUS_BUFFER_FULL)) {
+        LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  POLL BIT SET, STATUS REQUESTED:\n",
+              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
+
+        /* Polling Info Saving for In and Out of Window PDU */
+        /* avoid multi status trigger */
+        if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) ||
+            !(RLC_AM_GET_STATUS(rlc_pP->status_requested,(RLC_AM_STATUS_TRIGGERED_POLL | RLC_AM_STATUS_TRIGGERED_T_REORDERING))))
+        {
+            RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_POLL);
+
+            if ((pdu_status != RLC_AM_DATA_PDU_STATUS_OK) || ((pdu_status == RLC_AM_DATA_PDU_STATUS_OK) &&
+                                                           (!(RLC_AM_SN_IN_WINDOW(pdu_info_p->sn,rlc_pP->vr_r)) ||
+                                                            (RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)))
+                                                          )
+               )
+            {
+                /* Conditions are met for sending a Status Report */
+                /* Then clear Delay Flag and reset its corresponding sn */
+                RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
+                rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
+            }
+            else if (rlc_pP->sn_status_triggered_delayed == RLC_SN_UNDEFINED)
+            {
+                /* Delay status trigger if pdustatus OK and sn>= vr_ms */
+                /* Note: vr_r and vr_ms have been updated */
+                RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
+                rlc_pP->sn_status_triggered_delayed = pdu_info_p->sn;
+            }
+        }
+      }
+
+      /* ReEnable a previously delayed Status Trigger if PDU discarded or */
+      /* sn no more in RxWindow due to RxWindow advance or sn < vr_ms */
+      if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) &&
+          (pdu_status == RLC_AM_DATA_PDU_STATUS_OK)  &&
+          (!(RLC_AM_SN_IN_WINDOW(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r)) ||
+           (RLC_AM_DIFF_SN(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)))
+         )
+      {
+          RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
+          rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
+      }
+
+
+  } else {
+	  pdu_status = RLC_AM_DATA_PDU_STATUS_HEADER_ERROR;
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  PDU DISCARDED BAD HEADER FORMAT SN=%d\n",
+            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn);
+  }
+
+  if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) {
+	  /* Discard received block if out of window, duplicate or header error */
+      free_mem_block (tb_pP, __func__);
+  }
+  else if (reassemble) {
+	  /* Reassemble SDUs */
+	  rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP);
+  }
+}
diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c
index b3d8d36dc5..ac53afa40b 100644
--- a/openair2/LAYER2/RLC/rlc_mac.c
+++ b/openair2/LAYER2/RLC/rlc_mac.c
@@ -260,12 +260,12 @@ void mac_rlc_data_ind     (
 #ifdef DEBUG_MAC_INTERFACE
 
   if (num_tbP) {
-    LOG_I(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_IND on channel %d (%d), rb max %d, Num_tb %d\n",
+    LOG_I(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_IND on channel %d (%d), rb max %d, tb_sizeP %d\n",
           PROTOCOL_CTXT_ARGS(&ctxt),
           channel_idP,
           RLC_MAX_LC,
           NB_RB_MAX,
-          num_tbP);
+          tb_sizeP);
   }
 
 #endif // DEBUG_MAC_INTERFACE
diff --git a/openair2/RRC/LTE/L2_interface_common.c b/openair2/RRC/LTE/L2_interface_common.c
index b03b36a557..e8aece9f29 100644
--- a/openair2/RRC/LTE/L2_interface_common.c
+++ b/openair2/RRC/LTE/L2_interface_common.c
@@ -94,6 +94,8 @@ rrc_data_req(
     RRC_DCCH_DATA_REQ (message_p).confirmp  = confirmP;
     RRC_DCCH_DATA_REQ (message_p).sdu_size  = sdu_sizeP;
     RRC_DCCH_DATA_REQ (message_p).sdu_p     = message_buffer;
+    //memcpy (RRC_DCCH_DATA_REQ (message_p).sdu_p, buffer_pP, sdu_sizeP);
+
     RRC_DCCH_DATA_REQ (message_p).mode      = modeP;
     RRC_DCCH_DATA_REQ (message_p).module_id = ctxt_pP->module_id;
     RRC_DCCH_DATA_REQ (message_p).rnti      = ctxt_pP->rnti;
@@ -103,6 +105,10 @@ rrc_data_req(
       ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE,
       ctxt_pP->instance,
       message_p);
+    LOG_I(RRC,"sent RRC_DCCH_DATA_REQ to TASK_PDCP_ENB\n");
+    // RS/BK: Fix ME
+    pdcp_run(ctxt_pP);
+
     return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway.
 
   }
diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c
index 4c54f75d29..0dbbd7d747 100644
--- a/openair2/RRC/LTE/rrc_eNB.c
+++ b/openair2/RRC/LTE/rrc_eNB.c
@@ -1167,8 +1167,10 @@ rrc_eNB_generate_SecurityModeCommand(
     rrc_eNB_mui,
     size);
 
- if ((RC.rrc[ctxt_pP->module_id]->node_type  == ngran_eNB) ||
-	(RC.rrc[ctxt_pP->module_id]->node_type  == ngran_ng_eNB)) {
+ if ((RC.rrc[ctxt_pP->module_id]->node_type  != ngran_eNB_DU) ||
+	   (RC.rrc[ctxt_pP->module_id]->node_type  != ngran_gNB_DU)) {
+  LOG_I(RRC,"calling rrc_data_req :securityModeCommand\n");
+
     rrc_data_req(
 	       ctxt_pP,
 	       DCCH,
diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c
index 15ea141301..1f5a8772d4 100644
--- a/openair2/RRC/LTE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c
@@ -923,7 +923,6 @@ rrc_eNB_process_S1AP_DOWNLINK_NAS(
                S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
 
     LOG_DUMPMSG(RRC,DEBUG_RRC,buffer,length,"[MSG] RRC DL Information Transfer\n");
-
     /* 
      * switch UL or DL NAS message without RRC piggybacked to SRB2 if active. 
      */
diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c
index aea5a5ab99..793eb90740 100644
--- a/targets/COMMON/create_tasks.c
+++ b/targets/COMMON/create_tasks.c
@@ -85,6 +85,10 @@ int create_tasks(uint32_t enb_nb)
     if (enb_nb > 0) {
       rc = itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL);
       AssertFatal(rc >= 0, "Create task for CU F1AP failed\n");
+      //RS/BK: Fix me!
+      rc = itti_create_task (TASK_L2L1, l2l1_task, NULL);
+      AssertFatal(rc >= 0, "Create task for L2L1 failed\n");
+
     }
     /* fall through */
   case ngran_eNB:
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 2145e5d98c..34ac829f5c 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -1082,6 +1082,16 @@ int main( int argc, char **argv )
     RCconfig_L1();
   }
 
+
+  if (RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU) {
+    protocol_ctxt_t ctxt;
+    ctxt.module_id = 0 ;
+    ctxt.instance = 0;
+    ctxt.rnti = 0;
+    ctxt.enb_flag = 1;
+    pdcp_run(&ctxt);
+  }
+
   /* start threads if only L1 or not a CU */
   if (RC.nb_inst == 0 ||
       !(RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU)) {
-- 
GitLab