From e46fb846846d0cffcbcd96335b6b463c58d3d9e9 Mon Sep 17 00:00:00 2001
From: nguyennd <nguyennd@eurecom.fr>
Date: Fri, 13 Sep 2013 15:29:47 +0000
Subject: [PATCH] Update and validate the eMBMS operation and its interface to
 OTG, pre-ci test passed

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4148 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 openair1/SCHED/phy_procedures_lte_eNb.c       |   2 +-
 openair1/SCHED/phy_procedures_lte_ue.c        |   1 +
 openair1/SIMULATION/LTE_PHY/Makefile          |   2 +-
 openair2/COMMON/platform_constants.h          |   2 +-
 openair2/LAYER2/MAC/config.c                  |  18 +-
 openair2/LAYER2/MAC/defs.h                    |   4 +-
 openair2/LAYER2/MAC/eNB_scheduler.c           | 123 ++--
 openair2/LAYER2/MAC/main.c                    |   4 +-
 openair2/LAYER2/MAC/ue_procedures.c           |  28 +-
 openair2/LAYER2/PDCP_v10.1.0/pdcp.c           |   4 +-
 openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c      |  19 +-
 .../LAYER2/RLC/UM_v9.3.0/rlc_um_segment.c     |   2 +
 openair2/LAYER2/RLC/rlc.c                     |  12 +-
 openair2/LAYER2/RLC/rlc_rrc.c                 | 111 ++--
 openair2/RRC/LITE/MESSAGES/Makefile           |   1 +
 openair2/RRC/LITE/MESSAGES/asn1_msg.c         |  28 +-
 openair2/RRC/LITE/rrc_UE.c                    |  33 +-
 openair2/RRC/LITE/rrc_eNB.c                   |  46 +-
 openair2/UTIL/OTG/otg.c                       |   2 +
 openair2/UTIL/OTG/otg_defs.h                  |   4 +
 openair2/UTIL/OTG/otg_kpi.c                   | 568 +++++++++++-------
 openair2/UTIL/OTG/otg_rx.c                    |  14 +-
 openair2/UTIL/OTG/otg_tx.c                    |  37 +-
 targets/SIMU/USER/oaisim.c                    |   2 +-
 targets/SIMU/USER/oaisim_functions.c          |  84 ++-
 25 files changed, 688 insertions(+), 463 deletions(-)

diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 1b7f71f7c7e..09e359dc637 100755
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -73,7 +73,7 @@
 
 extern inline unsigned int taus(void);
 extern int exit_openair;
-extern void do_OFDM_mod(mod_sym_t **txdataF, s32 **txdata, uint32_t frame, u16 next_slot, LTE_DL_FRAME_PARMS *frame_parms);
+//extern void do_OFDM_mod(mod_sym_t **txdataF, s32 **txdata, uint32_t frame, u16 next_slot, LTE_DL_FRAME_PARMS *frame_parms);
 
 
 unsigned char dlsch_input_buffer[2700] __attribute__ ((aligned(16)));
diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c
index f8f95733292..314fc765619 100755
--- a/openair1/SCHED/phy_procedures_lte_ue.c
+++ b/openair1/SCHED/phy_procedures_lte_ue.c
@@ -2989,6 +2989,7 @@ int phy_procedures_UE_RX(u8 last_slot, PHY_VARS_UE *phy_vars_ue,u8 eNB_id,u8 abs
 	
 	if (ret == (1+phy_vars_ue->dlsch_ue_MCH[0]->max_turbo_iterations)) {
 	  phy_vars_ue->dlsch_mch_errors[0]++;
+	  LOG_D(PHY,"number of errors: %d\n",phy_vars_ue->dlsch_mch_errors[0]);
 	  LOG_D(PHY,"[UE %d] Frame %d, subframe %d: PMCH in error, not passing to L2 (TBS %d, iter %d,G %d)\n",phy_vars_ue->Mod_id,((last_slot>>1)==9?-1:0)+phy_vars_ue->frame,last_slot>>1,phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->TBS>>3,phy_vars_ue->dlsch_ue_MCH[0]->max_turbo_iterations,phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->G);
 	  dump_mch(phy_vars_ue,0,phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->G,(last_slot>>1));
 #ifdef DEBUG_DLSCH	  
diff --git a/openair1/SIMULATION/LTE_PHY/Makefile b/openair1/SIMULATION/LTE_PHY/Makefile
index f1ede21f837..b3b634302d9 100644
--- a/openair1/SIMULATION/LTE_PHY/Makefile
+++ b/openair1/SIMULATION/LTE_PHY/Makefile
@@ -9,7 +9,7 @@ OPENAIR1_TOP = $(OPENAIR1_DIR)
 OPENAIR2_TOP = $(OPENAIR2_DIR)
 OPENAIR3 = $(OPENAIR3_DIR)
 
-CFLAGS = -g -O2 -Wno-strict-aliasing -rdynamic -Wall -DPHYSIM -DNODE_RG -DUSER_MODE -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -DPHY_CONTEXT=1 $(CPUFLAGS) -DMALLOC_CHECK_=1 # -Wno-packed-bitfield-compat
+CFLAGS = -g -O -Wno-strict-aliasing -rdynamic -Wall -DPHYSIM -DNODE_RG -DUSER_MODE -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -DPHY_CONTEXT=1 $(CPUFLAGS) -DMALLOC_CHECK_=1 # -Wno-packed-bitfield-compat
 
 
 # DCI Debug
diff --git a/openair2/COMMON/platform_constants.h b/openair2/COMMON/platform_constants.h
index 73556d25bd7..7266b48803c 100755
--- a/openair2/COMMON/platform_constants.h
+++ b/openair2/COMMON/platform_constants.h
@@ -37,7 +37,7 @@
  */
 #   define MAX_IP_PACKET_SIZE          1512
 # else
-#   define MAX_IP_PACKET_SIZE          1500
+#   define MAX_IP_PACKET_SIZE          1500 // 3000
 # endif
 #endif
 // overwrite the previous deinitions
diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c
index fb8a539ee75..a70c982778e 100644
--- a/openair2/LAYER2/MAC/config.c
+++ b/openair2/LAYER2/MAC/config.c
@@ -70,7 +70,7 @@ int rrc_mac_config_req(u8 Mod_id,u8 eNB_flag,u8 UE_id,u8 eNB_index,
       mac_xface->phy_config_sib1_ue(Mod_id,eNB_index,tdd_Config,*SIwindowsize,*SIperiod);
   } 
 
-  if (radioResourceConfigCommon) {
+  if (radioResourceConfigCommon!=NULL) {
     if (eNB_flag==1) {
       LOG_I(MAC,"[CONFIG]SIB2/3 Contents (partial)\n");
       
@@ -185,7 +185,7 @@ int rrc_mac_config_req(u8 Mod_id,u8 eNB_flag,u8 UE_id,u8 eNB_index,
   }
 
   if (eNB_flag == 0) {
-    if (measObj!= NULL) 
+    if (measObj!= NULL) {
       if (measObj[0]!= NULL){
 	UE_mac_inst[Mod_id].n_adj_cells = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.count;
 	LOG_I(MAC,"Number of adjacent cells %d\n",UE_mac_inst[Mod_id].n_adj_cells);
@@ -195,6 +195,7 @@ int rrc_mac_config_req(u8 Mod_id,u8 eNB_flag,u8 UE_id,u8 eNB_index,
 	}
 	mac_xface->phy_config_meas_ue(Mod_id,eNB_index,UE_mac_inst[Mod_id].n_adj_cells,UE_mac_inst[Mod_id].adj_cell_id);
       }
+    }
   }
 
 
@@ -243,8 +244,13 @@ int rrc_mac_config_req(u8 Mod_id,u8 eNB_flag,u8 UE_id,u8 eNB_index,
 
   
   if (pmch_InfoList != NULL) {
+
+    //    LOG_I(MAC,"DUY: lcid when entering rrc_mac config_req is %02d\n",(pmch_InfoList->list.array[0]->mbms_SessionInfoList_r9.list.array[0]->logicalChannelIdentity_r9));
+
     if (eNB_flag == 1) {
+
       LOG_I(MAC, "[CONFIG] Number of PMCH in this MBSFN Area %d\n", pmch_InfoList->list.count);
+
       for (i =0; i< pmch_InfoList->list.count; i++) {
 	eNB_mac_inst[Mod_id].pmch_Config[i] = &pmch_InfoList->list.array[i]->pmch_Config_r9;
 
@@ -256,17 +262,15 @@ int rrc_mac_config_req(u8 Mod_id,u8 eNB_flag,u8 UE_id,u8 eNB_index,
 	      eNB_mac_inst[Mod_id].pmch_Config[i]->dataMCS_r9); 
 
 	// MBMS session info list in each MCH
-	//	for (j=0;j< pmch_InfoList->list.array[i]->mbms_SessionInfoList_r9.list.count;j++) {
-	  eNB_mac_inst[Mod_id].mbms_SessionList[i] = &pmch_InfoList->list.array[i]->mbms_SessionInfoList_r9;
-	  LOG_I(MAC, "PMCH[%d] Number of session (MTCH) is: %d\n",i, eNB_mac_inst[Mod_id].mbms_SessionList[i]->list.count);
-	  //	}
+	eNB_mac_inst[Mod_id].mbms_SessionList[i] = &pmch_InfoList->list.array[i]->mbms_SessionInfoList_r9;
+	LOG_I(MAC, "PMCH[%d] Number of session (MTCH) is: %d\n",i, eNB_mac_inst[Mod_id].mbms_SessionList[i]->list.count);
       }
     }
     else { // UE  
       LOG_I(MAC, "[UE %d] Configuring PMCH_config from MCCH MESSAGE \n",Mod_id);
       for (i =0; i< pmch_InfoList->list.count; i++) {
 	UE_mac_inst[Mod_id].pmch_Config[i] = &pmch_InfoList->list.array[i]->pmch_Config_r9;
-	LOG_I(MAC, "[UE %d] PMCH[%d]: MCH_Scheduling_Period = %ld\n", Mod_id, 
+	LOG_I(MAC, "[UE %d] PMCH[%d]: MCH_Scheduling_Period = %ld\n", Mod_id, i,
 	      UE_mac_inst[Mod_id].pmch_Config[i]->mch_SchedulingPeriod_r9); 
       }
       UE_mac_inst[Mod_id].mcch_status = 1;
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index 2ed4f7de46d..bbb04536e63 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -86,8 +86,8 @@
 
 
 #define MCCH 4 // MCCH
+#define MTCH 1 // MTCH
 
-#define MTCH 5 // MTCH
 #ifdef Rel10
 
 // Mask for identifying subframe for MBMS 
@@ -107,7 +107,7 @@
 #define MAX_PMCH_perMBSFN 15
 
 #define MCCH_PAYLOAD_SIZE_MAX 128
-#define MCH_PAYLOAD_SIZE_MAX 1024
+//#define MCH_PAYLOAD_SIZE_MAX 16384// this value is using in case mcs and TBS index are high
 #endif
 
 #ifdef USER_MODE
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index 084234755c5..1c5b929e4e0 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -1091,6 +1091,12 @@ int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) {
   int mcch_mcs;
   u16 TBS,j,padding=0,post_padding=0;
   mac_rlc_status_resp_t rlc_status;
+  int num_mtch;
+  int msi_length,i;
+  unsigned char sdu_lcids[11], num_sdus=0, offset=0;
+  u16 sdu_lengths[11], sdu_length_total=0;
+  unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; // check the max value, this is for dlsch only
+
   switch (eNB_mac_inst[Mod_id].mbsfn_AreaInfo[0]->mcch_Config_r9.signallingMCS_r9) {
   case 0:
     mcch_mcs = 2;
@@ -1259,22 +1265,17 @@ int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) {
     }
   }
   
-  // Calculate the mcs
+    // Calculate the mcs
   if ((msi_flag==1) || (mcch_flag==1)) {
     eNB_mac_inst[Mod_id].MCH_pdu.mcs = mcch_mcs;
   }
   else if (mtch_flag == 1) { // only MTCH in this subframe 
     eNB_mac_inst[Mod_id].MCH_pdu.mcs = eNB_mac_inst[Mod_id].pmch_Config[0]->dataMCS_r9;
   }
-
+  
   
   // 2nd: Create MSI, get MCCH from RRC and MTCHs from RLC
-  int num_mtch;
-  int msi_length,i;
-  unsigned char sdu_lcids[11], num_sdus=0, offset;
-  u16 sdu_lengths[11], sdu_length_total=0;
-  unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; // check the max value, this is for dlsch only
-
+ 
   // there is MSI (MCH Scheduling Info) 
   if (msi_flag == 1) {
     // Create MSI here
@@ -1292,7 +1293,7 @@ int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) {
     }
     msi_ptr+= sizeof(MSI_ELEMENT);
 
-    //MTCHs
+         //Header for MTCHs
     num_mtch = eNB_mac_inst[Mod_id].mbms_SessionList[0]->list.count;
     for (i=0;i<num_mtch;i++) { // loop for all session in this MCH (MCH[0]) at this moment
       ((MSI_ELEMENT *) msi_ptr)->lcid = eNB_mac_inst[Mod_id].mbms_SessionList[0]->list.array[i]->logicalChannelIdentity_r9;//mtch_lcid;
@@ -1306,7 +1307,9 @@ int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) {
     else 
       header_len_msi = 3;
 
-    LOG_D(MAC,"Scheduler: MSI is transmitted in this subframe \n" );
+    LOG_D(MAC,"[eNB %d] Frame %d : MSI->MCH, length of MSI is %d bytes \n",Mod_id,frame,msi_length);
+    //LOG_D(MAC,"Scheduler: MSI is transmitted in this subframe \n" );
+
     //   LOG_D(MAC,"Scheduler: MSI length is %d bytes\n",msi_length);
     // Store MSI data to mch_buffer[0]
     memcpy((char *)&mch_buffer[sdu_length_total],
@@ -1363,48 +1366,61 @@ int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) {
     }
     eNB_mac_inst[Mod_id].mcch_active=0;
   }
-
-  // there is MTCHs, loop if there are more than 1
+  
+     // there is MTCHs, loop if there are more than 1
   if (mtch_flag == 1) {
-
-    // Calculate TBS
+        // Calculate TBS
+    /*                                if ((msi_flag==1) || (mcch_flag==1)) {
+                                    TBS = mac_xface->get_TBS(mcch_mcs, mac_xface->lte_frame_parms->N_RB_DL);
+                                           }
+                                    else { // only MTCH in this subframe 
+                                    TBS = mac_xface->get_TBS(eNB_mac_inst[Mod_id].pmch_Config[0]->dataMCS_r9, mac_xface->lte_frame_parms->N_RB_DL);
+                                          }
+    */
     TBS = mac_xface->get_TBS_DL(eNB_mac_inst[Mod_id].MCH_pdu.mcs, mac_xface->lte_frame_parms->N_RB_DL);
-
-    //    get MTCH data from RLC (like for DTCH)
-    LOG_D(MAC,"[eNB %d] Frame %d : MTCH data is transmitted on this subframe\n",Mod_id,frame);  
-
-    /*    header_len_mtch = 3;
-	  LOG_D(MAC,"[eNB %d], Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n",
-	  Mod_id,frame,MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)),TBS,
-	  TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
     
-	  rlc_status = mac_rlc_status_ind(Mod_id,frame,1,MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)),
+        // get MTCH data from RLC (like for DTCH)
+    LOG_D(MAC,"[eNB %d] Frame %d : MTCH data is transmitted on subframe %d\n",Mod_id,frame,subframe);  
+    
+    header_len_mtch = 3;
+	  LOG_D(MAC,"[eNB %d], Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n",
+	  Mod_id,frame,MTCH,TBS,
 	  TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
     
-	  if (rlc_status.bytes_in_buffer >0) {
-	  //      LOG_I(MAC,"[eNB %d][MBMS USER-PLANE], Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d)\n",
-	  //    Mod_id,frame,TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch,header_len_mtch);
- 
-	  sdu_lengths[num_sdus] = mac_rlc_data_req(Mod_id,frame, RLC_MBMS_NO
-	  MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)),
-	  (char*)&mch_buffer[sdu_length_total]);
-	  LOG_I(MAC,"[eNB %d][MBMS USER-PLANE] Got %d bytes for MTCH %d\n",Mod_id,sdu_lengths[num_sdus],MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)));
-	  sdu_lcids[num_sdus] = MTCH;
-	  sdu_length_total += sdu_lengths[num_sdus];
-	  if (sdu_lengths[num_sdus] < 128)
-	  header_len_mtch = 2;
-	  num_sdus++;
-	  }
-	  else {
-	  header_len_mtch = 0;    
-	  }
-    */
+    rlc_status = mac_rlc_status_ind(Mod_id,frame,1,RLC_MBMS_YES,MTCH+ (maxDRB + 3) * MAX_MOBILES_PER_RG,
+				    TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
+    printf("frame %d, subframe %d,  rlc_status.bytes_in_buffer is %d\n",frame,subframe, rlc_status.bytes_in_buffer);
+
+    if (rlc_status.bytes_in_buffer >0) {
+      LOG_I(MAC,"[eNB %d][MBMS USER-PLANE], Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d)\n",
+	    Mod_id,frame,TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch,header_len_mtch);
+      
+      sdu_lengths[num_sdus] = mac_rlc_data_req(Mod_id,frame, RLC_MBMS_YES,
+					       MTCH + (maxDRB + 3) * MAX_MOBILES_PER_RG,
+					       (char*)&mch_buffer[sdu_length_total]);
+      //sdu_lengths[num_sdus] = mac_rlc_data_req(Mod_id,frame, RLC_MBMS_NO,  MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]);
+      LOG_I(MAC,"[eNB %d][MBMS USER-PLANE] Got %d bytes for MTCH %d\n",Mod_id,sdu_lengths[num_sdus],MTCH);
+      sdu_lcids[num_sdus] = MTCH;
+      sdu_length_total += sdu_lengths[num_sdus];
+      if (sdu_lengths[num_sdus] < 128)
+	header_len_mtch = 2;
+      num_sdus++;
+    }
+    else {
+      header_len_mtch = 0;    
+    }
   }
   
   // FINAL STEP: Prepare and multiplexe MSI, MCCH and MTCHs
   if ((sdu_length_total + header_len_msi + header_len_mcch + header_len_mtch) >0) {
-
     // Adjust the last subheader
+    /*                                 if ((msi_flag==1) || (mcch_flag==1)) {
+                                         eNB_mac_inst[Mod_id].MCH_pdu.mcs = mcch_mcs;
+                                          }
+                                        else if (mtch_flag == 1) { // only MTCH in this subframe 
+                                       eNB_mac_inst[Mod_id].MCH_pdu.mcs = eNB_mac_inst[Mod_id].pmch_Config[0]->dataMCS_r9;
+                                          }
+    */
     header_len_mtch_temp = header_len_mtch;
     header_len_mcch_temp = header_len_mcch;
     header_len_msi_temp = header_len_msi;
@@ -1439,7 +1455,7 @@ int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) {
 				   padding,                        
 				   post_padding);
 
-    LOG_D(MAC,"[DUY] MCS for this sf is %d\n", eNB_mac_inst[Mod_id].MCH_pdu.mcs);
+    LOG_D(MAC," MCS for this sf is %d\n", eNB_mac_inst[Mod_id].MCH_pdu.mcs);
 
     LOG_I(MAC,"[eNB %d][MBMS USER-PLANE ] Generate header : sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,padding %d,post_padding %d (mcs %d, TBS %d), header MTCH %d, header MCCH %d, header MSI %d\n",
 	  Mod_id,sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],offset,padding,post_padding,eNB_mac_inst[Mod_id].MCH_pdu.mcs,TBS,header_len_mtch, header_len_mcch, header_len_msi);
@@ -1448,14 +1464,21 @@ int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) {
     // filling remainder of MCH with random data if necessery
     for (j=0;j<(TBS-sdu_length_total-offset);j++)
       eNB_mac_inst[Mod_id].MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff);
-
+/*    
+   for (j=0;j<sdu_length_total;j++)
+      printf("%2x.",eNB_mac_inst[Mod_id].MCH_pdu.payload[j+offset]);
+      printf(" \n");*/
     return 1;
   } 
-  else 
+  else {
+    // for testing purpose, fill with random data 
+    //for (j=0;j<(TBS-sdu_length_total-offset);j++)
+    //  eNB_mac_inst[Mod_id].MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff);
     return 0;
-  
+  }
   //this is for testing 
-  /*  if (mtch_flag == 1) {
+  /*  
+  if (mtch_flag == 1) {
   //  LOG_D(MAC,"DUY: mch_buffer length so far is : %ld\n", &mch_buffer[sdu_length_total]-&mch_buffer[0]);
   return 1;
   }
@@ -1466,12 +1489,12 @@ int schedule_MBMS(unsigned char Mod_id,u32 frame, u8 subframe) {
 
 MCH_PDU *get_mch_sdu(uint8_t Mod_id,uint32_t frame, uint32_t subframe) {
   //  eNB_mac_inst[Mod_id].MCH_pdu.mcs=0;
-  LOG_D(MAC,"[DUY] MCH_pdu.mcs is %d\n", eNB_mac_inst[Mod_id].MCH_pdu.mcs);
+  LOG_D(MAC," MCH_pdu.mcs is %d\n", eNB_mac_inst[Mod_id].MCH_pdu.mcs);
   return(&eNB_mac_inst[Mod_id].MCH_pdu);
 }
 
-
 #endif
+
 // First stage of Random-Access Scheduling
 void schedule_RA(unsigned char Mod_id,u32 frame, unsigned char subframe,unsigned char Msg3_subframe,unsigned char *nprb,unsigned int *nCCE) {
 
@@ -4226,7 +4249,7 @@ void eNB_dlsch_ulsch_scheduler(u8 Mod_id,u8 cooperation_flag, u32 frame, u8 subf
 #endif
 
 #ifdef Rel10
-  if (eNB_mac_inst[Mod_id].MBMS_flag ==1) {
+  if (eNB_mac_inst[Mod_id].MBMS_flag >0) {
 
     mbsfn_status = schedule_MBMS(Mod_id,frame,subframe);
   }
diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c
index a2f093450c3..616e88d1e39 100644
--- a/openair2/LAYER2/MAC/main.c
+++ b/openair2/LAYER2/MAC/main.c
@@ -173,12 +173,12 @@ int mac_top_init(int eMBMS_active, u8 cba_group_active){
 #ifdef PHY_EMUL
     Mac_rlc_xface->Is_cluster_head[Mod_id]=2;//0: MR, 1: CH, 2: not CH neither MR
 #endif
-#ifdef Rel10
+    /*#ifdef Rel10
     int n;
     for (n=0;n<4096;n++)
       eNB_mac_inst[Mod_id].MCH_pdu.payload[n] = taus();
     //    Mac_rlc_xface->Node_id[Mod_id]=NODE_ID[Mod_id];
-#endif
+    #endif*/
   }
   //  Mac_rlc_xface->frame=Mac_rlc_xface->frame;
 
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index dbb911d6b32..84cdadda80c 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -485,7 +485,7 @@ void ue_send_mch_sdu(u8 Mod_id, u32 frame, u8 *sdu, u16 sdu_len, u8 eNB_index) {
   for (i=0; i<num_sdu; i++) {
     if (rx_lcids[i] == MCH_SCHDL_INFO) {
       if (UE_mac_inst[Mod_id].mcch_status==1) {
-	LOG_D(MAC,"[UE %d] Frame %d : MCH -> MSI  (eNB %d, %d bytes)\n",Mod_id,frame, eNB_index, rx_lengths[i]);
+	LOG_I(MAC,"[UE %d] Frame %d : MCH -> MSI  (eNB %d, %d bytes)\n",Mod_id,frame, eNB_index, rx_lengths[i]);
 	// ??store necessary scheduling info to ue_mac_inst in order to 
 	// calculate exact position of interested service (for the complex case has >1 mtch)
 	// set msi_status to 1
@@ -501,8 +501,18 @@ void ue_send_mch_sdu(u8 Mod_id, u32 frame, u8 *sdu, u16 sdu_len, u8 eNB_index) {
     }
     else if (rx_lcids[i] == MTCH) {
       if (UE_mac_inst[Mod_id].msi_status==1) {  
-	//	LOG_I(MAC,"[UE %d] Frame %d : MCH -> MTCH (eNB %d, %d bytes)\n",Mod_id,frame, eNB_index, rx_lengths[i]);
-	// mac_rlc_data_ind(); check for this function
+	LOG_I(MAC,"[UE %d] Frame %d : MCH -> MTCH (eNB %d, %d bytes)\n",Mod_id,frame, eNB_index, rx_lengths[i]);
+
+	mac_rlc_data_ind(Mod_id+NB_eNB_INST, // because rlc[module_idP] (to differential between eNB and UE)
+			 frame,
+			 0,
+			 RLC_MBMS_YES,
+			 MTCH + (maxDRB + 3),
+			 (char *)payload_ptr,
+			 rx_lengths[i],
+			 1,
+			 NULL);
+
       }
     }
     payload_ptr += rx_lengths[i];
@@ -528,13 +538,13 @@ int ue_query_mch(uint8_t Mod_id, uint32_t frame, uint32_t subframe) {
     if (UE_mac_inst[Mod_id].mbsfn_SubframeConfig[0]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame){// one-frame format
       
       if (UE_mac_inst[Mod_id].pmch_Config[0]) {
-	  //  Find the first subframe in this MCH to transmit MSI
-	  if (frame % mch_scheduling_period == UE_mac_inst[Mod_id].mbsfn_SubframeConfig[0]->radioframeAllocationOffset ) {
-	    while (ii == 0) {
-	      ii = UE_mac_inst[Mod_id].mbsfn_SubframeConfig[0]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos);
-	      msi_pos++;
-	    }
+	//  Find the first subframe in this MCH to transmit MSI
+	if (frame % mch_scheduling_period == UE_mac_inst[Mod_id].mbsfn_SubframeConfig[0]->radioframeAllocationOffset ) {
+	  while (ii == 0) {
+	    ii = UE_mac_inst[Mod_id].mbsfn_SubframeConfig[0]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos);
+	    msi_pos++;
 	  }
+	}
       }
       
       // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index bed4252f143..611c9231534 100755
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -94,7 +94,7 @@ BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
   mem_block_t* pdcp_pdu = NULL;
   rlc_op_status_t rlc_status;
 
-  if (pdcp->instanciated_instance == 0) {
+  if ((pdcp->instanciated_instance == 0) && (mode != PDCP_TM)) {
     LOG_W(PDCP, "Instance is not configured, Ignoring SDU...\n");
     return FALSE;
   }
@@ -119,7 +119,7 @@ BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
     LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_size);
     pdcp_pdu = get_free_mem_block(sdu_buffer_size);
     if (pdcp_pdu != NULL) {
-      memcpy(&pdcp_pdu->data, sdu_buffer, sdu_buffer_size); 
+      memcpy(&pdcp_pdu->data[0], sdu_buffer, sdu_buffer_size); 
       rlc_status = rlc_data_req(module_id, frame, eNB_flag, RLC_MBMS_YES, rb_id, muiP, confirmP, sdu_buffer_size, pdcp_pdu);
     } else
       rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;    
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
index 0dd027e4636..a0d535907fa 100755
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -638,12 +638,12 @@ void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index
   int pkt_size=0, pkt_cnt=0;
   u8 pdcp_mode;
   Packet_otg_elt * otg_pkt_info;
+
   // we need to add conditions to avoid transmitting data when the UE is not RRC connected.
 #if defined(USER_MODE) && defined(OAI_EMU)
   if (oai_emulation.info.otg_enabled ==1 ){
     module_id = (eNB_flag == 1) ?  eNB_index : NB_eNB_INST + UE_index ;
     //rb_id    = (eNB_flag == 1) ? eNB_index * MAX_NUM_RB + DTCH : (NB_eNB_INST + UE_index -1 ) * MAX_NUM_RB + DTCH ;
-
     if (eNB_flag == 1) { // search for DL traffic
       //for (dst_id = NB_eNB_INST; dst_id < NB_UE_INST + NB_eNB_INST; dst_id++) {
       while ((otg_pkt_info = pkt_list_remove_head(&(otg_pdcp_buffer[module_id]))) != NULL) {
@@ -653,6 +653,8 @@ void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index
         module_id = (otg_pkt_info->otg_pkt).module_id;
         rb_id = (otg_pkt_info->otg_pkt).rb_id;
         pdcp_mode = (otg_pkt_info->otg_pkt).mode;
+	//	LOG_I(PDCP,"pdcp_fifo, pdcp mode is= %d\n",pdcp_mode);
+	
         // generate traffic if the ue is rrc reconfigured state
 	// if (mac_get_rrc_status(module_id, eNB_flag, dst_id ) > 2 /*RRC_CONNECTED*/) { // not needed: this test is already done in update_otg_enb
 	otg_pkt = (u8*) (otg_pkt_info->otg_pkt).sdu_buffer;
@@ -664,6 +666,7 @@ void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index
 	  free(otg_pkt);
 	}
 	// } //else LOG_D(OTG,"frame %d enb %d-> ue %d link not yet established state %d  \n", frame, eNB_index,dst_id - NB_eNB_INST, mac_get_rrc_status(module_id, eNB_flag, dst_id - NB_eNB_INST));
+
       }
     }
     else {
@@ -678,7 +681,7 @@ void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index
 	otg_pkt = (u8*) (otg_pkt_info->otg_pkt).sdu_buffer;
 	pkt_size = (otg_pkt_info->otg_pkt).sdu_buffer_size;
 	if (otg_pkt != NULL){
-	//rb_id= eNB_index * MAX_NUM_RB + DTCH;
+	  //rb_id= eNB_index * MAX_NUM_RB + DTCH;
 	  LOG_D(OTG,"[UE %d] sending packet from module %d on rab id %d (src %d, dst %d) pkt size %d\n", UE_index, src_id, rb_id, src_id, dst_id, pkt_size);
 	  pdcp_data_req(src_id, frame, eNB_flag, rb_id, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO,pkt_size, otg_pkt, PDCP_DATA_PDU);
 	  free(otg_pkt);
@@ -692,9 +695,9 @@ void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index
     unsigned int ctime=0;
     src_id = eNB_index;
     ctime = frame * 100;
-
+    
     /*if  ((mac_get_rrc_status(eNB_index, eNB_flag, 0 ) > 2) &&
-  (mac_get_rrc_status(eNB_index, eNB_flag, 1 ) > 2)) { */
+      (mac_get_rrc_status(eNB_index, eNB_flag, 1 ) > 2)) { */
     for (dst_id = 0; dst_id<NUMBER_OF_UE_MAX; dst_id++) {
       if (mac_get_rrc_status(eNB_index, eNB_flag, dst_id ) > 2) {
         otg_pkt=packet_gen(src_id, dst_id, ctime, &pkt_size);
@@ -705,12 +708,12 @@ void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index
           free(otg_pkt);
         }
         /*else {
-            LOG_I(OTG,"nothing generated (src %d, dst %d)\n",src_id, dst_id);
-            }*/
+	  LOG_I(OTG,"nothing generated (src %d, dst %d)\n",src_id, dst_id);
+	  }*/
       }
       /*else {
-          LOG_I(OTG,"rrc_status (src %d, dst %d) = %d\n",src_id, dst_id, mac_get_rrc_status(src_id, eNB_flag, dst_id ));
-          }*/
+	LOG_I(OTG,"rrc_status (src %d, dst %d) = %d\n",src_id, dst_id, mac_get_rrc_status(src_id, eNB_flag, dst_id ));
+	}*/
     }
   }
 #endif
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_segment.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_segment.c
index fa7c3ddef59..526a3931563 100755
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_segment.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_segment.c
@@ -423,6 +423,7 @@ rlc_um_segment_5 (struct rlc_um_entity *rlcP,u32_t frame)
                 test_remaining_size_to_substract = 0;
                 test_remaining_num_li_to_substract = 0;
                 pdu_remaining_size = pdu_remaining_size - (test_li_length_in_bytes ^ 3);
+		data_pdu_size -=  (test_li_length_in_bytes ^ 3);//modifier pour duy
             } else if ((sdu_mngt->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) < test_pdu_remaining_size ) {
                 test_num_li += 1;
                 num_fill_sdu += 1;
@@ -439,6 +440,7 @@ rlc_um_segment_5 (struct rlc_um_entity *rlcP,u32_t frame)
                 test_remaining_size_to_substract = 0;
                 test_remaining_num_li_to_substract = 0;
                 pdu_remaining_size = pdu_remaining_size - 1;
+                data_pdu_size -= 1;//modifier pour duy
             }
             sdu_buffer_index = (sdu_buffer_index + 1) % rlcP->size_input_sdus_buffer;
         }
diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c
index a470ace477f..0276407b984 100644
--- a/openair2/LAYER2/RLC/rlc.c
+++ b/openair2/LAYER2/RLC/rlc.c
@@ -438,20 +438,18 @@ rlc_op_status_t rlc_data_req     (module_id_t module_idP, u32_t frame, u8_t eNB_
           } else {
               mbms_rb_id = rb_idP + (maxDRB + 3);
           }
+	  //  LOG_I(RLC,"DUY rlc_data_req: mbms_rb_id in RLC instant is: %d\n", mbms_rb_id);
           if (sduP != NULL) {
               if (sdu_sizeP > 0) {
                   LOG_I(RLC,"received a packet with size %d for MBMS \n", sdu_sizeP);
                   new_sdu = get_free_mem_block (sdu_sizeP + sizeof (struct rlc_um_data_req_alloc));
-
                   if (new_sdu != NULL) {
                       // PROCESS OF COMPRESSION HERE:
                       memset (new_sdu->data, 0, sizeof (struct rlc_um_data_req_alloc));
                       memcpy (&new_sdu->data[sizeof (struct rlc_um_data_req_alloc)], &sduP->data[0], sdu_sizeP);
-
                       ((struct rlc_um_data_req *) (new_sdu->data))->data_size = sdu_sizeP;
                       ((struct rlc_um_data_req *) (new_sdu->data))->data_offset = sizeof (struct rlc_um_data_req_alloc);
                       free_mem_block(sduP);
-
                       LOG_D(RLC, "%s\n",RLC_FG_BRIGHT_COLOR_RED);
                       if (rlc[module_idP].m_rlc_um_array[rlc[module_idP].m_rlc_pointer[mbms_rb_id].rlc_index].is_data_plane) {
                           LOG_D(RLC, "[MSC_MSG][FRAME %05d][PDCP][MOD %02d][RB %02d][--- RLC_UM_DATA_REQ/%d Bytes (MBMS) --->][RLC_UM][MOD %02d][RB %02d]\n",
@@ -480,13 +478,13 @@ rlc_op_status_t rlc_data_req     (module_id_t module_idP, u32_t frame, u8_t eNB_
               return RLC_OP_STATUS_BAD_PARAMETER;
           }
       } else {
-          return RLC_OP_STATUS_BAD_PARAMETER;
+	return RLC_OP_STATUS_BAD_PARAMETER;
       }
 #endif
   } else {
-      free_mem_block(sduP);
-      //handle_event(ERROR,"FILE %s FONCTION rlc_data_req() LINE %s : parameter module_id out of bounds :%d\n", __FILE__, __LINE__, module_idP);
-      return RLC_OP_STATUS_BAD_PARAMETER;
+    free_mem_block(sduP);
+    //handle_event(ERROR,"FILE %s FONCTION rlc_data_req() LINE %s : parameter module_id out of bounds :%d\n", __FILE__, __LINE__, module_idP);
+    return RLC_OP_STATUS_BAD_PARAMETER;
   }
 }
 
diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c
index a89aa5a1a48..71024c111f8 100644
--- a/openair2/LAYER2/RLC/rlc_rrc.c
+++ b/openair2/LAYER2/RLC/rlc_rrc.c
@@ -40,7 +40,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (module_id_t module_idP, u32_t frameP, u
   rlc_mode_t      rlc_type;
 #ifdef Rel10
   long int               cnt2            = 0;
-  long int               mrb_id          = 0;
+  //  long int               mrb_id          = 0;
   long int               mbms_service_id = 0;
   long int               mbms_session_id = 0;
   PMCH_Info_r9_t*        pmch_info_r9    = NULL;
@@ -264,61 +264,66 @@ rlc_op_status_t rrc_rlc_config_asn1_req (module_id_t module_idP, u32_t frameP, u
 
 
 #ifdef Rel10
-    if (pmch_info_listP != NULL) {
-        for (cnt=0;cnt<pmch_info_listP->list.count;cnt++) {
-            pmch_info_r9 = pmch_info_listP->list.array[cnt];
-
-            for (cnt2=0;cnt2<pmch_info_r9->mbms_SessionInfoList_r9.list.count;cnt2++) {
-                mbms_session = pmch_info_r9->mbms_SessionInfoList_r9.list.array[cnt2];
-
-                if (mbms_session->logicalChannelIdentity_r9 > 0) {
-                    //lc_id = (NUMBER_OF_UE_MAX*NB_RB_MAX) + mbms_session->logicalChannelIdentity_r9;
-
-                    if (eNB_flagP) {
-                    	lc_id = mbms_session->logicalChannelIdentity_r9 + (maxDRB + 3) * MAX_MOBILES_PER_RG;
-                    } else {
-                    	lc_id = mbms_session->logicalChannelIdentity_r9 + (maxDRB + 3);
-                    }
-
-                    if (mbms_session->sessionId_r9 != NULL) {
-                    	mbms_session_id = mbms_session->sessionId_r9->buf[0];
-                    } else {
-                    	mbms_session_id = mbms_session->logicalChannelIdentity_r9;
-                    }
-                    mbms_service_id = mbms_session->tmgi_r9.serviceId_r9.buf[0];
-                    rb_id = (mbms_service_id * maxSessionPerPMCH) + lc_id;
-
-                    if (rlc[module_idP].m_rlc_pointer[rb_id].rlc_type == RLC_NONE) {
-                        rlc_status = rrc_rlc_add_rlc (module_idP, frameP, rb_id, lc_id, RLC_UM);
-                        if (rlc_status != RLC_OP_STATUS_OK ) {
-                            LOG_D(RLC, "[RLC_RRC] COULD NOT ALLOCATE RLC UM INSTANCE\n");
-                            continue;//? return rlc_status;
-                        }
-                    } else if (rlc[module_idP].m_rlc_pointer[rb_id].rlc_type != RLC_UM) {
-                        LOG_E(RLC, "[RLC_RRC] MBMS ERROR IN CONFIG, RLC FOUND ALREADY CONFIGURED FOR MBMS BEARER IS NOT UM\n");
-                        continue;
-                    }
-                    dl_um_rlc.sn_FieldLength = SN_FieldLength_size10;
-                    dl_um_rlc.t_Reordering = T_Reordering_ms5;
+  if (pmch_info_listP != NULL) {
+
+    LOG_I(RRC,"[%s %d] Config RLC instant for MBMS\n", (eNB_flagP) ? "eNB" : "UE", module_idP);
+
+    for (cnt=0;cnt<pmch_info_listP->list.count;cnt++) {
+      pmch_info_r9 = pmch_info_listP->list.array[cnt];
+      
+      for (cnt2=0;cnt2<pmch_info_r9->mbms_SessionInfoList_r9.list.count;cnt2++) {
+	mbms_session = pmch_info_r9->mbms_SessionInfoList_r9.list.array[cnt2];
+	
+	if (mbms_session->logicalChannelIdentity_r9 > 0) {
+
+	  //	  lc_id = (NUMBER_OF_UE_MAX*NB_RB_MAX) + mbms_session->logicalChannelIdentity_r9;
+	  //   test this one and tell Lionel
+          if (eNB_flagP) {
+              lc_id = mbms_session->logicalChannelIdentity_r9 + (maxDRB + 3) * MAX_MOBILES_PER_RG;
+          } else {
+              lc_id = mbms_session->logicalChannelIdentity_r9 + (maxDRB + 3);
+          }
 
-                    config_req_rlc_um_asn1 (&rlc[module_idP].m_rlc_um_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index],
-                    		frameP,
-                    		eNB_flagP,
-                            RLC_MBMS_YES,
-                    		module_idP,
-                    		NULL,
-                    		&dl_um_rlc,
-                    		rb_id,
-                    		RADIO_ACCESS_BEARER);
-                } else {
-                    LOG_D(RLC, "[RLC_RRC] Invalid LogicalChannelIdentity for MTCH --- Value 0 is reserved for MCCH\n");
-                    lc_id = -1;
-                }
-            }
-        }
+	  
+	  if (mbms_session->sessionId_r9 != NULL) {
+	    mbms_session_id = mbms_session->sessionId_r9->buf[0];
+	  } else {
+	    mbms_session_id = mbms_session->logicalChannelIdentity_r9;
+	  }
+	  mbms_service_id = mbms_session->tmgi_r9.serviceId_r9.buf[2];// can use the pmch_index, here is the value 'cnt'
+	  rb_id = (mbms_service_id * maxSessionPerPMCH) + lc_id;
+	  
+	  if (rlc[module_idP].m_rlc_pointer[rb_id].rlc_type == RLC_NONE) {
+	    rlc_status = rrc_rlc_add_rlc (module_idP, frameP, rb_id, lc_id, RLC_UM);
+	    if (rlc_status != RLC_OP_STATUS_OK ) {
+	      LOG_D(RLC, "[RLC_RRC] COULD NOT ALLOCATE RLC UM INSTANCE\n");
+	      continue;//? return rlc_status;
+	    }
+	  } else if (rlc[module_idP].m_rlc_pointer[rb_id].rlc_type != RLC_UM) {
+	    LOG_E(RLC, "[RLC_RRC] MBMS ERROR IN CONFIG, RLC FOUND ALREADY CONFIGURED FOR MBMS BEARER IS NOT UM\n");
+	    continue;
+	  }
+	  dl_um_rlc.sn_FieldLength = SN_FieldLength_size5;
+	  dl_um_rlc.t_Reordering = T_Reordering_ms0;
+	  
+	  config_req_rlc_um_asn1 (&rlc[module_idP].m_rlc_um_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index],
+				  frameP,
+				  eNB_flagP,
+				  RLC_MBMS_YES,
+				  module_idP,
+				  NULL,
+				  &dl_um_rlc,
+				  rb_id,
+				  RADIO_ACCESS_BEARER);
+	} else {
+	  LOG_D(RLC, "[RLC_RRC] Invalid LogicalChannelIdentity for MTCH --- Value 0 is reserved for MCCH\n");
+	  lc_id = -1;
+	}
+      }
     }
+  }
 #endif
-
+  
   LOG_D(RLC, "[RLC_RRC][MOD_id %d]CONFIG REQ ASN1 END \n",module_idP);
   return RLC_OP_STATUS_OK;
 }
diff --git a/openair2/RRC/LITE/MESSAGES/Makefile b/openair2/RRC/LITE/MESSAGES/Makefile
index 993fee6814d..16a5170e309 100644
--- a/openair2/RRC/LITE/MESSAGES/Makefile
+++ b/openair2/RRC/LITE/MESSAGES/Makefile
@@ -30,3 +30,4 @@ regen: regenerate-from-asn1-source
 
 regenerate-from-asn1-source:
 	asn1c -gen-PER -fcompound-names -fnative-types -fskeletons-copy asn1c/ASN1_files/EUTRA-RRC-Definitions.asn
+
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
index ec4477e7eed..cacff00cc85 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
@@ -29,7 +29,7 @@
 #include "DRB-ToAddModList.h"
 #ifdef Rel10
 #include "MCCH-Message.h"
-#define MRB1 1
+//#define MRB1 1
 #endif
 
 #include "RRC/LITE/defs.h"
@@ -596,7 +596,7 @@ uint8_t do_SIB23(uint8_t Mod_id,
   *sib3 = &sib3_part->choice.sib3;
 
 #ifdef Rel10
-  if (MBMS_flag == 1) {
+  if (MBMS_flag > 0) {
     sib13_part = CALLOC(1,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
     memset(sib13_part,0,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
     sib13_part->present = SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920;
@@ -722,7 +722,7 @@ uint8_t do_SIB23(uint8_t Mod_id,
   //  (*sib2)->mbsfn_SubframeConfigList = NULL;
 
 #ifdef Rel10
-  if (MBMS_flag == 1) {
+  if (MBMS_flag > 0) {
     LOG_I(RRC,"Adding MBSFN Configuration to SIB2\n");
     MBSFN_SubframeConfig_t *sib2_mbsfn_SubframeConfig1;
     (*sib2)->mbsfn_SubframeConfigList = CALLOC(1,sizeof(struct MBSFN_SubframeConfigList));
@@ -738,10 +738,10 @@ uint8_t do_SIB23(uint8_t Mod_id,
     sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1;
     sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2;
     if (frame_parms->frame_type == TDD) {// pattern 001110 for TDD
-      sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x0e<<2;// shift 2 cuz 2last bits are unused.
+      sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x08<<2;// shift 2 cuz 2last bits are unused.
     } 
     else {   // pattern 101010 for FDD)
-      sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x2a<<2;
+      sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x30<<2;
     }
     ASN_SEQUENCE_ADD(&MBSFNSubframeConfigList->list,sib2_mbsfn_SubframeConfig1);
   }
@@ -785,7 +785,7 @@ uint8_t do_SIB23(uint8_t Mod_id,
   // SIB13
   // fill in all elements of SIB13 if present
 #ifdef Rel10
-  if (MBMS_flag == 1) {
+  if (MBMS_flag > 0 ) {
     //  Notification for mcch change
     (*sib13)->notificationConfig_r9.notificationRepetitionCoeff_r9= MBMS_NotificationConfig_r9__notificationRepetitionCoeff_r9_n2;
     (*sib13)->notificationConfig_r9.notificationOffset_r9= 0;
@@ -813,7 +813,7 @@ uint8_t do_SIB23(uint8_t Mod_id,
     }
     MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.bits_unused= 2;
 
-    MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= MBSFN_AreaInfo_r9__mcch_Config_r9__signallingMCS_r9_n7;
+    MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= MBSFN_AreaInfo_r9__mcch_Config_r9__signallingMCS_r9_n13;
 
     ASN_SEQUENCE_ADD(&MBSFNArea_list->list,MBSFN_Area1);
     
@@ -857,7 +857,7 @@ uint8_t do_SIB23(uint8_t Mod_id,
   ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list,
 		   sib3_part);
 #ifdef Rel10
-  if (MBMS_flag == 1) {
+  if (MBMS_flag > 0) {
     ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list,sib13_part);
   }
 #endif
@@ -1475,7 +1475,7 @@ uint8_t do_RRCConnectionReconfiguration(uint8_t                           Mod_id
 
 }
 
-uint8_t TMGI[5] = {5,4,0,0,1};//TMGI is a string of octet, ref. TS 24.008 fig. 10.5.4a
+uint8_t TMGI[5] = {4,3,2,1,0};//TMGI is a string of octet, ref. TS 24.008 fig. 10.5.4a
 
 #ifdef Rel10
 uint8_t do_MBSFNAreaConfig(LTE_DL_FRAME_PARMS *frame_parms,
@@ -1505,10 +1505,10 @@ uint8_t do_MBSFNAreaConfig(LTE_DL_FRAME_PARMS *frame_parms,
     mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1;
     mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2;
     if (frame_parms->frame_type == TDD) {// pattern 001110 for TDD
-      mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x0e<<2;// shift 2bits cuz 2last bits are unused.
+      mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x08<<2;// shift 2bits cuz 2last bits are unused.
     } 
     else {   // pattern 101010 for FDD)
-      mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x2a<<2;
+      mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x30<<2;
     }
     ASN_SEQUENCE_ADD(&(*mbsfnAreaConfiguration)->commonSF_Alloc_r9.list,mbsfn_SubframeConfig1);
 
@@ -1520,8 +1520,8 @@ uint8_t do_MBSFNAreaConfig(LTE_DL_FRAME_PARMS *frame_parms,
   pmch_Info_1 = CALLOC(1,sizeof(PMCH_Info_r9_t));
   memset((void*)pmch_Info_1,0,sizeof(PMCH_Info_r9_t));
   
-  pmch_Info_1->pmch_Config_r9.sf_AllocEnd_r9= 11;//take the value of last mbsfn subframe in this CSA period because there is only one PMCH in this mbsfn area
-  pmch_Info_1->pmch_Config_r9.dataMCS_r9= 15;
+  pmch_Info_1->pmch_Config_r9.sf_AllocEnd_r9= 3;//take the value of last mbsfn subframe in this CSA period because there is only one PMCH in this mbsfn area
+  pmch_Info_1->pmch_Config_r9.dataMCS_r9= 13;
   pmch_Info_1->pmch_Config_r9.mch_SchedulingPeriod_r9= PMCH_Config_r9__mch_SchedulingPeriod_r9_rf16;
 
   // MBMSs-SessionInfoList-r9
@@ -1539,7 +1539,7 @@ uint8_t do_MBSFNAreaConfig(LTE_DL_FRAME_PARMS *frame_parms,
   mbms_Session_1->sessionId_r9 = CALLOC(1,sizeof(OCTET_STRING_t));
   mbms_Session_1->sessionId_r9->buf= MALLOC(1);
   mbms_Session_1->sessionId_r9->size= 1;
-  mbms_Session_1->sessionId_r9->buf[0]= MRB1; 
+  mbms_Session_1->sessionId_r9->buf[0]= MTCH; 
   // Logical Channel ID
   mbms_Session_1->logicalChannelIdentity_r9= MTCH;
   ASN_SEQUENCE_ADD(&pmch_Info_1->mbms_SessionInfoList_r9.list,mbms_Session_1);
diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c
index 33f0b233860..4b94f7d2ab1 100644
--- a/openair2/RRC/LITE/rrc_UE.c
+++ b/openair2/RRC/LITE/rrc_UE.c
@@ -1472,6 +1472,7 @@ int decode_SI(u8 Mod_id,u32 frame,u8 eNB_index,u8 si_window) {
       if (UE_rrc_inst[Mod_id].MBMS_flag < 3) // see -Q option
 #endif
 	rrc_ue_generate_RRCConnectionRequest(Mod_id,frame,eNB_index);
+      LOG_I(RRC, "not sending connection request\n");
 
       if (UE_rrc_inst[Mod_id].Info[eNB_index].State == RRC_IDLE) {
 	LOG_I(RRC,"[UE %d] Received SIB1/SIB2/SIB3 Switching to RRC_SI_RECEIVED\n",Mod_id);
@@ -1577,6 +1578,7 @@ int decode_MCCH_Message(u8 Mod_id, u32 frame, u8 eNB_index, u8 *Sdu, u8 Sdu_len)
   asn_dec_rval_t dec_rval;
   
   if (UE_rrc_inst[Mod_id].Info[eNB_index].MCCH_MESSAGEStatus == 1) {
+    LOG_D(RRC,"MCCH MESSAGE has been already received!\n");
     return 0; // avoid decoding to prevent memory bloating
   }
   else {
@@ -1596,15 +1598,15 @@ int decode_MCCH_Message(u8 Mod_id, u32 frame, u8 eNB_index, u8 *Sdu, u8 Sdu_len)
 #endif
 
     if (mcch->message.present == MCCH_MessageType_PR_c1) {
-      LOG_D(RRC,"[UE %d] Found First MCCH_MESSAGE\n",Mod_id);
+      LOG_D(RRC,"[UE %d] Found mcch message \n",Mod_id);
       if(mcch->message.choice.c1.present == MCCH_MessageType__c1_PR_mbsfnAreaConfiguration_r9) {
 	/*	
 	memcpy((void*)*mcch_message,
 	       (void*)&mcch->message.choice.c1.choice.mbsfnAreaConfiguration_r9,
 	       sizeof(MBSFNAreaConfiguration_r9_t)); */
 	*mcch_message = &mcch->message.choice.c1.choice.mbsfnAreaConfiguration_r9;
-	LOG_D(RRC,"[UE %d] Found MBSFNAreaConfiguration\n",Mod_id);
-	decode_MBSFNAreaConfiguration(Mod_id,eNB_index);
+	LOG_I(RRC,"[UE %d] Frame %d : Found MBSFNAreaConfiguration from eNB \n",Mod_id, frame, eNB_index);
+	decode_MBSFNAreaConfiguration(Mod_id,eNB_index,frame);
 
       }
     }
@@ -1612,7 +1614,7 @@ int decode_MCCH_Message(u8 Mod_id, u32 frame, u8 eNB_index, u8 *Sdu, u8 Sdu_len)
   return 0;
 }
 
-void decode_MBSFNAreaConfiguration(u8 Mod_id, u8 eNB_index) {
+void decode_MBSFNAreaConfiguration(u8 Mod_id, u8 eNB_index, u32 frame) {
   LOG_D(RRC,"[UE %d] Number of MCH(s) in this MBSFN Area is %d\n", Mod_id, UE_rrc_inst[Mod_id].mcch_message[eNB_index]->pmch_InfoList_r9.list.count);
   //  store to MAC/PHY necessary parameters for receiving MTCHs
   rrc_mac_config_req(Mod_id,0,0,eNB_index,
@@ -1645,7 +1647,28 @@ void decode_MBSFNAreaConfiguration(u8 Mod_id, u8 eNB_index) {
 
   UE_rrc_inst[Mod_id].Info[eNB_index].MCCH_MESSAGEStatus = 1;
 
-  // Config Radio Bearer for MBMS user data (similar way to configure for eNB side in init_MBMS function)							       
+  // Config Radio Bearer for MBMS user data (similar way to configure for eNB side in init_MBMS function)
+    rrc_pdcp_config_asn1_req(NB_eNB_INST+Mod_id,frame,
+			   0,// eNB_flag
+			   eNB_index,// 0,// index
+			   NULL, // SRB_ToAddModList
+			   NULL, // DRB_ToAddModList
+			   (DRB_ToReleaseList_t*)NULL
+#ifdef Rel10
+			   ,
+			   &(UE_rrc_inst[Mod_id].mcch_message[eNB_index]->pmch_InfoList_r9)
+#endif
+			   );
+    
+  rrc_rlc_config_asn1_req(NB_eNB_INST+Mod_id, frame, 
+			  0,// eNB_flag
+			  0,
+			  NULL,// SRB_ToAddModList
+			  NULL,// DRB_ToAddModList
+			  NULL,// DRB_ToReleaseList
+			  &(UE_rrc_inst[Mod_id].mcch_message[eNB_index]->pmch_InfoList_r9));
+  // */
+  
 }
 
 #endif // rel10
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 668f0ded461..ff054c143ed 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -181,10 +181,8 @@ init_SI (u8 Mod_id)
                                                     &eNB_rrc_inst[Mod_id].sib3
 #ifdef Rel10
                                                     ,
-                                                    &eNB_rrc_inst[Mod_id].
-                                                    sib13,
-                                                    eNB_rrc_inst[Mod_id].
-                                                    MBMS_flag
+                                                    &eNB_rrc_inst[Mod_id].sib13,
+                                                    eNB_rrc_inst[Mod_id].MBMS_flag
 #endif
         );
       /*
@@ -231,7 +229,7 @@ init_SI (u8 Mod_id)
 
 
 #ifdef Rel10
-      if (eNB_rrc_inst[Mod_id].MBMS_flag == 1)
+      if (eNB_rrc_inst[Mod_id].MBMS_flag > 0)
         {
 
           //   LOG_D(RRC, "[eNB %d] mbsfn_SubframeConfigList.list.count = %ld\n", Mod_id, eNB_rrc_inst[Mod_id].sib2->mbsfn_SubframeConfigList->list.count);
@@ -348,9 +346,8 @@ init_MCCH (u8 Mod_id)
   // ??Configure MCCH logical channel
   // call mac_config_req with appropriate structure from ASN.1 description
 
-  //LOG_I(RRC, "DUY: lcid before entering rrc_mac_config_req is %02d\n",eNB_rrc_inst[Mod_id].mcch_message->pmch_InfoList_r9.list.array[0]->mbms_SessionInfoList_r9.list.array[0]->logicalChannelIdentity_r9);
   //  LOG_I(RRC, "DUY: serviceID is %d\n",eNB_rrc_inst[Mod_id].mcch_message->pmch_InfoList_r9.list.array[0]->mbms_SessionInfoList_r9.list.array[0]->tmgi_r9.serviceId_r9.buf[2]);
-  //LOG_I(RRC, "DUY: session ID is %d\n",eNB_rrc_inst[Mod_id].mcch_message->pmch_InfoList_r9.list.array[0]->mbms_SessionInfoList_r9.list.array[0]->sessionId_r9->buf[0]);
+  //  LOG_I(RRC, "DUY: session ID is %d\n",eNB_rrc_inst[Mod_id].mcch_message->pmch_InfoList_r9.list.array[0]->mbms_SessionInfoList_r9.list.array[0]->sessionId_r9->buf[0]);
   rrc_mac_config_req (Mod_id, 1, 0, 0,
                       (RadioResourceConfigCommonSIB_t *) NULL,
                       (struct PhysicalConfigDedicated *) NULL,
@@ -383,14 +380,15 @@ init_MCCH (u8 Mod_id)
 void
 init_MBMS (u8 Mod_id, u32 frame)
 {                               // init the configuration for MTCH 
-  //  int j,i, num_mch;
-  if (eNB_rrc_inst[Mod_id].MBMS_flag == 1)
+
+  if (eNB_rrc_inst[Mod_id].MBMS_flag > 0)
     {
 
       //  LOG_I(RRC,"[eNB %d] Frame %d : Configuring Radio Bearer for MBMS service in MCH[%d]\n", Mod_id, frame,i); //check the lcid
       // Configuring PDCP and RLC for MBMS Radio Bearer
 
-      rrc_pdcp_config_asn1_req (Mod_id, frame, 1, 0, NULL,      // SRB_ToAddModList
+      rrc_pdcp_config_asn1_req (Mod_id, frame, 1, 0, 
+				NULL,      // SRB_ToAddModList
                                 NULL,   // DRB_ToAddModList
                                 (DRB_ToReleaseList_t *) NULL
 #ifdef Rel10
@@ -398,20 +396,18 @@ init_MBMS (u8 Mod_id, u32 frame)
                                 &(eNB_rrc_inst[Mod_id].mcch_message->
                                   pmch_InfoList_r9)
 #endif
-        );
-
-      rrc_rlc_config_asn1_req (Mod_id, frame, 1, 0, NULL,       // SRB_ToAddModList
-                               NULL,    // DRB_ToAddModList
-                               NULL,    // DRB_ToReleaseList
-                               &(eNB_rrc_inst[Mod_id].mcch_message->
-                                 pmch_InfoList_r9));
-
-
-      //rrc_mac_config_req();
-      // use the same as of DTCH for the moment,need to check the flag for mXch 
-
-    }
-
+			     );
+    
+    rrc_rlc_config_asn1_req(Mod_id, frame, 1, 0,
+			    NULL,// SRB_ToAddModList
+			    NULL,// DRB_ToAddModList
+			    NULL,// DRB_ToReleaseList
+			    &(eNB_rrc_inst[Mod_id].mcch_message->pmch_InfoList_r9));
+    
+    //rrc_mac_config_req();
+    
+  }  
+  
 }
 
 #endif
@@ -483,7 +479,7 @@ openair_rrc_lite_eNB_init (u8 Mod_id)
   init_SI (Mod_id);
 
 #ifdef Rel10
-  if (eNB_rrc_inst[Mod_id].MBMS_flag == 1)
+  if (eNB_rrc_inst[Mod_id].MBMS_flag > 0)
     {
       /// MCCH INIT
       init_MCCH (Mod_id);
diff --git a/openair2/UTIL/OTG/otg.c b/openair2/UTIL/OTG/otg.c
index c92e395c566..35f57915a9a 100644
--- a/openair2/UTIL/OTG/otg.c
+++ b/openair2/UTIL/OTG/otg.c
@@ -112,6 +112,8 @@ char *str_sub (const char *s, unsigned int start, unsigned int end) {
 // set the simulation time
 void set_ctime(int ctime){
   otg_info->ctime=ctime;
+	//	otg_muticast_info->ctime=ctime;
+	
 }
 
 
diff --git a/openair2/UTIL/OTG/otg_defs.h b/openair2/UTIL/OTG/otg_defs.h
index 6b1e2d87023..e397a7b94e0 100644
--- a/openair2/UTIL/OTG/otg_defs.h
+++ b/openair2/UTIL/OTG/otg_defs.h
@@ -477,6 +477,10 @@ typedef struct {
 
   float radio_access_delay[NUMBER_OF_eNB_MAX + NUMBER_OF_SERVICE_MAX][NUMBER_OF_eNB_MAX + NUMBER_OF_SERVICE_MAX];
  
+  double tx_throughput[NUMBER_OF_eNB_MAX + NUMBER_OF_SERVICE_MAX][NUMBER_OF_eNB_MAX + NUMBER_OF_SERVICE_MAX];
+  double rx_goodput[NUMBER_OF_eNB_MAX + NUMBER_OF_SERVICE_MAX][NUMBER_OF_eNB_MAX + NUMBER_OF_SERVICE_MAX]; 	/*!< \brief  Rx goodput: (size of received data)/ctime*/
+  float rx_loss_rate[NUMBER_OF_eNB_MAX + NUMBER_OF_SERVICE_MAX][NUMBER_OF_eNB_MAX + NUMBER_OF_SERVICE_MAX]; 	/*!< \brief  Rx Loss Rate: ratio, unit: bytes*/  
+
   unsigned int rx_total_bytes_dl;
  
 }otg_multicast_info_t;
diff --git a/openair2/UTIL/OTG/otg_kpi.c b/openair2/UTIL/OTG/otg_kpi.c
index 76e8de99ded..867304586a7 100644
--- a/openair2/UTIL/OTG/otg_kpi.c
+++ b/openair2/UTIL/OTG/otg_kpi.c
@@ -48,18 +48,36 @@ extern unsigned char NB_UE_INST;
 
 void tx_throughput(int src, int dst, int application){
   
-  otg_info->tx_throughput[src][dst][application]=((double)otg_info->tx_num_bytes[src][dst][application] *1000*8)/ (get_ctime()*1024); // unit Kbit/sec, if ctime in ms
-	if (otg_info->tx_num_bytes_background[src][dst]>0)
-  	otg_info->tx_throughput_background[src][dst]=((double)otg_info->tx_num_bytes_background[src][dst]*1000*8)/ (get_ctime()*1024); // unit Kbit/sec, if ctime in ms
+  if (otg_info->tx_num_bytes[src][dst][application]>0)
+    otg_info->tx_throughput[src][dst][application]=((double)otg_info->tx_num_bytes[src][dst][application] *1000*8)/ (get_ctime()*1024); // unit Kbit/sec, if ctime in ms
+  
+  if (otg_info->tx_num_bytes_background[src][dst]>0)
+    otg_info->tx_throughput_background[src][dst]=((double)otg_info->tx_num_bytes_background[src][dst]*1000*8)/ (get_ctime()*1024); // unit Kbit/sec, if ctime in ms
+  
+  if (otg_multicast_info->tx_num_bytes[src][dst][application]>0){
+    if (application < 2)
+      otg_multicast_info->tx_throughput[src][dst]=((double)otg_multicast_info->tx_num_bytes[src][dst][application]*1000*8)/ (get_ctime()*1024); // unit Kbit/sec, if ctime in ms
+                                                       //otg_multicast_info->tx_num_bytes[src][dst][app] is 3 dimension param in otg_tx.c, only use [app]=0
+    //    LOG_I(OTG,"DUY, get_ctime() [i=%d,j=%d,k=%d] = %.d\n", src,dst,application,get_ctime());
+        LOG_I(OTG,"otg_multicast_info->tx_num_bytes[i=%d,j=%d,k=%d] = %.d\n", src,dst,application,otg_multicast_info->tx_num_bytes[src][dst][application]);
+  }
+
 }
 
 
 
 void rx_goodput(int src, int dst, int application){
 
-  otg_info->rx_goodput[src][dst][application]=((double)otg_info->rx_num_bytes[src][dst][application]*1000*8)/(get_ctime()*1024); // unit kB/sec, if ctime in ms 
-if (otg_info->rx_num_bytes_background[src][dst]>0)
-  otg_info->rx_goodput_background[src][dst]=((double)otg_info->rx_num_bytes_background[src][dst] *1000*8)/(get_ctime()*1024); // unit kB/sec, if ctime in ms
+  if (otg_info->rx_num_bytes[src][dst][application]>0)
+    otg_info->rx_goodput[src][dst][application]=((double)otg_info->rx_num_bytes[src][dst][application]*1000*8)/(get_ctime()*1024); // unit kB/sec, if ctime in ms 
+  
+  if (otg_info->rx_num_bytes_background[src][dst]>0)
+    otg_info->rx_goodput_background[src][dst]=((double)otg_info->rx_num_bytes_background[src][dst] *1000*8)/(get_ctime()*1024); // unit kB/sec, if ctime in ms
+  
+  if (otg_multicast_info->rx_num_bytes[src][dst][application]>0){
+    otg_multicast_info->rx_goodput[src][dst]=((double)otg_multicast_info->rx_num_bytes[src][dst][application] *1000*8)/(get_ctime()*1024); // unit kB/sec, if ctime in ms
+        LOG_I(OTG,"otg_multicast_info->rx_num_bytes[i=%d,j=%d,k=%d] = %.d\n", src,dst,application,otg_multicast_info->rx_num_bytes[src][dst][application]);
+  }
 }
 
 
@@ -81,6 +99,11 @@ if (otg_info->rx_loss_rate[src][dst][application]>0)
 LOG_I(OTG, "LOSS_RATE (src=%d, dst=%d, appli %d ):: = %lf(pkts) [TX %d] [RX %d], [NB UL %d] [NB DL %d]\n",src, dst, application, otg_info->rx_loss_rate[src][dst][application], otg_info->tx_num_pkt[src][dst][application],otg_info->rx_num_pkt[src][dst][application],otg_info->nb_loss_pkts_ul[src][dst][application], otg_info->nb_loss_pkts_dl[src][dst][application]);
   */
 
+   if (otg_multicast_info->rx_num_pkt[src][dst] < otg_multicast_info->tx_num_pkt[src][dst])
+    otg_multicast_info->rx_loss_rate[src][dst]= 1 - ((double)otg_multicast_info->rx_num_pkt[src][dst][application]/otg_multicast_info->tx_num_pkt[src][dst][0]);
+  else
+    otg_multicast_info->rx_loss_rate[src][dst]=0;
+
 }
 
 
@@ -154,12 +177,14 @@ void kpi_gen() {
   int tx_total_pkts_dl=0;
   int rx_total_bytes_dl=0;
   int rx_total_pkts_dl=0;
-  float min_owd_dl=0;
-  float max_owd_dl=0;
   int tx_total_bytes_ul=0;
   int tx_total_pkts_ul=0;
   int rx_total_bytes_ul=0;
   int rx_total_pkts_ul=0;
+
+  float min_owd_dl=0;
+  float max_owd_dl=0;
+
   int tx_total_bytes_dl_background=0;
   int tx_total_pkts_dl_background=0;
   int rx_total_bytes_dl_background=0;
@@ -168,11 +193,20 @@ void kpi_gen() {
   int tx_total_pkts_ul_background=0;
   int rx_total_bytes_ul_background=0;
   int rx_total_pkts_ul_background=0;
+
   float min_owd_ul=0;
   float max_owd_ul=0;  
 
+
+  int tx_total_bytes_dl_multicast=0;
+  int tx_total_pkts_dl_multicast=0;
+  int rx_total_bytes_dl_multicast=0;
+  int rx_total_pkts_dl_multicast=0;
+
+
   int num_active_source=0;
  
+
 char traffic_type[12];
 char traffic[30];
 
@@ -192,181 +226,232 @@ fc=fopen("/tmp/otg.log","w");;
     for (j=0; j<(NB_eNB_INST + NB_UE_INST); j++){
 
 /*background stats*/
-if (i<NB_eNB_INST){
-		tx_total_bytes_dl_background+=otg_info->tx_num_bytes_background[i][j];
-	  tx_total_pkts_dl_background+=otg_info->tx_num_pkt_background[i][j];	
-	  rx_total_bytes_dl_background+=otg_info->rx_num_bytes_background[i][j];
-	  rx_total_pkts_dl_background+=otg_info->rx_num_pkt_background[i][j];
-
-	}
-	else{
-		tx_total_bytes_ul_background+=otg_info->tx_num_bytes_background[i][j];
-	  tx_total_pkts_ul_background+=otg_info->tx_num_pkt_background[i][j];	
-	  rx_total_bytes_ul_background+=otg_info->rx_num_bytes_background[i][j];
-	  rx_total_pkts_ul_background+=otg_info->rx_num_pkt_background[i][j];
-}
-     for (k=0; k<MAX_EMU_TRAFFIC; k++) {    
-      tx_throughput(i,j,k);
-      rx_goodput(i,j,k);
-      rx_loss_rate_pkts(i,j,k);
-      average_pkt_jitter(i,j,k);
-
-      //LOG_I(OTG,"KPI: (src=%d, dst=%d) NB packet TX= %d,  NB packet RX= %d\n ",i, j,  otg_info->tx_num_pkt[i][j],  otg_info->rx_num_pkt[i][j]);
-      
+      if (i<NB_eNB_INST){
+	tx_total_bytes_dl_background+=otg_info->tx_num_bytes_background[i][j];
+	tx_total_pkts_dl_background+=otg_info->tx_num_pkt_background[i][j];	
+	rx_total_bytes_dl_background+=otg_info->rx_num_bytes_background[i][j];
+	rx_total_pkts_dl_background+=otg_info->rx_num_pkt_background[i][j];
+      }
+      else{
+	tx_total_bytes_ul_background+=otg_info->tx_num_bytes_background[i][j];
+	tx_total_pkts_ul_background+=otg_info->tx_num_pkt_background[i][j];	
+	rx_total_bytes_ul_background+=otg_info->rx_num_bytes_background[i][j];
+	rx_total_pkts_ul_background+=otg_info->rx_num_pkt_background[i][j];
+      }
       
-     if ((otg_info->tx_throughput[i][j][k]>0)||((otg_info->tx_throughput_background[i][j]>0) && (otg_info->tx_num_bytes[i][j][k]>0)))  {
-       
-       num_active_source+=1;
-       
-       if (i<NB_eNB_INST){
-   	tx_total_bytes_dl+=otg_info->tx_num_bytes[i][j][k];
-	  tx_total_pkts_dl+=otg_info->tx_num_pkt[i][j][k];	
-	  rx_total_bytes_dl+=otg_info->rx_num_bytes[i][j][k];
-	  rx_total_pkts_dl+=otg_info->rx_num_pkt[i][j][k];
-	  /*tx_total_bytes_dl_background+=otg_info->tx_num_bytes_background[i][j];
-	  tx_total_pkts_dl_background+=otg_info->tx_num_pkt_background[i][j];	
-	  rx_total_bytes_dl_background+=otg_info->rx_num_bytes_background[i][j];
-	  rx_total_pkts_dl_background+=otg_info->rx_num_pkt_background[i][j]; */
-	  if ((min_owd_dl>otg_info->rx_owd_min[i][j][k]) || (min_owd_dl==0))
-	    min_owd_dl=otg_info->rx_owd_min[i][j][k];
-	  if ((max_owd_dl<otg_info->rx_owd_max[i][j][k]) || (max_owd_dl==0))
-	    max_owd_dl=otg_info->rx_owd_max[i][j][k];
-	}
-	else{
-   	tx_total_bytes_ul+=otg_info->tx_num_bytes[i][j][k];
-	  tx_total_pkts_ul+=otg_info->tx_num_pkt[i][j][k];	
-	  rx_total_bytes_ul+=otg_info->rx_num_bytes[i][j][k];
-	  rx_total_pkts_ul+=otg_info->rx_num_pkt[i][j][k];
-   	/*tx_total_bytes_ul_background+=otg_info->tx_num_bytes_background[i][j];
-	  tx_total_pkts_ul_background+=otg_info->tx_num_pkt_background[i][j];	
-	  rx_total_bytes_ul_background+=otg_info->rx_num_bytes_background[i][j];
-	  rx_total_pkts_ul_background+=otg_info->rx_num_pkt_background[i][j];*/
-	  if ((min_owd_ul>otg_info->rx_owd_min[i][j][k]) || (min_owd_ul==0))
-	    min_owd_ul=otg_info->rx_owd_min[i][j][k];
-	  if ((max_owd_ul<otg_info->rx_owd_max[i][j][k]) || (max_owd_ul==0))
-	    max_owd_ul=otg_info->rx_owd_max[i][j][k];
-	}
-
-	//LOG_D(OTG,"KPI: (src=%d, dst=%d, appli %d) NB packet TX= %d,  NB packet RX= %d\n ",i, j,  otg_info->tx_num_pkt[i][j][k],  otg_info->rx_num_pkt[i][j][k]);
-
-	if (g_otg->application_idx[i][j]>1)
-		strcpy(traffic_type,"GATEWAY");
-	else
-		strcpy(traffic_type,"APPLICATION");
-
-
-  switch  (k) {
-    case  0 : 
-			strcpy(traffic,"CUSTOMIZED TRAFFIC ");
-       break;
-     case 1 :
-			strcpy(traffic,"M2M");
-       break;
-     case 2 :
-			strcpy(traffic,"SCBR");
-       break;
-     case 3 :
-			strcpy(traffic,"MCBR");
-       break;
-     case 4 :
-			strcpy(traffic,"BCBR");
-       break;
-     case 5 :
-			strcpy(traffic,"AUTO_PILOT");
-       break;
-     case 6 :
-			strcpy(traffic,"BICYCLE_RACE");
-       break;
-     case 7 :
-			strcpy(traffic,"OPENARENA");
-       break;
-     case 8 :
-			strcpy(traffic,"TEAM_FORTRESS");
-       break;
-     case 9 :
-			strcpy(traffic,"FULL_BUFFER");
-       break;
-     case 10 :
-			strcpy(traffic,"M2M_TRAFFIC");
-       break;
-     case 11 :
-			strcpy(traffic,"AUTO_PILOT_L");
-       break;
-     case 12 :
-			strcpy(traffic,"AUTO_PILOT_M");
-       break;
-     case 13 :
-			strcpy(traffic,"AUTO_PILOT_H");
-       break;
-     case 14 :
-			strcpy(traffic,"AUTO_PILOT_E");
-       break;
-     case 15 :
-			strcpy(traffic,"VIRTUAL_GAME_L");
-       break;
-     case 16 :
-			strcpy(traffic,"VIRTUAL_GAME_M");
-       break;
-     case 17 :
-			strcpy(traffic,"VIRTUAL_GAME_H");
-       break;
-     case 18 :
-			strcpy(traffic,"VIRTUAL_GAME_F"); 
-       break;
-     case 19 :
-			strcpy(traffic,"ALARM_HUMIDITY"); 
-       break;
-     case 20 :
-			strcpy(traffic,"ALARM_SMOKE"); 
-       break;
-     case 21 :
-			strcpy(traffic,"ALARM_TEMPERATURE"); 
-       break;
-     case 22 :
-			strcpy(traffic,"OPENARENA_DL"); 
-       break;
-     case 23 :
-			strcpy(traffic,"OPENARENA_UL"); 
-       break;
-     case 24 :
-			strcpy(traffic,"VOIP_G711"); 
-       break;
-     case 25 :
-			strcpy(traffic,"VOIP_G729"); 
-       break;
-     case 26 :
-			strcpy(traffic,"IQSIM_MANGO"); 
-       break;
-     case 27 :
-			strcpy(traffic,"IQSIM_NEWSTEO"); 
-       break;
-     case 28 :
-			strcpy(traffic,"OPEMARENA_DL_TARMA"); 
-       break;
-     case 29 :
-			strcpy(traffic,"VIDEO_VBR_10MBPS"); 
-       break;
-     case 30 :
-			strcpy(traffic,"VIDEO_VBR_4MBPS"); 
-       break;
-     case 31 :
-			strcpy(traffic,"VIDEO_VBR_2MBPS"); 
-       break;
-     case 32 :
-			strcpy(traffic,"VIDEO_VBR_768KBPS"); 
-       break;
-     case 33 :
-			strcpy(traffic,"VIDEO_VBR_384KBPS"); 
-       break;
-     case 34 :
-			strcpy(traffic,"VIDEO_VBR_192KBPS"); 
-       break;
- default:
-       strcpy(traffic,"UKNOWN TRAFFIC"); 
- 			break;
-     }
-
+      for (k=0; k<MAX_EMU_TRAFFIC; k++) {    
+	
+	tx_throughput(i,j,k);
+	rx_goodput(i,j,k);
+	rx_loss_rate_pkts(i,j,k);
+	average_pkt_jitter(i,j,k);
 
+	//LOG_I(OTG,"KPI: (src=%d, dst=%d) NB packet TX= %d,  NB packet RX= %d\n ",i, j,  otg_info->tx_num_pkt[i][j],  otg_info->rx_num_pkt[i][j]);
+	
+	if (otg_multicast_info->tx_throughput[i][j]>0)  { 
+	  //multicast
+	  tx_total_bytes_dl_multicast+=otg_multicast_info->tx_num_bytes[i][j][k];
+	  tx_total_pkts_dl_multicast+=otg_multicast_info->tx_num_pkt[i][j][k];	
+	  rx_total_bytes_dl_multicast+=otg_multicast_info->rx_num_bytes[i][j][k];
+	  rx_total_pkts_dl_multicast+=otg_multicast_info->rx_num_pkt[i][j][k];
+	  
+#ifdef STANDALONE
+	  LOG_I(OTG,"No stats for multicast ");       // do nothing
+#else
+	  // Multicast 
+	  //no multicast_status
+	  if (otg_multicast_info->tx_num_bytes[i][j][k]>0){
+	    LOG_I(OTG,"----------------------------------------------------------\n");
+	    LOG_I(OTG,"Total Time (multicast) (ms)= %d \n", otg_info->ctime+1);
+	    
+	    //	 LOG_I(OTG,"[%s] Multicast [eNB:%d -> UE:%d] \n",traffic_type, i, j);
+	    
+	    LOG_I(OTG,"[MULTICAST] Total packets(TX)= %d \n", otg_multicast_info->tx_num_pkt[i][j][k]);
+	    LOG_I(OTG,"[MULTICAST] Total bytes(TX)= %d \n", otg_multicast_info->tx_num_bytes[i][j][k]);
+	    LOG_I(OTG,"[MULTICAST] Total packets(RX)= %d \n", otg_multicast_info->rx_num_pkt[i][j][k]);
+	    LOG_I(OTG,"[MULTICAST] Total bytes(RX)= %d \n", otg_multicast_info->rx_num_bytes[i][j][k]);
+	    
+	    LOG_I(OTG,"[MULTICAST] TX throughput = %.7f (Kbit/s) \n", otg_multicast_info->tx_throughput[i][j]);
+	    LOG_I(OTG,"[MULTICAST] RX goodput = %.7f (Kbit/s) \n", otg_multicast_info->rx_goodput[i][j]);
+	    //	 if (otg_multicast_info->rx_loss_rate[i][j]>0){
+	    //  LOG_I(OTG,"[MULTICAST] Loss rate = %lf \n", (otg_multicast_info->rx_loss_rate[i][j]));
+	    //  LOG_I(OTG,"[MULTICAST] NB Lost  packets=%d \n", (otg_multicast_info->tx_num_pkt[i][j][k]-otg_multicast_info->rx_num_pkt[i][j][k]));
+	    //}
+	    
+	    // if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
+	    LOG_F(OTG,"----------------------------------------------------------\n");
+	    LOG_F(OTG,"Total Time (multicast) (ms)= %d \n", otg_info->ctime+1);
+	    //  if (i<NB_eNB_INST){
+	    LOG_F(OTG,"[%s] DL [eNB:%d -> UE:%d] \n",traffic_type ,i, j);
+	    //else
+	    //		LOG_F(OTG,"[%s] UL [Ue:%d -> eNB:%d] \n",traffic_type, i, j);
+	    LOG_F(OTG,"[MULTICAST] Total packets(TX)= %d \n", otg_multicast_info->tx_num_pkt[i][j][k]);
+	    LOG_F(OTG,"[MULTICAST] Total bytes(TX)= %d \n", otg_multicast_info->tx_num_bytes[i][j][k]);
+	    LOG_F(OTG,"[MULTICAST] TX throughput = %.7f(Kbit/s) \n", otg_multicast_info->tx_throughput[i][j]);
+	    LOG_F(OTG,"[MULTICAST] RX goodput= %.7f (Kbit/s) \n", otg_multicast_info->rx_goodput[i][j]);
+	    if (otg_multicast_info->rx_loss_rate[i][j]>0){
+	      LOG_F(OTG,"[MULTICAST] Loss rate = %lf \n", (otg_multicast_info->rx_loss_rate[i][j]));
+	      LOG_F(OTG,"[MULTICAST] NB Lost  packets=%d \n", (otg_multicast_info->tx_num_pkt[i][j][k]-otg_multicast_info->rx_num_pkt[i][j][k]));
+	    }
+	  }
+#endif
+	  
+	}// end for multicast
+	
+	if ((otg_info->tx_throughput[i][j][k]>0)||((otg_info->tx_throughput_background[i][j]>0) && (otg_info->tx_num_bytes[i][j][k]>0)))  {
+	  
+	  num_active_source+=1;
+	  
+	  if (i<NB_eNB_INST){ // DL
+	    tx_total_bytes_dl+=otg_info->tx_num_bytes[i][j][k];
+	    tx_total_pkts_dl+=otg_info->tx_num_pkt[i][j][k];	
+	    rx_total_bytes_dl+=otg_info->rx_num_bytes[i][j][k];
+	    rx_total_pkts_dl+=otg_info->rx_num_pkt[i][j][k];
+	    /*tx_total_bytes_dl_background+=otg_info->tx_num_bytes_background[i][j];
+	      tx_total_pkts_dl_background+=otg_info->tx_num_pkt_background[i][j];	
+	      rx_total_bytes_dl_background+=otg_info->rx_num_bytes_background[i][j];
+	      rx_total_pkts_dl_background+=otg_info->rx_num_pkt_background[i][j]; */
+	    
+	    if ((min_owd_dl>otg_info->rx_owd_min[i][j][k]) || (min_owd_dl==0))
+	      min_owd_dl=otg_info->rx_owd_min[i][j][k];
+	    if ((max_owd_dl<otg_info->rx_owd_max[i][j][k]) || (max_owd_dl==0))
+	      max_owd_dl=otg_info->rx_owd_max[i][j][k];
+	  }
+	  else { // UL
+	    tx_total_bytes_ul+=otg_info->tx_num_bytes[i][j][k];
+	    tx_total_pkts_ul+=otg_info->tx_num_pkt[i][j][k];	
+	    rx_total_bytes_ul+=otg_info->rx_num_bytes[i][j][k];
+	    rx_total_pkts_ul+=otg_info->rx_num_pkt[i][j][k];
+	    /*tx_total_bytes_ul_background+=otg_info->tx_num_bytes_background[i][j];
+	      tx_total_pkts_ul_background+=otg_info->tx_num_pkt_background[i][j];	
+	      rx_total_bytes_ul_background+=otg_info->rx_num_bytes_background[i][j];
+	      rx_total_pkts_ul_background+=otg_info->rx_num_pkt_background[i][j];*/
+	    if ((min_owd_ul>otg_info->rx_owd_min[i][j][k]) || (min_owd_ul==0))
+	      min_owd_ul=otg_info->rx_owd_min[i][j][k];
+	    if ((max_owd_ul<otg_info->rx_owd_max[i][j][k]) || (max_owd_ul==0))
+	      max_owd_ul=otg_info->rx_owd_max[i][j][k];
+	  }
+	  
+	  //LOG_D(OTG,"KPI: (src=%d, dst=%d, appli %d) NB packet TX= %d,  NB packet RX= %d\n ",i, j,  otg_info->tx_num_pkt[i][j][k],  otg_info->rx_num_pkt[i][j][k]);
+	  
+	  if (g_otg->application_idx[i][j]>1)
+	    strcpy(traffic_type,"GATEWAY");
+	  else
+	    strcpy(traffic_type,"APPLICATION");
+	  
+	  
+	  switch  (k) {
+	  case  0 : 
+	    strcpy(traffic,"CUSTOMIZED TRAFFIC ");
+	    break;
+	  case 1 :
+	    strcpy(traffic,"M2M");
+	    break;
+	  case 2 :
+	    strcpy(traffic,"SCBR");
+	    break;
+	  case 3 :
+	    strcpy(traffic,"MCBR");
+	    break;
+	  case 4 :
+	    strcpy(traffic,"BCBR");
+	    break;
+	  case 5 :
+	    strcpy(traffic,"AUTO_PILOT");
+	    break;
+	  case 6 :
+	    strcpy(traffic,"BICYCLE_RACE");
+	    break;
+	  case 7 :
+	    strcpy(traffic,"OPENARENA");
+	    break;
+	  case 8 :
+	    strcpy(traffic,"TEAM_FORTRESS");
+	    break;
+	  case 9 :
+	    strcpy(traffic,"FULL_BUFFER");
+	    break;
+	  case 10 :
+	    strcpy(traffic,"M2M_TRAFFIC");
+	    break;
+	  case 11 :
+	    strcpy(traffic,"AUTO_PILOT_L");
+	    break;
+	  case 12 :
+	    strcpy(traffic,"AUTO_PILOT_M");
+	    break;
+	  case 13 :
+	    strcpy(traffic,"AUTO_PILOT_H");
+	    break;
+	  case 14 :
+	    strcpy(traffic,"AUTO_PILOT_E");
+	    break;
+	  case 15 :
+	    strcpy(traffic,"VIRTUAL_GAME_L");
+	    break;
+	  case 16 :
+	    strcpy(traffic,"VIRTUAL_GAME_M");
+	    break;
+	  case 17 :
+	    strcpy(traffic,"VIRTUAL_GAME_H");
+	    break;
+	  case 18 :
+	    strcpy(traffic,"VIRTUAL_GAME_F"); 
+	    break;
+	  case 19 :
+	    strcpy(traffic,"ALARM_HUMIDITY"); 
+	    break;
+	  case 20 :
+	    strcpy(traffic,"ALARM_SMOKE"); 
+	    break;
+	  case 21 :
+	    strcpy(traffic,"ALARM_TEMPERATURE"); 
+	    break;
+	  case 22 :
+	    strcpy(traffic,"OPENARENA_DL"); 
+	    break;
+	  case 23 :
+	    strcpy(traffic,"OPENARENA_UL"); 
+	    break;
+	  case 24 :
+	    strcpy(traffic,"VOIP_G711"); 
+	    break;
+	  case 25 :
+	    strcpy(traffic,"VOIP_G729"); 
+	    break;
+	  case 26 :
+	    strcpy(traffic,"IQSIM_MANGO"); 
+	    break;
+	  case 27 :
+	    strcpy(traffic,"IQSIM_NEWSTEO"); 
+	    break;
+	  case 28 :
+	    strcpy(traffic,"OPEMARENA_DL_TARMA"); 
+	    break;
+	  case 29 :
+	    strcpy(traffic,"VIDEO_VBR_10MBPS"); 
+	    break;
+	  case 30 :
+	    strcpy(traffic,"VIDEO_VBR_4MBPS"); 
+	    break;
+	  case 31 :
+	    strcpy(traffic,"VIDEO_VBR_2MBPS"); 
+	    break;
+	  case 32 :
+	    strcpy(traffic,"VIDEO_VBR_768KBPS"); 
+	    break;
+	  case 33 :
+	    strcpy(traffic,"VIDEO_VBR_384KBPS"); 
+	    break;
+	  case 34 :
+	    strcpy(traffic,"VIDEO_VBR_192KBPS"); 
+	    break;
+	  default:
+	    strcpy(traffic,"UKNOWN TRAFFIC"); 
+	    break;
+	  }
+	  
+	  
 
 
 
@@ -378,17 +463,17 @@ if (i<NB_eNB_INST){
 		fprintf(file,"[%s] DL [eNB:%d, UE:%d][%s] \n", traffic_type,i,j,traffic);}
 	else
 		fprintf(file,"[%s] UL [eNB:%d, UE:%d][%s] \n",traffic_type,j,i,traffic);
-		fprintf(file,"[%s] Total packets(TX)= %d \n",traffic_type, otg_info->tx_num_pkt[i][j][k]);
-		fprintf(file,"[%s] Total bytes(TX)= %d \n",traffic_type, otg_info->tx_num_bytes[i][j][k]);
-		fprintf(file,"[%s] OWD MIN (one way)ms= %.2f \n",traffic_type, otg_info->rx_owd_min[i][j][k]);
-		fprintf(file,"[%s] OWD MAX (one way)ms= %.2f \n",traffic_type, otg_info->rx_owd_max[i][j][k]);
-		fprintf(file,"[%s] TX throughput = %.7f(Kbit/s) \n",traffic_type, otg_info->tx_throughput[i][j][k]);
-		fprintf(file,"[%s] RX goodput= %.7f (K/s) \n",traffic_type, otg_info->rx_goodput[i][j][k]);
-		if (otg_info->rx_loss_rate[i][j[k]]>0){
-	  	fprintf(file,"[%s] Loss rate = %.2f \n",traffic_type, (otg_info->rx_loss_rate[i][j][k]));
-	  	fprintf(file,"[%s] NB Lost  packets=%d \n",traffic_type, (otg_info->tx_num_pkt[i][j][k]-otg_info->rx_num_pkt[i][j][k]));
-	  	//fprintf(file,"[%s] NB Lost [OTG] packets=%d \n",traffic_type, otg_info->nb_loss_pkts_otg[i][j]);
-		}
+  fprintf(file,"[%s] Total packets(TX)= %d \n",traffic_type, otg_info->tx_num_pkt[i][j][k]);
+  fprintf(file,"[%s] Total bytes(TX)= %d \n",traffic_type, otg_info->tx_num_bytes[i][j][k]);
+  fprintf(file,"[%s] OWD MIN (one way)ms= %.2f \n",traffic_type, otg_info->rx_owd_min[i][j][k]);
+  fprintf(file,"[%s] OWD MAX (one way)ms= %.2f \n",traffic_type, otg_info->rx_owd_max[i][j][k]);
+  fprintf(file,"[%s] TX throughput = %.7f(Kbit/s) \n",traffic_type, otg_info->tx_throughput[i][j][k]);
+  fprintf(file,"[%s] RX goodput= %.7f (K/s) \n",traffic_type, otg_info->rx_goodput[i][j][k]);
+  if (otg_info->rx_loss_rate[i][j[k]]>0){
+    fprintf(file,"[%s] Loss rate = %.2f \n",traffic_type, (otg_info->rx_loss_rate[i][j][k]));
+    fprintf(file,"[%s] NB Lost  packets=%d \n",traffic_type, (otg_info->tx_num_pkt[i][j][k]-otg_info->rx_num_pkt[i][j][k]));
+    //fprintf(file,"[%s] NB Lost [OTG] packets=%d \n",traffic_type, otg_info->nb_loss_pkts_otg[i][j]);
+  }
 
  /* if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
     fprintf(file,"[BACKGROUND] Total packets(TX)= %d \n", otg_info->tx_num_pkt_background[i][j]);
@@ -472,8 +557,12 @@ if (i<NB_eNB_INST){
 */
 #endif 
 
-      }
-    }
+     }
+     
+     //     if ((otg_multicast_info->tx_throughput[i][j]>0) && (otg_info->tx_num_bytes[i][j][k]>0))  {
+
+     }// end loop of k
+
 
 
 #ifdef STANDALONE
@@ -496,46 +585,48 @@ if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
 	  }
 	}
 #else
-if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
- LOG_I(OTG,"----------------------------------------------------------\n");
-  LOG_I(OTG,"Total Time (ms)= %d \n", otg_info->ctime+1);
-  if (i<NB_eNB_INST){
-    LOG_I(OTG,"[%s] DL [eNB:%d -> UE:%d] \n",traffic_type, i, j);}
-  else
-    LOG_I(OTG,"[%s] UL [UE:%d -> eNB:%d] \n",traffic_type, i, j);
-
-    LOG_I(OTG,"[BACKGROUND] Total packets(TX)= %d \n", otg_info->tx_num_pkt_background[i][j]);
-	  LOG_I(OTG,"[BACKGROUND] Total bytes(TX)= %d \n", otg_info->tx_num_bytes_background[i][j]);
-	  LOG_I(OTG,"[BACKGROUND] TX throughput = %.7f(Kbit/s) \n", otg_info->tx_throughput_background[i][j]);
-	  LOG_I(OTG,"[BACKGROUND] RX goodput= %.7f (Kbit/s) \n", otg_info->rx_goodput_background[i][j]);
-	  if (otg_info->rx_loss_rate_background[i][j]>0){
-	    LOG_I(OTG,"[BACKGROUND] Loss rate = %lf \n", (otg_info->rx_loss_rate_background[i][j]));
-	    LOG_I(OTG,"[BACKGROUND] NB Lost  packets=%d \n", (otg_info->tx_num_pkt_background[i][j]-otg_info->rx_num_pkt_background[i][j]));
-	  }
-	}
 
-if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
-	LOG_F(OTG,"----------------------------------------------------------\n");
-	LOG_F(OTG,"Total Time (ms)= %d \n", otg_info->ctime+1);
-	if (i<NB_eNB_INST){
-		LOG_F(OTG,"[%s] DL [eNB:%d -> UE:%d] \n",traffic_type ,i, j);}
-	else
+ if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
+   LOG_I(OTG,"----------------------------------------------------------\n");
+   LOG_I(OTG,"Total Time (ms)= %d \n", otg_info->ctime+1);
+   if (i<NB_eNB_INST){
+     LOG_I(OTG,"[%s] DL [eNB:%d -> UE:%d] \n",traffic_type, i, j);}
+   else
+     LOG_I(OTG,"[%s] UL [UE:%d -> eNB:%d] \n",traffic_type, i, j);
+
+   LOG_I(OTG,"[BACKGROUND] Total packets(TX)= %d \n", otg_info->tx_num_pkt_background[i][j]);
+   LOG_I(OTG,"[BACKGROUND] Total bytes(TX)= %d \n", otg_info->tx_num_bytes_background[i][j]);
+   LOG_I(OTG,"[BACKGROUND] TX throughput = %.7f(Kbit/s) \n", otg_info->tx_throughput_background[i][j]);
+   LOG_I(OTG,"[BACKGROUND] RX goodput= %.7f (Kbit/s) \n", otg_info->rx_goodput_background[i][j]);
+   if (otg_info->rx_loss_rate_background[i][j]>0){
+     LOG_I(OTG,"[BACKGROUND] Loss rate = %lf \n", (otg_info->rx_loss_rate_background[i][j]));
+     LOG_I(OTG,"[BACKGROUND] NB Lost  packets=%d \n", (otg_info->tx_num_pkt_background[i][j]-otg_info->rx_num_pkt_background[i][j]));
+   }
+ }
+ 
+ if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
+   LOG_F(OTG,"----------------------------------------------------------\n");
+   LOG_F(OTG,"Total Time (ms)= %d \n", otg_info->ctime+1);
+   if (i<NB_eNB_INST){
+     LOG_F(OTG,"[%s] DL [eNB:%d -> UE:%d] \n",traffic_type ,i, j);}
+   else
 		LOG_F(OTG,"[%s] UL [UE:%d -> eNB:%d] \n",traffic_type, i, j);
-
-  	LOG_F(OTG,"[BACKGROUND] Total packets(TX)= %d \n", otg_info->tx_num_pkt_background[i][j]);
-	  LOG_F(OTG,"[BACKGROUND] Total bytes(TX)= %d \n", otg_info->tx_num_bytes_background[i][j]);
-	  LOG_F(OTG,"[BACKGROUND] TX throughput = %.7f(Kbit/s) \n", otg_info->tx_throughput_background[i][j]);
-	  LOG_F(OTG,"[BACKGROUND] RX goodput= %.7f (Kbit/s) \n", otg_info->rx_goodput_background[i][j]);
-	  if (otg_info->rx_loss_rate_background[i][j]>0){
-	    LOG_F(OTG,"[BACKGROUND] Loss rate = %lf \n", (otg_info->rx_loss_rate_background[i][j]));
-	    LOG_F(OTG,"[BACKGROUND] NB Lost  packets=%d \n", (otg_info->tx_num_pkt_background[i][j]-otg_info->rx_num_pkt_background[i][j]));
-	  }
-	}
+   
+   LOG_F(OTG,"[BACKGROUND] Total packets(TX)= %d \n", otg_info->tx_num_pkt_background[i][j]);
+   LOG_F(OTG,"[BACKGROUND] Total bytes(TX)= %d \n", otg_info->tx_num_bytes_background[i][j]);
+   LOG_F(OTG,"[BACKGROUND] TX throughput = %.7f(Kbit/s) \n", otg_info->tx_throughput_background[i][j]);
+   LOG_F(OTG,"[BACKGROUND] RX goodput= %.7f (Kbit/s) \n", otg_info->rx_goodput_background[i][j]);
+   if (otg_info->rx_loss_rate_background[i][j]>0){
+     LOG_F(OTG,"[BACKGROUND] Loss rate = %lf \n", (otg_info->rx_loss_rate_background[i][j]));
+     LOG_F(OTG,"[BACKGROUND] NB Lost  packets=%d \n", (otg_info->tx_num_pkt_background[i][j]-otg_info->rx_num_pkt_background[i][j]));
+   }
+ }
 #endif
 
 
-		}	
-  }
+    }// end loop of j	
+  }// end loop of i
+
   
   //  average_total_jitter();
   
@@ -598,6 +689,16 @@ if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
     LOG_I(OTG,"[BACKGROUND] TX throughput = %.7f(Kbit/s) \n", ((double)tx_total_bytes_dl_background*1000*8)/(otg_info->ctime*1024));
     LOG_I(OTG,"[BACKGROUND] RX throughput = %.7f(Kbit/s) \n", ((double)rx_total_bytes_dl_background*1000*8)/(otg_info->ctime*1024));
 	}
+  if (tx_total_pkts_dl_multicast>0){
+    LOG_I(OTG,"[MULTICAST] Total packets(TX)= %d \n", tx_total_pkts_dl_multicast);
+    LOG_I(OTG,"[MULTICAST] Total bytes(TX)= %d \n", tx_total_bytes_dl_multicast);
+    LOG_I(OTG,"[MULTICAST] Total packets(RX)= %d \n", rx_total_pkts_dl_multicast);
+    LOG_I(OTG,"[MULTICAST] Total bytes(RX)= %d \n", rx_total_bytes_dl_multicast);
+    LOG_I(OTG,"[MULTICAST] otg_multicast_info->ctime = %d \n", otg_multicast_info->ctime);
+    LOG_I(OTG,"[MULTICAST] TX throughput = %.7f(Kbit/s) \n", ((double)tx_total_bytes_dl_multicast*1000*8)/(otg_info->ctime*1024));
+    LOG_I(OTG,"[MULTICAST] RX throughput = %.7f(Kbit/s) \n", ((double)rx_total_bytes_dl_multicast*1000*8)/(otg_info->ctime*1024));
+	}
+ 
 
   LOG_F(OTG,"**************** TOTAL DL RESULTS ******************\n");
   LOG_F(OTG,"Total Time (ms)= %d \n", otg_info->ctime+1);
@@ -619,6 +720,15 @@ if ((g_otg->background_stats==1)&&(otg_info->tx_num_bytes_background[i][j]>0)){
     LOG_F(OTG,"[BACKGROUND] TX throughput = %.7f(Kbit/s) \n", ((double)tx_total_bytes_dl_background*1000*8)/(otg_info->ctime*1024));
     LOG_F(OTG,"[BACKGROUND] RX throughput = %.7f(Kbit/s) \n", ((double)rx_total_bytes_dl_background*1000*8)/(otg_info->ctime*1024));
 	}
+  if (tx_total_pkts_dl_multicast>0){
+    LOG_F(OTG,"[MULTICAST] Total packets(TX)= %d \n", tx_total_pkts_dl_multicast);
+    LOG_F(OTG,"[MULTICAST] Total bytes(TX)= %d \n", tx_total_bytes_dl_multicast);
+    LOG_F(OTG,"[MULTICAST] Total packets(RX)= %d \n", rx_total_pkts_dl_multicast);
+    LOG_F(OTG,"[MULTICAST] Total bytes(RX)= %d \n", rx_total_bytes_dl_multicast);
+    LOG_F(OTG,"[MULTICAST] TX throughput = %.7f(Kbit/s) \n", ((double)tx_total_bytes_dl_multicast*1000*8)/(otg_info->ctime*1024));
+    LOG_F(OTG,"[MULTICAST] RX throughput = %.7f(Kbit/s) \n", ((double)rx_total_bytes_dl_multicast*1000*8)/(otg_info->ctime*1024));
+	}
+ 
 
   
 	LOG_I(OTG,"**************** TOTAL UL RESULTS ******************\n");
diff --git a/openair2/UTIL/OTG/otg_rx.c b/openair2/UTIL/OTG/otg_rx.c
index a428c605526..a3a7f44ada9 100644
--- a/openair2/UTIL/OTG/otg_rx.c
+++ b/openair2/UTIL/OTG/otg_rx.c
@@ -105,13 +105,13 @@ int otg_rx_pkt( int src, int dst, int ctime, char *buffer_tx, unsigned int size)
       }
       else if (otg_hdr_info_rx->flag == 0x1000){
 	seq_num_rx = otg_multicast_info->rx_sn[src][dst][otg_hdr_rx->traffic_type];
+	nb_loss_pkts = otg_multicast_info->loss_pkts_dl[src][dst][otg_hdr_rx->traffic_type];
 	//	otg_multicast_info->ran_owd[src][dst][otg_hdr_rx->traffic_type] = ctime- otg_hdr_rx->time;
-	nb_loss_pkts = otg_multicast_info->loss_rate[src][dst][otg_hdr_rx->traffic_type];
 	//	rx_check_loss(src, dst, otg_hdr_info_rx->flag, otg_hdr_rx->seq_num, &seq_num_rx, &nb_loss_pkts);
 	//	otg_multicast_info->loss_rate[src][dst][otg_hdr_rx->traffic_type]=nb_loss_pkts;
 	//otg_multicast_info->rx_sn[src][dst][otg_hdr_rx->traffic_type]=seq_num_rx;
-	LOG_I(OTG,"received a multicast packet with size %d sn %d ran owd %d loss rate %d\n",
-	      otg_hdr_info_rx->size, seq_num_rx, ctime- otg_hdr_rx->time, nb_loss_pkts);
+	//	LOG_I(OTG,"received a multicast packet with size %d sn %d ran owd %d loss rate %d\n",
+	//	      otg_hdr_info_rx->size, seq_num_rx, ctime- otg_hdr_rx->time, nb_loss_pkts);
 	//return 0;
 	
       }
@@ -134,8 +134,6 @@ int otg_rx_pkt( int src, int dst, int ctime, char *buffer_tx, unsigned int size)
       if (otg_info->owd_const[src][dst][otg_hdr_rx->flow_id]==0)
 	owd_const_gen(src,dst,otg_hdr_rx->flow_id, otg_hdr_rx->traffic_type);
       
-      
-      
      
 	/******/
 /*
@@ -175,6 +173,8 @@ float owd_const_application_v=owd_const_application()/2;
       }
 
       if (otg_hdr_info_rx->flag == 0x1000){
+	LOG_I(OTG,"received a multicast packet at time %d with size %d, seq num %d, ran owd %d number loss packet %d\n",
+	      ctime,otg_hdr_info_rx->size, otg_hdr_rx->seq_num, ctime - otg_hdr_rx->time, nb_loss_pkts);
 	
 	LOG_I(OTG,"INFO LATENCY :: [SRC %d][DST %d] radio access %.2f (tx time %d, ctime %d), OWD:%.2f (ms):\n", 
 	      src, dst, otg_multicast_info->radio_access_delay[src][dst], otg_hdr_rx->time, ctime , otg_multicast_info->rx_pkt_owd[src][dst]);
@@ -187,13 +187,12 @@ float owd_const_application_v=owd_const_application()/2;
 	  otg_multicast_info->rx_owd_max[src][dst][otg_hdr_rx->traffic_type]=MAX(otg_multicast_info->rx_owd_max[src][dst][otg_hdr_rx->traffic_type],otg_multicast_info->rx_pkt_owd[src][dst] );
 	  otg_multicast_info->rx_owd_min[src][dst][otg_hdr_rx->traffic_type]=MIN(otg_multicast_info->rx_owd_min[src][dst][otg_hdr_rx->traffic_type],otg_multicast_info->rx_pkt_owd[src][dst] );
 	}
-	
 	if (g_otg->curve==1){ 
 	  if (g_otg->owd_radio_access==0)
 	    add_tab_metric(src, dst, otg_multicast_info->rx_pkt_owd[src][dst],  ((otg_hdr_info_rx->size*1000*8)/(otg_multicast_info->rx_pkt_owd[src][dst]*1024 )),  otg_hdr_rx->time);
 	  else
 	    add_tab_metric(src, dst, otg_multicast_info->radio_access_delay[src][dst],  ((otg_hdr_info_rx->size*1000*8)/(otg_multicast_info->rx_pkt_owd[src][dst]*1024 )),  otg_hdr_rx->time);    
-	}
+	    }
 	otg_multicast_info->rx_total_bytes_dl+=otg_hdr_info_rx->size;
       }
       else {
@@ -277,6 +276,7 @@ float owd_const_application_v=owd_const_application()/2;
       else if (otg_hdr_info_rx->flag == 0x1000){
 	otg_multicast_info->rx_num_pkt[src][dst][otg_hdr_rx->traffic_type]+=1;
 	otg_multicast_info->rx_num_bytes[src][dst][otg_hdr_rx->traffic_type]+=otg_hdr_info_rx->size;
+	//	LOG_D(OTG,"DUY: otg_multicast_info->rx_num_bytes[%d][%d][%d] is %d \nn",src,dst,otg_hdr_rx->traffic_type,otg_multicast_info->rx_num_bytes[src][dst][otg_hdr_rx->traffic_type]);
 	otg_multicast_info->rx_sn[src][dst][otg_hdr_rx->traffic_type]=seq_num_rx;
 	otg_multicast_info->loss_pkts_dl[src][dst][otg_hdr_rx->traffic_type]=nb_loss_pkts;
 
diff --git a/openair2/UTIL/OTG/otg_tx.c b/openair2/UTIL/OTG/otg_tx.c
index d0a4863a29b..7e7058a83c1 100644
--- a/openair2/UTIL/OTG/otg_tx.c
+++ b/openair2/UTIL/OTG/otg_tx.c
@@ -306,14 +306,20 @@ unsigned char *packet_gen_multicast(int src, int dst, int ctime, int * pkt_size)
   char *header=NULL; 
   unsigned int flag;
   int app,seq_num=0;
-  int otg_hdr_size= + sizeof(otg_hdr_info_t) + sizeof(otg_hdr_t);
+  int otg_hdr_size= sizeof(otg_hdr_info_t) + sizeof(otg_hdr_t);
 
   set_ctime(ctime); // fixme: this should be done separetly from packet_gen and packet_gen_multicast
   //for (app=0; app<MAX_NUM_APPLICATION; app++){  
   for (app=0; app<1; app++){  
+
     if ( (g_otg_multicast->idt_dist[src][dst][app]> 0) &&  
 	 ((ctime - otg_multicast_info->ptime[src][dst][app]) >= otg_multicast_info->idt[src][dst][app]) && 
 	 (g_otg_multicast->duration[src][dst][app] > ctime) ){
+
+      //Duy add
+      LOG_I(OTG,"multicast gen: entering generating\n");
+      //end Duy add
+
       //otg_info->idt[src][dst][app]= time_dist(src, dst, app, -1);
       otg_multicast_info->idt[src][dst][app]=ceil(uniform_dist(g_otg_multicast->idt_min[src][dst][app], 
 							       g_otg_multicast->idt_max[src][dst][app]));
@@ -328,7 +334,7 @@ unsigned char *packet_gen_multicast(int src, int dst, int ctime, int * pkt_size)
       if (otg_multicast_info->header_size_app[src][dst][app]==0){
 	otg_multicast_info->header_size_app[src][dst][app]=1;
 	LOG_W(OTG,"header type not defined, set to 1\n");
-      }
+	}
       header = random_string(otg_multicast_info->header_size_app[src][dst][app], 
 			     g_otg->packet_gen_type, 
 			     HEADER_ALPHABET);
@@ -336,12 +342,15 @@ unsigned char *packet_gen_multicast(int src, int dst, int ctime, int * pkt_size)
       flag = 0x1000;
       seq_num=otg_multicast_info->tx_sn[src][dst][app]++;
       otg_multicast_info->tx_num_pkt[src][dst][app]+=1;
-      otg_multicast_info->tx_num_bytes[src][dst][app]+= strlen(header) + strlen(payload)+otg_hdr_size;
+      otg_multicast_info->tx_num_bytes[src][dst][app]+= strlen(header) + strlen(payload) + otg_hdr_size;
+      LOG_D(OTG,"otg_multicast_info->tx_num_bytes[%d][%d][%d] = %d \n",src,dst,app, otg_multicast_info->tx_num_bytes[src][dst][app]);
       if (size!=strlen(payload))
 	LOG_E(OTG,"[src %d][dst %d] The expected packet size does not match the payload size : size %d, strlen %d \n", src, dst, size, strlen(payload));
-      else 
+      else {
 	LOG_I(OTG,"[src %d][dst %d]TX INFO pkt at time %d Size= [payload %d] [Total %d] with seq num %d: |%s|%s| \n", 
 	      src, dst, ctime, size, strlen(header)+strlen(payload)+otg_hdr_size, seq_num, header, payload);
+	LOG_D(OTG,"\n");
+      }
   
       buffer_size = otg_hdr_size + strlen(header) + strlen(payload);
       *pkt_size = buffer_size;
@@ -353,7 +362,8 @@ unsigned char *packet_gen_multicast(int src, int dst, int ctime, int * pkt_size)
   }
   
   if (buffer_size)
-    return serialize_buffer(header, payload, buffer_size,g_otg_multicast->application_type[src][dst][app], flag, 0, ctime, seq_num, 0, HDR_IP_v4_MIN+HDR_UDP, 1);
+    return serialize_buffer(header, payload, buffer_size,0/*g_otg_multicast->application_type[src][dst][app]*/, flag, 0, ctime, seq_num, 0, HDR_IP_v4_MIN+HDR_UDP, 1);
+                    // application_types is MSCBR = 1 is set in g_otg_multicast init, but 0 is need in otg_rx for coherence with index of otg_multicast_info
   else 
     return NULL;
 }
@@ -652,9 +662,9 @@ unsigned char * serialize_buffer(char* header, char* payload, unsigned int buffe
 void init_predef_multicast_traffic() {
   int i, j, k;
 
-for (i=0; i<2; i++){ // src //maxServiceCount
-   for (j=0; j<2; j++){ // dst // maxSessionPerPMCH
-     for (k=0; k<MAX_NUM_APPLICATION; k++){  
+for (i=0; i<1; i++){ // src //maxServiceCount
+   for (j=1; j<2; j++){ // dst // maxSessionPerPMCH
+     for (k=0; k<1/*MAX_NUM_APPLICATION*/; k++){  
        switch(g_otg_multicast->application_type[i][j][k]){
 	  case  MSCBR : 
 	    //LOG_D(OTG, "configure MSCBR for MBMS (service %d, session %d, app %d)\n", i, j, k);
@@ -662,12 +672,13 @@ for (i=0; i<2; i++){ // src //maxServiceCount
 	    g_otg_multicast->ip_v[i][j][k]= IPV4;
 
 	    g_otg_multicast->idt_dist[i][j][k]= UNIFORM;
-	    g_otg_multicast->idt_min[i][j][k]= 20;
-	    g_otg_multicast->idt_max[i][j][k]= 100;
+	    g_otg_multicast->idt_min[i][j][k]= 20;// can modify here to increase the frequency of generate data
+	    g_otg_multicast->idt_max[i][j][k]= 50;
 
-	    g_otg_multicast->size_dist[i][j][k]= FIXED;
-	    g_otg_multicast->size_min[i][j][k]= 20;
-	    g_otg_multicast->size_max[i][j][k]= 100;
+	    g_otg_multicast->size_dist[i][j][k]= UNIFORM;
+	    g_otg_multicast->size_min[i][j][k]= 768;
+	    g_otg_multicast->size_max[i][j][k]= 1024 ;//can not be greater than 1500 which is max_ip_packet_size in pdcp.c
+	                                        
 
 	    g_otg_multicast->duration[i][j][k] = 1000; // the packet will be generated after duration 
 	    header_size_gen_multicast(i,j,k);
diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c
index e74018f25d3..bf01b8eaf58 100644
--- a/targets/SIMU/USER/oaisim.c
+++ b/targets/SIMU/USER/oaisim.c
@@ -753,7 +753,7 @@ int
 	  UE_id= oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local + RN_id; // NB_UE_INST + RN_id
 	  eNB_id= oai_emulation.info.first_enb_local+oai_emulation.info.nb_enb_local + RN_id; // NB_eNB_INST + RN_id
 	  // currently only works in FDD
-	  if (oai_emulation.info.eMBMS_active_state == 3){
+	  if (oai_emulation.info.eMBMS_active_state == 4){
 	    r_mode = multicast_relay;
 	    LOG_I(EMU,"Activating the multicast relaying\n");
 	  }else {
diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c
index 9a87c809117..63f6091b550 100644
--- a/targets/SIMU/USER/oaisim_functions.c
+++ b/targets/SIMU/USER/oaisim_functions.c
@@ -111,7 +111,6 @@ void get_simulation_options(int argc, char *argv[]) {
   };
 
   while ((c = getopt_long (argc, argv, "aA:b:B:c:C:D:d:eE:f:FGg:hi:j:IJ:k:l:m:M:n:N:oO:p:P:rR:s:S:Q:t:T:u:U:vVx:y:w:W:X:z:Z:", long_options, &option_index)) != -1) {
-
     switch (c) {
     case 0:
       if (! strcmp(long_options[option_index].name, "pdcp_period")) {
@@ -788,32 +787,65 @@ void update_otg_eNB(int module_id, unsigned int ctime) {
 
 #ifdef Rel10
     int service_id, session_id, rb_id;
-    // MBSM multicast traffic
-    for (service_id = 0; service_id < 2 ; service_id++) { //maxServiceCount
-      for (session_id = 0; session_id < 2; session_id++) { // maxSessionPerPMCH
-        if (pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].instanciated_instance== module_id + 1){ // this service/session is configured
-          otg_pkt = malloc (sizeof(Packet_otg_elt));
-          // LOG_T(OTG,"multicast packet gen for (service/mch %d, session/lcid %d)\n", service_id, session_id);
-          rb_id = pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].rb_id;
-          (otg_pkt->otg_pkt).sdu_buffer = (u8*) packet_gen_multicast(module_id, session_id, ctime, &((otg_pkt->otg_pkt).sdu_buffer_size));
-          if ((otg_pkt->otg_pkt).sdu_buffer != NULL) {
-            (otg_pkt->otg_pkt).rb_id = rb_id;
-            (otg_pkt->otg_pkt).module_id = module_id;
-            //(otg_pkt->otg_pkt).dst_id = session_id;
-            //Adding the packet to the OTG-PDCP buffer
-            (otg_pkt->otg_pkt).mode = PDCP_TM;
-            pkt_list_add_tail_eurecom(otg_pkt, &(otg_pdcp_buffer[module_id]));
-            LOG_I(EMU, "[eNB %d] ADD pkt to OTG buffer for dst %d on rb_id %d\n", (otg_pkt->otg_pkt).module_id, (otg_pkt->otg_pkt).dst_id,(otg_pkt->otg_pkt).rb_id);
-          } else {
-            //LOG_I(EMU, "OTG returns null \n");
-            free(otg_pkt);
-            otg_pkt=NULL;
-          }
-        }
-      }
-    }
-#endif
+    // MBSM multicast traffic 
+    //   if (frame >= 46) {// only generate when UE can receive MTCH (need to control this value)
+      for (service_id = 0; service_id < 2 ; service_id++) { //maxServiceCount
+	for (session_id = 0; session_id < 2; session_id++) { // maxSessionPerPMCH
+	  //   LOG_I(OTG,"DUY:frame %d, pdcp_mbms_array[module_id][rb_id].instanciated_instance is %d\n",frame,pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].instanciated_instance);
+	  if (pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].instanciated_instance == module_id + 1){ // this service/session is configured
+	    
+	    otg_pkt = malloc (sizeof(Packet_otg_elt));
+	    // LOG_T(OTG,"multicast packet gen for (service/mch %d, session/lcid %d, rb_id %d)\n", service_id, session_id, service_id*maxSessionPerPMCH + session_id);
+	    rb_id = pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].rb_id;
+	    (otg_pkt->otg_pkt).sdu_buffer = (u8*) packet_gen_multicast(module_id, session_id, ctime, &((otg_pkt->otg_pkt).sdu_buffer_size));
+	    if ((otg_pkt->otg_pkt).sdu_buffer != NULL) {
+	      (otg_pkt->otg_pkt).rb_id = rb_id;
+	      (otg_pkt->otg_pkt).module_id = module_id;
+	      (otg_pkt->otg_pkt).dst_id = session_id;
+	      //Adding the packet to the OTG-PDCP buffer
+	      (otg_pkt->otg_pkt).mode = PDCP_TM;
+	      pkt_list_add_tail_eurecom(otg_pkt, &(otg_pdcp_buffer[module_id]));
+	      LOG_I(EMU, "[eNB %d] ADD packet multicast to OTG buffer for dst %d on rb_id %d\n", (otg_pkt->otg_pkt).module_id, (otg_pkt->otg_pkt).dst_id,(otg_pkt->otg_pkt).rb_id);
+	    } else {
+	      //LOG_I(EMU, "OTG returns null \n");
+	      free(otg_pkt);
+	      otg_pkt=NULL;
+	    }
+
+
+	    // old version	    
+	   /*	    // MBSM multicast traffic 
+#ifdef Rel10
+	    if (frame >= 46) {// only generate when UE can receive MTCH (need to control this value)
+	      for (service_id = 0; service_id < 2 ; service_id++) { //maxServiceCount
+		for (session_id = 0; session_id < 2; session_id++) { // maxSessionPerPMCH
+		  //   LOG_I(OTG,"DUY:frame %d, pdcp_mbms_array[module_id][rb_id].instanciated_instance is %d\n",frame,pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].instanciated_instance);
+		  if ((pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].instanciated_instance== module_id + 1) && (eNB_flag == 1)){ // this service/session is configured
+		    // LOG_T(OTG,"multicast packet gen for (service/mch %d, session/lcid %d)\n", service_id, session_id);
+		    // Duy add
+		    LOG_I(OTG, "frame %d, multicast packet gen for (service/mch %d, session/lcid %d, rb_id %d)\n",frame, service_id, session_id,service_id*maxSessionPerPMCH + session_id);
+		    // end Duy add
+		    rb_id = pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].rb_id;
+		    otg_pkt=(u8*) packet_gen_multicast(module_id, session_id, ctime, &pkt_size);
+		    if (otg_pkt != NULL) {
+		      LOG_D(OTG,"[eNB %d] sending a multicast packet from module %d on rab id %d (src %d, dst %d) pkt size %d\n", eNB_index, module_id, rb_id, module_id, session_id, pkt_size);
+		      pdcp_data_req(module_id, frame, eNB_flag, rb_id, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO, pkt_size, otg_pkt,PDCP_TM);
+		      free(otg_pkt);
+		    }
+		  }
+		}
+	      }
+	    } // end multicast traffic
+#endif 		    
+      	    */
 
+
+	  }
+	}
+      }
+      //    } // end multicast traffic
+#endif 	
+    
     //LOG_I(EMU, "[eNB %d] update OTG nb_elts = %d \n", module_id, otg_pdcp_buffer[module_id].nb_elements);
 
     //free(otg_pkt);
-- 
GitLab