diff --git a/.gitignore b/.gitignore
index 73e0407c4bc7be31e24154b4c91b44570966916d..8f8ff1f4548dc35d14b66d973dabe4b652aedbb8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,10 @@
 cmake_targets/log/
 cmake_targets/*/build/
 cmake_targets/ran_build/
+cmake_targets/nas_sim_tools/build/
 log/
 lte_build_oai/
 targets/bin/
+
+# vscode
+.vscode
diff --git a/README.txt b/README.txt
index 8fb670de983f6fef155c699fad8015ab4037535f..db3ee53045ed3a3815b1a370f116bf31d0535771 100644
--- a/README.txt
+++ b/README.txt
@@ -93,3 +93,4 @@ v0.4 -> Merge of feature-131-new-license. It closes issue#131 and changes the li
 v0.3 -> Last stable commit on develop branch before the merge of feature-131-new-license. This is the last commit with GPL License
 v0.2 -> Merge of enhancement-10-harmony to include NGFI RRH + New Interface for RF/BBU
 v0.1 -> Last stable commit on develop branch before enhancement-10-harmony
+
diff --git a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..db1c5eae2a1e81ddef717b5c997069b32b68f7f3
--- /dev/null
+++ b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf
@@ -0,0 +1,273 @@
+Active_eNBs = ( "eNB-Eurecom-LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_ENB";
+
+    eNB_name  =  "eNB-Eurecom-LTEBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code = 1;
+    plmn_list = ( { mcc = 208; mnc = 92; mnc_length = 2; } );
+
+    tr_s_preference     = "local_mac"
+
+    // In seconds
+    rrc_inactivity_threshold = 30;
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "3GPP_eNODEB";
+      node_timing               = "synch_to_ext_device";
+      node_synch_ref            = 0;
+      frame_type					      = "FDD";
+      tdd_config 					      = 3;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 17;
+      downlink_frequency      			      = 736000000L;
+      uplink_frequency_offset 			      = -30000000;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 25;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 1;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 125;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 0;
+      pdsch_referenceSignalPower 			      = -25;
+      pdsch_p_b                  			      = 0;
+      pusch_n_SB                 			      = 1;
+      pusch_enable64QAM          			      = "DISABLE";
+      pusch_hoppingMode                                  = "interSubFrame";
+      pusch_hoppingOffset                                = 0;
+      pusch_groupHoppingEnabled  			      = "ENABLE";
+      pusch_groupAssignment      			      = 0;
+      pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+      pusch_nDMRS1                                       = 1;
+      phich_duration                                     = "NORMAL";
+      phich_resource                                     = "ONESIXTH";
+      srs_enable                                         = "DISABLE";
+      /*  srs_BandwidthConfig                                =;
+      srs_SubframeConfig                                 =;
+      srs_ackNackST                                      =;
+      srs_MaxUpPts                                       =;*/
+
+      pusch_p0_Nominal                                   = -96;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -104;
+      msg3_delta_Preamble                                = 6;
+      pucch_deltaF_Format1                               = "deltaF2";
+      pucch_deltaF_Format1b                              = "deltaF3";
+      pucch_deltaF_Format2                               = "deltaF0";
+      pucch_deltaF_Format2a                              = "deltaF0";
+      pucch_deltaF_Format2b		    	      = "deltaF0";
+
+      rach_numberOfRA_Preambles                          = 64;
+      rach_preamblesGroupAConfig                         = "DISABLE";
+      /*
+      rach_sizeOfRA_PreamblesGroupA                      = ;
+      rach_messageSizeGroupA                             = ;
+      rach_messagePowerOffsetGroupB                      = ;
+      */
+      rach_powerRampingStep                              = 4;
+      rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleTransMax                              = 10;
+      rach_raResponseWindowSize                          = 10;
+      rach_macContentionResolutionTimer                  = 48;
+      rach_maxHARQ_Msg3Tx                                = 4;
+
+      pcch_default_PagingCycle                           = 128;
+      pcch_nB                                            = "oneT";
+      bcch_modificationPeriodCoeff			      = 2;
+      ue_TimersAndConstants_t300			      = 1000;
+      ue_TimersAndConstants_t301			      = 1000;
+      ue_TimersAndConstants_t310			      = 1000;
+      ue_TimersAndConstants_t311			      = 10000;
+      ue_TimersAndConstants_n310			      = 20;
+      ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                                    = 1;
+
+      //Parameters for SIB18
+      rxPool_sc_CP_Len                                       = "normal";
+      rxPool_sc_Period                                       = "sf40";
+      rxPool_data_CP_Len                                     = "normal";
+      rxPool_ResourceConfig_prb_Num                          = 20;
+      rxPool_ResourceConfig_prb_Start                        = 5;
+      rxPool_ResourceConfig_prb_End                          = 44;
+      rxPool_ResourceConfig_offsetIndicator_present          = "prSmall";
+      rxPool_ResourceConfig_offsetIndicator_choice           = 0;
+      rxPool_ResourceConfig_subframeBitmap_present           = "prBs40";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_buf              = "00000000000000000000";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_size             = 5;
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused      = 0;
+/*    rxPool_dataHoppingConfig_hoppingParameter                       = 0;
+      rxPool_dataHoppingConfig_numSubbands                            = "ns1";
+      rxPool_dataHoppingConfig_rbOffset                               = 0;
+      rxPool_commTxResourceUC-ReqAllowed                              = "TRUE";
+*/
+      // Parameters for SIB19
+      discRxPool_cp_Len                                               = "normal"
+      discRxPool_discPeriod                                           = "rf32"
+      discRxPool_numRetx                                              = 1;
+      discRxPool_numRepetition                                        = 2;
+      discRxPool_ResourceConfig_prb_Num                               = 5;
+      discRxPool_ResourceConfig_prb_Start                             = 3;
+      discRxPool_ResourceConfig_prb_End                               = 21;
+      discRxPool_ResourceConfig_offsetIndicator_present               = "prSmall";
+      discRxPool_ResourceConfig_offsetIndicator_choice                = 0;
+      discRxPool_ResourceConfig_subframeBitmap_present                = "prBs40";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf          = "f0ffffffff";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_size         = 5;
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused  = 0;
+
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "CI_MME_IP_ADDR";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    enable_measurement_reports = "no";
+
+    ///X2
+    enable_x2 = "no";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "CI_ENB_IP_ADDR";
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "CI_ENB_IP_ADDR";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+        ENB_IPV4_ADDRESS_FOR_X2C                 = "CI_ENB_IP_ADDR";
+        ENB_PORT_FOR_X2C                         = 36422; # Spec 36422
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+	phy_test_mode = 0;
+        puSch10xSnr     =  160;
+        puCch10xSnr     =  160;
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 125;
+         eNB_instances  = [0];
+
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+NETWORK_CONTROLLER :
+{
+    FLEXRAN_ENABLED        = "no";
+    FLEXRAN_INTERFACE_NAME = "eth0";
+    FLEXRAN_IPV4_ADDRESS   = "CI_MME_IP_ADDR";
+    FLEXRAN_PORT           = 2210;
+    FLEXRAN_CACHE          = "/mnt/oai_agent_cache";
+    FLEXRAN_AWAIT_RECONF   = "no";
+};
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..fbb8c5d6f871bf0b091cfe00f0857ed520e4367c
--- /dev/null
+++ b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf
@@ -0,0 +1,417 @@
+Active_eNBs = ( "eNB-Eurecom-LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_ENB";
+
+    eNB_name  =  "eNB-Eurecom-LTEBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code = 1;
+    plmn_list = ( { mcc = 208; mnc = 92; mnc_length = 2; } );
+
+    tr_s_preference     = "local_mac"
+
+    // In seconds
+    rrc_inactivity_threshold = 30;
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "3GPP_eNODEB";
+      node_timing               = "synch_to_ext_device";
+      node_synch_ref            = 0;
+      frame_type					      = "FDD";
+      tdd_config 					      = 3;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 17;
+      downlink_frequency      			      = 736000000L;
+      uplink_frequency_offset 			      = -30000000;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 25;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 1;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 125;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 0;
+      pdsch_referenceSignalPower 			      = -25;
+      pdsch_p_b                  			      = 0;
+      pusch_n_SB                 			      = 1;
+      pusch_enable64QAM          			      = "DISABLE";
+      pusch_hoppingMode                                  = "interSubFrame";
+      pusch_hoppingOffset                                = 0;
+      pusch_groupHoppingEnabled  			      = "ENABLE";
+      pusch_groupAssignment      			      = 0;
+      pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+      pusch_nDMRS1                                       = 1;
+      phich_duration                                     = "NORMAL";
+      phich_resource                                     = "ONESIXTH";
+      srs_enable                                         = "DISABLE";
+      /*  srs_BandwidthConfig                                =;
+      srs_SubframeConfig                                 =;
+      srs_ackNackST                                      =;
+      srs_MaxUpPts                                       =;*/
+
+      pusch_p0_Nominal                                   = -96;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -104;
+      msg3_delta_Preamble                                = 6;
+      pucch_deltaF_Format1                               = "deltaF2";
+      pucch_deltaF_Format1b                              = "deltaF3";
+      pucch_deltaF_Format2                               = "deltaF0";
+      pucch_deltaF_Format2a                              = "deltaF0";
+      pucch_deltaF_Format2b		    	      = "deltaF0";
+
+      rach_numberOfRA_Preambles                          = 64;
+      rach_preamblesGroupAConfig                         = "DISABLE";
+      /*
+      rach_sizeOfRA_PreamblesGroupA                      = ;
+      rach_messageSizeGroupA                             = ;
+      rach_messagePowerOffsetGroupB                      = ;
+      */
+      rach_powerRampingStep                              = 4;
+      rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleTransMax                              = 10;
+      rach_raResponseWindowSize                          = 10;
+      rach_macContentionResolutionTimer                  = 48;
+      rach_maxHARQ_Msg3Tx                                = 4;
+
+      pcch_default_PagingCycle                           = 128;
+      pcch_nB                                            = "oneT";
+      bcch_modificationPeriodCoeff			      = 2;
+      ue_TimersAndConstants_t300			      = 1000;
+      ue_TimersAndConstants_t301			      = 1000;
+      ue_TimersAndConstants_t310			      = 1000;
+      ue_TimersAndConstants_t311			      = 10000;
+      ue_TimersAndConstants_n310			      = 20;
+      ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                                    = 1;
+
+      //Parameters for SIB18
+      rxPool_sc_CP_Len                                       = "normal";
+      rxPool_sc_Period                                       = "sf40";
+      rxPool_data_CP_Len                                     = "normal";
+      rxPool_ResourceConfig_prb_Num                          = 20;
+      rxPool_ResourceConfig_prb_Start                        = 5;
+      rxPool_ResourceConfig_prb_End                          = 44;
+      rxPool_ResourceConfig_offsetIndicator_present          = "prSmall";
+      rxPool_ResourceConfig_offsetIndicator_choice           = 0;
+      rxPool_ResourceConfig_subframeBitmap_present           = "prBs40";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_buf              = "00000000000000000000";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_size             = 5;
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused      = 0;
+/*    rxPool_dataHoppingConfig_hoppingParameter                       = 0;
+      rxPool_dataHoppingConfig_numSubbands                            = "ns1";
+      rxPool_dataHoppingConfig_rbOffset                               = 0;
+      rxPool_commTxResourceUC-ReqAllowed                              = "TRUE";
+*/
+      // Parameters for SIB19
+      discRxPool_cp_Len                                               = "normal"
+      discRxPool_discPeriod                                           = "rf32"
+      discRxPool_numRetx                                              = 1;
+      discRxPool_numRepetition                                        = 2;
+      discRxPool_ResourceConfig_prb_Num                               = 5;
+      discRxPool_ResourceConfig_prb_Start                             = 3;
+      discRxPool_ResourceConfig_prb_End                               = 21;
+      discRxPool_ResourceConfig_offsetIndicator_present               = "prSmall";
+      discRxPool_ResourceConfig_offsetIndicator_choice                = 0;
+      discRxPool_ResourceConfig_subframeBitmap_present                = "prBs40";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf          = "f0ffffffff";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_size         = 5;
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused  = 0;
+
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "CI_MME_IP_ADDR";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    enable_measurement_reports = "no";
+
+    ///X2
+    enable_x2 = "no";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+
+    ///M2
+    target_mce_m2_ip_address      = ( { ipv4       = "127.0.0.7";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    enable_enb_m2 = "yes";
+    
+    mbms_configuration_data_list = (
+                {
+                        mbsfn_sync_area = 0x0001;
+                        mbms_service_area_list=(
+                                {
+                                        mbms_service_area=0x0001;
+                                }
+                        );
+                }
+
+    );
+
+
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "CI_ENB_IP_ADDR";
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "CI_ENB_IP_ADDR";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+        ENB_IPV4_ADDRESS_FOR_X2C                 = "CI_ENB_IP_ADDR";
+        ENB_PORT_FOR_X2C                         = 36422; # Spec 36422
+	ENB_IPV4_ADDRESS_FOR_M2C                 = "127.0.0.2/24";
+	ENB_PORT_FOR_M2C                         = 36443; # Spec 36443
+    };
+  }
+);
+
+MCEs = (
+        {
+            MCE_ID    =  0xe00;
+
+            MCE_name  =  "MCE-Vicomtech-LTEBox";
+
+            //M2
+            enable_mce_m2 = "yes";
+
+            //M3
+            enable_mce_m3 = "yes";
+
+            target_mme_m3_ip_address      = ( { ipv4       = "127.0.0.18";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+
+
+            NETWORK_INTERFACES :
+            {
+                MCE_INTERFACE_NAME_FOR_M2_ENB            = "lo";
+                MCE_IPV4_ADDRESS_FOR_M2C                 = "127.0.0.7/24";
+                MCE_PORT_FOR_M2C                         = 36443; # Spec 36443
+
+                MCE_INTERFACE_NAME_FOR_M3_MME            = "lo";
+                MCE_IPV4_ADDRESS_FOR_M3C                 = "127.0.0.3/24";
+                MCE_PORT_FOR_M3C                         = 36444; # Spec 36444
+            };
+
+            plnm:
+            {
+                mcc = 208;
+                mnc = 93;
+                mnc_length = 2;
+            };
+
+            mbms_sched_info :
+            {
+                mcch_update_time = 10;
+                mbms_area_config_list = (
+                {
+                   common_sf_allocation_period = 2; #rf4(0) rf8(1) rf16(2) rf32(3) rf64(4) rf128(5) rf256(6)
+                   mbms_area_id = 0;
+                   pmch_config_list = (
+                   {
+                        allocated_sf_end=64;
+                        data_mcs=10;
+                        mch_scheduling_period = 0; #rf8(0)
+                        mbms_session_list = (
+                        {
+                                #plnm + service_id ->tmgi
+                                plnm:
+                                {
+                                    mcc = 208;
+                                    mnc = 93;
+                                    mnc_length = 2;
+                                }
+                                service_id=0;
+                                lcid=8; #this must be properly defined lcid:8+service:0 -> rab_id:8
+                        }
+                        );
+                   }
+                   );
+
+                   mbms_sf_config_list = (
+                   {
+                        radioframe_allocation_period=1; #n1(0) n2(1) n4(2) n8(3) n16(4) n32(5)
+                        radioframe_alloocation_offset=0;
+                        num_frame="oneFrame";
+                        subframe_allocation=57; #xx100000
+                        //num_frame="fourFrame";
+                        //subframe_allocation=14548987; #
+                   }
+
+                  );
+
+                }
+                );
+            };
+            mcch_config_per_mbsfn_area = (
+            {
+                mbsfn_area                = 0;
+                pdcch_length              = 1; #s1(0), s2(1)
+                repetition_period         = 0; #rf32(0), rf64(1), rf128(2), rf256(3)
+                offset                    = 0;
+                modification_period       = 0; #rf512(0; rf1024(1)
+                subframe_allocation_info = 32; #BITSTRING (6bits -> one frame) xx100101
+                mcs                       = 0; #n2(0), n7(1), n13(2), n19(3)
+            }
+            );
+                  #);  #end mbms_scheduling_info
+
+        }
+);
+
+
+MMEs = (
+        {
+            MME_ID    =  0xe00;
+
+            MME_name  =  "MME-MBMS-Vicomtech-LTEBox";
+
+            //M3
+            enable_mme_m3 = "yes";
+            NETWORK_INTERFACES :
+            {
+                MME_INTERFACE_NAME_FOR_M3_MCE            = "lo";
+                MME_IPV4_ADDRESS_FOR_M3C                 = "127.0.0.18/24";
+                MME_PORT_FOR_M3C                         = 36444; # Spec 36444
+
+            };
+        }
+);
+
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+	phy_test_mode = 0;
+        puSch10xSnr     =  160;
+        puCch10xSnr     =  160;
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 125;
+         eNB_instances  = [0];
+
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+NETWORK_CONTROLLER :
+{
+    FLEXRAN_ENABLED        = "no";
+    FLEXRAN_INTERFACE_NAME = "eth0";
+    FLEXRAN_IPV4_ADDRESS   = "CI_MME_IP_ADDR";
+    FLEXRAN_PORT           = 2210;
+    FLEXRAN_CACHE          = "/mnt/oai_agent_cache";
+    FLEXRAN_AWAIT_RECONF   = "no";
+};
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf b/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf
new file mode 100644
index 0000000000000000000000000000000000000000..b61e5e05b1d3ab5036c941d4734f5c809f65fc4f
--- /dev/null
+++ b/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf
@@ -0,0 +1,378 @@
+Active_eNBs = ( "eNB-Eurecom-LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    # real_time choice in {hard, rt-preempt, no}
+    real_time       =  "no";
+
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_ENB";
+
+    eNB_name  =  "eNB-Eurecom-LTEBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code = 600;
+
+    plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } );
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "NGFI_RCC_IF4p5";
+      node_timing               = "synch_to_ext_device";
+      node_synch_ref            = 0;
+      frame_type					      = "FDD";
+      tdd_config 					      = 3;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 7;
+      downlink_frequency      			      = 2685000000L;
+      uplink_frequency_offset 			      = -120000000;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 50;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 2;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 125;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 0;
+      pdsch_referenceSignalPower 			      = -27;
+      pdsch_p_b                  			      = 0;
+      pusch_n_SB                 			      = 1;
+      pusch_enable64QAM          			      = "DISABLE";
+      pusch_hoppingMode                                  = "interSubFrame";
+      pusch_hoppingOffset                                = 0;
+      pusch_groupHoppingEnabled  			      = "ENABLE";
+      pusch_groupAssignment      			      = 0;
+      pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+      pusch_nDMRS1                                       = 1;
+      phich_duration                                     = "NORMAL";
+      phich_resource                                     = "ONESIXTH";
+      srs_enable                                         = "DISABLE";
+      /*  srs_BandwidthConfig                                =;
+      srs_SubframeConfig                                 =;
+      srs_ackNackST                                      =;
+      srs_MaxUpPts                                       =;*/
+
+      pusch_p0_Nominal                                   = -104;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -108;
+      msg3_delta_Preamble                                = 6;
+      pucch_deltaF_Format1                               = "deltaF2";
+      pucch_deltaF_Format1b                              = "deltaF3";
+      pucch_deltaF_Format2                               = "deltaF0";
+      pucch_deltaF_Format2a                              = "deltaF0";
+      pucch_deltaF_Format2b		    	      = "deltaF0";
+
+      rach_numberOfRA_Preambles                          = 64;
+      rach_preamblesGroupAConfig                         = "DISABLE";
+      /*
+      rach_sizeOfRA_PreamblesGroupA                      = ;
+      rach_messageSizeGroupA                             = ;
+      rach_messagePowerOffsetGroupB                      = ;
+      */
+      rach_powerRampingStep                              = 4;
+      rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleTransMax                              = 10;
+      rach_raResponseWindowSize                          = 10;
+      rach_macContentionResolutionTimer                  = 48;
+      rach_maxHARQ_Msg3Tx                                = 4;
+
+      pcch_default_PagingCycle                           = 128;
+      pcch_nB                                            = "oneT";
+      bcch_modificationPeriodCoeff			      = 2;
+      ue_TimersAndConstants_t300			      = 1000;
+      ue_TimersAndConstants_t301			      = 1000;
+      ue_TimersAndConstants_t310			      = 1000;
+      ue_TimersAndConstants_t311			      = 10000;
+      ue_TimersAndConstants_n310			      = 20;
+      ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                                    = 1;
+      mbms_dedicated_serving_cell			= "DISABLE"
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.15.130";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    enable_measurement_reports = "no";
+
+    ///X2
+    enable_x2 = "no";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+
+
+    ////////// MCE parameters:
+    target_mce_m2_ip_address      = ( { ipv4       = "127.0.0.7";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    ///M2
+    enable_enb_m2 = "yes";
+   
+
+    mbms_configuration_data_list = (
+                {
+                        mbsfn_sync_area = 0x0001;
+                        mbms_service_area_list=(
+                                {
+                                        mbms_service_area=0x0001;
+                                }
+                        );
+                }
+
+    );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "enp2s0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.10.15/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "enp2s0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.10.15/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+
+        ENB_IPV4_ADDRESS_FOR_X2C                 = "127.0.0.2/24";
+        ENB_PORT_FOR_X2C                         = 36422; # Spec 36422
+
+        ENB_IPV4_ADDRESS_FOR_M2C                 = "127.0.0.2/24";
+        ENB_PORT_FOR_M2C                         = 36443; # Spec 36443
+    };
+  }
+);
+
+MCEs = (
+        {
+            MCE_ID    =  0xe00;
+
+            MCE_name  =  "MCE-Vicomtech-LTEBox";
+
+            //M2
+            enable_mce_m2 = "yes";
+
+            //M3
+            enable_mce_m3 = "yes";
+
+            target_mme_m3_ip_address      = ( { ipv4       = "127.0.0.18";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+
+
+            NETWORK_INTERFACES :
+            {
+                MCE_INTERFACE_NAME_FOR_M2_ENB            = "lo";
+                MCE_IPV4_ADDRESS_FOR_M2C                 = "127.0.0.7/24";
+                MCE_PORT_FOR_M2C                         = 36443; # Spec 36443
+
+                MCE_INTERFACE_NAME_FOR_M3_MME            = "lo";
+                MCE_IPV4_ADDRESS_FOR_M3C                 = "127.0.0.3/24";
+                MCE_PORT_FOR_M3C                         = 36444; # Spec 36444
+            };
+
+            plnm:
+            {
+                mcc = 208;
+                mnc = 93;
+                mnc_length = 2;
+            };
+
+            mbms_sched_info :
+            {
+                mcch_update_time = 10;
+                mbms_area_config_list = (
+                {
+                   common_sf_allocation_period = 2; #rf4(0) rf8(1) rf16(2) rf32(3) rf64(4) rf128(5) rf256(6)
+                   mbms_area_id = 0;
+                   pmch_config_list = (
+                   {
+                        allocated_sf_end=32;
+                        data_mcs=14;
+                        mch_scheduling_period = 0; #rf8(0)
+                        mbms_session_list = (
+                        {
+                                #plnm + service_id ->tmgi
+                               plnm:
+                                {
+                                    mcc = 208;
+                                    mnc = 93;
+                                    mnc_length = 2;
+                                }
+                                service_id=0; #keep this allways as 0 (workaround for TUN if)
+                                lcid=6; #this must be properly defined lcid:6+service:0 -> rab_id:6
+                        }
+                        );
+                   }
+                   );
+
+                   mbms_sf_config_list = (
+                   {
+                        radioframe_allocation_period=1; #n1(0) n2(1) n4(2) n8(3) n16(4) n32(5)
+                        radioframe_alloocation_offset=0;
+                        num_frame="oneFrame";
+                        subframe_allocation=57; #xx111001
+                        //num_frame="fourFrame";
+                        //subframe_allocation=14548987; #
+                   }
+                   );
+
+                }
+                );
+            };
+
+
+            mcch_config_per_mbsfn_area = (
+            {
+                mbsfn_area                = 0;
+                pdcch_length              = 1; #s1(0), s2(1)
+                repetition_period         = 0; #rf32(0), rf64(1), rf128(2), rf256(3)
+                offset                    = 0;
+                modification_period       = 0; #rf512(0; rf1024(1)
+                subframe_allocation_info = 32; #BITSTRING (6bits -> one frame) xx100000
+                mcs                       = 1; #n2(0), n7(1), n13(2), n19(3)
+            }
+            );
+
+                  #);  #end mbms_scheduling_info
+
+        }
+);
+MMEs = (
+        {
+            MME_ID    =  0xe00;
+
+            MME_name  =  "MME-MBMS-Vicomtech-LTEBox";
+
+            //M3
+            enable_mme_m3 = "yes";
+            NETWORK_INTERFACES :
+            {
+                MME_INTERFACE_NAME_FOR_M3_MCE            = "lo";
+                MME_IPV4_ADDRESS_FOR_M3C                 = "127.0.0.18/24";
+                MME_PORT_FOR_M3C                         = 36444; # Spec 36444
+
+            };
+        }
+);
+
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+      	local_if_name  = "lo";			  
+      	remote_address = "127.0.0.2";
+    	local_address  = "127.0.0.1"; 
+    	local_portc    = 50000;	
+    	remote_portc   = 50000;
+    	local_portd    = 50001;	
+    	remote_portd   = 50001;
+	local_rf       = "no"
+    	tr_preference  = "udp_if4p5"
+	nb_tx          = 2
+	nb_rx          = 2
+	att_tx         = 0
+	att_rx         = 0;
+	eNB_instances  = [0];
+        is_slave       = "no";
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+log_config = { 
+      global_log_level                      ="info";
+      global_log_verbosity                  ="medium";
+      hw_log_level                          ="info";
+      hw_log_verbosity                      ="medium";
+      phy_log_level                         ="info";
+      phy_log_verbosity                     ="medium";
+      mac_log_level                         ="info";
+      mac_log_verbosity                     ="high";
+      rlc_log_level                         ="info";
+      rlc_log_verbosity                     ="medium";
+      pdcp_log_level                        ="info";
+      pdcp_log_verbosity                    ="medium";
+      rrc_log_level                         ="info";
+      rrc_log_verbosity                     ="medium";
+};
diff --git a/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf b/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf
new file mode 100644
index 0000000000000000000000000000000000000000..5daaa8d13aec7d65e9460d8badea53b755cee9d7
--- /dev/null
+++ b/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf
@@ -0,0 +1,378 @@
+Active_eNBs = ( "eNB-Eurecom-LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    # real_time choice in {hard, rt-preempt, no}
+    real_time       =  "no";
+
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_ENB";
+
+    eNB_name  =  "eNB-Eurecom-LTEBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code = 1;
+
+    plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } );
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "NGFI_RCC_IF4p5";
+      node_timing               = "synch_to_ext_device";
+      node_synch_ref            = 0;
+      frame_type					      = "FDD";
+      tdd_config 					      = 3;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 7;
+      downlink_frequency      			      = 2685000000L;
+      uplink_frequency_offset 			      = -120000000;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 50;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 2;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 125;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 0;
+      pdsch_referenceSignalPower 			      = -27;
+      pdsch_p_b                  			      = 0;
+      pusch_n_SB                 			      = 1;
+      pusch_enable64QAM          			      = "DISABLE";
+      pusch_hoppingMode                                  = "interSubFrame";
+      pusch_hoppingOffset                                = 0;
+      pusch_groupHoppingEnabled  			      = "ENABLE";
+      pusch_groupAssignment      			      = 0;
+      pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+      pusch_nDMRS1                                       = 1;
+      phich_duration                                     = "NORMAL";
+      phich_resource                                     = "ONESIXTH";
+      srs_enable                                         = "DISABLE";
+      /*  srs_BandwidthConfig                                =;
+      srs_SubframeConfig                                 =;
+      srs_ackNackST                                      =;
+      srs_MaxUpPts                                       =;*/
+
+      pusch_p0_Nominal                                   = -104;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -108;
+      msg3_delta_Preamble                                = 6;
+      pucch_deltaF_Format1                               = "deltaF2";
+      pucch_deltaF_Format1b                              = "deltaF3";
+      pucch_deltaF_Format2                               = "deltaF0";
+      pucch_deltaF_Format2a                              = "deltaF0";
+      pucch_deltaF_Format2b		    	      = "deltaF0";
+
+      rach_numberOfRA_Preambles                          = 64;
+      rach_preamblesGroupAConfig                         = "DISABLE";
+      /*
+      rach_sizeOfRA_PreamblesGroupA                      = ;
+      rach_messageSizeGroupA                             = ;
+      rach_messagePowerOffsetGroupB                      = ;
+      */
+      rach_powerRampingStep                              = 4;
+      rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleTransMax                              = 10;
+      rach_raResponseWindowSize                          = 10;
+      rach_macContentionResolutionTimer                  = 48;
+      rach_maxHARQ_Msg3Tx                                = 4;
+
+      pcch_default_PagingCycle                           = 128;
+      pcch_nB                                            = "oneT";
+      bcch_modificationPeriodCoeff			      = 2;
+      ue_TimersAndConstants_t300			      = 1000;
+      ue_TimersAndConstants_t301			      = 1000;
+      ue_TimersAndConstants_t310			      = 1000;
+      ue_TimersAndConstants_t311			      = 10000;
+      ue_TimersAndConstants_n310			      = 20;
+      ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                                    = 1;
+      mbms_dedicated_serving_cell			= "DISABLE"
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "127.0.0.3";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    enable_measurement_reports = "no";
+
+    ///X2
+    enable_x2 = "no";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+
+
+    ////////// MCE parameters:
+    target_mce_m2_ip_address      = ( { ipv4       = "127.0.0.7";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    ///M2
+    enable_enb_m2 = "yes";
+   
+
+    mbms_configuration_data_list = (
+                {
+                        mbsfn_sync_area = 0x0001;
+                        mbms_service_area_list=(
+                                {
+                                        mbms_service_area=0x0001;
+                                }
+                        );
+                }
+
+    );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "lo";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "127.0.0.2/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "lo";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "127.0.0.5/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+
+        ENB_IPV4_ADDRESS_FOR_X2C                 = "127.0.0.2/24";
+        ENB_PORT_FOR_X2C                         = 36422; # Spec 36422
+
+        ENB_IPV4_ADDRESS_FOR_M2C                 = "127.0.0.2/24";
+        ENB_PORT_FOR_M2C                         = 36443; # Spec 36443
+    };
+  }
+);
+
+MCEs = (
+        {
+            MCE_ID    =  0xe00;
+
+            MCE_name  =  "MCE-Vicomtech-LTEBox";
+
+            //M2
+            enable_mce_m2 = "yes";
+
+            //M3
+            enable_mce_m3 = "yes";
+
+            target_mme_m3_ip_address      = ( { ipv4       = "127.0.0.18";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+
+
+            NETWORK_INTERFACES :
+            {
+                MCE_INTERFACE_NAME_FOR_M2_ENB            = "lo";
+                MCE_IPV4_ADDRESS_FOR_M2C                 = "127.0.0.7/24";
+                MCE_PORT_FOR_M2C                         = 36443; # Spec 36443
+
+                MCE_INTERFACE_NAME_FOR_M3_MME            = "lo";
+                MCE_IPV4_ADDRESS_FOR_M3C                 = "127.0.0.3/24";
+                MCE_PORT_FOR_M3C                         = 36444; # Spec 36444
+            };
+
+            plnm:
+            {
+                mcc = 208;
+                mnc = 93;
+                mnc_length = 2;
+            };
+
+            mbms_sched_info :
+            {
+                mcch_update_time = 10;
+                mbms_area_config_list = (
+                {
+                   common_sf_allocation_period = 2; #rf4(0) rf8(1) rf16(2) rf32(3) rf64(4) rf128(5) rf256(6)
+                   mbms_area_id = 0;
+                   pmch_config_list = (
+                   {
+                        allocated_sf_end=32;
+                        data_mcs=14;
+                        mch_scheduling_period = 0; #rf8(0)
+                        mbms_session_list = (
+                        {
+                                #plnm + service_id ->tmgi
+                               plnm:
+                                {
+                                    mcc = 208;
+                                    mnc = 93;
+                                    mnc_length = 2;
+                                }
+                                service_id=0; #keep this allways as 0 (workaround for TUN if)
+                                lcid=6; #this must be properly defined lcid:6+service:0 -> rab_id:6
+                        }
+                        );
+                   }
+                   );
+
+                   mbms_sf_config_list = (
+                   {
+                        radioframe_allocation_period=1; #n1(0) n2(1) n4(2) n8(3) n16(4) n32(5)
+                        radioframe_alloocation_offset=0;
+                        num_frame="oneFrame";
+                        subframe_allocation=57; #xx111001
+                        //num_frame="fourFrame";
+                        //subframe_allocation=14548987; #
+                   }
+                   );
+
+                }
+                );
+            };
+
+
+            mcch_config_per_mbsfn_area = (
+            {
+                mbsfn_area                = 0;
+                pdcch_length              = 1; #s1(0), s2(1)
+                repetition_period         = 0; #rf32(0), rf64(1), rf128(2), rf256(3)
+                offset                    = 0;
+                modification_period       = 0; #rf512(0; rf1024(1)
+                subframe_allocation_info = 32; #BITSTRING (6bits -> one frame) xx100000
+                mcs                       = 1; #n2(0), n7(1), n13(2), n19(3)
+            }
+            );
+
+                  #);  #end mbms_scheduling_info
+
+        }
+);
+MMEs = (
+        {
+            MME_ID    =  0xe00;
+
+            MME_name  =  "MME-MBMS-Vicomtech-LTEBox";
+
+            //M3
+            enable_mme_m3 = "yes";
+            NETWORK_INTERFACES :
+            {
+                MME_INTERFACE_NAME_FOR_M3_MCE            = "lo";
+                MME_IPV4_ADDRESS_FOR_M3C                 = "127.0.0.18/24";
+                MME_PORT_FOR_M3C                         = 36444; # Spec 36444
+
+            };
+        }
+);
+
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+      	local_if_name  = "lo";			  
+      	remote_address = "127.0.0.2";
+    	local_address  = "127.0.0.1"; 
+    	local_portc    = 50000;	
+    	remote_portc   = 50000;
+    	local_portd    = 50001;	
+    	remote_portd   = 50001;
+	local_rf       = "no"
+    	tr_preference  = "udp_if4p5"
+	nb_tx          = 2
+	nb_rx          = 2
+	att_tx         = 0
+	att_rx         = 0;
+	eNB_instances  = [0];
+        is_slave       = "no";
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+log_config = { 
+      global_log_level                      ="info";
+      global_log_verbosity                  ="medium";
+      hw_log_level                          ="info";
+      hw_log_verbosity                      ="medium";
+      phy_log_level                         ="info";
+      phy_log_verbosity                     ="medium";
+      mac_log_level                         ="info";
+      mac_log_verbosity                     ="high";
+      rlc_log_level                         ="info";
+      rlc_log_verbosity                     ="medium";
+      pdcp_log_level                        ="info";
+      pdcp_log_verbosity                    ="medium";
+      rrc_log_level                         ="info";
+      rrc_log_verbosity                     ="medium";
+};
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index 049c7c5b41faca8f14128cbcede75d96486591c3..62690ea8cbab94908fca70c61bc72a69f6c3cb49 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -136,11 +136,13 @@ class SSHConnection():
 		self.eNB_serverId = ''
 		self.eNBLogFiles = ['', '', '']
 		self.eNBOptions = ['', '', '']
+		self.eNBmbmsEnables = [False, False, False]
 		self.ping_args = ''
 		self.ping_packetloss_threshold = ''
 		self.iperf_args = ''
 		self.iperf_packetloss_threshold = ''
 		self.iperf_profile = ''
+		self.iperf_options = ''
 		self.nbMaxUEtoAttach = -1
 		self.UEDevices = []
 		self.UEDevicesStatus = []
@@ -847,6 +849,17 @@ class SSHConnection():
 			self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED        = "yes";/\' ' + ci_full_config_file, '\$', 2);
 		else:
 			self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED        = "no";/\' ' + ci_full_config_file, '\$', 2);
+		self.eNBmbmsEnables[int(self.eNB_instance)] = False
+		self.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2);
+		result = re.search('yes', str(self.ssh.before))
+		if result is not None:
+			self.eNBmbmsEnables[int(self.eNB_instance)] = True
+			logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m')
+		result = re.search('noS1', str(self.Initialize_eNB_args))
+		eNBinNoS1 = False
+		if result is not None:
+			eNBinNoS1 = True
+			logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m')
 		# Launch eNB with the modified config file
 		self.command('source oaienv', '\$', 5)
 		self.command('cd cmake_targets', '\$', 5)
@@ -865,6 +878,7 @@ class SSHConnection():
 		time.sleep(6)
 		doLoop = True
 		loopCounter = 20
+		enbDidSync = False
 		while (doLoop):
 			loopCounter = loopCounter - 1
 			if (loopCounter == 0):
@@ -903,11 +917,27 @@ class SSHConnection():
 					time.sleep(6)
 				else:
 					doLoop = False
-					self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK)
-					logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m')
+					enbDidSync = True
 					time.sleep(10)
 
+		if enbDidSync and eNBinNoS1:
+			self.command('ifconfig oaitun_enb1', '\$', 4)
+			result = re.search('inet addr', str(self.ssh.before))
+			if result is not None:
+				logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m')
+			else:
+				logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m')
+			if self.eNBmbmsEnables[int(self.eNB_instance)]:
+				self.command('ifconfig oaitun_enm1', '\$', 4)
+				result = re.search('inet addr', str(self.ssh.before))
+				if result is not None:
+					logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m')
+				else:
+					logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m')
+
 		self.close()
+		self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK)
+		logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m')
 
 	def InitializeUE_common(self, device_id, idx):
 		try:
@@ -1102,13 +1132,17 @@ class SSHConnection():
 					logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m')
 					tunnelInterfaceStatus = True
 				else:
-					self.command('ifconfig oaitun_ue1', '\$', 4)
-					result = re.search('inet addr:1|inet 1', str(self.ssh.before))
+					logging.debug(str(self.ssh.before))
+					logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m')
+					tunnelInterfaceStatus = False
+				if self.eNBmbmsEnables[0]:
+					self.command('ifconfig oaitun_uem1', '\$', 4)
+					result = re.search('inet addr', str(self.ssh.before))
 					if result is not None:
-						logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m')
-						tunnelInterfaceStatus = True
+						logging.debug('\u001B[1m oaitun_uem1 interface is mounted and configured\u001B[0m')
+						tunnelInterfaceStatus = tunnelInterfaceStatus and True
 					else:
-						logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m')
+						logging.error('\u001B[1m oaitun_uem1 interface is either NOT mounted or NOT configured\u001B[0m')
 						tunnelInterfaceStatus = False
 			else:
 				tunnelInterfaceStatus = True
@@ -1126,7 +1160,10 @@ class SSHConnection():
 				self.UEDevicesStatus.append(UE_STATUS_DETACHED)
 		else:
 			if self.air_interface == 'lte':
-				self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured'
+				if self.eNBmbmsEnables[0]:
+					self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured'
+				else:
+					self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured'
 				self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE')
 			else:
 				self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced'
@@ -2691,17 +2728,18 @@ class SSHConnection():
 			iClientIPAddr = self.eNBIPAddress
 			iClientUser = self.eNBUserName
 			iClientPasswd = self.eNBPassword
-		# Starting the iperf server
-		self.open(iServerIPAddr, iServerUser, iServerPasswd)
-		# args SHALL be "-c client -u any"
-		# -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1
-		# -B 10.0.1.1 -u -s -i 1 -fm
-		server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args))
-		server_options = server_options.replace('-c','-B')
-		self.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5)
-		self.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5)
-		time.sleep(0.5)
-		self.close()
+		if self.iperf_options != 'sink':
+			# Starting the iperf server
+			self.open(iServerIPAddr, iServerUser, iServerPasswd)
+			# args SHALL be "-c client -u any"
+			# -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1
+			# -B 10.0.1.1 -u -s -i 1 -fm
+			server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args))
+			server_options = server_options.replace('-c','-B')
+			self.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5)
+			self.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5)
+			time.sleep(0.5)
+			self.close()
 
 		# Starting the iperf client
 		modified_options = self.Iperf_ComputeModifiedBW(0, 1)
@@ -2717,14 +2755,22 @@ class SSHConnection():
 			logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
 			clientStatus = -2
 		else:
-			clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options)
+			if self.iperf_options == 'sink':
+				clientStatus = 0
+				status_queue.put(0)
+				status_queue.put('OAI-UE')
+				status_queue.put('10.0.1.2')
+				status_queue.put('Sink Test : no check')
+			else:
+				clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options)
 		self.close()
 
 		# Stopping the iperf server
-		self.open(iServerIPAddr, iServerUser, iServerPasswd)
-		self.command('killall --signal SIGKILL iperf', '\$', 5)
-		time.sleep(0.5)
-		self.close()
+		if self.iperf_options != 'sink':
+			self.open(iServerIPAddr, iServerUser, iServerPasswd)
+			self.command('killall --signal SIGKILL iperf', '\$', 5)
+			time.sleep(0.5)
+			self.close()
 		if (clientStatus == -1):
 			if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')):
 				os.remove('iperf_server_' + self.testCase_id + '.log')
@@ -2732,9 +2778,10 @@ class SSHConnection():
 			self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options)
 
 		# copying on the EPC server for logCollection
-		copyin_res = self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log')
-		if (copyin_res == 0):
-			self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts')
+		if (clientStatus == -1):
+			copyin_res = self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log')
+			if (copyin_res == 0):
+				self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts')
 		copyin_res = self.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log')
 		if (copyin_res == 0):
 			self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts')
@@ -3027,6 +3074,7 @@ class SSHConnection():
 		ulschFailure = 0
 		cdrxActivationMessageCount = 0
 		dropNotEnoughRBs = 0
+		mbmsRequestMsg = 0
 		self.htmleNBFailureMsg = ''
 		isRRU = False
 		isSlave = False
@@ -3145,6 +3193,10 @@ class SSHConnection():
 			result = re.search('dropping, not enough RBs', str(line))
 			if result is not None:
 				dropNotEnoughRBs += 1
+			if self.eNBmbmsEnables[int(self.eNB_instance)]:
+				result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line))
+				if result is not None:
+					mbmsRequestMsg += 1
 		enb_log_file.close()
 		logging.debug('   File analysis completed')
 		self.htmleNBFailureMsg = ''
@@ -3196,6 +3248,11 @@ class SSHConnection():
 			rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected'
 			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
 			self.htmleNBFailureMsg += rrcMsg + '\n'
+		if self.eNBmbmsEnables[int(self.eNB_instance)]:
+			if mbmsRequestMsg > 0:
+				rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE'
+				logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
+				self.htmleNBFailureMsg += rrcMsg + '\n'
 		if X2HO_inNbProcedures > 0:
 			rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)'
 			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
@@ -3271,6 +3328,7 @@ class SSHConnection():
 		nrDecodeMib = 0
 		nrFoundDCI = 0
 		nrCRCOK = 0
+		mbms_messages = 0
 		self.htmlUEFailureMsg = ''
 		for line in ue_log_file.readlines():
 			result = re.search('nr_synchro_time', str(line))
@@ -3323,6 +3381,10 @@ class SSHConnection():
 			result = re.search('No cell synchronization found, abandoning', str(line))
 			if result is not None:
 				no_cell_sync_found = True
+			if self.eNBmbmsEnables[0]:
+				result = re.search('TRIED TO PUSH MBMS DATA', str(line))
+				if result is not None:
+					mbms_messages += 1
 			result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P<nidcell>\d{1,3}), N_RB_DL (?P<n_rb_dl>\d{1,3}), PHICH DURATION (?P<phich_duration>\d), PHICH RESOURCE (?P<phich_resource>.{1,4}), TX_ANT (?P<tx_ant>\d)", str(line))
 			if result is not None and (not mib_found):
 				try:
@@ -3433,6 +3495,14 @@ class SSHConnection():
 			statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1A" message(s)'
 			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
 			self.htmlUEFailureMsg += statMsg + '\n'
+		if self.eNBmbmsEnables[0]:
+			if mbms_messages > 0:
+				statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)'
+				logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
+			else:
+				statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)'
+				logging.debug('\u001B[1;30;41m ' + statMsg + ' \u001B[0m')
+			self.htmlUEFailureMsg += statMsg + '\n'
 		if foundSegFault:
 			logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m')
 			if not nrUEFlag:
@@ -3542,6 +3612,7 @@ class SSHConnection():
 					logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m')
 					self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!'
 					self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
+					self.eNBmbmsEnables[int(self.eNB_instance)] = False
 					return
 				if self.eNB_serverId != '0':
 					self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/')
@@ -3550,11 +3621,13 @@ class SSHConnection():
 				if (logStatus < 0):
 					self.CreateHtmlTestRow('N/A', 'KO', logStatus)
 					self.preamtureExit = True
+					self.eNBmbmsEnables[int(self.eNB_instance)] = False
 					return
 				else:
 					self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 			else:
 				self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		self.eNBmbmsEnables[int(self.eNB_instance)] = False
 
 	def TerminateHSS(self):
 		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
@@ -4558,6 +4631,13 @@ def GetParametersFromXML(action):
 			if SSH.iperf_profile != 'balanced' and SSH.iperf_profile != 'unbalanced' and SSH.iperf_profile != 'single-ue':
 				logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile)
 				SSH.iperf_profile = 'balanced'
+		SSH.iperf_options = test.findtext('iperf_options')
+		if (SSH.iperf_options is None):
+			SSH.iperf_options = 'check'
+		else:
+			if SSH.iperf_options != 'check' and SSH.iperf_options != 'sink':
+				logging.debug('ERROR: test-case has wrong option ' + SSH.iperf_options)
+				SSH.iperf_options = 'check'
 
 	if action == 'IdleSleep':
 		string_field = test.findtext('idle_sleep_time_in_sec')
diff --git a/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_mbms_no_s1.xml b/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_mbms_no_s1.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b841d3bab4b5eea7c60e0492904e8ca78094a4be
--- /dev/null
+++ b/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_mbms_no_s1.xml
@@ -0,0 +1,82 @@
+<!--
+
+ Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The OpenAirInterface Software Alliance licenses this file to You under
+ the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.openairinterface.org/?page_id=698
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ For more information about the OpenAirInterface (OAI) Software Alliance:
+      contact@openairinterface.org
+
+-->
+<testCaseList>
+	<htmlTabRef>test-05-tm1-mbms-nos1-tunnel</htmlTabRef>
+	<htmlTabName>Test-05MHz-MBMS-TM1-noS1-tunnel</htmlTabName>
+	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>2</repeatCount>
+	<TestCaseRequestedList>
+ 030201 090109
+ 030103 000001 090103 000002 040605 000001 090109 030201
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="000001">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="000002">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>15</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="000003">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="030103">
+		<class>Initialize_eNB</class>
+		<desc>Initialize eNB (FDD/Band7/5MHz/MBMS)</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf --noS1 --eNBs.[0].rrc_inactivity_threshold 0 --nokrnmod 1 --eNBs.[0].component_carriers.[0].eutra_band 7 --eNBs.[0].component_carriers.[0].downlink_frequency 2680000000 --eNBs.[0].component_carriers.[0].uplink_frequency_offset -120000000</Initialize_eNB_args>
+	</testCase>
+
+	<testCase id="030201">
+		<class>Terminate_eNB</class>
+		<desc>Terminate eNB</desc>
+	</testCase>
+
+	<testCase id="090103">
+		<class>Initialize_OAI_UE</class>
+		<desc>Initialize OAI UE (FDD/Band7/5MHz/MBMS)</desc>
+		<Initialize_OAI_UE_args>-C 2680000000 -r 25 --ue-rxgain 120 --ue-txgain 0 --ue-max-power 0 --ue-scan-carrier --nokrnmod 1 --noS1</Initialize_OAI_UE_args>
+	</testCase>
+
+	<testCase id="090109">
+		<class>Terminate_OAI_UE</class>
+		<desc>Terminate OAI UE</desc>
+	</testCase>
+
+	<testCase id="040605">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - DL/1.5Mbps/UDP/MBMS-sink)(20 sec)</desc>
+		<iperf_args>-c 10.0.2.2 -u -b 1.5M -t 20 -i 1 -fm -B 10.0.2.1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_options>sink</iperf_options>
+	</testCase>
+
+</testCaseList>
diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index e429b9e58fc18701cf0e1bbd47bc12d8ba847ba8..273591c8e2db59cc079010e19b01f1aff1273719 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -395,6 +395,145 @@ add_library(S1AP_ENB
   )
 add_dependencies(S1AP_ENB rrc_flag s1ap_flag)
 
+
+#M2AP
+# Same limitation as described in RRC/S1AP: unknown generated file list
+# so we generate it at cmake time
+##############
+add_list1_option(M2AP_RELEASE R14 "M2AP ASN.1 grammar version" R14)
+
+set(M2AP_DIR ${OPENAIR2_DIR}/M2AP)
+if (${M2AP_RELEASE} STREQUAL "R8")
+  make_version(M2AP_VERSION 8 9 0)
+  set(M2AP_ASN_FILES m2ap-8.9.0.asn1)
+elseif (${M2AP_RELEASE} STREQUAL "R11")
+  make_version(M2AP_VERSION 11 9 0)
+  set(M2AP_ASN_FILES m2ap-11.9.0.asn1)
+elseif (${M2AP_RELEASE} STREQUAL "R12")
+  make_version(M2AP_VERSION 12 9 0)
+  set(M2AP_ASN_FILES m2ap-12.9.0.asn1)
+elseif (${M2AP_RELEASE} STREQUAL "R14")
+  make_version(M2AP_VERSION 14 0 0)
+  set(M2AP_ASN_FILES m2ap-14.0.0.asn1)
+elseif (${M2AP_RELEASE} STREQUAL "R15")
+  make_version(M2AP_VERSION 15 1 0)
+  set(M2AP_ASN_FILES m2ap-15.1.0.asn1)
+endif(${M2AP_RELEASE} STREQUAL "R8")
+add_definitions(-DM2AP_VERSION=${M2AP_VERSION})
+set(M2AP_ASN_DIR ${M2AP_DIR}/MESSAGES/ASN1/${M2AP_RELEASE})
+set(M2AP_C_DIR ${asn1_generated_dir}/M2AP_${M2AP_RELEASE})
+
+# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make
+execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${M2AP_C_DIR}" "${M2AP_ASN_DIR}/${M2AP_ASN_FILES}"  "M2AP_" -fno-include-deps -DEMIT_ASN_DEBUG=1
+                RESULT_VARIABLE ret)
+if (NOT ${ret} STREQUAL 0)
+  message(FATAL_ERROR "${ret}: error")
+endif (NOT ${ret} STREQUAL 0)
+
+file(GLOB M2AP_source ${M2AP_C_DIR}/*.c)
+
+add_custom_target (
+  m2_flag ALL
+  COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${M2AP_C_DIR}" "${M2AP_ASN_DIR}/${M2AP_ASN_FILES}"  "M2AP_" -fno-include-deps
+  DEPENDS ${M2AP_ASN_DIR}/${M2AP_ASN_FILES}
+  )
+
+add_library(M2AP_LIB
+  ${M2AP_source}
+  ${M2AP_DIR}/m2ap_common.c
+  )
+add_dependencies(M2AP_LIB rrc_flag m2_flag)
+
+include_directories ("${M2AP_C_DIR}")
+include_directories ("${M2AP_DIR}")
+
+add_library(M2AP_ENB
+  ${M2AP_DIR}/m2ap_eNB.c
+  ${M2AP_DIR}/m2ap_MCE.c
+  ${M2AP_DIR}/m2ap_decoder.c
+  ${M2AP_DIR}/m2ap_encoder.c
+  ${M2AP_DIR}/m2ap_MCE_handler.c
+  ${M2AP_DIR}/m2ap_eNB_handler.c
+  ${M2AP_DIR}/m2ap_itti_messaging.c
+  ${M2AP_DIR}/m2ap_eNB_management_procedures.c
+  ${M2AP_DIR}/m2ap_eNB_generate_messages.c
+  ${M2AP_DIR}/m2ap_MCE_management_procedures.c
+  ${M2AP_DIR}/m2ap_MCE_generate_messages.c
+  ${M2AP_DIR}/m2ap_ids.c
+  ${M2AP_DIR}/m2ap_timers.c
+  ${M2AP_DIR}/m2ap_MCE_interface_management.c
+  ${M2AP_DIR}/m2ap_eNB_interface_management.c
+ )
+add_dependencies(M2AP_ENB rrc_flag m2_flag)
+
+#M3AP
+# Same limitation as described in RRC/S1AP: unknown generated file list
+# so we generate it at cmake time
+##############
+add_list1_option(M3AP_RELEASE R14 "M3AP ASN.1 grammar version" R14)
+
+set(M3AP_DIR ${OPENAIR3_DIR}/M3AP)
+if (${M3AP_RELEASE} STREQUAL "R8")
+  make_version(M3AP_VERSION 8 9 0)
+  set(M3AP_ASN_FILES m3ap-8.9.0.asn1)
+elseif (${M3AP_RELEASE} STREQUAL "R11")
+  make_version(M3AP_VERSION 11 9 0)
+  set(M3AP_ASN_FILES m3ap-11.9.0.asn1)
+elseif (${M3AP_RELEASE} STREQUAL "R12")
+  make_version(M3AP_VERSION 12 9 0)
+  set(M3AP_ASN_FILES m3ap-12.9.0.asn1)
+elseif (${M3AP_RELEASE} STREQUAL "R14")
+  make_version(M3AP_VERSION 14 0 0)
+  set(M3AP_ASN_FILES m3ap-14.0.0.asn1)
+elseif (${M3AP_RELEASE} STREQUAL "R15")
+  make_version(M3AP_VERSION 15 1 0)
+  set(M3AP_ASN_FILES m3ap-15.1.0.asn1)
+endif(${M3AP_RELEASE} STREQUAL "R8")
+add_definitions(-DM3AP_VERSION=${M3AP_VERSION})
+set(M3AP_ASN_DIR ${M3AP_DIR}/MESSAGES/ASN1/${M3AP_RELEASE})
+set(M3AP_C_DIR ${asn1_generated_dir}/M3AP_${M3AP_RELEASE})
+
+# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make
+execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${M3AP_C_DIR}" "${M3AP_ASN_DIR}/${M3AP_ASN_FILES}"  "M3AP_" -fno-include-deps
+                RESULT_VARIABLE ret)
+if (NOT ${ret} STREQUAL 0)
+  message(FATAL_ERROR "${ret}: error")
+endif (NOT ${ret} STREQUAL 0)
+
+file(GLOB M3AP_source ${M3AP_C_DIR}/*.c)
+
+add_custom_target (
+  m3_flag ALL
+  COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${M3AP_C_DIR}" "${M3AP_ASN_DIR}/${M3AP_ASN_FILES}"  "M3AP_" -fno-include-deps
+  DEPENDS ${M3AP_ASN_DIR}/${M3AP_ASN_FILES}
+  )
+
+add_library(M3AP_LIB
+  ${M3AP_source}
+  ${M3AP_DIR}/m3ap_common.c
+  )
+add_dependencies(M3AP_LIB rrc_flag m3_flag)
+
+include_directories ("${M3AP_C_DIR}")
+include_directories ("${M3AP_DIR}")
+
+add_library(M3AP_ENB
+  ${M3AP_DIR}/m3ap_decoder.c
+  ${M3AP_DIR}/m3ap_encoder.c
+  ${M3AP_DIR}/m3ap_MCE_handler.c
+  ${M3AP_DIR}/m3ap_MME_handler.c
+  ${M3AP_DIR}/m3ap_MME.c
+  ${M3AP_DIR}/m3ap_MME_management_procedures.c
+  ${M3AP_DIR}/m3ap_MME_interface_management.c
+  ${M3AP_DIR}/m3ap_MCE.c
+  ${M3AP_DIR}/m3ap_MCE_management_procedures.c
+  ${M3AP_DIR}/m3ap_MCE_interface_management.c
+  ${M3AP_DIR}/m3ap_itti_messaging.c
+  ${M3AP_DIR}/m3ap_ids.c
+  ${M3AP_DIR}/m3ap_timers.c
+  )
+add_dependencies(M3AP_ENB rrc_flag m3_flag)
+
 #X2AP
 # Same limitation as described in RRC/S1AP: unknown generated file list
 # so we generate it at cmake time
@@ -749,6 +888,7 @@ include_directories("${OPENAIR2_DIR}")
 include_directories("${OPENAIR3_DIR}/NAS/TOOLS")
 include_directories("${OPENAIR2_DIR}/ENB_APP")
 include_directories("${OPENAIR2_DIR}/GNB_APP")
+include_directories("${OPENAIR2_DIR}/MCE_APP")
 include_directories("${OPENAIR2_DIR}/LAYER2/RLC")
 include_directories("${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0")
 include_directories("${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0")
@@ -771,9 +911,12 @@ include_directories("${OPENAIR3_DIR}/SECU")
 include_directories("${OPENAIR3_DIR}/SCTP")
 include_directories("${OPENAIR3_DIR}/S1AP")
 include_directories("${OPENAIR2_DIR}/X2AP")
+include_directories("${OPENAIR2_DIR}/M2AP")
 include_directories("${OPENAIR2_DIR}/F1AP")
 include_directories("${OPENAIR3_DIR}/UDP")
 include_directories("${OPENAIR3_DIR}/GTPV1-U")
+include_directories("${OPENAIR3_DIR}/M3AP")
+include_directories("${OPENAIR3_DIR}/MME_APP")
 include_directories("${OPENAIR_DIR}/targets/COMMON")
 include_directories("${OPENAIR_DIR}/targets/ARCH/COMMON")
 include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY")
@@ -1529,6 +1672,7 @@ set(L2_SRC
 #  ${RRC_DIR}/rrc_UE.c
   ${RRC_DIR}/rrc_eNB.c
   ${RRC_DIR}/rrc_eNB_S1AP.c
+  ${RRC_DIR}/rrc_eNB_M2AP.c
   ${RRC_DIR}/rrc_eNB_UE_context.c
   ${RRC_DIR}/rrc_common.c
   ${RRC_DIR}/L2_interface.c
@@ -1647,12 +1791,18 @@ set (GNB_APP_SRC
   ${OPENAIR2_DIR}/GNB_APP/gnb_config.c
   )
 
+set (MCE_APP_SRC
+  ${OPENAIR2_DIR}/MCE_APP/mce_app.c
+  ${OPENAIR2_DIR}/MCE_APP/mce_config.c
+  )
+
 add_library(L2
   ${L2_SRC}
   ${MAC_SRC}
   ${ENB_APP_SRC}
+  ${MCE_APP_SRC}
   )
-add_dependencies(L2 rrc_flag s1ap_flag x2_flag)
+add_dependencies(L2 rrc_flag s1ap_flag x2_flag m2_flag m3_flag)
 
 add_library(MAC_NR
   ${MAC_NR_SRC}
@@ -1717,6 +1867,13 @@ set (GTPV1U_SRC
 add_library(GTPV1U ${GTPV1U_SRC})
 add_dependencies(GTPV1U rrc_flag)
 
+set (MME_APP_SRC
+  ${OPENAIR3_DIR}/MME_APP/mme_app.c
+  ${OPENAIR3_DIR}/MME_APP/mme_config.c
+)
+add_library(MME_APP ${MME_APP_SRC})
+add_dependencies(MME_APP rrc_flag s1ap_flag x2_flag m2_flag m3_flag)
+
 set(SCTP_SRC
   ${OPENAIR3_DIR}/SCTP/sctp_common.c
   ${OPENAIR3_DIR}/SCTP/sctp_eNB_task.c
@@ -2298,6 +2455,7 @@ add_executable(lte-softmodem
   ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c
   ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
   ${OPENAIR_TARGETS}/COMMON/create_tasks.c
+  ${OPENAIR_TARGETS}/COMMON/create_tasks_mbms.c
   ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
   ${OPENAIR2_DIR}/RRC/NAS/nas_config.c
   ${OPENAIR2_DIR}/RRC/NAS/rb_config.c
@@ -2317,7 +2475,7 @@ add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag)
 
 target_link_libraries (lte-softmodem
   -Wl,--start-group
-  RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB 
+  RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB 
   PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7
   ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB}
   -Wl,--end-group z dl)
@@ -2389,9 +2547,10 @@ if (NOT ${NOS1})
 endif()
 target_link_libraries (lte-uesoftmodem
   -Wl,--start-group
-  RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB F1AP F1AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON 
-  PHY_UE PHY_RU LFDS L2_UE L2_LTE SIMU ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
-  NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
+  RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP F1AP_LIB
+  GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
+  PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
+  ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES}
   -Wl,--end-group z dl)
 
 target_link_libraries (lte-uesoftmodem ${LIBXML2_LIBRARIES})
@@ -2654,7 +2813,7 @@ add_executable(test_epc_generate_scenario
   ${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h
   )
 target_link_libraries (test_epc_generate_scenario
-  -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
+  -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
   )
 
 add_executable(test_epc_play_scenario
@@ -2673,7 +2832,7 @@ add_executable(test_epc_play_scenario
   )
 target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c)
 target_link_libraries (test_epc_play_scenario
-  -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY_COMMON PHY PHY_UE LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
+  -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY_COMMON PHY PHY_UE LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
   )
 
 
@@ -2711,15 +2870,15 @@ if (${T_TRACER})
         syncsim nr_ulsim nr_dlsim nr_dlschsim nr_pbchsim nr_pucchsim
         nr_ulschsim ldpctest polartest smallblocktest cu_test du_test
         #all "add_library" definitions
-        ITTI RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB F1AP_LIB
-        F1AP params_libconfig oai_exmimodevif oai_usrpdevif oai_bladerfdevif
-        oai_lmssdrdevif oai_eth_transpro oai_mobipass tcp_bridge tcp_bridge_oai
-        coding FLPT_MSG ASYNC_IF FLEXRAN_AGENT HASHTABLE MSC UTIL OMG_SUMO 
-        SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB
-        SCHED_NR_UE_LIB NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB
-        NFAPI_USER_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_UE PHY_RU PHY_MEX
-        L2 L2_LTE L2_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_NR MAC_UE_NR CN_UTILS GTPV1U
-        SCTP_CLIENT UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU SIMU_ETH OPENAIR0_LIB)
+        ITTI RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP 
+        params_libconfig oai_exmimodevif oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif
+        oai_eth_transpro oai_mobipass tcp_bridge tcp_bridge_oai
+        coding FLPT_MSG ASYNC_IF FLEXRAN_AGENT HASHTABLE MSC UTIL OMG_SUMO
+        SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
+        NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
+        PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_UE PHY_RU PHY_MEX
+        L2 L2_LTE L2_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_NR MAC_UE_NR
+        CN_UTILS GTPV1U SCTP_CLIENT MME_APP UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU SIMU_ETH OPENAIR0_LIB)
     if (TARGET ${i})
       add_dependencies(${i} generate_T)
     endif()
diff --git a/common/ngran_types.h b/common/ngran_types.h
index 224a85def5c704f03f873e139f3a1a4de05123f0..3dfa7aa01afac085185239d814e5c80467c711fe 100644
--- a/common/ngran_types.h
+++ b/common/ngran_types.h
@@ -41,11 +41,13 @@ typedef enum {
   ngran_ng_eNB_CU = 4,
   ngran_gNB_CU    = 5,
   ngran_eNB_DU    = 6,
-  ngran_gNB_DU    = 7
+  ngran_gNB_DU    = 7,
+  ngran_eNB_MBMS_STA  = 8
 } ngran_node_t;
 
 #define NODE_IS_MONOLITHIC(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB    || (nOdE_TyPe) == ngran_ng_eNB    || (nOdE_TyPe) == ngran_gNB)
 #define NODE_IS_CU(nOdE_TyPe)         ((nOdE_TyPe) == ngran_eNB_CU || (nOdE_TyPe) == ngran_ng_eNB_CU || (nOdE_TyPe) == ngran_gNB_CU)
 #define NODE_IS_DU(nOdE_TyPe)         ((nOdE_TyPe) == ngran_eNB_DU || (nOdE_TyPe) == ngran_gNB_DU)
+#define NODE_IS_MBMS(nOdE_TyPe)       ((nOdE_TyPe) == ngran_eNB_MBMS_STA)
 
 #endif
diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c
index 5a5f334602801f8e09f7ba9c9e1ba755b1a055b8..f6d57bd791d1c1100f254e4f208671131ffd4b94 100644
--- a/common/utils/LOG/log.c
+++ b/common/utils/LOG/log.c
@@ -418,6 +418,8 @@ int logInit (void)
   register_log_component("eRAL","",RAL_ENB);
   register_log_component("mRAL","",RAL_UE);
   register_log_component("ENB_APP","log",ENB_APP);
+  register_log_component("MCE_APP","log",MCE_APP);
+  register_log_component("MME_APP","log",MME_APP);
   register_log_component("FLEXRAN_AGENT","log",FLEXRAN_AGENT);
   register_log_component("PROTO_AGENT","log",PROTO_AGENT);
   register_log_component("TMR","",TMR);
@@ -431,6 +433,8 @@ int logInit (void)
   register_log_component("GTPV1U","",GTPU);
   register_log_component("S1AP","",S1AP);
   register_log_component("F1AP","",F1AP);
+  register_log_component("M2AP","",M2AP);
+  register_log_component("M3AP","",M3AP);
   register_log_component("SCTP","",SCTP);
   register_log_component("X2AP","",X2AP);
   register_log_component("LOADER","log",LOADER);
diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h
index 096c0012039ba551787c1f4a72b4e98d4d6156e4..6baec7dfeb2188b1360a2cb9d854a1f061bb0520 100644
--- a/common/utils/LOG/log.h
+++ b/common/utils/LOG/log.h
@@ -215,6 +215,8 @@ typedef enum {
   RAL_ENB,
   RAL_UE,
   ENB_APP,
+  MCE_APP,
+  MME_APP,
   FLEXRAN_AGENT,
   TMR,
   USIM,
@@ -222,6 +224,8 @@ typedef enum {
   PROTO_AGENT,
   F1U,
   X2AP,
+  M2AP,
+  M3AP,
   GNB_APP,
   NR_RRC,
   NR_MAC,
diff --git a/common/utils/LOG/vcd_signal_dumper.c b/common/utils/LOG/vcd_signal_dumper.c
index 63c5336bd88fc25751b623106a1417525f631588..103cf1cd9473ae142af39f86e9a76ccc73e1b194 100644
--- a/common/utils/LOG/vcd_signal_dumper.c
+++ b/common/utils/LOG/vcd_signal_dumper.c
@@ -470,6 +470,8 @@ const char* eurecomFunctionsNames[] = {
   "pdcp_fifo_read_buffer",
   "pdcp_fifo_flush",
   "pdcp_fifo_flush_buffer",
+  "pdcp_mbms_fifo_read",
+  "pdcp_mbms_fifo_read_buffer",
   /* RRC signals  */
   "rrc_rx_tx",
   "rrc_mac_config_req",
diff --git a/common/utils/LOG/vcd_signal_dumper.h b/common/utils/LOG/vcd_signal_dumper.h
index 3a6fb6d6abb9f932b700efa1acb747ef6fd5a1ad..9383b39b1ee18712c75cb516d406588066ce3532 100644
--- a/common/utils/LOG/vcd_signal_dumper.h
+++ b/common/utils/LOG/vcd_signal_dumper.h
@@ -454,6 +454,8 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ_BUFFER,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_MBMS_FIFO_READ,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_MBMS_FIFO_READ_BUFFER,
 
   /* RRC signals  */
   VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,
diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h
index ab275d4d62d9cd7f03474e0a0521881b963adecb..b59fae2a0c3c06d7231eccf9586ad27b6bebb1e2 100644
--- a/common/utils/T/T_defs.h
+++ b/common/utils/T/T_defs.h
@@ -73,7 +73,7 @@ typedef struct {
 } T_cache_t;
 
 /* number of VCD functions (to be kept up to date! see in T_messages.txt) */
-#define VCD_NUM_FUNCTIONS (245)
+#define VCD_NUM_FUNCTIONS (247)
 
 /* number of VCD variables (to be kept up to date! see in T_messages.txt) */
 #define VCD_NUM_VARIABLES (186)
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 407bb66be17416fccb5345f58198da518fdf4357..387257d145eb49a4c806f36ab53fa7eb4a1fcd81 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -405,6 +405,48 @@ ID = LEGACY_X2AP_TRACE
     GROUP = ALL:LEGACY_X2AP:LEGACY_GROUP_TRACE:LEGACY
     FORMAT = string,log
 
+ID = LEGACY_M2AP_INFO
+    DESC = M2AP legacy logs - info level
+    GROUP = ALL:LEGACY_M2AP:LEGACY_GROUP_INFO:LEGACY
+    FORMAT = string,log
+ID = LEGACY_M2AP_ERROR
+    DESC = M2AP legacy logs - error level
+    GROUP = ALL:LEGACY_M2AP:LEGACY_GROUP_ERROR:LEGACY
+    FORMAT = string,log
+ID = LEGACY_M2AP_WARNING
+    DESC = M2AP legacy logs - warning level
+    GROUP = ALL:LEGACY_M2AP:LEGACY_GROUP_WARNING:LEGACY
+    FORMAT = string,log
+ID = LEGACY_M2AP_DEBUG
+    DESC = M2AP legacy logs - debug level
+    GROUP = ALL:LEGACY_M2AP:LEGACY_GROUP_DEBUG:LEGACY
+    FORMAT = string,log
+ID = LEGACY_M2AP_TRACE
+    DESC = M2AP legacy logs - trace level
+    GROUP = ALL:LEGACY_M2AP:LEGACY_GROUP_TRACE:LEGACY
+    FORMAT = string,log
+
+ID = LEGACY_M3AP_INFO
+    DESC = M3AP legacy logs - info level
+    GROUP = ALL:LEGACY_M3AP:LEGACY_GROUP_INFO:LEGACY
+    FORMAT = string,log
+ID = LEGACY_M3AP_ERROR
+    DESC = M3AP legacy logs - error level
+    GROUP = ALL:LEGACY_M3AP:LEGACY_GROUP_ERROR:LEGACY
+    FORMAT = string,log
+ID = LEGACY_M3AP_WARNING
+    DESC = M3AP legacy logs - warning level
+    GROUP = ALL:LEGACY_M3AP:LEGACY_GROUP_WARNING:LEGACY
+    FORMAT = string,log
+ID = LEGACY_M3AP_DEBUG
+    DESC = M3AP legacy logs - debug level
+    GROUP = ALL:LEGACY_M3AP:LEGACY_GROUP_DEBUG:LEGACY
+    FORMAT = string,log
+ID = LEGACY_M3AP_TRACE
+    DESC = M3AP legacy logs - trace level
+    GROUP = ALL:LEGACY_M3AP:LEGACY_GROUP_TRACE:LEGACY
+    FORMAT = string,log
+
 ID = LEGACY_RRC_INFO
     DESC = RRC legacy logs - info level
     GROUP = ALL:LEGACY_RRC:LEGACY_GROUP_INFO:LEGACY
@@ -529,6 +571,47 @@ ID = LEGACY_GNB_APP_DEBUG
 ID = LEGACY_GNB_APP_TRACE
     DESC = GNB_APP legacy logs - trace level
     GROUP = ALL:LEGACY_GNB_APP:LEGACY_GROUP_TRACE:LEGACY
+
+ID = LEGACY_MCE_APP_INFO
+    DESC = MCE_APP legacy logs - info level
+    GROUP = ALL:LEGACY_MCE_APP:LEGACY_GROUP_INFO:LEGACY
+    FORMAT = string,log
+ID = LEGACY_MCE_APP_ERROR
+    DESC = MCE_APP legacy logs - error level
+    GROUP = ALL:LEGACY_MCE_APP:LEGACY_GROUP_ERROR:LEGACY
+    FORMAT = string,log
+ID = LEGACY_MCE_APP_WARNING
+    DESC = MCE_APP legacy logs - warning level
+    GROUP = ALL:LEGACY_MCE_APP:LEGACY_GROUP_WARNING:LEGACY
+    FORMAT = string,log
+ID = LEGACY_MCE_APP_DEBUG
+    DESC = MCE_APP legacy logs - debug level
+    GROUP = ALL:LEGACY_MCE_APP:LEGACY_GROUP_DEBUG:LEGACY
+    FORMAT = string,log
+ID = LEGACY_MCE_APP_TRACE
+    DESC = MCE_APP legacy logs - trace level
+    GROUP = ALL:LEGACY_MCE_APP:LEGACY_GROUP_TRACE:LEGACY
+    FORMAT = string,log
+
+ID = LEGACY_MME_APP_INFO
+    DESC = MME_APP legacy logs - info level
+    GROUP = ALL:LEGACY_MME_APP:LEGACY_GROUP_INFO:LEGACY
+    FORMAT = string,log
+ID = LEGACY_MME_APP_ERROR
+    DESC = MME_APP legacy logs - error level
+    GROUP = ALL:LEGACY_MME_APP:LEGACY_GROUP_ERROR:LEGACY
+    FORMAT = string,log
+ID = LEGACY_MME_APP_WARNING
+    DESC = MME_APP legacy logs - warning level
+    GROUP = ALL:LEGACY_MME_APP:LEGACY_GROUP_WARNING:LEGACY
+    FORMAT = string,log
+ID = LEGACY_MME_APP_DEBUG
+    DESC = MME_APP legacy logs - debug level
+    GROUP = ALL:LEGACY_MME_APP:LEGACY_GROUP_DEBUG:LEGACY
+    FORMAT = string,log
+ID = LEGACY_MME_APP_TRACE
+    DESC = MME_APP legacy logs - trace level
+    GROUP = ALL:LEGACY_MME_APP:LEGACY_GROUP_TRACE:LEGACY
     FORMAT = string,log
 
 ID = LEGACY_FLEXRAN_AGENT_INFO
@@ -3098,6 +3181,16 @@ ID = VCD_FUNCTION_PDCP_FIFO_FLUSH_BUFFER
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
     VCD_NAME = pdcp_fifo_flush_buffer
+ID = VCD_FUNCTION_PDCP_MBMS_FIFO_READ
+    DESC = VCD function PDCP_MBMS_FIFO_READ
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = pdcp_mbms_fifo_read
+ID = VCD_FUNCTION_PDCP_MBMS_FIFO_READ_BUFFER
+    DESC = VCD function PDCP_MBMS_FIFO_READ_BUFFER
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = pdcp_mbms_fifo_read_buffer
 ID = VCD_FUNCTION_RRC_RX_TX
     DESC = VCD function RRC_RX_TX
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
diff --git a/common/utils/ocp_itti/all_msg.h b/common/utils/ocp_itti/all_msg.h
index bbbe576e1bf94fb0d5b5cff0d448d2a15bfcfc90..a2add514e1e08e8e1bbc894b0777623c9746e36a 100644
--- a/common/utils/ocp_itti/all_msg.h
+++ b/common/utils/ocp_itti/all_msg.h
@@ -9,6 +9,8 @@
 #endif
 #include "openair2/COMMON/s1ap_messages_def.h"
 #include "openair2/COMMON/x2ap_messages_def.h"
+#include "openair2/COMMON/m2ap_messages_def.h"
+#include "openair2/COMMON/m3ap_messages_def.h"
 #include "openair2/COMMON/sctp_messages_def.h"
 #include "openair2/COMMON/udp_messages_def.h"
 #include "openair2/COMMON/gtpv1_u_messages_def.h"
diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h
index 20cd82efcaa5d12fa2fb29ca4c67fc5c246edf64..52c733752de92d885a230330dce385d3e56f558e 100644
--- a/common/utils/ocp_itti/intertask_interface.h
+++ b/common/utils/ocp_itti/intertask_interface.h
@@ -206,6 +206,8 @@ typedef struct IttiMsgText_s {
 #endif
 #include <openair2/COMMON/s1ap_messages_types.h>
 #include <openair2/COMMON/x2ap_messages_types.h>
+#include <openair2/COMMON/m2ap_messages_types.h>
+#include <openair2/COMMON/m3ap_messages_types.h>
 #include <openair2/COMMON/sctp_messages_types.h>
 #include <openair2/COMMON/udp_messages_types.h>
 #include <openair2/COMMON/gtpv1_u_messages_types.h>
@@ -231,6 +233,7 @@ typedef struct IttiMsgText_s {
 #include <openair3/NAS/UE/user_defs.h>
 #include <openair3/NAS/UE/nas_ue_task.h>
 #include <openair3/S1AP/s1ap_eNB.h>
+#include <openair3/MME_APP/mme_app.h>
 //#include <proto.h>
 
 #include <openair3/GTPV1-U/gtpv1u_eNB_task.h>
@@ -290,9 +293,16 @@ typedef struct {
   TASK_DEF(TASK_RAL_ENB,  TASK_PRIORITY_MED,  200, NULL, NULL)  \
   TASK_DEF(TASK_S1AP,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
   TASK_DEF(TASK_X2AP,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_M2AP_ENB,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_M2AP_MCE,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_M3AP,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_M3AP_MME,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_M3AP_MCE,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
   TASK_DEF(TASK_SCTP,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
   TASK_DEF(TASK_ENB_APP,  TASK_PRIORITY_MED,  200, NULL, NULL)  \
   TASK_DEF(TASK_GNB_APP,  TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_MCE_APP,  TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_MME_APP,  TASK_PRIORITY_MED,  200, NULL, NULL)  \
   TASK_DEF(TASK_FLEXRAN_AGENT,TASK_PRIORITY_MED, 200, NULL, NULL) \
   TASK_DEF(TASK_PHY_UE,   TASK_PRIORITY_MED,  200, NULL, NULL)  \
   TASK_DEF(TASK_MAC_UE,   TASK_PRIORITY_MED,  200, NULL, NULL)  \
diff --git a/nfapi/open-nFAPI/nfapi/inc/nfapi.h b/nfapi/open-nFAPI/nfapi/inc/nfapi.h
index 29a0e50438542b11f5f8fc6715b1a99d16c2754d..0f09efa78ab7d41032c4b3d68df3aac4e4c38139 100644
--- a/nfapi/open-nFAPI/nfapi/inc/nfapi.h
+++ b/nfapi/open-nFAPI/nfapi/inc/nfapi.h
@@ -44,10 +44,14 @@ uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end);
 uint32_t pullarray8(uint8_t **in, uint8_t out[], uint32_t max_len, uint32_t len, uint8_t *end);
 uint32_t pullarray16(uint8_t **in, uint16_t out[], uint32_t max_len, uint32_t len, uint8_t *end);
 uint32_t pullarrays16(uint8_t **in, int16_t out[], uint32_t max_len, uint32_t len, uint8_t *end);
+uint32_t pullarray32(uint8_t **in, uint32_t out[], uint32_t max_len, uint32_t len, uint8_t *end);
+uint32_t pullarrays32(uint8_t **in, int32_t out[], uint32_t max_len, uint32_t len, uint8_t *end);
 
 uint32_t pusharray8(uint8_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end);
 uint32_t pusharray16(uint16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end);
 uint32_t pusharrays16(int16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end);
+uint32_t pusharray32(uint32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end);
+uint32_t pusharrays32(int32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end);
 
 typedef uint8_t (*pack_array_elem_fn)(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end);
 uint8_t packarray(void* array, uint16_t elem_size, uint16_t max_count, uint16_t count, uint8_t **ppWritePackedMsg, uint8_t *end, pack_array_elem_fn fn);
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
index 2c31af4bc1a3cae039498cd1ad4d17f177b2c54c..32a31a99f6a41206a6963ceeab31cb7f29786a1c 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
@@ -735,6 +735,23 @@ typedef struct {
 #define NFAPI_PUCCH_CONFIG_N_AN_CS_TAG 0x003E
 #define NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG 0x003F
 
+typedef struct{
+       nfapi_uint8_tlv_t mbsfn_area_idx;
+       nfapi_uint16_tlv_t mbsfn_area_id_r9;
+} nfapi_embms_sib13_config_t;
+#define NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDX_TAG 0x0039
+#define NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDR9_TAG 0x0040
+
+typedef struct {
+       nfapi_tl_t tl;
+       uint16_t  num_mbsfn_config;
+       uint16_t  radioframe_allocation_period[8];
+       uint16_t  radioframe_allocation_offset[8];
+       uint8_t  fourframes_flag[8];
+       int32_t  mbsfn_subframeconfig[8];
+} nfapi_embms_mbsfn_config_t;
+#define NFAPI_EMBMS_MBSFN_CONFIG_TAG 0x0041
+
 typedef struct {
        nfapi_uint8_tlv_t radioframe_allocation_period;
        nfapi_uint8_tlv_t radioframe_allocation_offset;
@@ -1143,6 +1160,9 @@ typedef struct {
 	nfapi_prach_config_t prach_config;
 	nfapi_pusch_config_t pusch_config;
 	nfapi_pucch_config_t pucch_config;
+        // addition nfpai tlvs for embms MBSFN config //TOBE REVIEWED
+        nfapi_embms_sib13_config_t embms_sib13_config;
+        nfapi_embms_mbsfn_config_t embms_mbsfn_config;
 	nfapi_fembms_config_t fembms_config;
 	nfapi_srs_config_t srs_config;
 	nfapi_uplink_reference_signal_config_t uplink_reference_signal_config;
@@ -1165,6 +1185,9 @@ typedef struct {
 	nfapi_prach_config_t prach_config;
 	nfapi_pusch_config_t pusch_config;
 	nfapi_pucch_config_t pucch_config;
+        // addition nfpai tlvs for embms MBSFN config //TOBE REVIEWED
+        nfapi_embms_sib13_config_t embms_sib13_config;
+        nfapi_embms_mbsfn_config_t embms_mbsfn_config;
         nfapi_fembms_config_t fembms_config;
 	nfapi_srs_config_t srs_config;
 	nfapi_uplink_reference_signal_config_t uplink_reference_signal_config;
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c
index 3f017bc9a4a53b1fc40d939c308b78642cce2cca..156a48ec05dd9d8504d7be28d67a1cfbfc3dfc64 100644
--- a/nfapi/open-nFAPI/nfapi/src/nfapi.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c
@@ -405,7 +405,116 @@ uint32_t pusharrays16(int16_t in[], uint32_t max_len, uint32_t len, uint8_t **ou
 		return 0;
 	}
 }
+uint32_t pullarray32(uint8_t **in, uint32_t out[], uint32_t max_len, uint32_t len, uint8_t *end)
+{
+       if(len == 0)
+               return 1;
+
+       if(len > max_len)
+       {
+               NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+               return 0;
+       }
+
+       if((end - (*in)) >= sizeof(uint32_t) * len)
+       {
+               uint32_t idx;
+               for(idx = 0; idx < len; ++idx)
+               {
+                       if(!pull32(in, &out[idx], end))
+                               return 0;
+               }
+
+               return sizeof(uint32_t) * len;
+       }
+       else
+       {
+               NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+               return 0;
+       }
+}
 
+uint32_t pullarrays32(uint8_t **in, int32_t out[], uint32_t max_len, uint32_t len, uint8_t *end)
+{
+       if(len == 0)
+               return 1;
+
+       if(len > max_len)
+       {
+               NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+               return 0;
+       }
+
+       if((end - (*in)) >= sizeof(uint32_t) * len)
+       {
+               uint32_t idx;
+               for(idx = 0; idx < len; ++idx)
+               {
+                       if(!pulls32(in, &out[idx], end))
+                       return 0;
+               }
+
+               return sizeof(uint32_t) * len;
+       }
+       else
+       {
+               NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+               return 0;
+       }
+}
+uint32_t pusharray32(uint32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end)
+{
+       if(len == 0)
+               return 1;
+
+       if(len > max_len)
+       {
+               NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+               return 0;
+       }
+
+       if((end - (*out)) >= sizeof(uint32_t) * len)
+       {
+               uint32_t idx;
+               for(idx = 0; idx < len; ++idx)
+               {
+                       if(!push32(in[idx], out, end))
+                               return 0;
+               }
+               return sizeof(uint32_t) * len;
+       }
+       else
+       {
+               NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+               return 0;
+       }
+}
+uint32_t pusharrays32(int32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end)
+{
+       if(len == 0)
+               return 1;
+
+       if(len > max_len)
+       {
+               NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+               return 0;
+       }
+
+       if((end - (*out)) >= sizeof(uint32_t) * len)
+       {
+               uint32_t idx;
+               for(idx = 0; idx < len; ++idx)
+               {
+                       pushs32(in[idx], out, end);
+               }
+               return sizeof(uint32_t) * len;
+       }
+       else
+       {
+               NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+               return 0;
+       }
+}
 uint32_t pullarray8(uint8_t **in, uint8_t out[], uint32_t max_len, uint32_t len, uint8_t *end)
 {
 	if(len == 0)
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
index 54e27123d995ea1ec3088e0daa7a48c74574d64d..a8ac0f0a654716202e00ff051702505b3ee482bc 100644
--- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
@@ -404,7 +404,26 @@ static uint8_t unpack_nmm_frequency_bands_value(void* tlv, uint8_t **ppReadPacke
 	return ( pull16(ppReadPackedMsg, &value->number_of_rf_bands, end) &&
 			 pullarray16(ppReadPackedMsg, value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, end));
 }
-
+static uint8_t pack_embms_mbsfn_config_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+       nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv;
+       
+       return ( push16(value->num_mbsfn_config, ppWritePackedMsg, end) &&
+                pusharray16(value->radioframe_allocation_period, 8,value->num_mbsfn_config ,ppWritePackedMsg, end) &&
+                pusharray16(value->radioframe_allocation_offset, 8,value->num_mbsfn_config ,ppWritePackedMsg, end) &&
+                pusharray8(value->fourframes_flag, 8,value->num_mbsfn_config,ppWritePackedMsg, end) &&
+                pusharrays32(value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, ppWritePackedMsg, end));
+}
+//static uint8_t unpack_embms_mbsfn_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end)
+//{
+//     nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv;
+//
+//     return ( pull16(ppReadPackedMsg, &value->num_mbsfn_config, end) &&
+//              pull16(ppReadPackedMsg, &value->radioframe_allocation_period, end) &&
+//              pull16(ppReadPackedMsg, &value->radioframe_allocation_offset, end) &&
+//              pull8(ppReadPackedMsg, &value->fourframes_flag, end) &&
+//                      pullarrays32(ppReadPackedMsg, value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, end));
+//}
 static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
 {
 	nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg;
@@ -461,6 +480,11 @@ static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_
 			pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
 			pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
 
+                       pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDX_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_idx), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+                       pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDR9_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_id_r9), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+                       pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_TAG, &(pNfapiMsg->embms_mbsfn_config), ppWritePackedMsg, end, &pack_embms_mbsfn_config_value) &&
+
                        pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_PERIOD_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
                        pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_OFFSET_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
                        pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_FLAG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_config_flag), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index d754d2613452b713cc0e25d32548dad9400deb41..4736ae765eb578541c271b2cd1c5f5fad5746e16 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -69,6 +69,9 @@ l1_north_init_eNB () {
         LOG_I(PHY,"%s() RC.eNB[%d][%d] installing callbacks\n", __FUNCTION__, i,  j);
         RC.eNB[i][j]->if_inst->PHY_config_req = phy_config_request;
         RC.eNB[i][j]->if_inst->schedule_response = schedule_response;
+        RC.eNB[i][j]->if_inst->PHY_config_update_sib2_req = phy_config_update_sib2_request;
+        RC.eNB[i][j]->if_inst->PHY_config_update_sib13_req = phy_config_update_sib13_request;
+       
       }
     }
   } else {
@@ -283,7 +286,53 @@ void phy_config_request(PHY_Config_t *phy_config) {
   LOG_I (PHY, "eNB %d/%d configured\n", Mod_id, CC_id);
 }
 
+void phy_config_update_sib2_request(PHY_Config_t *phy_config) {
 
+  uint8_t         Mod_id = phy_config->Mod_id;
+  int             CC_id = phy_config->CC_id;
+  int i;
+  nfapi_config_request_t *cfg = phy_config->cfg;
+  LOG_I(PHY,"Configure sib2 Mod_id(%d), CC_id(%d) cfg %p\n",Mod_id,CC_id,cfg);
+
+  LTE_DL_FRAME_PARMS *fp = &RC.eNB[Mod_id][CC_id]->frame_parms;
+
+  fp->num_MBSFN_config =  cfg->embms_mbsfn_config.num_mbsfn_config;
+  for( i=0; i < cfg->embms_mbsfn_config.num_mbsfn_config; i++){
+      fp->MBSFN_config[i].radioframeAllocationPeriod =  cfg->embms_mbsfn_config.radioframe_allocation_period[i];
+      fp->MBSFN_config[i].radioframeAllocationOffset =  cfg->embms_mbsfn_config.radioframe_allocation_offset[i];
+      fp->MBSFN_config[i].fourFrames_flag =            cfg->embms_mbsfn_config.fourframes_flag[i];
+      fp->MBSFN_config[i].mbsfn_SubframeConfig =       cfg->embms_mbsfn_config.mbsfn_subframeconfig[i];  // 6-bit subframe configuration
+      LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is  %x\n", i,
+              fp->MBSFN_config[i].mbsfn_SubframeConfig);
+  }
+
+
+
+}
+void phy_config_update_sib13_request(PHY_Config_t *phy_config) {
+
+  uint8_t         Mod_id = phy_config->Mod_id;
+  int             CC_id = phy_config->CC_id;
+  nfapi_config_request_t *cfg = phy_config->cfg;
+
+  LOG_I(PHY,"configure sib3 Mod_id(%d), CC_id(%d) cfg %p\n",Mod_id,CC_id,cfg);
+  LTE_DL_FRAME_PARMS *fp = &RC.eNB[Mod_id][CC_id]->frame_parms;
+  LOG_I (PHY, "[eNB%d] Applying MBSFN_Area_id %d for index %d\n", Mod_id, (uint16_t)cfg->embms_sib13_config.mbsfn_area_id_r9.value, (uint8_t)cfg->embms_sib13_config.mbsfn_area_idx.value);
+
+  //cfg->embms_sib13_config.mbsfn_area_idx;
+  //cfg->embms_sib13_config.mbsfn_area_id_r9;
+
+  AssertFatal((uint8_t)cfg->embms_sib13_config.mbsfn_area_idx.value == 0, "Fix me: only called when mbsfn_Area_idx == 0\n");
+  if (cfg->embms_sib13_config.mbsfn_area_idx.value == 0) {
+    fp->Nid_cell_mbsfn = (uint16_t)cfg->embms_sib13_config.mbsfn_area_id_r9.value;
+    LOG_I(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n");
+  }
+  lte_gold_mbsfn (fp, RC.eNB[Mod_id][CC_id]->lte_gold_mbsfn_table, fp->Nid_cell_mbsfn);
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+  lte_gold_mbsfn_khz_1dot25 (fp, RC.eNB[Mod_id][CC_id]->lte_gold_mbsfn_khz_1dot25_table, fp->Nid_cell_mbsfn);
+#endif
+}
 
 void phy_config_sib13_eNB(module_id_t Mod_id,int CC_id,int mbsfn_Area_idx,
                           long mbsfn_AreaId_r9) {
diff --git a/openair1/PHY/INIT/lte_init_ue.c b/openair1/PHY/INIT/lte_init_ue.c
index 6c9ca73754087f461ff9cd3f9d05d56ff87ee94c..1a6f0081e1ab0fe151b8470ccdbd4b056dd617c0 100644
--- a/openair1/PHY/INIT/lte_init_ue.c
+++ b/openair1/PHY/INIT/lte_init_ue.c
@@ -154,6 +154,42 @@ void phy_config_sib2_ue(module_id_t Mod_id,int CC_id,
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_OUT);
 }
 
+void phy_config_mbsfn_list_ue(module_id_t                          Mod_id,
+                        int                                  CC_id,
+                        struct LTE_MBSFN_SubframeConfigList *mbsfn_SubframeConfigList){
+  // MBSFN
+
+    PHY_VARS_UE *ue        = PHY_vars_UE_g[Mod_id][CC_id];
+    LTE_DL_FRAME_PARMS *fp = &ue->frame_parms;
+    int i;
+
+  if (mbsfn_SubframeConfigList != NULL) {
+
+    fp->num_MBSFN_config = mbsfn_SubframeConfigList->list.count;
+
+    for (i=0; i<mbsfn_SubframeConfigList->list.count; i++) {
+      fp->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod;
+      fp->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset;
+
+      if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {
+        fp->MBSFN_config[i].fourFrames_flag = 0;
+        fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration
+        LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] pattern is  %d\n", i,
+              fp->MBSFN_config[i].mbsfn_SubframeConfig);
+      } else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration
+        fp->MBSFN_config[i].fourFrames_flag = 1;
+        fp->MBSFN_config[i].mbsfn_SubframeConfig =
+          mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]|
+          (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)|
+          (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]<<16);
+        LOG_I(PHY, "[CONFIG]  LTE_MBSFN_SubframeConfig[%d] pattern is  %x\n", i,
+              fp->MBSFN_config[i].mbsfn_SubframeConfig);
+      }
+    }
+  }
+}
+
+
 void phy_config_sib13_ue(module_id_t Mod_id,int CC_id,uint8_t eNB_id,int mbsfn_Area_idx,
                          long mbsfn_AreaId_r9) {
   LTE_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms;
@@ -578,7 +614,8 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
   LTE_UE_PDSCH **const pdsch_vars_SI      = ue->pdsch_vars_SI;
   LTE_UE_PDSCH **const pdsch_vars_ra      = ue->pdsch_vars_ra;
   LTE_UE_PDSCH **const pdsch_vars_p       = ue->pdsch_vars_p;
-  LTE_UE_PDSCH **const pdsch_vars_mch     = ue->pdsch_vars_MCH;
+  //LTE_UE_PDSCH **const pdsch_vars_mch     = ue->pdsch_vars_MCH;
+  LTE_UE_PDSCH* (*pdsch_vars_MCH_th)[][NUMBER_OF_CONNECTED_eNB_MAX] = &ue->pdsch_vars_MCH;
   LTE_UE_PDSCH* (*pdsch_vars_th)[][NUMBER_OF_CONNECTED_eNB_MAX+1] = &ue->pdsch_vars;
   LTE_UE_PDCCH* (*pdcch_vars_th)[][NUMBER_OF_CONNECTED_eNB_MAX]   = &ue->pdcch_vars;
   LTE_UE_PBCH **const pbch_vars           = ue->pbch_vars;
@@ -660,6 +697,7 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
   for (eNB_id=0; eNB_id<ue->n_connected_eNB; eNB_id++) {
     for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
       (*pdsch_vars_th)[th_id][eNB_id]     = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
+      (*pdsch_vars_MCH_th)[th_id][eNB_id]     = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
     }
 
     for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
@@ -669,12 +707,13 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
     pdsch_vars_SI[eNB_id]  = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
     pdsch_vars_ra[eNB_id]  = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
     pdsch_vars_p[eNB_id]   = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
-    pdsch_vars_mch[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
+    //pdsch_vars_mch[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
     prach_vars[eNB_id]     = (LTE_UE_PRACH *)malloc16_clear(sizeof(LTE_UE_PRACH));
     pbch_vars[eNB_id]      = (LTE_UE_PBCH *)malloc16_clear(sizeof(LTE_UE_PBCH));
 
     for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
       phy_init_lte_ue__PDSCH( (*pdsch_vars_th)[th_id][eNB_id], fp );
+      phy_init_lte_ue__PDSCH( (*pdsch_vars_MCH_th)[th_id][eNB_id], fp );
     }
 
     for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
@@ -683,16 +722,25 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
       (*pdsch_vars_th)[th_id][eNB_id]->llr[1]              = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
       (*pdsch_vars_th)[th_id][eNB_id]->llr128_2ndstream    = (int16_t **)malloc16_clear( sizeof(int16_t *) );
       (*pdsch_vars_th)[th_id][eNB_id]->rho                 = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) );
+
+      (*pdsch_vars_MCH_th)[th_id][eNB_id]->llr_shifts      = (uint8_t *)malloc16_clear(7*2*fp->N_RB_DL*12);
+      (*pdsch_vars_MCH_th)[th_id][eNB_id]->llr_shifts_p        = (*pdsch_vars_th)[0][eNB_id]->llr_shifts;
+      (*pdsch_vars_MCH_th)[th_id][eNB_id]->llr[1]              = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
+      (*pdsch_vars_MCH_th)[th_id][eNB_id]->llr128_2ndstream    = (int16_t **)malloc16_clear( sizeof(int16_t *) );
+      (*pdsch_vars_MCH_th)[th_id][eNB_id]->rho                 = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) );
+
     }
 
     for (int i=0; i<fp->nb_antennas_rx; i++) {
       for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
         (*pdsch_vars_th)[th_id][eNB_id]->rho[i]     = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
+	(*pdsch_vars_MCH_th)[th_id][eNB_id]->rho[i]     = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
       }
     }
 
     for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
       (*pdsch_vars_th)[th_id][eNB_id]->dl_ch_rho2_ext      = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
+      (*pdsch_vars_MCH_th)[th_id][eNB_id]->dl_ch_rho2_ext      = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
     }
 
     for (i=0; i<fp->nb_antennas_rx; i++)
@@ -702,6 +750,7 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
 
         for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
           (*pdsch_vars_th)[th_id][eNB_id]->dl_ch_rho2_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
+	  (*pdsch_vars_MCH_th)[th_id][eNB_id]->dl_ch_rho2_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
         }
       }
 
@@ -713,6 +762,11 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
           (*pdsch_vars_th)[th_id][eNB_id]->dl_ch_rho_ext[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
           (*pdsch_vars_th)[th_id][eNB_id]->dl_ch_mag1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
           (*pdsch_vars_th)[th_id][eNB_id]->dl_ch_magb1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
+
+          (*pdsch_vars_MCH_th)[th_id][eNB_id]->rxdataF_comp1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
+          (*pdsch_vars_MCH_th)[th_id][eNB_id]->dl_ch_rho_ext[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
+          (*pdsch_vars_MCH_th)[th_id][eNB_id]->dl_ch_mag1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
+          (*pdsch_vars_MCH_th)[th_id][eNB_id]->dl_ch_magb1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
         }
 
         for (int i=0; i<fp->nb_antennas_rx; i++)
@@ -724,6 +778,11 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
               (*pdsch_vars_th)[th_id][eNB_id]->rxdataF_comp1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
               (*pdsch_vars_th)[th_id][eNB_id]->dl_ch_mag1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
               (*pdsch_vars_th)[th_id][eNB_id]->dl_ch_magb1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
+
+              (*pdsch_vars_MCH_th)[th_id][eNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
+              (*pdsch_vars_MCH_th)[th_id][eNB_id]->rxdataF_comp1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
+              (*pdsch_vars_MCH_th)[th_id][eNB_id]->dl_ch_mag1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
+              (*pdsch_vars_MCH_th)[th_id][eNB_id]->dl_ch_magb1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
             }
           }
       }
@@ -732,7 +791,7 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
     phy_init_lte_ue__PDSCH( pdsch_vars_SI[eNB_id], fp );
     phy_init_lte_ue__PDSCH( pdsch_vars_ra[eNB_id], fp );
     phy_init_lte_ue__PDSCH( pdsch_vars_p[eNB_id], fp );
-    phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], fp );
+    //phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], fp );
 
     // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE
     for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
@@ -770,7 +829,7 @@ int init_lte_ue_signal(PHY_VARS_UE *ue,
     phy_init_lte_ue__PDSCH( pdsch_vars_SI[eNB_id], fp );
     phy_init_lte_ue__PDSCH( pdsch_vars_ra[eNB_id], fp );
     phy_init_lte_ue__PDSCH( pdsch_vars_p[eNB_id], fp );
-    phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], fp );
+    //phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], fp );
 
     // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE
     for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
diff --git a/openair1/PHY/INIT/phy_init.h b/openair1/PHY/INIT/phy_init.h
index fe11590a1b07668dbad902bb5fba34bb8b7b9a47..05d3b6c73ffbbe38d6e66b94c9018311f5f7cea7 100644
--- a/openair1/PHY/INIT/phy_init.h
+++ b/openair1/PHY/INIT/phy_init.h
@@ -178,6 +178,18 @@ void phy_config_sib2_ue(module_id_t                          Mod_id,
                         LTE_AdditionalSpectrumEmission_t    *additionalSpectrumEmission,
                         struct LTE_MBSFN_SubframeConfigList *mbsfn_SubframeConfigList);
 
+ /*!
+  \fn void phy_config_mbsfn_list_ue(module_id_t Mod_id,uint8_t CC_id
+      struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList)
+  \brief Configure LTE_DL_FRAME_PARMS with components derived after reception of MBSFN config list from SIB2 (at UE).
+  @param Mod_id Instance id
+  @param CC_id
+  @param mbsfn_SubframeConfigList MBSFN subframe configuration
+ */
+void phy_config_mbsfn_list_ue(module_id_t                          Mod_id,
+                        int                                  CC_id,
+                        struct LTE_MBSFN_SubframeConfigList *mbsfn_SubframeConfigList);
+
 
 /*!
   \fn phy_config_afterHO_ue
@@ -374,6 +386,9 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id,
 void phy_cleanup(void);
 
 void phy_config_request(PHY_Config_t *phy_config);
+void phy_config_update_sib2_request(PHY_Config_t *phy_config);
+void phy_config_update_sib13_request(PHY_Config_t *phy_config);
+
 
 int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf);
 void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms);
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
index 8a3649cf8727d5ad00ec73ae3a754593406afef2..04a49d062a3be069a78bb6e505c3cf3eb830f200 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
@@ -1946,11 +1946,11 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF,
       case 2:  //QPSK
 
       //            LOG_I(PHY,"%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
-      ((int16_t*)&txdataF[4][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
+      ((int16_t*)&txdataF[0][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
 
       *jj = *jj + 1;
 
-      ((int16_t*)&txdataF[4][tti_offset])[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
+      ((int16_t*)&txdataF[0][tti_offset])[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
 
       *jj = *jj + 1;
 
@@ -1989,8 +1989,8 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF,
     *jj=*jj+1;
 
 
-    ((int16_t *)&txdataF[4][tti_offset])[0]=qam_table_s[qam16_table_offset_re];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
-    ((int16_t *)&txdataF[4][tti_offset])[1]=qam_table_s[qam16_table_offset_im];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
+    ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s[qam16_table_offset_re];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
+    ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s[qam16_table_offset_im];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
 
     break;
 
@@ -2029,8 +2029,8 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF,
 
     *jj=*jj+1;
 
-    ((int16_t *)&txdataF[4][tti_offset])[0]=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
-    ((int16_t *)&txdataF[4][tti_offset])[1]=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
+    ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
+    ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
 
     break;
     default:
diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c
index 6fab3dc59bd8e229708d7fe9dd3e32c3f249a6c5..f48ee629a1eed9f1161105fcd27cb288541aca2c 100644
--- a/openair1/PHY/LTE_TRANSPORT/pmch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pmch.c
@@ -96,13 +96,17 @@ void generate_mch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a)
 	    get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1,
 	    2,proc->frame_tx,subframe,0);
   
+  eNB->dlsch_MCH->harq_processes[0]->Qm = get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs);
+ 
   generate_mbsfn_pilot(eNB,proc,
 		       eNB->common_vars.txdataF,
 		       AMP);
   
+  AssertFatal(eNB->dlsch_MCH->harq_processes[0]->pdu != NULL, "attempt to encode a NULL harq PDU\n");
   
   AssertFatal(dlsch_encoding(eNB,
-			     a,
+			    // a,
+			    eNB->dlsch_MCH->harq_processes[0]->pdu,
 			     1,
 			     eNB->dlsch_MCH,
 			     proc->frame_tx,
diff --git a/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c
index 287f76ac9132603d843b351083656408869168f1..69aa1c06a34aefb8c0999db10b4b34cc8ab069b4 100644
--- a/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c
+++ b/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c
@@ -57,10 +57,10 @@ void dump_mch(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,in
 #define NSYMB_PMCH 12
   sprintf(fname,"mch_rxF_ext0.m");
   sprintf(vname,"pmch_rxF_ext0");
-  LOG_M(fname,vname,ue->pdsch_vars_MCH[eNB_id]->rxdataF_ext[0],12*(ue->frame_parms.N_RB_DL)*12,1,1);
+  LOG_M(fname,vname,ue->pdsch_vars_MCH[ue->current_thread_id[subframe]][eNB_id]->rxdataF_ext[0],12*(ue->frame_parms.N_RB_DL)*12,1,1);
   sprintf(fname,"mch_ch_ext00.m");
   sprintf(vname,"pmch_ch_ext00");
-  LOG_M(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_estimates_ext[0],12*(ue->frame_parms.N_RB_DL)*NSYMB_PMCH,1,1);
+  LOG_M(fname,vname,ue->pdsch_vars_MCH[ue->current_thread_id[subframe]][eNB_id]->dl_ch_estimates_ext[0],12*(ue->frame_parms.N_RB_DL)*NSYMB_PMCH,1,1);
   /*
     LOG_M("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*NSYMB_PMCH,1,1);
     LOG_M("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*NSYMB_PMCH,1,1);
@@ -69,16 +69,16 @@ void dump_mch(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,in
   */
   sprintf(fname,"mch_rxF_comp0.m");
   sprintf(vname,"pmch_rxF_comp0");
-  LOG_M(fname,vname,ue->pdsch_vars_MCH[eNB_id]->rxdataF_comp0[0],12*(ue->frame_parms.N_RB_DL)*NSYMB_PMCH,1,1);
+  LOG_M(fname,vname,ue->pdsch_vars_MCH[ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp0[0],12*(ue->frame_parms.N_RB_DL)*NSYMB_PMCH,1,1);
   sprintf(fname,"mch_rxF_llr.m");
   sprintf(vname,"pmch_llr");
-  LOG_M(fname,vname, ue->pdsch_vars_MCH[eNB_id]->llr[0],coded_bits_per_codeword,1,0);
+  LOG_M(fname,vname, ue->pdsch_vars_MCH[ue->current_thread_id[subframe]][eNB_id]->llr[0],coded_bits_per_codeword,1,0);
   sprintf(fname,"mch_mag1.m");
   sprintf(vname,"pmch_mag1");
-  LOG_M(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_mag0[0],12*(ue->frame_parms.N_RB_DL)*NSYMB_PMCH,1,1);
+  LOG_M(fname,vname,ue->pdsch_vars_MCH[ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag0[0],12*(ue->frame_parms.N_RB_DL)*NSYMB_PMCH,1,1);
   sprintf(fname,"mch_mag2.m");
   sprintf(vname,"pmch_mag2");
-  LOG_M(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_magb0[0],12*(ue->frame_parms.N_RB_DL)*NSYMB_PMCH,1,1);
+  LOG_M(fname,vname,ue->pdsch_vars_MCH[ue->current_thread_id[subframe]][eNB_id]->dl_ch_magb0[0],12*(ue->frame_parms.N_RB_DL)*NSYMB_PMCH,1,1);
   LOG_M("mch00_ch0.m","pmch00_ch0",
         &(ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id][0][0]),
         ue->frame_parms.ofdm_symbol_size*12,1,1);
@@ -96,6 +96,7 @@ void dump_mch(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,in
 void fill_UE_dlsch_MCH(PHY_VARS_UE *ue,int mcs,int ndi,int rvidx,int eNB_id) {
   LTE_UE_DLSCH_t *dlsch = ue->dlsch_MCH[eNB_id];
   LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
+  dlsch->Mdlharq = 1;
   //  dlsch->rnti   = M_RNTI;
   dlsch->harq_processes[0]->mcs   = mcs;
   dlsch->harq_processes[0]->rvidx = rvidx;
@@ -242,15 +243,16 @@ void mch_channel_level(int **dl_ch_estimates_ext,
 
     for (i=0; i<(nre>>2); i++) {
 #if defined(__x86_64__) || defined(__i386__)
-      avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
+      avg128 = _mm_add_epi32(avg128,_mm_srai_epi32(_mm_madd_epi16(dl_ch128[0],dl_ch128[0]),log2_approx(nre>>2)-1));
 #elif defined(__arm__)
 #endif
     }
 
-    avg[aarx] = (((int *)&avg128)[0] +
-                 ((int *)&avg128)[1] +
-                 ((int *)&avg128)[2] +
-                 ((int *)&avg128)[3])/nre;
+    avg[aarx] = (((((int*)&avg128)[0] +
+                 ((int*)&avg128)[1] +
+                 ((int*)&avg128)[2] +
+                 ((int*)&avg128)[3])/(nre>>factor2(nre)))*(1<<(log2_approx(nre>>2)-1-factor2(nre))));
+
     //            printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
   }
 
@@ -289,16 +291,21 @@ void mch_channel_level_khz_1dot25(int **dl_ch_estimates_ext,
 
     for (i=0; i<(nre>>2); i++) {
 #if defined(__x86_64__) || defined(__i386__)
-      avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
+      //avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
+      avg128 = _mm_add_epi32(avg128,_mm_srai_epi32(_mm_madd_epi16(dl_ch128[0],dl_ch128[0]),log2_approx(nre>>2)-1));
 #elif defined(__arm__)
 #endif
     }
 
-    avg[aarx] = (((int *)&avg128)[0] +
-                 ((int *)&avg128)[1] +
-                 ((int *)&avg128)[2] +
-                 ((int *)&avg128)[3])/nre;
-    //printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
+   // avg[aarx] = (((int*)&avg128)[0] +
+   //              ((int*)&avg128)[1] +
+   //              ((int*)&avg128)[2] +
+   //              ((int*)&avg128)[3])/nre;
+   avg[aarx] = (((((int*)&avg128)[0] +
+                 ((int*)&avg128)[1] +
+                 ((int*)&avg128)[2] +
+                 ((int*)&avg128)[3])/(nre>>factor2(nre)))*(1<<(log2_approx(nre>>2)-1-factor2(nre))));
+                //printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
   }
 
 #if defined(__x86_64__) || defined(__i386__)
@@ -1215,7 +1222,7 @@ int rx_pmch(PHY_VARS_UE *ue,
             uint8_t subframe,
             unsigned char symbol) {
   LTE_UE_COMMON *common_vars  = &ue->common_vars;
-  LTE_UE_PDSCH **pdsch_vars   = &ue->pdsch_vars_MCH[eNB_id];
+  LTE_UE_PDSCH **pdsch_vars   = &ue->pdsch_vars_MCH[ue->current_thread_id[subframe]][eNB_id];
   LTE_DL_FRAME_PARMS *frame_parms    = &ue->frame_parms;
   LTE_UE_DLSCH_t   **dlsch        = &ue->dlsch_MCH[eNB_id];
   int avgs,aarx;
@@ -1301,7 +1308,7 @@ int rx_pmch_khz_1dot25(PHY_VARS_UE *ue,
                        ,int mcs) { // currently work around TOFIX
   //unsigned int symbol;
   LTE_UE_COMMON *common_vars  = &ue->common_vars;
-  LTE_UE_PDSCH **pdsch_vars   = &ue->pdsch_vars_MCH[eNB_id];
+  LTE_UE_PDSCH **pdsch_vars   = &ue->pdsch_vars_MCH[ue->current_thread_id[subframe]][eNB_id];
   LTE_DL_FRAME_PARMS *frame_parms    = &ue->frame_parms;
   //LTE_UE_DLSCH_t   **dlsch        = &ue->dlsch_MCH[eNB_id];
   int avgs,aarx;
diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h
index adcc1470d9edad34d14e49da9658f00208beb9ee..aeada81d80dd9c0107de3db53e798458d3070109 100644
--- a/openair1/PHY/defs_RU.h
+++ b/openair1/PHY/defs_RU.h
@@ -617,7 +617,9 @@ typedef enum {
   RRU_sync_ok=6,
   RRU_frame_resynch=7,
   RRU_MSG_max_num=8,
-  RRU_check_sync = 9
+  RRU_check_sync = 9,
+  RRU_config_update=10,
+  RRU_config_update_ok=11
 } rru_config_msg_type_t;
 
 
@@ -711,6 +713,10 @@ typedef struct RRU_config_s {
   time_stats_t ru_arrival_time;
   /// mask for RUs serving eNB (PRACH)
   int RU_mask_prach;
+  /// embms mbsfn sf config
+  int num_MBSFN_config;
+  /// embms mbsfn sf config
+  MBSFN_config_t MBSFN_config[8];
 } RRU_config_t;
 
 #endif //__PHY_DEFS_RU__H__
diff --git a/openair1/PHY/defs_UE.h b/openair1/PHY/defs_UE.h
index 2dffd09131b671340f29f6303036e1e1fcea35de..9163fc13b6189f4015641220b6c0c199bc7d34c3 100644
--- a/openair1/PHY/defs_UE.h
+++ b/openair1/PHY/defs_UE.h
@@ -671,7 +671,7 @@ typedef struct {
   LTE_UE_PDSCH     *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1];
   LTE_UE_PDSCH     *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1];
   LTE_UE_PDSCH     *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1];
-  LTE_UE_PDSCH     *pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_PDSCH     *pdsch_vars_MCH[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX];
   LTE_UE_PBCH      *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX];
   LTE_UE_PDCCH     *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX];
   LTE_UE_PRACH     *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX];
diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h
index 943dd672e288127ad38ef434e5945733159f0502..dba49b6a78084ccf24e22bb40c4b3815e279bfe4 100644
--- a/openair1/PHY/defs_eNB.h
+++ b/openair1/PHY/defs_eNB.h
@@ -72,7 +72,6 @@
 #define MAX_NUM_RU_PER_eNB 64
 #define MAX_NUM_RX_PRACH_PREAMBLES 4
 
-
 typedef struct {
   /// \brief Pointers (dynamic) to the received data in the time domain.
   /// - first index: rx antenna [0..nb_antennas_rx[
diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c
index e8b422a157536397048c7488cbb9ea1d701de6fe..8105877bc34cb65a1089e0f07622c033545baabf 100644
--- a/openair1/SCHED/fapi_l1.c
+++ b/openair1/SCHED/fapi_l1.c
@@ -137,7 +137,6 @@ void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
   // adjust transmit amplitude here based on NFAPI info
 }
 
-
 extern uint32_t localRIV2alloc_LUT6[32];
 extern uint32_t localRIV2alloc_LUT25[512];
 extern uint32_t localRIV2alloc_LUT50_0[1600];
@@ -147,6 +146,52 @@ extern uint32_t localRIV2alloc_LUT100_1[6000];
 extern uint32_t localRIV2alloc_LUT100_2[6000];
 extern uint32_t localRIV2alloc_LUT100_3[6000];
 
+void handle_nfapi_mch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,
+                            nfapi_dl_config_request_pdu_t *dl_config_pdu,
+                            uint8_t *sdu){ 
+
+  nfapi_dl_config_mch_pdu_rel8_t *rel8 = &dl_config_pdu->mch_pdu.mch_pdu_rel8;
+
+  LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_MCH;
+  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
+
+    //  dlsch->rnti   = M_RNTI;
+  dlsch->harq_processes[0]->mcs   = rel8->modulation;
+  //  dlsch->harq_processes[0]->Ndi   = ndi;
+  dlsch->harq_processes[0]->rvidx = 0;//rvidx;
+  dlsch->harq_processes[0]->Nl    = 1;
+  dlsch->harq_processes[0]->TBS   = TBStable[get_I_TBS(dlsch->harq_processes[0]->mcs)][frame_parms->N_RB_DL-1];
+  //  dlsch->harq_ids[subframe]       = 0;
+  dlsch->harq_processes[0]->nb_rb = frame_parms->N_RB_DL;
+
+  switch(frame_parms->N_RB_DL) {
+  case 6:
+    dlsch->harq_processes[0]->rb_alloc[0] = 0x3f;
+    break;
+
+  case 25:
+    dlsch->harq_processes[0]->rb_alloc[0] = 0x1ffffff;
+    break;
+
+  case 50:
+    dlsch->harq_processes[0]->rb_alloc[0] = 0xffffffff;
+    dlsch->harq_processes[0]->rb_alloc[1] = 0x3ffff;
+    break;
+
+  case 100:
+    dlsch->harq_processes[0]->rb_alloc[0] = 0xffffffff;
+    dlsch->harq_processes[0]->rb_alloc[1] = 0xffffffff;
+    dlsch->harq_processes[0]->rb_alloc[2] = 0xffffffff;
+    dlsch->harq_processes[0]->rb_alloc[3] = 0xf;
+    break;
+  }
+
+  dlsch->harq_ids[proc->frame_tx%2][proc->subframe_tx] = 0;
+
+  dlsch->harq_processes[0]->pdu = sdu;
+
+  dlsch->active = 1;
+}
 
 void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,
                             nfapi_dl_config_request_pdu_t *dl_config_pdu,
@@ -807,8 +852,30 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
 
         break;
 
-      case NFAPI_DL_CONFIG_MCH_PDU_TYPE:
+      case NFAPI_DL_CONFIG_MCH_PDU_TYPE:{
         //      handle_nfapi_mch_dl_pdu(eNB,dl_config_pdu);
+	//AssertFatal(1==0,"OK\n");
+        nfapi_dl_config_mch_pdu_rel8_t *mch_pdu_rel8 = &dl_config_pdu->mch_pdu.mch_pdu_rel8;
+	uint16_t pdu_index = mch_pdu_rel8->pdu_index;
+	uint16_t tx_pdus = TX_req->tx_request_body.number_of_pdus;
+	uint16_t invalid_pdu = pdu_index == -1;
+	uint8_t *sdu = invalid_pdu ? NULL : pdu_index >= tx_pdus ? NULL : TX_req->tx_request_body.tx_pdu_list[pdu_index].segments[0].segment_data;
+        LOG_D(PHY,"%s() [PDU:%d] NFAPI_DL_CONFIG_MCH_PDU_TYPE SFN/SF:%04d%d TX:%d/%d RX:%d/%d pdu_index:%d sdu:%p\n",
+              __FUNCTION__, i,
+              NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),
+              proc->frame_tx, proc->subframe_tx,
+              proc->frame_rx, proc->subframe_rx,
+              pdu_index, sdu);
+	if (sdu) { //sdu != NULL)
+          if (NFAPI_MODE!=NFAPI_MODE_VNF)
+		handle_nfapi_mch_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu, sdu);
+        } else {
+          dont_send=1;
+          LOG_E(MAC,"%s() NFAPI_DL_CONFIG_MCH_PDU_TYPE sdu is NULL DL_CFG:SFN/SF:%d:pdu_index:%d TX_REQ:SFN/SF:%d:pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(DL_req->sfn_sf), pdu_index,
+                NFAPI_SFNSF2DEC(TX_req->sfn_sf), tx_pdus);
+        }
+	do_oai=1;
+	}
         break;
 
       case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: {
diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h
index 3bd469b685f6ea3fc04d973f9fc6463d4533a545..05ec813917be7b0122dcba129c43f3fddab841c0 100644
--- a/openair1/SCHED/fapi_l1.h
+++ b/openair1/SCHED/fapi_l1.h
@@ -53,6 +53,11 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro
 			    nfapi_dl_config_request_pdu_t *dl_config_pdu,
 			    uint8_t codeword_index,
 			    uint8_t *sdu);
+
+void handle_nfapi_mch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,
+			    nfapi_dl_config_request_pdu_t *dl_config_pdu,
+			    uint8_t *sdu);
+
 void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
 			 nfapi_ul_config_request_pdu_t *ul_config_pdu,
 			 uint16_t frame,uint8_t subframe,uint8_t srs_present);
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index c0afdf25d1d9403b8fe60c5f33e8a71e1ad40d08..34d5a015900ce174bb747ceaca81ac3a4cee6273 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -48,6 +48,8 @@
 
 #include "intertask_interface.h"
 
+#define MBMS_NFAPI_SCHEDULER
+
 nfapi_ue_release_request_body_t release_rntis;
 
 int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t UE_id,uint8_t harq_pid, uint8_t bw_factor) {
@@ -118,11 +120,21 @@ lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subfr
   return(subframe_select(&RC.eNB[Mod_id][CC_id]->frame_parms,subframe));
 }
 
+#ifdef MBMS_NFAPI_SCHEDULER
+void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
+  int subframe = proc->subframe_tx;
+  // This is DL-Cell spec pilots in Control region
+  generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1);
+  if(eNB->dlsch_MCH->active==1)
+  	generate_mch (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/);
+  eNB->dlsch_MCH->active = 0;
+}
+#else
 void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
   MCH_PDU *mch_pduP=NULL;
   //  uint8_t sync_area=255;
   int             subframe = proc->subframe_tx;
-  AssertFatal (1 == 0, "pmch not tested for the moment, exiting\n");
+  AssertFatal (1 == 1, "pmch not tested for the moment, exiting\n");
   // This is DL-Cell spec pilots in Control region
   generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1);
 
@@ -134,6 +146,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
     proc->frame_tx,
     subframe);
   */
+  mch_pduP= &RC.mac[eNB->Mod_id]->common_channels[eNB->CC_id].MCH_pdu;
   if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0
     LOG_D(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n",
           eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs,
@@ -147,12 +160,15 @@ void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
 
   if (mch_pduP) {
     fill_eNB_dlsch_MCH (eNB, mch_pduP->mcs, 1, 0);
+    eNB->dlsch_MCH->harq_ids[proc->frame_tx%2][subframe] = 0;
+    eNB->dlsch_MCH->harq_processes[0]->pdu=(uint8_t *) mch_pduP->payload;
     // Generate PMCH
-    generate_mch (eNB, proc, (uint8_t *) mch_pduP->payload);
+    generate_mch (eNB, proc, NULL/*(uint8_t *) mch_pduP->payload*/);
   } else {
     LOG_D (PHY, "[eNB/RN] Frame %d subframe %d: MCH not generated \n", proc->frame_tx, subframe);
   }
 }
+#endif
 
 void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
diff --git a/openair1/SCHED/prach_procedures.c b/openair1/SCHED/prach_procedures.c
index 3583e222d56af0918577a3d62a8c53c5165bdebe..4f2d05ef5043095abf960e1611db6af9fcee73a8 100644
--- a/openair1/SCHED/prach_procedures.c
+++ b/openair1/SCHED/prach_procedures.c
@@ -150,7 +150,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,
   } else {
     if ((eNB->prach_energy_counter == 100) &&
         (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) {
-      LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
+      LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
             eNB->Mod_id,
             eNB->CC_id,
             frame,
diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c
index 78475e986bbed16d32cabefbf1c45512e7c64d17..0188f5cab52c0b29fcf59f749bf0975fea7b7e3c 100644
--- a/openair1/SCHED/ru_procedures.c
+++ b/openair1/SCHED/ru_procedures.c
@@ -83,42 +83,66 @@ void feptx0(RU_t *ru,
   //LOG_D(PHY,"SFN/SF:RU:TX:%d/%d Generating slot %d\n",ru->proc.frame_tx, ru->proc.subframe_tx,slot);
 
   for (aa=0; aa<ru->nb_tx; aa++) {
-    if (fp->Ncp == EXTENDED) PHY_ofdm_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF],
-                                          (int*)&ru->common.txdata[aa][slot_offset],
-                                          fp->ofdm_symbol_size,
-                                          6,
-                                          fp->nb_prefix_samples,
-                                          CYCLIC_PREFIX);
-    else {
-       /* AssertFatal(ru->generate_dmrs_sync==1 && (fp->frame_type != TDD || ru->is_slave == 1),
-		  "ru->generate_dmrs_sync should not be set, frame_type %d, is_slave %d\n",
-		  fp->frame_type,ru->is_slave);
-       */
-      int num_symb = 7;
-
-      if (subframe_select(fp,subframe) == SF_S) num_symb=fp->dl_symbols_in_S_subframe+1;
-   
-      if (ru->generate_dmrs_sync == 1 && slot == 0 && subframe == 1 && aa==0) {
-        //int32_t dmrs[ru->frame_parms.ofdm_symbol_size*14] __attribute__((aligned(32)));
-        //int32_t *dmrsp[2] ={dmrs,NULL}; //{&dmrs[(3-ru->frame_parms.Ncp)*ru->frame_parms.ofdm_symbol_size],NULL};
-        generate_drs_pusch((PHY_VARS_UE *)NULL,
-                           (UE_rxtx_proc_t*)NULL,
-                           fp,
-                           ru->common.txdataF_BF,
-                           0,
-                           AMP,
-                           0,
-                           0,
-                           fp->N_RB_DL,
-                           aa);
-      } 
-      normal_prefix_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF],
-                        (int*)&ru->common.txdata[aa][slot_offset],
-                        num_symb,
-                        fp);
+    if (fp->Ncp == EXTENDED) {
+      PHY_ofdm_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF],
+                   (int*)&ru->common.txdata[aa][slot_offset],
+                   fp->ofdm_symbol_size,
+                   6,
+                   fp->nb_prefix_samples,
+                   CYCLIC_PREFIX);
+    } else {
+      if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)){
+        if (slot == 0) {//just use one slot chance
+          normal_prefix_mod(&ru->common.txdataF_BF[aa][slot*slot_sizeF],
+                            (int*)&ru->common.txdata[aa][slot_offset],
+                            2,
+                            fp);
+          PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot*slot_sizeF+fp->ofdm_symbol_size*2],
+                       (int*)&ru->common.txdata[aa][slot_offset+((fp->ofdm_symbol_size>>2)*2+fp->ofdm_symbol_size*2)],
+                       fp->ofdm_symbol_size,
+                       10,
+                       fp->ofdm_symbol_size>>2,
+                       CYCLIC_PREFIX);
+          LOG_D(PHY,"SFN/SF:RU:TX:%d/%d Generating slot %d F(%d) t(%d) IS PMCH(%d)\n",
+                    ru->proc.frame_tx,
+                    ru->proc.subframe_tx,
+                    slot,
+                    slot*slot_sizeF+fp->ofdm_symbol_size*2,
+                    slot_offset+((fp->ofdm_symbol_size>>2)*2+fp->ofdm_symbol_size*2),
+                    is_pmch_subframe(ru->proc.frame_tx,subframe,fp));
+        }
+      } else {
+         /* AssertFatal(ru->generate_dmrs_sync==1 && (fp->frame_type != TDD || ru->is_slave == 1),
+                        "ru->generate_dmrs_sync should not be set, frame_type %d, is_slave %d\n",
+                        fp->frame_type,ru->is_slave);
+         */
+	      int num_symb = 7;
+
+	      if (subframe_select(fp,subframe) == SF_S)
+             num_symb = fp->dl_symbols_in_S_subframe+1;
+
+	      if (ru->generate_dmrs_sync == 1 && slot == 0 && subframe == 1 && aa==0) {
+            //int32_t dmrs[ru->frame_parms.ofdm_symbol_size*14] __attribute__((aligned(32)));
+            //int32_t *dmrsp[2] ={dmrs,NULL}; //{&dmrs[(3-ru->frame_parms.Ncp)*ru->frame_parms.ofdm_symbol_size],NULL};
+
+            generate_drs_pusch((PHY_VARS_UE *)NULL,
+                               (UE_rxtx_proc_t*)NULL,
+                               fp,
+                               ru->common.txdataF_BF,
+                               0,
+                               AMP,
+                               0,
+                               0,
+                               fp->N_RB_DL,
+                               aa);
+	      } 
+          normal_prefix_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF],
+                            (int*)&ru->common.txdata[aa][slot_offset],
+                            num_symb,
+                            fp);
+      }
     }
 
-
    /* 
     len = fp->samples_per_tti>>1;
     
@@ -152,10 +176,10 @@ void feptx0(RU_t *ru,
 	tx_offset = (int)slot_offset+i-ru->N_TA_offset/2;
 	if (tx_offset<0)
 	  tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti;
-	
+
 	if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti))
 	  tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti;
-	
+
 	ru->common.txdata[aa][tx_offset] = 0x00000000;
       }
     }*/
@@ -237,7 +261,7 @@ void feptx_ofdm_2thread(RU_t *ru,
       exit_fun( "ERROR pthread_cond_signal" );
       return;
     }
-	//start_meas(&ru->ofdm_mod_wakeup_stats);
+    //start_meas(&ru->ofdm_mod_wakeup_stats);
     
     pthread_mutex_unlock( &proc->mutex_feptx );
   }
@@ -297,16 +321,29 @@ void feptx_ofdm(RU_t *ru,
                      fp->nb_prefix_samples,
                      CYCLIC_PREFIX);
       } else {
+       if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)/*subframe==1*/){
+        normal_prefix_mod(&ru->common.txdataF_BF[aa][0],
+                          dummy_tx_b,
+                          2,
+                          fp);
+        PHY_ofdm_mod(&ru->common.txdataF_BF[aa][fp->ofdm_symbol_size*2],
+                        dummy_tx_b+((fp->ofdm_symbol_size>>2)*2+fp->ofdm_symbol_size*2),
+                     fp->ofdm_symbol_size,
+                     10,
+                     fp->ofdm_symbol_size>>2,
+                    CYCLIC_PREFIX);
+        }else{
         normal_prefix_mod(&ru->common.txdataF_BF[aa][slot_offset_F],
                           dummy_tx_b,
                           7,
                           fp);
-	// if S-subframe generate first slot only
+    // if S-subframe generate first slot only
 	if (subframe_select(fp,subframe) == SF_DL) 
 	  normal_prefix_mod(&ru->common.txdataF_BF[aa][slot_offset_F+slot_sizeF],
 			    dummy_tx_b+(fp->samples_per_tti>>1),
 			    7,
 			    fp);
+	}
       }
 
       // if S-subframe generate first slot only
diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c
index 7248add73be8dfa27d96bb4d8addf2d5502a440f..4b3daef5f13360ed3c5d98f34c38422634580791 100644
--- a/openair1/SCHED_UE/phy_procedures_lte_ue.c
+++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c
@@ -2957,7 +2957,7 @@ void ue_pmch_procedures(PHY_VARS_UE *ue,
 
       dlsch_unscrambling(&ue->frame_parms,1,ue->dlsch_MCH[0],
                          ue->dlsch_MCH[0]->harq_processes[0]->G,
-                         ue->pdsch_vars_MCH[0]->llr[0],0,subframe_rx<<1);
+                         ue->pdsch_vars_MCH[ue->current_thread_id[subframe_rx]][0]->llr[0],0,subframe_rx<<1);
       LOG_D(PHY,"start turbo decode for MCH %d.%d --> nb_rb %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->nb_rb);
       LOG_D(PHY,"start turbo decode for MCH %d.%d --> rb_alloc_even %x \n", frame_rx, subframe_rx, (unsigned int)((intptr_t)ue->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even));
       LOG_D(PHY,"start turbo decode for MCH %d.%d --> Qm %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->Qm);
@@ -2965,7 +2965,7 @@ void ue_pmch_procedures(PHY_VARS_UE *ue,
       LOG_D(PHY,"start turbo decode for MCH %d.%d --> G  %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->G);
       LOG_D(PHY,"start turbo decode for MCH %d.%d --> Kmimo  %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->Kmimo);
       ret = dlsch_decoding(ue,
-                           ue->pdsch_vars_MCH[0]->llr[0],
+                           ue->pdsch_vars_MCH[ue->current_thread_id[subframe_rx]][0]->llr[0],
                            &ue->frame_parms,
                            ue->dlsch_MCH[0],
                            ue->dlsch_MCH[0]->harq_processes[0],
diff --git a/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c b/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
index 5735aa33a5e3f5d4ab729859b7bbb642650b27dd..dfb5578ba603dbacfa26e63117589187c487ec28 100644
--- a/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
+++ b/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
@@ -58,6 +58,8 @@ struct iovec nas_iov_rx = {nl_rx_buf, sizeof(nl_rx_buf)};
 
 int nas_sock_fd[MAX_MOBILES_PER_ENB];
 
+int nas_sock_mbms_fd[8];
+
 struct msghdr nas_msg_tx;
 struct msghdr nas_msg_rx;
 
@@ -92,6 +94,64 @@ static int tun_alloc(char *dev) {
   return fd;
 }
 
+
+int netlink_init_mbms_tun(char *ifprefix, int num_if) {
+  int ret;
+  char ifname[64];
+
+  int i= num_if-1;
+    sprintf(ifname, "oaitun_%.3s%d",ifprefix,i+1);
+    nas_sock_mbms_fd[i] = tun_alloc(ifname);
+
+    if (nas_sock_mbms_fd[i] == -1) {
+      printf("[NETLINK] Error opening socket %s (%d:%s)\n",ifname,errno, strerror(errno));
+      exit(1);
+    }
+
+    printf("[NETLINK]Opened socket %s with fd %d\n",ifname,nas_sock_mbms_fd[i]);
+    ret = fcntl(nas_sock_mbms_fd[i],F_SETFL,O_NONBLOCK);
+
+    if (ret == -1) {
+      printf("[NETLINK] Error fcntl (%d:%s)\n",errno, strerror(errno));
+
+      if (LINK_ENB_PDCP_TO_IP_DRIVER) {
+        exit(1);
+      }
+    }
+
+    memset(&nas_src_addr, 0, sizeof(nas_src_addr));
+    nas_src_addr.nl_family = AF_NETLINK;
+    nas_src_addr.nl_pid = 1;//getpid();  /* self pid */
+    nas_src_addr.nl_groups = 0;  /* not in mcast groups */
+    ret = bind(nas_sock_mbms_fd[i], (struct sockaddr *)&nas_src_addr, sizeof(nas_src_addr));
+    memset(&nas_dest_addr, 0, sizeof(nas_dest_addr));
+    nas_dest_addr.nl_family = AF_NETLINK;
+    nas_dest_addr.nl_pid = 0;   /* For Linux Kernel */
+    nas_dest_addr.nl_groups = 0; /* unicast */
+    // TX PART
+    nas_nlh_tx=(struct nlmsghdr *)malloc(NLMSG_SPACE(NL_MAX_PAYLOAD));
+    memset(nas_nlh_tx, 0, NLMSG_SPACE(NL_MAX_PAYLOAD));
+    /* Fill the netlink message header */
+    nas_nlh_tx->nlmsg_len = NLMSG_SPACE(NL_MAX_PAYLOAD);
+    nas_nlh_tx->nlmsg_pid = 1;//getpid();  /* self pid */
+    nas_nlh_tx->nlmsg_flags = 0;
+    nas_iov_tx.iov_base = (void *)nas_nlh_tx;
+    nas_iov_tx.iov_len = nas_nlh_tx->nlmsg_len;
+    memset(&nas_msg_tx,0,sizeof(nas_msg_tx));
+    nas_msg_tx.msg_name = (void *)&nas_dest_addr;
+    nas_msg_tx.msg_namelen = sizeof(nas_dest_addr);
+    nas_msg_tx.msg_iov = &nas_iov_tx;
+    nas_msg_tx.msg_iovlen = 1;
+    // RX PART
+    memset(&nas_msg_rx,0,sizeof(nas_msg_rx));
+    nas_msg_rx.msg_name = (void *)&nas_src_addr;
+    nas_msg_rx.msg_namelen = sizeof(nas_src_addr);
+    nas_msg_rx.msg_iov = &nas_iov_rx;
+    nas_msg_rx.msg_iovlen = 1;
+
+  return 1;
+}
+
 int netlink_init_tun(char *ifprefix, int num_if) {
   int ret;
   char ifname[64];
diff --git a/openair1/SIMULATION/ETH_TRANSPORT/proto.h b/openair1/SIMULATION/ETH_TRANSPORT/proto.h
index ff677d1580696f2f92a4ef07f38984ad77137968..02f7925d93fbd4a780011a06ffcd7b4830532f34 100644
--- a/openair1/SIMULATION/ETH_TRANSPORT/proto.h
+++ b/openair1/SIMULATION/ETH_TRANSPORT/proto.h
@@ -63,5 +63,6 @@ void clear_eNB_transport_info(uint8_t);
 void clear_UE_transport_info(uint8_t);
 int netlink_init(void);
 int netlink_init_tun(char *ifsuffix, int num_if);
+int netlink_init_mbms_tun(char *ifsuffix, int num_if);
 
 #endif /* EMU_PROTO_H_ */
diff --git a/openair2/COMMON/m2ap_messages_def.h b/openair2/COMMON/m2ap_messages_def.h
new file mode 100644
index 0000000000000000000000000000000000000000..adad70c9cc429458d297b827565b402f83ad6977
--- /dev/null
+++ b/openair2/COMMON/m2ap_messages_def.h
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+
+/* eNB application layer -> M2AP messages */
+/* ITTI LOG messages */
+/* ENCODER */
+MESSAGE_DEF(M2AP_RESET_REQUST_LOG               , MESSAGE_PRIORITY_MED, IttiMsgText                      , m2ap_reset_request_log)
+MESSAGE_DEF(M2AP_RESOURCE_STATUS_RESPONSE_LOG   , MESSAGE_PRIORITY_MED, IttiMsgText                      , m2ap_resource_status_response_log)
+MESSAGE_DEF(M2AP_RESOURCE_STATUS_FAILURE_LOG    , MESSAGE_PRIORITY_MED, IttiMsgText                      , m2ap_resource_status_failure_log)
+
+/* Messages for M2AP logging */
+MESSAGE_DEF(M2AP_SETUP_REQUEST_LOG              , MESSAGE_PRIORITY_MED, IttiMsgText                      , m2ap_setup_request_log)
+
+
+/* eNB application layer -> M2AP messages */
+MESSAGE_DEF(M2AP_REGISTER_ENB_REQ               , MESSAGE_PRIORITY_MED, m2ap_register_enb_req_t          , m2ap_register_enb_req)
+MESSAGE_DEF(M2AP_SUBFRAME_PROCESS               , MESSAGE_PRIORITY_MED, m2ap_subframe_process_t          , m2ap_subframe_process)
+
+/* M2AP -> eNB application layer messages */
+MESSAGE_DEF(M2AP_REGISTER_ENB_CNF               , MESSAGE_PRIORITY_MED, m2ap_register_enb_cnf_t          , m2ap_register_enb_cnf)
+MESSAGE_DEF(M2AP_DEREGISTERED_ENB_IND           , MESSAGE_PRIORITY_MED, m2ap_deregistered_enb_ind_t      , m2ap_deregistered_enb_ind)
+
+/* handover messages M2AP <-> RRC */
+//MESSAGE_DEF(M2AP_HANDOVER_REQ                   , MESSAGE_PRIORITY_MED, m2ap_handover_req_t              , m2ap_handover_req)
+//MESSAGE_DEF(M2AP_HANDOVER_REQ_ACK               , MESSAGE_PRIORITY_MED, m2ap_handover_req_ack_t          , m2ap_handover_req_ack)
+//MESSAGE_DEF(M2AP_HANDOVER_CANCEL                , MESSAGE_PRIORITY_MED, m2ap_handover_cancel_t           , m2ap_handover_cancel)
+
+/* handover messages M2AP <-> S1AP */
+//MESSAGE_DEF(M2AP_UE_CONTEXT_RELEASE             , MESSAGE_PRIORITY_MED, m2ap_ue_context_release_t        , m2ap_ue_context_release)
+
+/* M2AP -> SCTP */
+
+MESSAGE_DEF(M2AP_MCE_SCTP_REQ        , MESSAGE_PRIORITY_MED, m2ap_mce_sctp_req_t       , m2ap_mce_sctp_req)
+//MESSAGE_DEF(M2AP_ENB_SCTP_REQ        , MESSAGE_PRIORITY_MED, m2ap_enb_setup_req_t       , f1ap_enb_setup_req)
+
+/* eNB_DU application layer -> M2AP messages or CU M2AP -> RRC*/
+MESSAGE_DEF(M2AP_SETUP_REQ          , MESSAGE_PRIORITY_MED, m2ap_setup_req_t          , m2ap_setup_req)
+
+MESSAGE_DEF(M2AP_SETUP_RESP          , MESSAGE_PRIORITY_MED, m2ap_setup_resp_t          , m2ap_setup_resp)
+MESSAGE_DEF(M2AP_SETUP_FAILURE          , MESSAGE_PRIORITY_MED, m2ap_setup_failure_t          , m2ap_setup_failure)
+
+MESSAGE_DEF(M2AP_RESET          , MESSAGE_PRIORITY_MED, m2ap_reset_t          , m2ap_reset)
+
+MESSAGE_DEF(M2AP_REGISTER_MCE_REQ               , MESSAGE_PRIORITY_MED, m2ap_register_mce_req_t          , m2ap_register_mce_req)
+
+MESSAGE_DEF(M2AP_MBMS_SCHEDULING_INFORMATION               , MESSAGE_PRIORITY_MED,   m2ap_mbms_scheduling_information_t        , m2ap_mbms_scheduling_information)
+MESSAGE_DEF(M2AP_MBMS_SCHEDULING_INFORMATION_RESP               , MESSAGE_PRIORITY_MED,   m2ap_mbms_scheduling_information_resp_t        , m2ap_mbms_scheduling_information_resp)
+
+MESSAGE_DEF(M2AP_MBMS_SESSION_START_REQ               , MESSAGE_PRIORITY_MED,  m2ap_session_start_req_t         ,m2ap_session_start_req )
+MESSAGE_DEF(M2AP_MBMS_SESSION_START_RESP               , MESSAGE_PRIORITY_MED,  m2ap_session_start_resp_t         ,m2ap_session_start_resp )
+MESSAGE_DEF(M2AP_MBMS_SESSION_START_FAILURE               , MESSAGE_PRIORITY_MED,  m2ap_session_start_failure_t         ,m2ap_session_start_failure )
+
+MESSAGE_DEF(M2AP_MBMS_SESSION_STOP_REQ               , MESSAGE_PRIORITY_MED,  m2ap_session_stop_req_t         ,m2ap_session_stop_req )
+MESSAGE_DEF(M2AP_MBMS_SESSION_STOP_RESP               , MESSAGE_PRIORITY_MED,  m2ap_session_stop_resp_t         ,m2ap_session_stop_resp )
+
+
+MESSAGE_DEF(M2AP_ENB_CONFIGURATION_UPDATE           , MESSAGE_PRIORITY_MED, m2ap_enb_configuration_update_t, m2ap_enb_configuration_update )
+MESSAGE_DEF(M2AP_ENB_CONFIGURATION_UPDATE_ACK           , MESSAGE_PRIORITY_MED, m2ap_enb_configuration_update_ack_t, m2ap_enb_configuration_update_ack )
+MESSAGE_DEF(M2AP_ENB_CONFIGURATION_UPDATE_FAILURE           , MESSAGE_PRIORITY_MED, m2ap_enb_configuration_update_failure_t, m2ap_enb_configuration_update_failure )
+
+MESSAGE_DEF(M2AP_MCE_CONFIGURATION_UPDATE           , MESSAGE_PRIORITY_MED, m2ap_mce_configuration_update_t, m2ap_mce_configuration_update )
+MESSAGE_DEF(M2AP_MCE_CONFIGURATION_UPDATE_ACK           , MESSAGE_PRIORITY_MED, m2ap_mce_configuration_update_ack_t, m2ap_mce_configuration_update_ack )
+MESSAGE_DEF(M2AP_MCE_CONFIGURATION_UPDATE_FAILURE           , MESSAGE_PRIORITY_MED, m2ap_mce_configuration_update_failure_t, m2ap_mce_configuration_update_failure )
+
+
+MESSAGE_DEF(M2AP_ERROR_INDICATION                   , MESSAGE_PRIORITY_MED, m2ap_error_indication_t, m2ap_error_indication )
+MESSAGE_DEF(M2AP_MBMS_SESSION_UPDATE_REQ           , MESSAGE_PRIORITY_MED, m2ap_mbms_session_update_req_t, m2ap_mbms_session_update_req )
+MESSAGE_DEF(M2AP_MBMS_SESSION_UPDATE_RESP           , MESSAGE_PRIORITY_MED, m2ap_mbms_session_update_resp_t, m2ap_mbms_session_update_resp )
+MESSAGE_DEF(M2AP_MBMS_SESSION_UPDATE_FAILURE        , MESSAGE_PRIORITY_MED, m2ap_mbms_session_update_failure_t, m2ap_mbms_session_update_failure )
+MESSAGE_DEF(M2AP_MBMS_SERVICE_COUNTING_REPORT       , MESSAGE_PRIORITY_MED, m2ap_mbms_service_counting_report_t, m2ap_mbms_service_counting_report )
+MESSAGE_DEF(M2AP_MBMS_OVERLOAD_NOTIFICATION         , MESSAGE_PRIORITY_MED, m2ap_mbms_overload_notification_t, m2ap_mbms_overload_notification )
+MESSAGE_DEF(M2AP_MBMS_SERVICE_COUNTING_REQ         , MESSAGE_PRIORITY_MED, m2ap_mbms_service_counting_req_t, m2ap_mbms_service_counting_req ) 
+MESSAGE_DEF(M2AP_MBMS_SERVICE_COUNTING_RESP         , MESSAGE_PRIORITY_MED, m2ap_mbms_service_counting_resp_t, m2ap_mbms_service_counting_resp ) 
+MESSAGE_DEF(M2AP_MBMS_SERVICE_COUNTING_FAILURE      , MESSAGE_PRIORITY_MED, m2ap_mbms_service_counting_failure_t, m2ap_mbms_service_counting_failure )
+
diff --git a/openair2/COMMON/m2ap_messages_types.h b/openair2/COMMON/m2ap_messages_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..501414f296eaabe725f7aa26b77a475387731936
--- /dev/null
+++ b/openair2/COMMON/m2ap_messages_types.h
@@ -0,0 +1,666 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+
+#ifndef M2AP_MESSAGES_TYPES_H_
+#define M2AP_MESSAGES_TYPES_H_
+
+#include "s1ap_messages_types.h"
+#include "LTE_PhysCellId.h"
+
+//-------------------------------------------------------------------------------------------//
+// Defines to access message fields.
+
+#define M2AP_MCE_SCTP_REQ(mSGpTR)		(mSGpTR)->ittiMsg.m2ap_mce_sctp_req
+
+#define M2AP_REGISTER_ENB_REQ(mSGpTR)           (mSGpTR)->ittiMsg.m2ap_register_enb_req
+//#define M2AP_HANDOVER_REQ(mSGpTR)               (mSGpTR)->ittiMsg.m2ap_handover_req
+//#define M2AP_HANDOVER_REQ_ACK(mSGpTR)           (mSGpTR)->ittiMsg.m2ap_handover_req_ack
+#define M2AP_REGISTER_ENB_CNF(mSGpTR)           (mSGpTR)->ittiMsg.m2ap_register_enb_cnf
+#define M2AP_DEREGISTERED_ENB_IND(mSGpTR)       (mSGpTR)->ittiMsg.m2ap_deregistered_enb_ind
+//#define M2AP_UE_CONTEXT_RELEASE(mSGpTR)         (mSGpTR)->ittiMsg.m2ap_ue_context_release
+//#define M2AP_HANDOVER_CANCEL(mSGpTR)            (mSGpTR)->ittiMsg.m2ap_handover_cancel
+
+#define M2AP_ENB_SCTP_REQ(mSGpTR)                   (mSGpTR)->ittiMsg.m2ap_enb_sctp_req
+#define M2AP_SETUP_REQ(mSGpTR)                     (mSGpTR)->ittiMsg.m2ap_setup_req
+#define M2AP_SETUP_RESP(mSGpTR)                    (mSGpTR)->ittiMsg.m2ap_setup_resp
+#define M2AP_SETUP_FAILURE(mSGpTR)                 (mSGpTR)->ittiMsg.m2ap_setup_failure
+
+
+#define M2AP_REGISTER_MCE_REQ(mSGpTR)           (mSGpTR)->ittiMsg.m2ap_register_mce_req
+
+
+
+#define M2AP_MBMS_SCHEDULING_INFORMATION(mSGpTR) 	(mSGpTR)->ittiMsg.m2ap_mbms_scheduling_information
+#define M2AP_MBMS_SCHEDULING_INFORMATION_RESP(mSGpTR) 	(mSGpTR)->ittiMsg.m2ap_mbms_scheduling_information_resp
+#define M2AP_MBMS_SESSION_START_REQ(mSGpTR) 		(mSGpTR)->ittiMsg.m2ap_session_start_req
+#define M2AP_MBMS_SESSION_START_RESP(mSGpTR) 		(mSGpTR)->ittiMsg.m2ap_session_start_resp
+#define M2AP_MBMS_SESSION_START_FAILURE(mSGpTR) 	(mSGpTR)->ittiMsg.m2ap_session_start_failure
+#define M2AP_MBMS_SESSION_STOP_REQ(mSGpTR) 		(mSGpTR)->ittiMsg.m2ap_session_stop_req
+#define M2AP_MBMS_SESSION_STOP_RESP(mSGpTR) 		(mSGpTR)->ittiMsg.m2ap_session_stop_resp
+
+#define M2AP_RESET(mSGpTR)				(mSGpTR)->ittiMsg.m2ap_reset
+#define M2AP_ENB_CONFIGURATION_UPDATE(mSGpTR)		(mSGpTR)->ittiMsg.m2ap_enb_configuration_update
+#define M2AP_ENB_CONFIGURATION_UPDATE_ACK(mSGpTR)	(mSGpTR)->ittiMsg.m2ap_enb_configuration_update_ack
+#define M2AP_ENB_CONFIGURATION_UPDATE_FAILURE(mSGpTR)	(mSGpTR)->ittiMsg.m2ap_enb_configuration_update_failure
+#define M2AP_MCE_CONFIGURATION_UPDATE(mSGpTR)		(mSGpTR)->ittiMsg.m2ap_mce_configuration_update
+#define M2AP_MCE_CONFIGURATION_UPDATE_ACK(mSGpTR)	(mSGpTR)->ittiMsg.m2ap_mce_configuration_update_ack
+#define M2AP_MCE_CONFIGURATION_UPDATE_FAILURE(mSGpTR)	(mSGpTR)->ittiMsg.m2ap_mce_configuration_update_failure
+
+#define M2AP_ERROR_INDICATION(mSGpTR)			(mSGpTR)->ittiMsg.m2ap_error_indication
+#define M2AP_MBMS_SESSION_UPDATE_REQ(mSGpTR)		(mSGpTR)->ittiMsg.m2ap_mbms_session_update_req
+#define M2AP_MBMS_SESSION_UPDATE_RESP(mSGpTR)		(mSGpTR)->ittiMsg.m2ap_mbms_session_update_resp
+#define	M2AP_MBMS_SESSION_UPDATE_FAILURE(mSGpTR)	(mSGpTR)->ittiMsg.m2ap_mbms_session_update_failure
+#define M2AP_MBMS_SERVICE_COUNTING_REPORT(mSGpTR)	(mSGpTR)->ittiMsg.m2ap_mbms_service_counting_report
+#define M2AP_MBMS_OVERLOAD_NOTIFICATION(mSGpTR)		(mSGpTR)->ittiMsg.m2ap_mbms_overload_notification
+#define M2AP_MBMS_SERVICE_COUNTING_REQ(mSGpTR)		(mSGpTR)->ittiMsg.m2ap_mbms_service_counting_req
+#define M2AP_MBMS_SERVICE_COUNTING_RESP(mSGpTR)		(mSGpTR)->ittiMsg.m2ap_mbms_service_counting_resp
+#define M2AP_MBMS_SERVICE_COUNTING_FAILURE(mSGpTR)	(mSGpTR)->ittiMsg.m2ap_mbms_service_counting_failure
+
+#define M2AP_MAX_NB_ENB_IP_ADDRESS 2
+#define M2AP_MAX_NB_MCE_IP_ADDRESS 2
+
+#define M2AP_MAX_NB_CELLS 2
+
+
+
+typedef struct m2ap_net_ip_address_s {
+  unsigned ipv4:1;
+  unsigned ipv6:1;
+  char ipv4_address[16];
+  char ipv6_address[46];
+} m2ap_net_ip_address_t;
+
+typedef struct m2ap_enb_setup_req_s {
+   //
+} m2ap_enb_setup_req_t;
+
+
+typedef struct m2ap_setup_req_s {
+
+  // Midhaul networking parameters
+
+  /* Connexion id used between SCTP/M2AP */
+  uint16_t cnx_id;
+
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* The eNB IP address to bind */
+  m2ap_net_ip_address_t MCE_M2_ip_address;
+  m2ap_net_ip_address_t ENB_M2_ip_address;
+
+  /* Number of SCTP streams used for a mme association */
+  uint16_t sctp_in_streams;
+  uint16_t sctp_out_streams;
+
+  uint16_t default_sctp_stream_id;
+
+  // M2_Setup_Req payload
+  uint64_t eNB_id;
+  char *eNB_name;
+
+  uint64_t GlobalENB_ID;
+  char * ENBname;
+
+  uint16_t num_mbms_available;
+
+  /* M2AP_MBSFN_SynchronisationArea_ID_t */
+  long mbsfn_synchronization_area[M2AP_MAX_NB_CELLS];
+
+  /* eCGI->eCGI.pLMN_Identity */
+  uint16_t plmn_identity[M2AP_MAX_NB_CELLS];
+  /* eCGI->eCGI.eUTRANcellIdentifier */
+  uint16_t eutran_cell_identifier[M2AP_MAX_NB_CELLS];
+
+  struct{
+	  uint16_t mbsfn_sync_area;
+  	  uint16_t mbms_service_area_list[8];
+	  uint16_t num_mbms_service_area_list;
+  }mbms_configuration_data_list[8];
+  uint16_t num_mbms_configuration_data_list;
+
+
+//
+//  /* The type of the cell */
+//  enum cell_type_e cell_type;
+//
+//  /// number of DU cells available
+//  uint16_t num_cells_available; //0< num_cells_available <= 512;
+//
+//  // 
+//  uint16_t num_mbms_available;
+//
+//  // Served Cell Information
+//  /* Tracking area code */
+//  uint16_t tac[M2AP_MAX_NB_CELLS];
+//
+//  /* Mobile Country Codes
+//   * Mobile Network Codes
+//   */
+//  uint16_t mcc[M2AP_MAX_NB_CELLS];//[6];
+//  uint16_t mnc[M2AP_MAX_NB_CELLS];//[6];
+//  uint8_t  mnc_digit_length[M2AP_MAX_NB_CELLS];//[6];
+//
+//  // NR Global Cell Id
+//  uint64_t nr_cellid[M2AP_MAX_NB_CELLS];
+//  // NR Physical Cell Ids
+//  uint16_t nr_pci[M2AP_MAX_NB_CELLS];
+//  // Number of slide support items (max 16, could be increased to as much as 1024)
+//  uint16_t num_ssi[M2AP_MAX_NB_CELLS];//[6];
+//  uint8_t sst[M2AP_MAX_NB_CELLS];//[16][6];
+//  uint8_t sd[M2AP_MAX_NB_CELLS];//[16][6];
+//  // fdd_flag = 1 means FDD, 0 means TDD
+//  int  fdd_flag;
+//
+//  /* eCGI->eCGI.pLMN_Identity */
+//  uint16_t plmn_identity[M2AP_MAX_NB_CELLS];
+//  /* eCGI->eCGI.eUTRANcellIdentifier */
+//  uint16_t eutran_cell_identifier[M2AP_MAX_NB_CELLS];
+// 
+//  /* M2AP_MBSFN_SynchronisationArea_ID_t */
+//  long mbsfn_synchronization_area[M2AP_MAX_NB_CELLS];
+//
+//  uint16_t service_area_id[M2AP_MAX_NB_CELLS][4];
+//
+// union {
+//    struct {
+//      uint32_t ul_nr_arfcn;
+//      uint8_t ul_scs;
+//      uint8_t ul_nrb;
+//
+//      uint32_t dl_nr_arfcn;
+//      uint8_t dl_scs;
+//      uint8_t dl_nrb;
+//
+//      uint32_t sul_active;
+//      uint32_t sul_nr_arfcn;
+//      uint8_t sul_scs;
+//      uint8_t sul_nrb;
+//
+//      uint8_t ul_num_frequency_bands;
+//      uint16_t ul_nr_band[32];
+//      uint8_t ul_num_sul_frequency_bands;
+//      uint16_t ul_nr_sul_band[32];
+//
+//      uint8_t dl_num_frequency_bands;
+//      uint16_t dl_nr_band[32];
+//      uint8_t dl_num_sul_frequency_bands;
+//      uint16_t dl_nr_sul_band[32];
+//    } fdd;
+//    struct {
+//
+//      uint32_t nr_arfcn;
+//      uint8_t scs;
+//      uint8_t nrb;
+//
+//      uint32_t sul_active;
+//      uint32_t sul_nr_arfcn;
+//      uint8_t sul_scs;
+//      uint8_t sul_nrb;
+//
+//      uint8_t num_frequency_bands;
+//      uint16_t nr_band[32];
+//      uint8_t num_sul_frequency_bands;
+//      uint16_t nr_sul_band[32];
+//
+//    } tdd;
+//  } nr_mode_info[M2AP_MAX_NB_CELLS];
+//
+//  char *measurement_timing_information[M2AP_MAX_NB_CELLS];
+//  uint8_t ranac[M2AP_MAX_NB_CELLS];
+//
+//  // System Information
+//  uint8_t *mib[M2AP_MAX_NB_CELLS];
+//  int     mib_length[M2AP_MAX_NB_CELLS];
+//  uint8_t *sib1[M2AP_MAX_NB_CELLS];
+//  int     sib1_length[M2AP_MAX_NB_CELLS];
+
+
+} m2ap_setup_req_t;
+
+
+typedef struct m2ap_setup_resp_s {
+ 
+
+
+  struct {
+    uint8_t mbsfn_area;
+    uint8_t pdcch_length;
+    uint8_t repetition_period;
+    uint8_t offset;
+    uint8_t modification_period;
+    uint8_t subframe_allocation_info;
+    uint8_t mcs;
+  } mcch_config_per_mbsfn[8];
+
+  /* Connexion id used between SCTP/M2AP */
+  uint16_t cnx_id;
+
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* Number of SCTP streams used for a mme association */
+  uint16_t sctp_in_streams;
+  uint16_t sctp_out_streams;
+
+  
+  uint64_t MCE_id;
+  char     *MCE_name;
+
+  uint8_t num_mcch_config_per_mbsfn;
+
+
+//  /// string holding gNB_CU_name
+//  char     *gNB_CU_name;
+//  /// number of DU cells to activate
+//  uint16_t num_cells_to_activate; //0< num_cells_to_activate <= 512;
+//  /// mcc of DU cells
+//  //uint16_t mcc[M2AP_MAX_NB_CELLS];
+  uint16_t mcc;//[M2AP_MAX_NB_CELLS];
+  /// mnc of DU cells
+  //uint16_t mnc[M2AP_MAX_NB_CELLS];
+  uint16_t mnc;//[M2AP_MAX_NB_CELLS];
+  /// mnc digit length of DU cells
+  //uint8_t mnc_digit_length[M2AP_MAX_NB_CELLS];
+  uint8_t mnc_digit_length;//[M2AP_MAX_NB_CELLS];
+  // NR Global Cell Id
+//  uint64_t nr_cellid[M2AP_MAX_NB_CELLS];
+//  /// NRPCI
+//  uint16_t nrpci[M2AP_MAX_NB_CELLS];
+//  /// num SI messages per DU cell
+//  uint8_t num_SI[M2AP_MAX_NB_CELLS];
+//  /// SI message containers (up to 21 messages per cell)
+//  uint8_t *SI_container[M2AP_MAX_NB_CELLS][21];
+//  int      SI_container_length[M2AP_MAX_NB_CELLS][21];
+
+} m2ap_setup_resp_t;
+
+typedef struct m2ap_setup_failure_s {
+  uint16_t cause;
+  uint16_t time_to_wait;
+  uint16_t criticality_diagnostics;
+} m2ap_setup_failure_t;
+
+
+
+// eNB application layer -> M2AP messages
+
+/* M2AP UE CONTEXT RELEASE */
+//typedef struct m2ap_ue_context_release_s {
+//  /* used for M2AP->RRC in source and RRC->M2AP in target */
+//  int rnti;
+//
+//  int source_assoc_id;
+//} m2ap_ue_context_release_t;
+
+//typedef enum {
+//  M2AP_T_RELOC_PREP_TIMEOUT,
+//  M2AP_TX2_RELOC_OVERALL_TIMEOUT
+//} m2ap_handover_cancel_cause_t;
+
+//typedef struct m2ap_handover_cancel_s {
+//  int rnti;
+//  m2ap_handover_cancel_cause_t cause;
+//} m2ap_handover_cancel_t;
+typedef struct m2ap_register_mce_req_s {
+  /* Unique eNB_id to identify the eNB within EPC.
+   * For macro eNB ids this field should be 20 bits long.
+   * For home eNB ids this field should be 28 bits long.
+   */
+  uint32_t MCE_id;
+  /* The type of the cell */
+  enum cell_type_e cell_type;
+
+  /* Optional name for the cell
+   * NOTE: the name can be NULL (i.e no name) and will be cropped to 150
+   * characters.
+   */
+  char *MCE_name;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+
+  /*
+   * CC Params
+   */
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int16_t                 N_RB_DL[MAX_NUM_CCs];
+  lte_frame_type_t        frame_type[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* To be considered for TDD */
+  //uint16_t tdd_EARFCN;
+  //uint16_t tdd_Transmission_Bandwidth;
+
+  /* The local eNB IP address to bind */
+  net_ip_address_t mce_m2_ip_address;
+
+  /* Nb of MME to connect to */
+  uint8_t          nb_m2;
+
+  /* List of target eNB to connect to for M2*/
+  net_ip_address_t target_mce_m2_ip_address[M2AP_MAX_NB_ENB_IP_ADDRESS];
+
+  /* Number of SCTP streams used for associations */
+  uint16_t sctp_in_streams;
+  uint16_t sctp_out_streams;
+
+  /* eNB port for M2C*/
+  uint32_t mce_port_for_M2C;
+
+  /* timers (unit: millisecond) */
+  int t_reloc_prep;
+  int tm2_reloc_overall;
+} m2ap_register_mce_req_t;
+
+
+typedef struct m2ap_register_enb_req_s {
+  /* Unique eNB_id to identify the eNB within EPC.
+   * For macro eNB ids this field should be 20 bits long.
+   * For home eNB ids this field should be 28 bits long.
+   */
+  uint32_t eNB_id;
+  /* The type of the cell */
+  enum cell_type_e cell_type;
+
+  /* Optional name for the cell
+   * NOTE: the name can be NULL (i.e no name) and will be cropped to 150
+   * characters.
+   */
+  char *eNB_name;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+
+  struct{
+	  uint16_t mbsfn_sync_area;
+  	  uint16_t mbms_service_area_list[8];
+	  uint16_t num_mbms_service_area_list;
+  }mbms_configuration_data_list[8];
+  uint16_t num_mbms_configuration_data_list;
+
+
+
+  /*
+   * CC Params
+   */
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int16_t                 N_RB_DL[MAX_NUM_CCs];
+  lte_frame_type_t        frame_type[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* To be considered for TDD */
+  //uint16_t tdd_EARFCN;
+  //uint16_t tdd_Transmission_Bandwidth;
+
+  /* The local eNB IP address to bind */
+  net_ip_address_t enb_m2_ip_address;
+
+  /* Nb of MME to connect to */
+  uint8_t          nb_m2;
+
+  /* List of target eNB to connect to for M2*/
+  net_ip_address_t target_mce_m2_ip_address[M2AP_MAX_NB_ENB_IP_ADDRESS];
+
+  /* Number of SCTP streams used for associations */
+  uint16_t sctp_in_streams;
+  uint16_t sctp_out_streams;
+
+  /* eNB port for M2C*/
+  uint32_t enb_port_for_M2C;
+
+  /* timers (unit: millisecond) */
+  int t_reloc_prep;
+  int tm2_reloc_overall;
+} m2ap_register_enb_req_t;
+
+typedef struct m2ap_subframe_process_s {
+  /* nothing, we simply use the module ID in the header */
+} m2ap_subframe_process_t;
+
+//-------------------------------------------------------------------------------------------//
+// M2AP -> eNB application layer messages
+typedef struct m2ap_register_enb_cnf_s {
+  /* Nb of connected eNBs*/
+  uint8_t          nb_m2;
+} m2ap_register_enb_cnf_t;
+
+typedef struct m2ap_deregistered_enb_ind_s {
+  /* Nb of connected eNBs */
+  uint8_t          nb_m2;
+} m2ap_deregistered_enb_ind_t;
+
+
+typedef struct m2ap_mbms_scheduling_information_s {
+	uint16_t mcch_update_time;
+	struct{
+		uint8_t common_sf_allocation_period;
+		uint8_t mbms_area_id;
+		struct{
+			uint8_t allocated_sf_end;
+                        uint8_t data_mcs;
+                        uint8_t mch_scheduling_period;
+			struct{
+				//struct{
+				uint32_t service_id;
+				uint16_t lcid;
+				uint8_t mcc;
+				uint8_t mnc;
+				uint8_t mnc_length;
+				//}mbms_session_per_pmch[8];
+				//int num_mbms_session_per_pmch;
+			}mbms_session_list[8];
+			int num_mbms_session_list;
+		}pmch_config_list[8];
+		int num_pmch_config_list;
+
+		struct{
+			uint8_t radioframe_allocation_period;
+			uint8_t radioframe_allocation_offset;
+			uint8_t is_four_sf;
+			uint32_t subframe_allocation;
+		}mbms_sf_config_list[8];
+		int num_mbms_sf_config_list;
+		
+	}mbms_area_config_list[8];
+	uint8_t num_mbms_area_config_list;
+
+
+
+
+
+  	uint16_t mcc[M2AP_MAX_NB_CELLS];//[6];
+  	uint16_t mnc[M2AP_MAX_NB_CELLS];//[6];
+  	uint8_t  mnc_digit_length[M2AP_MAX_NB_CELLS];//[6];
+	uint8_t  TMGI[5]; // {4,3,2,1,0};
+	uint8_t is_one_frame;
+ 	uint8_t buf1; //i.e 0x38<<2
+ 	uint8_t buf2; //i.e 0x38<<2
+ 	uint8_t buf3; //i.e 0x38<<2
+	uint16_t common_subframe_allocation_period;
+	
+} m2ap_mbms_scheduling_information_t;
+
+
+typedef struct m2ap_mce_sctp_req_s {
+  	/* The local MCE IP address to bind */
+	net_ip_address_t mce_m2_ip_address;
+
+  	/* eNB port for M2C*/
+  	uint32_t mce_port_for_M2C;
+}m2ap_mce_sctp_req_t;
+
+typedef struct m2ap_mbms_scheduling_information_resp_s {
+} m2ap_mbms_scheduling_information_resp_t;
+typedef struct m2ap_session_start_req_s {
+} m2ap_session_start_req_t;
+typedef struct m2ap_session_start_resp_s {
+} m2ap_session_start_resp_t;
+typedef struct m2ap_session_start_failure_s {
+} m2ap_session_start_failure_t;
+typedef struct m2ap_session_stop_req_s {
+} m2ap_session_stop_req_t;
+typedef struct m2ap_session_stop_resp_s {
+} m2ap_session_stop_resp_t;
+typedef struct m2ap_reset_s {
+} m2ap_reset_t;
+typedef struct m2ap_enb_configuration_update_s {
+} m2ap_enb_configuration_update_t;
+typedef struct m2ap_enb_configuration_update_ack_s {
+} m2ap_enb_configuration_update_ack_t;
+typedef struct m2ap_enb_configuration_update_failure_s {
+} m2ap_enb_configuration_update_failure_t;
+typedef struct m2ap_mce_configuration_update_s {
+} m2ap_mce_configuration_update_t;
+typedef struct m2ap_mce_configuration_update_ack_s {
+} m2ap_mce_configuration_update_ack_t;
+typedef struct m2ap_mce_configuration_update_failure_s {
+} m2ap_mce_configuration_update_failure_t;
+typedef struct m2ap_error_indication_s {
+}m2ap_error_indication_t;
+typedef struct m2ap_mbms_session_update_req_s {
+} m2ap_mbms_session_update_req_t;
+typedef struct m2ap_mbms_session_update_resp_s {
+} m2ap_mbms_session_update_resp_t;
+typedef struct m2ap_mbms_session_update_failure_s {
+} m2ap_mbms_session_update_failure_t;
+typedef struct m2ap_mbms_service_counting_report_s {
+} m2ap_mbms_service_counting_report_t;
+typedef struct m2ap_mbms_overload_notification_s {
+} m2ap_mbms_overload_notification_t;
+typedef struct m2ap_mbms_service_counting_req_s {
+} m2ap_mbms_service_counting_req_t;
+typedef struct m2ap_mbms_service_counting_resp_s {
+} m2ap_mbms_service_counting_resp_t;
+typedef struct m2ap_mbms_service_counting_failure_s {
+} m2ap_mbms_service_counting_failure_t;
+
+
+//-------------------------------------------------------------------------------------------//
+// M2AP <-> RRC
+//typedef struct m2ap_gummei_s {
+//  uint16_t mcc;
+//  uint16_t mnc;
+//  uint8_t  mnc_len;
+//  uint8_t  mme_code;
+//  uint16_t mme_group_id;
+//} m2ap_gummei_t;
+//
+//typedef struct m2ap_lastvisitedcell_info_s {
+//  uint16_t mcc;
+//  uint16_t mnc;
+//  uint8_t  mnc_len;
+//  LTE_PhysCellId_t target_physCellId;
+//  cell_type_t cell_type;
+//  uint64_t time_UE_StayedInCell;
+//}m2ap_lastvisitedcell_info_t;
+//
+//typedef struct m2ap_handover_req_s {
+//  /* used for RRC->M2AP in source eNB */
+//  int rnti;
+//
+//  /* used for M2AP->RRC in target eNB */
+//  int x2_id;
+//
+//  LTE_PhysCellId_t target_physCellId;
+//
+//  m2ap_gummei_t ue_gummei;
+//
+//  /*UE-ContextInformation */
+//
+//  /* MME UE id  */
+//  uint32_t mme_ue_s1ap_id;
+//
+//  security_capabilities_t security_capabilities;
+//
+//  uint8_t      kenb[32]; // keNB or keNB*
+//
+//  /*next_hop_chaining_coun */
+//  long int     kenb_ncc;
+//
+//  /* UE aggregate maximum bitrate */
+//  ambr_t ue_ambr;
+//
+//  uint8_t nb_e_rabs_tobesetup;
+//
+// /* list of e_rab setup-ed by RRC layers */
+//  e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
+//
+//  /* list of e_rab to be setup by RRC layers */
+//  e_rab_t  e_rab_param[S1AP_MAX_E_RAB];
+//
+//  m2ap_lastvisitedcell_info_t lastvisitedcell_info;
+//
+//  uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
+//  int rrc_buffer_size;
+//
+//  int target_assoc_id;
+//} m2ap_handover_req_t;
+//
+//typedef struct m2ap_handover_req_ack_s {
+//  /* used for RRC->M2AP in target and M2AP->RRC in source */
+//  int rnti;
+//
+//  /* used for RRC->M2AP in target */
+//  int x2_id_target;
+//
+//  int source_assoc_id;
+//
+//  uint8_t nb_e_rabs_tobesetup;
+//
+// /* list of e_rab setup-ed by RRC layers */
+//  e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
+//
+//  /* list of e_rab to be setup by RRC layers */
+//  e_rab_t  e_rab_param[S1AP_MAX_E_RAB];
+//
+//  uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
+//  int rrc_buffer_size;
+//
+//  uint32_t mme_ue_s1ap_id;
+//} m2ap_handover_req_ack_t;
+//
+#endif /* M2AP_MESSAGES_TYPES_H_ */
diff --git a/openair2/COMMON/m3ap_messages_def.h b/openair2/COMMON/m3ap_messages_def.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ee725447ddd19067ab22762fd1d555690fdba4e
--- /dev/null
+++ b/openair2/COMMON/m3ap_messages_def.h
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/* eNB application layer -> M3AP messages */
+/* ITTI LOG messages */
+/* ENCODER */
+MESSAGE_DEF(M3AP_RESET_REQUST_LOG               , MESSAGE_PRIORITY_MED, IttiMsgText                      , m3ap_reset_request_log)
+MESSAGE_DEF(M3AP_RESOURCE_STATUS_RESPONSE_LOG   , MESSAGE_PRIORITY_MED, IttiMsgText                      , m3ap_resource_status_response_log)
+MESSAGE_DEF(M3AP_RESOURCE_STATUS_FAILURE_LOG    , MESSAGE_PRIORITY_MED, IttiMsgText                      , m3ap_resource_status_failure_log)
+
+/* Messages for M3AP logging */
+MESSAGE_DEF(M3AP_SETUP_REQUEST_LOG              , MESSAGE_PRIORITY_MED, IttiMsgText                      , m3ap_setup_request_log)
+
+
+/* eNB application layer -> M3AP messages */
+MESSAGE_DEF(M3AP_REGISTER_MCE_REQ               , MESSAGE_PRIORITY_MED, m3ap_register_mce_req_t          , m3ap_register_mce_req)
+MESSAGE_DEF(M3AP_SUBFRAME_PROCESS               , MESSAGE_PRIORITY_MED, m3ap_subframe_process_t          , m3ap_subframe_process)
+
+/* M3AP -> eNB application layer messages */
+MESSAGE_DEF(M3AP_REGISTER_MCE_CNF               , MESSAGE_PRIORITY_MED, m3ap_register_mce_cnf_t          , m3ap_register_mce_cnf)
+MESSAGE_DEF(M3AP_DEREGISTERED_MCE_IND           , MESSAGE_PRIORITY_MED, m3ap_deregistered_mce_ind_t      , m3ap_deregistered_mce_ind)
+
+/* handover messages M3AP <-> RRC */
+//MESSAGE_DEF(M3AP_HANDOVER_REQ                   , MESSAGE_PRIORITY_MED, m3ap_handover_req_t              , m3ap_handover_req)
+//MESSAGE_DEF(M3AP_HANDOVER_REQ_ACK               , MESSAGE_PRIORITY_MED, m3ap_handover_req_ack_t          , m3ap_handover_req_ack)
+//MESSAGE_DEF(M3AP_HANDOVER_CANCEL                , MESSAGE_PRIORITY_MED, m3ap_handover_cancel_t           , m3ap_handover_cancel)
+
+/* handover messages M3AP <-> S1AP */
+//MESSAGE_DEF(M3AP_UE_CONTEXT_RELEASE             , MESSAGE_PRIORITY_MED, m3ap_ue_context_release_t        , m3ap_ue_context_release)
+
+MESSAGE_DEF(M3AP_MME_SCTP_REQ        , MESSAGE_PRIORITY_MED, m3ap_mme_sctp_req_t       , m3ap_mme_sctp_req)
+
+
+MESSAGE_DEF(M3AP_MBMS_SESSION_START_REQ      , MESSAGE_PRIORITY_MED  ,m3ap_session_start_req_t         ,m3ap_session_start_req)
+MESSAGE_DEF(M3AP_MBMS_SESSION_START_RESP     , MESSAGE_PRIORITY_MED  ,m3ap_session_start_resp_t        ,m3ap_session_start_resp)
+MESSAGE_DEF(M3AP_MBMS_SESSION_START_FAILURE  , MESSAGE_PRIORITY_MED  ,m3ap_session_start_failure_t     ,m3ap_session_start_failure)
+MESSAGE_DEF(M3AP_MBMS_SESSION_STOP_REQ       , MESSAGE_PRIORITY_MED  ,m3ap_session_stop_req_t          ,m3ap_session_stop_req)
+MESSAGE_DEF(M3AP_MBMS_SESSION_STOP_RESP      , MESSAGE_PRIORITY_MED  ,m3ap_session_stop_resp_t         ,m3ap_session_stop_resp)
+MESSAGE_DEF(M3AP_MBMS_SESSION_STOP_FAILURE   , MESSAGE_PRIORITY_MED  ,m3ap_session_stop_failure_t      ,m3ap_session_stop_failure)
+MESSAGE_DEF(M3AP_ERROR_INDICATION            , MESSAGE_PRIORITY_MED  ,m3ap_error_indication_t               ,m3ap_error_indication)
+MESSAGE_DEF(M3AP_RESET          	     , MESSAGE_PRIORITY_MED  ,m3ap_reset_t                          ,m3ap_reset)
+MESSAGE_DEF(M3AP_RESET_ACK                   , MESSAGE_PRIORITY_MED  ,m3ap_reset_ack_t                      ,m3ap_reset_ack)
+MESSAGE_DEF(M3AP_MBMS_SESSION_UPDATE_REQ     , MESSAGE_PRIORITY_MED  ,m3ap_mbms_session_update_req_t        ,m3ap_mbms_session_update_req)
+MESSAGE_DEF(M3AP_MBMS_SESSION_UPDATE_RESP    , MESSAGE_PRIORITY_MED  ,m3ap_mbms_session_update_resp_t       ,m3ap_mbms_session_update_resp)
+MESSAGE_DEF(M3AP_MBMS_SESSION_UPDATE_FAILURE , MESSAGE_PRIORITY_MED  ,m3ap_mbms_session_update_failure_t    ,m3ap_mbms_session_update_failure)
+MESSAGE_DEF(M3AP_SETUP_REQ		     , MESSAGE_PRIORITY_MED  ,m3ap_setup_req_t                      ,m3ap_setup_req)
+MESSAGE_DEF(M3AP_SETUP_RESP	             , MESSAGE_PRIORITY_MED  ,m3ap_setup_resp_t                     ,m3ap_setup_resp)
+MESSAGE_DEF(M3AP_SETUP_FAILURE		     , MESSAGE_PRIORITY_MED  ,m3ap_setup_failure_t                  ,m3ap_setup_failure)
+MESSAGE_DEF(M3AP_MCE_CONFIGURATION_UPDATE        , MESSAGE_PRIORITY_MED  ,m3ap_mce_configuration_update_t           ,m3ap_mce_configuration_update)
+MESSAGE_DEF(M3AP_MCE_CONFIGURATION_UPDATE_ACK    , MESSAGE_PRIORITY_MED  ,m3ap_mce_configuration_update_ack_t       ,m3ap_mce_configuration_update_ack)
+MESSAGE_DEF(M3AP_MCE_CONFIGURATION_UPDATE_FAILURE, MESSAGE_PRIORITY_MED  ,m3ap_mce_configuration_update_failure_t   ,m3ap_mce_configuration_update_failure)
+
+
diff --git a/openair2/COMMON/m3ap_messages_types.h b/openair2/COMMON/m3ap_messages_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..21e24dd449c1403386c9af38b93f8e763c875d50
--- /dev/null
+++ b/openair2/COMMON/m3ap_messages_types.h
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef M3AP_MESSAGES_TYPES_H_
+#define M3AP_MESSAGES_TYPES_H_
+
+#include "s1ap_messages_types.h"
+#include "LTE_PhysCellId.h"
+
+//-------------------------------------------------------------------------------------------//
+// Defines to access message fields.
+#define M3AP_MME_SCTP_REQ(mSGpTR)		(mSGpTR)->ittiMsg.m3ap_mme_sctp_req
+
+#define M3AP_REGISTER_MCE_REQ(mSGpTR)           (mSGpTR)->ittiMsg.m3ap_register_mce_req
+//#define M3AP_HANDOVER_REQ(mSGpTR)               (mSGpTR)->ittiMsg.m3ap_handover_req
+//#define M3AP_HANDOVER_REQ_ACK(mSGpTR)           (mSGpTR)->ittiMsg.m3ap_handover_req_ack
+#define M3AP_REGISTER_MCE_CNF(mSGpTR)           (mSGpTR)->ittiMsg.m3ap_register_mce_cnf
+#define M3AP_DEREGISTERED_MCE_IND(mSGpTR)       (mSGpTR)->ittiMsg.m3ap_deregistered_mce_ind
+//#define M3AP_UE_CONTEXT_RELEASE(mSGpTR)         (mSGpTR)->ittiMsg.m3ap_ue_context_release
+//#define M3AP_HANDOVER_CANCEL(mSGpTR)            (mSGpTR)->ittiMsg.m3ap_handover_cancel
+
+
+#define M3AP_MBMS_SESSION_START_REQ(mSGpTR)            	(mSGpTR)->ittiMsg.m3ap_session_start_req
+#define M3AP_MBMS_SESSION_START_RESP(mSGpTR)            (mSGpTR)->ittiMsg.m3ap_session_start_resp
+#define M3AP_MBMS_SESSION_START_FAILURE(mSGpTR)         (mSGpTR)->ittiMsg.m3ap_session_start_failure
+#define M3AP_MBMS_SESSION_STOP_REQ(mSGpTR)            	(mSGpTR)->ittiMsg.m3ap_session_stop_req
+#define M3AP_MBMS_SESSION_STOP_RESP(mSGpTR)           	(mSGpTR)->ittiMsg.m3ap_session_stop_resp
+#define M3AP_MBMS_SESSION_STOP_FAILURE(mSGpTR)          (mSGpTR)->ittiMsg.m3ap_session_stop_failure
+#define M3AP_ERROR_INDICATION(mSGpTR)          		(mSGpTR)->ittiMsg.m3ap_error_indication
+#define M3AP_RESET(mSGpTR)          			(mSGpTR)->ittiMsg.m3ap_reset
+#define M3AP_RESET_ACK(mSGpTR)          		(mSGpTR)->ittiMsg.m3ap_reset_ack
+#define M3AP_MBMS_SESSION_UPDATE_REQ(mSGpTR)            (mSGpTR)->ittiMsg.m3ap_mbms_session_update_req
+#define M3AP_MBMS_SESSION_UPDATE_RESP(mSGpTR)           (mSGpTR)->ittiMsg.m3ap_mbms_session_update_resp
+#define M3AP_MBMS_SESSION_UPDATE_FAILURE(mSGpTR)        (mSGpTR)->ittiMsg.m3ap_mbms_session_update_failure
+#define M3AP_SETUP_REQ(mSGpTR)				(mSGpTR)->ittiMsg.m3ap_setup_req
+#define M3AP_SETUP_RESP(mSGpTR)				(mSGpTR)->ittiMsg.m3ap_setup_resp
+#define M3AP_SETUP_FAILURE(mSGpTR)			(mSGpTR)->ittiMsg.m3ap_setup_failure
+#define M3AP_MCE_CONFIGURATION_UPDATE(mSGpTR)		(mSGpTR)->ittiMsg.m3ap_mce_configuration_update
+#define M3AP_MCE_CONFIGURATION_UPDATE_ACK(mSGpTR)	(mSGpTR)->ittiMsg.m3ap_mce_configuration_update_ack
+#define M3AP_MCE_CONFIGURATION_UPDATE_FAILURE(mSGpTR)	(mSGpTR)->ittiMsg.m3ap_mce_configuration_update_failure
+
+
+#define M3AP_MAX_NB_MCE_IP_ADDRESS 2
+
+#define M3AP_MAX_NB_MME_IP_ADDRESS 2
+
+
+typedef struct m3ap_net_ip_address_s {
+  unsigned ipv4:1;
+  unsigned ipv6:1;
+  char ipv4_address[16];
+  char ipv6_address[46];
+} m3ap_net_ip_address_t;
+
+// eNB application layer -> M3AP messages
+
+/* M3AP UE CONTEXT RELEASE */
+//typedef struct m3ap_ue_context_release_s {
+//  /* used for M3AP->RRC in source and RRC->M3AP in target */
+//  int rnti;
+//
+//  int source_assoc_id;
+//} m3ap_ue_context_release_t;
+
+//typedef enum {
+//  M3AP_T_RELOC_PREP_TIMEOUT,
+//  M3AP_TX2_RELOC_OVERALL_TIMEOUT
+//} m3ap_handover_cancel_cause_t;
+
+//typedef struct m3ap_handover_cancel_s {
+//  int rnti;
+//  m3ap_handover_cancel_cause_t cause;
+//} m3ap_handover_cancel_t;
+
+typedef struct m3ap_register_mce_req_s {
+  /* Unique eNB_id to identify the eNB within EPC.
+   * For macro eNB ids this field should be 20 bits long.
+   * For home eNB ids this field should be 28 bits long.
+   */
+  uint32_t MCE_id;
+  /* The type of the cell */
+  enum cell_type_e cell_type;
+
+  /* Optional name for the cell
+   * NOTE: the name can be NULL (i.e no name) and will be cropped to 150
+   * characters.
+   */
+  char *MCE_name;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+
+  /*
+   * CC Params
+   */
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int16_t                 N_RB_DL[MAX_NUM_CCs];
+  lte_frame_type_t        frame_type[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* To be considered for TDD */
+  //uint16_t tdd_EARFCN;
+  //uint16_t tdd_Transmission_Bandwidth;
+
+  /* The local eNB IP address to bind */
+  net_ip_address_t mme_m3_ip_address;
+
+  /* Nb of MME to connect to */
+  uint8_t          nb_m3;
+
+  /* List of target eNB to connect to for M3*/
+  net_ip_address_t target_mme_m3_ip_address[M3AP_MAX_NB_MCE_IP_ADDRESS];
+
+  /* Number of SCTP streams used for associations */
+  uint16_t sctp_in_streams;
+  uint16_t sctp_out_streams;
+
+  /* eNB port for M3C*/
+  uint32_t mme_port_for_M3C;
+
+  /* timers (unit: millisecond) */
+  int t_reloc_prep;
+  int tm3_reloc_overall;
+
+  /* Nb of MME to connect to */
+  uint8_t          nb_mme;
+  /* List of MME to connect to */
+  net_ip_address_t mme_ip_address[M3AP_MAX_NB_MME_IP_ADDRESS];
+} m3ap_register_mce_req_t;
+
+typedef struct m3ap_subframe_process_s {
+  /* nothing, we simply use the module ID in the header */
+} m3ap_subframe_process_t;
+
+//-------------------------------------------------------------------------------------------//
+// M3AP -> eNB application layer messages
+typedef struct m3ap_register_mce_cnf_s {
+  /* Nb of connected eNBs*/
+  uint8_t          nb_mme;
+} m3ap_register_mce_cnf_t;
+
+typedef struct m3ap_deregistered_mce_ind_s {
+  /* Nb of connected eNBs */
+  uint8_t          nb_mme;
+} m3ap_deregistered_mce_ind_t;
+
+//-------------------------------------------------------------------------------------------//
+// M3AP <-> RRC
+//typedef struct m3ap_gummei_s {
+//  uint16_t mcc;
+//  uint16_t mnc;
+//  uint8_t  mnc_len;
+//  uint8_t  mme_code;
+//  uint16_t mme_group_id;
+//} m3ap_gummei_t;
+//
+//typedef struct m3ap_lastvisitedcell_info_s {
+//  uint16_t mcc;
+//  uint16_t mnc;
+//  uint8_t  mnc_len;
+//  LTE_PhysCellId_t target_physCellId;
+//  cell_type_t cell_type;
+//  uint64_t time_UE_StayedInCell;
+//}m3ap_lastvisitedcell_info_t;
+//
+//typedef struct m3ap_handover_req_s {
+//  /* used for RRC->M3AP in source eNB */
+//  int rnti;
+//
+//  /* used for M3AP->RRC in target eNB */
+//  int x2_id;
+//
+//  LTE_PhysCellId_t target_physCellId;
+//
+//  m3ap_gummei_t ue_gummei;
+//
+//  /*UE-ContextInformation */
+//
+//  /* MME UE id  */
+//  uint32_t mme_ue_s1ap_id;
+//
+//  security_capabilities_t security_capabilities;
+//
+//  uint8_t      kenb[32]; // keNB or keNB*
+//
+//  /*next_hop_chaining_coun */
+//  long int     kenb_ncc;
+//
+//  /* UE aggregate maximum bitrate */
+//  ambr_t ue_ambr;
+//
+//  uint8_t nb_e_rabs_tobesetup;
+//
+// /* list of e_rab setup-ed by RRC layers */
+//  e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
+//
+//  /* list of e_rab to be setup by RRC layers */
+//  e_rab_t  e_rab_param[S1AP_MAX_E_RAB];
+//
+//  m3ap_lastvisitedcell_info_t lastvisitedcell_info;
+//
+//  uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
+//  int rrc_buffer_size;
+//
+//  int target_assoc_id;
+//} m3ap_handover_req_t;
+//
+//typedef struct m3ap_handover_req_ack_s {
+//  /* used for RRC->M3AP in target and M3AP->RRC in source */
+//  int rnti;
+//
+//  /* used for RRC->M3AP in target */
+//  int x2_id_target;
+//
+//  int source_assoc_id;
+//
+//  uint8_t nb_e_rabs_tobesetup;
+//
+// /* list of e_rab setup-ed by RRC layers */
+//  e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
+//
+//  /* list of e_rab to be setup by RRC layers */
+//  e_rab_t  e_rab_param[S1AP_MAX_E_RAB];
+//
+//  uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
+//  int rrc_buffer_size;
+//
+//  uint32_t mme_ue_s1ap_id;
+//} m3ap_handover_req_ack_t;
+//
+
+typedef struct m3ap_mme_sctp_req_s {
+  	/* the local mce ip address to bind */
+	net_ip_address_t mme_m3_ip_address;
+
+  	/* enb port for m2c*/
+  	uint32_t mme_port_for_M3C;
+}m3ap_mme_sctp_req_t;
+
+
+
+typedef struct m3ap_session_start_req_s{
+}m3ap_session_start_req_t;
+typedef struct m3ap_session_start_resp_s{
+}m3ap_session_start_resp_t;
+typedef struct m3ap_session_start_failure_s{
+}m3ap_session_start_failure_t;
+typedef struct m3ap_session_stop_req_s{
+}m3ap_session_stop_req_t;
+typedef struct m3ap_session_stop_resp_s{
+}m3ap_session_stop_resp_t;
+typedef struct m3ap_session_stop_failure_s{
+}m3ap_session_stop_failure_t;
+typedef struct m3ap_error_indication_s{
+}m3ap_error_indication_t;
+typedef struct m3ap_reset_s{
+}m3ap_reset_t;
+typedef struct m3ap_reset_ack_s{
+}m3ap_reset_ack_t;
+typedef struct m3ap_mbms_session_update_req_s{
+}m3ap_mbms_session_update_req_t;
+typedef struct m3ap_mbms_session_update_resp_s{
+}m3ap_mbms_session_update_resp_t;
+typedef struct m3ap_mbms_session_update_failure_s{
+}m3ap_mbms_session_update_failure_t;
+typedef struct m3ap_setup_req_s{
+  /* Connexion id used between SCTP/M3AP */
+  uint16_t cnx_id;
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* Number of SCTP streams used for a mme association */
+  uint16_t sctp_in_streams;
+  uint16_t sctp_out_streams;
+
+  uint16_t default_sctp_stream_id;
+}m3ap_setup_req_t;
+typedef struct m3ap_setup_resp_s{
+}m3ap_setup_resp_t;
+typedef struct m3ap_setup_failure_s{
+}m3ap_setup_failure_t;
+typedef struct m3ap_mce_configuration_update_s{
+}m3ap_mce_configuration_update_t;
+typedef struct m3ap_mce_configuration_update_ack_s{
+}m3ap_mce_configuration_update_ack_t;
+typedef struct m3ap_mce_configuration_update_failure_s{
+}m3ap_mce_configuration_update_failure_t;
+
+
+
+
+
+
+
+
+
+
+
+
+#endif /* M3AP_MESSAGES_TYPES_H_ */
diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h
index f69186e4b86a60f7b1f8ba814801988faa00e1d0..09b3f2aab48f19673ed6eb85223ad2c99788e66d 100644
--- a/openair2/COMMON/mac_messages_def.h
+++ b/openair2/COMMON/mac_messages_def.h
@@ -45,3 +45,6 @@ MESSAGE_DEF(RRC_MAC_MCCH_DATA_REQ,      MESSAGE_PRIORITY_MED_PLUS, RrcMacMcchDat
 MESSAGE_DEF(RRC_MAC_MCCH_DATA_IND,      MESSAGE_PRIORITY_MED_PLUS, RrcMacMcchDataInd,           rrc_mac_mcch_data_ind)
 
 MESSAGE_DEF(RRC_MAC_PCCH_DATA_REQ,      MESSAGE_PRIORITY_MED_PLUS, RrcMacPcchDataReq,           rrc_mac_pcch_data_req)
+
+/* RRC configures DRX context (MAC timers) of a UE */
+MESSAGE_DEF(RRC_MAC_DRX_CONFIG_REQ, MESSAGE_PRIORITY_MED, rrc_mac_drx_config_req_t, rrc_mac_drx_config_req)
\ No newline at end of file
diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h
index 3bbea66d0d649d7b2463ede95787e99c44c7d78b..e227296d05d9c6d5352f855be00cb39a62ffabf6 100644
--- a/openair2/COMMON/mac_messages_types.h
+++ b/openair2/COMMON/mac_messages_types.h
@@ -29,6 +29,8 @@
 #ifndef MAC_MESSAGES_TYPES_H_
 #define MAC_MESSAGES_TYPES_H_
 
+#include <LTE_DRX-Config.h>
+
 //-------------------------------------------------------------------------------------------//
 // Defines to access message fields.
 #define RRC_MAC_IN_SYNC_IND(mSGpTR)             (mSGpTR)->ittiMsg.rrc_mac_in_sync_ind
@@ -48,6 +50,8 @@
 #define RRC_MAC_MCCH_DATA_IND(mSGpTR)           (mSGpTR)->ittiMsg.rrc_mac_mcch_data_ind
 #define RRC_MAC_PCCH_DATA_REQ(mSGpTR)           (mSGpTR)->ittiMsg.rrc_mac_pcch_data_req
 
+#define RRC_MAC_DRX_CONFIG_REQ(mSGpTR)           (mSGpTR)->ittiMsg.rrc_mac_drx_config_req
+
 // Some constants from "LAYER2/MAC/defs.h"
 #define BCCH_SDU_SIZE                           (512)
 #define BCCH_SDU_MBMS_SIZE                      (512)
@@ -145,4 +149,14 @@ typedef struct RrcMacPcchDataReq_s {
   uint8_t   sdu[PCCH_SDU_SIZE];
   uint8_t   enb_index;
 } RrcMacPcchDataReq;
+
+/* RRC configures DRX context (MAC timers) of a UE */
+typedef struct rrc_mac_drx_config_req_s {
+  /* UE RNTI to configure */
+  rnti_t rnti;
+
+  /* DRX configuration from MacMainConfig to configure UE's local timers */
+  LTE_DRX_Config_t * drx_Configuration;
+} rrc_mac_drx_config_req_t;
+
 #endif /* MAC_MESSAGES_TYPES_H_ */
diff --git a/openair2/COMMON/messages_def.h b/openair2/COMMON/messages_def.h
index b0219db50a284739c41f86c49b40523baddc62af..0d302cfea0493f4f2514968b301089a82cd7aee2 100644
--- a/openair2/COMMON/messages_def.h
+++ b/openair2/COMMON/messages_def.h
@@ -36,6 +36,8 @@
 #include "s1ap_messages_def.h"
 #include "f1ap_messages_def.h"
 #include "x2ap_messages_def.h"
+#include "m2ap_messages_def.h"
+#include "m3ap_messages_def.h"
 #include "sctp_messages_def.h"
 #include "udp_messages_def.h"
 #include "gtpv1_u_messages_def.h"
diff --git a/openair2/COMMON/platform_constants.h b/openair2/COMMON/platform_constants.h
index 4c4348dce9c217cf14a0c0d0137693e3996f5510..581ff39527b33191f9f77593d115b7e54a4c8d34 100644
--- a/openair2/COMMON/platform_constants.h
+++ b/openair2/COMMON/platform_constants.h
@@ -115,7 +115,8 @@
 #define NB_RAB_MAX     LTE_maxDRB       /* was 8, now 11 */
 #define RAB_SHIFT1     9
 #define RAB_SHIFT2     3
-#define RAB_OFFSET     0x0007
+//#define RAB_OFFSET     0x0007
+#define RAB_OFFSET     0x000F
 #define RAB_OFFSET1    0x7E00
 #define RAB_OFFSET2    0x01F8
 #define DIR_OFFSET     0x8000
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index 8f85d5e770b21af66562f82cbf79370d000d5027..6c62d59d6d54a1af58691846215d27dbfe257644 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -194,6 +194,7 @@ typedef struct RrcConfigurationReq_s {
   int16_t                 N_RB_DL[MAX_NUM_CCs];// for testing, change later
   int                     nb_antenna_ports[MAX_NUM_CCs];
   int                     eMBMS_configured;
+  int                     eMBMS_M2_configured;
   int                     eMTC_configured;
   int                     SL_configured;
 
diff --git a/openair2/COMMON/tasks_def.h b/openair2/COMMON/tasks_def.h
index 4703efc27e0b3d0f4c4085200d4a68db2321481d..0fb1bd6b30477a22099ed1659802f862efa4d99f 100644
--- a/openair2/COMMON/tasks_def.h
+++ b/openair2/COMMON/tasks_def.h
@@ -50,6 +50,15 @@ TASK_DEF(TASK_GTPV1_U,  TASK_PRIORITY_MED,          1000)
 TASK_DEF(TASK_S1AP,     TASK_PRIORITY_MED,          200)
 TASK_DEF(TASK_CU_F1,     TASK_PRIORITY_MED,          200)
 TASK_DEF(TASK_DU_F1,     TASK_PRIORITY_MED,          200)
+///   M3ap task, acts as both source and target
+TASK_DEF(TASK_M3AP,     TASK_PRIORITY_MED,          200)
+///   M3ap task, acts as both source and target
+TASK_DEF(TASK_M3AP_MME,     TASK_PRIORITY_MED,          200)
+///   M3ap task, acts as both source and target
+TASK_DEF(TASK_M3AP_MCE,     TASK_PRIORITY_MED,          200)
+///   M2ap task, acts as both source and target
+TASK_DEF(TASK_M2AP_MCE,     TASK_PRIORITY_MED,          200)
+TASK_DEF(TASK_M2AP_ENB,     TASK_PRIORITY_MED,          200)
 ///   X2ap task, acts as both source and target
 TASK_DEF(TASK_X2AP,     TASK_PRIORITY_MED,          200)
 ///   Sctp task (Used by both S1AP and X2AP)
diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c
index 2d5134e0d9e3dc35360a774e779ef1545aa82a1d..0e1c7e64bc8025ad5358f952ed2800c71ebbac32 100644
--- a/openair2/ENB_APP/enb_app.c
+++ b/openair2/ENB_APP/enb_app.c
@@ -46,6 +46,8 @@
 
 #   include "x2ap_eNB.h"
 #   include "x2ap_messages_types.h"
+#   include "m2ap_eNB.h"
+#   include "m2ap_messages_types.h"
 #   define X2AP_ENB_REGISTER_RETRY_DELAY   10
 
 #include "openair1/PHY/INIT/phy_init.h"
@@ -56,6 +58,90 @@ extern RAN_CONTEXT_t RC;
 
 #   define ENB_REGISTER_RETRY_DELAY 10
 
+#include "targets/RT/USER/lte-softmodem.h"
+
+
+/*************************** ENB M2AP **************************/
+//static uint32_t eNB_app_register_MBMS_STA(ngran_node_t node_type,uint32_t enb_id_start, uint32_t enb_id_end) {
+//  uint32_t         enb_id;
+//  //MessageDef      *msg_p;
+//  uint32_t         register_enb_pending = 0;
+//
+//  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
+//    {
+//
+//        //msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ);
+//        //RCconfig_S1(msg_p, enb_id);
+//
+//        if (enb_id == 0) RCconfig_gtpu();
+//
+//        //LOG_I(ENB_APP,"default drx %d\n",((S1AP_REGISTER_ENB_REQ(msg_p)).default_drx));
+//
+//        //LOG_I(ENB_APP,"[eNB %d] eNB_app_register via S1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
+//        //itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+//
+//      register_enb_pending++;
+//    }
+//  }
+//
+//  return register_enb_pending;
+//}
+//*****end M2AP ****/
+
+static uint32_t eNB_app_register_m2(uint32_t enb_id_start, uint32_t enb_id_end) {
+  uint32_t         enb_id;
+  MessageDef      *msg_p;
+  uint32_t         register_enb_m2_pending = 0;
+
+//  msg_p = itti_alloc_new_message (TASK_ENB_APP,MESSAGE_TEST );
+//  itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+
+  LOG_D(ENB_APP,"Register ...\n");
+
+  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
+    {
+      msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_REGISTER_ENB_REQ);
+      RCconfig_M2(msg_p, enb_id);
+      itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+      register_enb_m2_pending++;
+    }
+  }
+
+  return register_enb_m2_pending;
+}
+
+
+/***************************  M2AP ENB handle **********************************/
+static uint32_t eNB_app_handle_m2ap_mbms_scheduling_information(instance_t instance){
+        //uint32_t         mce_id=0;
+        MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SCHEDULING_INFORMATION_RESP);
+        itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+        return 0;
+}
+static uint32_t eNB_app_handle_m2ap_mbms_session_start_req(instance_t instance){
+        //uint32_t         mce_id=0;
+        MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_START_RESP);
+        itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+        return 0;
+}
+static uint32_t eNB_app_handle_m2ap_mbms_session_stop_req(instance_t instance){
+        //uint32_t         mce_id=0;
+        MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_STOP_RESP);
+        itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+        return 0;
+}
+static uint32_t eNB_app_handle_m2ap_mbms_session_update_req(instance_t instance){
+        //uint32_t         mce_id=0;
+        MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_UPDATE_RESP);
+        itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+        return 0;
+}
+
+//// end M2AP ENB handle **********************************/
 
 /*------------------------------------------------------------------------------*/
 
@@ -126,6 +212,9 @@ void *eNB_app_task(void *args_p) {
   uint32_t                        x2_register_enb_pending = 0;
   uint32_t                        x2_registered_enb = 0;
   long                            x2_enb_register_retry_timer_id;
+  uint32_t                        m2_register_enb_pending = 0;
+  uint32_t                        m2_registered_enb = 0;
+  long                            m2_enb_register_retry_timer_id;
   MessageDef                     *msg_p           = NULL;
   instance_t                      instance;
   int                             result;
@@ -144,6 +233,22 @@ void *eNB_app_task(void *args_p) {
     x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
   }
 
+  /* Try to register each eNB with MCE each other */
+  if (is_m2ap_eNB_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) {
+    //eNB_app_register_MBMS_STA(RC.rrc[0]->node_type, enb_id_start, enb_id_end);
+    //m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end);
+
+    if (timer_setup (5, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+                               NULL, &m2_enb_register_retry_timer_id) < 0) {
+                //LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");
+                //sleep(ENB_REGISTER_RETRY_DELAY);
+                /* Restart the registration process */
+                //registered_enb = 0;
+                //register_enb_pending = eNB_app_register (RC.rrc[0]->node_type,enb_id_start, enb_id_end);
+    }
+
+  }
+
   do {
     // Wait for a message
     itti_receive_msg (TASK_ENB_APP, &msg_p);
@@ -272,6 +377,12 @@ void *eNB_app_task(void *args_p) {
       }
         } /* if (EPC_MODE_ENABLED) */
 
+      if(TIMER_HAS_EXPIRED (msg_p).timer_id == m2_enb_register_retry_timer_id) {
+
+               LOG_I(ENB_APP, " Received %s: timer_id %ld M2 register\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
+               m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end);
+	}
+
       break;
 
     case X2AP_DEREGISTERED_ENB_IND:
@@ -316,6 +427,123 @@ void *eNB_app_task(void *args_p) {
 
       break;
 
+    case M2AP_DEREGISTERED_ENB_IND:
+      LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p),
+            M2AP_DEREGISTERED_ENB_IND(msg_p).nb_m2);
+      /* TODO handle recovering of registration */
+      break;
+
+    case M2AP_REGISTER_ENB_CNF:
+      LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p),
+            M2AP_REGISTER_ENB_CNF(msg_p).nb_m2);
+      DevAssert(m2_register_enb_pending > 0);
+      m2_register_enb_pending--;
+
+      /* Check if at least eNB is registered with one target eNB */
+      if (M2AP_REGISTER_ENB_CNF(msg_p).nb_m2 > 0) {
+        m2_registered_enb++;
+      }
+
+      /* Check if all register eNB requests have been processed */
+      if (m2_register_enb_pending == 0) {
+        if (m2_registered_enb == enb_nb) {
+          /* If all eNB are registered, start RRC HO task */
+          } else {
+          uint32_t m2_not_associated = enb_nb - m2_registered_enb;
+          LOG_W(ENB_APP, " %d eNB %s not associated with the target\n",
+                m2_not_associated, m2_not_associated > 1 ? "are" : "is");
+
+         // timer to retry
+         /* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
+          //if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
+         //               INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
+         //               &x2_enb_register_retry_timer_id) < 0) {
+          //  LOG_E(ENB_APP, " Can not start eNB X2AP register: retry timer, use \"sleep\" instead!\n");
+          //  sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
+          //  /* Restart the registration process */
+          //  x2_registered_enb = 0;
+          //  x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
+          //}
+        }
+      }
+      break;
+
+    case M2AP_SETUP_RESP:
+     LOG_I(ENB_APP,"M2AP_SETUP_RESP RESPONSE received\n");
+     // AssertFatal(NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received F1AP_REGISTER_ENB_CNF in CU/eNB\n");
+
+     // LOG_I(ENB_APP, "Received %s: associated ngran_eNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p),
+     //       F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate);
+     //
+     // handle_f1ap_setup_resp(&F1AP_SETUP_RESP(msg_p));
+
+     // DevAssert(register_enb_pending > 0);
+     // register_enb_pending--;
+
+     // /* Check if at least eNB is registered with one MME */
+     // if (F1AP_SETUP_RESP(msg_p).num_cells_to_activate > 0) {
+     //   registered_enb++;
+     // }
+
+     // /* Check if all register eNB requests have been processed */
+     // if (register_enb_pending == 0) {
+     //   if (registered_enb == enb_nb) {
+     //     /* If all eNB cells are registered, start L2L1 task */
+     //     MessageDef *msg_init_p;
+
+     //     msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
+     //     itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
+
+     //   } else {
+     //     LOG_W(ENB_APP, " %d eNB not associated with a MME, retrying registration in %d seconds ...\n",
+     //           enb_nb - registered_enb,  ENB_REGISTER_RETRY_DELAY);
+
+     //     /* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
+     //     if (timer_setup (ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+     //                      NULL, &enb_register_retry_timer_id) < 0) {
+     //       LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");
+
+     //       sleep(ENB_REGISTER_RETRY_DELAY);
+     //       /* Restart the registration process */
+     //       registered_enb = 0;
+     //       register_enb_pending = eNB_app_register (RC.rrc[0]->node_type,enb_id_start, enb_id_end);//, enb_properties_p);
+     //     }
+     //   }
+     // }
+     break;
+
+  case M2AP_MBMS_SCHEDULING_INFORMATION:
+     LOG_I(ENB_APP,"M2AP_SCHEDULING_INFORMATION received\n");
+     eNB_app_handle_m2ap_mbms_scheduling_information(ITTI_MESSAGE_GET_INSTANCE(msg_p));
+     break;
+  case M2AP_MBMS_SESSION_START_REQ:
+     LOG_I(ENB_APP,"M2AP_MBMS_SESSION_START_REQ received\n");
+     eNB_app_handle_m2ap_mbms_session_start_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
+     break;
+  case M2AP_MBMS_SESSION_STOP_REQ:
+     LOG_I(ENB_APP,"M2AP_MBMS_SESSION_STOP_REQ received\n");
+     eNB_app_handle_m2ap_mbms_session_stop_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
+     break;
+  case M2AP_RESET:
+     LOG_I(ENB_APP,"M2AP_RESET received\n");
+     break;
+  case M2AP_ENB_CONFIGURATION_UPDATE_ACK:
+     LOG_I(ENB_APP,"M2AP_ENB_CONFIGURATION_UPDATE_ACK received\n");
+     break;
+  case M2AP_ENB_CONFIGURATION_UPDATE_FAILURE:
+     LOG_I(ENB_APP,"M2AP_ENB_CONFIGURATION_UPDATE_FAILURE received\n");
+     break;
+  case M2AP_ERROR_INDICATION:
+     LOG_I(ENB_APP,"M2AP_MBMS_SESSION_UPDATE_REQ\n");
+     eNB_app_handle_m2ap_mbms_session_update_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
+     break;
+  case M2AP_MBMS_SERVICE_COUNTING_REQ:
+     LOG_I(ENB_APP,"M2AP_MBMS_SERVICE_COUNTING_REQ\n");
+     break;
+  case M2AP_MCE_CONFIGURATION_UPDATE:
+     LOG_I(ENB_APP,"M2AP_MCE_CONFIGURATION_UPDATE\n");
+     break;
+
     default:
       LOG_E(ENB_APP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
       break;
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 06386adbb792da85a3521a56346b5a4707caeb7c..ef4c32869111f15c7f2d05ddeb27c567270db4b1 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -380,7 +380,6 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) {
         for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
           PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
 
-        //RRC_CONFIGURATION_REQ (msg_p).rrc_inactivity_timer_thres = RRC_INACTIVITY_THRESH; // set to 0 to deactivate
         // In the configuration file it is in seconds. For RRC it has to be in milliseconds
         RRC_CONFIGURATION_REQ (msg_p).rrc_inactivity_timer_thres = (*ENBParamList.paramarray[i][ENB_RRC_INACTIVITY_THRES_IDX].uptr) * 1000;
         RRC_CONFIGURATION_REQ (msg_p).cell_identity = enb_id;
@@ -428,6 +427,14 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) {
         else
           RRC_CONFIGURATION_REQ (msg_p).enable_x2 = 0;
 
+       /* m2 enabled */
+       if (ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr != NULL &&
+            *(ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr) != NULL &&
+            !strcmp(*(ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr), "yes"))
+          RRC_CONFIGURATION_REQ (msg_p).eMBMS_M2_configured = 1;
+        else
+          RRC_CONFIGURATION_REQ (msg_p).eMBMS_M2_configured = 0;
+
         // Parse optional physical parameters
         config_getlist( &CCsParamList,NULL,0,enbpath);
         LOG_I(RRC,"num component carriers %d \n",CCsParamList.numelt);
@@ -2044,6 +2051,266 @@ int RCconfig_gtpu(void ) {
   return 0;
 }
 
+int RCconfig_M2(MessageDef *msg_p, uint32_t i) {
+  int   I, J, j, k, l;
+  int   enb_id;
+  char *address = NULL;
+  char *cidr    = NULL;
+  ccparams_lte_t ccparams_lte;
+  memset((void *)&ccparams_lte,0,sizeof(ccparams_lte_t));
+  paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
+  paramdef_t ENBParams[]  = ENBPARAMS_DESC;
+  paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0};
+  /* get global parameters, defined outside any section in the config file */
+  config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL);
+  checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
+  paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
+  paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS, NULL, 0};
+
+ // ccparams_MCE_t MCEconfig;
+ // memset((void *)&MCEconfig,0,sizeof(ccparams_MCE_t));
+ // paramdef_t MCEParams[]              = MCEPARAMS_DESC((&MCEconfig));
+ // checkedparam_t config_check_MCEparams[] = MCEPARAMS_CHECK;
+
+
+  /* map parameter checking array instances to parameter definition array instances */
+  for (I = 0; I < (sizeof(CCsParams) / sizeof(paramdef_t)); I++) {
+    CCsParams[I].chkPptr = &(config_check_CCparams[I]);
+  }
+
+  AssertFatal(i < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt,
+              "Failed to parse config file %s, %uth attribute %s \n",
+              RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS);
+
+  if (ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt > 0) {
+    // Output a list of all eNBs.
+    config_getlist( &ENBParamList,ENBParams,sizeof(ENBParams)/sizeof(paramdef_t),NULL);
+
+    if (ENBParamList.numelt > 0) {
+      for (k = 0; k < ENBParamList.numelt; k++) {
+        if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) {
+          // Calculate a default eNB ID
+          if (EPC_MODE_ENABLED) {
+            uint32_t hash;
+            hash = s1ap_generate_eNB_id ();
+            enb_id = k + (hash & 0xFFFF8);
+          } else {
+            enb_id = k;
+          }
+        } else {
+          enb_id = *(ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr);
+        }
+
+        // search if in active list
+        for (j = 0; j < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; j++) {
+          if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[j], *(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)) == 0) {
+            paramdef_t PLMNParams[] = PLMNPARAMS_DESC;
+            paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
+            /* map parameter checking array instances to parameter definition array instances */
+            checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
+
+            for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
+              PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
+
+            paramdef_t M2Params[]  = M2PARAMS_DESC;
+            paramlist_def_t M2ParamList = {ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS,NULL,0};
+            paramdef_t SCTPParams[]  = SCTPPARAMS_DESC;
+            paramdef_t NETParams[]  =  NETPARAMS_DESC;
+            paramdef_t MBMSConfigParams[]  = MBMS_CONFIG_PARAMS_DESC;
+            paramdef_t MBMSParams[]  = MBMSPARAMS_DESC;
+           paramlist_def_t MBMSConfigParamList = {ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST,NULL,0};
+           paramlist_def_t MBMSParamList = {ENB_CONFIG_STRING_MBMS_SERVICE_AREA_LIST,NULL,0};
+            /* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */
+            /* this is most probably a problem with the config module */
+            char aprefix[MAX_OPTNAME_SIZE*80 + 8];
+            sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
+            /* Some default/random parameters */
+            M2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id;
+
+            if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_ENB") == 0) {
+              M2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB;
+            } else  if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_HOME_ENB") == 0) {
+              M2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB;
+            } else {
+              AssertFatal (0,
+                           "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n",
+                           RC.config_file_name, i, *(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr));
+            }
+
+            M2AP_REGISTER_ENB_REQ (msg_p).eNB_name         = strdup(*(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr));
+            M2AP_REGISTER_ENB_REQ (msg_p).tac              = *ENBParamList.paramarray[k][ENB_TRACKING_AREA_CODE_IDX].uptr;
+            config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
+
+
+
+//            char aprefix2[MAX_OPTNAME_SIZE*80 + 8];
+//            sprintf(aprefix2,"%s.[%i].%s.[0]",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST);
+//            config_getlist(&MBMSParamList, MBMSParams, sizeof(MBMSParams)/sizeof(paramdef_t), aprefix2);
+//         if (MBMSParamList.numelt < 1 || MBMSParamList.numelt > 8)
+//              AssertFatal(0, "The number of MBMS Areas must be in [1,8], but is %d\n",
+//                          MBMSParamList.numelt);
+//         M2AP_REGISTER_ENB_REQ (msg_p).num_mbms_service_area_list = MBMSParamList.numelt;
+//         for(J=0; J<MBMSParamList.numelt;J++){
+//             M2AP_REGISTER_ENB_REQ (msg_p).mbms_service_area_list[J] = *MBMSParamList.paramarray[J][ENB_MBMS_SERVICE_AREA_IDX].uptr;
+//         }
+//
+
+            char aprefix2[MAX_OPTNAME_SIZE*80 + 8];
+            sprintf(aprefix2,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
+            config_getlist(&MBMSConfigParamList, MBMSConfigParams, sizeof(MBMSConfigParams)/sizeof(paramdef_t), aprefix2);
+            if (MBMSConfigParamList.numelt < 1 || MBMSConfigParamList.numelt > 8)
+              AssertFatal(0, "The number of MBMS Config Data must be in [1,8], but is %d\n",
+                          MBMSConfigParamList.numelt);
+            M2AP_REGISTER_ENB_REQ (msg_p).num_mbms_configuration_data_list = MBMSConfigParamList.numelt;
+           for(int I=0; I < MBMSConfigParamList.numelt; I++){
+
+                   sprintf(aprefix2,"%s.[%i].%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST,I);
+                   config_getlist(&MBMSParamList, MBMSParams, sizeof(MBMSParams)/sizeof(paramdef_t), aprefix2);
+                   if (MBMSParamList.numelt < 1 || MBMSParamList.numelt > 8)
+                     AssertFatal(0, "The number of MBMS Areas must be in [1,8], but is %d\n",
+                                 MBMSParamList.numelt);
+                   M2AP_REGISTER_ENB_REQ (msg_p).mbms_configuration_data_list[I].num_mbms_service_area_list = MBMSParamList.numelt;
+                   for(J=0; J<MBMSParamList.numelt;J++){
+                       M2AP_REGISTER_ENB_REQ (msg_p).mbms_configuration_data_list[I].mbms_service_area_list[J] = *MBMSParamList.paramarray[J][ENB_MBMS_SERVICE_AREA_IDX].uptr;
+                   }
+
+          }
+
+
+            if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
+              AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
+                          PLMNParamList.numelt);
+
+            if (PLMNParamList.numelt > 1)
+              LOG_W(M2AP, "M2AP currently handles only one PLMN, ignoring the others!\n");
+
+            M2AP_REGISTER_ENB_REQ (msg_p).mcc = *PLMNParamList.paramarray[0][ENB_MOBILE_COUNTRY_CODE_IDX].uptr;
+            M2AP_REGISTER_ENB_REQ (msg_p).mnc = *PLMNParamList.paramarray[0][ENB_MOBILE_NETWORK_CODE_IDX].uptr;
+            M2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length = *PLMNParamList.paramarray[0][ENB_MNC_DIGIT_LENGTH].u8ptr;
+            AssertFatal(M2AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length == 3
+                        || M2AP_REGISTER_ENB_REQ(msg_p).mnc < 100,
+                        "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n",
+                        M2AP_REGISTER_ENB_REQ(msg_p).mnc);
+            /* CC params */
+            config_getlist(&CCsParamList, NULL, 0, aprefix);
+            M2AP_REGISTER_ENB_REQ (msg_p).num_cc = CCsParamList.numelt;
+
+            if (CCsParamList.numelt > 0) {
+              //char ccspath[MAX_OPTNAME_SIZE*2 + 16];
+              for (J = 0; J < CCsParamList.numelt ; J++) {
+                sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, J);
+                config_get(CCsParams, sizeof(CCsParams)/sizeof(paramdef_t), aprefix);
+                M2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = ccparams_lte.eutra_band;
+                M2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = (uint32_t) ccparams_lte.downlink_frequency;
+                M2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = (unsigned int) ccparams_lte.uplink_frequency_offset;
+                M2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= ccparams_lte.Nid_cell;
+
+                if (ccparams_lte.Nid_cell>503) {
+                  AssertFatal (0,
+                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n",
+                               RC.config_file_name, k, ccparams_lte.Nid_cell);
+                }
+
+                M2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= ccparams_lte.N_RB_DL;
+
+                if ((ccparams_lte.N_RB_DL!=6) && (ccparams_lte.N_RB_DL!=15) && (ccparams_lte.N_RB_DL!=25) && (ccparams_lte.N_RB_DL!=50) && (ccparams_lte.N_RB_DL!=75) && (ccparams_lte.N_RB_DL!=100)) {
+                  AssertFatal (0,
+                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n",
+                               RC.config_file_name, k, ccparams_lte.N_RB_DL);
+                }
+
+                if (strcmp(ccparams_lte.frame_type, "FDD") == 0) {
+                  M2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD;
+                } else  if (strcmp(ccparams_lte.frame_type, "TDD") == 0) {
+                  M2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD;
+                } else {
+                  AssertFatal (0,
+                               "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n",
+                               RC.config_file_name, k, ccparams_lte.frame_type);
+                }
+
+                M2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency, ccparams_lte.N_RB_DL);
+                M2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency + ccparams_lte.uplink_frequency_offset, ccparams_lte.N_RB_DL);
+              }
+            }
+
+            sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
+            config_getlist( &M2ParamList,M2Params,sizeof(M2Params)/sizeof(paramdef_t),aprefix);
+            AssertFatal(M2ParamList.numelt <= M2AP_MAX_NB_ENB_IP_ADDRESS,
+                        "value of M2ParamList.numelt %d must be lower than M2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase M2AP_MAX_NB_ENB_IP_ADDRESS\n",
+                        M2ParamList.numelt,M2AP_MAX_NB_ENB_IP_ADDRESS);
+            M2AP_REGISTER_ENB_REQ (msg_p).nb_m2 = 0;
+
+            for (l = 0; l < M2ParamList.numelt; l++) {
+              M2AP_REGISTER_ENB_REQ (msg_p).nb_m2 += 1;
+              strcpy(M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4_address,*(M2ParamList.paramarray[l][ENB_M2_IPV4_ADDRESS_IDX].strptr));
+              strcpy(M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6_address,*(M2ParamList.paramarray[l][ENB_M2_IPV6_ADDRESS_IDX].strptr));
+
+              if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
+                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 1;
+                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 0;
+              } else if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
+                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 0;
+                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 1;
+              } else if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
+                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 1;
+                M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 1;
+              }
+            }
+            // timers
+            //{
+            //  int t_reloc_prep = 0;
+            //  int tx2_reloc_overall = 0;
+            //  paramdef_t p[] = {
+            //    { "t_reloc_prep", "t_reloc_prep", 0, iptr:&t_reloc_prep, defintval:0, TYPE_INT, 0 },
+            //    { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 }
+            //  };
+            //  config_get(p, sizeof(p)/sizeof(paramdef_t), aprefix);
+
+            //  if (t_reloc_prep <= 0 || t_reloc_prep > 10000 ||
+            //      tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000) {
+            //    LOG_E(M2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000]\n");
+            //    exit(1);
+            //  }
+
+            //  M2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep;
+            //  M2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall;
+            //}
+            // SCTP SETTING
+            M2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
+            M2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams  = SCTP_IN_STREAMS;
+
+            if (EPC_MODE_ENABLED) {
+              sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG);
+              config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix);
+              M2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr);
+              M2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[ENB_SCTP_OUTSTREAMS_IDX].uptr);
+            }
+
+            sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+            // NETWORK_INTERFACES
+            config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix);
+            M2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_M2C = (uint32_t)*(NETParams[ENB_PORT_FOR_M2C_IDX].uptr);
+
+            if ((NETParams[ENB_IPV4_ADDR_FOR_M2C_IDX].strptr == NULL) || (M2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_M2C == 0)) {
+              LOG_E(RRC,"Add eNB IPv4 address and/or port for M2C in the CONF file!\n");
+              exit(1);
+            }
+
+            cidr = *(NETParams[ENB_IPV4_ADDR_FOR_M2C_IDX].strptr);
+            address = strtok(cidr, "/");
+            M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv6 = 0;
+            M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv4 = 1;
+            strcpy(M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv4_address, address);
+          }
+        }
+      }
+    }
+  }
+
+  return 0;
+}
+
 //-----------------------------------------------------------------------------
 /*
 * Configure the s1ap_register_enb_req in itti message for future
diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h
index e9c7085d3e261f204e9e96ec36b9edd0890276e0..4bc4f5bf2244e306c998d95f8843880a13d324c3 100644
--- a/openair2/ENB_APP/enb_config.h
+++ b/openair2/ENB_APP/enb_config.h
@@ -116,6 +116,7 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i);
 
 void read_config_and_init(void);
 int RCconfig_X2(MessageDef *msg_p, uint32_t i);
+int RCconfig_M2(MessageDef *msg_p, uint32_t i);
 
 void fill_SL_configuration(MessageDef *msg_p,  ccparams_sidelink_t *SLconfig,int cell_idx,int cc_idx,char *config_fname);
 void fill_eMTC_configuration(MessageDef *msg_p,  ccparams_eMTC_t *eMTCconfig, int cell_idx,int cc_idx,char *config_fname,char *brparamspath);
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index f6c5ad1b0674f7f8a1e9d3a3f653be19faf55aa5..36ede04e347c09c5a5499c9991bfc90eb407a9e3 100644
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -202,6 +202,8 @@ typedef enum {
 #define ENB_CONFIG_STRING_RRC_INACTIVITY_THRESHOLD      "rrc_inactivity_threshold"
 #define ENB_CONFIG_STRING_MEASUREMENT_REPORTS           "enable_measurement_reports"
 #define ENB_CONFIG_STRING_X2                            "enable_x2"
+#define ENB_CONFIG_STRING_ENB_M2                        "enable_enb_m2"
+#define ENB_CONFIG_STRING_MCE_M2                        "enable_mce_m2"
 /*-----------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                            cell configuration parameters                                                                */
 /*   optname                                   helpstr   paramflags    XXXptr        defXXXval                   type           numelt     */
@@ -225,7 +227,10 @@ typedef enum {
     {ENB_CONFIG_STRING_RRC_INACTIVITY_THRESHOLD,     NULL,   0,            uptr:NULL,   defintval:0,                 TYPE_UINT,      0},  \
     {ENB_CONFIG_STRING_MEASUREMENT_REPORTS,          NULL,   0,            strptr:NULL, defstrval:NULL,              TYPE_STRING,    0},  \
     {ENB_CONFIG_STRING_X2,                           NULL,   0,            strptr:NULL, defstrval:NULL,              TYPE_STRING,    0},  \
+    {ENB_CONFIG_STRING_ENB_M2,                       NULL,   0,            strptr:NULL, defstrval:"no",              TYPE_STRING,    0},  \
+    {ENB_CONFIG_STRING_MCE_M2,                       NULL,   0,            strptr:NULL, defstrval:"no",              TYPE_STRING,    0},  \
   }
+
 #define ENB_ENB_ID_IDX                  0
 #define ENB_CELL_TYPE_IDX               1
 #define ENB_ENB_NAME_IDX                2
@@ -244,6 +249,8 @@ typedef enum {
 #define ENB_RRC_INACTIVITY_THRES_IDX    15
 #define ENB_ENABLE_MEASUREMENT_REPORTS  16
 #define ENB_ENABLE_X2                   17
+#define ENB_ENABLE_ENB_M2               18
+#define ENB_ENABLE_MCE_M2               19
 
 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
 #define ENBPARAMS_CHECK {                                           \
@@ -263,6 +270,8 @@ typedef enum {
     { .s5 = { NULL } },                                             \
     { .s5 = { NULL } },                                             \
     { .s5 = { NULL } },                                             \
+    { .s5 = { NULL } },                                             \
+    { .s5 = { NULL } },                                             \
   }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -297,6 +306,32 @@ typedef enum {
   }
 
 
+/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
+#define ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST                     "mbms_configuration_data_list"
+
+#define ENB_CONFIG_STRING_MBMS_SYNC_AREA           "mbms_sync_area"
+
+#define ENB_MBMS_SYNC_AREA_IDX     0
+
+#define MBMS_CONFIG_PARAMS_DESC {                                                                  \
+/*   optname                              helpstr               paramflags XXXptr     def val          type    numelt */ \
+  {ENB_CONFIG_STRING_MBMS_SYNC_AREA           , NULL,        0, uptr:NULL, defuintval:0, TYPE_UINT, 0},    \
+}
+
+
+/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
+#define ENB_CONFIG_STRING_MBMS_SERVICE_AREA_LIST                     "mbms_service_area_list"
+
+#define ENB_CONFIG_STRING_MBMS_SERVICE_AREA           "mbms_service_area"
+
+#define ENB_MBMS_SERVICE_AREA_IDX     0
+
+#define MBMSPARAMS_DESC {                                                                  \
+/*   optname                              helpstr               paramflags XXXptr     def val          type    numelt */ \
+  {ENB_CONFIG_STRING_MBMS_SERVICE_AREA, NULL,        0, uptr:NULL, defuintval:0, TYPE_UINT, 0},    \
+}
+
+
 /* component carries configuration parameters name */
 
 #define ENB_CONFIG_STRING_NB_ANT_PORTS                                  "nb_antenna_ports"
@@ -909,6 +944,39 @@ typedef struct srb1_params_s {
 #define ENB_X2_IPV4_ADDRESS_IDX          0
 #define ENB_X2_IPV6_ADDRESS_IDX          1
 #define ENB_X2_IP_ADDRESS_PREFERENCE_IDX 2
+
+
+/*---------------------------------------------------------------------------------------------------------------------------------------*/
+
+/* M2 configuration parameters section name */
+#define ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS                "target_mce_m2_ip_address"
+
+/* M2 configuration parameters names   */
+
+
+#define ENB_CONFIG_STRING_TARGET_MCE_M2_IPV4_ADDRESS              "ipv4"
+#define ENB_CONFIG_STRING_TARGET_MCE_M2_IPV6_ADDRESS              "ipv6"
+#define ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS_PREFERENCE     "preference"
+
+/*---------------------------------------------------------------------------------------------------------------------------------------*/
+
+
+
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+/*                                            M2 configuration parameters                                                             */
+/*   optname                                          helpstr   paramflags    XXXptr       defXXXval         type           numelt     */
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+#define M2PARAMS_DESC {  \
+{ENB_CONFIG_STRING_TARGET_MCE_M2_IPV4_ADDRESS,                   NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+{ENB_CONFIG_STRING_TARGET_MCE_M2_IPV6_ADDRESS,                   NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+{ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS_PREFERENCE,          NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+}
+
+#define ENB_M2_IPV4_ADDRESS_IDX          0
+#define ENB_M2_IPV6_ADDRESS_IDX          1
+#define ENB_M2_IP_ADDRESS_PREFERENCE_IDX 2
+/*---------------------------------------------------------------------------------------------------------------------------------------*/
+
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
 /* SCTP configuration parameters section name */
 #define ENB_CONFIG_STRING_SCTP_CONFIG                    "SCTP"
@@ -942,7 +1010,10 @@ typedef struct srb1_params_s {
 #define ENB_PORT_FOR_S1U_IDX                       4
 #define ENB_IPV4_ADDR_FOR_X2C_IDX                  5
 #define ENB_PORT_FOR_X2C_IDX                       6
-
+#define ENB_IPV4_ADDR_FOR_M2C_IDX                  7
+#define ENB_PORT_FOR_M2C_IDX                       8
+#define MCE_IPV4_ADDR_FOR_M2C_IDX                  9
+#define MCE_PORT_FOR_M2C_IDX                       10
 
 /* S1 interface configuration parameters names   */
 #define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME "ENB_INTERFACE_NAME_FOR_S1_MME"
@@ -955,6 +1026,13 @@ typedef struct srb1_params_s {
 #define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C         "ENB_IPV4_ADDRESS_FOR_X2C"
 #define ENB_CONFIG_STRING_ENB_PORT_FOR_X2C              "ENB_PORT_FOR_X2C"
 
+/* M2 interface configuration parameters names */
+#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_M2C         "ENB_IPV4_ADDRESS_FOR_M2C"
+#define ENB_CONFIG_STRING_ENB_PORT_FOR_M2C              "ENB_PORT_FOR_M2C"
+#define ENB_CONFIG_STRING_MCE_IPV4_ADDR_FOR_M2C         "MCE_IPV4_ADDRESS_FOR_M2C"
+#define ENB_CONFIG_STRING_MCE_PORT_FOR_M2C              "MCE_PORT_FOR_M2C"
+
+
 /*--------------------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                            S1/X2 interface configuration parameters                                                                 */
 /*   optname                                            helpstr   paramflags    XXXptr              defXXXval             type           numelt     */
@@ -967,7 +1045,12 @@ typedef struct srb1_params_s {
     {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U,                     NULL,      0,         uptr:NULL,           defintval:2152L,     TYPE_UINT,        0},      \
     {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C,                NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
     {ENB_CONFIG_STRING_ENB_PORT_FOR_X2C,                     NULL,      0,         uptr:NULL,           defintval:0L,        TYPE_UINT,        0},      \
+    {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_M2C,                NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
+    {ENB_CONFIG_STRING_ENB_PORT_FOR_M2C,                     NULL,      0,         uptr:NULL,           defintval:0L,        TYPE_UINT,        0},      \
+    {ENB_CONFIG_STRING_MCE_IPV4_ADDR_FOR_M2C,                NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
+    {ENB_CONFIG_STRING_MCE_PORT_FOR_M2C,                     NULL,      0,         uptr:NULL,           defintval:0L,        TYPE_UINT,        0},      \
   }
+}   
 
 /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                            GTPU  configuration parameters                                                                                                      */
@@ -985,8 +1068,6 @@ typedef struct srb1_params_s {
 #define CONFIG_STRING_L1_LIST                              "L1s"
 #define CONFIG_STRING_L1_CONFIG                            "l1_config"
 
-
-
 /*----------------------------------------------------------------------------------------------------------------------------------------------------*/
 
 /*----------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -1142,4 +1223,6 @@ typedef struct srb1_params_s {
 
 #include "enb_paramdef_emtc.h"
 #include "enb_paramdef_sidelink.h"
+#include "enb_paramdef_mce.h"
+#include "enb_paramdef_mme.h"
 #endif
diff --git a/openair2/ENB_APP/enb_paramdef_mce.h b/openair2/ENB_APP/enb_paramdef_mce.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a4dd157667856947b0678a4f39624c6b82ba381
--- /dev/null
+++ b/openair2/ENB_APP/enb_paramdef_mce.h
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file openair2/ENB_APP/enb_paramdef_mce.h
+ * \brief definition of configuration parameters for MCE modules 
+ * \author Javier MORGADE
+ * \date 2019
+ * \version 0.1
+ * \company VICOMTECH Spain
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "common/config/config_paramdesc.h"
+#include "RRC_paramsvalues.h"
+
+
+
+/* mce configuration parameters names */
+
+#define MCE_CONFIG_STRING_MCE_ID                        "MCE_ID"
+#define MCE_CONFIG_STRING_MCE_NAME                      "MCE_name"
+#define MCE_CONFIG_STRING_MCE_M2                        "enable_mce_m2"
+#define MCE_CONFIG_STRING_MCE_M3                        "enable_mce_m3"
+
+#define MCE_PARAMS_DESC {\
+{MCE_CONFIG_STRING_MCE_ID,                       NULL,   0,            uptr:NULL,   defintval:0,                 TYPE_UINT,      0},  \
+{MCE_CONFIG_STRING_MCE_NAME,                     NULL,   0,            strptr:NULL, defstrval:"OAIMCE",       TYPE_STRING,    0},  \
+{MCE_CONFIG_STRING_MCE_M2,                       NULL,   0,            strptr:NULL, defstrval:"no",              TYPE_STRING,    0},  \
+{MCE_CONFIG_STRING_MCE_M3,                       NULL,   0,            strptr:NULL, defstrval:"no",              TYPE_STRING,    0},  \
+}  
+
+#define MCE_MCE_ID_IDX                  0
+#define MCE_MCE_NAME_IDX                1
+#define MCE_ENABLE_MCE_M2_IDX           2
+#define MCE_ENABLE_MCE_M3_IDX           3
+
+#define MCE_PARAMS_CHECK {                                         \
+  { .s5 = { NULL } },                                             \
+  { .s5 = { NULL } },                                             \
+  { .s5 = { NULL } },                                             \
+  { .s5 = { NULL } },                                             \
+}
+
+
+#define MCE_CONFIG_STRING_NETWORK_INTERFACES_CONFIG     "NETWORK_INTERFACES"
+
+#define MCE2_INTERFACE_NAME_FOR_M2_ENB_IDX	0
+#define MCE2_IPV4_ADDR_FOR_M2C_IDX            	1
+#define MCE2_PORT_FOR_M2C_IDX             	2
+#define MCE2_INTERFACE_NAME_FOR_M3_MME_IDX      3
+#define MCE2_IPV4_ADDR_FOR_M3C_IDX            	4
+#define MCE2_PORT_FOR_M3C_IDX                	5
+
+/* interface configuration parameters names   */
+/* M2 interface configuration parameters names */
+#define MCE_CONFIG_STRING_MCE_INTERFACE_NAME_FOR_M2_ENB "ENB_INTERFACE_NAME_FOR_M2_ENB"
+#define MCE_CONFIG_STRING_MCE_IPV4_ADDRESS_FOR_M2C "MCE_IPV4_ADDRESS_FOR_M2C"
+#define MCE_CONFIG_STRING_MCE_PORT_FOR_M2C "MCE_PORT_FOR_M2C"
+
+/* M3 interface configuration parameters names */
+#define MCE_CONFIG_STRING_MCE_INTERFACE_NAME_FOR_M3_MME "MCE_INTERFACE_NAME_FOR_M3_MME"
+#define MCE_CONFIG_STRING_MCE_IPV4_ADDRESS_FOR_M3C "MCE_IPV4_ADDRESS_FOR_M3C"
+#define MCE_CONFIG_STRING_MCE_PORT_FOR_M3C "MCE_PORT_FOR_M3C"
+
+
+#define MCE_NETPARAMS_DESC {  \
+{MCE_CONFIG_STRING_MCE_INTERFACE_NAME_FOR_M2_ENB,        NULL,      0,         strptr:&mce_interface_name_for_m2_enb,    defstrval:"lo",      TYPE_STRING,      0},      \
+{MCE_CONFIG_STRING_MCE_IPV4_ADDRESS_FOR_M2C,             NULL,      0,         strptr:&mce_ipv4_address_for_m2c,         defstrval:NULL,      TYPE_STRING,      0},      \
+{MCE_CONFIG_STRING_MCE_PORT_FOR_M2C,                     NULL,      0,         uptr:&mce_port_for_m2c,           	 defintval:36443L,    TYPE_UINT,        0},      \
+{MCE_CONFIG_STRING_MCE_INTERFACE_NAME_FOR_M3_MME,        NULL,      0,         strptr:&mce_interface_name_for_m3_mme,    defstrval:NULL,      TYPE_STRING,      0},      \
+{MCE_CONFIG_STRING_MCE_IPV4_ADDRESS_FOR_M3C,             NULL,      0,         strptr:&mce_ipv4_address_for_m3c,         defstrval:NULL,      TYPE_STRING,      0},      \
+{MCE_CONFIG_STRING_MCE_PORT_FOR_M3C,                     NULL,      0,         uptr:&mce_port_for_m3c,           	 defintval:36444L,    TYPE_UINT,        0},      \
+} 
+
+
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+/*                                            M3 configuration parameters                                                             */
+/* M3 configuration parameters section name */
+#define MCE_CONFIG_STRING_TARGET_MME_M3_IP_ADDRESS                "target_mme_m3_ip_address"
+/* M3 configuration parameters names   */
+#define MCE_CONFIG_STRING_TARGET_MME_M3_IPV4_ADDRESS              "ipv4"
+#define MCE_CONFIG_STRING_TARGET_MME_M3_IPV6_ADDRESS              "ipv6"
+#define MCE_CONFIG_STRING_TARGET_MME_M3_IP_ADDRESS_PREFERENCE     "preference"
+/*   optname                                          helpstr   paramflags    XXXptr       defXXXval         type           numelt     */
+#define M3PARAMS_DESC {  \
+{MCE_CONFIG_STRING_TARGET_MME_M3_IPV4_ADDRESS,                   NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+{MCE_CONFIG_STRING_TARGET_MME_M3_IPV6_ADDRESS,                   NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+{MCE_CONFIG_STRING_TARGET_MME_M3_IP_ADDRESS_PREFERENCE,          NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+}
+
+#define MCE2_M3_IPV4_ADDRESS_IDX          0
+#define MCE2_M3_IPV6_ADDRESS_IDX          1
+#define MCE2_M3_IP_ADDRESS_PREFERENCE_IDX 2
+
+
+/*-----------------------------------------------------------------------------------------------------------------------------------*/
+/*                             MCCH related BCCH Configuration per MBSFN area configuration parameters                                                             */
+/* MCCH configuration parameters section */
+#define MCE_CONFIG_STRING_MCCH_CONFIG_PER_MBSFN_AREA                	"mcch_config_per_mbsfn_area"
+/* M3 configuration parameters names   */
+#define MCE_CONFIG_STRING_MCCH_MBSFN_AREA	                  	"mbsfn_area"
+#define MCE_CONFIG_STRING_MCCH_PDCCH_LENGTH              		"pdcch_length"
+#define MCE_CONFIG_STRING_MCCH_REPETITION_PERIOD     			"repetition_period"
+#define MCE_CONFIG_STRING_MCCH_OFFSET     				"offset"
+#define MCE_CONFIG_STRING_MCCH_MODIFICATION_PERIOD     			"modification_period"
+#define MCE_CONFIG_STRING_MCCH_SF_ALLOCATION_INFO     			"subframe_allocation_info"
+#define MCE_CONFIG_STRING_MCCH_MCS     					"mcs"
+
+/*   optname                                          helpstr   paramflags    XXXptr       defXXXval         type           numelt     */
+
+#define MCCH_PARAMS_DESC {  \
+{MCE_CONFIG_STRING_MCCH_MBSFN_AREA,         NULL,      0,         uptr:NULL,           	 defuintval:0,    TYPE_UINT,        0},      \
+{MCE_CONFIG_STRING_MCCH_PDCCH_LENGTH,       NULL,      0,         uptr:NULL,           	 defuintval:0,    TYPE_UINT,        0},      \
+{MCE_CONFIG_STRING_MCCH_REPETITION_PERIOD,  NULL,      0,         uptr:NULL,           	 defuintval:0,    TYPE_UINT,        0},      \
+{MCE_CONFIG_STRING_MCCH_OFFSET,             NULL,      0,         uptr:NULL,           	 defuintval:0,    TYPE_UINT,        0},      \
+{MCE_CONFIG_STRING_MCCH_MODIFICATION_PERIOD,NULL,      0,         uptr:NULL,           	 defuintval:0,    TYPE_UINT,        0},      \
+{MCE_CONFIG_STRING_MCCH_SF_ALLOCATION_INFO, NULL,      0,         uptr:NULL,       	 defuintval:0,    TYPE_UINT,        0},      \
+{MCE_CONFIG_STRING_MCCH_MCS,                NULL,      0,         uptr:NULL,           	 defuintval:0,    TYPE_UINT,        0},      \
+}
+
+#define MCCH_MBSFN_AREA_IDX          0
+#define MCCH_PDCCH_LENGTH_IDX        1
+#define MCCH_REPETITION_PERIOD_IDX   2
+#define MCCH_OFFSET_IDX 	     3
+#define MCCH_MODIFICATION_PERIOD_IDX 4
+#define MCCH_SF_ALLOCATION_INFO_IDX  5
+#define MCCH_MCS_IDX 		     6
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+/* M3 configuration parameters section name */
+#define MCE_CONFIG_STRING_PLMN                "plnm"
+/* M3 configuration parameters names   */
+#define MCE_CONFIG_STRING_MCC              "mcc"
+#define MCE_CONFIG_STRING_MNC              "mnc"
+#define MCE_CONFIG_STRING_MNC_LENGTH       "mnc_length"
+/*   optname                                          helpstr   paramflags    XXXptr       defXXXval         type           numelt     */
+#define MCE_PLMN_PARAMS_DESC {  \
+{MCE_CONFIG_STRING_MCC,                   NULL,      0,         uptr:NULL,   defuintval:1000,   TYPE_UINT,   0},          \
+{MCE_CONFIG_STRING_MNC,                   NULL,      0,         uptr:NULL,   defuintval:1000,   TYPE_UINT,   0},          \
+{MCE_CONFIG_STRING_MNC_LENGTH,            NULL,      0,         uptr:NULL,   defuintval:0,   TYPE_UINT,   0},          \
+}
+
+#define MCE_CONFIG_STRING_MCC_IDX          0
+#define MCE_CONFIG_STRING_MNC_IDX          1
+#define MCE_CONFIG_STRING_MNC_LENGTH_IDX   2
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+
+#define MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO			"mbms_sched_info"
+
+#define MCE_CONFIG_STRING_MCCH_UPDATE_TIME			"mcch_update_time"
+#define MCE_MBMS_SCHEDULING_INFO_PARAMS_DESC {  \
+{MCE_CONFIG_STRING_MCCH_UPDATE_TIME,            NULL,      0,         uptr:NULL,   defuintval:0,   TYPE_UINT,   0},          \
+}
+#define MCE_CONFIG_STRING_MCCH_UPDATE_TIME_IDX	0
+
+///*-------------------------------------------------------------------------------------------------------------------------------------*/
+#define MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST			"mbms_area_config_list"
+
+#define MCE_CONFIG_STRING_COMMON_SF_ALLOCATION_PERIOD			"common_sf_allocation_period"
+#define MCE_CONFIG_STRING_MBMS_AREA_ID					"mbms_area_id"
+
+#define MCE_MBMS_AREA_CONFIGURATION_LIST_PARAMS_DESC {  \
+{MCE_CONFIG_STRING_COMMON_SF_ALLOCATION_PERIOD,         NULL,      0,         uptr:NULL,           	 defuintval:0,    TYPE_UINT,        0},      \
+{MCE_CONFIG_STRING_MBMS_AREA_ID,       			NULL,      0,         uptr:NULL,           	 defuintval:0,    TYPE_UINT,        0},      \
+}
+#define MCE_CONFIG_STRING_COMMON_SF_ALLOCATION_PERIOD_IDX	0
+#define MCE_CONFIG_STRING_MBMS_AREA_ID_IDX	1
+//
+///*-------------------------------------------------------------------------------------------------------------------------------------*/
+#define MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST		"pmch_config_list"
+
+#define MCE_CONFIG_STRING_ALLOCATED_SF_END			"allocated_sf_end"
+#define MCE_CONFIG_STRING_DATA_MCS				"data_mcs"
+#define MCE_CONFIG_STRING_MCH_SCHEDULING_PERIOD			"mch_scheduling_period"
+
+#define MCE_MBMS_PMCH_CONFIGURATION_LIST_PARAMS_DESC {  \
+{MCE_CONFIG_STRING_ALLOCATED_SF_END,            NULL,      0,         uptr:NULL,   defuintval:0,   TYPE_UINT,   0},          \
+{MCE_CONFIG_STRING_DATA_MCS,            	NULL,      0,         uptr:NULL,   defuintval:0,   TYPE_UINT,   0},          \
+{MCE_CONFIG_STRING_MCH_SCHEDULING_PERIOD,       NULL,      0,         uptr:NULL,   defuintval:0,   TYPE_UINT,   0},          \
+}
+#define MCE_CONFIG_STRING_ALLOCATED_SF_END_IDX	0
+#define MCE_CONFIG_STRING_DATA_MCS_IDX			1
+#define MCE_CONFIG_STRING_MCH_SCHEDULING_PERIOD_IDX	2
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+#define MCE_CONFIG_STRING_MBMS_SESSION_LIST			"mbms_session_list"
+
+#define MCE_CONFIG_STRING_MBMS_SERVICE_ID			"service_id"
+#define MCE_CONFIG_STRING_MBMS_LCID_ID				"lcid_id"
+#define MCE_CONFIG_STRING_MBMS_LCID				"lcid"
+
+#define MCE_MBMS_MBMS_SESSION_LIST_DESC {  \
+{MCE_CONFIG_STRING_MBMS_SERVICE_ID,            	NULL,      0,         uptr:NULL,   defuintval:0,   TYPE_UINT32,   0},          \
+{MCE_CONFIG_STRING_MBMS_LCID_ID,            	NULL,      0,         uptr:NULL,   defuintval:0,   TYPE_UINT,   0},          \
+{MCE_CONFIG_STRING_MBMS_LCID,            	NULL,      0,         uptr:NULL,   defuintval:0,   TYPE_UINT,   0},          \
+}
+#define MCE_CONFIG_STRING_MBMS_SERVICE_ID_IDX	0
+#define MCE_CONFIG_STRING_MBMS_LCID_ID_IDX	1
+#define MCE_CONFIG_STRING_MBMS_LCID_IDX	2
+
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+#define MCE_CONFIG_STRING_MBMS_SF_CONFIGURATION_LIST			"mbms_sf_config_list"
+
+#define MCE_CONFIG_STRING_RADIOFRAME_ALLOCATION_PERIOD			"radioframe_allocation_period"
+#define MCE_CONFIG_STRING_RADIOFRAME_ALLOOCATION_OFFSET			"radioframe_alloocation_offset"
+#define MCE_CONFIG_STRING_NUM_FRAME					"num_frame"
+#define MCE_CONFIG_STRING_SUBFRAME_ALLOCATION				"subframe_allocation"
+
+#define MCE_MBMS_MBMS_SF_CONFIGURATION_LIST_PARAMS_DESC {  \
+{MCE_CONFIG_STRING_RADIOFRAME_ALLOCATION_PERIOD,            NULL,      0,         uptr:NULL,   defintval:0,   TYPE_UINT,   0},          \
+{MCE_CONFIG_STRING_RADIOFRAME_ALLOOCATION_OFFSET,            NULL,      0,         uptr:NULL,   defintval:0,   TYPE_UINT,   0},          \
+{MCE_CONFIG_STRING_NUM_FRAME,            NULL,      0,         strptr:NULL,   defstrval:"oneFrame",   TYPE_STRING,   0},          \
+{MCE_CONFIG_STRING_SUBFRAME_ALLOCATION,            NULL,      0,         uptr:NULL,   defintval:0,   TYPE_UINT,   0},          \
+}
+#define MCE_CONFIG_STRING_RADIOFRAME_ALLOCATION_PERIOD_IDX 0
+#define MCE_CONFIG_STRING_RADIOFRAME_ALLOOCATION_OFFSET_IDX	1
+#define MCE_CONFIG_STRING_NUM_FRAME_IDX	2
+#define MCE_CONFIG_STRING_SUBFRAME_ALLOCATION_IDX	3
+
+
+
diff --git a/openair2/ENB_APP/enb_paramdef_mme.h b/openair2/ENB_APP/enb_paramdef_mme.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ff1df765c07411d5b146e9ecfe73ada65deb0e3
--- /dev/null
+++ b/openair2/ENB_APP/enb_paramdef_mme.h
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file openair2/ENB_APP/enb_paramdef_mme.h
+ * \brief definition of configuration parameters for MME modules 
+ * \author Javier MORGADE
+ * \date 2019
+ * \version 0.1
+ * \company VICOMTECH Spain
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "common/config/config_paramdesc.h"
+#include "RRC_paramsvalues.h"
+
+
+
+/* mme configuration parameters names */
+
+#define MME_CONFIG_STRING_MME_ID                        "MME_ID"
+#define MME_CONFIG_STRING_MME_NAME                      "MME_name"
+#define MME_CONFIG_STRING_MME_M3                        "enable_mme_m3"
+
+#define MMEPARAMS_DESC {\
+{MME_CONFIG_STRING_MME_ID,                       NULL,   0,            uptr:NULL,   defintval:0,                 TYPE_UINT,      0},  \
+{MME_CONFIG_STRING_MME_NAME,                     NULL,   0,            strptr:NULL, defstrval:"OAIMME",       TYPE_STRING,    0},  \
+{MME_CONFIG_STRING_MME_M3,                       NULL,   0,            strptr:NULL, defstrval:"no",              TYPE_STRING,    0},  \
+}  
+
+#define MME_MME_ID_IDX                  0
+#define MME_MME_NAME_IDX                1
+#define MME_ENABLE_MME_M3_IDX           2
+
+#define MMEPARAMS_CHECK {                                         \
+  { .s5 = { NULL } },                                             \
+  { .s5 = { NULL } },                                             \
+  { .s5 = { NULL } },                                             \
+}
+
+
+#define MME_CONFIG_STRING_NETWORK_INTERFACES_CONFIG     "NETWORK_INTERFACES"
+
+#define MME_INTERFACE_NAME_FOR_M3_MME_IDX       0
+#define MME_IPV4_ADDRESS_FOR_M3C_IDX            1
+#define MME_PORT_FOR_M3C_IDX                	2
+
+/* interface configuration parameters names   */
+/* M3 interface configuration parameters names */
+#define MME_CONFIG_STRING_MME_INTERFACE_NAME_FOR_M3_MCE "MME_INTERFACE_NAME_FOR_M3_MCE"
+#define MME_CONFIG_STRING_MME_IPV4_ADDRESS_FOR_M3C "MME_IPV4_ADDRESS_FOR_M3C"
+#define MME_CONFIG_STRING_MME_PORT_FOR_M3C "MME_PORT_FOR_M3C"
+
+
+#define MME_NETPARAMS_DESC {  \
+{MME_CONFIG_STRING_MME_INTERFACE_NAME_FOR_M3_MCE,        NULL,      0,         strptr:&mme_interface_name_for_m3_mce,    defstrval:"lo",      TYPE_STRING,      0},      \
+{MME_CONFIG_STRING_MME_IPV4_ADDRESS_FOR_M3C,             NULL,      0,         strptr:&mme_ipv4_address_for_m3c,         defstrval:"127.0.0.18/24",      TYPE_STRING,      0},      \
+{MME_CONFIG_STRING_MME_PORT_FOR_M3C,                     NULL,      0,         uptr:&mme_port_for_m3c,           	 defintval:36444L,    TYPE_UINT,        0},      \
+} 
+
+
+
+
diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c
index 221786965d4d060c7a38ab48d84b872b210f1f80..dfac1ae7a0042eb426a2400940bfc6ed63826fbc 100644
--- a/openair2/ENB_APP/flexran_agent_ran_api.c
+++ b/openair2/ENB_APP/flexran_agent_ran_api.c
@@ -3496,7 +3496,6 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
       (*caps)[1] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
       (*caps)[2] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
       break;
-
     case ngran_eNB_DU:
     case ngran_gNB_DU:
       n_caps = 5;
@@ -3509,7 +3508,6 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
       (*caps)[3] = PROTOCOL__FLEX_BS_CAPABILITY__HIMAC;
       (*caps)[4] = PROTOCOL__FLEX_BS_CAPABILITY__RLC;
       break;
-
     case ngran_eNB:
     case ngran_ng_eNB:
     case ngran_gNB:
@@ -3526,6 +3524,8 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
       (*caps)[6] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
       (*caps)[7] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
       break;
+    case ngran_eNB_MBMS_STA:
+     break;
   }
 
   return n_caps;
@@ -3541,31 +3541,31 @@ uint16_t flexran_get_capabilities_mask(mid_t mod_id) {
     case ngran_ng_eNB_CU:
     case ngran_gNB_CU:
       mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
       break;
-
     case ngran_eNB_DU:
     case ngran_gNB_DU:
       mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC);
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC);
       break;
-
     case ngran_eNB:
     case ngran_ng_eNB:
     case ngran_gNB:
       mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
-             | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
-      break;
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
+           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
+      break;
+    case ngran_eNB_MBMS_STA:
+     break;
   }
 
   return mask;
diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c
index e1b7e114a448e527fa251164e89ce85381915609..223155c98a54974116063568fb38fba4d827d7cc 100644
--- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c
+++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c
@@ -47,13 +47,15 @@
 #include "common/ran_context.h"
 
 #include "rrc_eNB_UE_context.h"
+#include "asn1_msg.h"
+#include "intertask_interface.h"
 
 // undefine C_RNTI from
 // openair1/PHY/LTE_TRANSPORT/transport_common.h which
 // replaces in ie->value.choice.C_RNTI, causing
 // a compile error
 
-#undef C_RNTI
+#undef C_RNTI 
 
 extern f1ap_setup_req_t *f1ap_du_data;
 extern RAN_CONTEXT_t RC;
@@ -67,8 +69,10 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
                                       uint32_t         stream,
                                       F1AP_F1AP_PDU_t *pdu) {
   LOG_D(F1AP, "DU_handle_DL_RRC_MESSAGE_TRANSFER \n");
+  
   F1AP_DLRRCMessageTransfer_t    *container;
   F1AP_DLRRCMessageTransferIEs_t *ie;
+
   uint64_t        cu_ue_f1ap_id;
   uint64_t        du_ue_f1ap_id;
   uint64_t        srb_id;
@@ -76,20 +80,25 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
   sdu_size_t      rrc_dl_sdu_len;
   //uint64_t        subscriberProfileIDforRFP;
   //uint64_t        rAT_FrequencySelectionPriority;
+
   DevAssert(pdu != NULL);
 
   if (stream != 0) {
     LOG_E(F1AP, "[SCTP %d] Received F1 on stream != 0 (%d)\n",
-          assoc_id, stream);
+               assoc_id, stream);
     return -1;
   }
 
   container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer;
+
+
   /* GNB_CU_UE_F1AP_ID */
   F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container,
                              F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
   cu_ue_f1ap_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
   LOG_D(F1AP, "cu_ue_f1ap_id %lu \n", cu_ue_f1ap_id);
+
+
   /* GNB_DU_UE_F1AP_ID */
   F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container,
                              F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true);
@@ -107,7 +116,7 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
   /* oldgNB_DU_UE_F1AP_ID */
   if (0) {
     F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container,
-                               F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, true);
+                             F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, true);
   }
 
   /* mandatory */
@@ -121,7 +130,7 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
   /* ExecuteDuplication */
   if (0) {
     F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container,
-                               F1AP_ProtocolIE_ID_id_ExecuteDuplication, true);
+                             F1AP_ProtocolIE_ID_id_ExecuteDuplication, true);
     executeDuplication = ie->value.choice.ExecuteDuplication;
     LOG_D(F1AP, "ExecuteDuplication %d \n", executeDuplication);
   }
@@ -133,6 +142,7 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
                              F1AP_ProtocolIE_ID_id_RRCContainer, true);
   // BK: need check
   // create an ITTI message and copy SDU
+
   //  message_p = itti_alloc_new_message (TASK_CU_F1, RRC_MAC_CCCH_DATA_IND);
   //  memset (RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE);
   rrc_dl_sdu_len = ie->value.choice.RRCContainer.size;
@@ -148,17 +158,15 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
   /* RAT_FrequencyPriorityInformation */
   if (0) {
     F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container,
-                               F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation, true);
+                             F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation, true);
 
     switch(ie->value.choice.RAT_FrequencyPriorityInformation.present) {
       case F1AP_RAT_FrequencyPriorityInformation_PR_subscriberProfileIDforRFP:
         //subscriberProfileIDforRFP = ie->value.choice.RAT_FrequencyPriorityInformation.choice.subscriberProfileIDforRFP;
         break;
-
       case F1AP_RAT_FrequencyPriorityInformation_PR_rAT_FrequencySelectionPriority:
         //rAT_FrequencySelectionPriority = ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority;
         break;
-
       default:
         LOG_W(F1AP, "unhandled IE RAT_FrequencyPriorityInformation.present\n");
         break;
@@ -167,26 +175,28 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
 
   // decode RRC Container and act on the message type
   AssertFatal(srb_id<3,"illegal srb_id\n");
+
   protocol_ctxt_t ctxt;
   ctxt.rnti      = f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], du_ue_f1ap_id);
   ctxt.module_id = instance;
   ctxt.instance  = instance;
   ctxt.enb_flag  = 1;
-  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(
-        RC.rrc[ctxt.module_id],
-        ctxt.rnti);
+
+ struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(
+                                                RC.rrc[ctxt.module_id],
+                                                ctxt.rnti);
 
   if (srb_id == 0) {
-    LTE_DL_CCCH_Message_t *dl_ccch_msg=NULL;
+    LTE_DL_CCCH_Message_t* dl_ccch_msg=NULL;
     asn_dec_rval_t dec_rval;
     dec_rval = uper_decode(NULL,
-                           &asn_DEF_LTE_DL_CCCH_Message,
-                           (void **)&dl_ccch_msg,
-                           ie->value.choice.RRCContainer.buf,
-                           rrc_dl_sdu_len,0,0);
+         &asn_DEF_LTE_DL_CCCH_Message,
+         (void**)&dl_ccch_msg,
+         ie->value.choice.RRCContainer.buf,
+         rrc_dl_sdu_len,0,0);
     AssertFatal(dec_rval.code == RC_OK, "could not decode F1AP message\n");
-
     switch (dl_ccch_msg->message.choice.c1.present) {
+
       case LTE_DL_CCCH_MessageType__c1_PR_NOTHING:
         LOG_I(F1AP, "Received PR_NOTHING on DL-CCCH-Message\n");
         break;
@@ -206,29 +216,32 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
               "Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n");
         break;
 
-      case LTE_DL_CCCH_MessageType__c1_PR_rrcConnectionSetup: {
+      case LTE_DL_CCCH_MessageType__c1_PR_rrcConnectionSetup:
+      {
         LOG_I(F1AP,
               "Logical Channel DL-CCCH (SRB0), Received RRCConnectionSetup DU_ID %lx/RNTI %x\n",
               du_ue_f1ap_id,
               f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], du_ue_f1ap_id));
-        // Get configuration
-        LTE_RRCConnectionSetup_t *rrcConnectionSetup = &dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup;
+          // Get configuration
+
+        LTE_RRCConnectionSetup_t* rrcConnectionSetup = &dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup;
         AssertFatal(rrcConnectionSetup!=NULL,"rrcConnectionSetup is null\n");
-        LTE_RadioResourceConfigDedicated_t *radioResourceConfigDedicated = &rrcConnectionSetup->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r8.radioResourceConfigDedicated;
+        LTE_RadioResourceConfigDedicated_t* radioResourceConfigDedicated = &rrcConnectionSetup->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r8.radioResourceConfigDedicated;
+
         // get SRB logical channel information
         LTE_SRB_ToAddModList_t *SRB_configList;
         LTE_SRB_ToAddMod_t *SRB1_config;
         LTE_LogicalChannelConfig_t *SRB1_logicalChannelConfig = NULL;
         SRB_configList                 = radioResourceConfigDedicated->srb_ToAddModList;
-        AssertFatal(SRB_configList!=NULL,"SRB_configList is null\n");
 
+        AssertFatal(SRB_configList!=NULL,"SRB_configList is null\n");
         for (int cnt = 0; cnt < (SRB_configList)->list.count; cnt++) {
           if ((SRB_configList)->list.array[cnt]->srb_Identity == 1) {
             SRB1_config = (SRB_configList)->list.array[cnt];
 
             if (SRB1_config->logicalChannelConfig) {
               if (SRB1_config->logicalChannelConfig->present ==
-                  LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
+                LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
                 SRB1_logicalChannelConfig = &SRB1_config->logicalChannelConfig->choice.explicitValue;
               } else {
                 SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
@@ -238,32 +251,34 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
             }
           }
         } // for
-
         rrc_rlc_config_asn1_req(&ctxt,
-                                SRB_configList,
-                                (LTE_DRB_ToAddModList_t *) NULL,
-                                (LTE_DRB_ToReleaseList_t *) NULL,
-                                (LTE_PMCH_InfoList_r9_t *) NULL,
-                                0,0
-                               );
-        // This should be somewhere in the f1ap_cudu_ue_inst_t
-        /*int macrlc_instance = 0;
-
-        rnti_t rnti = f1ap_get_rnti_by_du_id(&f1ap_du_inst[0], du_ue_f1ap_id);
-        struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[macrlc_instance],rnti);
-        */
-        eNB_RRC_UE_t *ue_p = &ue_context_p->ue_context;
-        AssertFatal(ue_p->Srb0.Active == 1,"SRB0 is not active\n");
-        memcpy((void *)ue_p->Srb0.Tx_buffer.Payload,
-               (void *)ie->value.choice.RRCContainer.buf,
-               rrc_dl_sdu_len); // ie->value.choice.RRCContainer.size
-        ue_p->Srb0.Tx_buffer.payload_size = rrc_dl_sdu_len;
-        LTE_MAC_MainConfig_t    *mac_MainConfig  = NULL;
-
-        if (radioResourceConfigDedicated->mac_MainConfig)
-          mac_MainConfig = &radioResourceConfigDedicated->mac_MainConfig->choice.explicitValue;
-
-        rrc_mac_config_req_eNB(
+          SRB_configList,
+          (LTE_DRB_ToAddModList_t*) NULL,
+          (LTE_DRB_ToReleaseList_t*) NULL
+          , (LTE_PMCH_InfoList_r9_t *) NULL,
+          0,0
+          );
+
+      // This should be somewhere in the f1ap_cudu_ue_inst_t
+      /*int macrlc_instance = 0; 
+
+      rnti_t rnti = f1ap_get_rnti_by_du_id(&f1ap_du_inst[0], du_ue_f1ap_id);
+      struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[macrlc_instance],rnti);
+      */  
+      eNB_RRC_UE_t *ue_p = &ue_context_p->ue_context; 
+      AssertFatal(ue_p->Srb0.Active == 1,"SRB0 is not active\n");
+
+      memcpy((void*)ue_p->Srb0.Tx_buffer.Payload,
+             (void*)ie->value.choice.RRCContainer.buf,
+             rrc_dl_sdu_len); // ie->value.choice.RRCContainer.size
+
+      ue_p->Srb0.Tx_buffer.payload_size = rrc_dl_sdu_len;
+
+      LTE_MAC_MainConfig_t    *mac_MainConfig  = NULL;
+      if (radioResourceConfigDedicated->mac_MainConfig)
+        mac_MainConfig = &radioResourceConfigDedicated->mac_MainConfig->choice.explicitValue;
+
+      rrc_mac_config_req_eNB(
           ctxt.module_id,
           0, //primaryCC_id,
           0,0,0,0,0,0,
@@ -273,6 +288,7 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
           radioResourceConfigDedicated->physicalConfigDedicated,
           (LTE_SCellToAddMod_r10_t *)NULL,
+          //(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
           (LTE_MeasObjectToAddMod_t **) NULL,
           mac_MainConfig,
           1,
@@ -281,220 +297,236 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
           (LTE_TDD_Config_t *) NULL,
           NULL,
           (LTE_SchedulingInfoList_t *) NULL,
-          0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL,
-          0, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) NULL,
-          (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL,
-          0,
-          (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL,
-          (LTE_SchedulingInfo_MBMS_r14_t *) NULL,
-          (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
-          (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
-          (LTE_MBSFN_AreaInfoList_r9_t *) NULL
-        );
-        break;
+          0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL
+          , 0, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) NULL,
+          (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL
+                        ,
+                        0,
+                        (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL,
+                        (LTE_SchedulingInfo_MBMS_r14_t *) NULL,
+                        (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
+                        (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
+                        (LTE_MBSFN_AreaInfoList_r9_t *) NULL
+          );
+          break;
       } // case
 
       default:
         AssertFatal(1==0,
-                    "Unknown message\n");
+        "Unknown message\n");
         break;
     }// switch case
-
     return(0);
-  } else if (srb_id == 1) {
-    LTE_DL_DCCH_Message_t *dl_dcch_msg=NULL;
+  } else if (srb_id == 1) { 
+
+    LTE_DL_DCCH_Message_t* dl_dcch_msg=NULL;
     asn_dec_rval_t dec_rval;
     dec_rval = uper_decode(NULL,
-                           &asn_DEF_LTE_DL_DCCH_Message,
-                           (void **)&dl_dcch_msg,
-                           &ie->value.choice.RRCContainer.buf[1], // buf[0] includes the pdcp header
-                           rrc_dl_sdu_len,0,0);
-
-    if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0))
+         &asn_DEF_LTE_DL_DCCH_Message,
+         (void**)&dl_dcch_msg,
+         &ie->value.choice.RRCContainer.buf[1], // buf[0] includes the pdcp header
+         rrc_dl_sdu_len,0,0);
+    
+    if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) 
       LOG_E(F1AP," Failed to decode DL-DCCH (%zu bytes)\n",dec_rval.consumed);
     else
       LOG_D(F1AP, "Received message: present %d and c1 present %d\n",
             dl_dcch_msg->message.present, dl_dcch_msg->message.choice.c1.present);
 
     if (dl_dcch_msg->message.present == LTE_DL_DCCH_MessageType_PR_c1) {
+     
       switch (dl_dcch_msg->message.choice.c1.present) {
-        case LTE_DL_DCCH_MessageType__c1_PR_NOTHING:
-          LOG_I(F1AP, "Received PR_NOTHING on DL-DCCH-Message\n");
-          return 0;
-
-        case LTE_DL_DCCH_MessageType__c1_PR_dlInformationTransfer:
-          LOG_I(F1AP,"Received NAS DL Information Transfer\n");
-          break;
-
-        case LTE_DL_DCCH_MessageType__c1_PR_csfbParametersResponseCDMA2000:
-          LOG_I(F1AP,"Received NAS sfbParametersResponseCDMA2000\n");
-          break;
-
-        case LTE_DL_DCCH_MessageType__c1_PR_handoverFromEUTRAPreparationRequest:
-          LOG_I(F1AP,"Received NAS andoverFromEUTRAPreparationRequest\n");
-          break;
+	
+      case LTE_DL_DCCH_MessageType__c1_PR_NOTHING:
+        LOG_I(F1AP, "Received PR_NOTHING on DL-DCCH-Message\n");
+        return 0;
+      case LTE_DL_DCCH_MessageType__c1_PR_dlInformationTransfer:
+        LOG_I(F1AP,"Received NAS DL Information Transfer\n");
+        break;	
+      case LTE_DL_DCCH_MessageType__c1_PR_csfbParametersResponseCDMA2000:
+        LOG_I(F1AP,"Received NAS sfbParametersResponseCDMA2000\n");
+        break;  
+      case LTE_DL_DCCH_MessageType__c1_PR_handoverFromEUTRAPreparationRequest:
+        LOG_I(F1AP,"Received NAS andoverFromEUTRAPreparationRequest\n");
+        break;  
+      case LTE_DL_DCCH_MessageType__c1_PR_mobilityFromEUTRACommand:
+        LOG_I(F1AP,"Received NAS mobilityFromEUTRACommand\n");
+        break;
+      case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionReconfiguration:
+	     // handle RRCConnectionReconfiguration
+        LOG_I(F1AP,
+              "Logical Channel DL-DCCH (SRB1), Received RRCConnectionReconfiguration DU_ID %lx/RNTI %x\n",
+              du_ue_f1ap_id,
+              f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], du_ue_f1ap_id));
+	
+        LTE_RRCConnectionReconfiguration_t* rrcConnectionReconfiguration = &dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration;
+
+        if (rrcConnectionReconfiguration->criticalExtensions.present == LTE_RRCConnectionReconfiguration__criticalExtensions_PR_c1) {
+	        if (rrcConnectionReconfiguration->criticalExtensions.choice.c1.present ==
+	         LTE_RRCConnectionReconfiguration__criticalExtensions__c1_PR_rrcConnectionReconfiguration_r8) {
+	          LTE_RRCConnectionReconfiguration_r8_IEs_t* rrcConnectionReconfiguration_r8 =
+	          &rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8;
+	    
+            if (rrcConnectionReconfiguration_r8->mobilityControlInfo) {
+	            LOG_I(F1AP, "Mobility Control Information is present\n");
+	            AssertFatal(1==0,"Can't handle this yet in DU\n");
+	          }
+	          if (rrcConnectionReconfiguration_r8->measConfig != NULL) {
+	            LOG_I(F1AP, "Measurement Configuration is present\n");
+	          } 
+	    
+      	    if (rrcConnectionReconfiguration_r8->radioResourceConfigDedicated) {
+              LOG_I(F1AP, "Radio Resource Configuration is present\n");
+      	      uint8_t DRB2LCHAN[8];
+              long drb_id;
+              int i;
+              LTE_DRB_ToAddModList_t  *DRB_configList  = rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->drb_ToAddModList;
+              LTE_SRB_ToAddModList_t  *SRB_configList  = rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->srb_ToAddModList;
+              LTE_DRB_ToReleaseList_t *DRB_ReleaseList = rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->drb_ToReleaseList;
+              LTE_MAC_MainConfig_t    *mac_MainConfig  = NULL;
+              
+              for (i = 0; i< 8; i++){
+                DRB2LCHAN[i] = 0;
+              }
 
-        case LTE_DL_DCCH_MessageType__c1_PR_mobilityFromEUTRACommand:
-          LOG_I(F1AP,"Received NAS mobilityFromEUTRACommand\n");
-          break;
+              if (rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->mac_MainConfig) {
+                LOG_D(F1AP, "MAC Main Configuration is present\n");
 
-        case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionReconfiguration:
-          // handle RRCConnectionReconfiguration
-          LOG_I(F1AP,
-                "Logical Channel DL-DCCH (SRB1), Received RRCConnectionReconfiguration DU_ID %lx/RNTI %x\n",
-                du_ue_f1ap_id,
-                f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], du_ue_f1ap_id));
-          LTE_RRCConnectionReconfiguration_t *rrcConnectionReconfiguration = &dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration;
-
-          if (rrcConnectionReconfiguration->criticalExtensions.present == LTE_RRCConnectionReconfiguration__criticalExtensions_PR_c1) {
-            if (rrcConnectionReconfiguration->criticalExtensions.choice.c1.present ==
-                LTE_RRCConnectionReconfiguration__criticalExtensions__c1_PR_rrcConnectionReconfiguration_r8) {
-              LTE_RRCConnectionReconfiguration_r8_IEs_t *rrcConnectionReconfiguration_r8 =
-                &rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8;
-
-              if (rrcConnectionReconfiguration_r8->mobilityControlInfo) {
-                LOG_I(F1AP, "Mobility Control Information is present\n");
-                AssertFatal(1==0,"Can't handle this yet in DU\n");
-              }
+                mac_MainConfig = &rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->mac_MainConfig->choice.explicitValue;
 
-              if (rrcConnectionReconfiguration_r8->measConfig != NULL) {
-                LOG_I(F1AP, "Measurement Configuration is present\n");
-              }
+                /* CDRX Configuration */
+                if (mac_MainConfig->drx_Config == NULL) {
+                  LOG_W(F1AP, "drx_Configuration parameter is NULL, cannot configure local UE parameters or CDRX is deactivated\n");
+                } else {
+                  MessageDef *message_p = NULL;
 
-              if (rrcConnectionReconfiguration_r8->radioResourceConfigDedicated) {
-                LOG_I(F1AP, "Radio Resource Configuration is present\n");
-                uint8_t DRB2LCHAN[8];
-                long drb_id;
-                int i;
-                LTE_DRB_ToAddModList_t  *DRB_configList  = rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->drb_ToAddModList;
-                LTE_SRB_ToAddModList_t  *SRB_configList  = rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->srb_ToAddModList;
-                LTE_DRB_ToReleaseList_t *DRB_ReleaseList = rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->drb_ToReleaseList;
-                LTE_MAC_MainConfig_t    *mac_MainConfig  = NULL;
-
-                for (i = 0; i< 8; i++) {
-                  DRB2LCHAN[i] = 0;
+                  /* Send DRX configuration to MAC task to configure timers of local UE context */
+                  message_p = itti_alloc_new_message(TASK_DU_F1, RRC_MAC_DRX_CONFIG_REQ);
+                  RRC_MAC_DRX_CONFIG_REQ(message_p).rnti = ctxt.rnti;
+                  RRC_MAC_DRX_CONFIG_REQ(message_p).drx_Configuration = mac_MainConfig->drx_Config;
+                  itti_send_msg_to_task(TASK_MAC_ENB, ctxt.module_id, message_p);
+                  LOG_D(F1AP, "DRX configured in MAC Main Configuration for RRC Connection Reconfiguration\n");
                 }
+                /* End of CDRX configuration */
+              }
 
-                if (rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->mac_MainConfig)
-                  mac_MainConfig = &rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->mac_MainConfig->choice.explicitValue;
-
-                LTE_MeasGapConfig_t     *measGapConfig   = NULL;
-                struct LTE_PhysicalConfigDedicated *physicalConfigDedicated = rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->physicalConfigDedicated;
-                rrc_rlc_config_asn1_req(
-                  &ctxt,
-                  SRB_configList, // NULL,  //LG-RK 14/05/2014 SRB_configList,
-                  DRB_configList,
-                  DRB_ReleaseList, (LTE_PMCH_InfoList_r9_t *) NULL, 0, 0
+              LTE_MeasGapConfig_t     *measGapConfig   = NULL;
+              struct LTE_PhysicalConfigDedicated* physicalConfigDedicated = rrcConnectionReconfiguration_r8->radioResourceConfigDedicated->physicalConfigDedicated;
+              rrc_rlc_config_asn1_req(
+                &ctxt,
+                SRB_configList, // NULL,  //LG-RK 14/05/2014 SRB_configList,
+                DRB_configList,
+                DRB_ReleaseList, (LTE_PMCH_InfoList_r9_t *) NULL, 0, 0
                 );
 
-                if (SRB_configList != NULL) {
-                  for (i = 0; (i < SRB_configList->list.count) && (i < 3); i++) {
-                    if (SRB_configList->list.array[i]->srb_Identity == 1 ) {
-                      ue_context_p->ue_context.Srb1.Active=1;
-                    } else if (SRB_configList->list.array[i]->srb_Identity == 2 )  {
-                      ue_context_p->ue_context.Srb2.Active=1;
-                      ue_context_p->ue_context.Srb2.Srb_info.Srb_id=2;
-                      LOG_I(F1AP, "[DU %d] SRB2 is now active\n",ctxt.module_id);
-                    } else {
-                      LOG_W(F1AP, "[DU %d] invalide SRB identity %ld\n",ctxt.module_id,
-                            SRB_configList->list.array[i]->srb_Identity);
-                    }
+              if (SRB_configList != NULL) {
+                for (i = 0; (i < SRB_configList->list.count) && (i < 3); i++) {
+                  if (SRB_configList->list.array[i]->srb_Identity == 1 ){
+                    ue_context_p->ue_context.Srb1.Active=1;
                   }
-                }
-
-                if (DRB_configList != NULL) {
-                  for (i = 0; i < DRB_configList->list.count; i++) {  // num max DRB (11-3-8)
-                    if (DRB_configList->list.array[i]) {
-                      drb_id = (int)DRB_configList->list.array[i]->drb_Identity;
-                      LOG_I(F1AP,
-                            "[DU %d] Logical Channel UL-DCCH, Received RRCConnectionReconfiguration for UE rnti %x, reconfiguring DRB %d/LCID %d\n",
-                            ctxt.module_id,
-                            ctxt.rnti,
-                            (int)DRB_configList->list.array[i]->drb_Identity,
-                            (int)*DRB_configList->list.array[i]->logicalChannelIdentity);
-
-                      if (ue_context_p->ue_context.DRB_active[drb_id] == 0) {
-                        ue_context_p->ue_context.DRB_active[drb_id] = 1;
-
-                        if (DRB_configList->list.array[i]->logicalChannelIdentity) {
-                          DRB2LCHAN[i] = (uint8_t) * DRB_configList->list.array[i]->logicalChannelIdentity;
-                        }
-
-                        rrc_mac_config_req_eNB(
-                          ctxt.module_id,
-                          0,0,0,0,0,0, 0,
-                          ue_context_p->ue_context.rnti,
-                          (LTE_BCCH_BCH_Message_t *) NULL,
-                          (LTE_RadioResourceConfigCommonSIB_t *) NULL,
-                          (LTE_RadioResourceConfigCommonSIB_t *) NULL,
-                          physicalConfigDedicated,
-                          (LTE_SCellToAddMod_r10_t *)NULL,
-                          (LTE_MeasObjectToAddMod_t **) NULL,
-                          mac_MainConfig,
-                          DRB2LCHAN[i],
-                          DRB_configList->list.array[i]->logicalChannelConfig,
-                          measGapConfig,
-                          (LTE_TDD_Config_t *) NULL,
-                          NULL,
-                          (LTE_SchedulingInfoList_t *) NULL,
-                          0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL, 0,
-                          (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) NULL,
-                          (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL,
-                          0,
-                          (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL,
-                          (LTE_SchedulingInfo_MBMS_r14_t *) NULL,
-                          (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
-                          (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
-                          (LTE_MBSFN_AreaInfoList_r9_t *) NULL
-                        );
-                      }
-                    } else {        // remove LCHAN from MAC/PHY
-                      AssertFatal(1==0,"Can't handle this yet in DU\n");
-                    }
+                  else if (SRB_configList->list.array[i]->srb_Identity == 2 )  {
+                    ue_context_p->ue_context.Srb2.Active=1;
+                    ue_context_p->ue_context.Srb2.Srb_info.Srb_id=2;
+                    LOG_I(F1AP, "[DU %d] SRB2 is now active\n",ctxt.module_id);
+                  } else {
+                    LOG_W(F1AP, "[DU %d] invalide SRB identity %ld\n",ctxt.module_id,
+                   SRB_configList->list.array[i]->srb_Identity);
                   }
                 }
               }
-            }
-          }
-
-          break;
 
-        case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionRelease:
-          // handle RRCConnectionRelease
-          LOG_I(F1AP, "Received RRCConnectionRelease\n");
-          break;
+              if (DRB_configList != NULL) {
+                for (i = 0; i < DRB_configList->list.count; i++) {  // num max DRB (11-3-8)
+                  if (DRB_configList->list.array[i]) {
+                    drb_id = (int)DRB_configList->list.array[i]->drb_Identity;
+                    LOG_I(F1AP,
+                          "[DU %d] Logical Channel UL-DCCH, Received RRCConnectionReconfiguration for UE rnti %x, reconfiguring DRB %d/LCID %d\n",
+                          ctxt.module_id,
+                          ctxt.rnti,
+                          (int)DRB_configList->list.array[i]->drb_Identity,
+                          (int)*DRB_configList->list.array[i]->logicalChannelIdentity);
 
-        case LTE_DL_DCCH_MessageType__c1_PR_securityModeCommand:
-          LOG_I(F1AP, "Received securityModeCommand\n");
-          break;
+                  if (ue_context_p->ue_context.DRB_active[drb_id] == 0) {
+                    ue_context_p->ue_context.DRB_active[drb_id] = 1;
 
-        case LTE_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry:
-          LOG_I(F1AP, "Received ueCapabilityEnquiry\n");
-          break;
+                    if (DRB_configList->list.array[i]->logicalChannelIdentity) {
+                      DRB2LCHAN[i] = (uint8_t) * DRB_configList->list.array[i]->logicalChannelIdentity;
+                    }
 
-        case LTE_DL_DCCH_MessageType__c1_PR_counterCheck:
-        case LTE_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r10:
-        case LTE_DL_DCCH_MessageType__c1_PR_rnReconfiguration_r10:
-        case LTE_DL_DCCH_MessageType__c1_PR_spare1:
-        case LTE_DL_DCCH_MessageType__c1_PR_spare2:
-        case LTE_DL_DCCH_MessageType__c1_PR_spare3:
-          break;
+                    rrc_mac_config_req_eNB(
+                      ctxt.module_id,
+                      0,0,0,0,0,0,
+                   0,
+                   ue_context_p->ue_context.rnti,
+                   (LTE_BCCH_BCH_Message_t *) NULL,
+                   (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+                   (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+                   physicalConfigDedicated,
+                   (LTE_SCellToAddMod_r10_t *)NULL,
+                   //(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
+                   (LTE_MeasObjectToAddMod_t **) NULL,
+                   mac_MainConfig,
+                   DRB2LCHAN[i],
+                   DRB_configList->list.array[i]->logicalChannelConfig,
+                   measGapConfig,
+                   (LTE_TDD_Config_t *) NULL,
+                   NULL,
+                   (LTE_SchedulingInfoList_t *) NULL,
+                   0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL
+                   , 0, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) NULL,
+                   (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL,
+                         0,
+                         (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL,
+                         (LTE_SchedulingInfo_MBMS_r14_t *) NULL,
+                         (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
+                         (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
+                         (LTE_MBSFN_AreaInfoList_r9_t *) NULL
+                   );
+                  }
 
-        case LTE_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r9:
-          LOG_I(F1AP, "Received ueInformationRequest_r9\n");
+                } else {        // remove LCHAN from MAC/PHY
+                  AssertFatal(1==0,"Can't handle this yet in DU\n");  
+                } 
+        	     }
+        	   }
+           }
+         }
+       }
+	    break;
+      case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionRelease:
+  	    // handle RRCConnectionRelease
+        LOG_I(F1AP, "Received RRCConnectionRelease\n");
+  	    break;
+      case LTE_DL_DCCH_MessageType__c1_PR_securityModeCommand:
+        LOG_I(F1AP, "Received securityModeCommand\n");
+          break; 
+      case LTE_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry:
+        LOG_I(F1AP, "Received ueCapabilityEnquiry\n");
           break;
-
-        case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionResume_r13:
-          LOG_I(F1AP, "Received rrcConnectionResume_r13\n");
-      }
-    }
-  } else if (srb_id == 2) {
+      case LTE_DL_DCCH_MessageType__c1_PR_counterCheck:
+      case LTE_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r10:
+      case LTE_DL_DCCH_MessageType__c1_PR_rnReconfiguration_r10:
+      case LTE_DL_DCCH_MessageType__c1_PR_spare1:
+      case LTE_DL_DCCH_MessageType__c1_PR_spare2:
+      case LTE_DL_DCCH_MessageType__c1_PR_spare3:
+      case LTE_DL_DCCH_MessageType__c1_PR_spare4:
+  	    break;
+      case LTE_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r9:
+        LOG_I(F1AP, "Received ueInformationRequest_r9\n");
+        break;
+      case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionResume_r13:
+        LOG_I(F1AP, "Received rrcConnectionResume_r13\n");
+	   } 
+	 }	
+  }
+  else if (srb_id == 2) {
+    
   }
 
   LOG_I(F1AP, "Received DL RRC Transfer on srb_id %ld\n", srb_id);
   rlc_op_status_t    rlc_status;
   boolean_t          ret             = TRUE;
-  mem_block_t       *pdcp_pdu_p      = NULL;
+  mem_block_t       *pdcp_pdu_p      = NULL; 
   pdcp_pdu_p = get_free_mem_block(rrc_dl_sdu_len, __func__);
 
   //LOG_I(F1AP, "PRRCContainer size %lu:", ie->value.choice.RRCContainer.size);
@@ -505,67 +537,76 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t       instance,
   //for (int i=0;i<rrc_dl_sdu_len;i++) printf("%2x ",pdcp_pdu_p->data[i]);
   //printf("\n");
 
+
   if (pdcp_pdu_p != NULL) {
     memset(pdcp_pdu_p->data, 0, rrc_dl_sdu_len);
     memcpy(&pdcp_pdu_p->data[0], ie->value.choice.RRCContainer.buf, rrc_dl_sdu_len);
-    rlc_status = rlc_data_req(&ctxt
-                              , 1
-                              , MBMS_FLAG_NO
-                              , srb_id
-                              , 0
-                              , 0
-                              , rrc_dl_sdu_len
-                              , pdcp_pdu_p
-                              ,NULL
-                              ,NULL
-                             );
-
-    switch (rlc_status) {
-      case RLC_OP_STATUS_OK:
-        //LOG_I(F1AP, "Data sending request over RLC succeeded!\n");
-        ret=TRUE;
-        break;
-
-      case RLC_OP_STATUS_BAD_PARAMETER:
-        LOG_W(F1AP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
-        ret= FALSE;
-        break;
-
-      case RLC_OP_STATUS_INTERNAL_ERROR:
-        LOG_W(F1AP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
-        ret= FALSE;
-        break;
+      rlc_status = rlc_data_req(&ctxt
+                                , 1
+                                , MBMS_FLAG_NO
+                                , srb_id
+                                , 0
+                                , 0
+                                , rrc_dl_sdu_len
+                                , pdcp_pdu_p
+#ifdef Rel14
+                                ,NULL
+                                ,NULL
+#endif
+                                );
+      switch (rlc_status) {
+        case RLC_OP_STATUS_OK:
+          //LOG_I(F1AP, "Data sending request over RLC succeeded!\n");
+          ret=TRUE;
+          break;
 
-      case RLC_OP_STATUS_OUT_OF_RESSOURCES:
-        LOG_W(F1AP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
-        ret= FALSE;
-        break;
+        case RLC_OP_STATUS_BAD_PARAMETER:
+          LOG_W(F1AP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
+          ret= FALSE;
+          break;
 
-      default:
-        LOG_W(F1AP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
-        ret= FALSE;
-        break;
-    } // switch case
+        case RLC_OP_STATUS_INTERNAL_ERROR:
+          LOG_W(F1AP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
+          ret= FALSE;
+          break;
 
-    return ret;
-  } // if pdcp_pdu_p
+        case RLC_OP_STATUS_OUT_OF_RESSOURCES:
+          LOG_W(F1AP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
+          ret= FALSE;
+          break;
 
+        default:
+          LOG_W(F1AP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
+          ret= FALSE;
+          break;
+      } // switch case
+      return ret; 
+    } // if pdcp_pdu_p
+  
   return 0;
+  
 }
 
-int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, const f1ap_ul_rrc_message_t *msg) {
+int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, 
+                                    const f1ap_ul_rrc_message_t *msg) {
   const rnti_t rnti = msg->rnti;
+
   F1AP_F1AP_PDU_t                pdu;
   F1AP_ULRRCMessageTransfer_t    *out;
   F1AP_ULRRCMessageTransferIEs_t *ie;
+
   uint8_t *buffer = NULL;
   uint32_t len;
+
+
   LOG_I(F1AP, "[DU %d] %s: size %d UE RNTI %x in SRB %d\n",
         instance, __func__, msg->rrc_container_length, rnti, msg->srb_id);
+
   //LOG_I(F1AP, "%s() RRCContainer size %d: ", __func__, msg->rrc_container_length);
   //for (int i = 0;i < msg->rrc_container_length; i++)
   //  printf("%02x ", msg->rrc_container[i]);
   //printf("\n");
+
   /* Create */
   /* 0. Message Type */
   memset(&pdu, 0, sizeof(pdu));
@@ -575,14 +616,18 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, const f1ap_ul_rrc_messa
   pdu.choice.initiatingMessage->criticality   = F1AP_Criticality_ignore;
   pdu.choice.initiatingMessage->value.present = F1AP_InitiatingMessage__value_PR_ULRRCMessageTransfer;
   out = &pdu.choice.initiatingMessage->value.choice.ULRRCMessageTransfer;
+  
   /* mandatory */
   /* c1. GNB_CU_UE_F1AP_ID */
   ie = (F1AP_ULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_ULRRCMessageTransferIEs_t));
   ie->id                             = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
   ie->criticality                    = F1AP_Criticality_reject;
   ie->value.present                  = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID;
+
   ie->value.choice.GNB_CU_UE_F1AP_ID = f1ap_get_cu_ue_f1ap_id(&f1ap_du_inst[instance], rnti);
+
   ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
   /* mandatory */
   /* c2. GNB_DU_UE_F1AP_ID */
   ie = (F1AP_ULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_ULRRCMessageTransferIEs_t));
@@ -591,6 +636,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, const f1ap_ul_rrc_messa
   ie->value.present                  = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID;
   ie->value.choice.GNB_DU_UE_F1AP_ID = f1ap_get_du_ue_f1ap_id(&f1ap_du_inst[instance], rnti);
   ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
   /* mandatory */
   /* c3. SRBID */
   ie = (F1AP_ULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_ULRRCMessageTransferIEs_t));
@@ -599,6 +645,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, const f1ap_ul_rrc_messa
   ie->value.present                 = F1AP_ULRRCMessageTransferIEs__value_PR_SRBID;
   ie->value.choice.SRBID            = msg->srb_id;
   ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
   // issue in here
   /* mandatory */
   /* c4. RRCContainer */
@@ -612,90 +659,111 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, const f1ap_ul_rrc_messa
   ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
 
   if (msg->srb_id == 1 || msg->srb_id == 2) {
-    struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], rnti);
-    LTE_UL_DCCH_Message_t *ul_dcch_msg=NULL;
+    struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], rnti);
+
+   
+    LTE_UL_DCCH_Message_t* ul_dcch_msg=NULL;
     asn_dec_rval_t dec_rval;
     dec_rval = uper_decode(NULL,
-                           &asn_DEF_LTE_UL_DCCH_Message,
-                           (void **)&ul_dcch_msg,
-                           &ie->value.choice.RRCContainer.buf[1], // buf[0] includes the pdcp header
-                           msg->rrc_container_length, 0, 0);
-
-    if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0))
+         &asn_DEF_LTE_UL_DCCH_Message,
+         (void**)&ul_dcch_msg,
+         &ie->value.choice.RRCContainer.buf[1], // buf[0] includes the pdcp header
+         msg->rrc_container_length, 0, 0);
+    
+    if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) 
       LOG_E(F1AP, " Failed to decode UL-DCCH (%zu bytes)\n",dec_rval.consumed);
     else
       LOG_I(F1AP, "Received message: present %d and c1 present %d\n",
             ul_dcch_msg->message.present, ul_dcch_msg->message.choice.c1.present);
 
     if (ul_dcch_msg->message.present == LTE_UL_DCCH_MessageType_PR_c1) {
-      switch (ul_dcch_msg->message.choice.c1.present) {
-        case LTE_UL_DCCH_MessageType__c1_PR_NOTHING:   /* No components present */
-          break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_csfbParametersRequestCDMA2000:
-          break;
+      switch (ul_dcch_msg->message.choice.c1.present) {
+      case LTE_UL_DCCH_MessageType__c1_PR_NOTHING:   /* No components present */
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_measurementReport:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_csfbParametersRequestCDMA2000:
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_rrcConnectionReconfigurationComplete:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_measurementReport:
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_rrcConnectionReestablishmentComplete:
+      case LTE_UL_DCCH_MessageType__c1_PR_rrcConnectionReconfigurationComplete:
+        LOG_I(F1AP, "[MSG] RRC UL rrcConnectionReconfigurationComplete\n");
+        
+        /* CDRX: activated when RRC Connection Reconfiguration Complete is received */
+        int UE_id_mac = find_UE_id(instance, rnti);
+        
+        if (UE_id_mac == -1) {
+          LOG_E(F1AP, "Can't find UE_id(MAC) of UE rnti %x\n", rnti);
           break;
+        }
+        
+        UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[instance]->UE_list.UE_sched_ctrl[UE_id_mac]);
+        
+        if (UE_scheduling_control->cdrx_waiting_ack == TRUE) {
+          UE_scheduling_control->cdrx_waiting_ack = FALSE;
+          UE_scheduling_control->cdrx_configured = TRUE; // Set to TRUE when RRC Connection Reconfiguration Complete is received
+          LOG_I(F1AP, "CDRX configuration activated after RRC Connection Reconfiguration Complete reception\n");
+        }
+        /* End of CDRX processing */
+        
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_rrcConnectionSetupComplete:
-          LOG_I(F1AP, "[MSG] RRC UL rrcConnectionSetupComplete \n");
+      case LTE_UL_DCCH_MessageType__c1_PR_rrcConnectionReestablishmentComplete:
+        break;
 
-          if(!ue_context_p) {
-            LOG_E(F1AP, "Did not find the UE context associated with UE RNTOI %x, ue_context_p is NULL\n", rnti);
-          } else {
-            LOG_I(F1AP, "Processing RRCConnectionSetupComplete UE %x\n", rnti);
-            ue_context_p->ue_context.Status = RRC_CONNECTED;
-          }
+      case LTE_UL_DCCH_MessageType__c1_PR_rrcConnectionSetupComplete:
+        LOG_I(F1AP, "[MSG] RRC UL rrcConnectionSetupComplete \n");
+        
+        if(!ue_context_p){
+          LOG_E(F1AP, "Did not find the UE context associated with UE RNTOI %x, ue_context_p is NULL\n", rnti);
 
-          break;
+        } else {
+          LOG_I(F1AP, "Processing RRCConnectionSetupComplete UE %x\n", rnti);
+          ue_context_p->ue_context.Status = RRC_CONNECTED;
+        }
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_securityModeComplete:
-          LOG_I(F1AP, "[MSG] RRC securityModeComplete \n");
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_securityModeComplete:
+        LOG_I(F1AP, "[MSG] RRC securityModeComplete \n");
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_securityModeFailure:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_securityModeFailure:
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation:
-          LOG_I(F1AP, "[MSG] RRC ueCapabilityInformation \n");
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation:
+        LOG_I(F1AP, "[MSG] RRC ueCapabilityInformation \n");
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_ulHandoverPreparationTransfer:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_ulHandoverPreparationTransfer:
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
-          LOG_I(F1AP,"[MSG] RRC UL Information Transfer \n");
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
+        LOG_I(F1AP,"[MSG] RRC UL Information Transfer \n");
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_counterCheckResponse:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_counterCheckResponse:
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_ueInformationResponse_r9:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_ueInformationResponse_r9:
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_proximityIndication_r9:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_proximityIndication_r9:
+       break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_rnReconfigurationComplete_r10:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_rnReconfigurationComplete_r10:
+        break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10:
+       break;
 
-        case LTE_UL_DCCH_MessageType__c1_PR_interFreqRSTDMeasurementIndication_r10:
-          break;
+      case LTE_UL_DCCH_MessageType__c1_PR_interFreqRSTDMeasurementIndication_r10:
+       break;
       }
     }
   }
-
-  /* encode */
+    /* encode */
   if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
     LOG_E(F1AP, "Failed to encode F1 setup request\n");
     return -1;
@@ -708,14 +776,15 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, const f1ap_ul_rrc_messa
 
 /*  UL RRC Message Transfer */
 int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t     module_idP,
-    int             CC_idP,
-    int             UE_id,
-    rnti_t          rntiP,
-    const uint8_t   *sduP,
-    sdu_size_t      sdu_lenP) {
+                                            int             CC_idP,
+                                            int             UE_id,
+                                            rnti_t          rntiP,
+                                            const uint8_t   *sduP,
+                                            sdu_size_t      sdu_lenP) {
   F1AP_F1AP_PDU_t                       pdu;
   F1AP_InitialULRRCMessageTransfer_t    *out;
   F1AP_InitialULRRCMessageTransferIEs_t *ie;
+
   uint8_t  *buffer;
   uint32_t  len;
   int f1ap_uid = f1ap_add_ue (&f1ap_du_inst[module_idP], module_idP, CC_idP,UE_id, rntiP);
@@ -734,6 +803,8 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t     module_idP,
   pdu.choice.initiatingMessage->criticality   = F1AP_Criticality_ignore;
   pdu.choice.initiatingMessage->value.present = F1AP_InitiatingMessage__value_PR_InitialULRRCMessageTransfer;
   out = &pdu.choice.initiatingMessage->value.choice.InitialULRRCMessageTransfer;
+  
+
   /* mandatory */
   /* c1. GNB_DU_UE_F1AP_ID */
   ie = (F1AP_InitialULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_InitialULRRCMessageTransferIEs_t));
@@ -742,19 +813,23 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t     module_idP,
   ie->value.present                  = F1AP_InitialULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID;
   ie->value.choice.GNB_DU_UE_F1AP_ID = f1ap_du_inst[module_idP].f1ap_ue[f1ap_uid].du_ue_f1ap_id;
   ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
   /* mandatory */
   /* c2. NRCGI */
   ie = (F1AP_InitialULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_InitialULRRCMessageTransferIEs_t));
   ie->id                             = F1AP_ProtocolIE_ID_id_NRCGI;
   ie->criticality                    = F1AP_Criticality_reject;
   ie->value.present                  = F1AP_InitialULRRCMessageTransferIEs__value_PR_NRCGI;
+
   F1AP_NRCGI_t nRCGI;
   memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t));
   MCC_MNC_TO_PLMNID(f1ap_du_data->mcc[0], f1ap_du_data->mnc[0], f1ap_du_data->mnc_digit_length[0],
-                    &nRCGI.pLMN_Identity);
+                                         &nRCGI.pLMN_Identity);
   NR_CELL_ID_TO_BIT_STRING(f1ap_du_data->nr_cellid[0], &nRCGI.nRCellIdentity);
   ie->value.choice.NRCGI = nRCGI;
+
   ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
   /* mandatory */
   /* c3. C_RNTI */  // 16
   ie = (F1AP_InitialULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_InitialULRRCMessageTransferIEs_t));
@@ -763,6 +838,7 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t     module_idP,
   ie->value.present                  = F1AP_InitialULRRCMessageTransferIEs__value_PR_C_RNTI;
   C_RNTI_TO_BIT_STRING(rntiP, &ie->value.choice.C_RNTI);
   ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
   /* mandatory */
   /* c4. RRCContainer */
   ie = (F1AP_InitialULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_InitialULRRCMessageTransferIEs_t));
@@ -780,36 +856,32 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t     module_idP,
     ie->criticality                    = F1AP_Criticality_reject;
     ie->value.present                  = F1AP_InitialULRRCMessageTransferIEs__value_PR_DUtoCURRCContainer;
     OCTET_STRING_fromBuf(&ie->value.choice.DUtoCURRCContainer, "dummy_val",
-                         strlen("dummy_val"));
+                       strlen("dummy_val"));
     ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
   }
 
-  /* encode */
+    /* encode */
   if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
     LOG_E(F1AP, "Failed to encode F1 setup request\n");
     return -1;
   }
 
-  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_allocate_new_UE_context(RC.rrc[module_idP]);
-
-  ue_context_p->ue_id_rnti                    = rntiP;
 
+  struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_allocate_new_UE_context(RC.rrc[module_idP]);
+  ue_context_p->ue_id_rnti                    = rntiP; 
   ue_context_p->ue_context.rnti               = rntiP;
-
   ue_context_p->ue_context.random_ue_identity = rntiP;
-
   ue_context_p->ue_context.Srb0.Active        = 1;
-
   RB_INSERT(rrc_ue_tree_s, &RC.rrc[module_idP]->rrc_ue_head, ue_context_p);
-
   du_f1ap_itti_send_sctp_data_req(module_idP, f1ap_du_data->assoc_id, buffer, len,  f1ap_du_data->default_sctp_stream_id);
 
   return 0;
 }
-
+    
 
 void init_f1ap_du_ue_inst (void) {
-  memset(f1ap_du_inst, 0, sizeof(f1ap_du_inst));
+
+   memset(f1ap_du_inst, 0, sizeof(f1ap_du_inst));
 }
 
 
diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c
index d287e1e5bf7d5f4cadab48b590225f106ca75aea..566391ac7ad1555e56ccc11aea6bb69d6e8ac48e 100644
--- a/openair2/F1AP/f1ap_du_task.c
+++ b/openair2/F1AP/f1ap_du_task.c
@@ -175,7 +175,7 @@ void *F1AP_DU_task(void *arg) {
                                     &received_msg->ittiMsg.sctp_data_ind);
         break;
 
-     case F1AP_UL_RRC_MESSAGE: // from rrc
+     case F1AP_UL_RRC_MESSAGE: // to rrc
         LOG_I(F1AP, "DU Task Received F1AP_UL_RRC_MESSAGE\n");
         DU_send_UL_RRC_MESSAGE_TRANSFER(ITTI_MESSAGE_GET_INSTANCE(received_msg),
                                         &F1AP_UL_RRC_MESSAGE(received_msg));
diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c
index d503a37d8255de55e7206bc66c39b8fc23585f5b..7eb323abab59fbcaa215e28de8c9323fc6446f56 100644
--- a/openair2/LAYER2/MAC/config.c
+++ b/openair2/LAYER2/MAC/config.c
@@ -49,6 +49,7 @@
 #include "LTE_MBSFN-AreaInfoList-r9.h"
 #include "LTE_MBSFN-AreaInfo-r9.h"
 #include "LTE_MBSFN-SubframeConfigList.h"
+#include "LTE_MBSFN-SubframeConfig.h"
 #include "LTE_PMCH-InfoList-r9.h"
 
 
@@ -610,6 +611,123 @@ config_sib2(int Mod_idP,
   }
 }
 
+void
+config_sib2_mbsfn_part( int Mod_idP,
+              int CC_idP,
+            struct LTE_MBSFN_SubframeConfigList  *mbsfn_SubframeConfigListP) {
+
+  //LTE_DL_FRAME_PARMS *fp = &RC.eNB[Mod_idP][CC_idP]->frame_parms;
+  //int i;
+  //if(mbsfn_SubframeConfigListP != NULL) {
+  //  fp->num_MBSFN_config = mbsfn_SubframeConfigListP->list.count;
+
+  //  for(i = 0; i < mbsfn_SubframeConfigListP->list.count; i++) {
+  //    fp->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigListP->list.array[i]->radioframeAllocationPeriod;
+  //    fp->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigListP->list.array[i]->radioframeAllocationOffset;
+
+  //    if (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {
+  //      fp->MBSFN_config[i].fourFrames_flag = 0;
+  //      fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[0];  // 6-bit subframe configuration
+  //      LOG_I (PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is  %d\n", i, fp->MBSFN_config[i].mbsfn_SubframeConfig);
+  //    } else if (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) {       // 24-bit subframe configuration
+  //      fp->MBSFN_config[i].fourFrames_flag = 1;
+  //      fp->MBSFN_config[i].mbsfn_SubframeConfig =
+  //        mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]|
+  //        (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)|
+  //        (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]<<16);
+
+  //      LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is  %x\n", i,
+  //            fp->MBSFN_config[i].mbsfn_SubframeConfig);
+  //    }
+  //  }
+
+  //} else
+  //  fp->num_MBSFN_config = 0;
+
+   PHY_Config_t phycfg;
+   phycfg.Mod_id = Mod_idP;
+   phycfg.CC_id  = CC_idP;
+   phycfg.cfg    = &RC.mac[Mod_idP]->config[CC_idP];
+  int i;
+
+  if(mbsfn_SubframeConfigListP != NULL) {
+    phycfg.cfg->embms_mbsfn_config.num_mbsfn_config = mbsfn_SubframeConfigListP->list.count;
+
+    for(i = 0; i < mbsfn_SubframeConfigListP->list.count; i++) {
+       phycfg.cfg->embms_mbsfn_config.radioframe_allocation_period[i] = mbsfn_SubframeConfigListP->list.array[i]->radioframeAllocationPeriod;
+       phycfg.cfg->embms_mbsfn_config.radioframe_allocation_offset[i] = mbsfn_SubframeConfigListP->list.array[i]->radioframeAllocationOffset;
+
+      if (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {
+        phycfg.cfg->embms_mbsfn_config.fourframes_flag[i] = 0;
+        phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i] = mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[0];  // 6-bit subframe configuration
+        LOG_I (MAC, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is  %d\n", i, phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i]);
+      } else if (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) {       // 24-bit subframe configuration
+        phycfg.cfg->embms_mbsfn_config.fourframes_flag[i]  = 1;
+        phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i] =
+          mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]|
+          (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)|
+          (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]<<16);
+
+        LOG_I(MAC, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is  %x\n", i,
+              phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i]);
+      }
+    }
+    phycfg.cfg->num_tlv++;
+
+  } else{
+    phycfg.cfg->embms_mbsfn_config.num_mbsfn_config = 0;
+    phycfg.cfg->num_tlv++;
+  }
+
+  phycfg.cfg->embms_mbsfn_config.tl.tag = NFAPI_EMBMS_MBSFN_CONFIG_TAG;
+
+   if (RC.mac[Mod_idP]->if_inst->PHY_config_update_sib2_req) RC.mac[Mod_idP]->if_inst->PHY_config_update_sib2_req(&phycfg);
+}
+
+void
+config_sib13( int Mod_id,
+              int CC_id,
+              int mbsfn_Area_idx,
+             long mbsfn_AreaId_r9){
+
+  //nfapi_config_request_t *cfg = &RC.mac[Mod_id]->config[CC_id];
+
+  //work around until PHY_config_re "update" mechanisms get defined
+//  LTE_DL_FRAME_PARMS *fp = &RC.eNB[Mod_id][CC_id]->frame_parms;
+//  LOG_I (MAC, "[eNB%d] Applying MBSFN_Area_id %ld for index %d\n", Mod_id, mbsfn_AreaId_r9, mbsfn_Area_idx);
+//
+//  AssertFatal(mbsfn_Area_idx == 0, "Fix me: only called when mbsfn_Area_idx == 0\n");
+//  if (mbsfn_Area_idx == 0) {
+//    fp->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9;
+//    LOG_I(MAC,"Fix me: only called when mbsfn_Area_idx == 0)\n");
+//  }
+//  lte_gold_mbsfn (fp, RC.eNB[Mod_id][CC_id]->lte_gold_mbsfn_table, fp->Nid_cell_mbsfn);
+//
+//#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+//  lte_gold_mbsfn_khz_1dot25 (fp, RC.eNB[Mod_id][CC_id]->lte_gold_mbsfn_khz_1dot25_table, fp->Nid_cell_mbsfn);
+//#endif
+//
+   PHY_Config_t phycfg;
+   phycfg.Mod_id = Mod_id;
+   phycfg.CC_id  = CC_id;
+   phycfg.cfg    = &RC.mac[Mod_id]->config[CC_id];
+
+   phycfg.cfg->embms_sib13_config.mbsfn_area_idx.value =  (uint8_t)mbsfn_Area_idx;
+   phycfg.cfg->embms_sib13_config.mbsfn_area_idx.tl.tag =  NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDX_TAG;
+   phycfg.cfg->num_tlv++;
+   phycfg.cfg->embms_sib13_config.mbsfn_area_id_r9.value = (uint32_t)mbsfn_AreaId_r9;
+   phycfg.cfg->embms_sib13_config.mbsfn_area_id_r9.tl.tag = NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDR9_TAG;
+   phycfg.cfg->num_tlv++;
+
+   if (RC.mac[Mod_id]->if_inst->PHY_config_update_sib13_req) RC.mac[Mod_id]->if_inst->PHY_config_update_sib13_req(&phycfg);
+
+//    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT);
+
+}
+
+
+
+
 void
 config_dedicated(int Mod_idP,
                  int CC_idP,
@@ -820,6 +938,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP,
     }
 
     RC.mac[Mod_idP]->common_channels[0].MBMS_flag = MBMS_Flag;
+    config_sib2_mbsfn_part(Mod_idP,0,mbsfn_SubframeConfigList);
   }
 
   if (nonMBSFN_SubframeConfig != NULL) {
@@ -856,6 +975,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP,
       LOG_I(MAC,"[eNB %d][CONFIG] MBSFN_AreaInfo[%d]: MCCH Repetition Period = %ld\n", Mod_idP,i,
             RC.mac[Mod_idP]->common_channels[0].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_RepetitionPeriod_r9);
       //      config_sib13(Mod_idP,0,i,RC.mac[Mod_idP]->common_channels[0].mbsfn_AreaInfo[i]->mbsfn_AreaId_r9);
+	config_sib13(Mod_idP,0,i,RC.mac[Mod_idP]->common_channels[0].mbsfn_AreaInfo[i]->mbsfn_AreaId_r9);
     }
   }
 
@@ -885,6 +1005,10 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP,
       LOG_I(MAC, "PMCH[%d] Number of session (MTCH) is: %d\n", i,
             RC.mac[Mod_idP]->common_channels[0].
             mbms_SessionList[i]->list.count);
+       for(int ii=0; ii < RC.mac[Mod_idP]->common_channels[0].mbms_SessionList[i]->list.count;ii++){
+            LOG_I(MAC, "PMCH[%d] MBMS Session[%d] is: %lu\n", i,ii,
+               RC.mac[Mod_idP]->common_channels[0].mbms_SessionList[i]->list.array[ii]->logicalChannelIdentity_r9);
+       }
     }
   }
 
@@ -920,55 +1044,53 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP,
 
 //-----------------------------------------------------------------------------
 /*
-* Configure local DRX timers and thresholds following the drx_configuration input
+* Configure local CDRX timers and thresholds following the drx_configuration input
 */
-void eNB_Config_Local_DRX(
-  module_id_t Mod_id,
-  rnti_t rnti,
-  LTE_DRX_Config_t *const drx_Configuration
-)
+void eNB_Config_Local_DRX(instance_t Mod_id,
+                          rrc_mac_drx_config_req_t *rrc_mac_drx_config_req)
 //-----------------------------------------------------------------------------
 {
   UE_list_t *UE_list_mac = NULL;
-  int UE_id = -1;
   UE_sched_ctrl_t *UE_scheduling_control = NULL;
+  int UE_id = -1;
+  
+  rnti_t rnti = rrc_mac_drx_config_req->rnti;
+  LTE_DRX_Config_t *const drx_Configuration = rrc_mac_drx_config_req->drx_Configuration;
+
   UE_list_mac = &(RC.mac[Mod_id]->UE_list);
   UE_id = find_UE_id(Mod_id, rnti);
 
   /* Check UE_id */
   if (UE_id == -1) {
-    LOG_E(MAC, "%s:%d:%s: ERROR, UE_id == -1\n",
-          __FILE__,
-          __LINE__,
-          __FUNCTION__);
+    LOG_E(MAC, "[eNB_Config_Local_DRX] UE_id == -1\n");
     return;
   }
 
   /* Get struct to modify */
   UE_scheduling_control = &(UE_list_mac->UE_sched_ctrl[UE_id]);
+  UE_scheduling_control->cdrx_configured = FALSE; // will be set to true when no error
 
   /* Check drx_Configuration */
   if (drx_Configuration == NULL) {
-    LOG_I(MAC, "drx_Configuration parameter is NULL, cannot configure local UE parameters\n");
-    UE_scheduling_control->cdrx_configured = FALSE;
+    LOG_W(MAC, "[eNB_Config_Local_DRX] drx_Configuration parameter is NULL, cannot configure local UE parameters for CDRX\n");
     return;
   }
 
   /* Check if drx config present */
   if (drx_Configuration->present != LTE_DRX_Config_PR_setup) {
-    LOG_I(MAC, "No drx_Configuration present, don't configure local UE parameters\n");
-    UE_scheduling_control->cdrx_configured = FALSE;
+    LOG_I(MAC, "[eNB_Config_Local_DRX] No drx_Configuration present, don't configure local UE parameters for CDRX\n");
     return;
   }
 
-  /* Modify scheduling control structure according to DRX configuration: doesn't support every configurations! */
-  UE_scheduling_control->cdrx_configured = FALSE; // will be set to true when ACK is received
-  UE_scheduling_control->cdrx_waiting_ack = TRUE; // set to true first, waiting for the UE to configure CDRX on its side
+  /* Modify scheduling control structure according to DRX configuration: doesn't support every configurations! */  
+  UE_scheduling_control->cdrx_configured = FALSE; // will be set to true when receiving RRC Reconfiguration Complete
+  UE_scheduling_control->cdrx_waiting_ack = TRUE; // waiting for RRC Reconfiguration Complete message
   UE_scheduling_control->in_active_time = FALSE;
   UE_scheduling_control->dci0_ongoing_timer = 0;
   UE_scheduling_control->on_duration_timer = 0;
+  struct LTE_DRX_Config__setup *choiceSetup = &drx_Configuration->choice.setup;
 
-  switch (drx_Configuration->choice.setup.onDurationTimer) {
+  switch (choiceSetup->onDurationTimer) {
     case 0:
       UE_scheduling_control->on_duration_timer_thres = 1;
       break;
@@ -1034,13 +1156,13 @@ void eNB_Config_Local_DRX(
       break;
 
     default:
-      LOG_E(MAC, "Error in local DRX configuration, the on duration timer value specified is unknown\n");
+      LOG_E(MAC, "[eNB_Config_Local_DRX] Error in local DRX configuration, the on duration timer value specified is unknown\n");
       break;
   }
 
   UE_scheduling_control->drx_inactivity_timer = 0;
 
-  switch (drx_Configuration->choice.setup.drx_InactivityTimer) {
+  switch (choiceSetup->drx_InactivityTimer) {
     case 0:
       UE_scheduling_control->drx_inactivity_timer_thres = 1;
       break;
@@ -1134,11 +1256,11 @@ void eNB_Config_Local_DRX(
       break;
 
     default:
-      LOG_E(MAC, "Error in local DRX configuration, the drx inactivity timer value specified is unknown\n");
+      LOG_E(MAC, "[eNB_Config_Local_DRX] Error in local DRX configuration, the drx inactivity timer value specified is unknown\n");
       break;
   }
 
-  if (drx_Configuration->choice.setup.shortDRX == NULL) {
+  if (choiceSetup->shortDRX == NULL) {
     UE_scheduling_control->in_short_drx_cycle = FALSE;
     UE_scheduling_control->drx_shortCycle_timer_value = 0;
     UE_scheduling_control->short_drx_cycle_duration = 0;
@@ -1146,9 +1268,9 @@ void eNB_Config_Local_DRX(
     UE_scheduling_control->drx_shortCycle_timer_thres = -1;
   } else {
     UE_scheduling_control->in_short_drx_cycle = FALSE;
-    UE_scheduling_control->drx_shortCycle_timer_value = (uint8_t) drx_Configuration->choice.setup.shortDRX->drxShortCycleTimer;
+    UE_scheduling_control->drx_shortCycle_timer_value = (uint8_t) choiceSetup->shortDRX->drxShortCycleTimer;
 
-    switch (drx_Configuration->choice.setup.shortDRX->shortDRX_Cycle) {
+    switch (choiceSetup->shortDRX->shortDRX_Cycle) {
       case 0:
         UE_scheduling_control->short_drx_cycle_duration = 2;
         break;
@@ -1214,7 +1336,7 @@ void eNB_Config_Local_DRX(
         break;
 
       default:
-        LOG_E(MAC, "Error in local DRX configuration, the short drx timer value specified is unknown\n");
+        LOG_E(MAC, "[eNB_Config_Local_DRX] Error in local DRX configuration, the short drx timer value specified is unknown\n");
         break;
     }
 
@@ -1225,95 +1347,95 @@ void eNB_Config_Local_DRX(
   UE_scheduling_control->in_long_drx_cycle = FALSE;
   UE_scheduling_control->drx_longCycle_timer = 0;
 
-  switch (drx_Configuration->choice.setup.longDRX_CycleStartOffset.present) {
-    case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf10:
+  switch (choiceSetup->longDRX_CycleStartOffset.present) {
+    case 	LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf10:
       UE_scheduling_control->drx_longCycle_timer_thres = 10;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf10;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf10;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf20:
       UE_scheduling_control->drx_longCycle_timer_thres = 20;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf20;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf20;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf32:
       UE_scheduling_control->drx_longCycle_timer_thres = 32;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf32;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf32;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf40:
       UE_scheduling_control->drx_longCycle_timer_thres = 40;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf40;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf40;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf64:
       UE_scheduling_control->drx_longCycle_timer_thres = 64;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf64;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf64;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf80:
       UE_scheduling_control->drx_longCycle_timer_thres = 80;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf80;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf80;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf128:
       UE_scheduling_control->drx_longCycle_timer_thres = 128;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf128;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf128;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf160:
       UE_scheduling_control->drx_longCycle_timer_thres = 160;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf160;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf160;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf256:
       UE_scheduling_control->drx_longCycle_timer_thres = 256;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf256;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf256;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf320:
       UE_scheduling_control->drx_longCycle_timer_thres = 320;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf320;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf320;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf512:
       UE_scheduling_control->drx_longCycle_timer_thres = 512;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf512;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf512;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf640:
       UE_scheduling_control->drx_longCycle_timer_thres = 640;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf640;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf640;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf1024:
       UE_scheduling_control->drx_longCycle_timer_thres = 1024;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf1024;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf1024;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf1280:
       UE_scheduling_control->drx_longCycle_timer_thres = 1280;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf1280;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf1280;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf2048:
       UE_scheduling_control->drx_longCycle_timer_thres = 2048;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf2048;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf2048;
       break;
 
     case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf2560:
       UE_scheduling_control->drx_longCycle_timer_thres = 2560;
-      UE_scheduling_control->drx_start_offset = (uint16_t) drx_Configuration->choice.setup.longDRX_CycleStartOffset.choice.sf2560;
+      UE_scheduling_control->drx_start_offset = (uint16_t) choiceSetup->longDRX_CycleStartOffset.choice.sf2560;
       break;
 
     default:
-      LOG_E(MAC, "Invalid long_DRX value in DRX local configuration\n");
+      LOG_E(MAC, "[eNB_Config_Local_DRX] Invalid long_DRX value in DRX local configuration\n");
       break;
   }
 
   memset(UE_scheduling_control->drx_retransmission_timer, 0, sizeof(UE_scheduling_control->drx_retransmission_timer));
 
-  switch (drx_Configuration->choice.setup.drx_RetransmissionTimer) {
+  switch (choiceSetup->drx_RetransmissionTimer) {
     case 0:
       memset(UE_scheduling_control->drx_retransmission_timer_thres, 1, sizeof(UE_scheduling_control->drx_retransmission_timer_thres));
       break;
@@ -1347,7 +1469,7 @@ void eNB_Config_Local_DRX(
       break;
 
     default:
-      LOG_E(MAC, "Error in local DRX configuration, the drx retransmission timer value specified is unknown\n");
+      LOG_E(MAC, "[eNB_Config_Local_DRX] Error in local DRX configuration, the drx retransmission timer value specified is unknown\n");
       break;
   }
 }
diff --git a/openair2/LAYER2/MAC/config_ue.c b/openair2/LAYER2/MAC/config_ue.c
index a0233a5e428f0ea5f223fb30093f293e39ef2f79..897afbf62bc960dc73070aaef2e94715de4971b9 100644
--- a/openair2/LAYER2/MAC/config_ue.c
+++ b/openair2/LAYER2/MAC/config_ue.c
@@ -140,7 +140,7 @@ rrc_mac_config_req_ue(module_id_t Mod_idP,
     phy_config_sib2_ue(Mod_idP, 0, eNB_index,
                        radioResourceConfigCommon, ul_CarrierFreq,
                        ul_Bandwidth, additionalSpectrumEmission,
-                       mbsfn_SubframeConfigList);
+                       NULL/*mbsfn_SubframeConfigList*/);
   }
 
   // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup
@@ -469,6 +469,9 @@ rrc_mac_config_req_ue(module_id_t Mod_idP,
   }
 
   if (mbsfn_SubframeConfigList != NULL) {
+    phy_config_mbsfn_list_ue(Mod_idP, 0,
+                       mbsfn_SubframeConfigList);
+
     LOG_I(MAC,
           "[UE %d][CONFIG] Received %d subframe allocation pattern for MBSFN\n",
           Mod_idP, mbsfn_SubframeConfigList->list.count);
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index 2fa88dcde669d90d6009f419d1c4ea99523dbc48..05660b727e9f6c737b7e9a38e811c994a1871979 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -320,7 +320,7 @@ typedef struct {
 /*!\brief DTCH DRB1  logical channel */
 #define DTCH 3 // LCID
 /*!\brief MCCH logical channel */
-#define MCCH 4
+#define MCCH 11
 /*!\brief MTCH logical channel */
 #define MTCH 1
 // DLSCH LCHAN ID
diff --git a/openair2/LAYER2/MAC/defs_NB_IoT.h b/openair2/LAYER2/MAC/defs_NB_IoT.h
index 0d7dd7d2c06788e6af8089cb9b5e277c434f3412..517f01d1b932be33b345681118ed69a6ee5f2150 100644
--- a/openair2/LAYER2/MAC/defs_NB_IoT.h
+++ b/openair2/LAYER2/MAC/defs_NB_IoT.h
@@ -64,7 +64,8 @@
 #define DTCH 3 // LCID
 /*!\brief MCCH logical channel */
 //#define MCCH 4 
-#define MCCH 62
+//#define MCCH 62
+#define MCCH 11
 /*!\brief MTCH logical channel */
 #define MTCH 1 
 // DLSCH LCHAN ID
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index e6484aba3efd40eebb1b00cd4f53d4fcc91c01c0..365993337864bd1035a9891239aa91ac2475aef9 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -899,13 +899,18 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
 #if (!defined(PRE_SCD_THREAD))
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP, module_idP);
   pdcp_run(&ctxt);
+  pdcp_mbms_run(&ctxt);
   rrc_rx_tx(&ctxt, CC_id);
 #endif
 
   for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
     if (cc[CC_id].MBMS_flag > 0) {
       start_meas(&RC.mac[module_idP]->schedule_mch);
-      mbsfn_status[CC_id] = schedule_MBMS(module_idP, CC_id, frameP, subframeP);
+      int(*schedule_mch)(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_frame_t subframe) = NULL;
+      schedule_mch = schedule_MBMS_NFAPI;
+      if(schedule_mch){
+      	mbsfn_status[CC_id] = schedule_mch(module_idP, CC_id, frameP, subframeP);
+      }
       stop_meas(&RC.mac[module_idP]->schedule_mch);
     }
   }
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index c717f8b9019fe47a177832043b31e364c591659d..2a56c61a682489d1640c2e7fd5e8002c0437eafe 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -507,6 +507,13 @@ schedule_ue_spec(module_id_t module_idP,
   rrc_eNB_ue_context_t *ue_contextP = NULL;
   int nb_mac_CC = RC.nb_mac_CC[module_idP];
   long dl_Bandwidth;
+
+  if(is_pmch_subframe(frameP,subframeP,&RC.eNB[module_idP][0]->frame_parms)){
+       //LOG_E(MAC,"Frame[%d] SF:%d This SF should not be allocated\n",frameP,subframeP);
+       return ;
+  }
+
+
   start_meas(&eNB->schedule_dlsch);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,
                                           VCD_FUNCTION_IN);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
index 8d887409e1e27df52bc03bb4a1b5c923dd7638fa..260d8a7417c94d079b67cdc922753ad1c23f57c3 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
@@ -854,6 +854,12 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
 #ifdef DEBUG_eNB_SCHEDULER
   int k;
 #endif
+
+  if(is_pmch_subframe(frameP,subframeP,&RC.eNB[module_idP][0]->frame_parms)){
+       //LOG_E(MAC,"fairRR Frame[%d] SF:%d This SF should not be allocated\n",frameP,subframeP);
+       return;
+  }
+
   start_meas(&eNB->schedule_dlsch);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
   (VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
index 4c667a82799ce6cd2c901e6a077223c7b962e1ff..2d308430a5ebeae5633b438b0ebd1f880a0e6d69 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
@@ -34,6 +34,7 @@
 #include "LAYER2/MAC/mac_proto.h"
 #include "LAYER2/MAC/mac_extern.h"
 #include "common/utils/LOG/log.h"
+#include "nfapi/oai_integration/vendor_ext.h"
 #include "common/utils/LOG/vcd_signal_dumper.h"
 #include "UTIL/OPT/opt.h"
 #include "OCG.h"
@@ -79,690 +80,1598 @@ int8_t get_mbsfn_sf_alloction(module_id_t module_idP, uint8_t CC_id, uint8_t mbs
   }
 }
 
+static uint32_t bytes_in_buffer=0;
+static uint8_t msi_pmch_stop=0;
+//static uint8_t msi_active=0;
+//static uint8_t msi_pmch_stop2=0;
+uint16_t mbms_rab_id = 2047;
+static uint8_t msi_sfs=0;
 
-int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_frame_t subframeP) {
-  int mcch_flag = 0, mtch_flag = 0, msi_flag = 0;
-  int mbsfn_period = 0; // 1<<(RC.mac[module_idP]->mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
-  int mcch_period = 0;  //32<<(RC.mac[module_idP]->mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);
-  int mch_scheduling_period =
-    8 << (RC.mac[module_idP]->common_channels[CC_id].
-          pmch_Config[0]->mch_SchedulingPeriod_r9);
-  unsigned char mcch_sdu_length;
-  unsigned char header_len_mcch = 0, header_len_msi =
-                                    0, header_len_mtch = 0, header_len_mtch_temp =
-                                          0, header_len_mcch_temp = 0, header_len_msi_temp = 0;
-  int ii = 0, msi_pos = 0;
-  int mcch_mcs = -1;
-  uint16_t TBS, j = -1, padding = 0, post_padding = 0;
-  mac_rlc_status_resp_t rlc_status;
-  int num_mtch;
-  int msi_length, i, k;
-  unsigned char sdu_lcids[11], num_sdus = 0, offset = 0;
-  uint16_t sdu_lengths[11], sdu_length_total = 0;
-  unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES];  // check the max value, this is for dlsch only
-  COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id];
-  cc->MCH_pdu.Pdu_size = 0;
-
-  for (i = 0; i < cc->num_active_mbsfn_area; i++) {
-    // assume, that there is always a mapping
-    if ((j = get_mbsfn_sf_alloction(module_idP, CC_id, i)) == -1) {
-      return 0;
-    }
 
-    mbsfn_period =
-      1 << (cc->mbsfn_SubframeConfig[j]->radioframeAllocationPeriod);
-    mcch_period =
-      32 << (cc->mbsfn_AreaInfo[i]->
-             mcch_Config_r9.mcch_RepetitionPeriod_r9);
-    msi_pos = 0;
-    ii = 0;
-    LOG_D(MAC,
-          "[eNB %d] CC_id %d Frame %d subframeP %d : Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d)\n",
-          module_idP, CC_id, frameP, subframeP, i,
-          cc->num_active_mbsfn_area, j, cc->num_sf_allocation_pattern,
-          mbsfn_period, mcch_period);
-
-    switch (cc->mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) {
-      case 0:
-        mcch_mcs = 2;
-        break;
-
-      case 1:
-        mcch_mcs = 7;
-        break;
-
-      case 2:
-        mcch_mcs = 13;
-        break;
-
-      case 3:
-        mcch_mcs = 19;
-        break;
-    }
+//MSI_ELEMENT * ptr =NULL;
 
-    // 1st: Check the MBSFN subframes from SIB2 info (SF allocation pattern i, max 8 non-overlapping patterns exist)
-    if (frameP % mbsfn_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP
-      if (cc->mbsfn_SubframeConfig[j]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {  // one-frameP format
-
-        //  Find the first subframeP in this MCH to transmit MSI
-        if (frameP % mch_scheduling_period ==
-            cc->mbsfn_SubframeConfig[j]->
-            radioframeAllocationOffset) {
-          while (ii == 0) {
-            ii = cc->
-                 mbsfn_SubframeConfig[j]->subframeAllocation.
-                 choice.oneFrame.buf[0] & (0x80 >> msi_pos);
-            msi_pos++;
-          }
-
-          LOG_D(MAC,
-                "[eNB %d] CC_id %d Frame %d subframeP %d : sync area %d sf allocation pattern %d sf alloc %x msi pos is %d \n",
-                module_idP, CC_id, frameP, subframeP, i, j,
-                cc->mbsfn_SubframeConfig[j]->
-                subframeAllocation.choice.oneFrame.buf[0],
-                msi_pos);
-        }
-
-        // Check if the subframeP is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
-        switch (subframeP) {
-          case 1:
-            if (cc->tdd_Config == NULL) {
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_FDD_SF1) ==
-                  MBSFN_FDD_SF1) {
-                if (msi_pos == 1) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_FDD_SF1) ==
-                     MBSFN_FDD_SF1)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            }
-
-            break;
-
-          case 2:
-            if (cc->tdd_Config == NULL) {
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_FDD_SF2) ==
-                  MBSFN_FDD_SF2) {
-                if (msi_pos == 2) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_FDD_SF2) ==
-                     MBSFN_FDD_SF2)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            }
-
-            break;
-
-          case 3:
-            if (cc->tdd_Config != NULL) { // TDD
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_TDD_SF3) ==
-                  MBSFN_TDD_SF3) {
-                if (msi_pos == 1) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_TDD_SF3) ==
-                     MBSFN_TDD_SF3)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            } else {  // FDD
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_FDD_SF3) ==
-                  MBSFN_FDD_SF3) {
-                if (msi_pos == 3) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_FDD_SF3) ==
-                     MBSFN_FDD_SF3)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            }
-
-            break;
-
-          case 4:
-            if (cc->tdd_Config != NULL) {
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_TDD_SF4) ==
-                  MBSFN_TDD_SF4) {
-                if (msi_pos == 2) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_TDD_SF4) ==
-                     MBSFN_TDD_SF4)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            }
-
-            break;
-
-          case 6:
-            if (cc->tdd_Config == NULL) {
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_FDD_SF6) ==
-                  MBSFN_FDD_SF6) {
-                if (msi_pos == 4) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_FDD_SF6) ==
-                     MBSFN_FDD_SF6)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            }
-
-            break;
-
-          case 7:
-            if (cc->tdd_Config != NULL) { // TDD
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_TDD_SF7) ==
-                  MBSFN_TDD_SF7) {
-                if (msi_pos == 3) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_TDD_SF7) ==
-                     MBSFN_TDD_SF7)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            } else {  // FDD
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_FDD_SF7) ==
-                  MBSFN_FDD_SF7) {
-                if (msi_pos == 5) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_FDD_SF7) ==
-                     MBSFN_FDD_SF7)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            }
-
-            break;
-
-          case 8:
-            if (cc->tdd_Config != NULL) { //TDD
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_TDD_SF8) ==
-                  MBSFN_TDD_SF8) {
-                if (msi_pos == 4) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_TDD_SF8) ==
-                     MBSFN_TDD_SF8)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            } else {  // FDD
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_FDD_SF8) ==
-                  MBSFN_FDD_SF8) {
-                if (msi_pos == 6) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_FDD_SF8) ==
-                     MBSFN_FDD_SF8)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            }
-
-            break;
-
-          case 9:
-            if (cc->tdd_Config != NULL) {
-              if ((cc->
-                   mbsfn_SubframeConfig[j]->subframeAllocation.
-                   choice.oneFrame.buf[0] & MBSFN_TDD_SF9) ==
-                  MBSFN_TDD_SF9) {
-                if (msi_pos == 5) {
-                  msi_flag = 1;
-                }
-
-                if ((frameP % mcch_period ==
-                     cc->mbsfn_AreaInfo[i]->
-                     mcch_Config_r9.mcch_Offset_r9)
-                    &&
-                    ((cc->mbsfn_AreaInfo[i]->
-                      mcch_Config_r9.sf_AllocInfo_r9.
-                      buf[0] & MBSFN_TDD_SF9) ==
-                     MBSFN_TDD_SF9)) {
-                  mcch_flag = 1;
-                }
-
-                mtch_flag = 1;
-              }
-            }
-
-            break;
-        }   // end switch
-
-        // sf allocation is non-overlapping
-        if ((msi_flag == 1) || (mcch_flag == 1)
-            || (mtch_flag == 1)) {
-          LOG_D(MAC,
-                "[eNB %d] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n",
-                module_idP, CC_id, frameP, subframeP, i, j,
-                msi_flag, mcch_flag, mtch_flag);
-          break;
-        }
-      } else {    // four-frameP format
-      }
-    }
-  }       // end of for loop
 
-  cc->msi_active = 0;
-  cc->mcch_active = 0;
-  cc->mtch_active = 0;
+int
+schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
+	      sub_frame_t subframeP)
+{
 
-  // Calculate the mcs
-  if ((msi_flag == 1) || (mcch_flag == 1)) {
-    cc->MCH_pdu.mcs = mcch_mcs;
-  } else if (mtch_flag == 1) {  // only MTCH in this subframeP
-    cc->MCH_pdu.mcs = cc->pmch_Config[0]->dataMCS_r9;
-  }
+    nfapi_dl_config_request_body_t *dl_req;
+    //nfapi_dl_config_request_pdu_t *dl_config_pdu;
+    
+    int mcch_flag = 0, mtch_flag = 0, msi_flag = 0;
+    int mbsfn_period = 0;	// 1<<(RC.mac[module_idP]->mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
+    int mcch_period = 0;	//32<<(RC.mac[module_idP]->mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);
+    if(RC.mac[module_idP]->common_channels[CC_id].
+              pmch_Config[0] == NULL )
 
-  // 2nd: Create MSI, get MCCH from RRC and MTCHs from RLC
+	return 0;
 
-  // there is MSI (MCH Scheduling Info)
-  if (msi_flag == 1) {
-    // Create MSI here
-    uint16_t msi_control_element[29], *msi_ptr;
-    msi_ptr = &msi_control_element[0];
-    ((MSI_ELEMENT *) msi_ptr)->lcid = MCCH_LCHANID; //MCCH
+   		
 
-    if (mcch_flag == 1) {
-      ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0;
-      ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0;
-    } else {    // no mcch for this MSP
-      ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7; // stop value is 2047
-      ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xff;
-    }
 
-    msi_ptr += sizeof(MSI_ELEMENT);
-    //Header for MTCHs
-    num_mtch = cc->mbms_SessionList[0]->list.count;
+    int mch_scheduling_period =
+	8 << (RC.mac[module_idP]->common_channels[CC_id].
+	      pmch_Config[0]->mch_SchedulingPeriod_r9);
+    unsigned char mcch_sdu_length;
+    unsigned char header_len_mcch = 0, header_len_msi =
+	0, header_len_mtch = 0, header_len_mtch_temp =
+	0, header_len_mcch_temp = 0, header_len_msi_temp = 0;
+    int ii = 0, msi_pos = 0;
+    int mcch_mcs = -1;
+    uint16_t TBS, j = -1, padding = 0, post_padding = 0;
+    mac_rlc_status_resp_t rlc_status;
+    int num_mtch;
+    int msi_length, i, k;
+    //uint8_t l =0;
+    unsigned char sdu_lcids[11], num_sdus = 0, offset = 0;
+    uint16_t sdu_lengths[11], sdu_length_total = 0;
+    unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES];	// check the max value, this is for dlsch only
 
-    for (k = 0; k < num_mtch; k++) {  // loop for all session in this MCH (MCH[0]) at this moment
-      ((MSI_ELEMENT *) msi_ptr)->lcid = cc->mbms_SessionList[0]->list.array[k]->logicalChannelIdentity_r9;  //mtch_lcid;
-      ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; // last subframeP of this mtch (only one mtch now)
-      ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xB;
-      msi_ptr += sizeof(MSI_ELEMENT);
-    }
+    COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id];
 
-    msi_length = msi_ptr - msi_control_element;
+    cc->MCH_pdu.Pdu_size = 0;
 
-    if (msi_length < 128) {
-      header_len_msi = 2;
-    } else {
-      header_len_msi = 3;
+    for (i = 0; i < cc->num_active_mbsfn_area; i++) {
+	// assume, that there is always a mapping
+	if ((j = get_mbsfn_sf_alloction(module_idP, CC_id, i)) == -1) {
+	    return 0;
+	}
+
+	mbsfn_period =
+	    1 << (cc->mbsfn_SubframeConfig[j]->radioframeAllocationPeriod);
+	mcch_period =
+	    32 << (cc->mbsfn_AreaInfo[i]->
+		   mcch_Config_r9.mcch_RepetitionPeriod_r9);
+	msi_pos = 0;
+	ii = 0;
+	LOG_D(MAC,
+	      "[eNB %d] CC_id %d Frame %d subframeP %d : Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d)\n",
+	      module_idP, CC_id, frameP, subframeP, i,
+	      cc->num_active_mbsfn_area, j, cc->num_sf_allocation_pattern,
+	      mbsfn_period, mcch_period);
+
+
+	switch (cc->mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) {
+	case 0:
+	    mcch_mcs = 2;
+	    break;
+
+	case 1:
+	    mcch_mcs = 7;
+	    break;
+
+	case 2:
+	    mcch_mcs = 13;
+	    break;
+
+	case 3:
+	    mcch_mcs = 19;
+	    break;
+	}
+
+	// 1st: Check the MBSFN subframes from SIB2 info (SF allocation pattern i, max 8 non-overlapping patterns exist)
+	if (frameP % mbsfn_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset) {	// MBSFN frameP
+	    if (cc->mbsfn_SubframeConfig[j]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {	// one-frameP format
+
+		//  Find the first subframeP in this MCH to transmit MSI
+		if (frameP % mch_scheduling_period ==
+		    cc->mbsfn_SubframeConfig[j]->
+		    radioframeAllocationOffset) {
+		    while (ii == 0) {
+			ii = cc->
+			    mbsfn_SubframeConfig[j]->subframeAllocation.
+			    choice.oneFrame.buf[0] & (0x80 >> msi_pos);
+			msi_pos++;
+		    }
+
+		    LOG_D(MAC,
+			  "[eNB %d] CC_id %d Frame %d subframeP %d : sync area %d sf allocation pattern %d sf alloc %x msi pos is %d \n",
+			  module_idP, CC_id, frameP, subframeP, i, j,
+			  cc->mbsfn_SubframeConfig[j]->
+			  subframeAllocation.choice.oneFrame.buf[0],
+			  msi_pos);
+		}
+		// Check if the subframeP is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
+		switch (subframeP) {
+		case 1:
+		    if (cc->tdd_Config == NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF1) ==
+			    MBSFN_FDD_SF1) {
+			    if (msi_pos == 1) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF1) ==
+				 MBSFN_FDD_SF1)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 2:
+		    if (cc->tdd_Config == NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF2) ==
+			    MBSFN_FDD_SF2) {
+			    if (msi_pos == 2) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF2) ==
+				 MBSFN_FDD_SF2)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 3:
+		    if (cc->tdd_Config != NULL) {	// TDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF3) ==
+			    MBSFN_TDD_SF3) {
+			    if (msi_pos == 1) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF3) ==
+				 MBSFN_TDD_SF3)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    } else {	// FDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF3) ==
+			    MBSFN_FDD_SF3) {
+			    if (msi_pos == 3) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF3) ==
+				 MBSFN_FDD_SF3)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 4:
+		    if (cc->tdd_Config != NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF4) ==
+			    MBSFN_TDD_SF4) {
+			    if (msi_pos == 2) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF4) ==
+				 MBSFN_TDD_SF4)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 6:
+		    if (cc->tdd_Config == NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF6) ==
+			    MBSFN_FDD_SF6) {
+			    if (msi_pos == 4) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF6) ==
+				 MBSFN_FDD_SF6)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 7:
+		    if (cc->tdd_Config != NULL) {	// TDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF7) ==
+			    MBSFN_TDD_SF7) {
+			    if (msi_pos == 3) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF7) ==
+				 MBSFN_TDD_SF7)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    } else {	// FDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF7) ==
+			    MBSFN_FDD_SF7) {
+			    if (msi_pos == 5) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF7) ==
+				 MBSFN_FDD_SF7)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 8:
+		    if (cc->tdd_Config != NULL) {	//TDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF8) ==
+			    MBSFN_TDD_SF8) {
+			    if (msi_pos == 4) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF8) ==
+				 MBSFN_TDD_SF8)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    } else {	// FDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF8) ==
+			    MBSFN_FDD_SF8) {
+			    if (msi_pos == 6) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF8) ==
+				 MBSFN_FDD_SF8)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 9:
+		    if (cc->tdd_Config != NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF9) ==
+			    MBSFN_TDD_SF9) {
+			    if (msi_pos == 5) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF9) ==
+				 MBSFN_TDD_SF9)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+		}		// end switch
+
+		// sf allocation is non-overlapping
+		if ((msi_flag == 1) || (mcch_flag == 1)
+		    || (mtch_flag == 1)) {
+		    LOG_D(MAC,
+			  "[eNB %d] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n",
+			  module_idP, CC_id, frameP, subframeP, i, j,
+			  msi_flag, mcch_flag, mtch_flag);
+		    break;
+		}
+	    } else {		// four-frameP format
+	    }
+	}
+    }				// end of for loop
+
+    cc->msi_active = 0;
+    cc->mcch_active = 0;
+    cc->mtch_active = 0;
+
+    // Calculate the mcs
+    if ((msi_flag == 1) || (mcch_flag == 1)) {
+	cc->MCH_pdu.mcs = mcch_mcs;
+    } else if (mtch_flag == 1) {	// only MTCH in this subframeP
+	cc->MCH_pdu.mcs = cc->pmch_Config[0]->dataMCS_r9;
     }
 
-    LOG_D(MAC,
-          "[eNB %d] CC_id %d Frame %d : MSI->MCH, length of MSI is %d bytes \n",
-          module_idP, CC_id, frameP, msi_length);
-    //LOG_D(MAC,"Scheduler: MSI is transmitted in this subframeP \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],
-           msi_control_element, msi_length);
-    sdu_lcids[num_sdus] = MCH_SCHDL_INFO;
-    sdu_lengths[num_sdus] = msi_length;
-    sdu_length_total += sdu_lengths[num_sdus];
-    LOG_I(MAC, "[eNB %d] CC_id %d Create %d bytes for MSI\n",
-          module_idP, CC_id, sdu_lengths[num_sdus]);
-    num_sdus++;
-    cc->msi_active = 1;
-  }
 
-  // there is MCCH
-  if (mcch_flag == 1) {
-    LOG_D(MAC,
-          "[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n",
-          module_idP, CC_id, frameP, subframeP, i, j);
-    mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH, 0xFFFC, 1, &cc->MCCH_pdu.payload[0],
-                                       i);  // this is the mbsfn sync area index
-
-    if (mcch_sdu_length > 0) {
-      LOG_D(MAC,
-            "[eNB %d] CC_id %d Frame %d subframeP %d : MCCH->MCH, Received %d bytes from RRC \n",
-            module_idP, CC_id, frameP, subframeP, mcch_sdu_length);
-      header_len_mcch = 2;
-
-      if (cc->tdd_Config != NULL) {
-        LOG_D(MAC,
-              "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n",
-              module_idP, CC_id, frameP, subframeP,
-              mcch_sdu_length, mcch_mcs);
-      } else {
-        LOG_I(MAC,
-              "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n",
-              module_idP, CC_id, frameP, subframeP,
-              mcch_sdu_length, mcch_mcs);
-      }
-
-      cc->mcch_active = 1;
-      memcpy((char *) &mch_buffer[sdu_length_total],
-             &cc->MCCH_pdu.payload[0], mcch_sdu_length);
-      sdu_lcids[num_sdus] = MCCH_LCHANID;
-      sdu_lengths[num_sdus] = mcch_sdu_length;
-
-      if (sdu_lengths[num_sdus] > 128) {
-        header_len_mcch = 3;
-      }
-
-      sdu_length_total += sdu_lengths[num_sdus];
-      LOG_D(MAC,
-            "[eNB %d] CC_id %d Got %d bytes for MCCH from RRC \n",
-            module_idP, CC_id, sdu_lengths[num_sdus]);
-      num_sdus++;
+     uint8_t num_sf_alloc=0;
+    for( int iii=0; iii < 6; iii++)
+       num_sf_alloc += ( 0x39 & (0x80>>iii)) == (0x80 >> iii);
+    num_sf_alloc = 1;
+
+    // 2nd: Create MSI, get MCCH from RRC and MTCHs from RLC
+
+    // there is MSI (MCH Scheduling Info)
+    if (msi_flag == 1) {
+	// Create MSI here
+	uint16_t msi_control_element[29], *msi_ptr;
+
+	msi_ptr = &msi_control_element[0];
+	//((MSI_ELEMENT *) msi_ptr)->lcid = MCCH_LCHANID;	//MCCH
+
+	//if (mcch_flag == 1) {
+	//    ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0;
+	//    ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0;
+	//} else {		// no mcch for this MSP
+	//    ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7;	// stop value is 2047
+	//    ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xff;
+	//}
+
+	//msi_ptr += sizeof(MSI_ELEMENT);
+
+	//Header for MTCHs
+	num_mtch = cc->mbms_SessionList[0]->list.count;
+
+    	TBS =
+	get_TBS_DL(cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth));
+	//l=0;
+
+	for (k = 0; k < num_mtch; k++) {	// loop for all session in this MCH (MCH[0]) at this moment
+
+	    ((MSI_ELEMENT *) msi_ptr)->lcid = cc->mbms_SessionList[0]->list.array[k]->logicalChannelIdentity_r9;	//mtch_lcid;
+
+	    if( msi_sfs != 0 )
+	    	msi_pmch_stop = msi_sfs-1;
+	    else 
+		msi_pmch_stop = msi_sfs;
+
+	    if( msi_pmch_stop > cc->pmch_Config[0]->sf_AllocEnd_r9)
+		   LOG_W(MAC,"e-MBMS Buffer Overflow\n"); 
+
+	    if(msi_pmch_stop>=num_sf_alloc /*&& msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9*/)  {
+	        ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0;	// last subframeP of this mtch (only one mtch now) & stop_sf limited to 256
+	    	//((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = msi_pmch_stop;
+	    	((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9);
+		msi_pmch_stop = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9);
+	    }else{
+	    	((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7;	// last subframeP of this mtch (only one mtch now)
+	    	((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xFF; 
+		msi_pmch_stop=0;
+	    }
+
+	   
+	   
+	    msi_ptr += sizeof(MSI_ELEMENT);
+	}
+
+	msi_length = msi_ptr - msi_control_element;
+
+	if (msi_length < 128) {
+	    header_len_msi = 2;
+	} else {
+	    header_len_msi = 3;
+	}
+
+	LOG_D(MAC,
+	      "[eNB %d] CC_id %d Frame %d : MSI->MCH, length of MSI is %d bytes TBS %d, bytes in buffer %d stop_sf_LSB %d msi_sfs %d cc->pmch_Config[0]->sf_AllocEnd_r9 %ld\n",
+	      module_idP, CC_id, frameP, msi_length,TBS, bytes_in_buffer,msi_pmch_stop,msi_sfs,cc->pmch_Config[0]->sf_AllocEnd_r9);
+	    
+	msi_sfs = 0;
+
+	//LOG_D(MAC,"Scheduler: MSI is transmitted in this subframeP \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],
+	       msi_control_element, msi_length);
+
+	sdu_lcids[num_sdus] = MCH_SCHDL_INFO;
+	sdu_lengths[num_sdus] = msi_length;
+	sdu_length_total += sdu_lengths[num_sdus];
+	LOG_D(MAC, "[eNB %d] CC_id %d Create %d bytes for MSI\n",
+	      module_idP, CC_id, sdu_lengths[num_sdus]);
+	num_sdus++;
+	cc->msi_active = 1;
+    }
+    // there is MCCH
+    if (mcch_flag == 1) {
+	LOG_D(MAC,
+	      "[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n",
+	      module_idP, CC_id, frameP, subframeP, i, j);
+
+	mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH, 0xFFFC, 1, &cc->MCCH_pdu.payload[0], 
+					   i);	// this is the mbsfn sync area index
+
+        mcch_sdu_length+=1; //RLC ?
+
+	if (mcch_sdu_length > 0) {
+	    LOG_D(MAC,
+		  "[eNB %d] CC_id %d Frame %d subframeP %d : MCCH->MCH, Received %d bytes from RRC \n",
+		  module_idP, CC_id, frameP, subframeP, mcch_sdu_length);
+
+	    header_len_mcch = 2;
+
+	    if (cc->tdd_Config != NULL) {
+		LOG_D(MAC,
+		      "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n",
+		      module_idP, CC_id, frameP, subframeP,
+		      mcch_sdu_length, mcch_mcs);
+	    } else {
+		LOG_D(MAC,
+		      "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n",
+		      module_idP, CC_id, frameP, subframeP,
+		      mcch_sdu_length, mcch_mcs);
+	    }
+
+	    cc->mcch_active = 1;
+
+	    memcpy((char *) &mch_buffer[sdu_length_total]+1,
+		   &cc->MCCH_pdu.payload[0], mcch_sdu_length);
+	    sdu_lcids[num_sdus] = MCCH_LCHANID;
+	    sdu_lengths[num_sdus] = mcch_sdu_length;
+
+	    if (sdu_lengths[num_sdus] > 128) {
+		header_len_mcch = 3;
+	    }
+
+	    sdu_length_total += sdu_lengths[num_sdus];
+	    LOG_D(MAC,
+		  "[eNB %d] CC_id %d Got %d bytes for MCCH from RRC \n",
+		  module_idP, CC_id, sdu_lengths[num_sdus]);
+	    num_sdus++;
+	}
     }
-  }
-
-  TBS =
-    get_TBS_DL(cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth));
 
-  // do not let mcch and mtch multiplexing when relaying is active
-  // for sync area 1, so not transmit data
-  //if ((i == 0) && ((RC.mac[module_idP]->MBMS_flag != multicast_relay) || (RC.mac[module_idP]->mcch_active==0))) {
+    TBS =
+	get_TBS_DL(/*cc->pmch_Config[0]->dataMCS_r9*/cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth));
+    // do not let mcch and mtch multiplexing when relaying is active
+    // for sync area 1, so not transmit data
+    //if ((i == 0) && ((RC.mac[module_idP]->MBMS_flag != multicast_relay) || (RC.mac[module_idP]->mcch_active==0))) {
+
+    // there is MTCHs, loop if there are more than 1
+    if (mtch_flag == 1 ) {
+	// Calculate TBS
+	/* if ((msi_flag==1) || (mcch_flag==1)) {
+	   TBS = mac_xface->get_TBS(mcch_mcs, mac_xface->frame_parms->N_RB_DL);
+	   }
+	   else { // only MTCH in this subframeP
+	   TBS = mac_xface->get_TBS(RC.mac[module_idP]->pmch_Config[0]->dataMCS_r9, mac_xface->frame_parms->N_RB_DL);
+	   }
+
+	   // get MTCH data from RLC (like for DTCH)
+	   LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframe %d: Schedule MTCH (area %d, sfAlloc %d)\n",Mod_id,CC_id,frame,subframe,i,j);
+
+	   header_len_mtch = 3;
+	   LOG_D(MAC,"[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n",
+	   Mod_id,CC_id,frame,MTCH,TBS,
+	   TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
+
+	   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);
+
+	 */
+
+	// get MTCH data from RLC (like for DTCH)
+	LOG_D(MAC,
+	      "[eNB %d] CC_id %d Frame %d subframeP %d: Schedule MTCH (area %d, sfAlloc %d)\n",
+	      module_idP, CC_id, frameP, subframeP, i, j);
+
+	header_len_mtch = 3;
+	LOG_D(MAC,
+	      "[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n",
+	      module_idP, CC_id, frameP, MTCH, TBS,
+	      TBS - header_len_mcch - header_len_msi - sdu_length_total -
+	      header_len_mtch);
+
+	mbms_rab_id = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9;
+
+	rlc_status =
+	    mac_rlc_status_ind(module_idP, 0, frameP, subframeP,
+			       module_idP, ENB_FLAG_YES, MBMS_FLAG_YES,
+				cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9,
+			       //MTCH,
+			       TBS - header_len_mcch - header_len_msi -
+			       sdu_length_total - header_len_mtch
+                                    ,0, 0
+                                    );
+	bytes_in_buffer = rlc_status.bytes_in_buffer;
+
+
+	msi_sfs = rlc_status.bytes_in_buffer/TBS+(rlc_status.bytes_in_buffer%TBS?1:0);
+
+	LOG_D(MAC,
+	      "e-MBMS log channel %u frameP %d, subframeP %d,  rlc_status.bytes_in_buffer is %d TBS %d pmch_stop %d msi_sfs %d\n",
+	      MTCH, frameP, subframeP, rlc_status.bytes_in_buffer,TBS,msi_pmch_stop,msi_sfs);
+
+	if (rlc_status.bytes_in_buffer > 0 ||  msi_pmch_stop > 0  /*msi_pmch_stop>=num_sf_alloc*/ ) {
+	    //if(rlc_status.bytes_in_buffer > 0){
+	    LOG_I(MAC,
+		  "[eNB %d][MBMS USER-PLANE], CC_id %d, Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d) rlc_status.bytes_in_buffer %d\n",
+		  module_idP, CC_id, frameP,
+		  TBS - header_len_mcch - header_len_msi -
+		  sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer);
+
+	    sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0,	//not used
+						     (char *)
+						     &mch_buffer[sdu_length_total]
+                                ,0,
+                                 0
+                                 );
+	
+	    //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO,  MTCH+(MAX_NUM_RB*(MAX_MOBILES_PER_ENB+1)), (char*)&mch_buffer[sdu_length_total]);
+	    LOG_I(MAC,
+		  "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d msi_pmch_stop %d msi_sfs %d sdu_lengths[num_sdus] %d\n",
+		  module_idP, CC_id, sdu_lengths[num_sdus], MTCH,msi_pmch_stop,msi_sfs, sdu_lengths[num_sdus]);
+	    cc->mtch_active = 1;
+	    sdu_lcids[num_sdus] = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9/*MTCH*/;
+	    sdu_length_total += sdu_lengths[num_sdus];
+
+	    if (msi_pmch_stop != 0)
+	    	msi_pmch_stop--;
+
+
+	    if (sdu_lengths[num_sdus] < 128) {
+		header_len_mtch = 2;
+	    }
+
+	    num_sdus++;
+	  //}
+	} 
+	else {
+	//    LOG_E(MAC,
+	//	  "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d msi_pmch_stop %d msi_buffer %d msi_sfs %ld msi_buffer_act %ld  sdu_lengths[num_sdus] %d\n",
+	//	  module_idP, CC_id, sdu_lengths[num_sdus], MTCH,msi_pmch_stop,msi_sfs,msi_buffer_act, sdu_lengths[num_sdus]);
+
+	    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)) {
+	   RC.mac[module_idP]->MCH_pdu.mcs = mcch_mcs;
+	   }
+	   else if (mtch_flag == 1) { // only MTCH in this subframeP
+	   RC.mac[module_idP]->MCH_pdu.mcs = RC.mac[module_idP]->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;
+
+	if (header_len_mtch > 0) {
+	    header_len_mtch = 1;	// remove Length field in the  subheader for the last PDU
+	} else if (header_len_mcch > 0) {
+	    header_len_mcch = 1;
+	} else {
+	    header_len_msi = 1;
+	}
+
+	// Calculate the padding
+	if ((TBS - header_len_mtch - header_len_mcch - header_len_msi -
+	     sdu_length_total) < 0) {
+	    LOG_E(MAC, "Error in building MAC PDU, TBS %d < PDU %d \n",
+		  TBS,
+		  header_len_mtch + header_len_mcch + header_len_msi +
+		  sdu_length_total);
+	    return 0;
+	} else
+	    if ((TBS - header_len_mtch - header_len_mcch - header_len_msi -
+		 sdu_length_total) <= 2) {
+	    padding =
+		(TBS - header_len_mtch - header_len_mcch - header_len_msi -
+		 sdu_length_total);
+	    post_padding = 0;
+	} else {		// using post_padding, give back the Length field of subheader  for the last PDU
+	    padding = 0;
+
+	    if (header_len_mtch > 0) {
+		header_len_mtch = header_len_mtch_temp;
+	    } else if (header_len_mcch > 0) {
+		header_len_mcch = header_len_mcch_temp;
+	    } else {
+		header_len_msi = header_len_msi_temp;
+	    }
+
+	    post_padding =
+		TBS - sdu_length_total - header_len_msi - header_len_mcch -
+		header_len_mtch;
+	}
+
+	// Generate the MAC Header for MCH
+	// here we use the function for DLSCH because DLSCH & MCH have the same Header structure
+	offset = generate_dlsch_header((unsigned char *) cc->MCH_pdu.payload, num_sdus, sdu_lengths, sdu_lcids, 255,	// no drx
+				       31,	// no timing advance
+				       NULL,	// no contention res id
+				       padding, post_padding);
+
+	cc->MCH_pdu.Pdu_size = TBS;
+	cc->MCH_pdu.sync_area = i;
+	cc->MCH_pdu.msi_active = cc->msi_active;
+	cc->MCH_pdu.mcch_active = cc->mcch_active;
+	cc->MCH_pdu.mtch_active = cc->mtch_active;
+	LOG_D(MAC,
+	      " MCS for this sf is %d (mcch active %d, mtch active %d)\n",
+	      cc->MCH_pdu.mcs, cc->MCH_pdu.mcch_active,
+	      cc->MCH_pdu.mtch_active);
+	LOG_D(MAC,
+	      "[eNB %d][MBMS USER-PLANE ] CC_id %d 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",
+	      module_idP, CC_id, sdu_length_total, num_sdus,
+	      sdu_lengths[0], sdu_lcids[0], offset, padding, post_padding,
+	      cc->MCH_pdu.mcs, TBS, header_len_mtch, header_len_mcch,
+	      header_len_msi);
+	// copy SDU to mch_pdu after the MAC Header
+	memcpy(&cc->MCH_pdu.payload[offset], mch_buffer, sdu_length_total);
+
+	// filling remainder of MCH with random data if necessery
+	for (j = 0; j < (TBS - sdu_length_total - offset); j++) {
+	    cc->MCH_pdu.payload[offset + sdu_length_total + j] =
+		(char) (taus() & 0xff);
+	}
+
+	/* Tracing of PDU is done on UE side */
+	if (opt_enabled == 1) {
+	    trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, WS_M_RNTI , 0xffff,	// M_RNTI = 6 in wirehsark
+		      RC.mac[module_idP]->frame,
+		      RC.mac[module_idP]->subframe, 0, 0);
+	    LOG_D(OPT,
+		  "[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n",
+		  module_idP, CC_id, frameP, TBS);
+	}
+
+       	eNB_MAC_INST *eNB = RC.mac[module_idP];
+    	dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
+    //	dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
+    //	memset((void *) dl_config_pdu,
+    //                 0,
+    //                 sizeof(nfapi_dl_config_request_pdu_t));
+	dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
+    	fill_nfapi_mch_config(
+			dl_req,
+			TBS,
+			0,
+			0xfffd,
+			0,
+			get_Qm(cc->MCH_pdu.mcs),
+			cc->MCH_pdu.mcs,
+			6000, //equal to RS power
+			0 //mbsfn_area_id
+			);
+
+	eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body,
+                                        (frameP * 10) + subframeP,
+                                        TBS,
+                                        eNB->pdu_index[CC_id],
+                                        (uint8_t*)cc->MCH_pdu.payload);
+	
+
+	/*
+	   for (j=0;j<sdu_length_total;j++)
+	   printf("%2x.",RC.mac[module_idP]->MCH_pdu.payload[j+offset]);
+	   printf(" \n"); */
+	return 1;
+    } else {
+	cc->MCH_pdu.Pdu_size = 0;
+	cc->MCH_pdu.sync_area = 0;
+	cc->MCH_pdu.msi_active = 0;
+	cc->MCH_pdu.mcch_active = 0;
+	cc->MCH_pdu.mtch_active = 0;
+	// for testing purpose, fill with random data
+	//for (j=0;j<(TBS-sdu_length_total-offset);j++)
+	//  RC.mac[module_idP]->MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff);
+	return 0;
+    }
 
-  // there is MTCHs, loop if there are more than 1
-  if (mtch_flag == 1) {
-    // Calculate TBS
-    /* if ((msi_flag==1) || (mcch_flag==1)) {
-       TBS = mac_xface->get_TBS(mcch_mcs, mac_xface->frame_parms->N_RB_DL);
-       }
-       else { // only MTCH in this subframeP
-       TBS = mac_xface->get_TBS(RC.mac[module_idP]->pmch_Config[0]->dataMCS_r9, mac_xface->frame_parms->N_RB_DL);
+    //this is for testing
+    /*
+       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;
        }
+       else
+       return 0;
+     */
+}
+int
+schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
+	      sub_frame_t subframeP)
+{
+
+    int mcch_flag = 0, mtch_flag = 0, msi_flag = 0;
+    int mbsfn_period = 0;	// 1<<(RC.mac[module_idP]->mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
+    int mcch_period = 0;	//32<<(RC.mac[module_idP]->mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);
+    if(RC.mac[module_idP]->common_channels[CC_id].
+              pmch_Config[0] == NULL )
+
+	return 0;
+
+
+    int mch_scheduling_period =
+	8 << (RC.mac[module_idP]->common_channels[CC_id].
+	      pmch_Config[0]->mch_SchedulingPeriod_r9);
+    unsigned char mcch_sdu_length;
+    unsigned char header_len_mcch = 0, header_len_msi =
+	0, header_len_mtch = 0, header_len_mtch_temp =
+	0, header_len_mcch_temp = 0, header_len_msi_temp = 0;
+    int ii = 0, msi_pos = 0;
+    int mcch_mcs = -1;
+    uint16_t TBS, j = -1, padding = 0, post_padding = 0;
+    mac_rlc_status_resp_t rlc_status;
+    int num_mtch;
+    int msi_length, i, k;
+    //uint8_t l =0;
+    unsigned char sdu_lcids[11], num_sdus = 0, offset = 0;
+    uint16_t sdu_lengths[11], sdu_length_total = 0;
+    unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES];	// check the max value, this is for dlsch only
+
+    COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id];
 
-       // get MTCH data from RLC (like for DTCH)
-       LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframe %d: Schedule MTCH (area %d, sfAlloc %d)\n",Mod_id,CC_id,frame,subframe,i,j);
+    cc->MCH_pdu.Pdu_size = 0;
 
-       header_len_mtch = 3;
-       LOG_D(MAC,"[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n",
-       Mod_id,CC_id,frame,MTCH,TBS,
-       TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
+    for (i = 0; i < cc->num_active_mbsfn_area; i++) {
+	// assume, that there is always a mapping
+	if ((j = get_mbsfn_sf_alloction(module_idP, CC_id, i)) == -1) {
+	    return 0;
+	}
+
+	mbsfn_period =
+	    1 << (cc->mbsfn_SubframeConfig[j]->radioframeAllocationPeriod);
+	mcch_period =
+	    32 << (cc->mbsfn_AreaInfo[i]->
+		   mcch_Config_r9.mcch_RepetitionPeriod_r9);
+	msi_pos = 0;
+	ii = 0;
+	LOG_D(MAC,
+	      "[eNB %d] CC_id %d Frame %d subframeP %d : Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d)\n",
+	      module_idP, CC_id, frameP, subframeP, i,
+	      cc->num_active_mbsfn_area, j, cc->num_sf_allocation_pattern,
+	      mbsfn_period, mcch_period);
+
+
+	switch (cc->mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) {
+	case 0:
+	    mcch_mcs = 2;
+	    break;
+
+	case 1:
+	    mcch_mcs = 7;
+	    break;
+
+	case 2:
+	    mcch_mcs = 13;
+	    break;
+
+	case 3:
+	    mcch_mcs = 19;
+	    break;
+	}
+
+	// 1st: Check the MBSFN subframes from SIB2 info (SF allocation pattern i, max 8 non-overlapping patterns exist)
+	if (frameP % mbsfn_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset) {	// MBSFN frameP
+	    if (cc->mbsfn_SubframeConfig[j]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {	// one-frameP format
+
+		//  Find the first subframeP in this MCH to transmit MSI
+		if (frameP % mch_scheduling_period ==
+		    cc->mbsfn_SubframeConfig[j]->
+		    radioframeAllocationOffset) {
+		    while (ii == 0) {
+			ii = cc->
+			    mbsfn_SubframeConfig[j]->subframeAllocation.
+			    choice.oneFrame.buf[0] & (0x80 >> msi_pos);
+			msi_pos++;
+		    }
+
+		    LOG_D(MAC,
+			  "[eNB %d] CC_id %d Frame %d subframeP %d : sync area %d sf allocation pattern %d sf alloc %x msi pos is %d \n",
+			  module_idP, CC_id, frameP, subframeP, i, j,
+			  cc->mbsfn_SubframeConfig[j]->
+			  subframeAllocation.choice.oneFrame.buf[0],
+			  msi_pos);
+		}
+		// Check if the subframeP is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
+		switch (subframeP) {
+		case 1:
+		    if (cc->tdd_Config == NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF1) ==
+			    MBSFN_FDD_SF1) {
+			    if (msi_pos == 1) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF1) ==
+				 MBSFN_FDD_SF1)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 2:
+		    if (cc->tdd_Config == NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF2) ==
+			    MBSFN_FDD_SF2) {
+			    if (msi_pos == 2) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF2) ==
+				 MBSFN_FDD_SF2)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 3:
+		    if (cc->tdd_Config != NULL) {	// TDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF3) ==
+			    MBSFN_TDD_SF3) {
+			    if (msi_pos == 1) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF3) ==
+				 MBSFN_TDD_SF3)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    } else {	// FDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF3) ==
+			    MBSFN_FDD_SF3) {
+			    if (msi_pos == 3) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF3) ==
+				 MBSFN_FDD_SF3)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 4:
+		    if (cc->tdd_Config != NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF4) ==
+			    MBSFN_TDD_SF4) {
+			    if (msi_pos == 2) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF4) ==
+				 MBSFN_TDD_SF4)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 6:
+		    if (cc->tdd_Config == NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF6) ==
+			    MBSFN_FDD_SF6) {
+			    if (msi_pos == 4) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF6) ==
+				 MBSFN_FDD_SF6)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 7:
+		    if (cc->tdd_Config != NULL) {	// TDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF7) ==
+			    MBSFN_TDD_SF7) {
+			    if (msi_pos == 3) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF7) ==
+				 MBSFN_TDD_SF7)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    } else {	// FDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF7) ==
+			    MBSFN_FDD_SF7) {
+			    if (msi_pos == 5) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF7) ==
+				 MBSFN_FDD_SF7)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 8:
+		    if (cc->tdd_Config != NULL) {	//TDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF8) ==
+			    MBSFN_TDD_SF8) {
+			    if (msi_pos == 4) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF8) ==
+				 MBSFN_TDD_SF8)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    } else {	// FDD
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_FDD_SF8) ==
+			    MBSFN_FDD_SF8) {
+			    if (msi_pos == 6) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_FDD_SF8) ==
+				 MBSFN_FDD_SF8)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+
+		case 9:
+		    if (cc->tdd_Config != NULL) {
+			if ((cc->
+			     mbsfn_SubframeConfig[j]->subframeAllocation.
+			     choice.oneFrame.buf[0] & MBSFN_TDD_SF9) ==
+			    MBSFN_TDD_SF9) {
+			    if (msi_pos == 5) {
+				msi_flag = 1;
+			    }
+
+			    if ((frameP % mcch_period ==
+				 cc->mbsfn_AreaInfo[i]->
+				 mcch_Config_r9.mcch_Offset_r9)
+				&&
+				((cc->mbsfn_AreaInfo[i]->
+				  mcch_Config_r9.sf_AllocInfo_r9.
+				  buf[0] & MBSFN_TDD_SF9) ==
+				 MBSFN_TDD_SF9)) {
+				mcch_flag = 1;
+			    }
+
+			    mtch_flag = 1;
+			}
+		    }
+
+		    break;
+		}		// end switch
+
+		// sf allocation is non-overlapping
+		if ((msi_flag == 1) || (mcch_flag == 1)
+		    || (mtch_flag == 1)) {
+		    LOG_D(MAC,
+			  "[eNB %d] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n",
+			  module_idP, CC_id, frameP, subframeP, i, j,
+			  msi_flag, mcch_flag, mtch_flag);
+		    break;
+		}
+	    } else {		// four-frameP format
+	    }
+	}
+    }				// end of for loop
+
+    cc->msi_active = 0;
+    cc->mcch_active = 0;
+    cc->mtch_active = 0;
+
+    // Calculate the mcs
+    if ((msi_flag == 1) || (mcch_flag == 1)) {
+	cc->MCH_pdu.mcs = mcch_mcs;
+    } else if (mtch_flag == 1) {	// only MTCH in this subframeP
+	cc->MCH_pdu.mcs = cc->pmch_Config[0]->dataMCS_r9;
+    }
 
-       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);
 
-     */
-    // get MTCH data from RLC (like for DTCH)
-    LOG_D(MAC,
-          "[eNB %d] CC_id %d Frame %d subframeP %d: Schedule MTCH (area %d, sfAlloc %d)\n",
-          module_idP, CC_id, frameP, subframeP, i, j);
-    header_len_mtch = 3;
-    LOG_D(MAC,
-          "[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n",
-          module_idP, CC_id, frameP, MTCH, TBS,
-          TBS - header_len_mcch - header_len_msi - sdu_length_total -
-          header_len_mtch);
-    rlc_status =
-      mac_rlc_status_ind(module_idP, 0, frameP, subframeP,
-                         module_idP, ENB_FLAG_YES, MBMS_FLAG_YES,
-                         MTCH,
-                         TBS - header_len_mcch - header_len_msi -
-                         sdu_length_total - header_len_mtch,0, 0);
-    LOG_D(MAC,
-          "e-MBMS log channel %u frameP %d, subframeP %d,  rlc_status.bytes_in_buffer is %d\n",
-          MTCH, frameP, subframeP, rlc_status.bytes_in_buffer);
-
-    if (rlc_status.bytes_in_buffer > 0) {
-      LOG_I(MAC,
-            "[eNB %d][MBMS USER-PLANE], CC_id %d, Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d)\n",
-            module_idP, CC_id, frameP,
-            TBS - header_len_mcch - header_len_msi -
-            sdu_length_total - header_len_mtch, header_len_mtch);
-      sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES, MTCH, 0, //not used
-                              (char *) &mch_buffer[sdu_length_total],0, 0
-                                              );
-      //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO,  MTCH+(MAX_NUM_RB*(MAX_MOBILES_PER_ENB+1)), (char*)&mch_buffer[sdu_length_total]);
-      LOG_I(MAC,
-            "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d\n",
-            module_idP, CC_id, sdu_lengths[num_sdus], MTCH);
-      cc->mtch_active = 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;
+     uint8_t num_sf_alloc=0;
+    for( int iii=0; iii < 6; iii++)
+       num_sf_alloc += ( 0x39 & (0x80>>iii)) == (0x80 >> iii);
+    num_sf_alloc = 1;
+
+    // 2nd: Create MSI, get MCCH from RRC and MTCHs from RLC
+
+    // there is MSI (MCH Scheduling Info)
+    if (msi_flag == 1) {
+	// Create MSI here
+	uint16_t msi_control_element[29], *msi_ptr;
+
+	msi_ptr = &msi_control_element[0];
+	//((MSI_ELEMENT *) msi_ptr)->lcid = MCCH_LCHANID;	//MCCH
+
+	//if (mcch_flag == 1) {
+	//    ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0;
+	//    ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0;
+	//} else {		// no mcch for this MSP
+	//    ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7;	// stop value is 2047
+	//    ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xff;
+	//}
+
+	//msi_ptr += sizeof(MSI_ELEMENT);
+
+	//Header for MTCHs
+	num_mtch = cc->mbms_SessionList[0]->list.count;
+
+    	TBS =
+	get_TBS_DL(cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth));
+	//l=0;
+
+	for (k = 0; k < num_mtch; k++) {	// loop for all session in this MCH (MCH[0]) at this moment
+
+	    ((MSI_ELEMENT *) msi_ptr)->lcid = cc->mbms_SessionList[0]->list.array[k]->logicalChannelIdentity_r9;	//mtch_lcid;
+
+	    if( msi_sfs != 0 )
+	    	msi_pmch_stop = msi_sfs-1;
+	    else 
+		msi_pmch_stop = msi_sfs;
+
+	    if( msi_pmch_stop > cc->pmch_Config[0]->sf_AllocEnd_r9)
+		   LOG_W(MAC,"e-MBMS Buffer Overflow\n"); 
+
+	    if(msi_pmch_stop>=num_sf_alloc /*&& msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9*/)  {
+	        ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0;	// last subframeP of this mtch (only one mtch now) & stop_sf limited to 256
+	    	//((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = msi_pmch_stop;
+	    	((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9);
+		msi_pmch_stop = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9);
+	    }else{
+	    	((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7;	// last subframeP of this mtch (only one mtch now)
+	    	((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xFF; 
+		msi_pmch_stop=0;
+	    }
+
+	   
+	   
+	    msi_ptr += sizeof(MSI_ELEMENT);
+	}
+
+	msi_length = msi_ptr - msi_control_element;
+
+	if (msi_length < 128) {
+	    header_len_msi = 2;
+	} else {
+	    header_len_msi = 3;
+	}
+
+	LOG_D(MAC,
+	      "[eNB %d] CC_id %d Frame %d : MSI->MCH, length of MSI is %d bytes TBS %d, bytes in buffer %d stop_sf_LSB %d msi_sfs %d cc->pmch_Config[0]->sf_AllocEnd_r9 %ld\n",
+	      module_idP, CC_id, frameP, msi_length,TBS, bytes_in_buffer,msi_pmch_stop,msi_sfs,cc->pmch_Config[0]->sf_AllocEnd_r9);
+	    
+	msi_sfs = 0;
+
+	//LOG_D(MAC,"Scheduler: MSI is transmitted in this subframeP \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],
+	       msi_control_element, msi_length);
+
+	sdu_lcids[num_sdus] = MCH_SCHDL_INFO;
+	sdu_lengths[num_sdus] = msi_length;
+	sdu_length_total += sdu_lengths[num_sdus];
+	LOG_D(MAC, "[eNB %d] CC_id %d Create %d bytes for MSI\n",
+	      module_idP, CC_id, sdu_lengths[num_sdus]);
+	num_sdus++;
+	cc->msi_active = 1;
     }
-  }
-
-  // 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)) {
-       RC.mac[module_idP]->MCH_pdu.mcs = mcch_mcs;
-       }
-       else if (mtch_flag == 1) { // only MTCH in this subframeP
-       RC.mac[module_idP]->MCH_pdu.mcs = RC.mac[module_idP]->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;
-
-    if (header_len_mtch > 0) {
-      header_len_mtch = 1;  // remove Length field in the  subheader for the last PDU
-    } else if (header_len_mcch > 0) {
-      header_len_mcch = 1;
-    } else {
-      header_len_msi = 1;
+    // there is MCCH
+    if (mcch_flag == 1) {
+	LOG_D(MAC,
+	      "[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n",
+	      module_idP, CC_id, frameP, subframeP, i, j);
+
+	mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH, 0xFFFC, 1, &cc->MCCH_pdu.payload[0], 
+					   i);	// this is the mbsfn sync area index
+
+        mcch_sdu_length+=1; //RLC ?
+
+	if (mcch_sdu_length > 0) {
+	    LOG_D(MAC,
+		  "[eNB %d] CC_id %d Frame %d subframeP %d : MCCH->MCH, Received %d bytes from RRC \n",
+		  module_idP, CC_id, frameP, subframeP, mcch_sdu_length);
+
+	    header_len_mcch = 2;
+
+	    if (cc->tdd_Config != NULL) {
+		LOG_D(MAC,
+		      "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n",
+		      module_idP, CC_id, frameP, subframeP,
+		      mcch_sdu_length, mcch_mcs);
+	    } else {
+		LOG_D(MAC,
+		      "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n",
+		      module_idP, CC_id, frameP, subframeP,
+		      mcch_sdu_length, mcch_mcs);
+	    }
+
+	    cc->mcch_active = 1;
+
+	    memcpy((char *) &mch_buffer[sdu_length_total]+1,
+		   &cc->MCCH_pdu.payload[0], mcch_sdu_length);
+	    sdu_lcids[num_sdus] = MCCH_LCHANID;
+	    sdu_lengths[num_sdus] = mcch_sdu_length;
+
+	    if (sdu_lengths[num_sdus] > 128) {
+		header_len_mcch = 3;
+	    }
+
+	    sdu_length_total += sdu_lengths[num_sdus];
+	    LOG_D(MAC,
+		  "[eNB %d] CC_id %d Got %d bytes for MCCH from RRC \n",
+		  module_idP, CC_id, sdu_lengths[num_sdus]);
+	    num_sdus++;
+	}
     }
 
-    // Calculate the padding
-    if ((TBS - header_len_mtch - header_len_mcch - header_len_msi -
-         sdu_length_total) < 0) {
-      LOG_E(MAC, "Error in building MAC PDU, TBS %d < PDU %d \n",
-            TBS,
-            header_len_mtch + header_len_mcch + header_len_msi +
-            sdu_length_total);
-      return 0;
-    } else if ((TBS - header_len_mtch - header_len_mcch - header_len_msi -
-                sdu_length_total) <= 2) {
-      padding =
-        (TBS - header_len_mtch - header_len_mcch - header_len_msi -
-         sdu_length_total);
-      post_padding = 0;
-    } else {    // using post_padding, give back the Length field of subheader  for the last PDU
-      padding = 0;
-
-      if (header_len_mtch > 0) {
-        header_len_mtch = header_len_mtch_temp;
-      } else if (header_len_mcch > 0) {
-        header_len_mcch = header_len_mcch_temp;
-      } else {
-        header_len_msi = header_len_msi_temp;
-      }
-
-      post_padding =
-        TBS - sdu_length_total - header_len_msi - header_len_mcch -
-        header_len_mtch;
+    TBS =
+	get_TBS_DL(/*cc->pmch_Config[0]->dataMCS_r9*/cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth));
+    // do not let mcch and mtch multiplexing when relaying is active
+    // for sync area 1, so not transmit data
+    //if ((i == 0) && ((RC.mac[module_idP]->MBMS_flag != multicast_relay) || (RC.mac[module_idP]->mcch_active==0))) {
+
+    // there is MTCHs, loop if there are more than 1
+    if (mtch_flag == 1 ) {
+	// Calculate TBS
+	/* if ((msi_flag==1) || (mcch_flag==1)) {
+	   TBS = mac_xface->get_TBS(mcch_mcs, mac_xface->frame_parms->N_RB_DL);
+	   }
+	   else { // only MTCH in this subframeP
+	   TBS = mac_xface->get_TBS(RC.mac[module_idP]->pmch_Config[0]->dataMCS_r9, mac_xface->frame_parms->N_RB_DL);
+	   }
+
+	   // get MTCH data from RLC (like for DTCH)
+	   LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframe %d: Schedule MTCH (area %d, sfAlloc %d)\n",Mod_id,CC_id,frame,subframe,i,j);
+
+	   header_len_mtch = 3;
+	   LOG_D(MAC,"[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n",
+	   Mod_id,CC_id,frame,MTCH,TBS,
+	   TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
+
+	   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);
+
+	 */
+
+	// get MTCH data from RLC (like for DTCH)
+	LOG_D(MAC,
+	      "[eNB %d] CC_id %d Frame %d subframeP %d: Schedule MTCH (area %d, sfAlloc %d)\n",
+	      module_idP, CC_id, frameP, subframeP, i, j);
+
+	header_len_mtch = 3;
+	LOG_D(MAC,
+	      "[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n",
+	      module_idP, CC_id, frameP, MTCH, TBS,
+	      TBS - header_len_mcch - header_len_msi - sdu_length_total -
+	      header_len_mtch);
+
+	mbms_rab_id = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9;
+
+	rlc_status =
+	    mac_rlc_status_ind(module_idP, 0, frameP, subframeP,
+			       module_idP, ENB_FLAG_YES, MBMS_FLAG_YES,
+				cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9,
+			       //MTCH,
+			       TBS - header_len_mcch - header_len_msi -
+			       sdu_length_total - header_len_mtch
+                                    ,0, 0
+                                    );
+	bytes_in_buffer = rlc_status.bytes_in_buffer;
+
+
+	msi_sfs = rlc_status.bytes_in_buffer/TBS+(rlc_status.bytes_in_buffer%TBS?1:0);
+
+	LOG_D(MAC,
+	      "e-MBMS log channel %u frameP %d, subframeP %d,  rlc_status.bytes_in_buffer is %d TBS %d pmch_stop %d msi_sfs %d\n",
+	      MTCH, frameP, subframeP, rlc_status.bytes_in_buffer,TBS,msi_pmch_stop,msi_sfs);
+
+	if (rlc_status.bytes_in_buffer > 0 ||  msi_pmch_stop > 0  /*msi_pmch_stop>=num_sf_alloc*/ ) {
+	    //if(rlc_status.bytes_in_buffer > 0){
+	    LOG_I(MAC,
+		  "[eNB %d][MBMS USER-PLANE], CC_id %d, Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d) rlc_status.bytes_in_buffer %d\n",
+		  module_idP, CC_id, frameP,
+		  TBS - header_len_mcch - header_len_msi -
+		  sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer);
+
+	    sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0,	//not used
+						     (char *)
+						     &mch_buffer[sdu_length_total]
+                                ,0,
+                                 0
+                                 );
+	
+	    //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO,  MTCH+(MAX_NUM_RB*(MAX_MOBILES_PER_ENB+1)), (char*)&mch_buffer[sdu_length_total]);
+	    LOG_I(MAC,
+		  "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d msi_pmch_stop %d msi_sfs %d sdu_lengths[num_sdus] %d\n",
+		  module_idP, CC_id, sdu_lengths[num_sdus], MTCH,msi_pmch_stop,msi_sfs, sdu_lengths[num_sdus]);
+	    cc->mtch_active = 1;
+	    sdu_lcids[num_sdus] = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9/*MTCH*/;
+	    sdu_length_total += sdu_lengths[num_sdus];
+
+	    if (msi_pmch_stop != 0)
+	    	msi_pmch_stop--;
+
+
+	    if (sdu_lengths[num_sdus] < 128) {
+		header_len_mtch = 2;
+	    }
+
+	    num_sdus++;
+	  //}
+	} 
+	else {
+	//    LOG_E(MAC,
+	//	  "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d msi_pmch_stop %d msi_buffer %d msi_sfs %ld msi_buffer_act %ld  sdu_lengths[num_sdus] %d\n",
+	//	  module_idP, CC_id, sdu_lengths[num_sdus], MTCH,msi_pmch_stop,msi_sfs,msi_buffer_act, sdu_lengths[num_sdus]);
+
+	    header_len_mtch = 0;
+	}
     }
-
-    // Generate the MAC Header for MCH
-    // here we use the function for DLSCH because DLSCH & MCH have the same Header structure
-    offset = generate_dlsch_header((unsigned char *) cc->MCH_pdu.payload, num_sdus, sdu_lengths, sdu_lcids, 255,  // no drx
-                                   31,  // no timing advance
-                                   NULL,  // no contention res id
-                                   padding, post_padding);
-    cc->MCH_pdu.Pdu_size = TBS;
-    cc->MCH_pdu.sync_area = i;
-    cc->MCH_pdu.msi_active = cc->msi_active;
-    cc->MCH_pdu.mcch_active = cc->mcch_active;
-    cc->MCH_pdu.mtch_active = cc->mtch_active;
-    LOG_D(MAC,
-          " MCS for this sf is %d (mcch active %d, mtch active %d)\n",
-          cc->MCH_pdu.mcs, cc->MCH_pdu.mcch_active,
-          cc->MCH_pdu.mtch_active);
-    LOG_I(MAC,
-          "[eNB %d][MBMS USER-PLANE ] CC_id %d 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",
-          module_idP, CC_id, sdu_length_total, num_sdus,
-          sdu_lengths[0], sdu_lcids[0], offset, padding, post_padding,
-          cc->MCH_pdu.mcs, TBS, header_len_mtch, header_len_mcch,
-          header_len_msi);
-    // copy SDU to mch_pdu after the MAC Header
-    memcpy(&cc->MCH_pdu.payload[offset], mch_buffer, sdu_length_total);
-
-    // filling remainder of MCH with random data if necessery
-    for (j = 0; j < (TBS - sdu_length_total - offset); j++) {
-      cc->MCH_pdu.payload[offset + sdu_length_total + j] =
-        (char) (taus() & 0xff);
+    //  }
+
+    // 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)) {
+	   RC.mac[module_idP]->MCH_pdu.mcs = mcch_mcs;
+	   }
+	   else if (mtch_flag == 1) { // only MTCH in this subframeP
+	   RC.mac[module_idP]->MCH_pdu.mcs = RC.mac[module_idP]->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;
+
+	if (header_len_mtch > 0) {
+	    header_len_mtch = 1;	// remove Length field in the  subheader for the last PDU
+	} else if (header_len_mcch > 0) {
+	    header_len_mcch = 1;
+	} else {
+	    header_len_msi = 1;
+	}
+
+	// Calculate the padding
+	if ((TBS - header_len_mtch - header_len_mcch - header_len_msi -
+	     sdu_length_total) < 0) {
+	    LOG_E(MAC, "Error in building MAC PDU, TBS %d < PDU %d \n",
+		  TBS,
+		  header_len_mtch + header_len_mcch + header_len_msi +
+		  sdu_length_total);
+	    return 0;
+	} else
+	    if ((TBS - header_len_mtch - header_len_mcch - header_len_msi -
+		 sdu_length_total) <= 2) {
+	    padding =
+		(TBS - header_len_mtch - header_len_mcch - header_len_msi -
+		 sdu_length_total);
+	    post_padding = 0;
+	} else {		// using post_padding, give back the Length field of subheader  for the last PDU
+	    padding = 0;
+
+	    if (header_len_mtch > 0) {
+		header_len_mtch = header_len_mtch_temp;
+	    } else if (header_len_mcch > 0) {
+		header_len_mcch = header_len_mcch_temp;
+	    } else {
+		header_len_msi = header_len_msi_temp;
+	    }
+
+	    post_padding =
+		TBS - sdu_length_total - header_len_msi - header_len_mcch -
+		header_len_mtch;
+	}
+
+	// Generate the MAC Header for MCH
+	// here we use the function for DLSCH because DLSCH & MCH have the same Header structure
+	offset = generate_dlsch_header((unsigned char *) cc->MCH_pdu.payload, num_sdus, sdu_lengths, sdu_lcids, 255,	// no drx
+				       31,	// no timing advance
+				       NULL,	// no contention res id
+				       padding, post_padding);
+
+	cc->MCH_pdu.Pdu_size = TBS;
+	cc->MCH_pdu.sync_area = i;
+	cc->MCH_pdu.msi_active = cc->msi_active;
+	cc->MCH_pdu.mcch_active = cc->mcch_active;
+	cc->MCH_pdu.mtch_active = cc->mtch_active;
+	LOG_D(MAC,
+	      " MCS for this sf is %d (mcch active %d, mtch active %d)\n",
+	      cc->MCH_pdu.mcs, cc->MCH_pdu.mcch_active,
+	      cc->MCH_pdu.mtch_active);
+	LOG_D(MAC,
+	      "[eNB %d][MBMS USER-PLANE ] CC_id %d 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",
+	      module_idP, CC_id, sdu_length_total, num_sdus,
+	      sdu_lengths[0], sdu_lcids[0], offset, padding, post_padding,
+	      cc->MCH_pdu.mcs, TBS, header_len_mtch, header_len_mcch,
+	      header_len_msi);
+	// copy SDU to mch_pdu after the MAC Header
+	memcpy(&cc->MCH_pdu.payload[offset], mch_buffer, sdu_length_total);
+
+	// filling remainder of MCH with random data if necessery
+	for (j = 0; j < (TBS - sdu_length_total - offset); j++) {
+	    cc->MCH_pdu.payload[offset + sdu_length_total + j] =
+		(char) (taus() & 0xff);
+	}
+
+	/* Tracing of PDU is done on UE side */
+	if (opt_enabled == 1) {
+	    trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, WS_M_RNTI , 0xffff,	// M_RNTI = 6 in wirehsark
+		      RC.mac[module_idP]->frame,
+		      RC.mac[module_idP]->subframe, 0, 0);
+	    LOG_D(OPT,
+		  "[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n",
+		  module_idP, CC_id, frameP, TBS);
+	}
+
+	/*
+	   for (j=0;j<sdu_length_total;j++)
+	   printf("%2x.",RC.mac[module_idP]->MCH_pdu.payload[j+offset]);
+	   printf(" \n"); */
+	return 1;
+    } else {
+	cc->MCH_pdu.Pdu_size = 0;
+	cc->MCH_pdu.sync_area = 0;
+	cc->MCH_pdu.msi_active = 0;
+	cc->MCH_pdu.mcch_active = 0;
+	cc->MCH_pdu.mtch_active = 0;
+	// for testing purpose, fill with random data
+	//for (j=0;j<(TBS-sdu_length_total-offset);j++)
+	//  RC.mac[module_idP]->MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff);
+	return 0;
     }
 
-    /* Tracing of PDU is done on UE side */
-    trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, WS_M_RNTI, 0xffff,  // M_RNTI = 6 in wireshark
-              RC.mac[module_idP]->frame, RC.mac[module_idP]->subframe, 0, 0);
+    //this is for testing
     /*
-       for (j=0;j<sdu_length_total;j++)
-       printf("%2x.",RC.mac[module_idP]->MCH_pdu.payload[j+offset]);
-       printf(" \n"); */
-    return 1;
-  } else {
-    cc->MCH_pdu.Pdu_size = 0;
-    cc->MCH_pdu.sync_area = 0;
-    cc->MCH_pdu.msi_active = 0;
-    cc->MCH_pdu.mcch_active = 0;
-    cc->MCH_pdu.mtch_active = 0;
-    // for testing purpose, fill with random data
-    //for (j=0;j<(TBS-sdu_length_total-offset);j++)
-    //  RC.mac[module_idP]->MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff);
-    return 0;
-  }
-
-  //this is for testing
-  /*
-     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;
-     }
-     else
-     return 0;
-   */
+       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;
+       }
+       else
+       return 0;
+     */
 }
 
 
-MCH_PDU *get_mch_sdu(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframeP) {
+MCH_PDU *get_mch_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
+                     sub_frame_t subframeP) {
   //  RC.mac[module_idP]->MCH_pdu.mcs=0;
   //LOG_D(MAC," MCH_pdu.mcs is %d\n", RC.mac[module_idP]->MCH_pdu.mcs);
   //#warning "MCH pdu should take the CC_id index"
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index 0c6a97823a868999477e355dfed72e0cddf2c9a9..5189e769757fc79c12b18f844d6fcd6140ce2c2b 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -1586,6 +1586,39 @@ fill_nfapi_uci_acknak(module_id_t module_idP,
   return (((ackNAK_absSF / 10) << 4) + (ackNAK_absSF % 10));
 }
 
+//------------------------------------------------------------------------------
+
+void
+fill_nfapi_mch_config(nfapi_dl_config_request_body_t *dl_req,
+                  uint16_t length,
+                  uint16_t pdu_index,
+                  uint16_t rnti,
+                  uint8_t resource_allocation_type,
+                  uint16_t resource_block_coding,
+                  uint8_t modulation,
+                  uint16_t transmission_power,
+                  uint8_t mbsfn_area_id){
+  nfapi_dl_config_request_pdu_t *dl_config_pdu =
+    &dl_req->dl_config_pdu_list[dl_req->number_pdu];
+  memset((void *) dl_config_pdu, 0,
+         sizeof(nfapi_dl_config_request_pdu_t));
+  dl_config_pdu->pdu_type                                                    = NFAPI_DL_CONFIG_MCH_PDU_TYPE;
+  dl_config_pdu->pdu_size                                                    = (uint8_t) (2 + sizeof(nfapi_dl_config_mch_pdu));
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.tl.tag                                 = NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG;
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.length                                 = length;
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.pdu_index                              = pdu_index;
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.rnti                                   = rnti;
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.resource_allocation_type               = resource_allocation_type;
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.resource_block_coding                  = resource_block_coding;
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.modulation                             = modulation;
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.transmission_power                     = transmission_power;
+  dl_config_pdu->mch_pdu.mch_pdu_rel8.mbsfn_area_id                          = mbsfn_area_id;
+  dl_req->number_pdu++;
+}
+
+//------------------------------------------------------------------------------
+
+
 //------------------------------------------------------------------------------
 void
 fill_nfapi_dlsch_config(eNB_MAC_INST *eNB,
diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h
index 979ec4dace224ee83a426a64e91c225f93d980d3..d81010c267a4c5e5cfdc57aa9d1893ef754a59fa 100644
--- a/openair2/LAYER2/MAC/mac.h
+++ b/openair2/LAYER2/MAC/mac.h
@@ -411,8 +411,9 @@ typedef struct {
 #define BCCH_SIB1_BR 6    // SIB1_BR
 /*!\brief Values of BCCH SIB_BR logical channel (fake) */
 #define BCCH_SI_BR 7    // SI-BR
-/*!\brief Values of BCCH SIB1_BR logical channel (fake) */
+/*!\brief Values of BCCH SIB1_MBMS logical channel (fake) */
 #define BCCH_SIB1_MBMS 60              // SIB1_MBMS //TODO better armonize index
+/*!\brief Values of BCCH SI_MBMS logical channel (fake) */
 #define BCCH_SI_MBMS 61                // SIB_MBMS //TODO better armonize index
 /*!\brief Value of CCCH / SRB0 logical channel */
 #define CCCH 0      // srb0
@@ -424,7 +425,8 @@ typedef struct {
 #define DTCH 3      // LCID
 /*!\brief MCCH logical channel */
 //#define MCCH 4
-#define MCCH 62
+//#define MCCH 62
+#define MCCH 11
 /*!\brief MTCH logical channel */
 #define MTCH 1
 // DLSCH LCHAN ID
diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h
index cb93b76c91edfadbca9af9188a3793fde3cdaab9..c0ad9b176ca99697d8af2826eaf1a83f5367d03c 100644
--- a/openair2/LAYER2/MAC/mac_proto.h
+++ b/openair2/LAYER2/MAC/mac_proto.h
@@ -31,6 +31,7 @@
 
 #include "LAYER2/MAC/mac.h"
 #include "PHY/defs_common.h" // for PRACH_RESOURCES_t and lte_subframe_t
+#include "openair2/COMMON/mac_messages_types.h"
 
 
 /** \addtogroup _mac
@@ -85,6 +86,14 @@ void schedule_SI_MBMS(module_id_t module_idP, frame_t frameP,
 int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
                   sub_frame_t subframe);
 
+/** \brief MBMS scheduling: Checking the position for MBSFN subframes. Create MSI, transfer MCCH from RRC to MAC, transfer MTCHs from RLC to MAC. Multiplexing MSI,MCCH&MTCHs. Return 1 if there are MBSFN data being allocated, otherwise return 0;
+@param Mod_id Instance ID of eNB
+@param frame Frame index
+@param subframe Subframe number on which to act
+*/
+int schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_frame_t subframe);
+
+
 /** \brief check the mapping between sf allocation and sync area, Currently only supports 1:1 mapping
 @param Mod_id Instance ID of eNB
 @param mbsfn_sync_area index of mbsfn sync area
@@ -1192,6 +1201,16 @@ void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB,
                              uint8_t num_bf_prb_per_subband,
                              uint8_t num_bf_vector);
 
+void fill_nfapi_mch_config(nfapi_dl_config_request_body_t *dl_req,
+                  uint16_t length,
+                  uint16_t pdu_index,
+                  uint16_t rnti,
+                  uint8_t resource_allocation_type,
+                  uint16_t resource_block_coding,
+                  uint8_t modulation,
+                  uint16_t transmission_power,
+                  uint8_t mbsfn_area_id);
+
 void fill_nfapi_harq_information(module_id_t module_idP,
                                  int CC_idP,
                                  uint16_t rntiP,
@@ -1265,9 +1284,13 @@ int ue_ul_slice_membership(module_id_t mod_id, int UE_id, int slice_idx);
 
 /* DRX Configuration */
 /* Configure local DRX timers and thresholds in UE context, following the drx_configuration input */
-void eNB_Config_Local_DRX(module_id_t Mod_id, rnti_t rnti, LTE_DRX_Config_t *drx_Configuration);
+void eNB_Config_Local_DRX(instance_t Mod_id, rrc_mac_drx_config_req_t *rrc_mac_drx_config_req);                        
 
 /* from here: prototypes to get rid of compilation warnings: doc to be written by function author */
 uint8_t ul_subframe2_k_phich(COMMON_channels_t *cc, sub_frame_t ul_subframe);
 #endif
 /** @}*/
+
+/* MAC ITTI messaging related functions */
+/* Main loop of MAC itti message handling */
+void *mac_enb_task(void *arg);
diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c
index 4e139dcf92682280a0453e808237a1a4b5f0d66b..fe8980101dc34ddbc8e515de9d0b9f3d2e935f18 100644
--- a/openair2/LAYER2/MAC/main.c
+++ b/openair2/LAYER2/MAC/main.c
@@ -34,15 +34,12 @@
 #include "mac_proto.h"
 #include "mac_extern.h"
 #include "assertions.h"
-//#include "PHY_INTERFACE/phy_extern.h"
-//#include "PHY/defs_eNB.h"
-//#include "SCHED/sched_eNB.h"
 #include "LAYER2/PDCP_v10.1.0/pdcp.h"
 #include "RRC/LTE/rrc_defs.h"
 #include "common/utils/LOG/log.h"
 #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
-
 #include "common/ran_context.h"
+#include "intertask_interface.h"
 
 extern RAN_CONTEXT_t RC;
 
@@ -223,3 +220,47 @@ int l2_init_eNB(void)
 
     return (1);
 }
+
+//-----------------------------------------------------------------------------
+/*
+ * Main loop of MAC itti message handling
+ */
+void *mac_enb_task(void *arg)
+//-----------------------------------------------------------------------------
+{
+  MessageDef *received_msg = NULL;
+  int         result;
+
+  itti_mark_task_ready(TASK_MAC_ENB); // void function 10/2019
+  LOG_I(MAC,"Starting main loop of MAC message task\n");
+
+  while (1) {
+    itti_receive_msg(TASK_MAC_ENB, &received_msg);
+
+    switch (ITTI_MSG_ID(received_msg)) {
+      case RRC_MAC_DRX_CONFIG_REQ:
+        LOG_I(MAC, "MAC Task Received RRC_MAC_DRX_CONFIG_REQ\n");
+        /* Set timers and thresholds values in local MAC context of UE */
+        eNB_Config_Local_DRX(ITTI_MESSAGE_GET_INSTANCE(received_msg), &received_msg->ittiMsg.rrc_mac_drx_config_req);
+        break;
+
+      case TERMINATE_MESSAGE:
+        LOG_W(MAC, " *** Exiting MAC thread\n");
+        itti_exit_task();
+        break;
+
+      default:
+        LOG_E(MAC, "MAC instance received unhandled message: %d:%s\n",
+              ITTI_MSG_ID(received_msg), 
+              ITTI_MSG_NAME(received_msg));
+        break;  
+    } // end switch
+
+    result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
+    AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    
+    received_msg = NULL;
+  } // end while
+
+  return NULL;
+}
\ No newline at end of file
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index 74c834c4d0b6ad9fc8785fafba77314ae787f6f1..c340aa0b8fe2b9ca128f6b68270ae976d5f62074 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -74,6 +74,8 @@ extern UL_IND_t *UL_INFO;
 extern int next_ra_frame;
 extern module_id_t next_Mod_id;
 
+int mbms_rab_id = 2047;
+
 /*
  *
 #ifndef USER_MODE
@@ -792,6 +794,9 @@ ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
 
       if (j<28 && UE_mac_inst[module_idP].msi_status_v[j]==1) {
         LOG_D(MAC,"[UE %d] Frame %d : MCH->MTCH for sync area %d (eNB %d, %d bytes), j=%d\n", module_idP, frameP, sync_area, eNB_index, rx_lengths[i], j);
+        //This sucks I know ... workaround !
+       mbms_rab_id = rx_lcids[i];
+        //end sucks  :-(
         mac_rlc_data_ind(
           module_idP,
           UE_mac_inst[module_idP].crnti,
@@ -1096,6 +1101,7 @@ int ue_query_p_mch(module_id_t module_idP, uint32_t frameP, uint32_t subframe, i
 
 int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_t subframe, uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active) {
   int i = 0, j = 0, ii = 0, jj = 0, msi_pos = 0, mcch_mcs = -1, mtch_mcs = -1;
+  int l =0;
   int mcch_flag = 0, mtch_flag = 0, msi_flag = 0;
   long mch_scheduling_period = -1;
   uint8_t mch_lcid = 0;
@@ -1347,28 +1353,40 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_
         // Acount for sf_allocable in CSA
         int num_sf_alloc = 0;
 
-        for (i = 0; i < 8; i++) {
-          if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[i] == NULL)
+        for (l = 0; l < 8; l++) {
+          if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL)
             continue;
 
-          if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame)
+          if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame)
             continue;
 
-          uint32_t common_mbsfn_SubframeConfig = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[0];
+          uint32_t common_mbsfn_SubframeConfig = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.choice.oneFrame.buf[0];
 
           for (j = 0; j < 6; j++)
             num_sf_alloc += ((common_mbsfn_SubframeConfig & (0x80 >> j)) == (0x80 >> j));
+	    //num_sf_alloc=1;
         }
 
-        for (i = 0; i < 28; i++) {
-          if (UE_mac_inst[module_idP].pmch_stop_mtch[i] >= num_sf_alloc) {
-            if (UE_mac_inst[module_idP].pmch_stop_mtch[i] != 2047) {
-              if (UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch] != NULL)
+        for (l = 0; l < 28; l++) {
+          if (UE_mac_inst[module_idP].pmch_stop_mtch[l] >= 1/*num_sf_alloc*/) {
+            if (UE_mac_inst[module_idP].pmch_stop_mtch[l] != 2047) {
+              if (UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch] != NULL){
                 mtch_mcs = UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch]->dataMCS_r9;
+               long common_mbsfn_period  = 1 << UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[0]->radioframeAllocationPeriod;
+               long commonSF_AllocPeriod = 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9;
+               if(UE_mac_inst[module_idP].common_num_sf_alloc >= UE_mac_inst[module_idP].pmch_stop_mtch[l]){
+		       //LOG_E(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d\n",UE_mac_inst[module_idP].common_num_sf_alloc);
+
+                       mtch_mcs = -1;
+	       }/*else
+		       LOG_W(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d\n",UE_mac_inst[module_idP].common_num_sf_alloc);*/
+               	UE_mac_inst[module_idP].common_num_sf_alloc++;
+           	UE_mac_inst[module_idP].common_num_sf_alloc = UE_mac_inst[module_idP].common_num_sf_alloc % (num_sf_alloc * commonSF_AllocPeriod / common_mbsfn_period);
+	      }
               else
                 mtch_mcs = -1;
 
-              mch_lcid = (uint8_t)i;
+              mch_lcid = (uint8_t)l;
               break;
             }
           }
@@ -1377,7 +1395,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_
         // sf allocation is non-overlapping
         if ((msi_flag==1) || (mcch_flag==1) || (mtch_flag==1)) {
           LOG_D(MAC,"[UE %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n",
-                module_idP, frameP, subframe,i,j,msi_flag,mcch_flag,mtch_flag);
+                module_idP, frameP, subframe,l,j,msi_flag,mcch_flag,mtch_flag);
           *sync_area=i;
           break;
         }
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index f234e02c04b7086ca6e81c9552bbd00aeb47410d..88cad1890aa5aadf3478f3c7f510ec8d76126361 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -959,15 +959,15 @@ pdcp_data_ind(
 #ifdef MBMS_MULTICAST_OUT
 
   if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
-    struct iphdr   *ip_header = (struct iphdr *)&sdu_buffer_pP->data[payload_offset];
-    struct udphdr *udp_header = (struct udphdr *)&sdu_buffer_pP->data[payload_offset + sizeof(struct iphdr)];
-    struct sockaddr_in dest_addr;
-    dest_addr.sin_family      = AF_INET;
-    dest_addr.sin_port        = udp_header->dest;
-    dest_addr.sin_addr.s_addr = ip_header->daddr;
+   // struct iphdr   *ip_header = (struct iphdr *)&sdu_buffer_pP->data[payload_offset];
+   // struct udphdr *udp_header = (struct udphdr *)&sdu_buffer_pP->data[payload_offset + sizeof(struct iphdr)];
+   // struct sockaddr_in dest_addr;
+   // dest_addr.sin_family      = AF_INET;
+   // dest_addr.sin_port        = udp_header->dest;
+   // dest_addr.sin_addr.s_addr = ip_header->daddr;
 
-    sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
-    //packet_forwarded = TRUE;
+   // sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
+   // //packet_forwarded = TRUE;
 
   }
 
@@ -1251,6 +1251,132 @@ pdcp_run (
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
 }
 
+//-----------------------------------------------------------------------------
+void
+pdcp_mbms_run (
+  const protocol_ctxt_t *const  ctxt_pP
+)
+//-----------------------------------------------------------------------------
+{
+ // if (ctxt_pP->enb_flag) {
+ //   start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
+ // } else {
+ //   start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run);
+ // }
+
+ // pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615
+ // pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023
+ // pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe;
+ // pdcp_update_stats(ctxt_pP);
+ // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
+ // MessageDef   *msg_p;
+  //int           result;
+  //protocol_ctxt_t  ctxt;
+
+//  do {
+//    // Checks if a message has been sent to PDCP sub-task
+//    itti_poll_msg (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);
+//
+//    if (msg_p != NULL) {
+//      switch (ITTI_MSG_ID(msg_p)) {
+//        case RRC_DCCH_DATA_REQ:
+//          PROTOCOL_CTXT_SET_BY_MODULE_ID(
+//            &ctxt,
+//            RRC_DCCH_DATA_REQ (msg_p).module_id,
+//            RRC_DCCH_DATA_REQ (msg_p).enb_flag,
+//            RRC_DCCH_DATA_REQ (msg_p).rnti,
+//            RRC_DCCH_DATA_REQ (msg_p).frame,
+//            0,
+//            RRC_DCCH_DATA_REQ (msg_p).eNB_index);
+//          LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
+//                PROTOCOL_CTXT_ARGS(&ctxt),
+//                ITTI_MSG_NAME (msg_p),
+//                ITTI_MSG_ORIGIN_NAME(msg_p),
+//                ITTI_MSG_INSTANCE (msg_p),
+//                RRC_DCCH_DATA_REQ (msg_p).rb_id,
+//                RRC_DCCH_DATA_REQ (msg_p).muip,
+//                RRC_DCCH_DATA_REQ (msg_p).confirmp,
+//                RRC_DCCH_DATA_REQ (msg_p).mode);
+//          LOG_D(PDCP, "Before calling pdcp_data_req from pdcp_run! RRC_DCCH_DATA_REQ (msg_p).rb_id: %d \n", RRC_DCCH_DATA_REQ (msg_p).rb_id);
+//          result = pdcp_data_req (&ctxt,
+//                                  SRB_FLAG_YES,
+//                                  RRC_DCCH_DATA_REQ (msg_p).rb_id,
+//                                  RRC_DCCH_DATA_REQ (msg_p).muip,
+//                                  RRC_DCCH_DATA_REQ (msg_p).confirmp,
+//                                  RRC_DCCH_DATA_REQ (msg_p).sdu_size,
+//                                  RRC_DCCH_DATA_REQ (msg_p).sdu_p,
+//                                  RRC_DCCH_DATA_REQ (msg_p).mode,
+//                                  NULL, NULL
+//                                 );
+//
+//          if (result != TRUE)
+//            LOG_E(PDCP, "PDCP data request failed!\n");
+//
+//          // Message buffer has been processed, free it now.
+//          result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ (msg_p).sdu_p);
+//          AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+//          break;
+//
+//        case RRC_PCCH_DATA_REQ: {
+//          sdu_size_t     sdu_buffer_sizeP;
+//          sdu_buffer_sizeP = RRC_PCCH_DATA_REQ(msg_p).sdu_size;
+//          uint8_t CC_id = RRC_PCCH_DATA_REQ(msg_p).CC_id;
+//          uint8_t ue_index = RRC_PCCH_DATA_REQ(msg_p).ue_index;
+//          RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_paging[ue_index] = sdu_buffer_sizeP;
+//
+//          if (sdu_buffer_sizeP > 0) {
+//            memcpy(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].paging[ue_index], RRC_PCCH_DATA_REQ(msg_p).sdu_p, sdu_buffer_sizeP);
+//          }
+//
+//          //paging pdcp log
+//          LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP);
+//        }
+//        break;
+//
+//        default:
+//          LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
+//          break;
+//      }
+//
+//      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
+//      AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+//    }
+//  } while(msg_p != NULL);
+//
+  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
+  //  if (LINK_ENB_PDCP_TO_GTPV1U && ctxt_pP->enb_flag == ENB_FLAG_NO) {
+  //if (EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO ) {
+
+    pdcp_fifo_read_input_mbms_sdus_fromtun(ctxt_pP);
+  //}
+
+  // PDCP -> NAS/IP traffic: RX
+//  if (ctxt_pP->enb_flag) {
+//    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
+//  } else {
+//    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
+//  }
+//
+
+    //pdcp_fifo_flush_mbms_sdus(ctxt_pP);
+
+//  if (ctxt_pP->enb_flag) {
+//    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
+//  } else {
+//    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
+//  }
+//
+//  if (ctxt_pP->enb_flag) {
+//    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
+//  } else {
+//    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run);
+//  }
+//
+//  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
+}
+
+
+
 void pdcp_init_stats_UE(module_id_t mod, uint16_t uid) {
   Pdcp_stats_tx_window_ms[mod][uid] = 100;
   Pdcp_stats_rx_window_ms[mod][uid] = 100;
@@ -1695,7 +1821,7 @@ rrc_pdcp_config_asn1_req (
       for (j=0; j<mbms_SessionInfoList_r9_p->list.count; j++) {
         MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
 
-        if (MBMS_SessionInfo_p->sessionId_r9)
+        if (0/*MBMS_SessionInfo_p->sessionId_r9*/)
           lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
         else
           lc_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
@@ -1722,7 +1848,7 @@ rrc_pdcp_config_asn1_req (
           }
         }
 
-        LOG_D(PDCP, "lc_id (%02ld) mch_id(%02x,%02x,%02x) drb_id(%ld) action(%d)\n",
+        LOG_I(PDCP, "lc_id (%02ld) mch_id(%02x,%02x,%02x) drb_id(%ld) action(%d)\n",
               lc_id,
               MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[0],
               MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[1],
@@ -2174,16 +2300,31 @@ uint64_t pdcp_module_init( uint64_t pdcp_optmask ) {
       //Add --nr-ip-over-lte option check for next line
       if (IS_SOFTMODEM_NOS1)
     	  nas_config(1, 1, 2, "ue");
+      netlink_init_mbms_tun("uem",num_if);
+      nas_config_mbms(1, 2, 2, "uem");
       LOG_I(PDCP, "UE pdcp will use tun interface\n");
     } else if(ENB_NAS_USE_TUN) {
       netlink_init_tun("enb",1);
       nas_config(1, 1, 1, "enb");
+      if(pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT){
+      	netlink_init_mbms_tun("enm",1);
+      	nas_config_mbms(1, 2, 1, "enm"); 
+      	LOG_I(PDCP, "ENB pdcp will use mbms tun interface\n");
+      }
       LOG_I(PDCP, "ENB pdcp will use tun interface\n");
     } else {
       LOG_I(PDCP, "pdcp will use kernel modules\n");
       netlink_init();
     }
-  }
+  }else{
+         if(pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT){
+             LOG_W(PDCP, "ENB pdcp will use tun interface for MBMS\n");
+            netlink_init_mbms_tun("enm",1);
+             nas_config_mbms_s1(1, 2, 1, "enm"); 
+         }else
+             LOG_E(PDCP, "ENB pdcp will not use tun interface\n");
+   }
+
   return pdcp_params.optmask ;
 }
 
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
index 1d4c6127434e6b57d67601ab07edc321a02efa03..e9ac85866cec5d73e2b0e7dd7efe658981cf7e5e 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
@@ -61,6 +61,7 @@ typedef boolean_t (*pdcp_data_ind_func_t)( const protocol_ctxt_t *, const srb_fl
 /* UEs beyond that will be multiplexed on the same tun   */
 #define MAX_NUMBER_NETIF           16
 
+#define ENB_NAS_USE_TUN_W_MBMS_BIT      (1<< 10)
 #define PDCP_USE_NETLINK_BIT            (1<< 11)
 #define LINK_ENB_PDCP_TO_IP_DRIVER_BIT  (1<< 13)
 #define LINK_ENB_PDCP_TO_GTPV1U_BIT     (1<< 14)
@@ -388,6 +389,17 @@ boolean_t pdcp_remove_UE(
 */
 //void rrc_pdcp_config_release ( const protocol_ctxt_t* const  ctxt_pP, rb_id_t);
 
+/*! \fn void pdcp_mbms_run(const protocol_ctxt_t* const  ctxt_pP)
+* \brief Runs PDCP entity to let it handle incoming/outgoing SDUs
+* \param[in]  ctxt_pP           Running context.
+* \return none
+* \note None
+* @ingroup _pdcp
+*/
+void pdcp_mbms_run            (
+  const protocol_ctxt_t *const  ctxt_pP);
+
+
 /*! \fn void pdcp_run(const protocol_ctxt_t* const  ctxt_pP)
 * \brief Runs PDCP entity to let it handle incoming/outgoing SDUs
 * \param[in]  ctxt_pP           Running context.
@@ -413,6 +425,9 @@ void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req);
 void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind);
 pdcp_data_ind_func_t get_pdcp_data_ind_func(void);
 //-----------------------------------------------------------------------------
+int pdcp_fifo_flush_mbms_sdus                      ( const protocol_ctxt_t *const  ctxt_pP);
+int pdcp_fifo_read_input_mbms_sdus_fromtun       ( const protocol_ctxt_t *const  ctxt_pP);
+
 
 /*
  * Following two types are utilized between NAS driver and PDCP
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
index 9e873379b135d598ddd027dbfd4b3fe7be3c9e5c..df65240d62be146a2122ff6f08a66a7f8b559a1f 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -77,6 +77,11 @@ extern struct iovec nas_iov_rx;
 
 extern int nas_sock_fd[MAX_MOBILES_PER_ENB];
 
+extern int nas_sock_mbms_fd[8];
+
+extern int mbms_rab_id;
+
+
 extern struct msghdr nas_msg_tx;
 extern struct msghdr nas_msg_rx;
 
@@ -125,7 +130,16 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const  ctxt_pP) {
       ret = sendto(pdcp_pc5_sockfd, &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),
                    sizeof(sidelink_pc5s_element), 0, (struct sockaddr *)&prose_pdcp_addr,sizeof(prose_pdcp_addr) );
     } else if (UE_NAS_USE_TUN) {
-      ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
+      //ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
+       if(rb_id == mbms_rab_id){
+       ret = write(nas_sock_mbms_fd[0], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
+       LOG_I(PDCP,"[PDCP_FIFOS] ret %d TRIED TO PUSH MBMS DATA TO rb_id %d handle %d sizeToWrite %d\n",ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite);
+        }
+       else
+       {
+       ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
+       LOG_I(PDCP,"[PDCP_FIFOS] ret %d TRIED TO PUSH DATA TO rb_id %d handle %d sizeToWrite %d\n",ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite);
+       }
     } else if (ENB_NAS_USE_TUN) {
       ret = write(nas_sock_fd[0], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
     } else if (PDCP_USE_NETLINK) {
@@ -150,6 +164,47 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const  ctxt_pP) {
   return pdcp_nb_sdu_sent;
 }
 
+int pdcp_fifo_flush_mbms_sdus(const protocol_ctxt_t *const  ctxt_pP) {
+  mem_block_t     *sdu_p;
+  int              pdcp_nb_sdu_sent = 0;
+  //int              ret=0;
+
+  while ((sdu_p = list_get_head (&pdcp_sdu_list)) != NULL && ((pdcp_data_ind_header_t *)(sdu_p->data))->inst == ctxt_pP->module_id) {
+    ((pdcp_data_ind_header_t *)(sdu_p->data))->inst = 0;
+    //int rb_id = ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id;
+    //int sizeToWrite= sizeof (pdcp_data_ind_header_t) +
+                     //((pdcp_data_ind_header_t *) sdu_p->data)->data_size;
+
+    //if (rb_id == 10) { //hardcoded for PC5-Signaling
+    //  if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
+    //    debug_pdcp_pc5s_sdu((sidelink_pc5s_element *)&(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),
+    //                        "pdcp_fifo_flush_sdus sends a aPC5S message");
+    //  }
+
+    //  ret = sendto(pdcp_pc5_sockfd, &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),
+    //               sizeof(sidelink_pc5s_element), 0, (struct sockaddr *)&prose_pdcp_addr,sizeof(prose_pdcp_addr) );
+    //} else if (UE_NAS_USE_TUN) {
+    //  ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
+    //  LOG_I(PDCP,"[PDCP_FIFOS] ret %d TRIED TO PUSH DATA TO rb_id %d handle %d sizeToWrite %d\n",ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite);
+
+    //} else if (ENB_NAS_USE_TUN) {
+    //  ret = write(nas_sock_fd[0], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
+    //} else if (PDCP_USE_NETLINK) {
+    //  memcpy(NLMSG_DATA(nas_nlh_tx), (uint8_t *) sdu_p->data,  sizeToWrite);
+    //  nas_nlh_tx->nlmsg_len = sizeToWrite;
+    //  ret = sendmsg(nas_sock_fd[0],&nas_msg_tx,0);
+    //}  //  PDCP_USE_NETLINK
+
+    //AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s)\n", errno, strerror(errno));
+    list_remove_head (&pdcp_sdu_list);
+    free_mem_block (sdu_p, __func__);
+    pdcp_nb_sdu_sent ++;
+  }
+
+  return pdcp_nb_sdu_sent;
+}
+
+
 int pdcp_fifo_read_input_sdus_fromtun (const protocol_ctxt_t *const  ctxt_pP) {
   protocol_ctxt_t ctxt = *ctxt_pP;
   hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
@@ -203,6 +258,105 @@ int pdcp_fifo_read_input_sdus_fromtun (const protocol_ctxt_t *const  ctxt_pP) {
   return len;
 }
 
+int pdcp_fifo_read_input_mbms_sdus_fromtun (const protocol_ctxt_t *const  ctxt_pP) {
+  protocol_ctxt_t ctxt = *ctxt_pP;
+  hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
+  hashtable_rc_t h_rc = HASH_TABLE_OK;
+  //pdcp_t *pdcp_p = NULL;
+  int len;
+  rb_id_t rab_id = mbms_rab_id;//DEFAULT_RAB_ID;
+  if(mbms_rab_id > 9 || mbms_rab_id < 4)
+       h_rc = 2;
+
+  if(UE_NAS_USE_TUN)
+       return 0;
+
+  do {
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_MBMS_FIFO_READ, 1 );
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_MBMS_FIFO_READ_BUFFER, 1 );
+    len = read(UE_NAS_USE_TUN?nas_sock_mbms_fd[0]:nas_sock_mbms_fd[0], &nl_rx_buf, NL_MAX_PAYLOAD);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_MBMS_FIFO_READ_BUFFER, 0 );
+
+    if (len<=0) continue;
+
+    if (UE_NAS_USE_TUN) {
+      //key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
+      //h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
+    } else { // => ENB_NAS_USE_TUN
+    //ctxt.rnti=pdcp_eNB_UE_instance_to_rnti[0];
+     // ctxt.enb_flag=ENB_FLAG_YES;
+     // ctxt.module_id=0;
+     // key = PDCP_COLL_KEY_VALUE(ctxt.module_id, /*ctxt.rnti*/0, ctxt.enb_flag, /*mbms_rab_id*/8, SRB_FLAG_YES);
+     // h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
+     // LOG_W(PDCP,"h_rc %d %d\n",h_rc,rab_id);
+    }
+
+    LOG_D(PDCP, "PDCP_COLL_KEY_DEFAULT_DRB_VALUE(module_id=%d, rnti=%x, enb_flag=%d)\n",
+          ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
+
+    if (h_rc == HASH_TABLE_OK) {
+      LOG_I(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %d \n",
+            ctxt.frame, ctxt.instance, len, rab_id);
+      LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %04x][RB %u]\n",
+            ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id,
+            ctxt.rnti, rab_id);
+      MSC_LOG_RX_MESSAGE((ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
+                         (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
+                         NULL, 0,
+                         MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
+                         MSC_AS_TIME_ARGS(ctxt_pP),
+                         ctxt.instance, rab_id, rab_id, len);
+      pdcp_data_req(
+                &ctxt,
+                SRB_FLAG_NO,
+                //DEFAULT_RAB_ID,
+               rab_id,
+                RLC_MUI_UNDEFINED,
+                RLC_SDU_CONFIRM_NO,
+                len,
+                (unsigned char *)nl_rx_buf,
+                    PDCP_TRANSMISSION_MODE_TRANSPARENT
+                    , NULL, NULL
+                );
+
+      //pdcp_data_req(&ctxt, SRB_FLAG_NO, rab_id, RLC_MUI_UNDEFINED,
+      //              RLC_SDU_CONFIRM_NO, len, (unsigned char *)nl_rx_buf,
+      //              PDCP_TRANSMISSION_MODE_DATA
+      //              , NULL, NULL
+      //             );
+    } else {
+      MSC_LOG_RX_DISCARDED_MESSAGE(
+        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
+        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
+        NULL,
+        0,
+        MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
+        MSC_AS_TIME_ARGS(ctxt_pP),
+        ctxt.instance, rab_id, rab_id, len);
+      LOG_D(PDCP,
+            "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %04x][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
+            ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id,
+            ctxt.rnti, rab_id, key);
+       //if (!UE_NAS_USE_TUN) {
+       //    pdcp_data_req(
+        //        &ctxt,
+        //        SRB_FLAG_NO,
+        //        DEFAULT_RAB_ID,
+        //        RLC_MUI_UNDEFINED,
+        //        RLC_SDU_CONFIRM_NO,
+        //        len,
+        //        (unsigned char *)nl_rx_buf,
+        //            PDCP_TRANSMISSION_MODE_TRANSPARENT
+        //            , NULL, NULL
+        //        );
+        //}
+    }
+  } while (len > 0);
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_MBMS_FIFO_READ, 0 );
+  return len;
+}
+
 int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctxt_pP) {
   int  len = 1;
   int rlc_data_req_flag = 3;
diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c
index 49f7420216c1dde675249d62118d80e78c4532ac..73da0cdb66c8c7c7c248582b51ce0cd65ff3ae9b 100644
--- a/openair2/LAYER2/RLC/rlc_rrc.c
+++ b/openair2/LAYER2/RLC/rlc_rrc.c
@@ -339,7 +339,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
       for (j=0; j<mbms_SessionInfoList_r9_p->list.count; j++) {
         MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
 
-        if (MBMS_SessionInfo_p->sessionId_r9)
+        if (0/*MBMS_SessionInfo_p->sessionId_r9*/)
           mbms_session_id  = MBMS_SessionInfo_p->sessionId_r9->buf[0];
         else
           mbms_session_id  = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
@@ -379,7 +379,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
           }
         }
 
-        LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ MBMS ASN1 LC ID %u RB ID %ld SESSION ID %u SERVICE ID %u\n",
+        LOG_I(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ MBMS ASN1 LC ID %u RB ID %u SESSION ID %u SERVICE ID %u\n",
               PROTOCOL_CTXT_ARGS(ctxt_pP),
               lc_id,
               rb_id,
@@ -611,14 +611,14 @@ rlc_union_t *rrc_rlc_add_rlc   (
     }
 
     key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_id_p->service_id, mbms_id_p->session_id);
-  }
-
-  if ((sourceL2Id > 0) && (destinationL2Id > 0) ) {
-    key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, sourceL2Id, destinationL2Id, srb_flagP);
-    key_lcid = RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, sourceL2Id, destinationL2Id, srb_flagP);
   } else {
-    key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
-    key_lcid = RLC_COLL_KEY_LCID_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, srb_flagP);
+    if ((sourceL2Id > 0) && (destinationL2Id > 0) ) {
+       key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, sourceL2Id, destinationL2Id, srb_flagP);
+       key_lcid = RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, sourceL2Id, destinationL2Id, srb_flagP);
+    } else {
+       key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
+       key_lcid = RLC_COLL_KEY_LCID_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, srb_flagP);
+    }
   }
 
   h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
diff --git a/openair2/M2AP/MESSAGES/ASN1/R14/m2ap-14.0.0.asn1 b/openair2/M2AP/MESSAGES/ASN1/R14/m2ap-14.0.0.asn1
new file mode 100644
index 0000000000000000000000000000000000000000..997501f1a6ecf7a132f018a5af097b0c6b5c5fd6
--- /dev/null
+++ b/openair2/M2AP/MESSAGES/ASN1/R14/m2ap-14.0.0.asn1
@@ -0,0 +1,1897 @@
+-- 3GPP TS 36.443 V15.0.0 (2018-09)
+-- **************************************************************
+--
+-- Elementary Procedure definitions
+--
+-- **************************************************************
+
+M2AP-PDU-Descriptions {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) 
+eps-Access (21) modules (3) m2ap (4) version1 (1) m2ap-PDU-Descriptions (0) }
+
+DEFINITIONS AUTOMATIC TAGS ::= 
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+	Criticality,
+	ProcedureCode
+FROM M2AP-CommonDataTypes
+
+
+	SessionStartRequest,
+	SessionStartResponse,
+	SessionStartFailure,
+	SessionStopRequest,
+	SessionStopResponse, 
+	SessionUpdateRequest,
+	SessionUpdateResponse,
+	SessionUpdateFailure,
+	MbmsSchedulingInformation,
+	MbmsSchedulingInformationResponse,
+	ErrorIndication,
+	Reset,
+	ResetAcknowledge,
+	M2SetupRequest,
+	M2SetupResponse,
+	M2SetupFailure,
+	ENBConfigurationUpdate,
+	ENBConfigurationUpdateAcknowledge,
+	ENBConfigurationUpdateFailure,
+	MCEConfigurationUpdate,
+	MCEConfigurationUpdateAcknowledge,
+	MCEConfigurationUpdateFailure,
+	MbmsServiceCountingRequest,
+	MbmsServiceCountingResponse,
+	MbmsServiceCountingFailure,
+	MbmsServiceCountingResultsReport,
+	PrivateMessage,
+	MbmsOverloadNotification
+FROM M2AP-PDU-Contents
+
+	id-sessionStart,
+	id-sessionStop, 
+	id-sessionUpdate,
+	id-mbmsServiceCounting,
+	id-mbmsServiceCountingResultsReport,
+	id-mbmsSchedulingInformation,
+	id-errorIndication,
+	id-reset,
+	id-m2Setup,
+	id-eNBConfigurationUpdate,
+	id-mCEConfigurationUpdate,
+	id-privateMessage,
+	id-mbmsOverloadNotification
+FROM M2AP-Constants;
+
+
+-- **************************************************************
+--
+-- Interface Elementary Procedure Class
+--
+-- **************************************************************
+
+M2AP-ELEMENTARY-PROCEDURE ::= CLASS {
+	&InitiatingMessage				,
+	&SuccessfulOutcome				OPTIONAL,
+	&UnsuccessfulOutcome				OPTIONAL,
+	&procedureCode			ProcedureCode 	UNIQUE,
+	&criticality			Criticality 	DEFAULT ignore
+}
+WITH SYNTAX {
+	INITIATING MESSAGE		&InitiatingMessage
+	[SUCCESSFUL OUTCOME		&SuccessfulOutcome]
+	[UNSUCCESSFUL OUTCOME		&UnsuccessfulOutcome]
+	PROCEDURE CODE			&procedureCode
+	[CRITICALITY			&criticality]
+}
+
+-- **************************************************************
+--
+-- Interface PDU Definition
+--
+-- **************************************************************
+
+M2AP-PDU ::= CHOICE {
+	initiatingMessage	InitiatingMessage,
+	successfulOutcome	SuccessfulOutcome,
+	unsuccessfulOutcome	UnsuccessfulOutcome,
+	...
+}
+
+InitiatingMessage ::= SEQUENCE {
+	procedureCode	M2AP-ELEMENTARY-PROCEDURE.&procedureCode		({M2AP-ELEMENTARY-PROCEDURES}),
+	criticality		M2AP-ELEMENTARY-PROCEDURE.&criticality			({M2AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+	value			M2AP-ELEMENTARY-PROCEDURE.&InitiatingMessage	({M2AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+SuccessfulOutcome ::= SEQUENCE {
+	procedureCode	M2AP-ELEMENTARY-PROCEDURE.&procedureCode		({M2AP-ELEMENTARY-PROCEDURES}),
+	criticality		M2AP-ELEMENTARY-PROCEDURE.&criticality			({M2AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+	value			M2AP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome	({M2AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+UnsuccessfulOutcome ::= SEQUENCE {
+	procedureCode	M2AP-ELEMENTARY-PROCEDURE.&procedureCode		({M2AP-ELEMENTARY-PROCEDURES}),
+	criticality		M2AP-ELEMENTARY-PROCEDURE.&criticality			({M2AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+	value			M2AP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome	({M2AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+
+-- **************************************************************
+--
+-- Interface Elementary Procedure List
+--
+-- **************************************************************
+
+M2AP-ELEMENTARY-PROCEDURES M2AP-ELEMENTARY-PROCEDURE ::= {
+	M2AP-ELEMENTARY-PROCEDURES-CLASS-1			|
+	M2AP-ELEMENTARY-PROCEDURES-CLASS-2			,
+	...
+}
+
+M2AP-ELEMENTARY-PROCEDURES-CLASS-1 M2AP-ELEMENTARY-PROCEDURE ::= {
+	sessionStart											|
+	sessionStop												|
+	sessionUpdate											|
+	mbmsSchedulingInformation								|
+	reset													|
+	m2Setup													|
+	eNBConfigurationUpdate									|
+	mCEConfigurationUpdate									|
+	mbmsServiceCounting										,
+	...
+}
+
+M2AP-ELEMENTARY-PROCEDURES-CLASS-2 M2AP-ELEMENTARY-PROCEDURE ::= {
+	errorIndication							|
+	privateMessage							|
+	mbmsServiceCountingResultsReport		|
+	mbmsOverloadNotification				,
+	...
+
+}
+
+
+-- **************************************************************
+--
+-- Interface Elementary Procedures
+--
+-- **************************************************************
+
+sessionStart M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		SessionStartRequest
+	SUCCESSFUL OUTCOME		SessionStartResponse
+	UNSUCCESSFUL OUTCOME	SessionStartFailure
+	PROCEDURE CODE			id-sessionStart
+	CRITICALITY				reject
+}
+
+sessionStop M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		SessionStopRequest
+	SUCCESSFUL OUTCOME		SessionStopResponse
+	PROCEDURE CODE			id-sessionStop
+	CRITICALITY				reject
+}
+
+sessionUpdate M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		SessionUpdateRequest
+	SUCCESSFUL OUTCOME		SessionUpdateResponse
+	UNSUCCESSFUL OUTCOME	SessionUpdateFailure
+	PROCEDURE CODE			id-sessionUpdate
+	CRITICALITY				reject
+}
+
+mbmsSchedulingInformation M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MbmsSchedulingInformation
+	SUCCESSFUL OUTCOME		MbmsSchedulingInformationResponse
+	PROCEDURE CODE			id-mbmsSchedulingInformation
+	CRITICALITY				reject
+}
+
+errorIndication M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		ErrorIndication
+	PROCEDURE CODE			id-errorIndication
+	CRITICALITY				ignore
+}
+
+reset	M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		Reset
+	SUCCESSFUL OUTCOME		ResetAcknowledge
+	PROCEDURE CODE			id-reset
+	CRITICALITY				reject
+}
+
+m2Setup	M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		M2SetupRequest
+	SUCCESSFUL OUTCOME		M2SetupResponse
+	UNSUCCESSFUL OUTCOME	M2SetupFailure
+	PROCEDURE CODE			id-m2Setup
+	CRITICALITY				reject
+}
+
+eNBConfigurationUpdate		M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		ENBConfigurationUpdate
+	SUCCESSFUL OUTCOME		ENBConfigurationUpdateAcknowledge
+	UNSUCCESSFUL OUTCOME	ENBConfigurationUpdateFailure
+	PROCEDURE CODE			id-eNBConfigurationUpdate
+	CRITICALITY				reject
+}
+
+mCEConfigurationUpdate		M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MCEConfigurationUpdate
+	SUCCESSFUL OUTCOME		MCEConfigurationUpdateAcknowledge
+	UNSUCCESSFUL OUTCOME	MCEConfigurationUpdateFailure
+	PROCEDURE CODE			id-mCEConfigurationUpdate
+	CRITICALITY				reject
+}
+
+mbmsServiceCounting			M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MbmsServiceCountingRequest
+	SUCCESSFUL OUTCOME		MbmsServiceCountingResponse
+	UNSUCCESSFUL OUTCOME	MbmsServiceCountingFailure
+	PROCEDURE CODE			id-mbmsServiceCounting
+	CRITICALITY				reject
+}
+
+mbmsServiceCountingResultsReport	M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MbmsServiceCountingResultsReport
+	PROCEDURE CODE			id-mbmsServiceCountingResultsReport
+	CRITICALITY				reject
+}
+
+privateMessage			M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		PrivateMessage
+	PROCEDURE CODE			id-privateMessage
+	CRITICALITY				ignore
+}
+
+mbmsOverloadNotification	M2AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MbmsOverloadNotification
+	PROCEDURE CODE			id-mbmsOverloadNotification
+	CRITICALITY				reject
+}
+
+END
+
+-- **************************************************************
+--
+-- PDU definitions for M2AP.
+--
+-- **************************************************************
+
+M2AP-PDU-Contents {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m2ap (4) version1 (1) m2ap-PDU-Contents (1) }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+
+	Cause,
+	CriticalityDiagnostics,
+	ENB-MBMS-Configuration-data-Item,
+	ENB-MBMS-Configuration-data-ConfigUpdate-Item,
+	ENB-MBMS-M2AP-ID,
+	ENBname,
+	GlobalENB-ID,
+	GlobalMCE-ID,
+	MBSFN-Area-ID,
+	MBMS-Service-Area,
+	MBMS-Session-ID,
+	MBMSsessionListPerPMCH-Item,
+	MBMS-Service-associatedLogicalM2-ConnectionItem,
+	MBSFN-Subframe-Configuration,
+	MCCH-Update-Time,
+	MCCHrelatedBCCH-ConfigPerMBSFNArea-Item,
+	MCE-MBMS-M2AP-ID,
+	MCEname,
+	PMCH-Configuration,
+	Common-Subframe-Allocation-Period,
+	TimeToWait,
+	TMGI,
+	TNL-Information,
+	SFN,
+	MBMSsessionsToBeSuspendedListPerPMCH-Item,
+	SC-PTM-Information
+
+FROM M2AP-Ies
+
+	PrivateIE-Container{},
+	ProtocolExtensionContainer{},
+	ProtocolIE-Container{},
+	ProtocolIE-ContainerList{},
+	ProtocolIE-ContainerPair{},
+	ProtocolIE-ContainerPairList{},
+	ProtocolIE-Single-Container{},
+	M2AP-PRIVATE-IES,
+	M2AP-PROTOCOL-EXTENSION,
+	M2AP-PROTOCOL-IES,
+	M2AP-PROTOCOL-IES-PAIR
+FROM M2AP-Containers
+
+	id-MCE-MBMS-M2AP-ID,
+	id-ENB-MBMS-M2AP-ID,
+	id-TMGI,
+	id-MBMS-Session-ID,
+	id-MBMS-Service-Area,
+	id-TNL-Information,
+	id-Alternative-TNL-Information,
+	id-CriticalityDiagnostics,
+	id-Cause,
+	id-MBSFN-Area-Configuration-List,
+	id-MBSFN-Subframe-Configuration-Item,
+	id-MBSFN-Subframe-Configuration-List,
+	id-MCCH-Update-Time,
+	id-PMCH-Configuration-List,
+	id-PMCH-Configuration-Item,
+	id-Common-Subframe-Allocation-Period,
+	id-GlobalENB-ID,
+	id-ENBname,
+	id-ENB-MBMS-Configuration-data-List,
+	id-ENB-MBMS-Configuration-data-Item,
+	id-GlobalMCE-ID,
+	id-MCEname,
+	id-MCCHrelatedBCCH-ConfigPerMBSFNArea,
+	id-MCCHrelatedBCCH-ConfigPerMBSFNArea-Item,
+	id-TimeToWait,
+	id-ENB-MBMS-Configuration-data-List-ConfigUpdate,
+	id-ENB-MBMS-Configuration-data-ConfigUpdate-Item,
+	id-MBSFN-Area-ID,
+	id-ResetType,
+	id-MBMS-Service-associatedLogicalM2-ConnectionItem,
+	id-MBMS-Service-associatedLogicalM2-ConnectionListResAck,
+	id-MBMS-Counting-Request-Session,
+	id-MBMS-Counting-Request-Session-Item,
+	id-MBMS-Counting-Result-List,
+	id-MBMS-Counting-Result-Item,
+	id-MBMS-Suspension-Notification-List,
+	id-MBMS-Suspension-Notification-Item,
+	id-PMCH-Overload-Status,
+	id-Overload-Status-Per-PMCH-List,
+	id-Active-MBMS-Session-List,
+	id-SC-PTM-Information,
+	maxnoofMBSFN-Allocations,
+	maxnoofMBSFNareas,
+	maxnoofPMCHsperMBSFNarea,
+	maxnoofCells,
+	maxnoofMBMSServiceAreasPerCell,
+	maxnoofSessionsPerPMCH,
+	maxnooferrors,
+	maxNrOfIndividualM2ConnectionsToReset,
+	maxnoofCountingService
+
+FROM M2AP-Constants;
+
+-- **************************************************************
+--
+-- SESSION START REQUEST
+--
+-- **************************************************************
+
+SessionStartRequest ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{SessionStartRequest-Ies}},
+	...
+}
+
+SessionStartRequest-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID					CRITICALITY reject	TYPE MCE-MBMS-M2AP-ID					PRESENCE mandatory}|
+	{ ID id-TMGI								CRITICALITY reject	TYPE TMGI								PRESENCE mandatory}|
+	{ ID id-MBMS-Session-ID						CRITICALITY ignore	TYPE MBMS-Session-ID					PRESENCE optional}|
+	{ ID id-MBMS-Service-Area					CRITICALITY reject	TYPE MBMS-Service-Area					PRESENCE mandatory}|
+	{ ID id-TNL-Information						CRITICALITY reject	TYPE TNL-Information					PRESENCE mandatory}|
+	{ ID id-Alternative-TNL-Information			CRITICALITY ignore	TYPE TNL-Information					PRESENCE optional}|
+	{ ID id-SC-PTM-Information					CRITICALITY reject	TYPE SC-PTM-Information					PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- SESSION START RESPONSE
+--
+-- **************************************************************
+
+SessionStartResponse ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ SessionStartResponse-Ies}},
+	...
+}
+
+SessionStartResponse-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-ENB-MBMS-M2AP-ID					CRITICALITY ignore	TYPE ENB-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  },
+	...
+}
+
+
+-- **************************************************************
+--
+-- SESSION START FAILURE
+--
+-- **************************************************************
+
+SessionStartFailure ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ SessionStartFailure-Ies}},
+	...
+}
+
+SessionStartFailure-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-Cause								CRITICALITY ignore	TYPE Cause								PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  },
+	...
+}
+
+
+-- **************************************************************
+--
+-- SESSION STOP REQUEST
+--
+-- **************************************************************
+
+SessionStopRequest ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{SessionStopRequest-Ies}},
+	...
+}
+
+SessionStopRequest-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID					CRITICALITY reject	TYPE MCE-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-ENB-MBMS-M2AP-ID					CRITICALITY reject	TYPE ENB-MBMS-M2AP-ID					PRESENCE mandatory } ,
+	...
+}
+
+-- **************************************************************
+--
+-- SESSION STOP RESPONSE
+--
+-- **************************************************************
+
+SessionStopResponse ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ SessionStopResponse-Ies}},
+	...
+}
+
+SessionStopResponse-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-ENB-MBMS-M2AP-ID					CRITICALITY ignore	TYPE ENB-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  } ,
+	...
+}
+
+-- **************************************************************
+--
+-- SESSION UPDATE REQUEST
+--
+-- **************************************************************
+
+SessionUpdateRequest ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{SessionUpdateRequest-Ies}},
+	...
+}
+
+SessionUpdateRequest-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID			CRITICALITY reject	TYPE MCE-MBMS-M2AP-ID					PRESENCE mandatory}|
+	{ ID id-ENB-MBMS-M2AP-ID			CRITICALITY reject	TYPE ENB-MBMS-M2AP-ID					PRESENCE mandatory}|
+	{ ID id-TMGI						CRITICALITY reject	TYPE TMGI		 						PRESENCE mandatory}|
+	{ ID id-MBMS-Session-ID				CRITICALITY ignore	TYPE MBMS-Session-ID					PRESENCE optional}|
+	{ ID id-MBMS-Service-Area			CRITICALITY ignore	TYPE MBMS-Service-Area					PRESENCE optional}|
+	{ ID id-TNL-Information				CRITICALITY reject	TYPE TNL-Information					PRESENCE optional}|
+	{ ID id-SC-PTM-Information			CRITICALITY reject	TYPE SC-PTM-Information					PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- SESSION UPDATE RESPONSE
+--
+-- **************************************************************
+
+SessionUpdateResponse ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ SessionUpdateResponse-Ies}},
+	...
+}
+
+SessionUpdateResponse-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-ENB-MBMS-M2AP-ID					CRITICALITY ignore	TYPE ENB-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  },
+	...
+}
+-- **************************************************************
+--
+-- SESSION UPDATE FAILURE
+--
+-- **************************************************************
+
+SessionUpdateFailure ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ SessionUpdateFailure-Ies}},
+	...
+}
+
+SessionUpdateFailure-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-ENB-MBMS-M2AP-ID					CRITICALITY ignore	TYPE ENB-MBMS-M2AP-ID					PRESENCE mandatory } |
+	{ ID id-Cause								CRITICALITY ignore	TYPE Cause								PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  },
+	...
+}
+
+-- **************************************************************
+--
+-- MBMS SCHEDULING INFORMATION
+--
+-- **************************************************************
+
+MbmsSchedulingInformation ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MbmsSchedulingInformation-Ies}},
+	...
+}
+
+MbmsSchedulingInformation-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCCH-Update-Time					CRITICALITY reject	TYPE MCCH-Update-Time						PRESENCE mandatory }|
+	{ ID id-MBSFN-Area-Configuration-List		CRITICALITY reject	TYPE MBSFN-Area-Configuration-List			PRESENCE mandatory },
+	...
+}
+
+MBSFN-Area-Configuration-List ::= SEQUENCE (SIZE(1.. maxnoofMBSFNareas)) OF ProtocolIE-Container { { MBSFN-Area-Configuration-Item } }
+
+MBSFN-Area-Configuration-Item M2AP-PROTOCOL-IES ::= {
+	{ ID id-PMCH-Configuration-List				CRITICALITY reject	TYPE PMCH-Configuration-List				PRESENCE mandatory }|
+	{ ID id-MBSFN-Subframe-Configuration-List	CRITICALITY reject	TYPE MBSFN-Subframe-ConfigurationList		PRESENCE mandatory }|
+	{ ID id-Common-Subframe-Allocation-Period	CRITICALITY reject	TYPE Common-Subframe-Allocation-Period		PRESENCE mandatory }|
+	{ ID id-MBSFN-Area-ID						CRITICALITY reject	TYPE MBSFN-Area-ID							PRESENCE mandatory }|
+	{ ID id-MBMS-Suspension-Notification-List	CRITICALITY ignore	TYPE MBMS-Suspension-Notification-List		PRESENCE optional },
+	...
+}
+
+PMCH-Configuration-List ::= SEQUENCE (SIZE(0.. maxnoofPMCHsperMBSFNarea)) OF ProtocolIE-Single-Container { { PMCH-Configuration-ItemIEs } }
+
+PMCH-Configuration-ItemIEs M2AP-PROTOCOL-IES ::= {
+	{ ID id-PMCH-Configuration-Item	 CRITICALITY reject	TYPE PMCH-Configuration-Item	PRESENCE mandatory },
+	...
+}
+
+PMCH-Configuration-Item ::= SEQUENCE {
+	pmch-Configuration				PMCH-Configuration,
+	mbms-Session-List				MBMSsessionListPerPMCH-Item,
+	iE-Extensions					ProtocolExtensionContainer { { PMCH-Configuration-ItemExtIEs} } OPTIONAL,
+	...
+}
+
+PMCH-Configuration-ItemExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+MBSFN-Subframe-ConfigurationList ::= SEQUENCE (SIZE(1.. maxnoofMBSFN-Allocations)) OF ProtocolIE-Single-Container { { MBSFN-Subframe-ConfigurationItem } }
+
+MBSFN-Subframe-ConfigurationItem M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBSFN-Subframe-Configuration-Item		CRITICALITY reject	TYPE MBSFN-Subframe-Configuration		PRESENCE mandatory },
+	...
+}
+
+MBMS-Suspension-Notification-List ::= SEQUENCE (SIZE(1.. maxnoofPMCHsperMBSFNarea)) OF ProtocolIE-Single-Container { { MBMS-Suspension-Notification-ItemIEs } }
+
+MBMS-Suspension-Notification-ItemIEs M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Suspension-Notification-Item	CRITICALITY ignore	TYPE MBMS-Suspension-Notification-Item	PRESENCE optional},
+	...
+}
+
+MBMS-Suspension-Notification-Item ::= SEQUENCE {
+	sfn											SFN,
+	mbms-Sessions-To-Be-Suspended-List			MBMSsessionsToBeSuspendedListPerPMCH-Item,
+	iE-Extensions								ProtocolExtensionContainer { { MBMS-Suspension-Notification-ItemExtIEs} } OPTIONAL,
+	...
+}
+
+MBMS-Suspension-Notification-ItemExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+-- **************************************************************
+--
+-- MBMS SCHEDULING INFORMATION RESPONSE
+--
+-- **************************************************************
+
+MbmsSchedulingInformationResponse ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MbmsSchedulingInformationResponse-Ies}},
+	...
+}
+
+MbmsSchedulingInformationResponse-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional },
+	...
+}
+
+
+-- **************************************************************
+--
+-- M2 SETUP REQUEST
+--
+-- **************************************************************
+
+M2SetupRequest ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{M2SetupRequest-Ies}},
+	...
+}
+
+M2SetupRequest-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-GlobalENB-ID							CRITICALITY reject	TYPE GlobalENB-ID						PRESENCE mandatory}|
+	{ ID id-ENBname									CRITICALITY ignore	TYPE ENBname 							PRESENCE optional}|
+	{ ID id-ENB-MBMS-Configuration-data-List		CRITICALITY reject	TYPE ENB-MBMS-Configuration-data-List		PRESENCE mandatory},
+	...
+}
+
+ENB-MBMS-Configuration-data-List ::= SEQUENCE (SIZE(1.. maxnoofCells)) OF ProtocolIE-Single-Container { { ENB-MBMS-Configuration-data-ItemIEs } }
+
+ENB-MBMS-Configuration-data-ItemIEs M2AP-PROTOCOL-IES ::= {
+	{ ID id-ENB-MBMS-Configuration-data-Item	CRITICALITY reject	TYPE ENB-MBMS-Configuration-data-Item		PRESENCE mandatory },
+	...
+}
+
+
+-- **************************************************************
+--
+-- M2 SETUP RESPONSE
+--
+-- **************************************************************
+
+M2SetupResponse ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ M2SetupResponse-Ies}},
+	...
+}
+
+M2SetupResponse-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-GlobalMCE-ID							CRITICALITY reject	TYPE GlobalMCE-ID							PRESENCE mandatory }|
+	{ ID id-MCEname									CRITICALITY ignore	TYPE MCEname								PRESENCE optional }|
+	{ ID id-MCCHrelatedBCCH-ConfigPerMBSFNArea		CRITICALITY reject	TYPE MCCHrelatedBCCH-ConfigPerMBSFNArea			PRESENCE mandatory }|
+	{ ID id-CriticalityDiagnostics					CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional },
+	...
+}
+
+MCCHrelatedBCCH-ConfigPerMBSFNArea ::= SEQUENCE (SIZE(1.. maxnoofMBSFNareas)) OF ProtocolIE-Single-Container { { MCCHrelatedBCCH-ConfigPerMBSFNArea-ItemIEs } }
+
+MCCHrelatedBCCH-ConfigPerMBSFNArea-ItemIEs 	M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCCHrelatedBCCH-ConfigPerMBSFNArea-Item		CRITICALITY reject	TYPE MCCHrelatedBCCH-ConfigPerMBSFNArea-Item	PRESENCE mandatory },
+	...
+}
+
+-- **************************************************************
+--
+-- M2 SETUP FAILURE
+--
+-- **************************************************************
+
+M2SetupFailure ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ M2SetupFailure-Ies}},
+	...
+}
+
+M2SetupFailure-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-Cause						CRITICALITY ignore	TYPE Cause						PRESENCE mandatory}|
+	{ ID id-TimeToWait					CRITICALITY ignore	TYPE TimeToWait					PRESENCE optional}|
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics		PRESENCE optional},
+
+	...
+}
+
+-- **************************************************************
+--
+-- ENB CONFIGURATION UPDATE
+--
+-- **************************************************************
+
+ENBConfigurationUpdate ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ENBConfigurationUpdate-Ies}},
+	...
+}
+
+ENBConfigurationUpdate-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-GlobalENB-ID									CRITICALITY reject	TYPE GlobalENB-ID					PRESENCE optional }|
+	{ ID id-ENBname											CRITICALITY ignore	TYPE ENBname						PRESENCE optional }|
+	{ ID id-ENB-MBMS-Configuration-data-List-ConfigUpdate	CRITICALITY reject	TYPE ENB-MBMS-Configuration-data-List-ConfigUpdate	PRESENCE optional },
+	...
+}
+ENB-MBMS-Configuration-data-List-ConfigUpdate ::= SEQUENCE (SIZE(1.. maxnoofCells)) OF ProtocolIE-Single-Container { { ENB-MBMS-Configuration-data-ConfigUpdate-ItemIEs } }
+
+ENB-MBMS-Configuration-data-ConfigUpdate-ItemIEs 	M2AP-PROTOCOL-IES ::= {
+	{ ID id-ENB-MBMS-Configuration-data-ConfigUpdate-Item	CRITICALITY reject	TYPE ENB-MBMS-Configuration-data-ConfigUpdate-Item	PRESENCE mandatory },
+	...
+}
+
+-- **************************************************************
+--
+-- ENB CONFIGURATION UPDATE ACKNOWLEDGE
+--
+-- **************************************************************
+
+ENBConfigurationUpdateAcknowledge ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ ENBConfigurationUpdateAcknowledge-Ies}},
+	...
+}
+
+ENBConfigurationUpdateAcknowledge-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCCHrelatedBCCH-ConfigPerMBSFNArea				CRITICALITY reject	TYPE MCCHrelatedBCCH-ConfigPerMBSFNArea		PRESENCE optional }|
+	{ ID id-CriticalityDiagnostics							CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional },
+	...
+}
+
+
+-- **************************************************************
+--
+-- ENB CONFIGURATION UPDATE FAILURE
+--
+-- **************************************************************
+
+ENBConfigurationUpdateFailure ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ ENBConfigurationUpdateFailure-Ies}},
+	...
+}
+
+ENBConfigurationUpdateFailure-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-Cause						CRITICALITY ignore	TYPE Cause						PRESENCE mandatory}|
+	{ ID id-TimeToWait					CRITICALITY ignore	TYPE TimeToWait					PRESENCE optional}|
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics		PRESENCE optional},
+
+	...
+}
+
+
+-- **************************************************************
+--
+-- MCE CONFIGURATION UPDATE
+--
+-- **************************************************************
+
+MCEConfigurationUpdate ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{MCEConfigurationUpdate-Ies}},
+	...
+}
+
+MCEConfigurationUpdate-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-GlobalMCE-ID							CRITICALITY reject	TYPE GlobalMCE-ID						PRESENCE optional }|
+	{ ID id-MCEname									CRITICALITY ignore	TYPE MCEname							PRESENCE optional }|
+	{ ID id-MCCHrelatedBCCH-ConfigPerMBSFNArea		CRITICALITY reject	TYPE MCCHrelatedBCCH-ConfigPerMBSFNArea		PRESENCE optional },
+	...
+}
+
+-- **************************************************************
+--
+-- MCE CONFIGURATION UPDATE ACKNOWLEDGE
+--
+-- **************************************************************
+
+MCEConfigurationUpdateAcknowledge ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MCEConfigurationUpdateAcknowledge-Ies}},
+	...
+}
+
+MCEConfigurationUpdateAcknowledge-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics		PRESENCE optional},
+	...
+}
+
+
+-- **************************************************************
+--
+-- MCE CONFIGURATION UPDATE FAILURE
+--
+-- **************************************************************
+
+MCEConfigurationUpdateFailure ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MCEConfigurationUpdateFailure-Ies}},
+	...
+}
+
+MCEConfigurationUpdateFailure-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-Cause						CRITICALITY ignore	TYPE Cause						PRESENCE mandatory}|
+	{ ID id-TimeToWait					CRITICALITY ignore	TYPE TimeToWait					PRESENCE optional}|
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics		PRESENCE optional},
+
+	...
+}
+
+
+-- **************************************************************
+--
+-- ERROR INDICATION
+--
+-- **************************************************************
+
+ErrorIndication ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ErrorIndication-Ies}},
+	...
+}
+
+ErrorIndication-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCE-MBMS-M2AP-ID				CRITICALITY ignore	TYPE MCE-MBMS-M2AP-ID				PRESENCE optional}|
+	{ ID id-ENB-MBMS-M2AP-ID				CRITICALITY ignore	TYPE ENB-MBMS-M2AP-ID				PRESENCE optional}|
+	{ ID id-Cause							CRITICALITY ignore	TYPE Cause							PRESENCE optional}|
+	{ ID id-CriticalityDiagnostics			CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- RESET
+--
+-- **************************************************************
+
+Reset ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{Reset-Ies}},
+	...
+}
+
+Reset-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-Cause					CRITICALITY ignore	TYPE Cause				PRESENCE mandatory}|
+	{ ID id-ResetType				CRITICALITY reject	TYPE ResetType			PRESENCE mandatory},
+	...
+}
+
+ResetType ::= CHOICE {
+	m2-Interface			ResetAll,
+	partOfM2-Interface		MBMS-Service-associatedLogicalM2-ConnectionListRes,
+	...
+}
+
+ResetAll ::= ENUMERATED {
+	reset-all,
+	...
+}
+
+MBMS-Service-associatedLogicalM2-ConnectionListRes ::= SEQUENCE (SIZE(1.. maxNrOfIndividualM2ConnectionsToReset)) OF ProtocolIE-Single-Container { { MBMS-Service-associatedLogicalM2-ConnectionItemRes } }
+
+MBMS-Service-associatedLogicalM2-ConnectionItemRes 	M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Service-associatedLogicalM2-ConnectionItem	CRITICALITY reject	TYPE MBMS-Service-associatedLogicalM2-ConnectionItem	PRESENCE mandatory},
+	...
+}
+
+-- **************************************************************
+--
+-- RESET ACKNOWLEDGE
+--
+-- **************************************************************
+
+ResetAcknowledge ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ResetAcknowledge-Ies}},
+	...
+}
+
+ResetAcknowledge-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Service-associatedLogicalM2-ConnectionListResAck	CRITICALITY ignore	TYPE MBMS-Service-associatedLogicalM2-ConnectionListResAck		PRESENCE optional}|
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional},
+	...
+}
+
+MBMS-Service-associatedLogicalM2-ConnectionListResAck ::= SEQUENCE (SIZE(1.. maxNrOfIndividualM2ConnectionsToReset)) OF ProtocolIE-Single-Container { { MBMS-Service-associatedLogicalM2-ConnectionItemResAck } }
+
+MBMS-Service-associatedLogicalM2-ConnectionItemResAck 	M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Service-associatedLogicalM2-ConnectionItem	CRITICALITY ignore	TYPE MBMS-Service-associatedLogicalM2-ConnectionItem	PRESENCE mandatory},
+	...
+}
+
+
+-- **************************************************************
+--
+-- PRIVATE MESSAGE
+--
+-- **************************************************************
+
+PrivateMessage ::= SEQUENCE {
+	privateIEs		PrivateIE-Container  {{PrivateMessage-Ies}},
+	...
+}
+
+PrivateMessage-Ies M2AP-PRIVATE-IES ::= {
+	...
+}
+
+
+-- **************************************************************
+--
+-- MBMS SERVICE COUNTING REQUEST
+--
+-- **************************************************************
+
+MbmsServiceCountingRequest ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container	{{MbmsServiceCountingRequest-Ies}},
+	...
+}
+
+MbmsServiceCountingRequest-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MCCH-Update-Time						CRITICALITY reject	TYPE MCCH-Update-Time				PRESENCE mandatory }|
+	{ ID id-MBSFN-Area-ID							CRITICALITY reject	TYPE MBSFN-Area-ID					PRESENCE mandatory }|
+	{ ID id-MBMS-Counting-Request-Session			CRITICALITY reject	TYPE MBMS-Counting-Request-Session	PRESENCE mandatory },
+	...
+}
+
+MBMS-Counting-Request-Session ::= SEQUENCE (SIZE(1.. maxnoofCountingService)) OF ProtocolIE-Container { { MBMS-Counting-Request-Session-Item } }
+
+MBMS-Counting-Request-Session-Item M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Counting-Request-Session-Item	CRITICALITY reject	TYPE MBMS-Counting-Request-SessionIE		PRESENCE mandatory },
+	...
+}
+
+MBMS-Counting-Request-SessionIE ::= SEQUENCE{
+	tmgi					TMGI,
+	iE-Extensions			ProtocolExtensionContainer { { MBMS-Counting-Request-SessionIE-ExtIEs} } OPTIONAL,
+	...
+}
+
+MBMS-Counting-Request-SessionIE-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+-- **************************************************************
+--
+-- MBMS SERVICE COUNTING RESPONSE
+--
+-- **************************************************************
+
+MbmsServiceCountingResponse ::= SEQUENCE {
+	protocolIEs		ProtocolIE-Container		{{MbmsServiceCountingResponse-Ies}},
+	...
+}
+
+MbmsServiceCountingResponse-Ies M2AP-PROTOCOL-IES ::= {
+
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional },
+	...
+}
+
+
+-- **************************************************************
+--
+-- MBMS SERVICE COUNTING FAILURE
+--
+-- **************************************************************
+
+MbmsServiceCountingFailure ::= SEQUENCE {
+	protocolIEs		ProtocolIE-Container		{{ MbmsServiceCountingFailure-Ies}},
+	...
+}
+
+MbmsServiceCountingFailure-Ies M2AP-PROTOCOL-IES ::= {
+
+	{ ID id-Cause								CRITICALITY ignore	TYPE Cause							PRESENCE mandatory}|
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional},
+	...
+}
+
+
+-- **************************************************************
+--
+-- MBMS SERVICE COUNTING RESULTS REPORT
+--
+-- **************************************************************
+
+MbmsServiceCountingResultsReport ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container		{{ MbmsServiceCountingResultsReport-Ies}},
+	...
+}
+
+MbmsServiceCountingResultsReport-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBSFN-Area-ID					CRITICALITY reject	TYPE MBSFN-Area-ID						PRESENCE mandatory}|
+	{ ID id-MBMS-Counting-Result-List		CRITICALITY reject	TYPE MBMS-Counting-Result-List			PRESENCE mandatory},
+	...
+}
+
+MBMS-Counting-Result-List ::= SEQUENCE (SIZE(1.. maxnoofCountingService)) OF ProtocolIE-Container { { MBMS-Counting-Result-Item } }
+
+MBMS-Counting-Result-Item M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Counting-Result-Item		CRITICALITY reject	TYPE MBMS-Counting-Result		PRESENCE mandatory },
+	...
+}
+
+MBMS-Counting-Result ::= SEQUENCE{
+	tmgi				TMGI,
+	countingResult		CountingResult,
+	iE-Extensions		ProtocolExtensionContainer { { MBMS-Counting-Result-ExtIEs} } OPTIONAL,
+	...
+}
+
+MBMS-Counting-Result-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+CountingResult ::= INTEGER (0..1023)
+
+-- **************************************************************
+--
+-- MBMS OVERLOAD NOTIFICATION
+--
+-- **************************************************************
+
+MbmsOverloadNotification ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container		{{ MbmsOverloadNotification-Ies}},
+	...
+}
+
+MbmsOverloadNotification-Ies M2AP-PROTOCOL-IES ::= {
+	{ ID id-MBSFN-Area-ID						CRITICALITY reject	TYPE MBSFN-Area-ID						PRESENCE mandatory}|
+	{ ID id-Overload-Status-Per-PMCH-List		CRITICALITY reject	TYPE Overload-Status-Per-PMCH-List		PRESENCE mandatory},
+	...
+}
+
+Overload-Status-Per-PMCH-List ::= SEQUENCE (SIZE(1..maxnoofPMCHsperMBSFNarea)) OF ProtocolIE-Container { { Overload-Status-Per-PMCH-Item } }
+
+Overload-Status-Per-PMCH-Item M2AP-PROTOCOL-IES ::= {
+	{ ID id-PMCH-Overload-Status			CRITICALITY reject	TYPE PMCH-Overload-Status			PRESENCE mandatory }|
+	{ ID id-Active-MBMS-Session-List		CRITICALITY reject	TYPE Active-MBMS-Session-List		PRESENCE optional },
+	...
+}
+
+PMCH-Overload-Status ::= ENUMERATED {normal, overload, ...}
+
+Active-MBMS-Session-List ::= SEQUENCE (SIZE(1..maxnoofSessionsPerPMCH)) OF ProtocolIE-Container { { Active-MBMS-Session-Item } }
+
+Active-MBMS-Session-Item M2AP-PROTOCOL-IES ::= {
+	{ ID id-TMGI		CRITICALITY reject	TYPE TMGI		PRESENCE mandatory },
+	...
+}
+
+END
+
+-- **************************************************************
+--
+-- Information Element Definitions
+--
+-- **************************************************************
+
+M2AP-Ies {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m2ap (4) version1 (1) m2ap-Ies (2) }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+IMPORTS
+	id-MCH-Scheduling-PeriodExtended,
+	id-MCH-Scheduling-PeriodExtended2,
+	id-Modification-PeriodExtended,
+	id-Modulation-Coding-Scheme2,
+	id-Repetition-PeriodExtended,
+	id-Subcarrier-SpacingMBMS,
+	id-SubframeAllocationExtended,
+	maxnoofMBSFNareas,
+	maxnoofPMCHsperMBSFNarea,
+	maxnoofCells,
+	maxnoofMBMSServiceAreasPerCell,
+	maxnoofSessionsPerPMCH,
+	maxnooferrors,
+	maxnoofCellsforMBMS
+
+FROM M2AP-Constants
+
+	Criticality,
+	ProcedureCode,
+	ProtocolIE-ID,
+	TriggeringMessage
+FROM M2AP-CommonDataTypes
+
+	ProtocolExtensionContainer{},
+	ProtocolIE-Single-Container{},
+	M2AP-PROTOCOL-EXTENSION,
+	M2AP-PROTOCOL-IES
+FROM M2AP-Containers;
+
+-- A
+
+AllocatedSubframesEnd ::= INTEGER (0..1535)
+
+AllocationAndRetentionPriority ::= SEQUENCE {
+	priorityLevel				PriorityLevel,
+	pre-emptionCapability		Pre-emptionCapability,
+	pre-emptionVulnerability	Pre-emptionVulnerability,
+	iE-Extensions				ProtocolExtensionContainer { {AllocationAndRetentionPriority-ExtIEs} } OPTIONAL
+}
+
+AllocationAndRetentionPriority-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+-- B
+
+BitRate ::= INTEGER (0..10000000000)
+
+-- C
+
+Cause ::= CHOICE {
+	radioNetwork		CauseRadioNetwork,
+	transport			CauseTransport,
+	nAS					CauseNAS,
+	protocol			CauseProtocol,
+	misc				CauseMisc,
+	...
+}
+
+CauseMisc ::= ENUMERATED {
+	control-processing-overload,
+	hardware-failure,
+	om-intervention,
+	unspecified,
+	...
+}
+
+CauseNAS ::= ENUMERATED {
+	unspecified,
+	...
+}
+
+CauseProtocol ::= ENUMERATED {
+	transfer-syntax-error,
+	abstract-syntax-error-reject,
+	abstract-syntax-error-ignore-and-notify,
+	message-not-compatible-with-receiver-state,
+	semantic-error,
+	abstract-syntax-error-falsely-constructed-message,
+	unspecified,
+	...
+}
+
+CauseRadioNetwork ::= ENUMERATED {
+	unknown-or-already-allocated-MCE-MBMS-M2AP-ID,
+	unknown-or-already-allocated-eNB-MBMS-M2AP-ID,
+	unknown-or-inconsistent-pair-of-MBMS-M2AP-IDs,
+	radio-resources-not-available,
+	interaction-with-other-procedure,
+	unspecified,
+	...,
+	invalid-QoS-combination,
+	not-supported-QCI-value
+
+}
+
+CauseTransport ::= ENUMERATED {
+	transport-resource-unavailable,
+	unspecified,
+	...
+}
+
+Cell-Information ::= SEQUENCE {
+	eCGI							ECGI,
+	cellReservationInfo			ENUMERATED {reservedCell, nonReservedCell, ...},
+	iE-Extensions					ProtocolExtensionContainer { { Cell-Information-ExtIEs} } OPTIONAL,
+	...
+}
+
+Cell-Information-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+Cell-Information-List ::= SEQUENCE (SIZE(1..maxnoofCells)) OF Cell-Information
+
+CriticalityDiagnostics ::= SEQUENCE {
+	procedureCode					ProcedureCode					OPTIONAL,
+	triggeringMessage				TriggeringMessage				OPTIONAL,
+	procedureCriticality			Criticality						OPTIONAL,
+	iEsCriticalityDiagnostics		CriticalityDiagnostics-IE-List	OPTIONAL,
+	iE-Extensions					ProtocolExtensionContainer { {CriticalityDiagnostics-ExtIEs} }	OPTIONAL,
+	...
+}
+
+
+CriticalityDiagnostics-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+CriticalityDiagnostics-IE-List ::= SEQUENCE (SIZE (1..maxnooferrors)) OF
+	SEQUENCE {
+		iECriticality			Criticality,
+		iE-ID					ProtocolIE-ID,
+		typeOfError				TypeOfError,
+		iE-Extensions			ProtocolExtensionContainer { {CriticalityDiagnostics-IE-List-ExtIEs} } OPTIONAL,
+		...
+}
+
+CriticalityDiagnostics-IE-List-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+
+-- D
+-- E
+
+ECGI ::= SEQUENCE {
+	pLMN-Identity				PLMN-Identity,
+	eUTRANcellIdentifier		EUTRANCellIdentifier,
+	iE-Extensions				ProtocolExtensionContainer { {ECGI-ExtIEs} } OPTIONAL,
+	...
+}
+
+ECGI-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+
+ENB-ID ::= CHOICE {
+	macro-eNB-ID	BIT STRING (SIZE (20)),
+	... ,
+	short-Macro-eNB-ID		BIT STRING (SIZE(18)),
+	long-Macro-eNB-ID		BIT STRING (SIZE(21))
+}
+
+ENB-MBMS-Configuration-data-Item ::= SEQUENCE {
+	eCGI							ECGI,
+	mbsfnSynchronisationArea		MBSFN-SynchronisationArea-ID,
+	mbmsServiceAreaList				MBMS-Service-Area-ID-List,
+	iE-Extensions					ProtocolExtensionContainer { { ENB-MBMS-Configuration-data-Item-ExtIEs} } OPTIONAL,
+	...
+}
+
+ENB-MBMS-Configuration-data-Item-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+ENB-MBMS-Configuration-data-ConfigUpdate-Item ::= CHOICE {
+	mBMSConfigData					ENB-MBMS-Configuration-data-Item,
+	eCGI							ECGI,
+	...
+}
+
+ENB-MBMS-M2AP-ID ::= INTEGER (0..65535)
+
+ENBname ::= PrintableString (SIZE (1..150,...))
+
+EUTRANCellIdentifier ::= BIT STRING (SIZE (28))
+
+
+-- F
+-- G
+
+GBR-QosInformation ::= SEQUENCE {
+	mBMS-E-RAB-MaximumBitrateDL			BitRate,
+	mBMS-E-RAB-GuaranteedBitrateDL		BitRate,
+	iE-Extensions						ProtocolExtensionContainer { { GBR-QosInformation-ExtIEs} } OPTIONAL,
+	...
+}
+
+GBR-QosInformation-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+GlobalENB-ID ::= SEQUENCE {
+	pLMN-Identity			PLMN-Identity,
+	eNB-ID					ENB-ID,
+	iE-Extensions			ProtocolExtensionContainer { {GlobalENB-ID-ExtIEs} } OPTIONAL,
+	...
+}
+
+GlobalENB-ID-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+GlobalMCE-ID ::= SEQUENCE {
+	pLMN-Identity			PLMN-Identity,
+	mCE-ID					MCE-ID,
+	iE-Extensions			ProtocolExtensionContainer { {GlobalMCE-ID-ExtIEs} } OPTIONAL,
+	...
+}
+
+GlobalMCE-ID-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+GTP-TEID ::= OCTET STRING (SIZE (4))
+
+-- H
+-- I
+
+IPAddress ::= OCTET STRING (SIZE(4..16))
+
+-- J
+-- K
+-- L
+
+LCID ::= INTEGER (0..28)
+
+-- M
+
+MBMS-Cell-List ::= SEQUENCE (SIZE(1.. maxnoofCellsforMBMS)) OF ECGI
+
+MBMS-E-RAB-QoS-Parameters ::= SEQUENCE {
+	qCI								QCI,
+	gbrQosInformation				GBR-QosInformation		OPTIONAL,
+	allocationAndRetentionPriority	AllocationAndRetentionPriority,
+	iE-Extensions					ProtocolExtensionContainer { { MBMS-E-RAB-QoS-Parameters-ExtIEs} }	OPTIONAL,
+	...
+}
+
+MBMS-E-RAB-QoS-Parameters-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+MBMS-Service-associatedLogicalM2-ConnectionItem ::= SEQUENCE {
+	eNB-MBMS-M2AP-ID				ENB-MBMS-M2AP-ID OPTIONAL,
+	mCE-MBMS-M2AP-ID				MCE-MBMS-M2AP-ID OPTIONAL,
+	iE-Extensions					ProtocolExtensionContainer { { MBMS-Service-associatedLogicalM2-ConnectionItemExtIEs} } OPTIONAL,
+	...
+}
+
+
+MBMS-Service-associatedLogicalM2-ConnectionItemExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+MBMS-Service-Area ::= OCTET STRING
+
+MBMS-Service-Area-ID-List ::= SEQUENCE (SIZE(1..maxnoofMBMSServiceAreasPerCell)) OF MBMS-Service-Area
+
+MBMS-Session-ID ::= OCTET STRING (SIZE (1))
+
+MBMSsessionListPerPMCH-Item ::= SEQUENCE (SIZE(1..maxnoofSessionsPerPMCH)) OF SEQUENCE {
+	tmgi							TMGI,
+	lcid							LCID,
+	iE-Extensions					ProtocolExtensionContainer { { MBMSsessionListPerPMCH-Item-ExtIEs} } OPTIONAL,
+	...
+}
+
+MBMSsessionListPerPMCH-Item-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+MBMSsessionsToBeSuspendedListPerPMCH-Item ::= SEQUENCE (SIZE(1..maxnoofSessionsPerPMCH)) OF SEQUENCE {
+	tmgi							TMGI,
+	iE-Extensions					ProtocolExtensionContainer { { MBMSsessionsToBeSuspendedListPerPMCH-Item-ExtIEs} } OPTIONAL,
+	...
+}
+
+MBMSsessionsToBeSuspendedListPerPMCH-Item-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+MBSFN-Area-ID ::= INTEGER (0..255)
+
+MBSFN-SynchronisationArea-ID ::= INTEGER (0..65535)
+
+MBSFN-Subframe-Configuration ::= SEQUENCE {
+	radioframeAllocationPeriod		ENUMERATED {n1, n2, n4, n8, n16, n32},
+	radioframeAllocationOffset		INTEGER (0..7),
+	subframeAllocation				CHOICE {
+		oneFrame						BIT STRING (SIZE (6)  ),
+		fourFrames						BIT STRING (SIZE (24) ) },
+	iE-Extensions					ProtocolExtensionContainer { { MBSFN-Subframe-Configuration-ExtIEs} } OPTIONAL,
+	...
+}
+
+MBSFN-Subframe-Configuration-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	{ID id-SubframeAllocationExtended		CRITICALITY reject	EXTENSION SubframeAllocationExtended	PRESENCE optional},
+	...
+}
+
+MCCH-Update-Time ::= INTEGER (0..255)
+
+MCCHrelatedBCCH-ConfigPerMBSFNArea-Item ::= SEQUENCE {
+	mbsfnArea						MBSFN-Area-ID,
+	pdcchLength						ENUMERATED {s1, s2, ...},
+	repetitionPeriod				ENUMERATED {rf32, rf64, rf128, rf256},
+	offset							INTEGER (0..10),
+	modificationPeriod				ENUMERATED {rf512, rf1024},
+	subframeAllocationInfo			BIT STRING (SIZE(6)),
+	modulationAndCodingScheme		ENUMERATED {n2, n7, n13, n19},
+	cellInformationList				Cell-Information-List	OPTIONAL,
+	iE-Extensions					ProtocolExtensionContainer { { MCCHrelatedBCCH-ConfigPerMBSFNArea-Item-ExtIEs} } OPTIONAL,
+	...
+}
+
+MCCHrelatedBCCH-ConfigPerMBSFNArea-Item-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+-- Extension for Rel-14 to support MCCH repetition period values –-
+	{ID id-Repetition-PeriodExtended			CRITICALITY reject	EXTENSION Repetition-PeriodExtended	PRESENCE optional}|
+-- Extension for Rel-14 to support MCCH modification period values –-
+	{ID id-Modification-PeriodExtended			CRITICALITY reject	EXTENSION Modification-PeriodExtended	PRESENCE optional}|
+	{ID id-Subcarrier-SpacingMBMS				CRITICALITY reject	EXTENSION Subcarrier-SpacingMBMS		PRESENCE optional},
+	...
+}
+
+MCE-ID ::= OCTET STRING (SIZE(2))
+
+MCE-MBMS-M2AP-ID ::= INTEGER (0.. 16777215)
+
+MCEname ::= PrintableString (SIZE (1..150,...))
+
+
+MCH-Scheduling-Period ::= ENUMERATED {rf8, rf16, rf32, rf64, rf128, rf256, rf512, rf1024}
+
+MCH-Scheduling-PeriodExtended ::= ENUMERATED {rf4, ...}
+
+MCH-Scheduling-PeriodExtended2 ::= ENUMERATED {rf1, rf2, ...}
+
+
+Modulation-Coding-Scheme2 ::= INTEGER (0..27)
+
+Modification-PeriodExtended ::= ENUMERATED {rf1, rf2, rf4, rf8, rf16, rf32, rf64, rf128, rf256, ...}
+
+-- N
+-- O
+-- P
+
+PLMN-Identity ::= OCTET STRING (SIZE(3))
+
+PMCH-Configuration ::= SEQUENCE {
+	allocatedSubframesEnd			AllocatedSubframesEnd,
+	dataMCS							INTEGER (0..28),
+	mchSchedulingPeriod				MCH-Scheduling-Period,
+	iE-Extensions					ProtocolExtensionContainer { {PMCH-Configuration-ExtIEs} } OPTIONAL,
+	...
+}
+
+PMCH-Configuration-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+-- Extension for Rel-12 to support 256QAM for MTCH –
+	{ID id-Modulation-Coding-Scheme2			CRITICALITY reject	EXTENSION Modulation-Coding-Scheme2		PRESENCE optional}|
+-- Extension for Rel-12 to support shorter MCH scheduling period –
+	{ID id-MCH-Scheduling-PeriodExtended		CRITICALITY reject	EXTENSION MCH-Scheduling-PeriodExtended	PRESENCE optional}|
+-- Extension for Rel-14 to support shorter MCH scheduling period values –
+	{ID id-MCH-Scheduling-PeriodExtended2		CRITICALITY	reject	EXTENSION MCH-Scheduling-PeriodExtended2	PRESENCE optional},
+	...
+}
+
+Common-Subframe-Allocation-Period ::= ENUMERATED {rf4, rf8, rf16, rf32, rf64, rf128, rf256}
+
+Pre-emptionCapability ::= ENUMERATED {
+	shall-not-trigger-pre-emption,
+	may-trigger-pre-emption
+}
+
+Pre-emptionVulnerability ::= ENUMERATED {
+	not-pre-emptable,
+	pre-emptable
+}
+
+PriorityLevel ::= INTEGER { spare (0), highest (1), lowest (14), no-priority (15) } (0..15)
+
+-- Q
+
+QCI ::= INTEGER (0..255)
+
+-- R
+
+Repetition-PeriodExtended ::= ENUMERATED {rf1, rf2, rf4, rf8, rf16, ...}
+
+-- S
+
+SC-PTM-Information ::= SEQUENCE {
+	mbmsCellList					MBMS-Cell-List,
+	mbms-E-RAB-QoS-Parameters		MBMS-E-RAB-QoS-Parameters,
+	iE-Extensions					ProtocolExtensionContainer { {SC-PTM-Information-ExtIEs} } OPTIONAL,
+	...
+}
+
+SC-PTM-Information-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+SFN ::= INTEGER (0..1023)
+
+Subcarrier-SpacingMBMS ::= ENUMERATED {khz-7dot5, khz-1dot25, ...}
+
+SubframeAllocationExtended	::=	CHOICE {
+		oneFrameExtension				BIT STRING (SIZE(2)),
+		fourFrameExtension				BIT STRING (SIZE(8)),
+		choice-extension				ProtocolIE-Single-Container { { SubframeAllocationExtended-ExtIEs} },
+
+		...
+}
+
+
+SubframeAllocationExtended-ExtIEs M2AP-PROTOCOL-IES ::= {	...
+}
+
+-- T
+
+TimeToWait ::= ENUMERATED {v1s, v2s, v5s, v10s, v20s, v60s, ...}
+
+TMGI ::= SEQUENCE {
+	pLMNidentity			PLMN-Identity,
+	serviceID				OCTET STRING (SIZE (3)),
+	iE-Extensions			ProtocolExtensionContainer { {TMGI-ExtIEs} } OPTIONAL,
+	...
+}
+
+TMGI-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+
+TNL-Information ::= SEQUENCE {
+	iPMCAddress						IPAddress,
+	iPSourceAddress					IPAddress,
+	gTP-TEID						GTP-TEID,
+	iE-Extensions					ProtocolExtensionContainer { {TNL-Information-ExtIEs} } OPTIONAL,
+	...
+}
+
+TNL-Information-ExtIEs M2AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+TypeOfError ::= ENUMERATED {
+	not-understood,
+	missing,
+	...
+}
+
+
+-- U
+-- V
+-- W
+-- X
+-- Y
+-- Z
+
+END
+
+-- **************************************************************
+--
+-- Common definitions
+--
+-- **************************************************************
+
+M2AP-CommonDataTypes {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) 
+eps-Access (21) modules (3) m2ap (4) version1 (1) m2ap-CommonDataTypes (3)  }
+
+DEFINITIONS AUTOMATIC TAGS ::= 
+
+BEGIN
+
+-- **************************************************************
+--
+-- Extension constants
+--
+-- **************************************************************
+
+maxPrivateIEs 									INTEGER ::= 65535
+maxProtocolExtensions 							INTEGER ::= 65535
+maxProtocolIEs									INTEGER ::= 65535
+
+-- **************************************************************
+--
+-- Common Data Types
+--
+-- **************************************************************
+
+Criticality		::= ENUMERATED { reject, ignore, notify }
+
+Presence		::= ENUMERATED { optional, conditional, mandatory }
+
+PrivateIE-ID	::= CHOICE {
+	local				INTEGER (0.. maxPrivateIEs),
+	global				OBJECT IDENTIFIER
+}
+
+ProcedureCode		::= INTEGER (0..255)
+
+
+ProtocolIE-ID		::= INTEGER (0..maxProtocolIEs)
+
+
+TriggeringMessage	::= ENUMERATED { initiating-message, successful-outcome, unsuccessful-outcome}
+
+END
+
+-- **************************************************************
+--
+-- Constant definitions
+--
+-- **************************************************************
+
+M2AP-Constants {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) 
+eps-Access (21) modules (3) m2ap (4) version1 (1) m2ap-Constants (4) }
+
+DEFINITIONS AUTOMATIC TAGS ::= 
+
+BEGIN
+
+IMPORTS
+	ProcedureCode,
+	ProtocolIE-ID
+FROM M2AP-CommonDataTypes;
+
+-- **************************************************************
+--
+-- Elementary Procedures
+--
+-- **************************************************************
+
+id-sessionStart													ProcedureCode ::= 0
+id-sessionStop													ProcedureCode ::= 1
+id-mbmsSchedulingInformation									ProcedureCode ::= 2
+id-errorIndication												ProcedureCode ::= 3
+id-reset														ProcedureCode ::= 4
+id-m2Setup														ProcedureCode ::= 5
+id-eNBConfigurationUpdate										ProcedureCode ::= 6
+id-mCEConfigurationUpdate										ProcedureCode ::= 7
+id-privateMessage												ProcedureCode ::= 8
+id-sessionUpdate												ProcedureCode ::= 9
+id-mbmsServiceCounting											ProcedureCode ::= 10
+id-mbmsServiceCountingResultsReport								ProcedureCode ::= 11
+id-mbmsOverloadNotification										ProcedureCode ::= 12
+
+-- **************************************************************
+--
+-- Lists
+--
+-- **************************************************************
+
+maxnoofMBSFNareas							INTEGER ::= 256 
+maxnoofMBSFN-Allocations					INTEGER ::= 8
+maxnoofPMCHsperMBSFNarea					INTEGER ::= 15
+maxnoofCells								INTEGER ::= 256
+maxnoofMBMSServiceAreasPerCell				INTEGER ::= 256 
+maxnoofSessionsPerPMCH						INTEGER ::= 29
+maxnooferrors								INTEGER ::= 256
+maxNrOfIndividualM2ConnectionsToReset		INTEGER ::= 256
+maxnoofCountingService						INTEGER ::= 16
+maxnoofCellsforMBMS							INTEGER ::= 4096
+
+
+-- **************************************************************
+--
+-- Ies
+--
+-- **************************************************************
+
+id-MCE-MBMS-M2AP-ID															ProtocolIE-ID ::= 0
+id-ENB-MBMS-M2AP-ID															ProtocolIE-ID ::= 1
+id-TMGI																		ProtocolIE-ID ::= 2
+id-MBMS-Session-ID															ProtocolIE-ID ::= 3
+id-MBMS-Service-Area														ProtocolIE-ID ::= 6
+id-TNL-Information															ProtocolIE-ID ::= 7
+id-CriticalityDiagnostics													ProtocolIE-ID ::= 8
+id-Cause																	ProtocolIE-ID ::= 9
+id-MBSFN-Area-Configuration-List											ProtocolIE-ID ::= 10
+id-PMCH-Configuration-List													ProtocolIE-ID ::= 11
+id-PMCH-Configuration-Item													ProtocolIE-ID ::= 12
+id-GlobalENB-ID																ProtocolIE-ID ::= 13
+id-ENBname																	ProtocolIE-ID ::= 14
+id-ENB-MBMS-Configuration-data-List											ProtocolIE-ID ::= 15
+id-ENB-MBMS-Configuration-data-Item											ProtocolIE-ID ::= 16
+id-GlobalMCE-ID																ProtocolIE-ID ::= 17
+id-MCEname																	ProtocolIE-ID ::= 18
+id-MCCHrelatedBCCH-ConfigPerMBSFNArea										ProtocolIE-ID ::= 19
+id-MCCHrelatedBCCH-ConfigPerMBSFNArea-Item									ProtocolIE-ID ::= 20
+id-TimeToWait																ProtocolIE-ID ::= 21
+id-MBSFN-Subframe-Configuration-List										ProtocolIE-ID ::= 22
+id-MBSFN-Subframe-Configuration-Item										ProtocolIE-ID ::= 23
+id-Common-Subframe-Allocation-Period										ProtocolIE-ID ::= 24
+id-MCCH-Update-Time															ProtocolIE-ID ::= 25
+id-ENB-MBMS-Configuration-data-List-ConfigUpdate							ProtocolIE-ID ::= 26
+id-ENB-MBMS-Configuration-data-ConfigUpdate-Item							ProtocolIE-ID ::= 27
+id-MBMS-Service-associatedLogicalM2-ConnectionItem							ProtocolIE-ID ::= 28
+id-MBSFN-Area-ID															ProtocolIE-ID ::= 29
+id-ResetType																ProtocolIE-ID ::= 30
+id-MBMS-Service-associatedLogicalM2-ConnectionListResAck					ProtocolIE-ID ::= 31
+id-MBMS-Counting-Request-Session											ProtocolIE-ID ::= 32
+id-MBMS-Counting-Request-Session-Item										ProtocolIE-ID ::= 33
+id-MBMS-Counting-Result-List												ProtocolIE-ID ::= 34
+id-MBMS-Counting-Result-Item												ProtocolIE-ID ::= 35
+id-Modulation-Coding-Scheme2												ProtocolIE-ID ::= 36
+id-MCH-Scheduling-PeriodExtended											ProtocolIE-ID ::= 37
+id-Alternative-TNL-Information												ProtocolIE-ID ::= 38
+id-Overload-Status-Per-PMCH-List											ProtocolIE-ID ::= 39
+id-PMCH-Overload-Status														ProtocolIE-ID ::= 41
+id-Active-MBMS-Session-List													ProtocolIE-ID ::= 42
+id-MBMS-Suspension-Notification-List 										ProtocolIE-ID ::= 43
+id-MBMS-Suspension-Notification-Item										ProtocolIE-ID ::= 44
+id-SC-PTM-Information														ProtocolIE-ID ::= 45
+id-Modification-PeriodExtended												ProtocolIE-ID ::= 46
+id-Repetition-PeriodExtended												ProtocolIE-ID ::= 47
+id-MCH-Scheduling-PeriodExtended2											ProtocolIE-ID ::= 48
+id-Subcarrier-SpacingMBMS													ProtocolIE-ID ::= 49
+id-SubframeAllocationExtended												ProtocolIE-ID ::= 50
+
+END
+
+
+-- **************************************************************
+--
+-- Container definitions
+--
+-- **************************************************************
+
+M2AP-Containers {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m2ap (4) version1 (1) m2ap-Containers (5)  }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+	maxPrivateIEs,
+	maxProtocolExtensions,
+	maxProtocolIEs,
+	Criticality,
+	Presence,
+	PrivateIE-ID,
+	ProtocolIE-ID
+FROM M2AP-CommonDataTypes;
+
+-- **************************************************************
+--
+-- Class Definition for Protocol Ies
+--
+-- **************************************************************
+
+M2AP-PROTOCOL-IES ::= CLASS {
+	&id				ProtocolIE-ID 			UNIQUE,
+	&criticality	Criticality,
+	&Value,
+	&presence		Presence
+}
+WITH SYNTAX {
+	ID				&id
+	CRITICALITY		&criticality
+	TYPE			&Value
+	PRESENCE		&presence
+}
+
+-- **************************************************************
+--
+-- Class Definition for Protocol Ies
+--
+-- **************************************************************
+
+M2AP-PROTOCOL-IES-PAIR ::= CLASS {
+	&id						ProtocolIE-ID 		UNIQUE,
+	&firstCriticality		Criticality,
+	&FirstValue,
+	&secondCriticality		Criticality,
+	&SecondValue,
+	&presence				Presence
+}
+WITH SYNTAX {
+	ID						&id
+	FIRST CRITICALITY 		&firstCriticality
+	FIRST TYPE				&FirstValue
+	SECOND CRITICALITY 		&secondCriticality
+	SECOND TYPE				&SecondValue
+	PRESENCE				&presence
+}
+
+-- **************************************************************
+--
+-- Class Definition for Protocol Extensions
+--
+-- **************************************************************
+
+M2AP-PROTOCOL-EXTENSION ::= CLASS {
+	&id					ProtocolIE-ID 		UNIQUE,
+	&criticality		Criticality,
+	&Extension,
+	&presence			Presence
+}
+WITH SYNTAX {
+	ID					&id
+	CRITICALITY			&criticality
+	EXTENSION			&Extension
+	PRESENCE			&presence
+}
+
+-- **************************************************************
+--
+-- Class Definition for Private Ies
+--
+-- **************************************************************
+
+M2AP-PRIVATE-IES ::= CLASS {
+	&id					PrivateIE-ID,
+	&criticality		Criticality,
+	&Value,
+	&presence			Presence
+}
+WITH SYNTAX {
+	ID					&id
+	CRITICALITY			&criticality
+	TYPE				&Value
+	PRESENCE			&presence
+}
+
+-- **************************************************************
+--
+-- Container for Protocol Ies
+--
+-- **************************************************************
+
+ProtocolIE-Container {M2AP-PROTOCOL-IES : IesSetParam} ::=
+	SEQUENCE (SIZE (0..maxProtocolIEs)) OF
+	ProtocolIE-Field {{IesSetParam}}
+
+ProtocolIE-Single-Container {M2AP-PROTOCOL-IES : IesSetParam} ::=
+	ProtocolIE-Field {{IesSetParam}}
+
+ProtocolIE-Field {M2AP-PROTOCOL-IES : IesSetParam} ::= SEQUENCE {
+	id				M2AP-PROTOCOL-IES.&id					({IesSetParam}),
+	criticality		M2AP-PROTOCOL-IES.&criticality			({IesSetParam}{@id}),
+	value			M2AP-PROTOCOL-IES.&Value				({IesSetParam}{@id})
+}
+
+-- **************************************************************
+--
+-- Container for Protocol IE Pairs
+--
+-- **************************************************************
+
+ProtocolIE-ContainerPair {M2AP-PROTOCOL-IES-PAIR : IesSetParam} ::=
+	SEQUENCE (SIZE (0..maxProtocolIEs)) OF
+	ProtocolIE-FieldPair {{IesSetParam}}
+
+ProtocolIE-FieldPair {M2AP-PROTOCOL-IES-PAIR : IesSetParam} ::= SEQUENCE {
+	id					M2AP-PROTOCOL-IES-PAIR.&id					({IesSetParam}),
+	firstCriticality	M2AP-PROTOCOL-IES-PAIR.&firstCriticality	({IesSetParam}{@id}),
+	firstValue			M2AP-PROTOCOL-IES-PAIR.&FirstValue			({IesSetParam}{@id}),
+	secondCriticality	M2AP-PROTOCOL-IES-PAIR.&secondCriticality	({IesSetParam}{@id}),
+	secondValue			M2AP-PROTOCOL-IES-PAIR.&SecondValue			({IesSetParam}{@id})
+}
+
+-- **************************************************************
+--
+-- Container Lists for Protocol IE Containers
+--
+-- **************************************************************
+
+ProtocolIE-ContainerList {INTEGER : lowerBound, INTEGER : upperBound, M2AP-PROTOCOL-IES : IesSetParam} ::=
+	SEQUENCE (SIZE (lowerBound..upperBound)) OF
+	ProtocolIE-Container {{IesSetParam}}
+
+ProtocolIE-ContainerPairList {INTEGER : lowerBound, INTEGER : upperBound, M2AP-PROTOCOL-IES-PAIR : IesSetParam} ::=
+	SEQUENCE (SIZE (lowerBound..upperBound)) OF
+	ProtocolIE-ContainerPair {{IesSetParam}}
+
+-- **************************************************************
+--
+-- Container for Protocol Extensions
+--
+-- **************************************************************
+
+ProtocolExtensionContainer {M2AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::=
+	SEQUENCE (SIZE (1..maxProtocolExtensions)) OF
+	ProtocolExtensionField {{ExtensionSetParam}}
+
+ProtocolExtensionField {M2AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= SEQUENCE {
+	id					M2AP-PROTOCOL-EXTENSION.&id				({ExtensionSetParam}),
+	criticality			M2AP-PROTOCOL-EXTENSION.&criticality	({ExtensionSetParam}{@id}),
+	extensionValue		M2AP-PROTOCOL-EXTENSION.&Extension		({ExtensionSetParam}{@id})
+}
+
+-- **************************************************************
+--
+-- Container for Private Ies
+--
+-- **************************************************************
+
+PrivateIE-Container {M2AP-PRIVATE-IES : IesSetParam} ::=
+	SEQUENCE (SIZE (1..maxPrivateIEs)) OF
+	PrivateIE-Field {{IesSetParam}}
+
+PrivateIE-Field {M2AP-PRIVATE-IES : IesSetParam} ::= SEQUENCE {
+	id				M2AP-PRIVATE-IES.&id			({IesSetParam}),
+	criticality		M2AP-PRIVATE-IES.&criticality	({IesSetParam}{@id}),
+	value			M2AP-PRIVATE-IES.&Value			({IesSetParam}{@id})
+}
+
+END
+
+
diff --git a/openair2/M2AP/MESSAGES/asn1tostruct.py b/openair2/M2AP/MESSAGES/asn1tostruct.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c0f7e8a16a52ca7588a40cefb73428156a14f7d
--- /dev/null
+++ b/openair2/M2AP/MESSAGES/asn1tostruct.py
@@ -0,0 +1,697 @@
+import re, os, sys, string
+import datetime
+import getopt
+import getpass
+
+version = "1.0.2"
+
+lines = ""
+iesDefs = {}
+ieofielist = {}
+outdir = './'
+
+filenames = []
+verbosity = 0
+prefix = ""
+
+FAIL = '\033[91m'
+WARN = '\033[93m'
+ENDC = '\033[0m'
+
+fileprefix = ""
+fileprefix_first_upper = ""
+
+def printFail(string):
+    sys.stderr.write(FAIL + string + ENDC + "\n")
+
+def printWarning(string):
+    print WARN + string + ENDC
+
+def printDebug(string):
+    if verbosity > 0:
+        print string
+
+def outputHeaderToFile(f, filename):
+    now = datetime.datetime.now()
+    f.write("""/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+""")
+    f.write("/*******************************************************************************\n")
+    f.write(" * This file had been created by asn1tostruct.py script v%s\n" % (version))
+    f.write(" * Please do not modify this file but regenerate it via script.\n")
+    f.write(" * Created on: %s by %s\n * from %s\n" % (str(now), getpass.getuser(), filenames))
+    f.write(" ******************************************************************************/\n")
+
+def lowerFirstCamelWord(word):
+    """ puts the first word in a CamelCase Word in lowercase.
+
+    I.e. CustomerID becomes customerID, XMLInfoTest becomes xmlInfoTest
+    """
+    newstr = ''
+    swapped = word.swapcase()
+    idx = 0
+
+    # if it's all-caps, return an all-lowered version
+    lowered = word.lower()
+
+    if swapped == lowered:
+        return lowered
+
+    for c in swapped:
+        if c in string.lowercase:
+            newstr += c
+            idx    += 1
+        else:
+            break
+    if idx < 2:
+        newstr += word[idx:]
+    else:
+        newstr = newstr[:-1]+ word[idx-1:]
+
+    return newstr
+
+def usage():
+    print "Python parser for asn1 v%s" % (version)
+    print "Usage: python asn1tostruct.py [options]"
+    print "Available options:"
+    print "-d        Enable script debug"
+    print "-f [file] Input file to parse"
+    print "-o [dir]  Output files to given directory"
+    print "-h        Print this help and return"
+
+try:
+    opts, args = getopt.getopt(sys.argv[1:], "df:ho:", ["debug", "file", "help", "outdir"])
+except getopt.GetoptError as err:
+    # print help information and exit:
+    usage()
+    sys.exit(2)
+
+for o, a in opts:
+    if o in ("-f", "--file"):
+        filenames.append(a)
+    if o in ("-d", "--debug"):
+        verbosity = 1
+    if o in ("-o", "--outdir"):
+        outdir = a
+        if outdir.rfind('/') != len(outdir):
+            outdir += '/'
+    if o in ("-h", "--help"):
+        usage()
+        sys.exit(2)
+
+for filename in filenames:
+    file = open(filename, 'r')
+    for line in file:
+        # Removing any comment
+        if line.find('--') >= 0:
+            line = line[:line.find('--')]
+        # Removing any carriage return
+        lines += re.sub('\r', '', line)
+
+    for m in re.findall(r'([a-zA-Z0-9-]+)\s*::=\s+SEQUENCE\s+\(\s*SIZE\s*\(\s*\d+\s*\.\.\s*[0-9a-zA-Z-]+\s*\)\s*\)\s*OF\s+[a-zA-Z-]+\s*\{\s*\{\s*([0-9a-zA-Z-]+)\s*\}\s*\}', lines, re.MULTILINE):
+        ieofielist[m[0]] = m[1]
+    for m in re.findall(r'([a-zA-Z0-9-]+)\s*::=\s+E-RAB-IE-ContainerList\s*\{\s*\{\s*([a-zA-Z0-9-]+)\s*\}\s*\}', lines, re.MULTILINE):
+        ieofielist[m[0]] = m[1]
+
+    for i in re.findall(r'([a-zA-Z0-9-]+)\s+([A-Z0-9-]+)\s*::=\s*\{\s+([\,\|\{\}\t\n\.{3}\ \-a-zA-Z0-9]+)\s+}\n', lines, re.MULTILINE):
+        ies = []
+        maxLength = 0
+        # TODO: handle extensions
+        if i[1].find('EXTENSION') >= 0:
+            continue
+        if fileprefix == "":
+            fileprefix = i[1][:i[1].find('-')].lower()
+        for j in re.findall(r'\s*\{\s*([a-zA-Z0-9-\ \t]+)\s*\}\s*[\|,]*', i[2], re.MULTILINE):
+            for k in re.findall(r'ID\s*([a-zA-Z0-9\-]+)\s*CRITICALITY\s*([a-zA-Z0-9\-]+)\s+[A-Z]+\s+([a-zA-Z0-9\-]+)\s*PRESENCE\s*([a-zA-Z0-9\-]+)', j, re.MULTILINE):
+                printDebug("Got new ie for message " + i[0] + ": " + str(k))
+                if len(k[2]) > maxLength:
+                    maxLength = len(k[2])
+                ies.append(k)
+
+        if len(ies) > 0:
+            iesDefs[i[0]] = { "length": maxLength, "ies": ies }
+        else:
+            printWarning("Didn't find any information element for message: " + i[0])
+
+if len(iesDefs) == 0:
+    printFail("No Information Element parsed, exiting")
+    sys.exit(0)
+
+fileprefix_first_upper = fileprefix[0].upper() + fileprefix[1:]
+
+f = open(outdir + fileprefix + '_ies_defs.h', 'w')
+outputHeaderToFile(f, filename)
+f.write("#include \"%s_common.h\"\n\n" % (fileprefix))
+f.write("#ifndef %s_IES_DEFS_H_\n#define %s_IES_DEFS_H_\n\n" % (fileprefix.upper(), fileprefix.upper()))
+f.write("/* Define the version of script used to generate this file */\n")
+f.write("#define %s_SCRIPT_VERSION (%s)\n\n" % (fileprefix.upper(), re.sub('\.', '', version)))
+
+for key in iesDefs:
+
+    if key not in ieofielist.values():
+        continue
+
+    for (i, j) in ieofielist.items():
+        if j == key:
+            break
+
+    f.write("typedef struct %sIEs_s {\n" % (re.sub('-', '_', i)))
+    f.write("    A_SEQUENCE_OF(struct %s_s) %s;\n" % (re.sub('IEs', '', re.sub('-', '_', ieofielist[i])), lowerFirstCamelWord(re.sub('IEs', '', re.sub('-', '_', ieofielist[i])))))
+    f.write("} %sIEs_t;\n\n" % (re.sub('-', '_', i)))
+
+for key in iesDefs:
+    keyupperunderscore = re.sub('-', '_', key.upper())
+    keylowerunderscore = re.sub('-', '_', key.lower())
+    shift = 0
+
+    if len(iesDefs[key]["ies"]) == 0:
+        continue
+
+    # Presence mask
+    for ie in iesDefs[key]["ies"]:
+        ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
+
+        if ie[3] == "optional" or ie[3] == "conditional":
+            f.write("#define {0:<{pad}} {1}\n".format("%s_%s_PRESENT" % (keyupperunderscore, ieupperunderscore), "(1 << %d)" % shift,
+            pad=iesDefs[key]["length"] + len(keyupperunderscore) + 9))
+            shift += 1
+    if (shift > 0):
+        f.write("\n")
+
+    f.write("typedef struct %s_s {\n" % (re.sub('-', '_', key)))
+    if (shift > 0):
+        f.write("    {0:<{pad}} {1};\n".format("uint16_t", "presenceMask", pad=iesDefs[key]["length"] + 2))
+    for ie in iesDefs[key]["ies"]:
+        ieunderscore = re.sub('-', '_', ie[2])
+        iename = re.sub('id-', '', ie[0])
+        ienameunderscore = lowerFirstCamelWord(re.sub('-', '_', iename))
+        if ie[2] in ieofielist:
+            f.write("    %sIEs_t %s;" % (re.sub('-', '_', ie[2]), ienameunderscore))
+        else:
+            f.write("    {0:<{pad}} {1};".format("%s_t" % ieunderscore, ienameunderscore, pad=iesDefs[key]["length"] + 2))
+        if ie[3] == "optional":
+            f.write(" ///< Optional field")
+        elif ie[3] == "conditional":
+            f.write(" ///< Conditional field")
+        f.write("\n")
+
+    f.write("} %s_t;\n\n" % (re.sub('-', '_', key)))
+
+f.write("typedef struct %s_message_s {\n" % (fileprefix))
+f.write("    %s_ProcedureCode_t procedureCode;\n" % (fileprefix_first_upper))
+f.write("    %s_Criticality_t   criticality;\n" % (fileprefix_first_upper))
+f.write("    uint8_t            direction;\n")
+f.write("    union {\n")
+
+messageList = iesDefs.keys()
+messageList.sort()
+for message in messageList:
+    if message in ieofielist.values():
+        continue
+    if len(iesDefs[message]["ies"]) == 0:
+        continue
+    f.write("        %s_t %s;\n" % (re.sub('-', '_', message), lowerFirstCamelWord(re.sub('-', '_', message))))
+f.write("    } msg;\n")
+f.write("} %s_message;\n\n" % (fileprefix))
+
+for key in iesDefs:
+    if key in ieofielist.values():
+        continue
+    structName = re.sub('ies', '', key)
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', re.sub('-IEs', '', key)))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    keylowerunderscore = re.sub('-', '_', key.lower())
+    firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+    f.write("/** \\brief Decode function for %s ies.\n" % (key))
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write(" * \\param %s Pointer to ASN1 structure in which data will be stored\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write(" *  \\param any_p Pointer to the ANY value to decode.\n")
+    f.write(" **/\n")
+    f.write("int %s_decode_%s(\n" % (fileprefix, keylowerunderscore))
+
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write("    %s_t *%s,\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write("    ANY_t *any_p);\n\n")
+
+    if len(iesDefs[key]["ies"]) == 0:
+        continue
+
+    f.write("/** \\brief Encode function for %s ies.\n" % (key))
+    f.write(" *  \\param %s Pointer to the ASN1 structure.\n" % (firstlower))
+    f.write(" *  \\param %s Pointer to the IES structure.\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write(" **/\n")
+    f.write("int %s_encode_%s(\n" % (fileprefix, re.sub('-', '_', structName.lower())))
+    f.write("    %s_t *%s,\n" % (asn1cStruct, firstlower))
+    f.write("    %s_t *%s);\n\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
+
+for key in iesDefs:
+    if key not in ieofielist.values():
+        continue
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+    f.write("/** \\brief Encode function for %s ies.\n" % (key))
+    f.write(" *  \\param %s Pointer to the ASN1 structure.\n" % (firstlower))
+    f.write(" *  \\param %s Pointer to the IES structure.\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write(" **/\n")
+    f.write("int %s_encode_%s(\n" % (fileprefix, firstlower.lower()))
+    f.write("    %s_t *%s,\n" % (asn1cStruct, firstlower))
+    f.write("    %sIEs_t *%sIEs);\n\n" % (asn1cStruct, firstlower))
+    f.write("/** \\brief Decode function for %s ies.\n" % (key))
+    f.write(" *  \\param any_p Pointer to the ANY value to decode.\n")
+    f.write(" *  \\param callback Callback function called when any_p is successfully decoded.\n")
+    f.write(" **/\n")
+    f.write("int %s_decode_%s(\n" % (fileprefix, firstlower.lower()))
+    f.write("    %sIEs_t *%sIEs,\n" % (asn1cStruct, firstlower))
+    f.write("    %s_t *%s);\n\n" % (asn1cStruct, lowerFirstCamelWord(asn1cStruct)))
+
+for key in iesDefs:
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    if key in ieofielist.values():
+        f.write("/** \\brief Display %s encapsulated IE using XER encoding.\n" % (asn1cStruct))
+        f.write(" *  \\param %s Pointer to the IES structure.\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+        f.write(" *  \\param file File descriptor to write output.\n")
+        f.write(" **/\n")
+        f.write("asn_enc_rval_t %s_xer_print_%s(\n" % (fileprefix, re.sub('item', 'list', firstlower.lower())))
+        f.write("    asn_app_consume_bytes_f *cb,\n")
+        f.write("    void *app_key,\n")
+        f.write("    %sIEs_t *%sIEs);\n\n" % (re.sub('item', 'list', asn1cStruct), firstlower))
+    else:
+        f.write("/** \\brief Display %s message using XER encoding.\n" % (asn1cStruct))
+        f.write(" *  \\param message_p Pointer to root message.\n")
+        f.write(" *  \\param file File descriptor to write output.\n")
+        f.write(" **/\n")
+        f.write("asn_enc_rval_t %s_xer_print_%s(\n" % (fileprefix, firstlower.lower()))
+        f.write("    asn_app_consume_bytes_f *cb,\n")
+        f.write("    void *app_key,\n")
+        f.write("    %s_message *message_p);\n\n" % (fileprefix))
+
+f.write("int %s_xer__print2sp(const void *buffer, size_t size, void *app_key);\n\n" % (fileprefix.lower()))
+f.write("int %s_xer__print2fp(const void *buffer, size_t size, void *app_key);\n\n" % (fileprefix.lower()))
+f.write("extern size_t %s_string_total_size;\n\n" % (fileprefix.lower()))
+f.write("#endif /* %s_IES_DEFS_H_ */\n\n" % (fileprefix.upper()))
+
+#Generate Decode functions
+f = open(outdir + fileprefix + '_decoder.c', 'w')
+outputHeaderToFile(f, filename)
+f.write("#include \"%s_common.h\"\n#include \"%s_ies_defs.h\"\n\n" % (fileprefix, fileprefix))
+for key in iesDefs:
+    if key in ieofielist.values():
+        continue
+    structName = re.sub('ies', '', key)
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
+    if asn1cStruct.rfind('_') == len(asn1cStruct) - 1:
+        asn1cStruct = asn1cStruct[:-1]
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    ielistname = re.sub('UE', 'ue', asn1cStruct)
+    ielistnamefirstlower = ielistname[:1].lower() + ielistname[1:]
+    asn1cStructfirstlower = asn1cStruct[:1].lower() + asn1cStruct[1:]
+    keyName = re.sub('-', '_', key)
+    keyupperunderscore = keyName.upper()
+    firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    iesaccess = ""
+    if key not in ieofielist.values():
+        iesaccess = "%s_ies." % (firstlower)
+
+    f.write("int %s_decode_%s(\n" % (fileprefix, re.sub('-', '_', structName.lower())))
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write("    %s_t *%s,\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write("    ANY_t *any_p) {\n\n")
+
+    f.write("    %s_t  %s;\n    %s_t *%s_p = &%s;\n" % (asn1cStruct, asn1cStructfirstlower, asn1cStruct, asn1cStructfirstlower, asn1cStructfirstlower))
+    f.write("    int i, decoded = 0;\n")
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write("    int tempDecoded = 0;\n")
+
+    f.write("    assert(any_p != NULL);\n")
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write("    assert(%s != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+
+    f.write("    %s_DEBUG(\"Decoding message %s (%%s:%%d)\\n\", __FILE__, __LINE__);\n\n" % (fileprefix.upper(), re.sub('-', '_', keyName)))
+    f.write("    ANY_to_type_aper(any_p, &asn_DEF_%s, (void**)&%s_p);\n\n" % (asn1cStruct, asn1cStructfirstlower))
+    f.write("    for (i = 0; i < %s_p->%slist.count; i++) {\n" % (asn1cStructfirstlower, iesaccess))
+    f.write("        %s_IE_t *ie_p;\n" % (fileprefix[0].upper() + fileprefix[1:]))
+    f.write("        ie_p = %s_p->%slist.array[i];\n" % (asn1cStructfirstlower, iesaccess))
+    f.write("        switch(ie_p->id) {\n")
+    for ie in iesDefs[key]["ies"]:
+        iename = re.sub('id-', '', ie[0])
+        ienameunderscore = lowerFirstCamelWord(re.sub('-', '_', iename))
+        ienameunderscorefirstlower = lowerFirstCamelWord(ienameunderscore)
+        ietypesubst = re.sub('-', '', ie[2])
+        ietypeunderscore = re.sub('-', '_', ie[2])
+        ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
+
+        if ie[3] == "optional":
+            f.write("            /* Optional field */\n")
+        elif ie[3] == "conditional":
+            f.write("            /* Conditional field */\n")
+        f.write("            case %s_ProtocolIE_ID_%s:\n" % (fileprefix_first_upper, re.sub('-', '_', ie[0])))
+        f.write("            {\n")
+        f.write("                %s_t *%s_p = NULL;\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        if ie[3] != "mandatory":
+            f.write("                %s->presenceMask |= %s_%s_PRESENT;\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), keyupperunderscore, ieupperunderscore))
+        f.write("                tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_%s, (void**)&%s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        f.write("                if (tempDecoded < 0 || %s_p == NULL) {\n" % (lowerFirstCamelWord(ietypesubst)))
+        f.write("                    %s_ERROR(\"Decoding of IE %s failed\\n\");\n" % (fileprefix.upper(), ienameunderscore))
+        f.write("                    if (%s_p)\n" % (lowerFirstCamelWord(ietypesubst)))
+        f.write("                        ASN_STRUCT_FREE(asn_DEF_%s, %s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        f.write("                    return -1;\n")
+        f.write("                }\n")
+        f.write("                decoded += tempDecoded;\n")
+        f.write("                if (asn1_xer_print)\n")
+        f.write("                    xer_fprint(stdout, &asn_DEF_%s, %s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        if ie[2] in ieofielist.keys():
+            f.write("                if (%s_decode_%s(&%s->%s, %s_p) < 0) {\n" % (fileprefix, ietypeunderscore.lower(), lowerFirstCamelWord(re.sub('-', '_', key)), ienameunderscore, lowerFirstCamelWord(ietypesubst)))
+            f.write("                    %s_ERROR(\"Decoding of encapsulated IE %s failed\\n\");\n" % (fileprefix.upper(), lowerFirstCamelWord(ietypesubst)))
+            f.write("                    ASN_STRUCT_FREE(asn_DEF_%s, %s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+            f.write("                }\n")
+        else:
+            f.write("                memcpy(&%s->%s, %s_p, sizeof(%s_t));\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), ienameunderscore, lowerFirstCamelWord(ietypesubst), ietypeunderscore))
+            #f.write("                ASN_STRUCT_FREE(asn_DEF_%s, %s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        f.write("            } break;\n")
+    f.write("            default:\n")
+    f.write("                %s_ERROR(\"Unknown protocol IE id (%%d) for message %s\\n\", (int)ie_p->id);\n" % (fileprefix.upper(), re.sub('-', '_', structName.lower())))
+    f.write("                return -1;\n")
+    f.write("        }\n")
+    f.write("    }\n")
+    f.write("    return decoded;\n")
+    f.write("}\n\n")
+
+for key in iesDefs:
+    if key not in ieofielist.values():
+        continue
+
+    keyname = re.sub('IEs', '', re.sub('Item', 'List', key))
+
+    f.write("int %s_decode_%s(\n" % (fileprefix, re.sub('-', '_', keyname).lower()))
+    f.write("    %sIEs_t *%sIEs,\n" % (re.sub('-', '_', keyname), lowerFirstCamelWord(re.sub('-', '_', keyname))))
+    f.write("    %s_t *%s) {\n\n" % (re.sub('-', '_', keyname), lowerFirstCamelWord(re.sub('-', '_', keyname))))
+    f.write("    int i, decoded = 0;\n")
+    f.write("    int tempDecoded = 0;\n\n")
+
+    f.write("    assert(%s != NULL);\n" % (lowerFirstCamelWord(re.sub('-', '_', keyname))));
+    f.write("    assert(%sIEs != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', keyname))));
+
+    f.write("    for (i = 0; i < %s->list.count; i++) {\n" % (lowerFirstCamelWord(re.sub('-', '_', keyname))))
+    f.write("        %s_IE_t *ie_p = %s->list.array[i];\n" % (fileprefix[0].upper() + fileprefix[1:], lowerFirstCamelWord(re.sub('-', '_', keyname))))
+    f.write("        switch (ie_p->id) {\n")
+    for ie in iesDefs[key]["ies"]:
+        iename = re.sub('id-', '', ie[0])
+        ienameunderscore = lowerFirstCamelWord(re.sub('-', '_', iename))
+        f.write("            case %s_ProtocolIE_ID_%s:\n" % (fileprefix_first_upper, re.sub('-', '_', ie[0])))
+        f.write("            {\n")
+        f.write("                %s_t *%s_p = NULL;\n" % (re.sub('-', '_', ie[2]), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_%s, (void**)&%s_p);\n" % (re.sub('-', '_', ie[2]), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                if (tempDecoded < 0 || %s_p == NULL) {\n" % (lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                    %s_ERROR(\"Decoding of IE %s for message %s failed\\n\");\n" % (fileprefix.upper(), ienameunderscore, re.sub('-', '_', keyname)))
+        f.write("                    if (%s_p)\n" % (lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        #f.write("                        free(%s_p);\n" % (lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                        ASN_STRUCT_FREE(asn_DEF_%s, %s_p);\n" % (re.sub('-', '_', ie[2]), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                    return -1;\n")
+        f.write("                }\n")
+        f.write("                decoded += tempDecoded;\n")
+        f.write("                if (asn1_xer_print)\n")
+        f.write("                    xer_fprint(stdout, &asn_DEF_%s, %s_p);\n" % (re.sub('-', '_', ie[2]), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                ASN_SEQUENCE_ADD(&%sIEs->%s, %s_p);\n" % (lowerFirstCamelWord(re.sub('-', '_', keyname)),
+        re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key))), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("            } break;\n")
+    f.write("            default:\n")
+    f.write("                %s_ERROR(\"Unknown protocol IE id (%%d) for message %s\\n\", (int)ie_p->id);\n" % (fileprefix.upper(), re.sub('-', '_', structName.lower())))
+    f.write("                return -1;\n")
+    f.write("        }\n")
+    f.write("    }\n")
+    f.write("    return decoded;\n")
+    f.write("}\n\n")
+
+
+#Generate IES Encode functions
+f = open(outdir + fileprefix + '_encoder.c', 'w')
+outputHeaderToFile(f,filename)
+f.write("#include \"%s_common.h\"\n" % (fileprefix))
+f.write("#include \"%s_ies_defs.h\"\n\n" % (fileprefix))
+for key in iesDefs:
+    if key in ieofielist.values():
+        continue
+
+    structName = re.sub('ies', '', key)
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    if asn1cStruct.rfind('_') == len(asn1cStruct) - 1:
+        asn1cStruct = asn1cStruct[:-1]
+    asn1cStructfirstlower = asn1cStruct[:1].lower() + asn1cStruct[1:]
+    firstwordlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    iesaccess = ""
+    if key not in ieofielist.values():
+        iesaccess = "%s_ies." % (firstwordlower)
+
+    keyName = re.sub('-', '_', key)
+    keyupperunderscore = keyName.upper()
+    # No IE to encode...
+    if len(iesDefs[key]["ies"]) == 0:
+        continue
+
+    f.write("int %s_encode_%s(\n" % (fileprefix, re.sub('-', '_', structName.lower())))
+    f.write("    %s_t *%s,\n" % (asn1cStruct, firstwordlower))
+    f.write("    %s_t *%s) {\n\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
+
+    f.write("    %s_IE_t *ie;\n\n" % (fileprefix_first_upper))
+
+    f.write("    assert(%s != NULL);\n" % (firstwordlower));
+    f.write("    assert(%s != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', key))));
+
+    for ie in iesDefs[key]["ies"]:
+        iename = re.sub('-', '_', re.sub('id-', '', ie[0]))
+        ienameunderscore = re.sub('-', '_', iename)
+        ienamefirstwordlower = lowerFirstCamelWord(iename)
+        ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
+        ietypeunderscore = re.sub('-', '_', ie[2])
+
+        if ie[3] != "mandatory":
+            if ie[3] == "optional":
+                f.write("    /* Optional field */\n")
+            elif ie[3] == "conditional":
+                f.write("    /* Conditional field */\n")
+            f.write("    if (%s->presenceMask & %s_%s_PRESENT) {\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), keyupperunderscore, ieupperunderscore))
+            #f.write("        == %s_%s_PRESENT) {\n" % (keyupperunderscore, ieupperunderscore))
+            f.write("        if ((ie = %s_new_ie(%s_ProtocolIE_ID_%s,\n" % (fileprefix, fileprefix_first_upper, re.sub('-', '_', ie[0])))
+            f.write("                            %s_Criticality_%s,\n" % (fileprefix_first_upper, ie[1]))
+            f.write("                            &asn_DEF_%s,\n" % (ietypeunderscore))
+            f.write("                            &%s->%s)) == NULL) {\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower))
+            f.write("            return -1;\n")
+            f.write("        }\n")
+            f.write("        ASN_SEQUENCE_ADD(&%s->%slist, ie);\n" % (firstwordlower, iesaccess))
+            f.write("    }\n\n")
+        else:
+            if ie[2] in ieofielist.keys():
+                f.write("    %s_t %s;\n\n" % (ietypeunderscore, ienamefirstwordlower))
+                f.write("    memset(&%s, 0, sizeof(%s_t));\n" % (ienamefirstwordlower, ietypeunderscore))
+                f.write("\n")
+                f.write("    if (%s_encode_%s(&%s, &%s->%s) < 0) return -1;\n" % (fileprefix, ietypeunderscore.lower(), ienamefirstwordlower, lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower))
+            f.write("    if ((ie = %s_new_ie(%s_ProtocolIE_ID_%s,\n" % (fileprefix, fileprefix_first_upper, re.sub('-', '_', ie[0])))
+            f.write("                        %s_Criticality_%s,\n" % (fileprefix_first_upper, ie[1]))
+            f.write("                        &asn_DEF_%s,\n" % (ietypeunderscore))
+            if ie[2] in ieofielist.keys():
+                f.write("                          &%s)) == NULL) {\n" % (ienamefirstwordlower))
+            else:
+                f.write("                          &%s->%s)) == NULL) {\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower))
+            f.write("        return -1;\n")
+            f.write("    }\n")
+            f.write("    ASN_SEQUENCE_ADD(&%s->%slist, ie);\n\n" % (firstwordlower, iesaccess))
+            if ie[2] in ieofielist.keys():
+                f.write("    /* Free any dynamic allocation that is no more used */\n")
+                f.write("    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_%s, &%s);\n\n" % (ietypeunderscore, ienamefirstwordlower))
+
+    f.write("    return 0;\n")
+    f.write("}\n\n")
+
+for (key, value) in iesDefs.items():
+    if key not in ieofielist.values():
+        continue
+
+    ie = value["ies"][0]
+    ietypeunderscore = re.sub('-', '_', ie[2])
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', re.sub('-IEs', '', key)))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    firstwordlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    for (i, j) in ieofielist.items():
+        if j == key:
+            break
+    f.write("int %s_encode_%s(\n" % (fileprefix, re.sub('-', '_', i).lower()))
+    f.write("    %s_t *%s,\n" % (asn1cStruct, firstwordlower))
+    f.write("    %sIEs_t *%sIEs) {\n\n" % (re.sub('-', '_', i), lowerFirstCamelWord(re.sub('-', '_', i))))
+    f.write("    int i;\n")
+
+    f.write("    %s_IE_t *ie;\n\n" % (fileprefix_first_upper))
+
+    f.write("    assert(%s != NULL);\n" % (firstwordlower));
+    f.write("    assert(%sIEs != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', i))));
+
+    f.write("    for (i = 0; i < %sIEs->%s.count; i++) {\n" % (firstwordlower, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+    f.write("        if ((ie = %s_new_ie(%s_ProtocolIE_ID_%s,\n" % (fileprefix, fileprefix_first_upper, re.sub('-', '_', ie[0])))
+    f.write("                            %s_Criticality_%s,\n" % (fileprefix_first_upper, ie[1]))
+    f.write("                            &asn_DEF_%s,\n" % (ietypeunderscore))
+    f.write("                            %sIEs->%s.array[i])) == NULL) {\n" % (firstwordlower, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+    f.write("            return -1;\n")
+    f.write("        }\n")
+    f.write("        ASN_SEQUENCE_ADD(&%s->list, ie);\n" % (firstwordlower))
+    f.write("    }\n")
+    f.write("    return 0;\n")
+    f.write("}\n\n")
+
+#Generate xer print functions
+f = open(outdir + fileprefix + '_xer_print.c', 'w')
+outputHeaderToFile(f, filename)
+f.write("#include <stdlib.h>\n")
+f.write("#include <stdio.h>\n\n")
+f.write("#include <asn_application.h>\n#include <asn_internal.h>\n\n")
+f.write("#include \"%s_common.h\"\n#include \"%s_ies_defs.h\"\n\n" % (fileprefix, fileprefix))
+
+f.write("size_t %s_string_total_size = 0;\n\n" % (fileprefix.lower()))
+f.write("""int
+%s_xer__print2fp(const void *buffer, size_t size, void *app_key) {
+    FILE *stream = (FILE *)app_key;
+
+    if(fwrite(buffer, 1, size, stream) != size)
+        return -1;
+
+    return 0;
+}
+
+""" % (fileprefix.lower()))
+
+f.write("""int %s_xer__print2sp(const void *buffer, size_t size, void *app_key) {
+    char *string = (char *)app_key;
+
+    /* Copy buffer to the formatted string */
+    memcpy(&string[%s_string_total_size], buffer, size);
+
+    %s_string_total_size += size;
+
+    return 0;
+}
+
+""" % (fileprefix.lower(), fileprefix.lower(), fileprefix.lower()))
+
+f.write("""static asn_enc_rval_t
+xer_encode_local(asn_TYPE_descriptor_t *td, void *sptr,
+        asn_app_consume_bytes_f *cb, void *app_key, int indent) {
+    asn_enc_rval_t er, tmper;
+    const char *mname;
+    size_t mlen;
+    int xcan = 2;
+
+    if(!td || !sptr) goto cb_failed;
+
+    mname = td->xml_tag;
+    mlen = strlen(mname);
+
+    _i_ASN_TEXT_INDENT(0, indent);
+    _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
+
+    tmper = td->xer_encoder(td, sptr, indent + 1, XER_F_BASIC, cb, app_key);
+    if(tmper.encoded == -1) return tmper;
+
+    _ASN_CALLBACK3("</", 2, mname, mlen, ">\\n", xcan);
+
+    er.encoded = 4 + xcan + (2 * mlen) + tmper.encoded;
+
+    _ASN_ENCODED_OK(er);
+cb_failed:
+    _ASN_ENCODE_FAILED;
+}
+""")
+
+for (key, value) in iesDefs.items():
+    keyName = re.sub('-', '_', key)
+    keyupperunderscore = keyName.upper()
+    iesStructName = lowerFirstCamelWord(re.sub('-', '_', key))
+
+    ie = value["ies"][0]
+    ietypeunderscore = re.sub('-', '_', ie[2])
+
+    if key in ieofielist.values():
+        f.write("asn_enc_rval_t %s_xer_print_%s(\n" % (fileprefix, re.sub('ies', '', re.sub('item', 'list', re.sub('-', '_', key).lower()))))
+    else:
+        f.write("asn_enc_rval_t %s_xer_print_%s(\n" % (fileprefix, re.sub('ies', '', re.sub('-', '_', key).lower())))
+    #f.write("    FILE *file,\n")
+    f.write("    asn_app_consume_bytes_f *cb,\n")
+    f.write("    void *app_key,\n")
+    if key in ieofielist.values():
+        iesStructName = lowerFirstCamelWord(re.sub('Item', 'List', re.sub('-', '_', key)))
+        f.write("    %sIEs_t *%s) {\n\n" % (re.sub('IEs', '', re.sub('Item', 'List', re.sub('-', '_', key))), iesStructName))
+        f.write("    int i;\n")
+        f.write("    asn_enc_rval_t er;\n")
+    else:
+        f.write("    %s_message *message_p)\n{\n" % (fileprefix))
+        f.write("    %s_t *%s;\n" % (re.sub('-', '_', key), iesStructName))
+        f.write("    asn_enc_rval_t er;\n")
+        #f.write("    void *app_key = (void *)file;\n")
+        #f.write("    asn_app_consume_bytes_f *cb = %s_xer__print2fp;\n\n" % (fileprefix.lower()))
+
+        f.write("    %s = &message_p->msg.%s;\n\n" % (iesStructName, iesStructName))
+
+    if key in ieofielist.values():
+        # Increase indentation level
+        f.write("    for (i = 0; i < %s->%s.count; i++) {\n" % (iesStructName, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+        #f.write("        xer_fprint(file, &asn_DEF_%s, %s->%s.array[i]);\n" % (ietypeunderscore, iesStructName, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+        f.write("        er = xer_encode(&asn_DEF_%s, %s->%s.array[i], XER_F_BASIC, cb, app_key);\n" % (ietypeunderscore, iesStructName, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+        f.write("    }\n")
+    else:
+        f.write("    cb(\"<%s-PDU>\\n\", %d, app_key);\n" % (key, len("<%s-PDU>\n" % (key))))
+        f.write("    xer_encode_local(&asn_DEF_%s_Criticality, &message_p->criticality, cb, app_key, 1);\n" % fileprefix_first_upper)
+        f.write("    xer_encode_local(&asn_DEF_%s_ProcedureCode, &message_p->procedureCode, cb, app_key, 1);\n" % fileprefix_first_upper)
+
+        f.write("    cb(\"    <%s>\\n\", %d, app_key);\n" % (key, len("    <%s>\n" % (key))))
+
+        for ie in iesDefs[key]["ies"]:
+            iename = re.sub('-', '_', re.sub('id-', '', ie[0]))
+            ienameunderscore = re.sub('-', '_', iename)
+            ienamefirstwordlower = lowerFirstCamelWord(iename)
+            ietypeunderscore = re.sub('-', '_', ie[2])
+            ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
+
+            if ie[3] != "mandatory":
+                if ie[3] == "optional":
+                    f.write("    /* Optional field */\n")
+                elif ie[3] == "conditional":
+                    f.write("    /* Conditional field */\n")
+                f.write("    if (%s->presenceMask & %s_%s_PRESENT)\n    " % (iesStructName, keyupperunderscore, ieupperunderscore))
+
+            # Is it an encapsulated IE ?
+            if ie[2] in ieofielist.keys():
+                f.write("    %s_xer_print_%s(cb, app_key, &%s->%s);\n" % (fileprefix, re.sub('ies', '', re.sub('-', '_', ie[2]).lower()), iesStructName, ienamefirstwordlower))
+            else:
+                f.write("    xer_encode_local(&asn_DEF_%s, &%s->%s, cb, app_key, 2);\n" % (ietypeunderscore, iesStructName, ienamefirstwordlower))
+        f.write("    cb(\"    </%s>\\n\", %d, app_key);\n" % (key, len("    </%s>\n" % (key))))
+        f.write("    cb(\"</%s-PDU>\\n\", %d, app_key);\n" % (key, len("</%s-PDU>\n" % (key))))
+
+    f.write("    _ASN_ENCODED_OK(er);\n")
+    #if key not in ieofielist.values():
+        #f.write("cb_failed:\n")
+        #f.write("    return er;\n")
+    f.write("}\n\n")
diff --git a/openair2/M2AP/m2ap_MCE.c b/openair2/M2AP/m2ap_MCE.c
new file mode 100644
index 0000000000000000000000000000000000000000..096f3cabee8be15e11cb027d32047cff6f2b8481
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE.c
@@ -0,0 +1,733 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE.c
+ * \brief m2ap tasks for MCE
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
+#include "intertask_interface.h"
+
+#include "m2ap_MCE.h"
+#include "m2ap_MCE_defs.h"
+#include "m2ap_MCE_management_procedures.h"
+#include "m2ap_MCE_handler.h"
+#include "m2ap_MCE_generate_messages.h"
+#include "m2ap_common.h"
+#include "m2ap_MCE_interface_management.h"
+#include "m2ap_ids.h"
+#include "m2ap_timers.h"
+
+#include "queue.h"
+#include "assertions.h"
+#include "conversions.h"
+
+struct m2ap_mce_map;
+struct m2ap_MCE_data_s;
+
+m2ap_setup_req_t *m2ap_mce_data_from_enb;
+
+RB_PROTOTYPE(m2ap_mce_map, m2ap_MCE_data_s, entry, m2ap_MCE_compare_assoc_id);
+
+static
+void m2ap_MCE_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
+
+static
+void m2ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
+
+static
+void m2ap_MCE_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind);
+
+static
+void m2ap_MCE_handle_register_MCE(instance_t instance,
+                                  m2ap_register_mce_req_t *m2ap_register_MCE);
+static
+void m2ap_MCE_register_MCE(m2ap_MCE_instance_t *instance_p,
+                           net_ip_address_t    *target_MCE_ip_addr,
+                           net_ip_address_t    *local_ip_addr,
+                           uint16_t             in_streams,
+                           uint16_t             out_streams,
+                           uint32_t             mce_port_for_M2C,
+                           int                  multi_sd);
+
+//static
+//void m2ap_MCE_handle_handover_req(instance_t instance,
+//                                  m2ap_handover_req_t *m2ap_handover_req);
+//
+//static
+//void m2ap_MCE_handle_handover_req_ack(instance_t instance,
+//                                      m2ap_handover_req_ack_t *m2ap_handover_req_ack);
+//
+//static
+//void m2ap_MCE_ue_context_release(instance_t instance,
+//                                 m2ap_ue_context_release_t *m2ap_ue_context_release);
+//
+
+static
+void m2ap_MCE_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
+  int result;
+  DevAssert(sctp_data_ind != NULL);
+  m2ap_MCE_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
+                          sctp_data_ind->buffer, sctp_data_ind->buffer_length);
+  result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
+  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+}
+
+static
+void m2ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
+
+   DevAssert(sctp_new_association_resp != NULL);
+
+  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+    LOG_W(M2AP, "Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+              sctp_new_association_resp->sctp_state,
+              instance,
+              sctp_new_association_resp->ulp_cnx_id);
+
+    if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN)
+      //proto_agent_stop(instance);
+      //f1ap_handle_setup_message(instance, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+    return; // exit -1 for debugging
+  }
+
+   // go to an init func
+  m2ap_mce_data_from_enb = (m2ap_setup_req_t *)calloc(1, sizeof(m2ap_setup_req_t));
+  // save the assoc id
+  m2ap_mce_data_from_enb->assoc_id         = sctp_new_association_resp->assoc_id;
+  m2ap_mce_data_from_enb->sctp_in_streams  = sctp_new_association_resp->in_streams;
+  m2ap_mce_data_from_enb->sctp_out_streams = sctp_new_association_resp->out_streams;
+
+
+
+ // m2ap_MCE_instance_t *instance_p;
+ // m2ap_MCE_data_t *m2ap_mce_data_p;
+ // DevAssert(sctp_new_association_resp != NULL);
+ // printf("m2ap_MCE_handle_sctp_association_resp at 1\n");
+ // dump_mce_trees_m2();
+ // instance_p = instance;//m2ap_MCE_get_instance(instance);
+ // DevAssert(instance_p != NULL);
+
+ // /* if the assoc_id is already known, it is certainly because an IND was received
+ //  * before. In this case, just update streams and return
+ //  */
+ // if (sctp_new_association_resp->assoc_id != -1) {
+ //   m2ap_mce_data_p = m2ap_get_MCE(instance_p, sctp_new_association_resp->assoc_id,
+ //                                  sctp_new_association_resp->ulp_cnx_id);
+
+ //   if (m2ap_mce_data_p != NULL) {
+ //     /* some sanity check - to be refined at some point */
+ //     if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+ //       M2AP_ERROR("m2ap_mce_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
+ //       abort();
+ //     }
+
+ //     m2ap_mce_data_p->in_streams  = sctp_new_association_resp->in_streams;
+ //     m2ap_mce_data_p->out_streams = sctp_new_association_resp->out_streams;
+ //     return;
+ //   }
+ // }
+
+ // m2ap_mce_data_p = m2ap_get_MCE(instance_p, -1,
+ //                                sctp_new_association_resp->ulp_cnx_id);
+ // DevAssert(m2ap_mce_data_p != NULL);
+ // printf("m2ap_MCE_handle_sctp_association_resp at 2\n");
+ // dump_mce_trees_m2();
+
+ // if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+ //   M2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+ //             sctp_new_association_resp->sctp_state,
+ //             instance,
+ //             sctp_new_association_resp->ulp_cnx_id);
+ //   //m2ap_eNB_handle_m2_setup_message(instance_p, m2ap_mce_data_p,
+ //                                //sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+ //   return;
+ // }
+
+ // printf("m2ap_MCE_handle_sctp_association_resp at 3\n");
+ // dump_mce_trees_m2();
+ // /* Update parameters */
+ // m2ap_mce_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
+ // m2ap_mce_data_p->in_streams  = sctp_new_association_resp->in_streams;
+ // m2ap_mce_data_p->out_streams = sctp_new_association_resp->out_streams;
+ // printf("m2ap_MCE_handle_sctp_association_resp at 4\n");
+ // dump_mce_trees_m2();
+ // /* Prepare new m2 Setup Request */
+ // //m2ap_MCE_generate_m2_setup_request(instance_p, m2ap_mce_data_p);
+}
+
+static
+void m2ap_MCE_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) {
+  //m2ap_MCE_instance_t *instance_p;
+  //m2ap_MCE_data_t *m2ap_mce_data_p;
+  //printf("m2ap_MCE_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
+  ///dump_mce_trees_m2();
+  ///DevAssert(sctp_new_association_ind != NULL);
+  ///instance_p = instance;//m2ap_MCE_get_instance(instance);
+  ///DevAssert(instance_p != NULL);
+  ///m2ap_mce_data_p = m2ap_get_MCE(instance_p, sctp_new_association_ind->assoc_id, -1);
+
+  ///if (m2ap_mce_data_p != NULL) abort();
+
+  /////  DevAssert(m2ap_enb_data_p != NULL);
+  ///if (m2ap_mce_data_p == NULL) {
+  ///  /* Create new MCE descriptor */
+  ///  m2ap_mce_data_p = calloc(1, sizeof(*m2ap_mce_data_p));
+  ///  DevAssert(m2ap_mce_data_p != NULL);
+  ///  m2ap_mce_data_p->cnx_id                = m2ap_MCE_fetch_add_global_cnx_id();
+  ///  m2ap_mce_data_p->m2ap_MCE_instance = instance_p;
+  ///  /* Insert the new descriptor in list of known MCE
+  ///   * but not yet associated.
+  ///   */
+  ///  RB_INSERT(m2ap_mce_map, &instance_p->m2ap_mce_head, m2ap_mce_data_p);
+  ///  m2ap_mce_data_p->state = M2AP_MCE_STATE_CONNECTED;
+  ///  instance_p->m2_target_mce_nb++;
+
+  ///  if (instance_p->m2_target_mce_pending_nb > 0) {
+  ///    instance_p->m2_target_mce_pending_nb--;
+  ///  }
+  ///} else {
+  ///  M2AP_WARN("m2ap_mce_data_p already exists\n");
+  ///}
+
+  ///printf("m2ap_MCE_handle_sctp_association_ind at 2\n");
+  ///dump_mce_trees_m2();
+  ////* Update parameters */
+  ///m2ap_mce_data_p->assoc_id    = sctp_new_association_ind->assoc_id;
+  ///m2ap_mce_data_p->in_streams  = sctp_new_association_ind->in_streams;
+  ///m2ap_mce_data_p->out_streams = sctp_new_association_ind->out_streams;
+  ///printf("m2ap_MCE_handle_sctp_association_ind at 3\n");
+  ///dump_mce_trees_m2();
+}
+
+int m2ap_MCE_init_sctp (m2ap_MCE_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t mce_port_for_M2C) {
+  // Create and alloc new message
+  MessageDef                             *message;
+  sctp_init_t                            *sctp_init  = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(local_ip_addr != NULL);
+  message = itti_alloc_new_message (TASK_M2AP_MCE, SCTP_INIT_MSG_MULTI_REQ);
+  sctp_init = &message->ittiMsg.sctp_init_multi;
+  sctp_init->port = mce_port_for_M2C;
+  sctp_init->ppid = M2AP_SCTP_PPID;
+  sctp_init->ipv4 = 1;
+  sctp_init->ipv6 = 0;
+  sctp_init->nb_ipv4_addr = 1;
+#if 0
+  memcpy(&sctp_init->ipv4_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+#endif
+  sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
+  /*
+   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+   * * * * Disable it for now.
+   */
+  sctp_init->nb_ipv6_addr = 0;
+  sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
+  return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
+}
+
+static void m2ap_MCE_register_MCE(m2ap_MCE_instance_t *instance_p,
+                                  net_ip_address_t    *target_MCE_ip_address,
+                                  net_ip_address_t    *local_ip_addr,
+                                  uint16_t             in_streams,
+                                  uint16_t             out_streams,
+                                  uint32_t         mce_port_for_M2C,
+                                  int                  multi_sd) {
+  MessageDef                       *message                   = NULL;
+  sctp_new_association_req_multi_t *sctp_new_association_req  = NULL;
+  m2ap_MCE_data_t                  *m2ap_mce_data             = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(target_MCE_ip_address != NULL);
+  message = itti_alloc_new_message(TASK_M2AP_MCE, SCTP_NEW_ASSOCIATION_REQ_MULTI);
+  sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi;
+  sctp_new_association_req->port = mce_port_for_M2C;
+  sctp_new_association_req->ppid = M2AP_SCTP_PPID;
+  sctp_new_association_req->in_streams  = in_streams;
+  sctp_new_association_req->out_streams = out_streams;
+  sctp_new_association_req->multi_sd = multi_sd;
+  memcpy(&sctp_new_association_req->remote_address,
+         target_MCE_ip_address,
+         sizeof(*target_MCE_ip_address));
+  memcpy(&sctp_new_association_req->local_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+  /* Create new MCE descriptor */
+  m2ap_mce_data = calloc(1, sizeof(*m2ap_mce_data));
+  DevAssert(m2ap_mce_data != NULL);
+  m2ap_mce_data->cnx_id                = m2ap_MCE_fetch_add_global_cnx_id();
+  sctp_new_association_req->ulp_cnx_id = m2ap_mce_data->cnx_id;
+  m2ap_mce_data->assoc_id          = -1;
+  m2ap_mce_data->m2ap_MCE_instance = instance_p;
+  /* Insert the new descriptor in list of known MCE
+   * but not yet associated.
+   */
+  RB_INSERT(m2ap_mce_map, &instance_p->m2ap_mce_head, m2ap_mce_data);
+  m2ap_mce_data->state = M2AP_MCE_STATE_WAITING;
+  instance_p->m2_target_mce_nb ++;
+  instance_p->m2_target_mce_pending_nb ++;
+  itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
+}
+
+static
+void m2ap_MCE_handle_register_MCE(instance_t instance,
+                                  m2ap_register_mce_req_t *m2ap_register_MCE) {
+  m2ap_MCE_instance_t *new_instance;
+  DevAssert(m2ap_register_MCE != NULL);
+  /* Look if the provided instance already exists */
+  new_instance = m2ap_MCE_get_instance(instance);
+
+  if (new_instance != NULL) {
+    /* Checks if it is a retry on the same MCE */
+    DevCheck(new_instance->MCE_id == m2ap_register_MCE->MCE_id, new_instance->MCE_id, m2ap_register_MCE->MCE_id, 0);
+    DevCheck(new_instance->cell_type == m2ap_register_MCE->cell_type, new_instance->cell_type, m2ap_register_MCE->cell_type, 0);
+    DevCheck(new_instance->tac == m2ap_register_MCE->tac, new_instance->tac, m2ap_register_MCE->tac, 0);
+    DevCheck(new_instance->mcc == m2ap_register_MCE->mcc, new_instance->mcc, m2ap_register_MCE->mcc, 0);
+    DevCheck(new_instance->mnc == m2ap_register_MCE->mnc, new_instance->mnc, m2ap_register_MCE->mnc, 0);
+    M2AP_WARN("MCE[%d] already registered\n", instance);
+  } else {
+    new_instance = calloc(1, sizeof(m2ap_MCE_instance_t));
+    DevAssert(new_instance != NULL);
+    RB_INIT(&new_instance->m2ap_mce_head);
+    /* Copy usefull parameters */
+    new_instance->instance         = instance;
+    new_instance->MCE_name         = m2ap_register_MCE->MCE_name;
+    new_instance->MCE_id           = m2ap_register_MCE->MCE_id;
+    new_instance->cell_type        = m2ap_register_MCE->cell_type;
+    new_instance->tac              = m2ap_register_MCE->tac;
+    new_instance->mcc              = m2ap_register_MCE->mcc;
+    new_instance->mnc              = m2ap_register_MCE->mnc;
+    new_instance->mnc_digit_length = m2ap_register_MCE->mnc_digit_length;
+    new_instance->num_cc           = m2ap_register_MCE->num_cc;
+
+    m2ap_id_manager_init(&new_instance->id_manager);
+    m2ap_timers_init(&new_instance->timers,
+                     m2ap_register_MCE->t_reloc_prep,
+                     m2ap_register_MCE->tm2_reloc_overall);
+
+    for (int i = 0; i< m2ap_register_MCE->num_cc; i++) {
+      new_instance->eutra_band[i]              = m2ap_register_MCE->eutra_band[i];
+      new_instance->downlink_frequency[i]      = m2ap_register_MCE->downlink_frequency[i];
+      new_instance->uplink_frequency_offset[i] = m2ap_register_MCE->uplink_frequency_offset[i];
+      new_instance->Nid_cell[i]                = m2ap_register_MCE->Nid_cell[i];
+      new_instance->N_RB_DL[i]                 = m2ap_register_MCE->N_RB_DL[i];
+      new_instance->frame_type[i]              = m2ap_register_MCE->frame_type[i];
+      new_instance->fdd_earfcn_DL[i]           = m2ap_register_MCE->fdd_earfcn_DL[i];
+      new_instance->fdd_earfcn_UL[i]           = m2ap_register_MCE->fdd_earfcn_UL[i];
+    }
+
+    DevCheck(m2ap_register_MCE->nb_m2 <= M2AP_MAX_NB_MCE_IP_ADDRESS,
+             M2AP_MAX_NB_MCE_IP_ADDRESS, m2ap_register_MCE->nb_m2, 0);
+    memcpy(new_instance->target_mce_m2_ip_address,
+           m2ap_register_MCE->target_mce_m2_ip_address,
+           m2ap_register_MCE->nb_m2 * sizeof(net_ip_address_t));
+    new_instance->nb_m2             = m2ap_register_MCE->nb_m2;
+    new_instance->mce_m2_ip_address = m2ap_register_MCE->mce_m2_ip_address;
+    new_instance->sctp_in_streams   = m2ap_register_MCE->sctp_in_streams;
+    new_instance->sctp_out_streams  = m2ap_register_MCE->sctp_out_streams;
+    new_instance->mce_port_for_M2C  = m2ap_register_MCE->mce_port_for_M2C;
+    /* Add the new instance to the list of MCE (meaningfull in virtual mode) */
+    m2ap_MCE_insert_new_instance(new_instance);
+    M2AP_INFO("Registered new MCE[%d] and %s MCE id %u\n",
+              instance,
+              m2ap_register_MCE->cell_type == CELL_MACRO_ENB ? "macro" : "home",
+              m2ap_register_MCE->MCE_id);
+
+    /* initiate the SCTP listener */
+    if (m2ap_MCE_init_sctp(new_instance,&m2ap_register_MCE->mce_m2_ip_address,m2ap_register_MCE->mce_port_for_M2C) <  0 ) {
+      M2AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
+      return;
+    }
+
+    M2AP_INFO("MCE[%d] MCE id %u acting as a listner (server)\n",
+              instance, m2ap_register_MCE->MCE_id);
+  }
+}
+
+static
+void m2ap_MCE_handle_sctp_init_msg_multi_cnf(
+  instance_t instance_id,
+  sctp_init_msg_multi_cnf_t *m) {
+  m2ap_MCE_instance_t *instance;
+  int index;
+  DevAssert(m != NULL);
+  instance = m2ap_MCE_get_instance(instance_id);
+  DevAssert(instance != NULL);
+  instance->multi_sd = m->multi_sd;
+
+  /* Exit if CNF message reports failure.
+   * Failure means multi_sd < 0.
+   */
+  if (instance->multi_sd < 0) {
+    M2AP_ERROR("Error: be sure to properly configure M2 in your configuration file.\n");
+    DevAssert(instance->multi_sd >= 0);
+  }
+
+  /* Trying to connect to the provided list of MCE ip address */
+
+  for (index = 0; index < instance->nb_m2; index++) {
+    M2AP_INFO("MCE[%d] MCE id %u acting as an initiator (client)\n",
+              instance_id, instance->MCE_id);
+    m2ap_MCE_register_MCE(instance,
+                          &instance->target_mce_m2_ip_address[index],
+                          &instance->mce_m2_ip_address,
+                          instance->sctp_in_streams,
+                          instance->sctp_out_streams,
+                          instance->mce_port_for_M2C,
+                          instance->multi_sd);
+  }
+}
+
+//static
+//void m2ap_MCE_handle_handover_req(instance_t instance,
+//                                  m2ap_handover_req_t *m2ap_handover_req)
+//{
+//  m2ap_MCE_instance_t *instance_p;
+//  m2ap_MCE_data_t     *target;
+//  m2ap_id_manager     *id_manager;
+//  int                 ue_id;
+//
+//  int target_pci = m2ap_handover_req->target_physCellId;
+//
+//  instance_p = m2ap_MCE_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m2ap_is_MCE_pci_in_list(target_pci);
+//  DevAssert(target != NULL);
+//
+//  /* allocate m2ap ID */
+//  id_manager = &instance_p->id_manager;
+//  ue_id = m2ap_allocate_new_id(id_manager);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not allocate a new M2AP UE ID\n");
+//    /* TODO: cancel handover: send (to be defined) message to RRC */
+//    exit(1);
+//  }
+//  /* id_source is ue_id, id_target is unknown yet */
+//  m2ap_set_ids(id_manager, ue_id, m2ap_handover_req->rnti, ue_id, -1);
+//  m2ap_id_set_state(id_manager, ue_id, M2ID_STATE_SOURCE_PREPARE);
+//  m2ap_set_reloc_prep_timer(id_manager, ue_id,
+//                            m2ap_timer_get_tti(&instance_p->timers));
+//  m2ap_id_set_target(id_manager, ue_id, target);
+//
+//  m2ap_MCE_generate_m2_handover_request(instance_p, target, m2ap_handover_req, ue_id);
+//}
+
+//static
+//void m2ap_MCE_handle_handover_req_ack(instance_t instance,
+//                                      m2ap_handover_req_ack_t *m2ap_handover_req_ack)
+//{
+//  /* TODO: remove this hack (the goal is to find the correct
+//   * eNodeB structure for the other end) - we need a proper way for RRC
+//   * and M2AP to identify eNodeBs
+//   * RRC knows about mod_id and M2AP knows about MCE_id (MCE_ID in
+//   * the configuration file)
+//   * as far as I understand.. CROUX
+//   */
+//  m2ap_MCE_instance_t *instance_p;
+//  m2ap_MCE_data_t     *target;
+//  int source_assoc_id = m2ap_handover_req_ack->source_assoc_id;
+//  int                 ue_id;
+//  int                 id_source;
+//  int                 id_target;
+//
+//  instance_p = m2ap_MCE_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m2ap_get_MCE(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  /* rnti is a new information, save it */
+//  ue_id     = m2ap_handover_req_ack->m2_id_target;
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//  m2ap_set_ids(&instance_p->id_manager, ue_id, m2ap_handover_req_ack->rnti, id_source, id_target);
+//
+//  m2ap_MCE_generate_m2_handover_request_ack(instance_p, target, m2ap_handover_req_ack);
+//}
+//
+//static
+//void m2ap_MCE_ue_context_release(instance_t instance,
+//                                 m2ap_ue_context_release_t *m2ap_ue_context_release)
+//{
+//  m2ap_MCE_instance_t *instance_p;
+//  m2ap_MCE_data_t     *target;
+//  int source_assoc_id = m2ap_ue_context_release->source_assoc_id;
+//  int ue_id;
+//  instance_p = m2ap_MCE_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m2ap_get_MCE(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  m2ap_MCE_generate_m2_ue_context_release(instance_p, target, m2ap_ue_context_release);
+//
+//  /* free the M2AP UE ID */
+//  ue_id = m2ap_find_id_from_rnti(&instance_p->id_manager, m2ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not find UE %x\n", m2ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  m2ap_release_id(&instance_p->id_manager, ue_id);
+//}
+
+void MCE_task_send_sctp_init_req(instance_t enb_id, m2ap_mce_sctp_req_t * m2ap_mce_sctp_req) {
+  // 1. get the itti msg, and retrive the enb_id from the message
+  // 2. use RC.rrc[enb_id] to fill the sctp_init_t with the ip, port
+  // 3. creat an itti message to init
+
+  LOG_I(M2AP, "M2AP_SCTP_REQ(create socket)\n");
+  MessageDef  *message_p = NULL;
+
+  message_p = itti_alloc_new_message (TASK_M2AP_MCE, SCTP_INIT_MSG);
+
+ // if( m2ap_mce_sctp_req == NULL ){
+ //         message_p->ittiMsg.sctp_init.port = M2AP_PORT_NUMBER;
+ //         message_p->ittiMsg.sctp_init.ppid = M2AP_SCTP_PPID;
+ //         message_p->ittiMsg.sctp_init.ipv4 = 1;
+ //         message_p->ittiMsg.sctp_init.ipv6 = 0;
+ //         message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
+ //         //message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+ //         message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr("127.0.0.7");
+ //         /*
+ //          * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+ //          * * * * Disable it for now.
+ //          */
+ //         message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0;
+ //         message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1";
+ // }else{
+	  message_p->ittiMsg.sctp_init.port = m2ap_mce_sctp_req->mce_port_for_M2C;
+	  message_p->ittiMsg.sctp_init.ppid = M2AP_SCTP_PPID;
+	  message_p->ittiMsg.sctp_init.ipv4 = 1;
+	  message_p->ittiMsg.sctp_init.ipv6 = 0;
+	  message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
+	  //message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+	  message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(m2ap_mce_sctp_req->mce_m2_ip_address.ipv4_address);
+	  /*
+	   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+	   * * * * Disable it for now.
+	   */
+	  message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0;
+	  message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1";
+ // }
+
+  itti_send_msg_to_task(TASK_SCTP, enb_id, message_p);
+}
+
+void *m2ap_MCE_task(void *arg) {
+  MessageDef *received_msg = NULL;
+  int         result;
+  M2AP_DEBUG("Starting M2AP layer\n");
+  m2ap_MCE_prepare_internal_data();
+  itti_mark_task_ready(TASK_M2AP_MCE);
+
+  //MCE_task_send_sctp_init_req(0,NULL);
+
+
+  while (1) {
+    itti_receive_msg(TASK_M2AP_MCE, &received_msg);
+
+    switch (ITTI_MSG_ID(received_msg)) {
+      case MESSAGE_TEST:
+	LOG_W(M2AP,"MCE Received MESSAGE_TEST Message\n");
+	//MessageDef * message_p = itti_alloc_new_message(TASK_M2AP_MCE, MESSAGE_TEST);
+        //itti_send_msg_to_task(TASK_M3AP, 1/*ctxt_pP->module_id*/, message_p);
+	break;
+      case TERMINATE_MESSAGE:
+        M2AP_WARN(" *** Exiting M2AP thread\n");
+        itti_exit_task();
+        break;
+
+      case M2AP_MCE_SCTP_REQ:
+	MCE_task_send_sctp_init_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+				     &M2AP_MCE_SCTP_REQ(received_msg));
+	break;
+
+      case M2AP_SUBFRAME_PROCESS:
+        m2ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg));
+        break;
+
+      case M2AP_REGISTER_MCE_REQ:
+	LOG_I(M2AP,"MCE Received M2AP_REGISTER_MCE_REQ Message\n");
+        m2ap_MCE_handle_register_MCE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_REGISTER_MCE_REQ(received_msg));
+        break;
+
+      case M2AP_SETUP_RESP:
+	LOG_I(M2AP,"MCE Received M2AP_SETUP_RESP Message\n");
+	MCE_send_M2_SETUP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+				    &M2AP_SETUP_RESP(received_msg));
+	break;
+
+      case M2AP_SETUP_FAILURE:
+	LOG_I(M2AP,"MCE Received M2AP_SETUP_FAILURE Message\n");
+	MCE_send_M2_SETUP_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+				    &M2AP_SETUP_FAILURE(received_msg));
+	break;
+
+      case M2AP_MBMS_SCHEDULING_INFORMATION:
+	LOG_I(M2AP,"MCE Received M2AP_MBMS_SCHEDULING_INFORMATION Message\n");
+        MCE_send_MBMS_SCHEDULING_INFORMATION(0,
+						&M2AP_MBMS_SCHEDULING_INFORMATION(received_msg));
+	break;
+
+       case M2AP_MBMS_SESSION_START_REQ:
+	LOG_I(M2AP,"MCE Received M2AP_MBMS_SESSION_START_REQ Message\n");
+        MCE_send_MBMS_SESSION_START_REQUEST(0,
+						&M2AP_MBMS_SESSION_START_REQ(received_msg));
+	break;
+
+       case M2AP_MBMS_SESSION_STOP_REQ:
+	LOG_I(M2AP,"MCE Received M2AP_MBMS_SESSION_STOP_REQ Message\n");
+        MCE_send_MBMS_SESSION_STOP_REQUEST(0,
+						&M2AP_MBMS_SESSION_STOP_REQ(received_msg));
+	break;
+	
+       case M2AP_MBMS_SESSION_UPDATE_REQ:
+	LOG_I(M2AP,"MCE Received M2AP_MBMS_SESSION_UPDATE_REQ Message\n");
+        MCE_send_MBMS_SESSION_UPDATE_REQUEST(0,
+						&M2AP_MBMS_SESSION_UPDATE_REQ(received_msg));
+	break;
+
+       case M2AP_RESET:
+	LOG_I(M2AP,"MCE Received M2AP_RESET Message\n");
+        MCE_send_RESET(0,
+						&M2AP_RESET(received_msg));
+	break;
+
+       case M2AP_ENB_CONFIGURATION_UPDATE_ACK:
+	LOG_I(M2AP,"MCE Received M2AP_ENB_CONFIGURATION_UPDATE_ACK Message\n");
+        MCE_send_ENB_CONFIGURATION_UPDATE_ACKNOWLEDGE(0,
+						&M2AP_ENB_CONFIGURATION_UPDATE_ACK(received_msg));
+	break;
+
+       case M2AP_ENB_CONFIGURATION_UPDATE_FAILURE:
+	LOG_I(M2AP,"MCE Received M2AP_ENB_CONFIGURATION_UPDATE_FAILURE Message\n");
+        MCE_send_ENB_CONFIGURATION_UPDATE_FAILURE(0,
+						&M2AP_ENB_CONFIGURATION_UPDATE_FAILURE(received_msg));
+	break;
+
+
+       case M2AP_MCE_CONFIGURATION_UPDATE:
+	LOG_I(M2AP,"MCE Received M2AP_MCE_CONFIGURATION_UPDATE Message\n");
+        //MCE_send_MCE_CONFIGURATION_UPDATE(0,
+						//&M2AP_MCE_CONFIGURATION_UPDATE(received_msg));
+	break;
+
+
+//      case M2AP_HANDOVER_REQ:
+//        m2ap_MCE_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                     &M2AP_HANDOVER_REQ(received_msg));
+//        break;
+//
+//      case M2AP_HANDOVER_REQ_ACK:
+//        m2ap_MCE_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                         &M2AP_HANDOVER_REQ_ACK(received_msg));
+//        break;
+//
+//      case M2AP_UE_CONTEXT_RELEASE:
+//        m2ap_MCE_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                                &M2AP_UE_CONTEXT_RELEASE(received_msg));
+//        break;
+//
+      case SCTP_INIT_MSG_MULTI_CNF:
+        LOG_D(M2AP,"MCE Received SCTP_INIT_MSG_MULTI_CNF Message\n");
+        m2ap_MCE_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                                &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_RESP:
+        LOG_D(M2AP,"MCE Received SCTP_NEW_ASSOCIATION_RESP Message\n");
+        m2ap_MCE_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                              &received_msg->ittiMsg.sctp_new_association_resp);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_IND:
+        LOG_D(M2AP,"MCE Received SCTP_NEW_ASSOCIATION Message\n");
+        m2ap_MCE_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                             &received_msg->ittiMsg.sctp_new_association_ind);
+        break;
+
+      case SCTP_DATA_IND:
+        LOG_D(M2AP,"MCE Received SCTP_DATA_IND Message\n");
+        m2ap_MCE_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                      &received_msg->ittiMsg.sctp_data_ind);
+        break;
+
+      default:
+        M2AP_ERROR("MCE Received unhandled message: %d:%s\n",
+                   ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
+        break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    received_msg = NULL;
+  }
+
+  return NULL;
+}
+
+#include "common/config/config_userapi.h"
+
+int is_m2ap_MCE_enabled(void)
+{
+  static volatile int config_loaded = 0;
+  static volatile int enabled = 0;
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+  if (pthread_mutex_lock(&mutex)) goto mutex_error;
+
+  if (config_loaded) {
+    if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+    return enabled;
+  }
+
+  char *enable_m2 = NULL;
+  paramdef_t p[] = {
+   { "enable_mce_m2", "yes/no", 0, strptr:&enable_m2, defstrval:"", TYPE_STRING, 0 }
+  };
+
+  /* TODO: do it per module - we check only first MCE */
+  config_get(p, sizeof(p)/sizeof(paramdef_t), "MCEs.[0]");
+  if (enable_m2 != NULL && strcmp(enable_m2, "yes") == 0)
+    enabled = 1;
+
+  config_loaded = 1;
+
+  if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+
+  return enabled;
+
+mutex_error:
+  LOG_E(M2AP, "mutex error\n");
+  exit(1);
+}
diff --git a/openair2/M2AP/m2ap_MCE.h b/openair2/M2AP/m2ap_MCE.h
new file mode 100644
index 0000000000000000000000000000000000000000..563b860883fe2caed0d050281eeedf8ec4ef6555
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE.h
+ * \brief m2ap tasks for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+/** @defgroup _m2ap_impl_ M2AP Layer Reference Implementation
+ * @ingroup _ref_implementation_
+ * @{
+ */
+
+#ifndef M2AP_MCE_H_
+#define M2AP_MCE_H_
+
+#include "m2ap_MCE_defs.h"
+
+
+int m2ap_MCE_init_sctp (m2ap_MCE_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t enb_port_for_M2C);
+
+void *m2ap_MCE_task(void *arg);
+
+int is_m2ap_MCE_enabled(void);
+
+#endif /* M2AP_MCE_H_ */
+
+/**
+ * @}
+ */
diff --git a/openair2/M2AP/m2ap_MCE_defs.h b/openair2/M2AP/m2ap_MCE_defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..5267232d69f5482ae6cab17371d0629aadbdc0e4
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_defs.h
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_defs.h
+ * \brief m2ap struct definitions for MCE
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "queue.h"
+#include "tree.h"
+
+#include "sctp_eNB_defs.h"
+
+#include "m2ap_ids.h" //looks X2AP specific for HO
+#include "m2ap_timers.h"
+
+#ifndef M2AP_MCE_DEFS_H_
+#define M2AP_MCE_DEFS_H_
+
+#define M2AP_MCE_NAME_LENGTH_MAX    (150)
+
+typedef enum {
+  /* Disconnected state: initial state for any association. */
+  M2AP_MCE_STATE_DISCONNECTED = 0x0,
+
+  /* State waiting for m2 Setup response message if the target MCE accepts or
+   * M2 Setup failure if rejects the MCE.
+   */
+  M2AP_MCE_STATE_WAITING     = 0x1,
+
+  /* The MCE is successfully connected to another MCE. */
+  M2AP_MCE_STATE_CONNECTED   = 0x2,
+
+  /* M2AP is ready, and the MCE is successfully connected to another MCE. */
+  M2AP_MCE_STATE_READY             = 0x3,
+
+  M2AP_MCE_STATE_OVERLOAD          = 0x4,
+
+  M2AP_MCE_STATE_RESETTING         = 0x5,
+
+  /* Max number of states available */
+  M2AP_MCE_STATE_MAX,
+} m2ap_MCE_state_t;
+
+/* Served PLMN identity element */
+/*struct plmn_identity_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+  STAILQ_ENTRY(plmn_identity_s) next;
+};*/
+
+/* Served group id element */
+/*struct served_group_id_s {
+  uint16_t mce_group_id;
+  STAILQ_ENTRY(served_group_id_s) next;
+};*/
+
+/* Served enn code for a particular MCE */
+/*struct mce_code_s {
+  uint8_t mce_code;
+  STAILQ_ENTRY(mce_code_s) next;
+};*/
+
+struct m2ap_MCE_instance_s;
+
+/* This structure describes association of a MCE to another MCE */
+typedef struct m2ap_MCE_data_s {
+  /* MCE descriptors tree, ordered by sctp assoc id */
+  RB_ENTRY(m2ap_MCE_data_s) entry;
+
+  /* This is the optional name provided by the MME */
+  char *MCE_name;
+
+  /*  target MCE ID */
+  uint32_t MCE_id;
+
+  /* Current MCE load information (if any). */
+  //m2ap_load_state_t overload_state;
+
+  /* Current MCE->MCE M2AP association state */
+  m2ap_MCE_state_t state;
+
+  /* Next usable stream for UE signalling */
+  int32_t nextstream;
+
+  /* Number of input/ouput streams */
+  uint16_t in_streams;
+  uint16_t out_streams;
+
+  /* Connexion id used between SCTP/M2AP */
+  uint16_t cnx_id;
+
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* Nid cells */
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* Only meaningfull in virtual mode */
+  struct m2ap_MCE_instance_s *m2ap_MCE_instance;
+} m2ap_MCE_data_t;
+
+typedef struct m2ap_MCE_instance_s {
+  /* used in simulation to store multiple MCE instances*/
+  STAILQ_ENTRY(m2ap_MCE_instance_s) m2ap_MCE_entries;
+
+  /* Number of target MCEs requested by MCE (tree size) */
+  uint32_t m2_target_mce_nb;
+  /* Number of target MCEs for which association is pending */
+  uint32_t m2_target_mce_pending_nb;
+  /* Number of target MCE successfully associated to MCE */
+  uint32_t m2_target_mce_associated_nb;
+  /* Tree of M2AP MCE associations ordered by association ID */
+  RB_HEAD(m2ap_mce_map, m2ap_MCE_data_s) m2ap_mce_head;
+
+  /* Tree of UE ordered by MCE_ue_m2ap_id's */
+  //  RB_HEAD(m2ap_ue_map, m2ap_MCE_ue_context_s) m2ap_ue_head;
+
+  /* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
+  instance_t instance;
+
+  /* Displayable name of MCE */
+  char *MCE_name;
+
+  /* Unique MCE_id to identify the MCE within EPC.
+   * In our case the MCE is a macro MCE so the id will be 20 bits long.
+   * For Home MCE id, this field should be 28 bits long.
+   */
+  uint32_t MCE_id;
+  /* The type of the cell */
+  cell_type_t cell_type;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t  mcc;
+  uint16_t  mnc;
+  uint8_t   mnc_digit_length;
+
+  /* CC params */
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int16_t                 N_RB_DL[MAX_NUM_CCs];
+  lte_frame_type_t        frame_type[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
+  net_ip_address_t target_mce_m2_ip_address[M2AP_MAX_NB_MCE_IP_ADDRESS];
+  uint8_t          nb_m2;
+  net_ip_address_t mce_m2_ip_address;
+  uint16_t         sctp_in_streams;
+  uint16_t         sctp_out_streams;
+  uint32_t         mce_port_for_M2C;
+  int              multi_sd;
+
+  m2ap_id_manager  id_manager;
+  m2ap_timers_t    timers;
+} m2ap_MCE_instance_t;
+
+typedef struct {
+  /* List of served MCEs
+   * Only used for virtual mode
+   */
+  STAILQ_HEAD(m2ap_MCE_instances_head_s, m2ap_MCE_instance_s) m2ap_MCE_instances_head;
+  /* Nb of registered MCEs */
+  uint8_t nb_registered_MCEs;
+
+  /* Generate a unique connexion id used between M2AP and SCTP */
+  uint16_t global_cnx_id;
+} m2ap_MCE_internal_data_t;
+
+int m2ap_MCE_compare_assoc_id(struct m2ap_MCE_data_s *p1, struct m2ap_MCE_data_s *p2);
+
+/* Generate the tree management functions */
+struct m2ap_MCE_map;
+struct m2ap_MCE_data_s;
+RB_PROTOTYPE(m2ap_MCE_map, m2ap_MCE_data_s, entry, m2ap_MCE_compare_assoc_id);
+
+
+#endif /* M2AP_MCE_DEFS_H_ */
diff --git a/openair2/M2AP/m2ap_MCE_generate_messages.c b/openair2/M2AP/m2ap_MCE_generate_messages.c
new file mode 100644
index 0000000000000000000000000000000000000000..a28097cf1afe014dbc74681c0f5a1fa55b57a71b
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_generate_messages.c
@@ -0,0 +1,804 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_generate_messages.c
+ * \brief m2ap procedures for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+//#include "M2AP_LastVisitedCell-Item.h"
+
+#include "m2ap_common.h"
+#include "m2ap_MCE.h"
+#include "m2ap_MCE_generate_messages.h"
+#include "m2ap_encoder.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+#include "m2ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+int m2ap_MCE_generate_m2_setup_request(
+  m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupRequest_t              *out;
+  M2AP_M2SetupRequest_Ies_t          *ie;
+  //M2AP_PLMN_Identity_t               *plmn;
+  //ServedCells__Member                *servedCellMember;
+  //M2AP_GU_Group_ID_t                 *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(m2ap_MCE_data_p != NULL);
+
+  m2ap_MCE_data_p->state = M2AP_MCE_STATE_WAITING;
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_M2SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M2SetupRequest;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GlobalMCE_ID;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_IEs__value_PR_GlobalMCE_ID;
+  //MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &ie->value.choice.GlobalMCE_ID.pLMN_Identity);
+  //ie->value.choice.GlobalMCE_ID.MCE_ID.present = M2AP_MCE_ID_PR_macro_MCE_ID;
+  //MACRO_MCE_ID_TO_BIT_STRING(instance_p->MCE_id,
+  //                           &ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID);
+  //M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->MCE_id,
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[0],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[1],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_IEs__value_PR_ServedCells;
+  //{
+  //  for (int i = 0; i<instance_p->num_cc; i++){
+  //    servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
+  //    {
+  //      servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
+
+  //      MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                    &servedCellMember->servedCellInfo.cellId.pLMN_Identity);
+  //      MACRO_MCE_ID_TO_CELL_IDENTITY(instance_p->MCE_id,0,
+  //                                 &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+
+  //      INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+  //      plmn = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_PLMN_Identity_t));
+  //      {
+  //        MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
+  //        ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
+  //      }
+
+  //      if (instance_p->frame_type[i] == FDD) {
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = M2AP_EUTRA_Mode_Info_PR_fDD;
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
+  //        switch (instance_p->N_RB_DL[i]) {
+  //          case 6:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            break;
+  //          case 15:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            break;
+  //          case 25:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            break;
+  //          case 50:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            break;
+  //          case 75:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            break;
+  //          case 100:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            break;
+  //          default:
+  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+  //            break;
+  //        }
+  //      }
+  //      else {
+  //        AssertFatal(0,"M2Setuprequest not supported for TDD!");
+  //      }
+  //    }
+  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+  //  }
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_IEs__value_PR_GUGroupIDList;
+  //{
+  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_GU_Group_ID_t));
+  //  {
+  //    MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &gu->pLMN_Identity);
+  //    //@TODO: consider to update this value
+  //    INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
+  //  }
+  //  ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup request\n");
+    return -1;
+  }
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 M2Setup/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_generate_m2_setup_response(m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupResponse_t              *out;
+  M2AP_M2SetupResponse_Ies_t          *ie;
+  //M2AP_PLMN_Identity_t                *plmn;
+  //ServedCells__Member                 *servedCellMember;
+  //M2AP_GU_Group_ID_t                  *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(m2ap_MCE_data_p != NULL);
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_M2SetupResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.M2SetupResponse;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GlobalMCE_ID;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GlobalMCE_ID;
+  //MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &ie->value.choice.GlobalMCE_ID.pLMN_Identity);
+  //ie->value.choice.GlobalMCE_ID.MCE_ID.present = M2AP_MCE_ID_PR_macro_MCE_ID;
+  //MACRO_MCE_ID_TO_BIT_STRING(instance_p->MCE_id,
+  //                           &ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID);
+  //M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->MCE_id,
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[0],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[1],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_ServedCells;
+  //{
+  //  for (int i = 0; i<instance_p->num_cc; i++){
+  //    servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
+  //    {
+  //      servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
+
+  //      MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                    &servedCellMember->servedCellInfo.cellId.pLMN_Identity);
+  //      MACRO_MCE_ID_TO_CELL_IDENTITY(instance_p->MCE_id,0,
+  //                                 &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+
+  //      INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+  //      plmn = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_PLMN_Identity_t));
+  //      {
+  //        MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
+  //        ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
+  //      }
+
+  //      if (instance_p->frame_type[i] == FDD) {
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = M2AP_EUTRA_Mode_Info_PR_fDD;
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
+  //        switch (instance_p->N_RB_DL[i]) {
+  //          case 6:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            break;
+  //          case 15:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            break;
+  //          case 25:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            break;
+  //          case 50:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            break;
+  //          case 75:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            break;
+  //          case 100:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            break;
+  //          default:
+  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+  //            break;
+  //        }
+  //      }
+  //      else {
+  //        AssertFatal(0,"M2Setupresponse not supported for TDD!");
+  //      }
+  //    }
+  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+  //  }
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GUGroupIDList;
+  //{
+  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_GU_Group_ID_t));
+  //  {
+  //    MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &gu->pLMN_Identity);
+  //    //@TODO: consider to update this value
+  //    INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
+  //  }
+  //  ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup response\n");
+    return -1;
+  }
+
+  m2ap_MCE_data_p->state = M2AP_MCE_STATE_READY;
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 M2Setup/successfulOutcome assoc_id %u", m2ap_MCE_data_p->assoc_id);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupFailure_t              *out;
+  M2AP_M2SetupFailure_Ies_t          *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+  pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.unsuccessfulOutcome.criticality = M2AP_Criticality_reject;
+  pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_Cause;
+  //ie->criticality = M2AP_Criticality_ignore;
+  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_Cause;
+
+  //m2ap_MCE_set_cause (&ie->value.choice.Cause, cause_type, cause_value);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional: consider to handle this later */
+  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_TimeToWait;
+  //ie->criticality = M2AP_Criticality_ignore;
+  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_TimeToWait;
+
+  //if (time_to_wait > -1) {
+  //  ie->value.choice.TimeToWait = time_to_wait;
+  //}
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup failure\n");
+    return -1;
+  }
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE,
+  //                    MSC_M2AP_TARGET_MCE, NULL, 0,
+  //                    "0 M2Setup/unsuccessfulOutcome  assoc_id %u cause %u value %u",
+  //                    assoc_id, cause_type, cause_value);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value)
+{
+
+  DevAssert (cause_p != NULL);
+  cause_p->present = cause_type;
+
+  switch (cause_type) {
+  case M2AP_Cause_PR_radioNetwork:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_transport:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_protocol:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_misc:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+//int m2ap_MCE_generate_m2_handover_request (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id)
+//{
+//
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_HandoverRequest_t              *out;
+//  M2AP_HandoverRequest_IEs_t          *ie;
+//  M2AP_E_RABs_ToBeSetup_ItemIEs_t     *e_RABS_ToBeSetup_ItemIEs;
+//  M2AP_E_RABs_ToBeSetup_Item_t        *e_RABs_ToBeSetup_Item;
+//  M2AP_LastVisitedCell_Item_t         *lastVisitedCell_Item;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverRequest;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_Cause;
+//  ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetCell_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_ECGI;
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &ie->value.choice.ECGI.pLMN_Identity);
+//  MACRO_MCE_ID_TO_CELL_IDENTITY(m2ap_MCE_data_p->MCE_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_GUMMEI_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_GUMMEI;
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &ie->value.choice.GUMMEI.gU_Group_ID.pLMN_Identity);
+//  //@TODO: consider to update these values
+//  INT16_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
+//  MME_CODE_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_ContextInformation;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
+//  //@TODO: consider to update this value
+//  ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = m2ap_handover_req->mme_ue_s1ap_id;
+//
+//  KMCE_STAR_TO_BIT_STRING(m2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
+//
+//  if (m2ap_handover_req->kenb_ncc >=0) { // Check this condition
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = m2ap_handover_req->kenb_ncc;
+//  }
+//  else {
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
+//  }
+//
+//  ENCRALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.encryption_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+//
+//  INTPROTALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.integrity_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
+//
+//  //@TODO: update with proper UEAMPR
+//  UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
+//  UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
+//  {
+//    for (int i=0;i<m2ap_handover_req->nb_e_rabs_tobesetup;i++) {
+//      e_RABS_ToBeSetup_ItemIEs = (M2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_ToBeSetup_ItemIEs_t));
+//      e_RABS_ToBeSetup_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
+//      e_RABS_ToBeSetup_ItemIEs->criticality = M2AP_Criticality_ignore;
+//      e_RABS_ToBeSetup_ItemIEs->value.present = M2AP_E_RABs_ToBeSetup_ItemIEs__value_PR_E_RABs_ToBeSetup_Item;
+//      e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
+//      {
+//        e_RABs_ToBeSetup_Item->e_RAB_ID = m2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = m2ap_handover_req->e_rab_param[i].qos.qci;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(m2ap_handover_req->e_rabs_tobesetup[i].MCE_addr.length/8);
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = m2ap_handover_req->e_rabs_tobesetup[i].MCE_addr.length%8;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf =
+//                        calloc(1,e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        memcpy (e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
+//                        m2ap_handover_req->e_rabs_tobesetup[i].MCE_addr.buffer,
+//                        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        INT32_TO_OCTET_STRING(m2ap_handover_req->e_rabs_tobesetup[i].gtp_teid,&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID);
+//      }
+//      ASN_SEQUENCE_ADD(&ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list, e_RABS_ToBeSetup_ItemIEs);
+//    }
+//  }
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.UE_ContextInformation.rRC_Context, (char*) m2ap_handover_req->rrc_buffer, m2ap_handover_req->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_HistoryInformation;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
+//  //@TODO: consider to update this value
+//  {
+//   lastVisitedCell_Item = (M2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(M2AP_LastVisitedCell_Item_t));
+//   lastVisitedCell_Item->present = M2AP_LastVisitedCell_Item_PR_e_UTRAN_Cell;
+//   MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
+//   MACRO_MCE_ID_TO_CELL_IDENTITY(0, 0, &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
+//   lastVisitedCell_Item->choice.e_UTRAN_Cell.cellType.cell_Size = M2AP_Cell_Size_small;
+//   lastVisitedCell_Item->choice.e_UTRAN_Cell.time_UE_StayedInCell = 2;
+//   ASN_SEQUENCE_ADD(&ie->value.choice.UE_HistoryInformation.list, lastVisitedCell_Item);
+//  }
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover request\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_handover_request_ack (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack)
+//{
+//
+//  M2AP_M2AP_PDU_t                        pdu;
+//  M2AP_HandoverRequestAcknowledge_t      *out;
+//  M2AP_HandoverRequestAcknowledge_IEs_t  *ie;
+//  M2AP_E_RABs_Admitted_ItemIEs_t         *e_RABS_Admitted_ItemIEs;
+//  M2AP_E_RABs_Admitted_Item_t            *e_RABs_Admitted_Item;
+//  int                                    ue_id;
+//  int                                    id_source;
+//  int                                    id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id     = m2ap_handover_req_ack->m2_id_target;
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
+//  out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
+//
+//  {
+//      for (int i=0;i<m2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
+//        e_RABS_Admitted_ItemIEs = (M2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_Admitted_ItemIEs_t));
+//        e_RABS_Admitted_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
+//        e_RABS_Admitted_ItemIEs->criticality = M2AP_Criticality_ignore;
+//        e_RABS_Admitted_ItemIEs->value.present = M2AP_E_RABs_Admitted_ItemIEs__value_PR_E_RABs_Admitted_Item;
+//        e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
+//        {
+//          e_RABs_Admitted_Item->e_RAB_ID = m2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
+//        }
+//        ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_List.list, e_RABS_Admitted_ItemIEs);
+//      }
+//  }
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetMCEtoSource_MCETransparentContainer;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_TargetMCEtoSource_MCETransparentContainer;
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.TargetMCEtoSource_MCETransparentContainer, (char*) m2ap_handover_req_ack->rrc_buffer, m2ap_handover_req_ack->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover response\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_ue_context_release (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p, m2ap_ue_context_release_t *m2ap_ue_context_release)
+//{
+//
+//  M2AP_M2AP_PDU_t                pdu;
+//  M2AP_UEContextRelease_t        *out;
+//  M2AP_UEContextRelease_IEs_t    *ie;
+//  int                            ue_id;
+//  int                            id_source;
+//  int                            id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id = m2ap_find_id_from_rnti(&instance_p->id_manager, m2ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not find UE %x\n", m2ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP ue context relase message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_uEContextRelease;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_UEContextRelease;
+//  out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 UE Context Release\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_handover_cancel (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause)
+//{
+//  M2AP_M2AP_PDU_t              pdu;
+//  M2AP_HandoverCancel_t        *out;
+//  M2AP_HandoverCancel_IEs_t    *ie;
+//  int                          ue_id;
+//  int                          id_source;
+//  int                          id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id = m2_ue_id;
+//  id_source = ue_id;
+//  id_target = m2ap_id_get_id_target(&instance_p->id_manager, ue_id);
+//
+//  /* Prepare the M2AP handover cancel message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverCancel;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverCancel;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  if (id_target != -1) {
+//    ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//    ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//    ie->criticality = M2AP_Criticality_ignore;
+//    ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID_1;
+//    ie->value.choice.UE_M2AP_ID_1 = id_target;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_Cause;
+//  switch (cause) {
+//  case M2AP_T_RELOC_PREP_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_trelocprep_expiry;
+//    break;
+//  case M2AP_TX2_RELOC_OVERALL_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_tx2relocoverall_expiry;
+//    break;
+//  default:
+//    /* we can't come here */
+//    M2AP_ERROR("unhandled cancel cause\n");
+//    exit(1);
+//  }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 Handover Cancel\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
diff --git a/openair2/M2AP/m2ap_MCE_generate_messages.h b/openair2/M2AP/m2ap_MCE_generate_messages.h
new file mode 100644
index 0000000000000000000000000000000000000000..1632dc807acc307de1af06650f2f824272239c7a
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_generate_messages.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_generate_messages.h
+ * \brief m2ap procedures for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_GENERATE_MESSAGES_H_
+#define M2AP_MCE_GENERATE_MESSAGES_H_
+
+#include "m2ap_MCE_defs.h"
+#include "m2ap_common.h"
+
+int m2ap_MCE_generate_m2_setup_request(m2ap_MCE_instance_t *instance_p,
+				       m2ap_MCE_data_t *m2ap_MCE_data_p);
+
+int m2ap_MCE_generate_m2_setup_response(m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p);
+
+int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait);
+
+int m2ap_MCE_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value);
+
+//int m2ap_MCE_generate_m2_handover_request (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id);
+//
+//int m2ap_MCE_generate_m2_handover_request_ack (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack);
+//
+//int m2ap_MCE_generate_m2_ue_context_release (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                             m2ap_ue_context_release_t *m2ap_ue_context_release);
+//
+//int m2ap_MCE_generate_m2_handover_cancel (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause);
+
+#endif /*  M2AP_MCE_GENERATE_MESSAGES_H_ */
diff --git a/openair2/M2AP/m2ap_MCE_handler.c b/openair2/M2AP/m2ap_MCE_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..85e342f9964c08d71648f0d8479ec7ee598a8dc3
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_handler.c
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_handler.c
+ * \brief m2ap handler procedures for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m2ap_common.h"
+#include "m2ap_MCE_defs.h"
+#include "m2ap_MCE_handler.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+//#include "m2ap_MCE_management_procedures.h"
+#include "m2ap_MCE_generate_messages.h"
+
+#include "m2ap_MCE_interface_management.h"
+//#include "m2ap_eNB_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m2ap_message_decoded_callback m2ap_MCE_messages_callback[][3] = {
+  { 0, MCE_handle_MBMS_SESSION_START_RESPONSE, 0 }, /* MBMSSessionStart  */
+  { 0, MCE_handle_MBMS_SESSION_STOP_RESPONSE, 0 }, /* MBMSSessionStop */
+  { 0, MCE_handle_MBMS_SCHEDULING_INFORMATION_RESPONSE, 0 }, /* MBMSSchedulingInformation */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { MCE_handle_M2_SETUP_REQUEST, 0, 0 }, /* M2 Setup */
+  { 0, 0, 0 }, /* eNBConfigurationUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { 0, 0, 0 }, /* privateMessage */
+  { 0, 0, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MBMSServiceCounting */
+  { 0, 0, 0 }, /* MBMSServiceCountingResultReport */
+  { 0, 0, 0 } /* MBMSOverloadNotification */
+};
+
+static char *m2ap_direction2String(int m2ap_dir) {
+static char *m2ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m2ap_direction_String[m2ap_dir]);
+}
+
+
+int m2ap_MCE_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M2AP_M2AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  if (m2ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M2AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m2ap_MCE_messages_callback) / (3 * sizeof(
+        m2ap_MCE_message_decoded_callback))
+      || (pdu.present > M2AP_M2AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M2AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
+               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m2ap_MCE_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M2AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m2ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M2AP, "Calling handler with instance %d\n",instance);
+  ret = (*m2ap_MCE_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair2/M2AP/m2ap_MCE_handler.h b/openair2/M2AP/m2ap_MCE_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..e9faae8f5d972c06655650583492914b92897e25
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_handler.h
+ * \brief m2ap handler procedures for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_HANDLERS_H_
+#define M2AP_MCE_HANDLERS_H_
+
+#include "m2ap_MCE_defs.h"
+
+//void m2ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+int m2ap_MCE_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+//int m2ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            //const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M2AP_MCE_HANDLERS_H_ */
diff --git a/openair2/M2AP/m2ap_MCE_interface_management.c b/openair2/M2AP/m2ap_MCE_interface_management.c
new file mode 100644
index 0000000000000000000000000000000000000000..1bef8341794aea861c475fe077e850cbc3456f7b
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_interface_management.c
@@ -0,0 +1,1421 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_interface_management.c
+ * \brief m2ap interface management for MCE
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "m2ap_common.h"
+#include "m2ap_encoder.h"
+#include "m2ap_decoder.h"
+#include "m2ap_itti_messaging.h"
+#include "m2ap_MCE_interface_management.h"
+
+#include "conversions.h"
+
+extern m2ap_setup_req_t *m2ap_mce_data_from_enb;
+
+/*
+ * MBMS Session start
+ */
+int MCE_send_MBMS_SESSION_START_REQUEST(instance_t instance/*, uint32_t assoc_id*/,m2ap_session_start_req_t* m2ap_session_start_req){
+
+  //AssertFatal(1==0,"Not implemented yet\n");
+    
+  //module_id_t enb_mod_idP=0;
+  //module_id_t du_mod_idP=0;
+
+  M2AP_M2AP_PDU_t          pdu; 
+  M2AP_SessionStartRequest_t       *out;
+  M2AP_SessionStartRequest_Ies_t   *ie;
+
+  uint8_t *buffer;
+  uint32_t len;
+  //int	   i=0; 
+  //int 	   j=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_sessionStart;
+  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_SessionStartRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.SessionStartRequest;  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+  ie = (M2AP_SessionStartRequest_Ies_t *)calloc(1, sizeof(M2AP_SessionStartRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStartRequest_Ies__value_PR_MCE_MBMS_M2AP_ID;
+  //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. TMGI (integrer value) */
+  ie = (M2AP_SessionStartRequest_Ies_t *)calloc(1, sizeof(M2AP_SessionStartRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_TMGI;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStartRequest_Ies__value_PR_TMGI;
+  MCC_MNC_TO_PLMNID(0,0,3,&ie->value.choice.TMGI.pLMNidentity);/*instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,*/
+  uint8_t TMGI[5] = {4,3,2,1,0};
+  OCTET_STRING_fromBuf(&ie->value.choice.TMGI.serviceID,(const char*)&TMGI[2],3);
+ 
+                       //&ie->choice.TMGI.pLMN_Identity);
+  //INT16_TO_OCTET_STRING(0,&ie->choice.TMGI.serviceId);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c3. MBMS_Session_ID (integrer value) */ //OCTET_STRING
+  if(0){
+	  ie = (M2AP_SessionStartRequest_Ies_t *)calloc(1, sizeof(M2AP_SessionStartRequest_Ies_t));
+	  ie->id                        = M2AP_ProtocolIE_ID_id_MBMS_Session_ID;
+	  ie->criticality               = M2AP_Criticality_reject;
+	  ie->value.present             = M2AP_SessionStartRequest_Ies__value_PR_MBMS_Session_ID;
+  	  //INT16_TO_OCTET_STRING(0,&ie->choice.MBMS_Session_ID);
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */
+  /* c5. MBMS_Service_Area (integrer value) */ //OCTET_STRING
+  ie = (M2AP_SessionStartRequest_Ies_t *)calloc(1, sizeof(M2AP_SessionStartRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MBMS_Service_Area; 
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStartRequest_Ies__value_PR_MBMS_Service_Area;
+  //OCTET_STRING_fromBuf(&ie->value.choice.MBMS_Service_Area, m2ap_setup_resp->MCEname,
+                         //strlen(m2ap_setup_resp->MCEname));
+  //INT16_TO_OCTET_STRING(0,&ie->choice.TMGI.serviceId);
+  ie->value.choice.MBMS_Service_Area.buf = calloc(3,sizeof(uint8_t));
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  /* mandatory */
+  /* c6. TNL_Information (integrer value) */
+  ie = (M2AP_SessionStartRequest_Ies_t *)calloc(1, sizeof(M2AP_SessionStartRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_TNL_Information; 
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStartRequest_Ies__value_PR_TNL_Information;
+  //ie->value.choice.TNL_Information.iPMCAddress.buf = calloc(4,sizeof(uint8_t));
+  //ie->value.choice.TNL_Information.iPSourceAddress.buf = calloc(4,sizeof(uint8_t));
+  //TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234,&ie->value.choice.TNL_Information.iPMCAddress);
+  //TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234,&ie->value.choice.TNL_Information.iPSourceAddress);
+  
+  OCTET_STRING_fromBuf(&ie->value.choice.TNL_Information.gTP_TEID, "1204",strlen("1234"));
+  OCTET_STRING_fromBuf(&ie->value.choice.TNL_Information.iPMCAddress, "1204",strlen("1234"));
+  OCTET_STRING_fromBuf(&ie->value.choice.TNL_Information.iPSourceAddress, "1204",strlen("1234"));
+  
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if(0){
+	 // /* optional */
+	 // /* c7. TNL_Information_1 (integrer value) */
+	 // ie = (M2AP_SessionStartRequest_Ies_t *)calloc(1, sizeof(M2AP_SessionStartRequest_Ies_t));
+	 // ie->id                        = M2AP_ProtocolIE_ID_id_TNL_Information_1; 
+	 // ie->criticality               = M2AP_Criticality_reject;
+	 // ie->value.present             = M2AP_SessionStartRequest_Ies__value_PR_TNL_Information_1;
+	 // //asn_int642INTEGER(&ie->value.choice.MBMS_Session_ID, f1ap_du_data->MBMS_Session_ID); //?
+	 // ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+   
+
+  /* encode */
+  if (m2ap_encode_pdu(&pdu,&buffer,&len) < 0){
+	return -1;
+  }
+
+  //MCE_m2ap_itti_send_sctp_data_req(instance, m2ap_mce_data_from_mce->assoid,buffer,len,0); 
+  m2ap_MCE_itti_send_sctp_data_req(instance,m2ap_mce_data_from_enb->assoc_id,buffer,len,0);
+  return 0;
+
+}
+
+int MCE_handle_MBMS_SESSION_START_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu){
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M2AP, "MCE_handle_MBMS_SESSION_START_RESPONSE\n");
+
+   AssertFatal(pdu->present == M2AP_M2AP_PDU_PR_successfulOutcome,
+	       "pdu->present != M2AP_M2AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M2AP_ProcedureCode_id_sessionStart,
+	       "pdu->choice.successfulOutcome->procedureCode != M2AP_ProcedureCode_id_sessionStart\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M2AP_Criticality_reject,
+	       "pdu->choice.successfulOutcome->criticality != M2AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M2AP_SuccessfulOutcome__value_PR_SessionStartResponse,
+	       "pdu->choice.successfulOutcome.value.present != M2AP_SuccessfulOutcome__value_PR_SessionStartResponse\n");
+
+
+  M2AP_SessionStartResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.SessionStartResponse;
+  M2AP_SessionStartResponse_Ies_t  *ie;
+  int MCE_MBMS_M2AP_ID=-1;
+  int ENB_MBMS_M2AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE,M2AP_MBMS_SESSION_START_RESP); //TODO
+
+  LOG_D(M2AP, "M2AP: SessionStart-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID:
+       AssertFatal(ie->criticality == M2AP_Criticality_reject,
+                   "ie->criticality != M2AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M2AP_SessionStartResponse_Ies__value_PR_MCE_MBMS_M2AP_ID,
+                   "ie->value.present != M2AP_sessionStartResponse_IEs__value_PR_MCE_MBMS_M2AP_ID\n");
+       MCE_MBMS_M2AP_ID=ie->value.choice.MCE_MBMS_M2AP_ID;
+       LOG_D(M2AP, "M2AP: SessionStart-Resp: MCE_MBMS_M2AP_ID %d\n",
+             MCE_MBMS_M2AP_ID);
+       break;
+      case M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID:
+       AssertFatal(ie->criticality == M2AP_Criticality_reject,
+                   "ie->criticality != M2AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M2AP_SessionStartResponse_Ies__value_PR_ENB_MBMS_M2AP_ID,
+                   "ie->value.present != M2AP_sessionStartResponse_Ies__value_PR_ENB_MBMS_M2AP_ID\n");
+       ENB_MBMS_M2AP_ID=ie->value.choice.ENB_MBMS_M2AP_ID;
+       LOG_D(M2AP, "M2AP: SessionStart-Resp: ENB_MBMS_M2AP_ID %d\n",
+             ENB_MBMS_M2AP_ID);
+       break;
+     }
+  }
+
+  AssertFatal(MCE_MBMS_M2AP_ID!=-1,"MCE_MBMS_M2AP_ID was not sent\n");
+  AssertFatal(ENB_MBMS_M2AP_ID!=-1,"ENB_MBMS_M2AP_ID was not sent\n");
+  //M2AP_SESSION_START_RESP(msg_p).
+//  MSC_LOG_RX_MESSAGE(
+//    MSC_M2AP_MCE,
+//    MSC_M2AP_ENB,
+	//return 0;
+//    0,
+//    0,
+//    MSC_AS_TIME_FMT" MCE_handle_M2_SESSION_START_RESPONSE successfulOutcome assoc_id %d",
+//    0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+//    assoc_id);
+//
+   LOG_D(M2AP, "Sending M2AP_SESSION_START_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n",
+         assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id));
+   itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g);
+   return 0;
+
+}
+int MCE_handle_MBMS_SESSION_START_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+/*
+ * MBMS Session stop
+ */
+int MCE_send_MBMS_SESSION_STOP_REQUEST(instance_t instance, m2ap_session_stop_req_t* m2ap_session_stop_req){
+
+    
+ // module_id_t enb_mod_idP=0;
+  //module_id_t du_mod_idP=0;
+
+  M2AP_M2AP_PDU_t          pdu; 
+  M2AP_SessionStopRequest_t        *out;
+  M2AP_SessionStopRequest_Ies_t    *ie;
+
+  uint8_t *buffer;
+  uint32_t len;
+  //int	   i=0; 
+  //int 	   j=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_sessionStop;
+  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_SessionStopRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.SessionStopRequest; 
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+  ie = (M2AP_SessionStopRequest_Ies_t *)calloc(1, sizeof(M2AP_SessionStopRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStopRequest_Ies__value_PR_MCE_MBMS_M2AP_ID;
+  ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. ENB_MBMS_M2AP_ID (integer value) */ //long
+  ie = (M2AP_SessionStopRequest_Ies_t *)calloc(1, sizeof(M2AP_SessionStopRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStopRequest_Ies__value_PR_ENB_MBMS_M2AP_ID;
+  ie->value.choice.ENB_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  /* encode */
+  if (m2ap_encode_pdu(&pdu,&buffer,&len) < 0){
+	return -1;
+  }
+
+  //MCE_m2ap_itti_send_sctp_data_req(instance, m2ap_mce_data_from_mce->assoid,buffer,len,0); 
+  m2ap_MCE_itti_send_sctp_data_req(instance, m2ap_mce_data_from_enb->assoc_id,buffer,len,0);
+  return 0;
+
+
+                        
+}
+
+int MCE_handle_MBMS_SESSION_STOP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu){
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M2AP, "MCE_handle_MBMS_SESSION_STOP_RESPONSE\n");
+
+   AssertFatal(pdu->present == M2AP_M2AP_PDU_PR_successfulOutcome,
+	       "pdu->present != M2AP_M2AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M2AP_ProcedureCode_id_sessionStop,
+	       "pdu->choice.successfulOutcome->procedureCode != M2AP_ProcedureCode_id_sessionStop\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M2AP_Criticality_reject,
+	       "pdu->choice.successfulOutcome->criticality != M2AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M2AP_SuccessfulOutcome__value_PR_SessionStopResponse,
+	       "pdu->choice.successfulOutcome->value.present != M2AP_SuccessfulOutcome__value_PR_SessionStopResponse\n");
+
+
+  M2AP_SessionStopResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.SessionStopResponse;
+  M2AP_SessionStopResponse_Ies_t  *ie;
+  int MCE_MBMS_M2AP_ID=-1;
+  int ENB_MBMS_M2AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE,M2AP_MBMS_SESSION_STOP_RESP); //TODO
+
+  LOG_D(M2AP, "M2AP: SessionStop-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID:
+       AssertFatal(ie->criticality == M2AP_Criticality_reject,
+                   "ie->criticality != M2AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M2AP_SessionStopResponse_Ies__value_PR_MCE_MBMS_M2AP_ID,
+                   "ie->value.present != M2AP_SessionStopResponse_Ies__value_PR_MCE_MBMS_M2AP_ID\n");
+       MCE_MBMS_M2AP_ID=ie->value.choice.MCE_MBMS_M2AP_ID;
+       LOG_D(M2AP, "M2AP: SessionStop-Resp: MCE_MBMS_M2AP_ID %d\n",
+             MCE_MBMS_M2AP_ID);
+       break;
+      case M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID:
+       AssertFatal(ie->criticality == M2AP_Criticality_reject,
+                   "ie->criticality != M2AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M2AP_SessionStopResponse_Ies__value_PR_ENB_MBMS_M2AP_ID,
+                   "ie->value.present != M2AP_SessionStopResponse_Ies__value_PR_ENB_MBMS_M2AP_ID\n");
+       ENB_MBMS_M2AP_ID=ie->value.choice.ENB_MBMS_M2AP_ID;
+       LOG_D(M2AP, "M2AP: SessionStop-Resp: ENB_MBMS_M2AP_ID %d\n",
+             ENB_MBMS_M2AP_ID);
+       break;
+     }
+  }
+
+  AssertFatal(MCE_MBMS_M2AP_ID!=-1,"MCE_MBMS_M2AP_ID was not sent\n");
+  AssertFatal(ENB_MBMS_M2AP_ID!=-1,"ENB_MBMS_M2AP_ID was not sent\n");
+ // M2AP_SESSION_STOP_RESP(msg_p).
+ // MSC_LOG_RX_MESSAGE(
+ //   MSC_M2AP_MCE,
+ //   MSC_M2AP_ENB,
+ //   0,
+ //   0,
+ //   MSC_AS_TIME_FMT" MCE_handle_M2_SESSION_STOP_RESPONSE successfulOutcome assoc_id %d",
+ //   0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ //   assoc_id);
+
+ //  LOG_D(M2AP, "Sending M2AP_SESSION_START_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n",
+ //        assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id));
+   itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g);
+ //                      
+	return 0;
+}
+
+
+
+int MCE_handle_MBMS_SESSION_STOP_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+                      
+}
+ typedef struct M2AP_MBSFN_Area_Configuration{
+	M2AP_PMCH_Configuration_List_t   PMCH_Configuration_List;
+        M2AP_MBSFN_Subframe_ConfigurationList_t  MBSFN_Subframe_ConfigurationList;
+        M2AP_Common_Subframe_Allocation_Period_t         Common_Subframe_Allocation_Period;
+        M2AP_MBSFN_Area_ID_t     MBSFN_Area_ID;
+        M2AP_MBMS_Suspension_Notification_List_t         MBMS_Suspension_Notification_List;
+  }M2AP_MBSFN_Area_Configuration_t;
+
+
+/*
+ * MBMS Scheduling Information
+ */
+ uint8_t m2ap_message[]    = {0x00, 0x02, 0x00, 0x3a, 0x00, 0x00, 0x02, 0x00, 0x19, 0x00, 0x01, 0x00, 0x00,
+                            0x0a, 0x00, 0x2e, 0x00, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x12, 0x10, 0x00, 0x0c,
+                            0x00, 0x0d, 0x00, 0x00, 0x3f, 0x13, 0x00, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00,
+                            0x01, 0x08, 0x00, 0x16, 0x00, 0x07, 0x00, 0x00, 0x17, 0x00, 0x02, 0x00, 0x40,
+                            0x00, 0x18, 0x00, 0x01, 0x80, 0x00, 0x1d, 0x00, 0x01, 0x01};
+
+
+int MCE_send_MBMS_SCHEDULING_INFORMATION(instance_t instance, /*uint32_t assoc_id,*/m2ap_mbms_scheduling_information_t * m2ap_mbms_scheduling_information){
+   
+  //module_id_t enb_mod_idP=0;
+  //module_id_t du_mod_idP=0;
+
+  M2AP_M2AP_PDU_t          pdu; 
+  M2AP_MbmsSchedulingInformation_t       *out;
+  M2AP_MbmsSchedulingInformation_Ies_t   *ie;
+
+  uint8_t *buffer/*,*buffer2*/;
+  uint32_t len/*,len2*/;
+  int	   i=0; 
+  int 	   j=0;
+  int 	   k=0;
+  //int 	   l=0;
+  //int 	   l=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_mbmsSchedulingInformation;
+  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_MbmsSchedulingInformation;
+  out = &pdu.choice.initiatingMessage.value.choice.MbmsSchedulingInformation; 
+
+  /* mandatory */
+  /* c1. MCCH_Update_Time */ //long
+  ie=(M2AP_MbmsSchedulingInformation_Ies_t*)calloc(1,sizeof(M2AP_MbmsSchedulingInformation_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MCCH_Update_Time;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_MbmsSchedulingInformation_Ies__value_PR_MCCH_Update_Time;
+  //ie->value.choice.MCCH_Update_Time =  ; 
+  ie->value.choice.MCCH_Update_Time = m2ap_mbms_scheduling_information->mcch_update_time;
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);  
+
+  /* mandatory */
+  /* c2. MBSFN_Area_Configuration_List */ //long
+  ie=(M2AP_MbmsSchedulingInformation_Ies_t*)calloc(1,sizeof(M2AP_MbmsSchedulingInformation_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MBSFN_Area_Configuration_List;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_MbmsSchedulingInformation_Ies__value_PR_MBSFN_Area_Configuration_List;
+
+  for(i=0; i < m2ap_mbms_scheduling_information->num_mbms_area_config_list; i++){ 
+      M2AP_MBSFN_Area_Configuration_List_t * m2ap_mbsfn_area_configuration_list = (M2AP_MBSFN_Area_Configuration_List_t*)calloc(1,sizeof(M2AP_MBSFN_Area_Configuration_List_t));
+      /*M2AP_MBSFN_Area_Configuration_Item_t*/
+      M2AP_MBSFN_Area_Configuration_Item_t *mbsfn_area_configuration_item_ie;
+      mbsfn_area_configuration_item_ie =(M2AP_MBSFN_Area_Configuration_Item_t*)calloc(1,sizeof(M2AP_MBSFN_Area_Configuration_Item_t)); 
+      mbsfn_area_configuration_item_ie->id = M2AP_ProtocolIE_ID_id_PMCH_Configuration_List;
+      mbsfn_area_configuration_item_ie->criticality = M2AP_Criticality_reject;
+      mbsfn_area_configuration_item_ie->value.present = M2AP_MBSFN_Area_Configuration_Item__value_PR_PMCH_Configuration_List;
+
+      for(j=0; j < m2ap_mbms_scheduling_information->mbms_area_config_list[i].num_pmch_config_list; j++){
+      
+      	M2AP_PMCH_Configuration_ItemIEs_t * pmch_configuration_item_ies = (M2AP_PMCH_Configuration_ItemIEs_t*)calloc(1,sizeof(M2AP_PMCH_Configuration_ItemIEs_t));
+      	pmch_configuration_item_ies->id = M2AP_ProtocolIE_ID_id_PMCH_Configuration_Item;
+      	pmch_configuration_item_ies->criticality = M2AP_Criticality_reject;
+      	pmch_configuration_item_ies->value.present = M2AP_PMCH_Configuration_ItemIEs__value_PR_PMCH_Configuration_Item;
+
+      	M2AP_PMCH_Configuration_Item_t * pmch_configuration_item;/* = (M2AP_PMCH_Configuration_Item_t*)calloc(1,sizeof(M2AP_PMCH_Configuration_Item_t));*/
+      	pmch_configuration_item = &pmch_configuration_item_ies->value.choice.PMCH_Configuration_Item;
+      	{
+            pmch_configuration_item->pmch_Configuration.dataMCS = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].data_mcs;
+            pmch_configuration_item->pmch_Configuration.mchSchedulingPeriod = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mch_scheduling_period;
+	    pmch_configuration_item->pmch_Configuration.allocatedSubframesEnd = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].allocated_sf_end;
+            for(k=0; k < m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].num_mbms_session_list; k++){
+            	MBMSsessionListPerPMCH_Item__Member *member;
+            	member = (MBMSsessionListPerPMCH_Item__Member*)calloc(1,sizeof(MBMSsessionListPerPMCH_Item__Member));
+            	MCC_MNC_TO_PLMNID(
+            			  m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mcc,
+            			  m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mnc,
+            			  m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mnc_length
+            			,&member->tmgi.pLMNidentity);
+
+	  	//INT16_TO_OCTET_STRING(0,&imember->tmgi);
+		char buf[4];
+	        INT32_TO_BUFFER(m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id,buf);
+            	//uint8_t TMGI[5] = {4,3,2,1,0};
+            	OCTET_STRING_fromBuf(&member->tmgi.serviceID,(const char*)&buf[1],3);
+
+            		//LOG_D(M2AP,"%p,%p,%p,%li,%ld,%ld\n",pmch_configuration_item,&pmch_configuration_item->mbms_Session_List.list,member, m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid,sizeof(member->lcid),sizeof(m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid)); 
+		//long kk = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid;
+		//uint64_t kk=(m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid);
+		//memcpy(&member->lcid,&m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid,sizeof(member->lcid));
+	//	member->lcid = 1;
+	//	for( l=2; l < 28;l++)
+	//		LOG_E(M2AP,"%di\n",l);
+	//		if(l ==  m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid){
+        //    	member->lcid++;//m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id;
+	//		break;
+	//	}
+                member->lcid = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid;
+		//member->lcid = (M2AP_LCID_t*)calloc(1,sizeof(M2AP_LCID_t));
+		
+            	ASN_SEQUENCE_ADD(&pmch_configuration_item->mbms_Session_List.list,member);
+            }
+      
+      	}
+      /*M2AP_MBSFN_Subframe_ConfigurationList_t*/
+      // M2AP_MBSFN_Area_Configuration_Item_t *mbsfn_area_configuration_item_ie2;
+      //(mbsfn_area_configuration_item_ie+1) =(M2AP_MBSFN_Area_Configuration_Item_t*)calloc(1,sizeof(M2AP_MBSFN_Area_Configuration_Item_t)); 
+
+      	ASN_SEQUENCE_ADD(&mbsfn_area_configuration_item_ie->value.choice.PMCH_Configuration_List.list,pmch_configuration_item_ies);
+
+      }
+
+      ASN_SEQUENCE_ADD(m2ap_mbsfn_area_configuration_list,mbsfn_area_configuration_item_ie);
+
+      /*M2AP_MBSFN_Area_Configuration_Item_t*/
+      M2AP_MBSFN_Area_Configuration_Item_t *mbsfn_area_configuration_item_ie_1;
+      mbsfn_area_configuration_item_ie_1 =(M2AP_MBSFN_Area_Configuration_Item_t*)calloc(1,sizeof(M2AP_MBSFN_Area_Configuration_Item_t)); 
+      (mbsfn_area_configuration_item_ie_1)->id = M2AP_ProtocolIE_ID_id_MBSFN_Subframe_Configuration_List;
+      (mbsfn_area_configuration_item_ie_1)->criticality = M2AP_Criticality_reject;
+      (mbsfn_area_configuration_item_ie_1)->value.present = M2AP_MBSFN_Area_Configuration_Item__value_PR_MBSFN_Subframe_ConfigurationList;
+
+      for(j=0; j < m2ap_mbms_scheduling_information->mbms_area_config_list[i].num_mbms_sf_config_list; j++){
+	   M2AP_MBSFN_Subframe_ConfigurationItem_t * mbsfn_subframe_configuration_item_ies = (M2AP_MBSFN_Subframe_ConfigurationItem_t*)calloc(1,sizeof(M2AP_MBSFN_Subframe_ConfigurationItem_t));
+	   mbsfn_subframe_configuration_item_ies->id = M2AP_ProtocolIE_ID_id_MBSFN_Subframe_Configuration_Item;
+	   mbsfn_subframe_configuration_item_ies->criticality = M2AP_Criticality_reject;
+	   mbsfn_subframe_configuration_item_ies->value.present = M2AP_MBSFN_Subframe_ConfigurationItem__value_PR_MBSFN_Subframe_Configuration;
+
+	   M2AP_MBSFN_Subframe_Configuration_t * mbsfn_subframe_configuration; /* = (M2AP_MBSFN_Subframe_Configuration_t*)calloc(1,sizeof(M2AP_MBSFN_Subframe_Configuration_t));*/
+	   mbsfn_subframe_configuration = &mbsfn_subframe_configuration_item_ies->value.choice.MBSFN_Subframe_Configuration;
+	   {
+		   mbsfn_subframe_configuration->radioframeAllocationPeriod = m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_period;
+		   mbsfn_subframe_configuration->radioframeAllocationOffset = m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_offset;
+		   if(m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].is_four_sf){
+			   mbsfn_subframe_configuration->subframeAllocation.present = M2AP_MBSFN_Subframe_Configuration__subframeAllocation_PR_fourFrames;
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf = MALLOC(3);
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation) & 0xFF);
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation>>8) & 0xFF);
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf[0] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation>>16) & 0xFF);
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.size =3;
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.bits_unused = 0;
+
+		   }else{
+			   mbsfn_subframe_configuration->subframeAllocation.present = M2AP_MBSFN_Subframe_Configuration__subframeAllocation_PR_oneFrame;
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf = MALLOC(1);
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.size = 1;
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.bits_unused = 2;
+			   //mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf[0] = 0x38<<2;
+			   mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf[0] = (m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation & 0x3F)<<2;
+		   }
+
+		   ASN_SEQUENCE_ADD(&(mbsfn_area_configuration_item_ie_1)->value.choice.MBSFN_Subframe_ConfigurationList.list,mbsfn_subframe_configuration_item_ies);
+	   }
+       }
+
+       ASN_SEQUENCE_ADD(m2ap_mbsfn_area_configuration_list,mbsfn_area_configuration_item_ie_1);
+
+
+      /*M2AP_MBSFN_Area_Configuration_Item_t*/
+      M2AP_MBSFN_Area_Configuration_Item_t *mbsfn_area_configuration_item_ie_2;
+      mbsfn_area_configuration_item_ie_2 =(M2AP_MBSFN_Area_Configuration_Item_t*)calloc(1,sizeof(M2AP_MBSFN_Area_Configuration_Item_t)); 
+      (mbsfn_area_configuration_item_ie_2)->id = M2AP_ProtocolIE_ID_id_Common_Subframe_Allocation_Period;
+      (mbsfn_area_configuration_item_ie_2)->criticality = M2AP_Criticality_reject;
+      (mbsfn_area_configuration_item_ie_2)->value.present = M2AP_MBSFN_Area_Configuration_Item__value_PR_Common_Subframe_Allocation_Period;
+      (mbsfn_area_configuration_item_ie_2)->value.choice.Common_Subframe_Allocation_Period=m2ap_mbms_scheduling_information->mbms_area_config_list[i].common_sf_allocation_period;
+
+       ASN_SEQUENCE_ADD(m2ap_mbsfn_area_configuration_list,mbsfn_area_configuration_item_ie_2);
+
+
+      /*M2AP_MBSFN_Area_Configuration_Item_t*/
+      M2AP_MBSFN_Area_Configuration_Item_t *mbsfn_area_configuration_item_ie_3;
+      mbsfn_area_configuration_item_ie_3 =(M2AP_MBSFN_Area_Configuration_Item_t*)calloc(1,sizeof(M2AP_MBSFN_Area_Configuration_Item_t)); 
+      (mbsfn_area_configuration_item_ie_3)->id = M2AP_ProtocolIE_ID_id_MBSFN_Area_ID;
+      (mbsfn_area_configuration_item_ie_3)->criticality = M2AP_Criticality_reject;
+      (mbsfn_area_configuration_item_ie_3)->value.present = M2AP_MBSFN_Area_Configuration_Item__value_PR_MBSFN_Area_ID;
+      (mbsfn_area_configuration_item_ie_3)->value.choice.MBSFN_Area_ID = m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_area_id;
+
+      ASN_SEQUENCE_ADD(m2ap_mbsfn_area_configuration_list,mbsfn_area_configuration_item_ie_3);
+
+
+ASN_SET_ADD(&ie->value.choice.MBSFN_Area_Configuration_List,m2ap_mbsfn_area_configuration_list);
+
+/* xer_fprint(stdout,&asn_DEF_M2AP_MBSFN_Area_Configuration_Item,mbsfn_area_configuration_item_ie);
+ xer_fprint(stdout,&asn_DEF_M2AP_MBSFN_Area_Configuration_Item,mbsfn_area_configuration_item_ie_1);
+ xer_fprint(stdout,&asn_DEF_M2AP_MBSFN_Area_Configuration_Item,mbsfn_area_configuration_item_ie_2);
+ xer_fprint(stdout,&asn_DEF_M2AP_MBSFN_Area_Configuration_Item,mbsfn_area_configuration_item_ie_3);
+ xer_fprint(stdout,&asn_DEF_M2AP_MBSFN_Area_Configuration_List, &ie->value.choice.MBSFN_Area_Configuration_List);*/
+
+  }
+
+
+ ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);  
+
+ 
+ 
+  /* encode */
+  if (m2ap_encode_pdu(&pdu,&buffer,&len) < 0){
+	return -1;
+ }
+  m2ap_MCE_itti_send_sctp_data_req(instance,m2ap_mce_data_from_enb->assoc_id,buffer,len,0);
+  return 0;
+                        
+}
+
+int MCE_handle_MBMS_SCHEDULING_INFORMATION_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu){
+
+  LOG_D(M2AP, "MCE_handle_MBMS_SCHEDULING_INFORMATION_RESPONSE\n");
+
+   AssertFatal(pdu->present == M2AP_M2AP_PDU_PR_successfulOutcome,
+	       "pdu->present != M2AP_M2AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M2AP_ProcedureCode_id_mbmsSchedulingInformation,
+	       "pdu->choice.successfulOutcome->procedureCode != M2AP_ProcedureCode_id_mbmsSchedulingInformation\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M2AP_Criticality_reject,
+	       "pdu->choice.successfulOutcome->criticality != M2AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M2AP_SuccessfulOutcome__value_PR_MbmsSchedulingInformationResponse,
+	       "pdu->choice.successfulOutcome->value.present != M2AP_SuccessfulOutcome__value_PR_MbmsSchedulingInformationResponse\n");
+
+
+  //M2AP_MbmsSchedulingInformationResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.MbmsSchedulingInformationResponse;
+  //M2AP_MbmsSchedulingInformationResponse_Ies_t  *ie;
+  //int MCE_MBMS_M2AP_ID=-1;
+  //int ENB_MBMS_M2AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE,M2AP_MBMS_SCHEDULING_INFORMATION_RESP); //TODO
+
+//  LOG_D(M2AP, "M2AP: SessionStop-Resp: protocolIEs.list.count %d\n",
+//         in->protocolIEs.list.count);
+//  for (int i=0;i < in->protocolIEs.list.count; i++) {
+//     ie = in->protocolIEs.list.array[i];
+//     //switch (ie->id) {
+//     //case M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID:
+//     //  AssertFatal(ie->criticality == M2AP_Criticality_reject,
+//     //              "ie->criticality != M2AP_Criticality_reject\n");
+//     //  AssertFatal(ie->value.present == M2AP_sessionStopIEs__value_PR_MCE_MBMS_M2AP_ID,
+//     //              "ie->value.present != M2AP_sessionStopIEs__value_PR_MCE_MBMS_M2AP_ID\n");
+//     //  TransactionId=ie->value.choice.MCE_MBMS_M2AP_ID;
+//     //  LOG_D(M2AP, "M2AP: SessionStop-Resp: MCE_MBMS_M2AP_ID %d\n",
+//     //        MCE_MBMS_M2AP_ID);
+//     //  break;
+//     // case M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID:
+//     //  AssertFatal(ie->criticality == M2AP_Criticality_reject,
+//     //              "ie->criticality != M2AP_Criticality_reject\n");
+//     //  AssertFatal(ie->value.present == M2AP_sessionStopIEs__value_PR_ENB_MBMS_M2AP_ID,
+//     //              "ie->value.present != M2AP_sessionStopIEs__value_PR_ENB_MBMS_M2AP_ID\n");
+//     //  TransactionId=ie->value.choice.ENB_MBMS_M2AP_ID;
+//     //  LOG_D(M2AP, "M2AP: SessionStop-Resp: ENB_MBMS_M2AP_ID %d\n",
+//     //        ENB_MBMS_M2AP_ID);
+//     //  break;
+//     //}
+//  }
+//
+//  M2AP_SESSION_STOP_RESP(msg_p).
+//  MSC_LOG_RX_MESSAGE(
+//    MSC_M2AP_MCE,
+//    MSC_M2AP_ENB,
+//    0,
+//    0,
+//    MSC_AS_TIME_FMT" MCE_handle_M2_SCHEDULING_INFORMATION_RESPONSE successfulOutcome assoc_id %d",
+//    0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+//    assoc_id);
+//
+//   LOG_D(M2AP, "Sending M2AP_SCHEDULING_INFO_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n",
+//         assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id));
+//   itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p);
+
+    itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), msg_g);
+//
+   return 0;
+                       
+}
+
+/*
+ * Reset
+ */
+
+int MCE_send_RESET(instance_t instance, m2ap_reset_t * m2ap_reset) {
+  AssertFatal(1==0,"Not implemented yet\n");
+  //M2AP_Reset_t     Reset;
+                        
+}
+
+
+int MCE_handle_RESET_ACKKNOWLEDGE(instance_t instance,
+                                  uint32_t assoc_id,
+                                  uint32_t stream,
+                                  M2AP_M2AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+int MCE_handle_RESET(instance_t instance,
+                     uint32_t assoc_id,
+                     uint32_t stream,
+                     M2AP_M2AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+int MCE_send_RESET_ACKNOWLEDGE(instance_t instance, M2AP_ResetAcknowledge_t *ResetAcknowledge) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+/*
+ *    M2 Setup
+ */
+int MCE_handle_M2_SETUP_REQUEST(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M2AP_M2AP_PDU_t *pdu)
+{
+  LOG_D(M2AP, "MCE_handle_M2_SETUP_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  M2AP_M2SetupRequest_t              *container;
+  M2AP_M2SetupRequest_Ies_t           *ie;
+  int i = 0/*,j=0*/;
+  int num_mbms_available=0;
+
+  DevAssert(pdu != NULL);
+
+  container = &pdu->choice.initiatingMessage.value.choice.M2SetupRequest;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received m2 setup request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p = itti_alloc_new_message(TASK_MCE_APP, M2AP_SETUP_REQ); 
+  
+  /* assoc_id */
+  M2AP_SETUP_REQ(message_p).assoc_id = assoc_id;
+
+ /* GlobalENB_id */
+ // this function exits if the ie is mandatory
+  M2AP_FIND_PROTOCOLIE_BY_ID(M2AP_M2SetupRequest_Ies_t, ie, container,
+                             M2AP_ProtocolIE_ID_id_GlobalENB_ID, true);
+  //asn_INTEGER2ulong(&ie->value.choice.GlobalENB_ID.eNB_ID, &M2AP_SETUP_REQ(message_p).GlobalENB_ID);
+  if(ie!=NULL){
+  if(ie->value.choice.GlobalENB_ID.eNB_ID.present == M2AP_ENB_ID_PR_macro_eNB_ID){
+  }else if(ie->value.choice.GlobalENB_ID.eNB_ID.present == M2AP_ENB_ID_PR_short_Macro_eNB_ID){
+  }else if(ie->value.choice.GlobalENB_ID.eNB_ID.present == M2AP_ENB_ID_PR_long_Macro_eNB_ID){
+  }
+  }
+
+  LOG_D(M2AP, "M2AP_SETUP_REQ(message_p).GlobalENB_ID %lu \n", M2AP_SETUP_REQ(message_p).GlobalENB_ID);
+
+  /* ENB_name */
+  M2AP_FIND_PROTOCOLIE_BY_ID(M2AP_M2SetupRequest_Ies_t, ie, container,
+                              M2AP_ProtocolIE_ID_id_ENBname, false);
+  if(ie!=NULL){
+	  M2AP_SETUP_REQ(message_p).ENBname = calloc(ie->value.choice.ENBname.size + 1, sizeof(char));
+	  memcpy(M2AP_SETUP_REQ(message_p).ENBname, ie->value.choice.ENBname.buf,
+		 ie->value.choice.ENBname.size);
+
+	  /* Convert the mme name to a printable string */
+	  M2AP_SETUP_REQ(message_p).ENBname[ie->value.choice.ENBname.size] = '\0';
+	  LOG_D(M2AP, "M2AP_SETUP_REQ(message_p).gNB_DU_name %s \n", M2AP_SETUP_REQ(message_p).ENBname);
+  }
+   /* ENB_MBMS_Configuration_data_List */
+
+
+  M2AP_FIND_PROTOCOLIE_BY_ID(M2AP_M2SetupRequest_Ies_t, ie, container,
+                              M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_List, true);
+
+  if(ie!=NULL){
+	  M2AP_SETUP_REQ(message_p).num_mbms_available = ie->value.choice.ENB_MBMS_Configuration_data_List.list.count;
+	  LOG_D(M2AP, "M2AP_SETUP_REQ(message_p).num_mbms_available %d \n",
+		M2AP_SETUP_REQ(message_p).num_mbms_available);
+	  num_mbms_available = M2AP_SETUP_REQ(message_p).num_mbms_available;
+	  for (i=0; i<num_mbms_available; i++) {
+		 M2AP_ENB_MBMS_Configuration_data_Item_t *mbms_configuration_item_p;
+		 mbms_configuration_item_p = &(((M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *)ie->value.choice.ENB_MBMS_Configuration_data_List.list.array[i])->value.choice.ENB_MBMS_Configuration_data_Item);
+	    /* eCGI */
+	       //mbms_configuration_item_p->eCGI ... (M2AP_ECGI_t)
+
+	    OCTET_STRING_TO_INT16(&(mbms_configuration_item_p->eCGI.pLMN_Identity),M2AP_SETUP_REQ(message_p).plmn_identity[i]);
+	    //OCTET_STRING_TO_INT16(&(mbms_configuration_item_p->eCGI.eUTRANcellIdentifier),M2AP_SETUP_REQ(message_p).eutran_cell_identifier[i]);
+	    /* mbsfnSynchronisationArea */
+	       //mbms_configuration_item_p->mbsfnSynchronisationArea ... (M2AP_MBSFN_SynchronisationArea_ID_t)
+
+	    M2AP_SETUP_REQ(message_p).mbsfn_synchronization_area[i]=mbms_configuration_item_p->mbsfnSynchronisationArea;
+	    /* mbmsServiceAreaList */
+	       //mbms_configuration_item_p->mbmsServiceAreaList ... (M2AP_MBMS_Service_Area_ID_List_t)
+	  }
+  }
+    
+//    /* tac */
+//    OCTET_STRING_TO_INT16(&(served_celles_item_p->served_Cell_Information.fiveGS_TAC), M2AP_SETUP_REQ(message_p).tac[i]);
+//    LOG_D(M2AP, "M2AP_SETUP_REQ(message_p).tac[%d] %d \n",
+//          i, M2AP_SETUP_REQ(message_p).tac[i]);
+//
+//    /* - nRCGI */
+//    TBCD_TO_MCC_MNC(&(served_celles_item_p->served_Cell_Information.nRCGI.pLMN_Identity), M2AP_SETUP_REQ(message_p).mcc[i],
+//                    M2AP_SETUP_REQ(message_p).mnc[i],
+//                    M2AP_SETUP_REQ(message_p).mnc_digit_length[i]);
+//    
+//    
+//    // NR cellID
+//    BIT_STRING_TO_NR_CELL_IDENTITY(&served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity,
+//				   M2AP_SETUP_REQ(message_p).nr_cellid[i]);
+//    LOG_D(M2AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
+//          M2AP_SETUP_REQ(message_p).mcc[i],
+//          M2AP_SETUP_REQ(message_p).mnc[i],
+//          (long long unsigned int)M2AP_SETUP_REQ(message_p).nr_cellid[i]);
+//    LOG_D(M2AP, "nr_cellId : %x %x %x %x %x\n",
+//          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[0],
+//          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[1],
+//          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[2],
+//          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[3],
+//          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[4]);
+//    /* - nRPCI */
+//    M2AP_SETUP_REQ(message_p).nr_pci[i] = served_celles_item_p->served_Cell_Information.nRPCI;
+//    LOG_D(M2AP, "M2AP_SETUP_REQ(message_p).nr_pci[%d] %d \n",
+//          i, M2AP_SETUP_REQ(message_p).nr_pci[i]);
+//  
+//    // System Information
+//    /* mib */
+//    M2AP_SETUP_REQ(message_p).mib[i] = calloc(served_celles_item_p->gNB_DU_System_Information->mIB_message.size + 1, sizeof(char));
+//    memcpy(M2AP_SETUP_REQ(message_p).mib[i], served_celles_item_p->gNB_DU_System_Information->mIB_message.buf,
+//           served_celles_item_p->gNB_DU_System_Information->mIB_message.size);
+//    /* Convert the mme name to a printable string */
+//    M2AP_SETUP_REQ(message_p).mib[i][served_celles_item_p->gNB_DU_System_Information->mIB_message.size] = '\0';
+//    M2AP_SETUP_REQ(message_p).mib_length[i] = served_celles_item_p->gNB_DU_System_Information->mIB_message.size;
+//    LOG_D(M2AP, "M2AP_SETUP_REQ(message_p).mib[%d] %s , len = %d \n",
+//          i, M2AP_SETUP_REQ(message_p).mib[i], M2AP_SETUP_REQ(message_p).mib_length[i]);
+//
+//    /* sib1 */
+//    M2AP_SETUP_REQ(message_p).sib1[i] = calloc(served_celles_item_p->gNB_DU_System_Information->sIB1_message.size + 1, sizeof(char));
+//    memcpy(M2AP_SETUP_REQ(message_p).sib1[i], served_celles_item_p->gNB_DU_System_Information->sIB1_message.buf,
+//           served_celles_item_p->gNB_DU_System_Information->sIB1_message.size);
+//    /* Convert the mme name to a printable string */
+//    M2AP_SETUP_REQ(message_p).sib1[i][served_celles_item_p->gNB_DU_System_Information->sIB1_message.size] = '\0';
+//    M2AP_SETUP_REQ(message_p).sib1_length[i] = served_celles_item_p->gNB_DU_System_Information->sIB1_message.size;
+//    LOG_D(M2AP, "M2AP_SETUP_REQ(message_p).sib1[%d] %s , len = %d \n",
+//          i, M2AP_SETUP_REQ(message_p).sib1[i], M2AP_SETUP_REQ(message_p).sib1_length[i]);
+//  }
+
+
+  //printf("m2ap_mce_data_from_enb->assoc_id %d %d\n",m2ap_mce_data_from_enb->assoc_id,assoc_id);
+
+  *m2ap_mce_data_from_enb = M2AP_SETUP_REQ(message_p);
+  //printf("m2ap_mce_data_from_enb->assoc_id %d %d\n",m2ap_mce_data_from_enb->assoc_id,assoc_id);
+
+//  MSC_LOG_TX_MESSAGE(
+//  MSC_M2AP_MCE,
+//  MSC_RRC_ENB,
+//  0,
+//  0,
+//  MSC_AS_TIME_FMT" MCE_handle_M2_SETUP_REQUEST",
+//  0,0//MSC_AS_TIME_ARGS(ctxt_pP),
+//  );
+//
+  if (num_mbms_available > 0) {
+    itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+  } else {
+       //MCE_send_M2_SETUP_FAILURE(instance);
+       return -1;
+  }
+//  return 0;
+    //TEST POINT MCE -> eNB
+//    if(1){
+//	printf("instance %d\n",instance);
+//	//MCE_send_M2_SETUP_RESPONSE(instance,assoc_id,m2ap_mce_data_from_enb->assoc_id);
+//	//MCE_send_MBMS_SESSION_START_REQUEST(instance,assoc_id);
+//	//MCE_send_MBMS_SESSION_STOP_REQUEST(instance,assoc_id);
+//	//MCE_send_MBMS_SCHEDULING_INFORMATION(instance,assoc_id,NULL); //TODO
+//    }
+//    else 
+//	MCE_send_M2_SETUP_FAILURE(instance,assoc_id);
+
+    return 0;
+}
+
+int MCE_send_M2_SETUP_RESPONSE(instance_t instance, /*uint32_t assoc_id,*/
+                               m2ap_setup_resp_t *m2ap_setup_resp) {
+  
+  //module_id_t mce_mod_idP;
+  //module_id_t enb_mod_idP;
+
+  // This should be fixed
+  //enb_mod_idP = (module_id_t)0;
+  //mce_mod_idP  = (module_id_t)0;
+
+  M2AP_M2AP_PDU_t           pdu;
+  M2AP_M2SetupResponse_t    *out;
+  M2AP_M2SetupResponse_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       i = 0;
+  //int       j = 0;
+
+  AssertFatal(m2ap_setup_resp!=NULL,"m2ap_setup_resp = NULL\n");
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M2AP_SuccessfulOutcome_t *)calloc(1, sizeof(M2AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.successfulOutcome.criticality   = M2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_M2SetupResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.M2SetupResponse;
+  
+  /* mandatory */
+  /* c1. GlobalMCE ID (integer value)*/
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_GlobalMCE_ID;
+  ie->criticality               = M2AP_Criticality_reject; //?
+  ie->value.present             = M2AP_M2SetupResponse_Ies__value_PR_GlobalMCE_ID;
+  //ie->value.choice.TransactionID = M2AP_get_next_transaction_identifier(enb_mod_idP, cu_mod_idP);
+  MCC_MNC_TO_PLMNID(m2ap_setup_resp->mcc, m2ap_setup_resp->mnc, m2ap_setup_resp->mnc_digit_length,
+  		&ie->value.choice.GlobalMCE_ID.pLMN_Identity);
+
+  ie->value.choice.GlobalMCE_ID.mCE_ID.buf =calloc(2, sizeof(uint8_t));
+  ie->value.choice.GlobalMCE_ID.mCE_ID.buf[0] = (m2ap_setup_resp->MCE_id) >> 8;
+  ie->value.choice.GlobalMCE_ID.mCE_ID.buf[1] = ((m2ap_setup_resp->MCE_id) & 0x0ff); 
+  ie->value.choice.GlobalMCE_ID.mCE_ID.size=2;
+  //ie->value.choice.GlobalMCE_ID.mCE_ID.bits_unused=0;
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+ 
+  /* optional */
+  /* c2. MCEname */
+  if (m2ap_setup_resp->MCE_name != NULL) {
+    ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+    ie->id                        = M2AP_ProtocolIE_ID_id_MCEname;
+    ie->criticality               = M2AP_Criticality_ignore;
+    ie->value.present             = M2AP_M2SetupResponse_Ies__value_PR_MCEname;
+    OCTET_STRING_fromBuf(&ie->value.choice.MCEname, m2ap_setup_resp->MCE_name,
+                         strlen(m2ap_setup_resp->MCE_name));
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */
+  /* c3. cells to be Activated list */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MCCHrelatedBCCH_ConfigPerMBSFNArea;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_M2SetupResponse_Ies__value_PR_MCCHrelatedBCCH_ConfigPerMBSFNArea;
+
+  for( i=0; i < m2ap_setup_resp->num_mcch_config_per_mbsfn; i++) 
+  {
+
+	  M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs_t * mcch_related_bcch_config_per_mbsfn_area_item_ies;
+	  mcch_related_bcch_config_per_mbsfn_area_item_ies = (M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs_t*)calloc(1,sizeof(M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs_t));
+	  mcch_related_bcch_config_per_mbsfn_area_item_ies->id=M2AP_ProtocolIE_ID_id_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item;
+	  mcch_related_bcch_config_per_mbsfn_area_item_ies->criticality = M2AP_Criticality_ignore;
+	  mcch_related_bcch_config_per_mbsfn_area_item_ies->value.present=M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs__value_PR_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item;
+
+	  
+	  M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item_t * config_per_mbsfn_area_item;
+	  config_per_mbsfn_area_item = &mcch_related_bcch_config_per_mbsfn_area_item_ies->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea_Item;
+	  {
+		config_per_mbsfn_area_item->pdcchLength=m2ap_setup_resp->mcch_config_per_mbsfn[i].pdcch_length;//M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item__pdcchLength_s1;
+		config_per_mbsfn_area_item->offset=m2ap_setup_resp->mcch_config_per_mbsfn[i].offset;//0;
+		config_per_mbsfn_area_item->repetitionPeriod=m2ap_setup_resp->mcch_config_per_mbsfn[i].repetition_period;//M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item__repetitionPeriod_rf32;
+		config_per_mbsfn_area_item->modificationPeriod=m2ap_setup_resp->mcch_config_per_mbsfn[i].modification_period;//M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item__modificationPeriod_rf512;
+		config_per_mbsfn_area_item->subframeAllocationInfo.buf = MALLOC(1); 
+		config_per_mbsfn_area_item->subframeAllocationInfo.size=1;
+		/*char * t;
+		int bits=7;
+		for( t = m2ap_setup_resp->mcch_config_per_mbsfn[i].subframe_allocation_info; *t != '\0'; t++,bits--){
+			if(*t=='1'){
+				config_per_mbsfn_area_item->subframeAllocationInfo.buf[0] |= (uint8_t)(0x1<<bits);
+			}
+                }*/
+		config_per_mbsfn_area_item->subframeAllocationInfo.buf[0] = (uint8_t)((m2ap_setup_resp->mcch_config_per_mbsfn[i].subframe_allocation_info & 0x3F)<<2);
+
+		//config_per_mbsfn_area_item->subframeAllocationInfo.buf[0]=0x1<<7;
+		config_per_mbsfn_area_item->subframeAllocationInfo.bits_unused=2;
+		
+		//memset(&config_per_mbsfn_area_item->subframeAllocationInfo,0,sizeof(BIT_STRING_t));
+		
+		config_per_mbsfn_area_item->modulationAndCodingScheme = m2ap_setup_resp->mcch_config_per_mbsfn[i].mcs;//M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item__modulationAndCodingScheme_n2;
+		ASN_SEQUENCE_ADD(&ie->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea.list,mcch_related_bcch_config_per_mbsfn_area_item_ies);
+	  }
+
+  }
+ 
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  
+
+  /* encode */
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 response\n");
+    return -1;
+  }
+
+  m2ap_MCE_itti_send_sctp_data_req(instance,m2ap_mce_data_from_enb->assoc_id,buffer,len,0);
+
+  return 0;
+}
+
+int MCE_send_M2_SETUP_FAILURE(instance_t instance,m2ap_setup_failure_t* m2ap_setup_failure) {
+  
+ // module_id_t enb_mod_idP;
+  //module_id_t mce_mod_idP;
+
+  // This should be fixed
+  //enb_mod_idP = (module_id_t)0;
+  //mce_mod_idP  = (module_id_t)0;
+
+  M2AP_M2AP_PDU_t           pdu;
+  M2AP_M2SetupFailure_t    *out;
+  M2AP_M2SetupFailure_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+  //pdu.choice.unsuccessfulOutcome = (M2AP_UnsuccessfulOutcome_t *)calloc(1, sizeof(M2AP_UnsuccessfulOutcome_t));
+  pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.unsuccessfulOutcome.criticality   = M2AP_Criticality_reject;
+  pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+
+  /* mandatory */
+  /* c1. Transaction ID (integer value)*/
+ // ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+ // ie->id                        = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+ // ie->criticality               = M2AP_Criticality_reject;
+ // ie->value.present             = M2AP_M2SetupFailure_Ies__value_PR_GlobalENB_ID;
+ // ie->value.choice.GlobalENB_ID = M2AP_get_next_transaction_identifier(enb_mod_idP, mce_mod_idP);
+ // ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. Cause */
+  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_Cause;
+  ie->criticality               = M2AP_Criticality_ignore;
+  ie->value.present             = M2AP_M2SetupFailure_Ies__value_PR_Cause;
+  ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+  ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_unspecified;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional */
+  /* c3. TimeToWait */
+  if (0) {
+    ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+    ie->id                        = M2AP_ProtocolIE_ID_id_TimeToWait;
+    ie->criticality               = M2AP_Criticality_ignore;
+    ie->value.present             = M2AP_M2SetupFailure_Ies__value_PR_TimeToWait;
+    ie->value.choice.TimeToWait = M2AP_TimeToWait_v10s;
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* optional */
+  /* c4. CriticalityDiagnostics*/
+  if (0) {
+    ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+    ie->id                        = M2AP_ProtocolIE_ID_id_CriticalityDiagnostics;
+    ie->criticality               = M2AP_Criticality_ignore;
+    ie->value.present             = M2AP_M2SetupFailure_Ies__value_PR_CriticalityDiagnostics;
+    ie->value.choice.CriticalityDiagnostics.procedureCode = (M2AP_ProcedureCode_t *)calloc(1, sizeof(M2AP_ProcedureCode_t));
+    *ie->value.choice.CriticalityDiagnostics.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+    ie->value.choice.CriticalityDiagnostics.triggeringMessage = (M2AP_TriggeringMessage_t *)calloc(1, sizeof(M2AP_TriggeringMessage_t));
+    *ie->value.choice.CriticalityDiagnostics.triggeringMessage = M2AP_TriggeringMessage_initiating_message;
+    ie->value.choice.CriticalityDiagnostics.procedureCriticality = (M2AP_Criticality_t *)calloc(1, sizeof(M2AP_Criticality_t));
+    *ie->value.choice.CriticalityDiagnostics.procedureCriticality = M2AP_Criticality_reject;
+    //ie->value.choice.CriticalityDiagnostics.transactionID = (M2AP_TransactionID_t *)calloc(1, sizeof(M2AP_TransactionID_t));
+    //*ie->value.choice.CriticalityDiagnostics.transactionID = 0;
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* encode */
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 setup request\n");
+    return -1;
+  }
+
+  //mce_m2ap_itti_send_sctp_data_req(instance, m2ap_mce_data_from_enb->assoc_id, buffer, len, 0);
+  m2ap_MCE_itti_send_sctp_data_req(instance,m2ap_mce_data_from_enb->assoc_id,buffer,len,0);
+
+  return 0;
+}
+
+/*
+ * MCE Configuration Update
+ */
+
+int MCE_send_MCE_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_idP){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+  
+  M2AP_M2AP_PDU_t          pdu;
+  M2AP_MCEConfigurationUpdate_t    *out;
+  M2AP_MCEConfigurationUpdate_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+  //int       j = 0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_mCEConfigurationUpdate;
+  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_MCEConfigurationUpdate;
+  out = &pdu.choice.initiatingMessage.value.choice.MCEConfigurationUpdate;
+ 
+  /* mandatory */
+  /* c1. Transaction ID (integer value)*/
+  ie = (M2AP_MCEConfigurationUpdate_Ies_t *)calloc(1, sizeof(M2AP_MCEConfigurationUpdate_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_GlobalMCE_ID;
+  ie->criticality               = M2AP_Criticality_reject; //?
+  ie->value.present             = M2AP_MCEConfigurationUpdate_Ies__value_PR_GlobalMCE_ID;
+  //ie->value.choice.TransactionID = M2AP_get_next_transaction_identifier(enb_mod_idP, cu_mod_idP);
+  MCC_MNC_TO_PLMNID(0,0,3/*instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,*/
+  ,&ie->value.choice.GlobalMCE_ID.pLMN_Identity);
+
+  ie->value.choice.GlobalMCE_ID.mCE_ID.buf =calloc(2, sizeof(uint8_t));
+  ie->value.choice.GlobalMCE_ID.mCE_ID.size=2;
+  //ie->value.choice.GlobalMCE_ID.mCE_ID.bits_unused=6;
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+ 
+  /* optional */
+  /* c2. MCEname */
+  //if (m2ap_setup_resp->MCEname != NULL) {
+  //  ie = (M2AP_MCEConfigurationUpdate_Ies_t *)calloc(1, sizeof(M2AP_MCEConfigurationUpdate_Ies_t));
+  //  ie->id                        = M2AP_ProtocolIE_ID_id_MCEname;
+  //  ie->criticality               = M2AP_Criticality_ignore;
+  //  ie->value.present             = M2AP_MCEConfigurationUpdate_Ies__value_PR_MCEname;
+  //  OCTET_STRING_fromBuf(&ie->value.choice.MCEname, m2ap_setup_resp->MCEname,
+  //                       strlen(m2ap_setup_resp->MCEname));
+  //  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  //}
+
+  /* mandatory */
+  /* c3. cells to be Activated list */
+  ie = (M2AP_MCEConfigurationUpdate_Ies_t *)calloc(1, sizeof(M2AP_MCEConfigurationUpdate_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MCCHrelatedBCCH_ConfigPerMBSFNArea;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_MCEConfigurationUpdate_Ies__value_PR_MCCHrelatedBCCH_ConfigPerMBSFNArea;
+
+  M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs_t * mcch_related_bcch_config_per_mbsfn_area_item_ies;
+  mcch_related_bcch_config_per_mbsfn_area_item_ies = (M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs_t*)calloc(1,sizeof(M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs_t));
+  mcch_related_bcch_config_per_mbsfn_area_item_ies->id=M2AP_ProtocolIE_ID_id_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item;
+  mcch_related_bcch_config_per_mbsfn_area_item_ies->criticality = M2AP_Criticality_ignore;
+  mcch_related_bcch_config_per_mbsfn_area_item_ies->value.present=M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs__value_PR_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item;
+
+  M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item_t * config_per_mbsfn_area_item;
+  config_per_mbsfn_area_item = &mcch_related_bcch_config_per_mbsfn_area_item_ies->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea_Item;
+  {
+	config_per_mbsfn_area_item->pdcchLength=M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item__pdcchLength_s1;
+	config_per_mbsfn_area_item->offset=0;
+	config_per_mbsfn_area_item->repetitionPeriod=M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item__repetitionPeriod_rf32;
+	config_per_mbsfn_area_item->modificationPeriod=M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item__modificationPeriod_rf512;
+  	config_per_mbsfn_area_item->subframeAllocationInfo.buf = MALLOC(1); 
+  	config_per_mbsfn_area_item->subframeAllocationInfo.size=1;
+  	//config_per_mbsfn_area_item->subframeAllocationInfo.buf[0]=0x1<<7;
+  	config_per_mbsfn_area_item->subframeAllocationInfo.bits_unused=2;
+	
+	//memset(&config_per_mbsfn_area_item->subframeAllocationInfo,0,sizeof(BIT_STRING_t));
+	
+        config_per_mbsfn_area_item->modulationAndCodingScheme = M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item__modulationAndCodingScheme_n2;
+	ASN_SEQUENCE_ADD(&ie->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea.list,mcch_related_bcch_config_per_mbsfn_area_item_ies);
+  }
+  
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  
+
+  /* encode */
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 response\n");
+    return -1;
+  }
+
+  //MCE_m2ap_itti_send_sctp_data_req(instance, m2ap_mce_data_from_du->assoc_id, buffer, len, 0);
+ //printf(",m2ap_mce_data_from_enb->assoc_id %d\n",m2ap_mce_data_from_enb->assoc_id);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance,m2ap_mce_data_from_enb->assoc_id,buffer,len,0);
+
+
+
+  
+}
+
+
+int MCE_handle_MCE_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+    LOG_D(M2AP, "MCE_handle_MCE_CONFIGURATION_UPDATE_FAILURE\n");
+
+  M2AP_MCEConfigurationUpdateFailure_t    *in = &pdu->choice.unsuccessfulOutcome.value.choice.MCEConfigurationUpdateFailure;
+
+
+   //M2AP_MCEConfigurationUpdateFailure_Ies_t *ie;
+
+
+  MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_MCE, M2AP_MCE_CONFIGURATION_UPDATE_FAILURE);
+
+   LOG_D(M2AP, "M2AP: MCEConfigurationUpdate-Failure: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  // for (int i=0;i < in->protocolIEs.list.count; i++) {
+  //   ie = in->protocolIEs.list.array[i];
+  //  // switch (ie->id) {
+  //  // case M2AP_ProtocolIE_ID_id_TimeToWait:
+  //  //   AssertFatal(ie->criticality == M2AP_Criticality_ignore,
+  //  //             "ie->criticality != M2AP_Criticality_ignore\n");
+  //  //   AssertFatal(ie->value.present == M2AP_M2SetupFailure_Ies__value_PR_TimeToWait,
+  //  //             "ie->value.present != M2AP_M2SetupFailure_Ies__value_PR_TimeToWait\n");
+  //  //   LOG_D(M2AP, "M2AP: M2Setup-Failure: TimeToWait %d\n");/*,
+  //  //         GlobalMCE_ID);*/
+  //  //   break;
+  //  // }
+  // }
+   //AssertFatal(GlobalMCE_ID!=-1,"GlobalMCE_ID was not sent\n");
+   //AssertFatal(num_cells_to_activate>0,"No cells activated\n");
+   //M2AP_SETUP_RESP (msg_p).num_cells_to_activate = num_cells_to_activate;
+
+   //for (int i=0;i<num_cells_to_activate;i++)
+   //  AssertFatal(M2AP_SETUP_RESP (msg_p).num_SI[i] > 0, "System Information %d is missing",i);
+
+   //MSC_LOG_RX_MESSAGE(
+   // MSC_M2AP_eNB,
+   // MSC_M2AP_CU,
+   // 0,
+   // 0,
+   // MSC_AS_TIME_FMT" eNB_handle_M2_SETUP_RESPONSE successfulOutcome assoc_id %d",
+   // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+   // assoc_id);
+
+   //LOG_D(M2AP, "Sending M2AP_SETUP_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n",
+   //      assoc_id,ENB_MOeNBLE_ID_TO_INSTANCE(assoc_id));
+
+   itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p);
+
+   return 0;
+
+}
+
+
+int MCE_handle_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M2AP, "MCE_handle_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M2AP_MCEConfigurationUpdateAcknowledge_t              *container;
+  //M2AP_MCEConfigurationUpdateAcknowledge_Ies_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.MCEConfigurationUpdate;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_MCE, M2AP_MCE_CONFIGURATION_UPDATE_ACK);
+
+
+  itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+  return 0;
+
+}
+
+
+/*
+ * ENB Configuration Update
+ */
+
+
+int MCE_handle_ENB_CONFIGURATION_UPDATE(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M2AP, "MCE_handle_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M2AP_MCEConfigurationUpdateAcknowledge_t              *container;
+  //M2AP_MCEConfigurationUpdateAcknowledge_Ies_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.MCEConfigurationUpdate;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_MCE, M2AP_MCE_CONFIGURATION_UPDATE_ACK);
+
+
+  itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+   return 0;
+
+}
+
+
+int MCE_send_ENB_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                    m2ap_enb_configuration_update_failure_t * m2ap_enb_configuration_update_failure){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+int MCE_send_ENB_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                    m2ap_enb_configuration_update_ack_t *m2ap_enb_configuration_update_ack){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+/*
+ * Error Indication
+ */
+
+int MCE_handle_ERROR_INDICATION(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+
+
+}
+
+int MCE_send_ERROR_INDICATION(instance_t instance, M2AP_ErrorIndication_t *ErrorIndication) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+
+/*
+ * Session Update Request
+ */
+int MCE_send_MBMS_SESSION_UPDATE_REQUEST(instance_t instance, m2ap_mbms_session_update_req_t * m2ap_mbms_session_update_req){
+  AssertFatal(1==0,"Not implemented yet\n");
+  //M2AP_SessionUpdateRequest_t      SessionUpdateRequest;
+}
+
+
+
+int MCE_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+
+int MCE_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+/*
+ * Service Counting Request
+ */
+int MCE_send_MBMS_SERVICE_COUNTING_REQUEST(instance_t instance, module_id_t du_mod_idP){
+  AssertFatal(1==0,"Not implemented yet\n");
+  //M2AP_MbmsServiceCountingRequest_t        MbmsServiceCountingRequest;
+}
+
+
+
+int MCE_handle_MBMS_SERVICE_COUNTING_RESPONSE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+int MCE_handle_MBMS_SESSION_COUNTING_FAILURE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+/*
+ * Service Counting Results Report
+ */
+
+int MCE_handle_MBMS_SESSION_COUNTING_RESULTS_REPORT(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+/*
+ * Overload Notification
+ */
+int MCE_handle_MBMS_OVERLOAD_NOTIFICATION(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+ 
+}
+
+
+
+
diff --git a/openair2/M2AP/m2ap_MCE_interface_management.h b/openair2/M2AP/m2ap_MCE_interface_management.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b899e9ea275e8646fbf73c6adf9f8ff0ec5c231
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_interface_management.h
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_interface_management.h
+ * \brief m2ap interface management for MCE
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M2AP_MCE_INTERFACE_MANAGEMENT_H_
+#define M2AP_MCE_INTERFACE_MANAGEMENT_H_
+/*
+ * MBMS Session start
+ */
+int MCE_send_MBMS_SESSION_START_REQUEST(instance_t instance/*,
+                                uint32_t assoc_id*/,m2ap_session_start_req_t* m2ap_session_start_req);
+int MCE_handle_MBMS_SESSION_START_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu);
+
+int MCE_handle_MBMS_SESSION_START_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu);
+/*
+ * MBMS Session stop
+ */
+int MCE_send_MBMS_SESSION_STOP_REQUEST(instance_t instance,
+                                m2ap_session_stop_req_t* m2ap_session_stop_req);
+
+int MCE_handle_MBMS_SESSION_STOP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu);
+
+/*
+ * MBMS Scheduling Information
+ */
+int MCE_send_MBMS_SCHEDULING_INFORMATION(instance_t instance,
+                                /*uint32_t assoc_id,*/ m2ap_mbms_scheduling_information_t * m2ap_mbms_scheduling_information );
+
+int MCE_handle_MBMS_SCHEDULING_INFORMATION_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu);
+
+
+
+/*
+ * Reset
+ */
+int MCE_send_RESET(instance_t instance, m2ap_reset_t * m2ap_reset);
+
+int MCE_handle_RESET_ACKKNOWLEDGE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu);
+
+int MCE_handle_RESET(instance_t instance,
+                    uint32_t assoc_id,
+                    uint32_t stream,
+                    M2AP_M2AP_PDU_t *pdu);
+int MCE_send_RESET_ACKNOWLEDGE(instance_t instance, M2AP_ResetAcknowledge_t *ResetAcknowledge);
+
+/*
+ * M2AP Setup
+ */
+int MCE_handle_M2_SETUP_REQUEST(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M2AP_M2AP_PDU_t *pdu);
+
+int MCE_send_M2_SETUP_RESPONSE(instance_t instance,/*uint32_t assoc_id,*/  m2ap_setup_resp_t *m2ap_setup_resp);
+
+int MCE_send_M2_SETUP_FAILURE(instance_t instance, /*uint32_t assoc_id*/ m2ap_setup_failure_t * m2ap_setup_failure);
+
+
+/*
+ * MCE Configuration Update
+ */
+
+int MCE_send_MCE_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_idP);
+
+int MCE_handle_MCE_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu);
+
+int MCE_handle_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu);
+
+/*
+ * ENB Configuration Update
+ */
+
+
+int MCE_handle_ENB_CONFIGURATION_UPDATE(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          M2AP_M2AP_PDU_t *pdu);
+
+int MCE_send_ENB_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                    m2ap_enb_configuration_update_failure_t *m2ap_enb_configuration_update_failure);
+
+int MCE_send_ENB_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                    m2ap_enb_configuration_update_ack_t *m2ap_enb_configuration_update_ack);
+/*
+ * Error Indication
+ */
+int MCE_handle_ERROR_INDICATION(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M2AP_M2AP_PDU_t *pdu);
+int MCE_send_ERROR_INDICATION(instance_t instance, M2AP_ErrorIndication_t *ErrorIndication);
+
+
+/*
+ * Session Update Request
+ */
+int MCE_send_MBMS_SESSION_UPDATE_REQUEST(instance_t instance, m2ap_mbms_session_update_req_t * m2ap_mbms_session_update_req);
+
+int MCE_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu);
+
+int MCE_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu);
+
+/*
+ * Service Counting Request
+ */
+int MCE_send_MBMS_SERVICE_COUNTING_REQUEST(instance_t instance, module_id_t du_mod_idP);
+
+int MCE_handle_MBMS_SERVICE_COUNTING_RESPONSE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu);
+
+int MCE_handle_MBMS_SESSION_COUNTING_FAILURE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu);
+/*
+ * Service Counting Results Report
+ */
+
+int MCE_handle_MBMS_SESSION_COUNTING_RESULTS_REPORT(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu);
+
+/*
+ * Overload Notification
+ */
+int MCE_handle_MBMS_OVERLOAD_NOTIFICATION(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M2AP_M2AP_PDU_t *pdu);
+
+
+
+
+
+#endif /* M2AP_MCE_INTERFACE_MANAGEMENT_H_ */
+
+
+
diff --git a/openair2/M2AP/m2ap_MCE_management_procedures.c b/openair2/M2AP/m2ap_MCE_management_procedures.c
new file mode 100644
index 0000000000000000000000000000000000000000..3934a57c74971b8250d7e8d5db01a2c6f7d28853
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_management_procedures.c
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_management_procedures.c
+ * \brief m2ap tasks for MCE
+ * \author Javier Morgade  <javier.morade@ieee.org>
+ * \date 2018
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "assertions.h"
+#include "conversions.h"
+
+#include "m2ap_common.h"
+#include "m2ap_MCE_defs.h"
+#include "m2ap_MCE.h"
+
+
+#define M2AP_DEBUG_LIST
+#ifdef M2AP_DEBUG_LIST
+#  define M2AP_MCE_LIST_OUT(x, args...) M2AP_DEBUG("[MCE]%*s"x"\n", 4*indent, "", ##args)
+#else
+#  define M2AP_MCE_LIST_OUT(x, args...)
+#endif
+
+static int                  indent = 0;
+
+
+m2ap_MCE_internal_data_t m2ap_MCE_internal_data;
+
+RB_GENERATE(m2ap_mce_map, m2ap_MCE_data_s, entry, m2ap_MCE_compare_assoc_id);
+
+int m2ap_MCE_compare_assoc_id(
+  struct m2ap_MCE_data_s *p1, struct m2ap_MCE_data_s *p2)
+{
+  if (p1->assoc_id == -1) {
+    if (p1->cnx_id < p2->cnx_id) {
+      return -1;
+    }
+
+    if (p1->cnx_id > p2->cnx_id) {
+      return 1;
+    }
+  } else {
+    if (p1->assoc_id < p2->assoc_id) {
+      return -1;
+    }
+
+    if (p1->assoc_id > p2->assoc_id) {
+      return 1;
+    }
+  }
+
+  /* Matching reference */
+  return 0;
+}
+
+uint16_t m2ap_MCE_fetch_add_global_cnx_id(void)
+{
+  return ++m2ap_MCE_internal_data.global_cnx_id;
+}
+
+void m2ap_MCE_prepare_internal_data(void)
+{
+  memset(&m2ap_MCE_internal_data, 0, sizeof(m2ap_MCE_internal_data));
+  STAILQ_INIT(&m2ap_MCE_internal_data.m2ap_MCE_instances_head);
+}
+
+void m2ap_MCE_insert_new_instance(m2ap_MCE_instance_t *new_instance_p)
+{
+  DevAssert(new_instance_p != NULL);
+
+  STAILQ_INSERT_TAIL(&m2ap_MCE_internal_data.m2ap_MCE_instances_head,
+                     new_instance_p, m2ap_MCE_entries);
+}
+
+void dump_mce_tree_m2(m2ap_MCE_data_t *t)
+{
+  if (t == NULL) return;
+  printf("-----------------------\n");
+  printf("MCE id %d %s\n", t->MCE_id, t->MCE_name);
+  printf("state %d\n", t->state);
+  printf("nextstream %d\n", t->nextstream);
+  printf("in_streams %d out_streams %d\n", t->in_streams, t->out_streams);
+  printf("cnx_id %d assoc_id %d\n", t->cnx_id, t->assoc_id);
+  dump_mce_tree_m2(t->entry.rbe_left);
+  dump_mce_tree_m2(t->entry.rbe_right);
+}
+
+void dump_mce_trees_m2(void)
+{
+m2ap_MCE_instance_t *zz;
+STAILQ_FOREACH(zz, &m2ap_MCE_internal_data.m2ap_MCE_instances_head,
+               m2ap_MCE_entries) {
+//printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance);
+dump_mce_tree_m2(zz->m2ap_mce_head.rbh_root);
+//printf("---------------------------------------------\n");
+}
+}
+
+struct m2ap_MCE_data_s *m2ap_get_MCE(m2ap_MCE_instance_t *instance_p,
+				     int32_t assoc_id,
+				     uint16_t cnx_id)
+{
+  struct m2ap_MCE_data_s  temp;
+  struct m2ap_MCE_data_s *found;
+
+//printf("m2ap_get_MCE at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
+//dump_mce_trees_m2();
+
+  memset(&temp, 0, sizeof(struct m2ap_MCE_data_s));
+
+  temp.assoc_id = assoc_id;
+  temp.cnx_id   = cnx_id;
+
+  if (instance_p == NULL) {
+    STAILQ_FOREACH(instance_p, &m2ap_MCE_internal_data.m2ap_MCE_instances_head,
+                   m2ap_MCE_entries) {
+      found = RB_FIND(m2ap_mce_map, &instance_p->m2ap_mce_head, &temp);
+
+      if (found != NULL) {
+        return found;
+      }
+    }
+  } else {
+    return RB_FIND(m2ap_mce_map, &instance_p->m2ap_mce_head, &temp);
+  }
+
+  return NULL;
+}
+
+
+m2ap_MCE_instance_t *m2ap_MCE_get_instance(instance_t instance)
+{
+  m2ap_MCE_instance_t *temp = NULL;
+
+  STAILQ_FOREACH(temp, &m2ap_MCE_internal_data.m2ap_MCE_instances_head,
+                 m2ap_MCE_entries) {
+    if (temp->instance == instance) {
+      /* Matching occurence */
+      return temp;
+    }
+  }
+
+  return NULL;
+}
+
+/// utility functions
+
+void m2ap_dump_MCE (m2ap_MCE_data_t  * MCE_ref);
+
+void
+m2ap_dump_MCE_list (void) {
+   m2ap_MCE_instance_t *inst = NULL;
+   struct m2ap_MCE_data_s *found = NULL;
+   struct m2ap_MCE_data_s temp;
+
+   memset(&temp, 0, sizeof(struct m2ap_MCE_data_s));
+
+  STAILQ_FOREACH (inst, &m2ap_MCE_internal_data.m2ap_MCE_instances_head,  m2ap_MCE_entries) {
+    found = RB_FIND(m2ap_mce_map, &inst->m2ap_mce_head, &temp);
+    m2ap_dump_MCE (found);
+  }
+}
+
+void m2ap_dump_MCE (m2ap_MCE_data_t  * MCE_ref) {
+
+  if (MCE_ref == NULL) {
+    return;
+  }
+
+  M2AP_MCE_LIST_OUT ("");
+  M2AP_MCE_LIST_OUT ("MCE name:          %s", MCE_ref->MCE_name == NULL ? "not present" : MCE_ref->MCE_name);
+  M2AP_MCE_LIST_OUT ("MCE STATE:         %07x", MCE_ref->state);
+  M2AP_MCE_LIST_OUT ("MCE ID:            %07x", MCE_ref->MCE_id);
+  indent++;
+  M2AP_MCE_LIST_OUT ("SCTP cnx id:     %d", MCE_ref->cnx_id);
+  M2AP_MCE_LIST_OUT ("SCTP assoc id:     %d", MCE_ref->assoc_id);
+  M2AP_MCE_LIST_OUT ("SCTP instreams:    %d", MCE_ref->in_streams);
+  M2AP_MCE_LIST_OUT ("SCTP outstreams:   %d", MCE_ref->out_streams);
+  indent--;
+}
+
+m2ap_MCE_data_t  * m2ap_is_MCE_pci_in_list (const uint32_t pci)
+{
+  m2ap_MCE_instance_t    *inst;
+  struct m2ap_MCE_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m2ap_MCE_internal_data.m2ap_MCE_instances_head, m2ap_MCE_entries) {
+    RB_FOREACH(elm, m2ap_mce_map, &inst->m2ap_mce_head) {
+      for (int i = 0; i<elm->num_cc; i++) {
+        if (elm->Nid_cell[i] == pci) {
+          return elm;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+m2ap_MCE_data_t  * m2ap_is_MCE_id_in_list (const uint32_t MCE_id)
+{
+  m2ap_MCE_instance_t    *inst;
+  struct m2ap_MCE_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m2ap_MCE_internal_data.m2ap_MCE_instances_head, m2ap_MCE_entries) {
+    RB_FOREACH(elm, m2ap_mce_map, &inst->m2ap_mce_head) {
+      if (elm->MCE_id == MCE_id)
+        return elm;
+    }
+  }
+  return NULL;
+}
+
+m2ap_MCE_data_t  * m2ap_is_MCE_assoc_id_in_list (const uint32_t sctp_assoc_id)
+{
+  m2ap_MCE_instance_t    *inst;
+  struct m2ap_MCE_data_s *found;
+  struct m2ap_MCE_data_s temp;
+
+  temp.assoc_id = sctp_assoc_id;
+  temp.cnx_id = -1;
+
+  STAILQ_FOREACH(inst, &m2ap_MCE_internal_data.m2ap_MCE_instances_head, m2ap_MCE_entries) {
+    found = RB_FIND(m2ap_mce_map, &inst->m2ap_mce_head, &temp);
+    if (found != NULL){
+      if (found->assoc_id == sctp_assoc_id) {
+	return found;
+      }
+    }
+  }
+  return NULL;
+}
diff --git a/openair2/M2AP/m2ap_MCE_management_procedures.h b/openair2/M2AP/m2ap_MCE_management_procedures.h
new file mode 100644
index 0000000000000000000000000000000000000000..9e13e723c966de7ce2da6c76858562fa93d48854
--- /dev/null
+++ b/openair2/M2AP/m2ap_MCE_management_procedures.h
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_management_procedures.h
+ * \brief m2ap tasks for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_MANAGEMENT_PROCEDURES_H_
+#define M2AP_MCE_MANAGEMENT_PROCEDURES_H
+
+void m2ap_MCE_prepare_internal_data(void);
+
+void dump_trees_m2(void);
+
+void m2ap_MCE_insert_new_instance(m2ap_MCE_instance_t *new_instance_p);
+
+m2ap_MCE_instance_t *m2ap_MCE_get_instance(uint8_t mod_id);
+
+uint16_t m2ap_MCE_fetch_add_global_cnx_id(void);
+
+void m2ap_MCE_prepare_internal_data(void);
+
+m2ap_MCE_data_t* m2ap_is_MCE_id_in_list(uint32_t MCE_id);
+
+m2ap_MCE_data_t* m2ap_is_MCE_assoc_id_in_list(uint32_t sctp_assoc_id);
+
+m2ap_MCE_data_t* m2ap_is_MCE_pci_in_list (const uint32_t pci);
+
+struct m2ap_MCE_data_s *m2ap_get_MCE(m2ap_MCE_instance_t *instance_p,
+                                     int32_t assoc_id,
+                                     uint16_t cnx_id);
+
+#endif /* M2AP_MCE_MANAGEMENT_PROCEDURES_H_ */
diff --git a/openair2/M2AP/m2ap_common.c b/openair2/M2AP/m2ap_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..d288a0a11467b5d3512dd1b6655912b6ced39db0
--- /dev/null
+++ b/openair2/M2AP/m2ap_common.c
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_common.c
+ * \brief m2ap procedures for both eNB and MCE
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "m2ap_common.h"
+#include "M2AP_M2AP-PDU.h"
+
+int asn_debug = 0;
+int asn1_xer_print = 0;
+
+#if defined(EMIT_ASN_DEBUG_EXTERN)
+inline void ASN_DEBUG(const char *fmt, ...)
+{
+  if (asn_debug) {
+    int adi = asn_debug_indent;
+    va_list ap;
+    va_start(ap, fmt);
+    fprintf(stderr, "[ASN1]");
+
+    while(adi--) fprintf(stderr, " ");
+
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, "\n");
+    va_end(ap);
+  }
+}
+#endif
+
+ssize_t m2ap_generate_initiating_message(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M2AP_ProcedureCode_t    procedureCode,
+  M2AP_Criticality_t      criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr)
+{
+  M2AP_M2AP_PDU_t pdu;
+  ssize_t    encoded;
+  memset(&pdu, 0, sizeof(M2AP_M2AP_PDU_t));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = procedureCode;
+  pdu.choice.initiatingMessage.criticality   = criticality;
+  ANY_fromType_aper((ANY_t *)&pdu.choice.initiatingMessage.value, td, sptr);
+
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M2AP_M2AP_PDU, (void *)&pdu);
+  }
+
+  /* We can safely free list of IE from sptr */
+  ASN_STRUCT_FREE_CONTENTS_ONLY(*td, sptr);
+
+  if ((encoded = aper_encode_to_new_buffer(&asn_DEF_M2AP_M2AP_PDU, 0, &pdu,
+                 (void **)buffer)) < 0) {
+    return -1;
+  }
+
+  *length = encoded;
+  return encoded;
+}
+
+
+ssize_t m2ap_generate_unsuccessfull_outcome(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M2AP_ProcedureCode_t         procedureCode,
+  M2AP_Criticality_t           criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr)
+{
+  M2AP_M2AP_PDU_t pdu;
+  ssize_t    encoded;
+  memset(&pdu, 0, sizeof(M2AP_M2AP_PDU_t));
+  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = procedureCode;
+  pdu.choice.successfulOutcome.criticality   = criticality;
+  ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr);
+
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M2AP_M2AP_PDU, (void *)&pdu);
+  }
+
+  /* We can safely free list of IE from sptr */
+  ASN_STRUCT_FREE_CONTENTS_ONLY(*td, sptr);
+
+  if ((encoded = aper_encode_to_new_buffer(&asn_DEF_M2AP_M2AP_PDU, 0, &pdu,
+                 (void **)buffer)) < 0) {
+    return -1;
+  }
+
+  *length = encoded;
+  return encoded;
+}
+
+void m2ap_handle_criticality(M2AP_Criticality_t criticality)
+{
+
+}
+
diff --git a/openair2/M2AP/m2ap_common.h b/openair2/M2AP/m2ap_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..95da064b4abdfc1882ade115e9d400a370147d4f
--- /dev/null
+++ b/openair2/M2AP/m2ap_common.h
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#if HAVE_CONFIG_H_
+# include "config.h"
+#endif
+
+#include "M2AP_ProtocolIE-Field.h"
+#include "M2AP_M2AP-PDU.h"
+#include "M2AP_InitiatingMessage.h"
+#include "M2AP_SuccessfulOutcome.h"
+#include "M2AP_UnsuccessfulOutcome.h"
+#include "M2AP_ProtocolIE-FieldPair.h"
+#include "M2AP_ProtocolIE-ContainerPair.h"
+#include "M2AP_ProtocolExtensionField.h"
+#include "M2AP_ProtocolExtensionContainer.h"
+#include "M2AP_PMCH-Configuration-Item.h"
+#include "M2AP_asn_constant.h"
+#include "intertask_interface.h"
+
+#include "common/ran_context.h"
+
+#ifndef M2AP_COMMON_H_
+#define M2AP_COMMON_H_
+
+/** @defgroup _m2ap_impl_ M2AP Layer Reference Implementation
+ * @ingroup _ref_implementation_
+ * @{
+ */
+
+/* Checking version of ASN1C compiler */
+#if (ASN1C_ENVIRONMENT_VERSION < 923)
+# error "You are compiling m2ap with the wrong version of ASN1C"
+#endif
+
+#ifndef M2AP_PORT
+# define M2AP_PORT 36423
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+extern int asn1_xer_print;
+
+#if defined(ENB_MODE)
+# include "common/utils/LOG/log.h"
+# include "m2ap_default_values.h"
+# define M2AP_INFO(x, args...) LOG_I(M2AP, x, ##args)
+# define M2AP_ERROR(x, args...) LOG_E(M2AP, x, ##args)
+# define M2AP_WARN(x, args...)  LOG_W(M2AP, x, ##args)
+# define M2AP_DEBUG(x, args...) LOG_D(M2AP, x, ##args)
+#else
+# define M2AP_INFO(x, args...) do { fprintf(stdout, "[M2AP][I]"x, ##args); } while(0)
+# define M2AP_ERROR(x, args...) do { fprintf(stdout, "[M2AP][E]"x, ##args); } while(0)
+# define M2AP_WARN(x, args...)  do { fprintf(stdout, "[M2AP][W]"x, ##args); } while(0)
+# define M2AP_DEBUG(x, args...) do { fprintf(stdout, "[M2AP][D]"x, ##args); } while(0)
+#endif
+
+#define M2AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \
+  do {\
+    IE_TYPE **ptr; \
+    ie = NULL; \
+    for (ptr = container->protocolIEs.list.array; \
+         ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \
+         ptr++) { \
+      if((*ptr)->id == IE_ID) { \
+        ie = *ptr; \
+        break; \
+      } \
+    } \
+    if (mandatory) DevAssert(ie != NULL); \
+  } while(0)
+
+/** \brief Function callback prototype.
+ **/
+typedef int (*m2ap_message_decoded_callback)(
+  instance_t instance,
+  uint32_t assocId,
+  uint32_t stream,
+  M2AP_M2AP_PDU_t *pdu);
+
+typedef int (*m2ap_MCE_message_decoded_callback)(
+  instance_t instance,
+  uint32_t assocId,
+  uint32_t stream,
+  M2AP_M2AP_PDU_t *pdu);
+
+typedef int (*m2ap_eNB_message_decoded_callback)(
+  instance_t instance,
+  uint32_t assocId,
+  uint32_t stream,
+  M2AP_M2AP_PDU_t *pdu);
+
+
+
+/** \brief Encode a successfull outcome message
+ \param buffer pointer to buffer in which data will be encoded
+ \param length pointer to the length of buffer
+ \param procedureCode Procedure code for the message
+ \param criticality Criticality of the message
+ \param td ASN1C type descriptor of the sptr
+ \param sptr Deferenced pointer to the structure to encode
+ @returns size in bytes encded on success or 0 on failure
+ **/
+ssize_t m2ap_generate_successfull_outcome(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M2AP_ProcedureCode_t         procedureCode,
+  M2AP_Criticality_t           criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr);
+
+/** \brief Encode an initiating message
+ \param buffer pointer to buffer in which data will be encoded
+ \param length pointer to the length of buffer
+ \param procedureCode Procedure code for the message
+ \param criticality Criticality of the message
+ \param td ASN1C type descriptor of the sptr
+ \param sptr Deferenced pointer to the structure to encode
+ @returns size in bytes encded on success or 0 on failure
+ **/
+ssize_t m2ap_generate_initiating_message(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M2AP_ProcedureCode_t    procedureCode,
+  M2AP_Criticality_t      criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr);
+
+/** \brief Encode an unsuccessfull outcome message
+ \param buffer pointer to buffer in which data will be encoded
+ \param length pointer to the length of buffer
+ \param procedureCode Procedure code for the message
+ \param criticality Criticality of the message
+ \param td ASN1C type descriptor of the sptr
+ \param sptr Deferenced pointer to the structure to encode
+ @returns size in bytes encded on success or 0 on failure
+ **/
+ssize_t m2ap_generate_unsuccessfull_outcome(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M2AP_ProcedureCode_t         procedureCode,
+  M2AP_Criticality_t           criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr);
+
+/** \brief Handle criticality
+ \param criticality Criticality of the IE
+ @returns void
+ **/
+void m2ap_handle_criticality(M2AP_Criticality_t criticality);
+
+#endif /* M2AP_COMMON_H_ */
diff --git a/openair2/M2AP/m2ap_decoder.c b/openair2/M2AP/m2ap_decoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..1237c4ec8ec6246764ee69d79cd17d43d64f02b3
--- /dev/null
+++ b/openair2/M2AP/m2ap_decoder.c
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_decoder.c
+ * \brief m2ap decoder procedures 
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+
+#include "assertions.h"
+#include "intertask_interface.h"
+#include "m2ap_common.h"
+#include "m2ap_decoder.h"
+
+static int m2ap_decode_initiating_message(M2AP_M2AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.initiatingMessage.procedureCode) {
+    case M2AP_ProcedureCode_id_sessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_initiating_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_sessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_initiating_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_m2Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_initiating_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_mbmsSchedulingInformation:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_initiating_message!\n");
+      break;
+
+
+   
+//    case M2AP_ProcedureCode_id_handoverPreparation:
+//      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+//      M2AP_INFO("m2ap__decode_initiating_message!\n");
+//      break;
+//
+//    case M2AP_ProcedureCode_id_uEContextRelease:
+//      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+//      M2AP_INFO("m2ap__decode_initiating_message!\n");
+//      break;
+//
+//    case M2AP_ProcedureCode_id_handoverCancel:
+//      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+//      M2AP_INFO("m2ap__decode_initiating_message!\n");
+//      break;
+//
+    default:
+      M2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
+                  (int)pdu->choice.initiatingMessage.procedureCode);
+      AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n",
+                   (int)pdu->choice.initiatingMessage.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+static int m2ap_decode_successful_outcome(M2AP_M2AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.successfulOutcome.procedureCode) {
+    case M2AP_ProcedureCode_id_sessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_successfuloutcome_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_sessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_succesfuloutcome_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_m2Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_succesfuloutcome_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_mbmsSchedulingInformation:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_succesfuloutcome_message!\n");
+      break;
+
+
+//    case M2AP_ProcedureCode_id_handoverPreparation:
+//      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+//      M2AP_INFO("m2ap__decode_successfuloutcome_message!\n");
+//      break;
+//
+    default:
+      M2AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
+                  (int)pdu->choice.successfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+static int m2ap_decode_unsuccessful_outcome(M2AP_M2AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
+    case M2AP_ProcedureCode_id_sessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_initiating_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_sessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_initiating_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_m2Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_initiating_message!\n");
+      break;
+    case M2AP_ProcedureCode_id_mbmsSchedulingInformation:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M2AP_M2AP_PDU, pdu);
+      M2AP_INFO("m2ap__decode_initiating_message!\n");
+      break;
+
+
+    default:
+       M2AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
+                  (int)pdu->choice.unsuccessfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+int m2ap_decode_pdu(M2AP_M2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
+{
+  asn_dec_rval_t dec_ret;
+
+  DevAssert(buffer != NULL);
+
+  dec_ret = aper_decode(NULL,
+                        &asn_DEF_M2AP_M2AP_PDU,
+                        (void **)&pdu,
+                        buffer,
+                        length,
+                        0,
+                        0);
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M2AP_M2AP_PDU, pdu);
+  }
+
+  if (dec_ret.code != RC_OK) {
+    M2AP_ERROR("Failed to decode pdu\n");
+    return -1;
+  }
+
+  switch(pdu->present) {
+    case M2AP_M2AP_PDU_PR_initiatingMessage:
+      return m2ap_decode_initiating_message(pdu);
+
+    case M2AP_M2AP_PDU_PR_successfulOutcome:
+      return m2ap_decode_successful_outcome(pdu);
+
+    case M2AP_M2AP_PDU_PR_unsuccessfulOutcome:
+      return m2ap_decode_unsuccessful_outcome(pdu);
+
+    default:
+      M2AP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present);
+      break;
+  }
+
+
+  return -1;
+}
diff --git a/openair2/M2AP/m2ap_decoder.h b/openair2/M2AP/m2ap_decoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ab01fe703281b051f6d9aff72b9bada78788e58
--- /dev/null
+++ b/openair2/M2AP/m2ap_decoder.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_decoder.h
+ * \brief m2ap decoder procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_DECODER_H_
+#define M2AP_DECODER_H_
+
+int m2ap_decode_pdu(M2AP_M2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
+__attribute__ ((warn_unused_result));
+
+#endif /* M2AP_DECODER_H_ */
diff --git a/openair2/M2AP/m2ap_default_values.h b/openair2/M2AP/m2ap_default_values.h
new file mode 100644
index 0000000000000000000000000000000000000000..baae4b963c29f07ee98fbb2b5f3baa74693d305f
--- /dev/null
+++ b/openair2/M2AP/m2ap_default_values.h
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_default_values.h
+ * \brief default values for m2ap procedures
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M2AP_DEFAULT_VALUES_H_
+#define M2AP_DEFAULT_VALUES_H_
+
+#define ENB_TAC (1)
+#define ENB_MCC (208)
+#define ENB_MNC (92)
+
+#define ENB_NAME        "Eurecom ENB"
+#define ENB_NAME_FORMAT (ENB_NAME" %u")
+
+#define M2AP_PORT_NUMBER        (36443)
+#define M2AP_SCTP_PPID          (43)
+
+#endif /* M2AP_DEFAULT_VALUES_H_ */
+
diff --git a/openair2/M2AP/m2ap_eNB.c b/openair2/M2AP/m2ap_eNB.c
new file mode 100644
index 0000000000000000000000000000000000000000..206b7cf8ca7e6b34f75c9064ba79d01c9bb27a66
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB.c
@@ -0,0 +1,704 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB.c
+ * \brief m2ap tasks for eNB
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
+#include "intertask_interface.h"
+
+#include "m2ap_eNB.h"
+#include "m2ap_eNB_defs.h"
+#include "m2ap_eNB_management_procedures.h"
+#include "m2ap_eNB_handler.h"
+#include "m2ap_eNB_generate_messages.h"
+#include "m2ap_common.h"
+#include "m2ap_eNB_interface_management.h"
+#include "m2ap_ids.h"
+#include "m2ap_timers.h"
+
+#include "queue.h"
+#include "assertions.h"
+#include "conversions.h"
+
+struct m2ap_enb_map;
+struct m2ap_eNB_data_s;
+
+m2ap_setup_req_t * m2ap_enb_data_g;
+
+RB_PROTOTYPE(m2ap_enb_map, m2ap_eNB_data_s, entry, m2ap_eNB_compare_assoc_id);
+
+static
+void m2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
+
+static
+void m2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
+
+static
+void m2ap_eNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind);
+
+static
+void m2ap_eNB_handle_register_eNB(instance_t instance,
+                                  m2ap_register_enb_req_t *m2ap_register_eNB);
+static
+void m2ap_eNB_register_eNB(m2ap_eNB_instance_t *instance_p,
+                           net_ip_address_t    *target_eNB_ip_addr,
+                           net_ip_address_t    *local_ip_addr,
+                           uint16_t             in_streams,
+                           uint16_t             out_streams,
+                           uint32_t             enb_port_for_M2C,
+                           int                  multi_sd);
+
+//static
+//void m2ap_eNB_handle_handover_req(instance_t instance,
+//                                  m2ap_handover_req_t *m2ap_handover_req);
+//
+//static
+//void m2ap_eNB_handle_handover_req_ack(instance_t instance,
+//                                      m2ap_handover_req_ack_t *m2ap_handover_req_ack);
+//
+//static
+//void m2ap_eNB_ue_context_release(instance_t instance,
+//                                 m2ap_ue_context_release_t *m2ap_ue_context_release);
+//
+
+static
+void m2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
+  int result;
+  DevAssert(sctp_data_ind != NULL);
+  m2ap_eNB_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
+                          sctp_data_ind->buffer, sctp_data_ind->buffer_length);
+  result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
+  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+}
+
+static
+void m2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
+  m2ap_eNB_instance_t *instance_p;
+  m2ap_eNB_data_t *m2ap_enb_data_p;
+  DevAssert(sctp_new_association_resp != NULL);
+ // printf("m2ap_eNB_handle_sctp_association_resp at 1\n");
+ // dump_trees_m2();
+  instance_p = m2ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  /* if the assoc_id is already known, it is certainly because an IND was received
+   * before. In this case, just update streams and return
+   */
+  if (sctp_new_association_resp->assoc_id != -1) {
+    m2ap_enb_data_p = m2ap_get_eNB(instance_p, sctp_new_association_resp->assoc_id,
+                                   sctp_new_association_resp->ulp_cnx_id);
+
+    if (m2ap_enb_data_p != NULL) {
+      /* some sanity check - to be refined at some point */
+      if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+        M2AP_ERROR("m2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
+        abort();
+      }
+
+      m2ap_enb_data_p->in_streams  = sctp_new_association_resp->in_streams;
+      m2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
+      return;
+    }
+  }
+
+  m2ap_enb_data_p = m2ap_get_eNB(instance_p, -1,
+                                 sctp_new_association_resp->ulp_cnx_id);
+  DevAssert(m2ap_enb_data_p != NULL);
+  //printf("m2ap_eNB_handle_sctp_association_resp at 2\n");
+  //dump_trees_m2();
+
+  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+    M2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+              sctp_new_association_resp->sctp_state,
+              instance,
+              sctp_new_association_resp->ulp_cnx_id);
+    //m2ap_handle_m2_setup_message(instance_p, m2ap_enb_data_p,
+    //                             sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+    return;
+  }
+
+  //printf("m2ap_eNB_handle_sctp_association_resp at 3\n");
+  //dump_trees_m2();
+  /* Update parameters */
+  m2ap_enb_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
+  m2ap_enb_data_p->in_streams  = sctp_new_association_resp->in_streams;
+  m2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
+  //printf("m2ap_eNB_handle_sctp_association_resp at 4\n");
+  //dump_trees_m2();
+
+  m2ap_enb_data_g->assoc_id    = sctp_new_association_resp->assoc_id;
+  m2ap_enb_data_g->sctp_in_streams  = sctp_new_association_resp->in_streams;
+  m2ap_enb_data_g->sctp_out_streams = sctp_new_association_resp->out_streams;
+
+  /* Prepare new m2 Setup Request */
+  //m2ap_eNB_generate_m2_setup_request(instance_p, m2ap_enb_data_p);
+  eNB_send_M2_SETUP_REQUEST(instance_p, m2ap_enb_data_p);
+  //eNB_send_M2_SETUP_REQUEST(instance_p, m2ap_enb_data_g);
+  
+}
+
+static
+void m2ap_eNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) {
+  m2ap_eNB_instance_t *instance_p;
+  m2ap_eNB_data_t *m2ap_enb_data_p;
+  //printf("m2ap_eNB_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
+  //dump_trees_m2();
+  DevAssert(sctp_new_association_ind != NULL);
+  instance_p = m2ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+  m2ap_enb_data_p = m2ap_get_eNB(instance_p, sctp_new_association_ind->assoc_id, -1);
+
+  if (m2ap_enb_data_p != NULL) abort();
+
+  //  DevAssert(m2ap_enb_data_p != NULL);
+  if (m2ap_enb_data_p == NULL) {
+    /* Create new eNB descriptor */
+    m2ap_enb_data_p = calloc(1, sizeof(*m2ap_enb_data_p));
+    DevAssert(m2ap_enb_data_p != NULL);
+    m2ap_enb_data_p->cnx_id                = m2ap_eNB_fetch_add_global_cnx_id();
+    m2ap_enb_data_p->m2ap_eNB_instance = instance_p;
+    /* Insert the new descriptor in list of known eNB
+     * but not yet associated.
+     */
+    RB_INSERT(m2ap_enb_map, &instance_p->m2ap_enb_head, m2ap_enb_data_p);
+    m2ap_enb_data_p->state = M2AP_ENB_STATE_CONNECTED;
+    instance_p->m2_target_enb_nb++;
+
+    if (instance_p->m2_target_enb_pending_nb > 0) {
+      instance_p->m2_target_enb_pending_nb--;
+    }
+  } else {
+    M2AP_WARN("m2ap_enb_data_p already exists\n");
+  }
+
+  //printf("m2ap_eNB_handle_sctp_association_ind at 2\n");
+  //dump_trees_m2();
+  /* Update parameters */
+  m2ap_enb_data_p->assoc_id    = sctp_new_association_ind->assoc_id;
+  m2ap_enb_data_p->in_streams  = sctp_new_association_ind->in_streams;
+  m2ap_enb_data_p->out_streams = sctp_new_association_ind->out_streams;
+  //printf("m2ap_eNB_handle_sctp_association_ind at 3\n");
+  //dump_trees_m2();
+}
+
+int m2ap_eNB_init_sctp (m2ap_eNB_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t enb_port_for_M2C) {
+  // Create and alloc new message
+  MessageDef                             *message;
+  sctp_init_t                            *sctp_init  = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(local_ip_addr != NULL);
+  message = itti_alloc_new_message (TASK_M2AP_ENB, SCTP_INIT_MSG_MULTI_REQ);
+  sctp_init = &message->ittiMsg.sctp_init_multi;
+  sctp_init->port = enb_port_for_M2C;
+  sctp_init->ppid = M2AP_SCTP_PPID;
+  sctp_init->ipv4 = 1;
+  sctp_init->ipv6 = 0;
+  sctp_init->nb_ipv4_addr = 1;
+#if 0
+  memcpy(&sctp_init->ipv4_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+#endif
+  sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
+  /*
+   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+   * * * * Disable it for now.
+   */
+  sctp_init->nb_ipv6_addr = 0;
+  sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
+  return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
+}
+
+static void m2ap_eNB_register_eNB(m2ap_eNB_instance_t *instance_p,
+                                  net_ip_address_t    *target_eNB_ip_address,
+                                  net_ip_address_t    *local_ip_addr,
+                                  uint16_t             in_streams,
+                                  uint16_t             out_streams,
+                                  uint32_t         enb_port_for_M2C,
+                                  int                  multi_sd) {
+  MessageDef                       *message                   = NULL;
+  sctp_new_association_req_multi_t *sctp_new_association_req  = NULL;
+  m2ap_eNB_data_t                  *m2ap_enb_data             = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(target_eNB_ip_address != NULL);
+  message = itti_alloc_new_message(TASK_M2AP_ENB, SCTP_NEW_ASSOCIATION_REQ_MULTI);
+  sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi;
+  sctp_new_association_req->port = enb_port_for_M2C;
+  sctp_new_association_req->ppid = M2AP_SCTP_PPID;
+  sctp_new_association_req->in_streams  = in_streams;
+  sctp_new_association_req->out_streams = out_streams;
+  sctp_new_association_req->multi_sd = multi_sd;
+  memcpy(&sctp_new_association_req->remote_address,
+         target_eNB_ip_address,
+         sizeof(*target_eNB_ip_address));
+  memcpy(&sctp_new_association_req->local_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+  /* Create new eNB descriptor */
+  m2ap_enb_data = calloc(1, sizeof(*m2ap_enb_data));
+  DevAssert(m2ap_enb_data != NULL);
+  m2ap_enb_data->cnx_id                = m2ap_eNB_fetch_add_global_cnx_id();
+  sctp_new_association_req->ulp_cnx_id = m2ap_enb_data->cnx_id;
+  m2ap_enb_data->assoc_id          = -1;
+  m2ap_enb_data->m2ap_eNB_instance = instance_p;
+
+
+  m2ap_enb_data_g = (m2ap_setup_req_t*)calloc(1,sizeof(m2ap_setup_req_t));
+  
+
+  //
+  m2ap_enb_data->eNB_name = "enb_name";
+  /* Insert the new descriptor in list of known eNB
+   * but not yet associated.
+   */
+  RB_INSERT(m2ap_enb_map, &instance_p->m2ap_enb_head, m2ap_enb_data);
+  m2ap_enb_data->state = M2AP_ENB_STATE_WAITING;
+  instance_p->m2_target_enb_nb ++;
+  instance_p->m2_target_enb_pending_nb ++;
+  itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
+}
+
+static
+void m2ap_eNB_handle_register_eNB(instance_t instance,
+                                  m2ap_register_enb_req_t *m2ap_register_eNB) {
+  m2ap_eNB_instance_t *new_instance;
+  DevAssert(m2ap_register_eNB != NULL);
+  /* Look if the provided instance already exists */
+  new_instance = m2ap_eNB_get_instance(instance);
+
+  if (new_instance != NULL) {
+    /* Checks if it is a retry on the same eNB */
+    DevCheck(new_instance->eNB_id == m2ap_register_eNB->eNB_id, new_instance->eNB_id, m2ap_register_eNB->eNB_id, 0);
+    DevCheck(new_instance->cell_type == m2ap_register_eNB->cell_type, new_instance->cell_type, m2ap_register_eNB->cell_type, 0);
+    DevCheck(new_instance->tac == m2ap_register_eNB->tac, new_instance->tac, m2ap_register_eNB->tac, 0);
+    DevCheck(new_instance->mcc == m2ap_register_eNB->mcc, new_instance->mcc, m2ap_register_eNB->mcc, 0);
+    DevCheck(new_instance->mnc == m2ap_register_eNB->mnc, new_instance->mnc, m2ap_register_eNB->mnc, 0);
+    M2AP_WARN("eNB[%d] already registered\n", instance);
+  } else {
+    new_instance = calloc(1, sizeof(m2ap_eNB_instance_t));
+    DevAssert(new_instance != NULL);
+    RB_INIT(&new_instance->m2ap_enb_head);
+    /* Copy usefull parameters */
+    new_instance->instance         = instance;
+    new_instance->eNB_name         = m2ap_register_eNB->eNB_name;
+    new_instance->eNB_id           = m2ap_register_eNB->eNB_id;
+    new_instance->cell_type        = m2ap_register_eNB->cell_type;
+    new_instance->tac              = m2ap_register_eNB->tac;
+    new_instance->mcc              = m2ap_register_eNB->mcc;
+    new_instance->mnc              = m2ap_register_eNB->mnc;
+    new_instance->mnc_digit_length = m2ap_register_eNB->mnc_digit_length;
+    new_instance->num_cc           = m2ap_register_eNB->num_cc;
+
+    m2ap_id_manager_init(&new_instance->id_manager);
+    m2ap_timers_init(&new_instance->timers,
+                     m2ap_register_eNB->t_reloc_prep,
+                     m2ap_register_eNB->tm2_reloc_overall);
+
+    for (int i = 0; i< m2ap_register_eNB->num_cc; i++) {
+      new_instance->eutra_band[i]              = m2ap_register_eNB->eutra_band[i];
+      new_instance->downlink_frequency[i]      = m2ap_register_eNB->downlink_frequency[i];
+      new_instance->uplink_frequency_offset[i] = m2ap_register_eNB->uplink_frequency_offset[i];
+      new_instance->Nid_cell[i]                = m2ap_register_eNB->Nid_cell[i];
+      new_instance->N_RB_DL[i]                 = m2ap_register_eNB->N_RB_DL[i];
+      new_instance->frame_type[i]              = m2ap_register_eNB->frame_type[i];
+      new_instance->fdd_earfcn_DL[i]           = m2ap_register_eNB->fdd_earfcn_DL[i];
+      new_instance->fdd_earfcn_UL[i]           = m2ap_register_eNB->fdd_earfcn_UL[i];
+    }
+
+    DevCheck(m2ap_register_eNB->nb_m2 <= M2AP_MAX_NB_ENB_IP_ADDRESS,
+             M2AP_MAX_NB_ENB_IP_ADDRESS, m2ap_register_eNB->nb_m2, 0);
+    memcpy(new_instance->target_mce_m2_ip_address,
+           m2ap_register_eNB->target_mce_m2_ip_address,
+           m2ap_register_eNB->nb_m2 * sizeof(net_ip_address_t));
+    new_instance->nb_m2             = m2ap_register_eNB->nb_m2;
+    new_instance->enb_m2_ip_address = m2ap_register_eNB->enb_m2_ip_address;
+    new_instance->sctp_in_streams   = m2ap_register_eNB->sctp_in_streams;
+    new_instance->sctp_out_streams  = m2ap_register_eNB->sctp_out_streams;
+    new_instance->enb_port_for_M2C  = m2ap_register_eNB->enb_port_for_M2C;
+
+
+    new_instance->num_mbms_configuration_data_list = m2ap_register_eNB->num_mbms_configuration_data_list;
+    for(int j=0; j < m2ap_register_eNB->num_mbms_configuration_data_list;j++){
+	    new_instance->mbms_configuration_data_list[j].num_mbms_service_area_list = m2ap_register_eNB->mbms_configuration_data_list[j].num_mbms_service_area_list;
+	    for(int i=0; i <  m2ap_register_eNB->mbms_configuration_data_list[j].num_mbms_service_area_list; i++ ){
+		//strcpy(&new_instance->mbms_configuration_data_list[j].mbms_service_area_list[i],&m2ap_register_eNB->mbms_configuration_data_list[j].mbms_service_area_list[i]);
+		new_instance->mbms_configuration_data_list[j].mbms_service_area_list[i]=m2ap_register_eNB->mbms_configuration_data_list[j].mbms_service_area_list[i];
+	    }
+    }
+
+    /* Add the new instance to the list of eNB (meaningfull in virtual mode) */
+    m2ap_eNB_insert_new_instance(new_instance);
+    M2AP_INFO("Registered new eNB[%d] and %s eNB id %u\n",
+              instance,
+              m2ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
+              m2ap_register_eNB->eNB_id);
+
+    /* initiate the SCTP listener */
+    if (m2ap_eNB_init_sctp(new_instance,&m2ap_register_eNB->enb_m2_ip_address,m2ap_register_eNB->enb_port_for_M2C) <  0 ) {
+      M2AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
+      return;
+    }
+
+    M2AP_INFO("eNB[%d] eNB id %u acting as a listner (server)\n",
+              instance, m2ap_register_eNB->eNB_id);
+  }
+}
+
+static
+void m2ap_eNB_handle_sctp_init_msg_multi_cnf(
+  instance_t instance_id,
+  sctp_init_msg_multi_cnf_t *m) {
+  m2ap_eNB_instance_t *instance;
+  int index;
+  DevAssert(m != NULL);
+  instance = m2ap_eNB_get_instance(instance_id);
+  DevAssert(instance != NULL);
+  instance->multi_sd = m->multi_sd;
+
+  /* Exit if CNF message reports failure.
+   * Failure means multi_sd < 0.
+   */
+  if (instance->multi_sd < 0) {
+    M2AP_ERROR("Error: be sure to properly configure M2 in your configuration file.\n");
+    DevAssert(instance->multi_sd >= 0);
+  }
+
+  /* Trying to connect to the provided list of eNB ip address */
+
+  for (index = 0; index < instance->nb_m2; index++) {
+    M2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n",
+              instance_id, instance->eNB_id);
+    m2ap_eNB_register_eNB(instance,
+                          &instance->target_mce_m2_ip_address[index],
+                          &instance->enb_m2_ip_address,
+                          instance->sctp_in_streams,
+                          instance->sctp_out_streams,
+                          instance->enb_port_for_M2C,
+                          instance->multi_sd);
+  }
+}
+
+//static
+//void m2ap_eNB_handle_handover_req(instance_t instance,
+//                                  m2ap_handover_req_t *m2ap_handover_req)
+//{
+//  m2ap_eNB_instance_t *instance_p;
+//  m2ap_eNB_data_t     *target;
+//  m2ap_id_manager     *id_manager;
+//  int                 ue_id;
+//
+//  int target_pci = m2ap_handover_req->target_physCellId;
+//
+//  instance_p = m2ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m2ap_is_eNB_pci_in_list(target_pci);
+//  DevAssert(target != NULL);
+//
+//  /* allocate m2ap ID */
+//  id_manager = &instance_p->id_manager;
+//  ue_id = m2ap_allocate_new_id(id_manager);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not allocate a new M2AP UE ID\n");
+//    /* TODO: cancel handover: send (to be defined) message to RRC */
+//    exit(1);
+//  }
+//  /* id_source is ue_id, id_target is unknown yet */
+//  m2ap_set_ids(id_manager, ue_id, m2ap_handover_req->rnti, ue_id, -1);
+//  m2ap_id_set_state(id_manager, ue_id, M2ID_STATE_SOURCE_PREPARE);
+//  m2ap_set_reloc_prep_timer(id_manager, ue_id,
+//                            m2ap_timer_get_tti(&instance_p->timers));
+//  m2ap_id_set_target(id_manager, ue_id, target);
+//
+//  m2ap_eNB_generate_m2_handover_request(instance_p, target, m2ap_handover_req, ue_id);
+//}
+
+//static
+//void m2ap_eNB_handle_handover_req_ack(instance_t instance,
+//                                      m2ap_handover_req_ack_t *m2ap_handover_req_ack)
+//{
+//  /* TODO: remove this hack (the goal is to find the correct
+//   * eNodeB structure for the other end) - we need a proper way for RRC
+//   * and M2AP to identify eNodeBs
+//   * RRC knows about mod_id and M2AP knows about eNB_id (eNB_ID in
+//   * the configuration file)
+//   * as far as I understand.. CROUX
+//   */
+//  m2ap_eNB_instance_t *instance_p;
+//  m2ap_eNB_data_t     *target;
+//  int source_assoc_id = m2ap_handover_req_ack->source_assoc_id;
+//  int                 ue_id;
+//  int                 id_source;
+//  int                 id_target;
+//
+//  instance_p = m2ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m2ap_get_eNB(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  /* rnti is a new information, save it */
+//  ue_id     = m2ap_handover_req_ack->m2_id_target;
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//  m2ap_set_ids(&instance_p->id_manager, ue_id, m2ap_handover_req_ack->rnti, id_source, id_target);
+//
+//  m2ap_eNB_generate_m2_handover_request_ack(instance_p, target, m2ap_handover_req_ack);
+//}
+//
+//static
+//void m2ap_eNB_ue_context_release(instance_t instance,
+//                                 m2ap_ue_context_release_t *m2ap_ue_context_release)
+//{
+//  m2ap_eNB_instance_t *instance_p;
+//  m2ap_eNB_data_t     *target;
+//  int source_assoc_id = m2ap_ue_context_release->source_assoc_id;
+//  int ue_id;
+//  instance_p = m2ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m2ap_get_eNB(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  m2ap_eNB_generate_m2_ue_context_release(instance_p, target, m2ap_ue_context_release);
+//
+//  /* free the M2AP UE ID */
+//  ue_id = m2ap_find_id_from_rnti(&instance_p->id_manager, m2ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not find UE %x\n", m2ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  m2ap_release_id(&instance_p->id_manager, ue_id);
+//}
+
+//void MCE_task_send_sctp_init_req(instance_t enb_id) {
+//  // 1. get the itti msg, and retrive the enb_id from the message
+//  // 2. use RC.rrc[enb_id] to fill the sctp_init_t with the ip, port
+//  // 3. creat an itti message to init
+//
+//  LOG_I(M2AP, "M2AP_SCTP_REQ(create socket)\n");
+//  MessageDef  *message_p = NULL;
+//
+//  message_p = itti_alloc_new_message (M2AP, SCTP_INIT_MSG);
+//  message_p->ittiMsg.sctp_init.port = M2AP_PORT_NUMBER;
+//  message_p->ittiMsg.sctp_init.ppid = M2AP_SCTP_PPID;
+//  message_p->ittiMsg.sctp_init.ipv4 = 1;
+//  message_p->ittiMsg.sctp_init.ipv6 = 0;
+//  message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
+//  //message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+//  message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr("127.0.0.7");
+//  /*
+//   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+//   * * * * Disable it for now.
+//   */
+//  message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0;
+//  message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1";
+//
+//  itti_send_msg_to_task(TASK_SCTP, enb_id, message_p);
+//}
+//
+void *m2ap_eNB_task(void *arg) {
+  MessageDef *received_msg = NULL;
+  int         result;
+  M2AP_DEBUG("Starting M2AP layer\n");
+  m2ap_eNB_prepare_internal_data();
+
+  itti_mark_task_ready(TASK_M2AP_ENB);
+
+ // MCE_task_send_sctp_init_req(0);
+
+  while (1) {
+    itti_receive_msg(TASK_M2AP_ENB, &received_msg);
+
+    switch (ITTI_MSG_ID(received_msg)) {
+      case MESSAGE_TEST:
+	LOG_D(M2AP,"eNB Received MESSAGE_TEST Message %s\n",itti_get_task_name(ITTI_MSG_ORIGIN_ID(received_msg)));
+	//MessageDef * message_p = itti_alloc_new_message(TASK_M2AP_ENB, MESSAGE_TEST);
+        //itti_send_msg_to_task(TASK_M3AP, 1/*ctxt_pP->module_id*/, message_p);
+	break;
+      case TERMINATE_MESSAGE:
+        M2AP_WARN(" *** Exiting M2AP thread\n");
+        itti_exit_task();
+        break;
+
+      case M2AP_SUBFRAME_PROCESS:
+        m2ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg));
+        break;
+
+      case M2AP_REGISTER_ENB_REQ:
+	LOG_I(M2AP,"eNB Received M2AP_REGISTER_ENB_REQ Message\n");
+        m2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_REGISTER_ENB_REQ(received_msg));
+        break;
+
+
+      case M2AP_MBMS_SCHEDULING_INFORMATION_RESP:
+	LOG_I(M2AP,"eNB M2AP_MBMS_SCHEDULING_INFORMATION_RESP Message\n");
+        eNB_send_MBMS_SCHEDULING_INFORMATION_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SCHEDULING_INFORMATION_RESP(received_msg));
+	break;
+      case M2AP_MBMS_SESSION_START_RESP:
+	LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_START_RESP Message\n");
+        eNB_send_MBMS_SESSION_START_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SESSION_START_RESP(received_msg));
+	break;
+      case M2AP_MBMS_SESSION_START_FAILURE:
+	LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_START_FAILURE Message\n");
+        eNB_send_MBMS_SESSION_START_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SESSION_START_FAILURE(received_msg));
+	break;
+      case M2AP_MBMS_SESSION_STOP_RESP:
+	LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_STOP_RESP Message\n");
+        eNB_send_MBMS_SESSION_STOP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SESSION_STOP_RESP(received_msg));
+	break;
+      case M2AP_ENB_CONFIGURATION_UPDATE:
+	LOG_I(M2AP,"eNB M2AP_ENB_CONFIGURATION_UPDATE Message\n");
+        eNB_send_eNB_CONFIGURATION_UPDATE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_ENB_CONFIGURATION_UPDATE(received_msg));
+	break;
+      case M2AP_MCE_CONFIGURATION_UPDATE_ACK:
+	LOG_I(M2AP,"eNB M2AP_MCE_CONFIGURATION_UPDATE_ACK Message\n");
+        //eNB_send_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+         //                            &M2AP_MCE_CONFIGURATION_UPDATE_ACK(received_msg));
+	break;
+      case M2AP_MCE_CONFIGURATION_UPDATE_FAILURE:
+	LOG_I(M2AP,"eNB M2AP_MCE_CONFIGURATION_UPDATE_FAILURE Message\n");
+        //(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     //&M2AP_MCE_CONFIGURATION_UPDATE_FAILURE(received_msg));
+	break;
+      case M2AP_MBMS_SESSION_UPDATE_RESP:
+	LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_UPDATE_RESP Message\n");
+        eNB_send_MBMS_SESSION_UPDATE_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SESSION_UPDATE_RESP(received_msg));
+	break;
+      case M2AP_MBMS_SESSION_UPDATE_FAILURE:
+	LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_UPDATE_FAILURE Message\n");
+        eNB_send_MBMS_SESSION_UPDATE_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SESSION_UPDATE_FAILURE(received_msg));
+	break;
+      case M2AP_MBMS_SERVICE_COUNTING_REPORT:
+	LOG_I(M2AP,"eNB M2AP_MBMS_SERVICE_COUNTING_REPORT Message\n");
+        eNB_send_MBMS_SERVICE_COUNTING_REPORT(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SERVICE_COUNTING_REPORT(received_msg));
+	break;
+      case M2AP_MBMS_OVERLOAD_NOTIFICATION:
+	LOG_I(M2AP,"eNB M2AP_MBMS_OVERLOAD_NOTIFICATION Message\n");
+        eNB_send_MBMS_OVERLOAD_NOTIFICATION(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_OVERLOAD_NOTIFICATION(received_msg));
+	break;
+      case M2AP_MBMS_SERVICE_COUNTING_RESP:
+	LOG_I(M2AP,"eNB M2AP_MBMS_SERVICE_COUNTING_RESP Message\n");
+        eNB_send_MBMS_SERVICE_COUNTING_RESP(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SERVICE_COUNTING_RESP(received_msg));
+	break;
+      case M2AP_MBMS_SERVICE_COUNTING_FAILURE:
+	LOG_I(M2AP,"eNB  Message\n");
+        eNB_send_MBMS_SERVICE_COUNTING_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M2AP_MBMS_SERVICE_COUNTING_FAILURE(received_msg));
+	break;
+
+
+      case SCTP_INIT_MSG_MULTI_CNF:
+	LOG_I(M2AP,"eNB Received SCTP_INIT_MSG_MULTI_CNF Message\n");
+        m2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                                &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_RESP:
+	LOG_I(M2AP,"eNB Received SCTP_NEW_ASSOCIATION_RESP Message\n");
+        m2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                              &received_msg->ittiMsg.sctp_new_association_resp);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_IND:
+	LOG_I(M2AP,"eNB Received SCTP_NEW_ASSOCIATION Message\n");
+        m2ap_eNB_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                             &received_msg->ittiMsg.sctp_new_association_ind);
+        break;
+
+      case SCTP_DATA_IND:
+	LOG_I(M2AP,"eNB Received SCTP_DATA_IND Message\n");
+        m2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                      &received_msg->ittiMsg.sctp_data_ind);
+        break;
+
+      default:
+        M2AP_ERROR("eNB Received unhandled message: %d:%s\n",
+                   ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
+        break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    received_msg = NULL;
+  }
+
+  return NULL;
+}
+
+#include "common/config/config_userapi.h"
+
+int is_m2ap_eNB_enabled(void)
+{
+  static volatile int config_loaded = 0;
+  static volatile int enabled = 0;
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+  if (pthread_mutex_lock(&mutex)) goto mutex_error;
+
+  if (config_loaded) {
+    if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+    return enabled;
+  }
+
+  char *enable_m2 = NULL;
+  paramdef_t p[] = {
+   { "enable_enb_m2", "yes/no", 0, strptr:&enable_m2, defstrval:"", TYPE_STRING, 0 }
+  };
+
+  /* TODO: do it per module - we check only first eNB */
+  config_get(p, sizeof(p)/sizeof(paramdef_t), "eNBs.[0]");
+  if (enable_m2 != NULL && strcmp(enable_m2, "yes") == 0)
+    enabled = 1;
+
+  config_loaded = 1;
+
+  if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+
+  return enabled;
+
+mutex_error:
+  LOG_E(M2AP, "mutex error\n");
+  exit(1);
+}
diff --git a/openair2/M2AP/m2ap_eNB.h b/openair2/M2AP/m2ap_eNB.h
new file mode 100644
index 0000000000000000000000000000000000000000..608da07e7e1ca72ab0b5e43e20fa999b40225568
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB.h
+ * \brief m2ap tasks for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+/** @defgroup _m2ap_impl_ M2AP Layer Reference Implementation
+ * @ingroup _ref_implementation_
+ * @{
+ */
+
+#ifndef M2AP_ENB_H_
+#define M2AP_ENB_H_
+
+#include "m2ap_eNB_defs.h"
+
+
+int m2ap_eNB_init_sctp (m2ap_eNB_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t enb_port_for_M2C);
+
+void *m2ap_eNB_task(void *arg);
+
+int is_m2ap_eNB_enabled(void);
+
+#endif /* M2AP_ENB_H_ */
+
+/**
+ * @}
+ */
diff --git a/openair2/M2AP/m2ap_eNB_defs.h b/openair2/M2AP/m2ap_eNB_defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..b8f7e4b3c61600651e2b2f0ceeb520d23b8357a7
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_defs.h
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_defs.h
+ * \brief m2ap struct definitions for eNB
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "queue.h"
+#include "tree.h"
+
+#include "sctp_eNB_defs.h"
+
+#include "m2ap_ids.h" //looks X2AP specific for HO
+#include "m2ap_timers.h"
+
+#ifndef M2AP_ENB_DEFS_H_
+#define M2AP_ENB_DEFS_H_
+
+#define M2AP_ENB_NAME_LENGTH_MAX    (150)
+
+typedef enum {
+  /* Disconnected state: initial state for any association. */
+  M2AP_ENB_STATE_DISCONNECTED = 0x0,
+
+  /* State waiting for m2 Setup response message if the target eNB accepts or
+   * M2 Setup failure if rejects the eNB.
+   */
+  M2AP_ENB_STATE_WAITING     = 0x1,
+
+  /* The eNB is successfully connected to another eNB. */
+  M2AP_ENB_STATE_CONNECTED   = 0x2,
+
+  /* M2AP is ready, and the eNB is successfully connected to another eNB. */
+  M2AP_ENB_STATE_READY             = 0x3,
+
+  M2AP_ENB_STATE_OVERLOAD          = 0x4,
+
+  M2AP_ENB_STATE_RESETTING         = 0x5,
+
+  /* Max number of states available */
+  M2AP_ENB_STATE_MAX,
+} m2ap_eNB_state_t;
+
+/* Served PLMN identity element */
+/*struct plmn_identity_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+  STAILQ_ENTRY(plmn_identity_s) next;
+};*/
+
+/* Served group id element */
+/*struct served_group_id_s {
+  uint16_t enb_group_id;
+  STAILQ_ENTRY(served_group_id_s) next;
+};*/
+
+/* Served enn code for a particular eNB */
+/*struct enb_code_s {
+  uint8_t enb_code;
+  STAILQ_ENTRY(enb_code_s) next;
+};*/
+
+struct m2ap_eNB_instance_s;
+
+/* This structure describes association of a eNB to another eNB */
+typedef struct m2ap_eNB_data_s {
+  /* eNB descriptors tree, ordered by sctp assoc id */
+  RB_ENTRY(m2ap_eNB_data_s) entry;
+
+  /* This is the optional name provided by the MME */
+  char *eNB_name;
+
+  /*  target eNB ID */
+  uint32_t eNB_id;
+
+  /* Current eNB load information (if any). */
+  //m2ap_load_state_t overload_state;
+
+  /* Current eNB->eNB M2AP association state */
+  m2ap_eNB_state_t state;
+
+  /* Next usable stream for UE signalling */
+  int32_t nextstream;
+
+  /* Number of input/ouput streams */
+  uint16_t in_streams;
+  uint16_t out_streams;
+
+  /* Connexion id used between SCTP/M2AP */
+  uint16_t cnx_id;
+
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* Nid cells */
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* Only meaningfull in virtual mode */
+  struct m2ap_eNB_instance_s *m2ap_eNB_instance;
+} m2ap_eNB_data_t;
+
+typedef struct m2ap_eNB_instance_s {
+  /* used in simulation to store multiple eNB instances*/
+  STAILQ_ENTRY(m2ap_eNB_instance_s) m2ap_eNB_entries;
+
+  /* Number of target eNBs requested by eNB (tree size) */
+  uint32_t m2_target_enb_nb;
+  /* Number of target eNBs for which association is pending */
+  uint32_t m2_target_enb_pending_nb;
+  /* Number of target eNB successfully associated to eNB */
+  uint32_t m2_target_enb_associated_nb;
+  /* Tree of M2AP eNB associations ordered by association ID */
+  RB_HEAD(m2ap_enb_map, m2ap_eNB_data_s) m2ap_enb_head;
+
+  /* Tree of UE ordered by eNB_ue_m2ap_id's */
+  //  RB_HEAD(m2ap_ue_map, m2ap_eNB_ue_context_s) m2ap_ue_head;
+
+  /* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
+  instance_t instance;
+
+  /* Displayable name of eNB */
+  char *eNB_name;
+
+  /* Unique eNB_id to identify the eNB within EPC.
+   * In our case the eNB is a macro eNB so the id will be 20 bits long.
+   * For Home eNB id, this field should be 28 bits long.
+   */
+  uint32_t eNB_id;
+  /* The type of the cell */
+  cell_type_t cell_type;
+
+  //uint16_t num_mbms_service_area_list;
+  //uint16_t mbms_service_area_list[8];
+
+  struct{
+          uint16_t mbsfn_sync_area;
+          uint16_t mbms_service_area_list[8];
+          uint16_t num_mbms_service_area_list;
+  }mbms_configuration_data_list[8];
+  uint8_t num_mbms_configuration_data_list;
+
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t  mcc;
+  uint16_t  mnc;
+  uint8_t   mnc_digit_length;
+
+  /* CC params */
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int16_t                 N_RB_DL[MAX_NUM_CCs];
+  lte_frame_type_t        frame_type[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
+  net_ip_address_t target_mce_m2_ip_address[M2AP_MAX_NB_ENB_IP_ADDRESS];
+  uint8_t          nb_m2;
+  net_ip_address_t enb_m2_ip_address;
+  uint16_t         sctp_in_streams;
+  uint16_t         sctp_out_streams;
+  uint32_t         enb_port_for_M2C;
+  int              multi_sd;
+
+  m2ap_id_manager  id_manager;
+  m2ap_timers_t    timers;
+} m2ap_eNB_instance_t;
+
+typedef struct {
+  /* List of served eNBs
+   * Only used for virtual mode
+   */
+  STAILQ_HEAD(m2ap_eNB_instances_head_s, m2ap_eNB_instance_s) m2ap_eNB_instances_head;
+  /* Nb of registered eNBs */
+  uint8_t nb_registered_eNBs;
+
+  /* Generate a unique connexion id used between M2AP and SCTP */
+  uint16_t global_cnx_id;
+} m2ap_eNB_internal_data_t;
+
+int m2ap_eNB_compare_assoc_id(struct m2ap_eNB_data_s *p1, struct m2ap_eNB_data_s *p2);
+
+/* Generate the tree management functions */
+struct m2ap_eNB_map;
+struct m2ap_eNB_data_s;
+RB_PROTOTYPE(m2ap_eNB_map, m2ap_eNB_data_s, entry, m2ap_eNB_compare_assoc_id);
+
+
+#endif /* M2AP_ENB_DEFS_H_ */
diff --git a/openair2/M2AP/m2ap_eNB_generate_messages.c b/openair2/M2AP/m2ap_eNB_generate_messages.c
new file mode 100644
index 0000000000000000000000000000000000000000..b6c821e1cee29b730894835219e06aef00bc8a61
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_generate_messages.c
@@ -0,0 +1,808 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_generate_messages.c
+ * \brief m2ap procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+//#include "M2AP_LastVisitedCell-Item.h"
+
+#include "m2ap_common.h"
+#include "m2ap_eNB.h"
+#include "m2ap_eNB_generate_messages.h"
+#include "m2ap_encoder.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+#include "m2ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+//int m2ap_eNB_generate_m2_setup_request(
+//  m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p)
+//{
+//  module_id_t enb_mod_idP=0;
+//  module_id_t du_mod_idP=0;
+//
+//  M2AP_M2AP_PDU_t          pdu;
+//  M2AP_M2SetupRequest_t    *out;
+//  M2AP_M2SetupRequest_Ies_t *ie;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       i = 0;
+//  int       j = 0;
+//
+//  /* Create */
+//  /* 0. pdu Type */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+//  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_M2SetupRequest;
+//  out = &pdu.choice.initiatingMessage.value.choice.M2SetupRequest;
+//
+//  /* mandatory */
+//  /* c1. GlobalENB_ID (integer value) */
+//  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+//  ie->id                        = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+//  ie->criticality               = M2AP_Criticality_reject;
+//  ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_GlobalENB_ID;
+//  //ie->value.choice.GlobalENB_ID.eNB_ID = 1;//M2AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                  &ie->value.choice.GlobalENB_ID.pLMN_Identity);
+//  ie->value.choice.GlobalENB_ID.eNB_ID.present = M2AP_ENB_ID_PR_macro_eNB_ID;
+//  MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
+//                           &ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
+//  M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
+//          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
+//          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
+//          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  ///* mandatory */
+//  ///* c2. GNB_eNB_ID (integrer value) */
+//  //ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+//  //ie->id                        = M2AP_ProtocolIE_ID_id_gNB_eNB_ID;
+//  //ie->criticality               = M2AP_Criticality_reject;
+//  //ie->value.present             = M2AP_M2SetupRequestIEs__value_PR_GNB_eNB_ID;
+//  //asn_int642INTEGER(&ie->value.choice.GNB_eNB_ID, f1ap_du_data->gNB_eNB_id);
+//  //ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  /* c3. ENBname */
+//  if (m2ap_eNB_data_p->eNB_name != NULL) {
+//    ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+//    ie->id                        = M2AP_ProtocolIE_ID_id_ENBname;
+//    ie->criticality               = M2AP_Criticality_ignore;
+//    ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_ENBname;
+//    //OCTET_STRING_fromBuf(&ie->value.choice.ENB_Name, m2ap_eNB_data_p->eNB_name,
+//                         //strlen(m2ap_eNB_data_p->eNB_name));
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* mandatory */
+//  /* c4. serverd cells list */
+//  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+//  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_List;
+//  ie->criticality               = M2AP_Criticality_reject;
+//  ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_ENB_MBMS_Configuration_data_List;
+//
+//  int num_mbms_available = 1;//m2ap_du_data->num_mbms_available;
+//  LOG_D(M2AP, "num_mbms_available = %d \n", num_mbms_available);
+//
+// for (i=0;
+//       i<num_mbms_available;
+//       i++) {
+//        /* mandatory */
+//        /* 4.1 serverd cells item */
+//
+//        M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *mbms_configuration_data_list_item_ies;
+//        mbms_configuration_data_list_item_ies = (M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *)calloc(1, sizeof(M2AP_ENB_MBMS_Configuration_data_ItemIEs_t));
+//        mbms_configuration_data_list_item_ies->id = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_Item;
+//        mbms_configuration_data_list_item_ies->criticality = M2AP_Criticality_reject;
+//        mbms_configuration_data_list_item_ies->value.present = M2AP_ENB_MBMS_Configuration_data_ItemIEs__value_PR_ENB_MBMS_Configuration_data_Item;
+//
+//	M2AP_ENB_MBMS_Configuration_data_Item_t *mbms_configuration_data_item;
+//	mbms_configuration_data_item = &mbms_configuration_data_list_item_ies->value.choice.ENB_MBMS_Configuration_data_Item;
+//	{
+//		MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                  &mbms_configuration_data_item->eCGI.pLMN_Identity);
+//        	MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
+//                                   &mbms_configuration_data_item->eCGI.eUTRANcellIdentifier);
+//		M2AP_MBMS_Service_Area_t * mbms_service_area;
+//		mbms_service_area = (M2AP_MBMS_Service_Area_t*)calloc(1,sizeof(M2AP_MBMS_Service_Area_t));
+//		ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area);
+//
+//
+//	}
+//
+//
+//        //M2AP_ENB_MBMS_Configuration_data_Item_t mbms_configuration_data_item;
+//        //memset((void *)&mbms_configuration_data_item, 0, sizeof(M2AP_ENB_MBMS_Configuration_data_Item_t));
+//	
+//	//M2AP_ECGI_t      eCGI;
+//		//M2AP_PLMN_Identity_t     pLMN_Identity;
+//		//M2AP_EUTRANCellIdentifier_t      eUTRANcellIdentifier
+//	//M2AP_MBSFN_SynchronisationArea_ID_t      mbsfnSynchronisationArea;
+//	//M2AP_MBMS_Service_Area_ID_List_t         mbmsServiceAreaList;
+//
+//
+//	ASN_SEQUENCE_ADD(&ie->value.choice.ENB_MBMS_Configuration_data_List.list,mbms_configuration_data_list_item_ies);
+//
+// }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  LOG_W(M2AP,"m2ap_eNB_data_p->assoc_id %d\n",m2ap_eNB_data_p->assoc_id);
+//  /* encode */
+//  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    LOG_E(M2AP, "Failed to encode M2 setup request\n");
+//    return -1;
+//  }
+//
+// 
+//  LOG_W(M2AP,"pdu.present %d\n",pdu.present);
+// // MSC_LOG_TX_MESSAGE(
+// // MSC_M2AP_eNB,
+// // MSC_M2AP_MCE,
+// // (const char *)buffer,
+// // len,
+// // MSC_AS_TIME_FMT" M2_SETUP_REQUEST initiatingMessage MCEname %s",
+// // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+// // m2ap_eNB_data_p->ENBname);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p, m2ap_eNB_data_p->assoc_id, buffer, len, 0);
+//
+//  return 0;
+//
+//
+//}
+
+//int m2ap_MCE_generate_m2_setup_response(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p)
+//{
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_M2SetupResponse_t              *out;
+//  M2AP_M2SetupResponse_Ies_t          *ie;
+//  //M2AP_PLMN_Identity_t                *plmn;
+//  //ServedCells__Member                 *servedCellMember;
+//  //M2AP_GU_Group_ID_t                  *gu;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  /* Prepare the M2AP message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_M2SetupResponse;
+//  out = &pdu.choice.successfulOutcome.value.choice.M2SetupResponse;
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GlobalENB_ID;
+//  //MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//  //                  &ie->value.choice.GlobalENB_ID.pLMN_Identity);
+//  //ie->value.choice.GlobalENB_ID.eNB_ID.present = M2AP_ENB_ID_PR_macro_eNB_ID;
+//  //MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
+//  //                           &ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
+//  //M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
+//  //          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
+//  //          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
+//  //          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_ServedCells;
+//  //{
+//  //  for (int i = 0; i<instance_p->num_cc; i++){
+//  //    servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
+//  //    {
+//  //      servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
+//
+//  //      MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//  //                    &servedCellMember->servedCellInfo.cellId.pLMN_Identity);
+//  //      MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
+//  //                                 &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+//
+//  //      INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+//  //      plmn = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_PLMN_Identity_t));
+//  //      {
+//  //        MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
+//  //        ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
+//  //      }
+//
+//  //      if (instance_p->frame_type[i] == FDD) {
+//  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = M2AP_EUTRA_Mode_Info_PR_fDD;
+//  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
+//  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
+//  //        switch (instance_p->N_RB_DL[i]) {
+//  //          case 6:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+//  //            break;
+//  //          case 15:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+//  //            break;
+//  //          case 25:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+//  //            break;
+//  //          case 50:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+//  //            break;
+//  //          case 75:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+//  //            break;
+//  //          case 100:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+//  //            break;
+//  //          default:
+//  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+//  //            break;
+//  //        }
+//  //      }
+//  //      else {
+//  //        AssertFatal(0,"M2Setupresponse not supported for TDD!");
+//  //      }
+//  //    }
+//  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+//  //  }
+//  //}
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GUGroupIDList;
+//  //{
+//  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_GU_Group_ID_t));
+//  //  {
+//  //    MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//  //                  &gu->pLMN_Identity);
+//  //    //@TODO: consider to update this value
+//  //    INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
+//  //  }
+//  //  ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
+//  //}
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode M2 setup response\n");
+//    return -1;
+//  }
+//
+//  m2ap_eNB_data_p->state = M2AP_ENB_STATE_READY;
+//
+//  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 M2Setup/successfulOutcome assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 0);
+//
+//  return ret;
+//}
+
+//int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+//                                       uint32_t assoc_id,
+//                                       M2AP_Cause_PR cause_type,
+//                                       long cause_value,
+//                                       long time_to_wait)
+//{
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_M2SetupFailure_t              *out;
+//  M2AP_M2SetupFailure_Ies_t          *ie;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  /* Prepare the M2AP message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+//  pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+//  pdu.choice.unsuccessfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+//  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  //ie->criticality = M2AP_Criticality_ignore;
+//  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_Cause;
+//
+//  //m2ap_eNB_set_cause (&ie->value.choice.Cause, cause_type, cause_value);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional: consider to handle this later */
+//  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_TimeToWait;
+//  //ie->criticality = M2AP_Criticality_ignore;
+//  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_TimeToWait;
+//
+//  //if (time_to_wait > -1) {
+//  //  ie->value.choice.TimeToWait = time_to_wait;
+//  //}
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode M2 setup failure\n");
+//    return -1;
+//  }
+//
+//  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB,
+//  //                    MSC_M2AP_TARGET_ENB, NULL, 0,
+//  //                    "0 M2Setup/unsuccessfulOutcome  assoc_id %u cause %u value %u",
+//  //                    assoc_id, cause_type, cause_value);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
+//
+//  return ret;
+//}
+
+int m2ap_eNB_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value)
+{
+
+  DevAssert (cause_p != NULL);
+  cause_p->present = cause_type;
+
+  switch (cause_type) {
+  case M2AP_Cause_PR_radioNetwork:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_transport:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_protocol:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_misc:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+//int m2ap_eNB_generate_m2_handover_request (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id)
+//{
+//
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_HandoverRequest_t              *out;
+//  M2AP_HandoverRequest_IEs_t          *ie;
+//  M2AP_E_RABs_ToBeSetup_ItemIEs_t     *e_RABS_ToBeSetup_ItemIEs;
+//  M2AP_E_RABs_ToBeSetup_Item_t        *e_RABs_ToBeSetup_Item;
+//  M2AP_LastVisitedCell_Item_t         *lastVisitedCell_Item;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverRequest;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_Cause;
+//  ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetCell_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_ECGI;
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &ie->value.choice.ECGI.pLMN_Identity);
+//  MACRO_ENB_ID_TO_CELL_IDENTITY(m2ap_eNB_data_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_GUMMEI_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_GUMMEI;
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &ie->value.choice.GUMMEI.gU_Group_ID.pLMN_Identity);
+//  //@TODO: consider to update these values
+//  INT16_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
+//  MME_CODE_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_ContextInformation;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
+//  //@TODO: consider to update this value
+//  ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = m2ap_handover_req->mme_ue_s1ap_id;
+//
+//  KENB_STAR_TO_BIT_STRING(m2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
+//
+//  if (m2ap_handover_req->kenb_ncc >=0) { // Check this condition
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = m2ap_handover_req->kenb_ncc;
+//  }
+//  else {
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
+//  }
+//
+//  ENCRALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.encryption_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+//
+//  INTPROTALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.integrity_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
+//
+//  //@TODO: update with proper UEAMPR
+//  UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
+//  UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
+//  {
+//    for (int i=0;i<m2ap_handover_req->nb_e_rabs_tobesetup;i++) {
+//      e_RABS_ToBeSetup_ItemIEs = (M2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_ToBeSetup_ItemIEs_t));
+//      e_RABS_ToBeSetup_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
+//      e_RABS_ToBeSetup_ItemIEs->criticality = M2AP_Criticality_ignore;
+//      e_RABS_ToBeSetup_ItemIEs->value.present = M2AP_E_RABs_ToBeSetup_ItemIEs__value_PR_E_RABs_ToBeSetup_Item;
+//      e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
+//      {
+//        e_RABs_ToBeSetup_Item->e_RAB_ID = m2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = m2ap_handover_req->e_rab_param[i].qos.qci;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(m2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length/8);
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = m2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length%8;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf =
+//                        calloc(1,e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        memcpy (e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
+//                        m2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.buffer,
+//                        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        INT32_TO_OCTET_STRING(m2ap_handover_req->e_rabs_tobesetup[i].gtp_teid,&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID);
+//      }
+//      ASN_SEQUENCE_ADD(&ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list, e_RABS_ToBeSetup_ItemIEs);
+//    }
+//  }
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.UE_ContextInformation.rRC_Context, (char*) m2ap_handover_req->rrc_buffer, m2ap_handover_req->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_HistoryInformation;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
+//  //@TODO: consider to update this value
+//  {
+//   lastVisitedCell_Item = (M2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(M2AP_LastVisitedCell_Item_t));
+//   lastVisitedCell_Item->present = M2AP_LastVisitedCell_Item_PR_e_UTRAN_Cell;
+//   MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
+//   MACRO_ENB_ID_TO_CELL_IDENTITY(0, 0, &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
+//   lastVisitedCell_Item->choice.e_UTRAN_Cell.cellType.cell_Size = M2AP_Cell_Size_small;
+//   lastVisitedCell_Item->choice.e_UTRAN_Cell.time_UE_StayedInCell = 2;
+//   ASN_SEQUENCE_ADD(&ie->value.choice.UE_HistoryInformation.list, lastVisitedCell_Item);
+//  }
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover request\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_handover_request_ack (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack)
+//{
+//
+//  M2AP_M2AP_PDU_t                        pdu;
+//  M2AP_HandoverRequestAcknowledge_t      *out;
+//  M2AP_HandoverRequestAcknowledge_IEs_t  *ie;
+//  M2AP_E_RABs_Admitted_ItemIEs_t         *e_RABS_Admitted_ItemIEs;
+//  M2AP_E_RABs_Admitted_Item_t            *e_RABs_Admitted_Item;
+//  int                                    ue_id;
+//  int                                    id_source;
+//  int                                    id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id     = m2ap_handover_req_ack->m2_id_target;
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
+//  out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
+//
+//  {
+//      for (int i=0;i<m2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
+//        e_RABS_Admitted_ItemIEs = (M2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_Admitted_ItemIEs_t));
+//        e_RABS_Admitted_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
+//        e_RABS_Admitted_ItemIEs->criticality = M2AP_Criticality_ignore;
+//        e_RABS_Admitted_ItemIEs->value.present = M2AP_E_RABs_Admitted_ItemIEs__value_PR_E_RABs_Admitted_Item;
+//        e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
+//        {
+//          e_RABs_Admitted_Item->e_RAB_ID = m2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
+//        }
+//        ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_List.list, e_RABS_Admitted_ItemIEs);
+//      }
+//  }
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_TargeteNBtoSource_eNBTransparentContainer;
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.TargeteNBtoSource_eNBTransparentContainer, (char*) m2ap_handover_req_ack->rrc_buffer, m2ap_handover_req_ack->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover response\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_ue_context_release (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p, m2ap_ue_context_release_t *m2ap_ue_context_release)
+//{
+//
+//  M2AP_M2AP_PDU_t                pdu;
+//  M2AP_UEContextRelease_t        *out;
+//  M2AP_UEContextRelease_IEs_t    *ie;
+//  int                            ue_id;
+//  int                            id_source;
+//  int                            id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id = m2ap_find_id_from_rnti(&instance_p->id_manager, m2ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not find UE %x\n", m2ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP ue context relase message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_uEContextRelease;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_UEContextRelease;
+//  out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 UE Context Release\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_handover_cancel (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause)
+//{
+//  M2AP_M2AP_PDU_t              pdu;
+//  M2AP_HandoverCancel_t        *out;
+//  M2AP_HandoverCancel_IEs_t    *ie;
+//  int                          ue_id;
+//  int                          id_source;
+//  int                          id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id = m2_ue_id;
+//  id_source = ue_id;
+//  id_target = m2ap_id_get_id_target(&instance_p->id_manager, ue_id);
+//
+//  /* Prepare the M2AP handover cancel message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverCancel;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverCancel;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  if (id_target != -1) {
+//    ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//    ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//    ie->criticality = M2AP_Criticality_ignore;
+//    ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID_1;
+//    ie->value.choice.UE_M2AP_ID_1 = id_target;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_Cause;
+//  switch (cause) {
+//  case M2AP_T_RELOC_PREP_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_trelocprep_expiry;
+//    break;
+//  case M2AP_TX2_RELOC_OVERALL_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_tx2relocoverall_expiry;
+//    break;
+//  default:
+//    /* we can't come here */
+//    M2AP_ERROR("unhandled cancel cause\n");
+//    exit(1);
+//  }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 Handover Cancel\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
diff --git a/openair2/M2AP/m2ap_eNB_generate_messages.h b/openair2/M2AP/m2ap_eNB_generate_messages.h
new file mode 100644
index 0000000000000000000000000000000000000000..49247405f788d8e681ac928ff8117df846fe627f
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_generate_messages.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_generate_messages.h
+ * \brief m2ap procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_ENB_GENERATE_MESSAGES_H_
+#define M2AP_ENB_GENERATE_MESSAGES_H_
+
+#include "m2ap_eNB_defs.h"
+#include "m2ap_common.h"
+
+//int m2ap_eNB_generate_m2_setup_request(m2ap_eNB_instance_t *instance_p,
+//				       m2ap_eNB_data_t *m2ap_eNB_data_p);
+//
+//int m2ap_MCE_generate_m2_setup_response(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p);
+//
+/*int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait);*/
+
+int m2ap_eNB_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value);
+
+//int m2ap_eNB_generate_m2_handover_request (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id);
+//
+//int m2ap_eNB_generate_m2_handover_request_ack (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack);
+//
+//int m2ap_eNB_generate_m2_ue_context_release (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                             m2ap_ue_context_release_t *m2ap_ue_context_release);
+//
+//int m2ap_eNB_generate_m2_handover_cancel (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause);
+
+#endif /*  M2AP_ENB_GENERATE_MESSAGES_H_ */
diff --git a/openair2/M2AP/m2ap_eNB_handler.c b/openair2/M2AP/m2ap_eNB_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..fe0059f0a5a424d2d0ad00ff20371c61e2e52c64
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_handler.c
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_handler.c
+ * \brief m2ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m2ap_common.h"
+#include "m2ap_eNB_defs.h"
+#include "m2ap_eNB_handler.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+#include "m2ap_eNB_management_procedures.h"
+#include "m2ap_eNB_generate_messages.h"
+
+//#include "m2ap_MCE_interface_management.h"
+#include "m2ap_eNB_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m2ap_eNB_message_decoded_callback m2ap_eNB_messages_callback[][3] = {
+  { eNB_handle_MBMS_SESSION_START_REQUEST, 0, 0 }, /* MBMSSessionStart  */
+  { eNB_handle_MBMS_SESSION_STOP_REQUEST, 0, 0 }, /* MBMSSessionStop */
+  { eNB_handle_MBMS_SCHEDULING_INFORMATION, 0, 0 }, /* MBMSSchedulingInformation */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { 0,eNB_handle_M2_SETUP_RESPONSE,eNB_handle_M2_SETUP_FAILURE }, /* M2 Setup */
+  { 0, 0, 0 }, /* eNBConfigurationUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { 0, 0, 0 }, /* privateMessage */
+  { 0, 0, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MBMSServiceCounting */
+  { 0, 0, 0 }, /* MBMSServiceCountingResultReport */
+  { 0, 0, 0 } /* MBMSOverloadNotification */
+};
+
+static char *m2ap_direction2String(int m2ap_dir) {
+static char *m2ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m2ap_direction_String[m2ap_dir]);
+}
+
+
+int m2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M2AP_M2AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  if (m2ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M2AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m2ap_eNB_messages_callback) / (3 * sizeof(
+        m2ap_message_decoded_callback))
+      || (pdu.present > M2AP_M2AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M2AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
+               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m2ap_eNB_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M2AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m2ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M2AP, "Calling handler with instance %d\n",instance);
+  ret = (*m2ap_eNB_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair2/M2AP/m2ap_eNB_handler.h b/openair2/M2AP/m2ap_eNB_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea4231a6e3c2c55b5fb107c59d67324fb32c2bf7
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_handler.h
+ * \brief m2ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_ENB_HANDLERS_H_
+#define M2AP_ENB_HANDLERS_H_
+
+#include "m2ap_eNB_defs.h"
+
+//void m2ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+int m2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+//int m2ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            //const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M2AP_ENB_HANDLERS_H_ */
diff --git a/openair2/M2AP/m2ap_eNB_interface_management.c b/openair2/M2AP/m2ap_eNB_interface_management.c
new file mode 100644
index 0000000000000000000000000000000000000000..95b83720258dead917526f44f08b9b9f242f8bf7
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_interface_management.c
@@ -0,0 +1,1319 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_interface_management.c
+ * \brief m2ap interface management for MCE
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech, Spain
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "intertask_interface.h"
+
+#include "m2ap_common.h"
+#include "m2ap_eNB.h"
+#include "m2ap_eNB_generate_messages.h"
+#include "m2ap_encoder.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+#include "m2ap_eNB_interface_management.h"
+
+
+#include "m2ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+#include "M2AP_MBSFN-Area-Configuration-List.h" 
+
+//#include "m2ap_common.h"
+//#include "m2ap_encoder.h"
+//#include "m2ap_decoder.h"
+//#include "m2ap_itti_messaging.h"
+//#include "m2ap_eNB_interface_management.h"
+//#include "assertions.h"
+
+extern m2ap_setup_req_t *m2ap_enb_data_g;
+
+
+//extern m2ap_setup_req_t *m2ap_mce_data_from_enb;
+int eNB_handle_MBMS_SCHEDULING_INFORMATION(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M2AP_M2AP_PDU_t *pdu){
+  LOG_D(M2AP, "eNB_handle_MBMS_SCHEDULING_INFORMATION assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p/*,*message_p2*/;
+  M2AP_MbmsSchedulingInformation_t *container;
+  M2AP_MbmsSchedulingInformation_Ies_t   *ie;
+  int i = 0;
+  int j = 0;
+  int k = 0;
+  //int m = 0;
+
+  DevAssert(pdu != NULL);
+
+  container = &pdu->choice.initiatingMessage.value.choice.MbmsSchedulingInformation;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS scheduling information on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SCHEDULING_INFORMATION);
+  //message_p2  = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SCHEDULING_INFORMATION);
+
+
+
+
+
+  M2AP_FIND_PROTOCOLIE_BY_ID(M2AP_MbmsSchedulingInformation_Ies_t, ie, container,M2AP_ProtocolIE_ID_id_MCCH_Update_Time ,true);
+  //printf("id %d\n",ie->id);
+
+  M2AP_FIND_PROTOCOLIE_BY_ID(M2AP_MbmsSchedulingInformation_Ies_t, ie, container,M2AP_ProtocolIE_ID_id_MBSFN_Area_Configuration_List ,true);
+
+  if(ie){
+
+	  //printf("id %d\n",ie->id);
+	  //printf("MBSFN_Area_Configuration_List  %p\n",ie->value.choice.MBSFN_Area_Configuration_List.list.array);
+	  /*M2AP_MBSFN_Area_Configuration_Item_t  * kk  = &ie->value.choice.MBSFN_Area_Configuration_List.list.array[0];
+	  printf("M2AP_MBSFN_Area_Configuration_Item %p\n",kk);
+	  printf("M2AP_MBSFN_Area_Configuration_Item %d\n",kk->id);*/
+
+	  const asn_anonymous_sequence_ *list = _A_CSEQUENCE_FROM_VOID((void*)&ie->value.choice.MBSFN_Area_Configuration_List);
+	  if(list->count > 0 ){
+		M2AP_MBMS_SCHEDULING_INFORMATION(message_p).num_mbms_area_config_list = list->count;
+	  }
+	  for(i=0; i < list->count; i++ ){
+		  void * memb_ptr = list->array[i];
+		  //printf("%p %d\n", memb_ptr,list->count);
+		  const asn_anonymous_sequence_ *list1 = _A_CSEQUENCE_FROM_VOID((void*)memb_ptr);
+		  void * memb_ptr1 = list1->array[0];
+		  //printf("%p %d\n", memb_ptr1,list1->count);
+		  void * memb_ptr2 = list1->array[1];
+		  void * memb_ptr3 = list1->array[2];
+		  void * memb_ptr4 = list1->array[3];
+
+		  //printf("%lu\n", ((M2AP_MBSFN_Area_Configuration_Item_t*)memb_ptr1)->id);
+		  M2AP_MBSFN_Area_Configuration_Item_t * m2ap_mbsfn_area_configuration_item = (M2AP_MBSFN_Area_Configuration_Item_t*)memb_ptr1;
+		  //printf("count %d\n",m2ap_mbsfn_area_configuration_item->value.choice.PMCH_Configuration_List.list.count);
+		  if(m2ap_mbsfn_area_configuration_item->value.choice.PMCH_Configuration_List.list.count > 0){
+			M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].num_pmch_config_list = m2ap_mbsfn_area_configuration_item->value.choice.PMCH_Configuration_List.list.count;
+		  }
+		  for(j=0; j < m2ap_mbsfn_area_configuration_item->value.choice.PMCH_Configuration_List.list.count; j++){
+			  M2AP_PMCH_Configuration_Item_t * m2ap_pmchconfiguration_item =&(((M2AP_PMCH_Configuration_ItemIEs_t*)m2ap_mbsfn_area_configuration_item->value.choice.PMCH_Configuration_List.list.array[j])->value.choice.PMCH_Configuration_Item);
+			  M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].data_mcs = m2ap_pmchconfiguration_item->pmch_Configuration.dataMCS;
+			  M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mch_scheduling_period = m2ap_pmchconfiguration_item->pmch_Configuration.mchSchedulingPeriod;
+			  M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].allocated_sf_end = m2ap_pmchconfiguration_item->pmch_Configuration.allocatedSubframesEnd;
+			  //printf("dataMCS %lu\n",m2ap_pmchconfiguration_item->pmch_Configuration.dataMCS);
+			  //printf("allocatedSubframesEnd %lu\n",m2ap_pmchconfiguration_item->pmch_Configuration.allocatedSubframesEnd);
+			  if(m2ap_pmchconfiguration_item->mbms_Session_List.list.count > 0){
+				M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].num_mbms_session_list = m2ap_pmchconfiguration_item->mbms_Session_List.list.count;
+			  }
+			  for(k=0; k < m2ap_pmchconfiguration_item->mbms_Session_List.list.count; k++){
+				//long mnc,mcc,mnc_length;
+				PLMNID_TO_MCC_MNC(&m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->tmgi.pLMNidentity,
+				M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mcc,
+				M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mnc,
+				M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mnc_length);
+				//char buf[4];
+				
+				//BUFFER_TO_INT32(buf,);
+				M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id = ((m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->tmgi.serviceID.buf[0]<<16) | (m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->tmgi.serviceID.buf[1]<<8) | (m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->tmgi.serviceID.buf[2])); //
+				M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid = m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->lcid; //*/
+				//LOG_E(M2AP,"buf[0]:%d buf[1]:%d buf[2]:%d\n",m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->tmgi.serviceID.buf[0],m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->tmgi.serviceID.buf[1],m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->tmgi.serviceID.buf[2]);
+			  }
+		  }
+
+		  //printf("%lu\n", ((M2AP_MBSFN_Area_Configuration_Item_t*)memb_ptr2)->id);
+		  M2AP_MBSFN_Area_Configuration_Item_t * m2ap_mbsfn_area_configuration_item2 = (M2AP_MBSFN_Area_Configuration_Item_t*)memb_ptr2;
+		  //printf("count %d\n",m2ap_mbsfn_area_configuration_item2->value.choice.MBSFN_Subframe_ConfigurationList.list.count);
+		  if(m2ap_mbsfn_area_configuration_item2->value.choice.MBSFN_Subframe_ConfigurationList.list.count > 0){
+			M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].num_mbms_sf_config_list = m2ap_mbsfn_area_configuration_item2->value.choice.MBSFN_Subframe_ConfigurationList.list.count;
+		  }
+		  for(j=0; j < m2ap_mbsfn_area_configuration_item2->value.choice.MBSFN_Subframe_ConfigurationList.list.count; j++){
+			  M2AP_MBSFN_Subframe_Configuration_t * m2ap_mbsfn_sf_configuration = &(((M2AP_MBSFN_Subframe_ConfigurationItem_t*)m2ap_mbsfn_area_configuration_item2->value.choice.MBSFN_Subframe_ConfigurationList.list.array[j])->value.choice.MBSFN_Subframe_Configuration);
+			  //printf("radioframe_allocation_period %lu\n",m2ap_mbsfn_sf_configuration->radioframeAllocationPeriod);
+			  //printf("radioframe_allocation_offset %lu\n",m2ap_mbsfn_sf_configuration->radioframeAllocationOffset);
+			  M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_period = m2ap_mbsfn_sf_configuration->radioframeAllocationPeriod;
+			  M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_offset = m2ap_mbsfn_sf_configuration->radioframeAllocationOffset;
+			  if( m2ap_mbsfn_sf_configuration->subframeAllocation.present == M2AP_MBSFN_Subframe_Configuration__subframeAllocation_PR_fourFrames ) {
+				M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation = m2ap_mbsfn_sf_configuration->subframeAllocation.choice.oneFrame.buf[0] | (m2ap_mbsfn_sf_configuration->subframeAllocation.choice.oneFrame.buf[1]<<8) | (m2ap_mbsfn_sf_configuration->subframeAllocation.choice.oneFrame.buf[0]<<16);
+			  }else{
+				M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation = (m2ap_mbsfn_sf_configuration->subframeAllocation.choice.oneFrame.buf[0] >> 2) & 0x3F;
+			  }
+                  }
+		
+
+		  //printf("%lu\n", ((M2AP_MBSFN_Area_Configuration_Item_t*)memb_ptr3)->id);
+		  M2AP_MBSFN_Area_Configuration_Item_t * m2ap_mbsfn_area_configuration_item3 = (M2AP_MBSFN_Area_Configuration_Item_t*)memb_ptr3;
+		  //printf("count %d\n",m2ap_mbsfn_area_configuration_item2->value.choice.MBSFN_Subframe_ConfigurationList.list.count);
+		  //printf("Common_Subframe_Allocation_Period %lu\n",m2ap_mbsfn_area_configuration_item3->value.choice.Common_Subframe_Allocation_Period);
+		  M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].common_sf_allocation_period = m2ap_mbsfn_area_configuration_item3->value.choice.Common_Subframe_Allocation_Period;
+
+		  //printf("%lu\n", ((M2AP_MBSFN_Area_Configuration_Item_t*)memb_ptr4)->id);
+		  M2AP_MBSFN_Area_Configuration_Item_t * m2ap_mbsfn_area_configuration_item4 = (M2AP_MBSFN_Area_Configuration_Item_t*)memb_ptr4;
+		  //printf("MBMS_Area_ID %lu\n",m2ap_mbsfn_area_configuration_item4->value.choice.MBSFN_Area_ID);
+		  M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_area_id = m2ap_mbsfn_area_configuration_item4->value.choice.MBSFN_Area_ID;
+	  } 
+	
+
+	  //const asn_anonymous_sequence_ *list3 = _A_CSEQUENCE_FROM_VOID((void*)memb_ptr2);
+	  //void * memb_ptr3 = list3->array[0];
+	  //printf("%p\n", memb_ptr3);
+
+
+
+
+	  //xer_fprint(stdout, &asn_DEF_M2AP_MBSFN_Area_Configuration_List,  &ie->value.choice.MBSFN_Area_Configuration_List);
+	
+  }
+  
+  itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+  return 0;
+  
+}
+int eNB_send_MBMS_SCHEDULING_INFORMATION_RESPONSE(instance_t instance, m2ap_mbms_scheduling_information_resp_t * m2ap_mbms_scheduling_information_resp){
+//	module_id_t mce_mod_idP;
+  //module_id_t enb_mod_idP;
+
+  // This should be fixed
+ // enb_mod_idP = (module_id_t)0;
+ // mce_mod_idP  = (module_id_t)0;
+
+  M2AP_M2AP_PDU_t           pdu;
+  //M2AP_MbmsSchedulingInformationResponse_t    *out;
+  //M2AP_MbmsSchedulingInformationResponse_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M2AP_SuccessfulOutcome_t *)calloc(1, sizeof(M2AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_mbmsSchedulingInformation;
+  pdu.choice.successfulOutcome.criticality   = M2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_MbmsSchedulingInformationResponse;
+  //out = &pdu.choice.successfulOutcome.value.choice.MbmsSchedulingInformationResponse;
+  
+
+//  /* mandatory */
+//  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+//  ie = (M2AP_MbmsSchedulingInformationResponse_Ies_t *)calloc(1, sizeof(M2AP_MbmsSchedulingInformationResponse_Ies_t));
+//  ie->id                        = M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID;
+//  ie->criticality               = M2AP_Criticality_reject;
+//  ie->value.present             = M2AP_MbmsSchedulingInformationResponse_Ies__value_PR_MCE_MBMS_M2AP_ID;
+//  //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+// /* mandatory */
+//  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+//  ie = (M2AP_SessionStartResponse_Ies_t *)calloc(1, sizeof(M2AP_SessionStartResponse_Ies_t));
+//  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID;
+//  ie->criticality               = M2AP_Criticality_reject;
+//  ie->value.present             = M2AP_MbmsSchedulingInformationResponse_Ies__value_PR_ENB_MBMS_M2AP_ID;
+//  //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 SessionStart Response\n");
+    return -1;
+  }
+
+
+  LOG_D(M2AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M2AP_eNB,
+ // MSC_M2AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M2_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m2ap_eNB_data_p->ENBname);
+
+  m2ap_eNB_itti_send_sctp_data_req(instance, m2ap_enb_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+
+
+
+
+int eNB_handle_MBMS_SESSION_START_REQUEST(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M2AP_M2AP_PDU_t *pdu){
+  LOG_D(M2AP, "eNB_handle_MBMS_SESSION_START_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M2AP_SessionStartRequest_t              *container;
+  //M2AP_SessionStartRequest_Ies_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.SessionStartRequest;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SESSION_START_REQ);
+
+
+  itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+//  if(1){
+//	eNB_send_MBMS_SESSION_START_RESPONSE(instance,NULL);
+//  }else
+//	eNB_send_MBMS_SESSION_START_FAILURE(instance,NULL);
+  return 0;
+  
+}
+
+int eNB_send_MBMS_SESSION_START_RESPONSE(instance_t instance, m2ap_session_start_resp_t * m2ap_session_start_resp){
+//	module_id_t mce_mod_idP;
+//  module_id_t enb_mod_idP;
+
+  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+
+  M2AP_M2AP_PDU_t           pdu;
+  M2AP_SessionStartResponse_t    *out;
+  M2AP_SessionStartResponse_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M2AP_SuccessfulOutcome_t *)calloc(1, sizeof(M2AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_sessionStart;
+  pdu.choice.successfulOutcome.criticality   = M2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_SessionStartResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.SessionStartResponse;
+  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+  ie = (M2AP_SessionStartResponse_Ies_t *)calloc(1, sizeof(M2AP_SessionStartResponse_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStartResponse_Ies__value_PR_MCE_MBMS_M2AP_ID;
+  //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+  ie = (M2AP_SessionStartResponse_Ies_t *)calloc(1, sizeof(M2AP_SessionStartResponse_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStartResponse_Ies__value_PR_ENB_MBMS_M2AP_ID;
+  //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 SessionStart Response\n");
+    return -1;
+  }
+
+
+  LOG_D(M2AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M2AP_eNB,
+ // MSC_M2AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M2_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m2ap_eNB_data_p->ENBname);
+
+  m2ap_eNB_itti_send_sctp_data_req(instance, m2ap_enb_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+
+
+int eNB_send_MBMS_SESSION_START_FAILURE(instance_t instance, m2ap_session_start_failure_t * m2ap_session_start_failure){
+  //module_id_t enb_mod_idP;
+  //module_id_t mce_mod_idP;
+
+  // This should be fixed
+  //enb_mod_idP = (module_id_t)0;
+ // mce_mod_idP  = (module_id_t)0;
+
+  M2AP_M2AP_PDU_t           pdu;
+  M2AP_SessionStartFailure_t    *out;
+  M2AP_SessionStartFailure_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+  //pdu.choice.unsuccessfulOutcome = (M2AP_UnsuccessfulOutcome_t *)calloc(1, sizeof(M2AP_UnsuccessfulOutcome_t));
+  pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_sessionStart;
+  pdu.choice.unsuccessfulOutcome.criticality   = M2AP_Criticality_reject;
+  pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_SessionStartFailure;
+  out = &pdu.choice.unsuccessfulOutcome.value.choice.SessionStartFailure;
+
+  /* mandatory */
+  /* c1. Transaction ID (integer value)*/
+ // ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+ // ie->id                        = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+ // ie->criticality               = M2AP_Criticality_reject;
+ // ie->value.present             = M2AP_M2SetupFailure_Ies__value_PR_GlobalENB_ID;
+ // ie->value.choice.GlobalENB_ID = M2AP_get_next_transaction_identifier(enb_mod_idP, mce_mod_idP);
+ // ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+  ie = (M2AP_SessionStartFailure_Ies_t *)calloc(1, sizeof(M2AP_SessionStartFailure_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStartFailure_Ies__value_PR_MCE_MBMS_M2AP_ID;
+  //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+
+  /* mandatory */
+  /* c2. Cause */
+  ie = (M2AP_SessionStartFailure_Ies_t *)calloc(1, sizeof(M2AP_SessionStartFailure_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_Cause;
+  ie->criticality               = M2AP_Criticality_ignore;
+  ie->value.present             = M2AP_SessionStartFailure_Ies__value_PR_Cause;
+  ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+  ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_unspecified;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+     /* encode */
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 setup request\n");
+    return -1;
+  }
+
+  //mce_m2ap_itti_send_sctp_data_req(instance, m2ap_mce_data_from_enb->assoc_id, buffer, len, 0);
+  m2ap_eNB_itti_send_sctp_data_req(instance,m2ap_enb_data_g->assoc_id,buffer,len,0);
+
+
+  return 0;
+}
+
+int eNB_handle_MBMS_SESSION_STOP_REQUEST(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M2AP_M2AP_PDU_t *pdu){
+  LOG_D(M2AP, "eNB_handle_MBMS_SESSION_STOP_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M2AP_SessionStopRequest_t              *container;
+  //M2AP_SessionStopRequest_Ies_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.SessionStopRequest;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SESSION_STOP_REQ);
+
+
+  itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+
+
+//  if(1){
+//	eNB_send_MBMS_SESSION_STOP_RESPONSE(instance,NULL);
+//  }else
+//	eNB_send_MBMS_SESSION_STOP_FAILURE(instance,NULL);
+  return 0;
+  
+}
+int eNB_send_MBMS_SESSION_STOP_RESPONSE(instance_t instance, m2ap_session_stop_resp_t * m2ap_session_stop_resp){
+	//module_id_t mce_mod_idP;
+  //module_id_t enb_mod_idP;
+
+  // This should be fixed
+  //enb_mod_idP = (module_id_t)0;
+  //mce_mod_idP  = (module_id_t)0;
+
+  M2AP_M2AP_PDU_t           pdu;
+  M2AP_SessionStopResponse_t    *out;
+  M2AP_SessionStopResponse_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M2AP_SuccessfulOutcome_t *)calloc(1, sizeof(M2AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_sessionStop;
+  pdu.choice.successfulOutcome.criticality   = M2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_SessionStopResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.SessionStopResponse;
+  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+  ie = (M2AP_SessionStopResponse_Ies_t *)calloc(1, sizeof(M2AP_SessionStopResponse_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStopResponse_Ies__value_PR_MCE_MBMS_M2AP_ID;
+  //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long
+  ie = (M2AP_SessionStopResponse_Ies_t *)calloc(1, sizeof(M2AP_SessionStopResponse_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_SessionStopResponse_Ies__value_PR_ENB_MBMS_M2AP_ID;
+  //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 SessionStop Response\n");
+    return -1;
+  }
+
+
+  LOG_D(M2AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M2AP_eNB,
+ // MSC_M2AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M2_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m2ap_eNB_data_p->ENBname);
+
+  m2ap_eNB_itti_send_sctp_data_req(instance, m2ap_enb_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+
+ uint8_t bytes [] = {0x00, 0x05, /* .....+.. */
+0x00, 0x24, 0x00, 0x00, 0x02, 0x00, 0x0d, 0x00, /* .$...... */
+0x08, 0x00, 0x02, 0xf8, 0x39, 0x00, 0x00, 0xe0, /* ....9... */
+0x00, 0x00, 0x0f, 0x00, 0x11, 0x00, 0x00, 0x10, /* ........ */
+0x00, 0x0c, 0x00, 0x02, 0xf8, 0x39, 0x00, 0xe0, /* .....9.. */
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ 
+
+/*
+    M2 Setup
+*/
+
+// SETUP REQUEST
+int eNB_send_M2_SETUP_REQUEST(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t* m2ap_eNB_data_p) {
+ // module_id_t enb_mod_idP=0;
+ // module_id_t du_mod_idP=0;
+
+  M2AP_M2AP_PDU_t          pdu;
+  M2AP_M2SetupRequest_t    *out;
+  M2AP_M2SetupRequest_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       i = 0;
+  int       j = 0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_M2SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M2SetupRequest;
+
+  /* mandatory */
+  /* c1. GlobalENB_ID (integer value) */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_GlobalENB_ID;
+  //ie->value.choice.GlobalENB_ID.eNB_ID = 1;//M2AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);
+  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                  &ie->value.choice.GlobalENB_ID.pLMN_Identity);
+  ie->value.choice.GlobalENB_ID.eNB_ID.present = M2AP_ENB_ID_PR_macro_eNB_ID;
+  MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
+                           &ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
+  M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  ///* mandatory */
+  ///* c2. GNB_eNB_ID (integrer value) */
+  //ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id                        = M2AP_ProtocolIE_ID_id_gNB_eNB_ID;
+  //ie->criticality               = M2AP_Criticality_reject;
+  //ie->value.present             = M2AP_M2SetupRequestIEs__value_PR_GNB_eNB_ID;
+  //asn_int642INTEGER(&ie->value.choice.GNB_eNB_ID, f1ap_du_data->gNB_eNB_id);
+  //ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+     /* optional */
+  /* c3. ENBname */
+  if (m2ap_eNB_data_p->eNB_name != NULL) {
+    ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+    ie->id                        = M2AP_ProtocolIE_ID_id_ENBname;
+    ie->criticality               = M2AP_Criticality_ignore;
+    ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_ENBname;
+    OCTET_STRING_fromBuf(&ie->value.choice.ENBname, m2ap_eNB_data_p->eNB_name,
+                         strlen(m2ap_eNB_data_p->eNB_name));
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */
+  /* c4. serverd cells list */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_List;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_ENB_MBMS_Configuration_data_List;
+
+  int num_mbms_available = instance_p->num_mbms_configuration_data_list;
+  LOG_D(M2AP, "num_mbms_available = %d \n", num_mbms_available);
+
+ for (i=0;
+       i<num_mbms_available;
+       i++) {
+        /* mandatory */
+        /* 4.1 serverd cells item */
+
+        M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *mbms_configuration_data_list_item_ies;
+        mbms_configuration_data_list_item_ies = (M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *)calloc(1, sizeof(M2AP_ENB_MBMS_Configuration_data_ItemIEs_t));
+        mbms_configuration_data_list_item_ies->id = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_Item;
+        mbms_configuration_data_list_item_ies->criticality = M2AP_Criticality_reject;
+        mbms_configuration_data_list_item_ies->value.present = M2AP_ENB_MBMS_Configuration_data_ItemIEs__value_PR_ENB_MBMS_Configuration_data_Item;
+
+        M2AP_ENB_MBMS_Configuration_data_Item_t *mbms_configuration_data_item;
+        mbms_configuration_data_item = &mbms_configuration_data_list_item_ies->value.choice.ENB_MBMS_Configuration_data_Item;
+        {
+		/* M2AP_ECGI_t eCGI */
+                MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                  &mbms_configuration_data_item->eCGI.pLMN_Identity);
+                MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
+                                   &mbms_configuration_data_item->eCGI.eUTRANcellIdentifier);
+		/* M2AP_MBSFN_SynchronisationArea_ID_t mbsfnSynchronisationArea */ 
+		mbms_configuration_data_item->mbsfnSynchronisationArea=instance_p->mbms_configuration_data_list[i].mbsfn_sync_area; //? long
+		/* M2AP_MBMS_Service_Area_ID_List_t mbmsServiceAreaList */
+		for(j=0;j<instance_p->mbms_configuration_data_list[i].num_mbms_service_area_list;j++){
+			M2AP_MBMS_Service_Area_t * mbms_service_area = (M2AP_MBMS_Service_Area_t*)calloc(1,sizeof(M2AP_MBMS_Service_Area_t));
+			
+			char buf[2];
+			INT16_TO_BUFFER(instance_p->mbms_configuration_data_list[i].mbms_service_area_list[j],buf);
+			OCTET_STRING_fromBuf(mbms_service_area,buf,2);
+			//LOG_D(M2AP,"%s\n",instance_p->mbms_configuration_data_list[i].mbms_service_area_list[j]);
+			//OCTET_STRING_fromBuf(mbms_service_area,"03",2);
+                	ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area);
+		}
+                /*M2AP_MBMS_Service_Area_t * mbms_service_area,*mbms_service_area2;
+                mbms_service_area = (M2AP_MBMS_Service_Area_t*)calloc(1,sizeof(M2AP_MBMS_Service_Area_t));
+                mbms_service_area2 = (M2AP_MBMS_Service_Area_t*)calloc(1,sizeof(M2AP_MBMS_Service_Area_t));
+		//memset(mbms_service_area,0,sizeof(OCTET_STRING_t));
+		OCTET_STRING_fromBuf(mbms_service_area,"01",2);
+                ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area);
+		OCTET_STRING_fromBuf(mbms_service_area2,"02",2);
+                ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area2);*/
+
+
+        }
+
+
+        //M2AP_ENB_MBMS_Configuration_data_Item_t mbms_configuration_data_item;
+        //memset((void *)&mbms_configuration_data_item, 0, sizeof(M2AP_ENB_MBMS_Configuration_data_Item_t));
+
+        //M2AP_ECGI_t      eCGI;
+                //M2AP_PLMN_Identity_t     pLMN_Identity;
+                //M2AP_EUTRANCellIdentifier_t      eUTRANcellIdentifier
+        //M2AP_MBSFN_SynchronisationArea_ID_t      mbsfnSynchronisationArea;
+        //M2AP_MBMS_Service_Area_ID_List_t         mbmsServiceAreaList;
+
+
+        ASN_SEQUENCE_ADD(&ie->value.choice.ENB_MBMS_Configuration_data_List.list,mbms_configuration_data_list_item_ies);
+
+ }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  
+ LOG_D(M2AP,"m2ap_eNB_data_p->assoc_id %d\n",m2ap_eNB_data_p->assoc_id);
+  /* encode */
+ if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+   LOG_E(M2AP, "Failed to encode M2 setup request\n");
+   return -1;
+ }
+
+
+  LOG_D(M2AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M2AP_eNB,
+ // MSC_M2AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M2_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m2ap_eNB_data_p->ENBname);
+
+
+//  buffer = &bytes[0];
+//  len = 40;
+//
+//  for(int i=0; i < len; i++ )
+//	printf("%02X",buffer[i]);
+//  printf("\n");
+//
+  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return 0;
+}
+
+
+int eNB_handle_M2_SETUP_RESPONSE(instance_t instance,
+				uint32_t               assoc_id,
+				uint32_t               stream,
+				M2AP_M2AP_PDU_t       *pdu)
+{
+
+   LOG_D(M2AP, "eNB_handle_M2_SETUP_RESPONSE\n");
+
+   AssertFatal(pdu->present == M2AP_M2AP_PDU_PR_successfulOutcome,
+	       "pdu->present != M2AP_M2AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M2AP_ProcedureCode_id_m2Setup,
+	       "pdu->choice.successfulOutcome.procedureCode != M2AP_ProcedureCode_id_M2Setup\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M2AP_Criticality_reject,
+	       "pdu->choice.successfulOutcome.criticality != M2AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M2AP_SuccessfulOutcome__value_PR_M2SetupResponse,
+	       "pdu->choice.successfulOutcome.value.present != M2AP_SuccessfulOutcome__value_PR_M2SetupResponse\n");
+
+   M2AP_M2SetupResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.M2SetupResponse;
+
+
+   M2AP_M2SetupResponse_Ies_t *ie;
+   //int GlobalMCE_ID = -1;
+   int num_cells_to_activate = 0;
+   //M2AP_Cells_to_be_Activated_List_Item_t *cell;
+   int i,j;
+
+   MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_SETUP_RESP);
+   //MessageDef *msg_p2 = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_SETUP_RESP);
+
+   LOG_D(M2AP, "M2AP: M2Setup-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+   for (j=0;j < in->protocolIEs.list.count; j++) {
+     ie = in->protocolIEs.list.array[j];
+     switch (ie->id) {
+     case M2AP_ProtocolIE_ID_id_GlobalMCE_ID:
+       AssertFatal(ie->criticality == M2AP_Criticality_reject,
+		   "ie->criticality != M2AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M2AP_M2SetupResponse_Ies__value_PR_GlobalMCE_ID,
+		   "ie->value.present != M2AP_M2SetupResponse_Ies__value_PR_GlobalMCE_ID\n");
+       LOG_D(M2AP, "M2AP: M2Setup-Resp: GlobalMCE_ID \n");/*,
+             GlobalMCE_ID);*/
+       /*PLMNID_TO_MCC_MNC(&m2ap_pmchconfiguration_item->mbms_Session_List.list.array[k]->tmgi.pLMNidentity,
+				&M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mcc,
+				&M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mnc,
+				&M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].mnc_length);*/
+
+       
+       break;
+     case M2AP_ProtocolIE_ID_id_MCEname:
+       AssertFatal(ie->criticality == M2AP_Criticality_ignore,
+		   "ie->criticality != M2AP_Criticality_ignore\n");
+       AssertFatal(ie->value.present == M2AP_M2SetupResponse_Ies__value_PR_MCEname,
+		   "ie->value.present != M2AP_M2SetupResponse_Ies__value_PR_MCEname\n");
+       //M2AP_SETUP_RESP (msg_p).MCE_name = malloc(ie->value.choice.size+1);
+       //memcpy(M2AP_SETUP_RESP (msg_p).gNB_CU_name,ie->value.choice.GNB_CU_Name.buf,ie->value.choice.GNB_CU_Name.size);
+       //M2AP_SETUP_RESP (msg_p).gNB_CU_name[ie->value.choice.GNB_CU_Name.size]='\0';
+       //LOG_D(M2AP, "M2AP: M2Setup-Resp: gNB_CU_name %s\n",
+             //M2AP_SETUP_RESP (msg_p).gNB_CU_name);
+       break;
+     case M2AP_ProtocolIE_ID_id_MCCHrelatedBCCH_ConfigPerMBSFNArea:
+       AssertFatal(ie->criticality == M2AP_Criticality_reject,
+		   "ie->criticality != M2AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M2AP_M2SetupResponse_Ies__value_PR_MCCHrelatedBCCH_ConfigPerMBSFNArea,
+		   "ie->value.present != M2AP_M2SetupResponse_Ies__value_PR_MCCHrelatedBCCH_ConfigPerMBSFNArea\n");
+       num_cells_to_activate = ie->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea.list.count;
+       if(ie->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea.list.count > 0 ){
+        	M2AP_SETUP_RESP(msg_p).num_mcch_config_per_mbsfn = ie->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea.list.count;
+       }
+       //LOG_D(M2AP, "M2AP: Activating %d cells\n",num_cells_to_activate);
+       for (i=0;i<num_cells_to_activate;i++) {
+	M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs_t * mcch_related_bcch_config_per_mbms_area_ies = (M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_ItemIEs_t*) ie->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea.list.array[i];
+	AssertFatal(mcch_related_bcch_config_per_mbms_area_ies->id == M2AP_ProtocolIE_ID_id_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item, 
+			" mcch_related_bcch_config_per_mbms_area_ies->id != M2AP_ProtocolIE_ID_id_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item ");
+	M2AP_MCCHrelatedBCCH_ConfigPerMBSFNArea_Item_t * config_per_mbsfn_area_item = &mcch_related_bcch_config_per_mbms_area_ies->value.choice.MCCHrelatedBCCH_ConfigPerMBSFNArea_Item;
+	M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[i].pdcch_length = (uint8_t)config_per_mbsfn_area_item->pdcchLength; 
+	M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[i].offset 	     = (uint8_t)config_per_mbsfn_area_item->offset;
+	M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[i].modification_period = (uint8_t)config_per_mbsfn_area_item->modificationPeriod;
+	M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[i].mcs 	     = (uint8_t)config_per_mbsfn_area_item->modulationAndCodingScheme;
+	M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[i].repetition_period  = (uint8_t)config_per_mbsfn_area_item->repetitionPeriod;
+
+	//LOG_E(M2AP,"mcs %lu\n",config_per_mbsfn_area_item->modulationAndCodingScheme);
+	//LOG_E(M2AP,"pdcch_length %lu\n",config_per_mbsfn_area_item->pdcchLength);
+	//LOG_E(M2AP,"modification_period %lu\n",config_per_mbsfn_area_item->modificationPeriod);
+	//LOG_E(M2AP,"repetition_period %lu\n",config_per_mbsfn_area_item->repetitionPeriod);
+	//LOG_E(M2AP,"offset %lu\n",config_per_mbsfn_area_item->offset);
+	//LOG_E(M2AP,"subframe_allocation_info %lu\n", config_per_mbsfn_area_item->subframeAllocationInfo.size);
+	
+
+	if(config_per_mbsfn_area_item->subframeAllocationInfo.size == 1){
+		M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[i].subframe_allocation_info = config_per_mbsfn_area_item->subframeAllocationInfo.buf[0]>>2;
+		LOG_D(M2AP,"subframe_allocation_info %d\n", config_per_mbsfn_area_item->subframeAllocationInfo.buf[0]);
+	}		
+       }
+       break;
+     }
+   }
+   //AssertFatal(GlobalMCE_ID!=-1,"GlobalMCE_ID was not sent\n");
+   //AssertFatal(num_cells_to_activate>0,"No cells activated\n");
+   //M2AP_SETUP_RESP (msg_p).num_cells_to_activate = num_cells_to_activate;
+
+   //for (int i=0;i<num_cells_to_activate;i++)  
+   //  AssertFatal(M2AP_SETUP_RESP (msg_p).num_SI[i] > 0, "System Information %d is missing",i);
+
+   //MSC_LOG_RX_MESSAGE(
+   // MSC_M2AP_eNB,
+   // MSC_M2AP_CU,
+   // 0,
+   // 0,
+   // MSC_AS_TIME_FMT" eNB_handle_M2_SETUP_RESPONSE successfulOutcome assoc_id %d",
+   // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+   // assoc_id);
+ 
+   //LOG_D(M2AP, "Sending M2AP_SETUP_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n",
+   //      assoc_id,ENB_MOeNBLE_ID_TO_INSTANCE(assoc_id));
+   //itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p2);
+   itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p);
+
+   return 0;
+}
+
+// SETUP FAILURE
+int eNB_handle_M2_SETUP_FAILURE(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M2AP_M2AP_PDU_t *pdu) {
+  LOG_D(M2AP, "eNB_handle_M2_SETUP_FAILURE\n");
+
+  M2AP_M2SetupFailure_t    *in = &pdu->choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+
+
+   M2AP_M2SetupFailure_Ies_t *ie;
+
+
+  MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_SETUP_FAILURE);
+
+   LOG_D(M2AP, "M2AP: M2Setup-Failure: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+   for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M2AP_ProtocolIE_ID_id_TimeToWait:
+       AssertFatal(ie->criticality == M2AP_Criticality_ignore,
+		   "ie->criticality != M2AP_Criticality_ignore\n");
+       AssertFatal(ie->value.present == M2AP_M2SetupFailure_Ies__value_PR_TimeToWait,
+		   "ie->value.present != M2AP_M2SetupFailure_Ies__value_PR_TimeToWait\n");
+       LOG_D(M2AP, "M2AP: M2Setup-Failure: TimeToWait \n");/*,
+             GlobalMCE_ID);*/
+       break;
+     }
+   }
+   //AssertFatal(GlobalMCE_ID!=-1,"GlobalMCE_ID was not sent\n");
+   //AssertFatal(num_cells_to_activate>0,"No cells activated\n");
+   //M2AP_SETUP_RESP (msg_p).num_cells_to_activate = num_cells_to_activate;
+
+   //for (int i=0;i<num_cells_to_activate;i++)  
+   //  AssertFatal(M2AP_SETUP_RESP (msg_p).num_SI[i] > 0, "System Information %d is missing",i);
+
+   //MSC_LOG_RX_MESSAGE(
+   // MSC_M2AP_eNB,
+   // MSC_M2AP_CU,
+   // 0,
+   // 0,
+   // MSC_AS_TIME_FMT" eNB_handle_M2_SETUP_RESPONSE successfulOutcome assoc_id %d",
+   // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+   // assoc_id);
+ 
+   //LOG_D(M2AP, "Sending M2AP_SETUP_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n",
+   //      assoc_id,ENB_MOeNBLE_ID_TO_INSTANCE(assoc_id));
+
+   itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p);
+  
+  return 0;
+}
+
+/*
+ * eNB Configuration Update
+ */
+int eNB_send_eNB_CONFIGURATION_UPDATE(instance_t instance, m2ap_enb_configuration_update_t * m2ap_enb_configuration_update) 
+{
+
+  AssertFatal(1==0,"Not implemented yet\n");
+
+  M2AP_M2AP_PDU_t          pdu;
+  M2AP_ENBConfigurationUpdate_t    *out;
+  M2AP_ENBConfigurationUpdate_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       i = 0;
+  //int       j = 0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_eNBConfigurationUpdate;
+  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_ENBConfigurationUpdate;
+  out = &pdu.choice.initiatingMessage.value.choice.ENBConfigurationUpdate;
+
+  /* mandatory */
+  /* c1. GlobalENB_ID (integer value) */
+  ie = (M2AP_ENBConfigurationUpdate_Ies_t *)calloc(1, sizeof(M2AP_ENBConfigurationUpdate_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_ENBConfigurationUpdate_Ies__value_PR_GlobalENB_ID;
+  //ie->value.choice.GlobalENB_ID.eNB_ID = 1;//M2AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);
+  MCC_MNC_TO_PLMNID(0, 0, 3,
+                  &ie->value.choice.GlobalENB_ID.pLMN_Identity);
+  ie->value.choice.GlobalENB_ID.eNB_ID.present = M2AP_ENB_ID_PR_macro_eNB_ID;
+  MACRO_ENB_ID_TO_BIT_STRING(10,
+                           &ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
+  M2AP_INFO("%d -> %02x%02x%02x\n", 10,
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional */
+  /* c3. ENBname */
+  if (0) {
+    ie = (M2AP_ENBConfigurationUpdate_Ies_t *)calloc(1, sizeof(M2AP_ENBConfigurationUpdate_Ies_t));
+    ie->id                        = M2AP_ProtocolIE_ID_id_ENBname;
+    ie->criticality               = M2AP_Criticality_ignore;
+    ie->value.present             = M2AP_ENBConfigurationUpdate_Ies__value_PR_ENBname;
+    //OCTET_STRING_fromBuf(&ie->value.choice.ENBname, m2ap_eNB_data_p->eNB_name,
+                         //strlen(m2ap_eNB_data_p->eNB_name));
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */
+  /* c4. serverd cells list */
+  ie = (M2AP_ENBConfigurationUpdate_Ies_t *)calloc(1, sizeof(M2AP_ENBConfigurationUpdate_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_List_ConfigUpdate;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_ENBConfigurationUpdate_Ies__value_PR_ENB_MBMS_Configuration_data_List_ConfigUpdate;
+
+  int num_mbms_available = 1;//m2ap_du_data->num_mbms_available;
+  LOG_D(M2AP, "num_mbms_available = %d \n", num_mbms_available);
+
+ for (i=0;
+       i<num_mbms_available;
+       i++) {
+        /* mandatory */
+        /* 4.1 serverd cells item */
+
+        M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *mbms_configuration_data_list_item_ies;
+        mbms_configuration_data_list_item_ies = (M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *)calloc(1, sizeof(M2AP_ENB_MBMS_Configuration_data_ItemIEs_t));
+        mbms_configuration_data_list_item_ies->id = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_Item;
+        mbms_configuration_data_list_item_ies->criticality = M2AP_Criticality_reject;
+        mbms_configuration_data_list_item_ies->value.present = M2AP_ENB_MBMS_Configuration_data_ItemIEs__value_PR_ENB_MBMS_Configuration_data_Item;
+
+        M2AP_ENB_MBMS_Configuration_data_Item_t *mbms_configuration_data_item;
+        mbms_configuration_data_item = &mbms_configuration_data_list_item_ies->value.choice.ENB_MBMS_Configuration_data_Item;
+        {
+		/* M2AP_ECGI_t eCGI */
+                MCC_MNC_TO_PLMNID(0, 0, 3,
+                  &mbms_configuration_data_item->eCGI.pLMN_Identity);
+                MACRO_ENB_ID_TO_CELL_IDENTITY(10,0,
+                                   &mbms_configuration_data_item->eCGI.eUTRANcellIdentifier);
+		/* M2AP_MBSFN_SynchronisationArea_ID_t mbsfnSynchronisationArea */ 
+		mbms_configuration_data_item->mbsfnSynchronisationArea=10000; //? long
+		/* M2AP_MBMS_Service_Area_ID_List_t mbmsServiceAreaList */
+                M2AP_MBMS_Service_Area_t * mbms_service_area,*mbms_service_area2;
+                mbms_service_area = (M2AP_MBMS_Service_Area_t*)calloc(1,sizeof(M2AP_MBMS_Service_Area_t));
+                mbms_service_area2 = (M2AP_MBMS_Service_Area_t*)calloc(1,sizeof(M2AP_MBMS_Service_Area_t));
+		//memset(mbms_service_area,0,sizeof(OCTET_STRING_t));
+		OCTET_STRING_fromBuf(mbms_service_area,"01",2);
+                ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area);
+		OCTET_STRING_fromBuf(mbms_service_area2,"02",2);
+                ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area2);
+
+
+        }
+
+
+        //M2AP_ENB_MBMS_Configuration_data_Item_t mbms_configuration_data_item;
+        //memset((void *)&mbms_configuration_data_item, 0, sizeof(M2AP_ENB_MBMS_Configuration_data_Item_t));
+
+        //M2AP_ECGI_t      eCGI;
+                //M2AP_PLMN_Identity_t     pLMN_Identity;
+                //M2AP_EUTRANCellIdentifier_t      eUTRANcellIdentifier
+        //M2AP_MBSFN_SynchronisationArea_ID_t      mbsfnSynchronisationArea;
+        //M2AP_MBMS_Service_Area_ID_List_t         mbmsServiceAreaList;
+
+
+        ASN_SEQUENCE_ADD(&ie->value.choice.ENB_MBMS_Configuration_data_List_ConfigUpdate.list,mbms_configuration_data_list_item_ies);
+
+ }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  
+ //LOG_D(M2AP,"m2ap_eNB_data_p->assoc_id %d\n",m2ap_eNB_data_p->assoc_id);
+  /* encode */
+ if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+   LOG_E(M2AP, "Failed to encode M2 setup request\n");
+   return -1;
+ }
+
+
+  LOG_D(M2AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M2AP_eNB,
+ // MSC_M2AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M2_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m2ap_eNB_data_p->ENBname);
+
+
+//  buffer = &bytes[0];
+//  len = 40;
+//
+//  for(int i=0; i < len; i++ )
+//	printf("%02X",buffer[i]);
+//  printf("\n");
+//
+  m2ap_eNB_itti_send_sctp_data_req(instance, m2ap_enb_data_g->assoc_id, buffer, len, 0);
+
+   return 0;
+}
+
+int eNB_handle_eNB_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                                         uint32_t assoc_id,
+                                         uint32_t stream,
+                                         M2AP_M2AP_PDU_t *pdu)
+{
+
+  AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M2AP, "eNB_handle_eNB_CONFIGURATION_UPDATE_FAILURE\n");
+
+  M2AP_ENBConfigurationUpdateFailure_t    *in = &pdu->choice.unsuccessfulOutcome.value.choice.ENBConfigurationUpdateFailure;
+
+
+   //M2AP_ENBConfigurationUpdateFailure_Ies_t *ie;
+
+
+  MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_ENB_CONFIGURATION_UPDATE_FAILURE);
+
+   LOG_D(M2AP, "M2AP: ENBConfigurationUpdate-Failure: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+   //for (int i=0;i < in->protocolIEs.list.count; i++) {
+   //  ie = in->protocolIEs.list.array[i];
+   // // switch (ie->id) {
+   // // case M2AP_ProtocolIE_ID_id_TimeToWait:
+   // //   AssertFatal(ie->criticality == M2AP_Criticality_ignore,
+   // //    	   "ie->criticality != M2AP_Criticality_ignore\n");
+   // //   AssertFatal(ie->value.present == M2AP_M2SetupFailure_Ies__value_PR_TimeToWait,
+   // //    	   "ie->value.present != M2AP_M2SetupFailure_Ies__value_PR_TimeToWait\n");
+   // //   LOG_D(M2AP, "M2AP: M2Setup-Failure: TimeToWait %d\n");/*,
+   // //         GlobalMCE_ID);*/
+   // //   break;
+   // // }
+   //}
+   //AssertFatal(GlobalMCE_ID!=-1,"GlobalMCE_ID was not sent\n");
+   //AssertFatal(num_cells_to_activate>0,"No cells activated\n");
+   //M2AP_SETUP_RESP (msg_p).num_cells_to_activate = num_cells_to_activate;
+
+   //for (int i=0;i<num_cells_to_activate;i++)  
+   //  AssertFatal(M2AP_SETUP_RESP (msg_p).num_SI[i] > 0, "System Information %d is missing",i);
+
+   //MSC_LOG_RX_MESSAGE(
+   // MSC_M2AP_eNB,
+   // MSC_M2AP_CU,
+   // 0,
+   // 0,
+   // MSC_AS_TIME_FMT" eNB_handle_M2_SETUP_RESPONSE successfulOutcome assoc_id %d",
+   // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+   // assoc_id);
+ 
+   //LOG_D(M2AP, "Sending M2AP_SETUP_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n",
+   //      assoc_id,ENB_MOeNBLE_ID_TO_INSTANCE(assoc_id));
+
+   itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p);
+
+   return 0;
+}
+
+
+
+int eNB_handle_eNB_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                                         uint32_t assoc_id,
+                                         uint32_t stream,
+                                         M2AP_M2AP_PDU_t *pdu)
+{
+  LOG_D(M2AP, "eNB_handle_eNB_CONFIGURATION_UPDATE_ACKNOWLEDGE assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M2AP_ENBConfigurationUpdateAcknowledge_t              *container;
+  //M2AP_ENBConfigurationUpdateAcknowledge_Ies_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.ENBConfigurationUpdate;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_ENB_CONFIGURATION_UPDATE_ACK);
+
+
+  itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+   return 0;
+}
+
+
+/*
+ * MCE Configuration Update
+ */
+int eNB_handle_MCE_CONFIGURATION_UPDATE(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          M2AP_M2AP_PDU_t *pdu)
+{
+ LOG_D(M2AP, "eNB_handle_MCE_CONFIGURATION_UPDATE assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M2AP_MCEConfigurationUpdate_t              *container;
+  //M2AP_MCEConfigurationUpdate_Ies_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.MCEConfigurationUpdate;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MCE_CONFIGURATION_UPDATE);
+
+
+  itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+   return 0;
+}
+
+int eNB_send_MCE_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                    M2AP_MCEConfigurationUpdateFailure_t *MCEConfigurationUpdateFailure)
+{
+
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+
+
+int eNB_send_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                    M2AP_MCEConfigurationUpdateAcknowledge_t *MCEConfigurationUpdateAcknowledge)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+
+
+/*
+ * Error Indication
+ */
+int eNB_send_ERROR_INDICATION(instance_t instance, m2ap_error_indication_t * m2ap_error_indication)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+
+int eNB_handle_ERROR_INDICATION(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M2AP_M2AP_PDU_t *pdu)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+
+
+
+/*
+ * Session Update Request
+ */
+int eNB_handle_MBMS_SESSION_UPDATE_REQUEST(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu)
+{
+  LOG_D(M2AP, "eNB_handle_MBMS_SESSION_STOP_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M2AP_SessionUpdateRequest_t              *container;
+  //M2AP_SessionUpdateRequest_Ies_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.SessionUpdateRequest;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SESSION_UPDATE_REQ);
+
+
+  itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+
+   return 0;
+}
+
+
+int eNB_send_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, m2ap_mbms_session_update_resp_t * m2ap_mbms_session_update_resp)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+
+
+int eNB_send_MBMS_SESSION_UPDATE_FAILURE(instance_t instance, m2ap_mbms_session_update_failure_t * m2ap_mbms_session_update_failure)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+
+/*
+ * Service Counting
+ */
+
+int eNB_handle_MBMS_SERVICE_COUNTING_REQ(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu)
+{
+  LOG_D(M2AP, "eNB_handle_MBMS_SERVICE_COUNTING_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M2AP_MbmsServiceCountingRequest_t              *container;
+  //M2AP_MbmsServiceCountingRequest_Ies_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+ // container = &pdu->choice.initiatingMessage.value.choice.MbmsServiceCountingRequest;
+
+  /* M2 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  message_p  = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SERVICE_COUNTING_REQ);
+
+
+  itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+
+
+   return 0;
+}
+int eNB_send_MBMS_SERVICE_COUNTING_REPORT(instance_t instance, m2ap_mbms_service_counting_report_t * m2ap_mbms_service_counting_report)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+int eNB_send_MBMS_SERVICE_COUNTING_RESP(instance_t instance, m2ap_mbms_service_counting_resp_t * m2ap_mbms_service_counting_resp)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+int eNB_send_MBMS_SERVICE_COUNTING_FAILURE(instance_t instance, m2ap_mbms_service_counting_failure_t * m2ap_mbms_service_counting_failure)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+
+/*
+ * Overload Notification
+ */
+int eNB_send_MBMS_OVERLOAD_NOTIFICATION(instance_t instance, m2ap_mbms_overload_notification_t * m2ap_mbms_overload_notification)
+{
+  AssertFatal(1==0,"Not implemented yet\n");
+   return 0;
+}
+
+
+
+
diff --git a/openair2/M2AP/m2ap_eNB_interface_management.h b/openair2/M2AP/m2ap_eNB_interface_management.h
new file mode 100644
index 0000000000000000000000000000000000000000..09bab1f1259196fb6052af547cb1139b1d103d15
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_interface_management.h
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_interface_management.h
+ * \brief m2ap interface management for eNB
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M2AP_ENB_INTERFACE_MANAGEMENT_H_
+#define M2AP_ENB_INTERFACE_MANAGEMENT_H_
+
+/*
+ * Session Start 
+ */
+
+int eNB_handle_MBMS_SESSION_START_REQUEST(instance_t instance, 
+					uint32_t assoc_id,
+                                	uint32_t stream,
+                                	M2AP_M2AP_PDU_t *pdu);
+
+int eNB_send_MBMS_SESSION_START_RESPONSE(instance_t instance, m2ap_session_start_resp_t * m2ap_session_start_resp);
+int eNB_send_MBMS_SESSION_START_FAILURE(instance_t instance, m2ap_session_start_failure_t * m2ap_session_start_failure  );
+
+/*
+ * Session Stop
+ */
+
+int eNB_handle_MBMS_SESSION_STOP_REQUEST(instance_t instance, 
+					uint32_t assoc_id,
+                                	uint32_t stream,
+                                	M2AP_M2AP_PDU_t *pdu);
+int eNB_send_MBMS_SESSION_STOP_RESPONSE(instance_t instance, m2ap_session_stop_resp_t * m2ap_session_stop_resp);
+
+
+/*
+ * MBMS Scheduling Information
+ */
+
+int eNB_handle_MBMS_SCHEDULING_INFORMATION(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu);
+
+int eNB_send_MBMS_SCHEDULING_INFORMATION_RESPONSE(instance_t instance, m2ap_mbms_scheduling_information_resp_t * m2ap_mbms_scheduling_information_resp);
+
+
+/*
+ * Reset
+ */
+int eNB_handle_RESET(instance_t instance,
+                    uint32_t assoc_id,
+                    uint32_t stream,
+                    M2AP_M2AP_PDU_t *pdu);
+int eNB_send_RESET_ACKKNOWLEDGE(instance_t instance, M2AP_ResetAcknowledge_t *ResetAcknowledge);
+int eNB_send_RESET(instance_t instance, M2AP_Reset_t *Reset);
+int eNB_handle_RESET_ACKNOWLEDGE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu);
+
+/*
+ * M2AP Setup
+ */
+int eNB_send_M2_SETUP_REQUEST( m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p);
+
+int eNB_handle_M2_SETUP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M2AP_M2AP_PDU_t *pdu);
+
+int eNB_handle_M2_SETUP_FAILURE(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M2AP_M2AP_PDU_t *pdu);
+
+/*
+ * eNB Configuration Update
+ */ 
+int eNB_send_eNB_CONFIGURATION_UPDATE(instance_t instance, m2ap_enb_configuration_update_t * m2ap_enb_configuration_update);
+
+int eNB_handle_eNB_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+					 uint32_t assoc_id,
+                                         uint32_t stream,
+                                         M2AP_M2AP_PDU_t *pdu);
+
+int eNB_handle_eNB_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+				         uint32_t assoc_id,
+                                         uint32_t stream,
+                                         M2AP_M2AP_PDU_t *pdu);
+
+/*
+ * MCE Configuration Update
+ */
+int eNB_handle_MCE_CONFIGURATION_UPDATE(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          M2AP_M2AP_PDU_t *pdu);
+
+int eNB_send_MCE_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                    M2AP_MCEConfigurationUpdateFailure_t *MCEConfigurationUpdateFailure);
+
+int eNB_send_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                    M2AP_MCEConfigurationUpdateAcknowledge_t *MCEConfigurationUpdateAcknowledge);
+
+/*
+ * Error Indication
+ */
+int eNB_send_ERROR_INDICATION(instance_t instance, m2ap_error_indication_t * m2ap_error_indication);
+int eNB_handle_ERROR_INDICATION(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M2AP_M2AP_PDU_t *pdu);
+
+
+/*
+ * Session Update Request
+ */
+int eNB_handle_MBMS_SESSION_UPDATE_REQUEST(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu);
+
+int eNB_send_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, m2ap_mbms_session_update_resp_t * m2ap_mbms_session_update_resp); //??
+
+int eNB_send_MBMS_SESSION_UPDATE_FAILURE(instance_t instance, m2ap_mbms_session_update_failure_t * m2ap_mbms_session_update_failure);
+
+/*
+ * Service Counting
+ */ 
+
+int eNB_handle_MBMS_SERVICE_COUNTING_REQ(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M2AP_M2AP_PDU_t *pdu);
+int eNB_send_MBMS_SERVICE_COUNTING_REPORT(instance_t instance, m2ap_mbms_service_counting_report_t * m2ap_mbms_service_counting_report);
+int eNB_send_MBMS_SERVICE_COUNTING_RESP(instance_t instance, m2ap_mbms_service_counting_resp_t * m2ap_mbms_service_counting_resp);
+int eNB_send_MBMS_SERVICE_COUNTING_FAILURE(instance_t instance, m2ap_mbms_service_counting_failure_t * m2ap_mbms_service_counting_failure);
+
+ 
+/* 
+ * Overload Notification
+ */
+int eNB_send_MBMS_OVERLOAD_NOTIFICATION(instance_t instance, m2ap_mbms_overload_notification_t * m2ap_mbms_overload_notification);
+
+
+#endif /* M2AP_ENB_INTERFACE_MANAGEMENT_H_ */
+
+
+
diff --git a/openair2/M2AP/m2ap_eNB_management_procedures.c b/openair2/M2AP/m2ap_eNB_management_procedures.c
new file mode 100644
index 0000000000000000000000000000000000000000..b3ada92fa83c761febb9693cc116812d11a31ece
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_management_procedures.c
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_management_procedures.c
+ * \brief m2ap tasks for eNB
+ * \author Javier Morgade  <javier.morade@ieee.org>
+ * \date 2018
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "assertions.h"
+#include "conversions.h"
+
+#include "m2ap_common.h"
+#include "m2ap_eNB_defs.h"
+#include "m2ap_eNB.h"
+
+
+#define M2AP_DEBUG_LIST
+#ifdef M2AP_DEBUG_LIST
+#  define M2AP_eNB_LIST_OUT(x, args...) M2AP_DEBUG("[eNB]%*s"x"\n", 4*indent, "", ##args)
+#else
+#  define M2AP_eNB_LIST_OUT(x, args...)
+#endif
+
+static int                  indent = 0;
+
+
+m2ap_eNB_internal_data_t m2ap_eNB_internal_data;
+
+RB_GENERATE(m2ap_enb_map, m2ap_eNB_data_s, entry, m2ap_eNB_compare_assoc_id);
+
+int m2ap_eNB_compare_assoc_id(
+  struct m2ap_eNB_data_s *p1, struct m2ap_eNB_data_s *p2)
+{
+  if (p1->assoc_id == -1) {
+    if (p1->cnx_id < p2->cnx_id) {
+      return -1;
+    }
+
+    if (p1->cnx_id > p2->cnx_id) {
+      return 1;
+    }
+  } else {
+    if (p1->assoc_id < p2->assoc_id) {
+      return -1;
+    }
+
+    if (p1->assoc_id > p2->assoc_id) {
+      return 1;
+    }
+  }
+
+  /* Matching reference */
+  return 0;
+}
+
+uint16_t m2ap_eNB_fetch_add_global_cnx_id(void)
+{
+  return ++m2ap_eNB_internal_data.global_cnx_id;
+}
+
+void m2ap_eNB_prepare_internal_data(void)
+{
+  memset(&m2ap_eNB_internal_data, 0, sizeof(m2ap_eNB_internal_data));
+  STAILQ_INIT(&m2ap_eNB_internal_data.m2ap_eNB_instances_head);
+}
+
+void m2ap_eNB_insert_new_instance(m2ap_eNB_instance_t *new_instance_p)
+{
+  DevAssert(new_instance_p != NULL);
+
+  STAILQ_INSERT_TAIL(&m2ap_eNB_internal_data.m2ap_eNB_instances_head,
+                     new_instance_p, m2ap_eNB_entries);
+}
+
+void dump_tree_m2(m2ap_eNB_data_t *t)
+{
+  if (t == NULL) return;
+  printf("-----------------------\n");
+  printf("eNB id %d %s\n", t->eNB_id, t->eNB_name);
+  printf("state %d\n", t->state);
+  printf("nextstream %d\n", t->nextstream);
+  printf("in_streams %d out_streams %d\n", t->in_streams, t->out_streams);
+  printf("cnx_id %d assoc_id %d\n", t->cnx_id, t->assoc_id);
+  dump_tree_m2(t->entry.rbe_left);
+  dump_tree_m2(t->entry.rbe_right);
+}
+
+void dump_trees_m2(void)
+{
+m2ap_eNB_instance_t *zz;
+STAILQ_FOREACH(zz, &m2ap_eNB_internal_data.m2ap_eNB_instances_head,
+               m2ap_eNB_entries) {
+printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance);
+dump_tree_m2(zz->m2ap_enb_head.rbh_root);
+printf("---------------------------------------------\n");
+}
+}
+
+struct m2ap_eNB_data_s *m2ap_get_eNB(m2ap_eNB_instance_t *instance_p,
+				     int32_t assoc_id,
+				     uint16_t cnx_id)
+{
+  struct m2ap_eNB_data_s  temp;
+  struct m2ap_eNB_data_s *found;
+
+printf("m2ap_get_eNB at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
+dump_trees_m2();
+
+  memset(&temp, 0, sizeof(struct m2ap_eNB_data_s));
+
+  temp.assoc_id = assoc_id;
+  temp.cnx_id   = cnx_id;
+
+  if (instance_p == NULL) {
+    STAILQ_FOREACH(instance_p, &m2ap_eNB_internal_data.m2ap_eNB_instances_head,
+                   m2ap_eNB_entries) {
+      found = RB_FIND(m2ap_enb_map, &instance_p->m2ap_enb_head, &temp);
+
+      if (found != NULL) {
+        return found;
+      }
+    }
+  } else {
+    return RB_FIND(m2ap_enb_map, &instance_p->m2ap_enb_head, &temp);
+  }
+
+  return NULL;
+}
+
+
+m2ap_eNB_instance_t *m2ap_eNB_get_instance(instance_t instance)
+{
+  m2ap_eNB_instance_t *temp = NULL;
+
+  STAILQ_FOREACH(temp, &m2ap_eNB_internal_data.m2ap_eNB_instances_head,
+                 m2ap_eNB_entries) {
+    if (temp->instance == instance) {
+      /* Matching occurence */
+      return temp;
+    }
+  }
+
+  return NULL;
+}
+
+/// utility functions
+
+void m2ap_dump_eNB (m2ap_eNB_data_t  * eNB_ref);
+
+void
+m2ap_dump_eNB_list (void) {
+   m2ap_eNB_instance_t *inst = NULL;
+   struct m2ap_eNB_data_s *found = NULL;
+   struct m2ap_eNB_data_s temp;
+
+   memset(&temp, 0, sizeof(struct m2ap_eNB_data_s));
+
+  STAILQ_FOREACH (inst, &m2ap_eNB_internal_data.m2ap_eNB_instances_head,  m2ap_eNB_entries) {
+    found = RB_FIND(m2ap_enb_map, &inst->m2ap_enb_head, &temp);
+    m2ap_dump_eNB (found);
+  }
+}
+
+void m2ap_dump_eNB (m2ap_eNB_data_t  * eNB_ref) {
+
+  if (eNB_ref == NULL) {
+    return;
+  }
+
+  M2AP_eNB_LIST_OUT ("");
+  M2AP_eNB_LIST_OUT ("eNB name:          %s", eNB_ref->eNB_name == NULL ? "not present" : eNB_ref->eNB_name);
+  M2AP_eNB_LIST_OUT ("eNB STATE:         %07x", eNB_ref->state);
+  M2AP_eNB_LIST_OUT ("eNB ID:            %07x", eNB_ref->eNB_id);
+  indent++;
+  M2AP_eNB_LIST_OUT ("SCTP cnx id:     %d", eNB_ref->cnx_id);
+  M2AP_eNB_LIST_OUT ("SCTP assoc id:     %d", eNB_ref->assoc_id);
+  M2AP_eNB_LIST_OUT ("SCTP instreams:    %d", eNB_ref->in_streams);
+  M2AP_eNB_LIST_OUT ("SCTP outstreams:   %d", eNB_ref->out_streams);
+  indent--;
+}
+
+m2ap_eNB_data_t  * m2ap_is_eNB_pci_in_list (const uint32_t pci)
+{
+  m2ap_eNB_instance_t    *inst;
+  struct m2ap_eNB_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m2ap_eNB_internal_data.m2ap_eNB_instances_head, m2ap_eNB_entries) {
+    RB_FOREACH(elm, m2ap_enb_map, &inst->m2ap_enb_head) {
+      for (int i = 0; i<elm->num_cc; i++) {
+        if (elm->Nid_cell[i] == pci) {
+          return elm;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+m2ap_eNB_data_t  * m2ap_is_eNB_id_in_list (const uint32_t eNB_id)
+{
+  m2ap_eNB_instance_t    *inst;
+  struct m2ap_eNB_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m2ap_eNB_internal_data.m2ap_eNB_instances_head, m2ap_eNB_entries) {
+    RB_FOREACH(elm, m2ap_enb_map, &inst->m2ap_enb_head) {
+      if (elm->eNB_id == eNB_id)
+        return elm;
+    }
+  }
+  return NULL;
+}
+
+m2ap_eNB_data_t  * m2ap_is_eNB_assoc_id_in_list (const uint32_t sctp_assoc_id)
+{
+  m2ap_eNB_instance_t    *inst;
+  struct m2ap_eNB_data_s *found;
+  struct m2ap_eNB_data_s temp;
+
+  temp.assoc_id = sctp_assoc_id;
+  temp.cnx_id = -1;
+
+  STAILQ_FOREACH(inst, &m2ap_eNB_internal_data.m2ap_eNB_instances_head, m2ap_eNB_entries) {
+    found = RB_FIND(m2ap_enb_map, &inst->m2ap_enb_head, &temp);
+    if (found != NULL){
+      if (found->assoc_id == sctp_assoc_id) {
+	return found;
+      }
+    }
+  }
+  return NULL;
+}
diff --git a/openair2/M2AP/m2ap_eNB_management_procedures.h b/openair2/M2AP/m2ap_eNB_management_procedures.h
new file mode 100644
index 0000000000000000000000000000000000000000..fbc49d01698f3883f27761eea86dd2b2c039b8fa
--- /dev/null
+++ b/openair2/M2AP/m2ap_eNB_management_procedures.h
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_management_procedures.h
+ * \brief m2ap tasks for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_ENB_MANAGEMENT_PROCEDURES_H_
+#define M2AP_ENB_MANAGEMENT_PROCEDURES_H
+
+void m2ap_eNB_prepare_internal_data(void);
+
+void dump_trees_m2(void);
+
+void m2ap_eNB_insert_new_instance(m2ap_eNB_instance_t *new_instance_p);
+
+m2ap_eNB_instance_t *m2ap_eNB_get_instance(uint8_t mod_id);
+
+uint16_t m2ap_eNB_fetch_add_global_cnx_id(void);
+
+//void m2ap_eNB_prepare_internal_data(void);
+
+m2ap_eNB_data_t* m2ap_is_eNB_id_in_list(uint32_t eNB_id);
+
+m2ap_eNB_data_t* m2ap_is_eNB_assoc_id_in_list(uint32_t sctp_assoc_id);
+
+m2ap_eNB_data_t* m2ap_is_eNB_pci_in_list (const uint32_t pci);
+
+struct m2ap_eNB_data_s *m2ap_get_eNB(m2ap_eNB_instance_t *instance_p,
+                                     int32_t assoc_id,
+                                     uint16_t cnx_id);
+
+#endif /* M2AP_ENB_MANAGEMENT_PROCEDURES_H_ */
diff --git a/openair2/M2AP/m2ap_encoder.c b/openair2/M2AP/m2ap_encoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..8f798ff55cf750c860b40aaf8cd0daf8d67268bf
--- /dev/null
+++ b/openair2/M2AP/m2ap_encoder.c
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_encoder.c
+ * \brief m2ap encoder procedures
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "assertions.h"
+#include "conversions.h"
+#include "intertask_interface.h"
+#include "m2ap_common.h"
+#include "m2ap_encoder.h"
+
+int m2ap_encode_pdu(M2AP_M2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
+{
+  ssize_t    encoded;
+
+  DevAssert(pdu != NULL);
+  DevAssert(buffer != NULL);
+  DevAssert(len != NULL);
+
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M2AP_M2AP_PDU, (void *)pdu);
+  }
+
+  encoded = aper_encode_to_new_buffer(&asn_DEF_M2AP_M2AP_PDU, 0, pdu, (void **)buffer);
+
+  if (encoded < 0) {
+    return -1;
+  }
+
+  *len = encoded;
+
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, pdu);
+  return encoded;
+}
diff --git a/openair2/M2AP/m2ap_encoder.h b/openair2/M2AP/m2ap_encoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf844f2983e0fed2ae4bb8dd9b7b342ee071bb85
--- /dev/null
+++ b/openair2/M2AP/m2ap_encoder.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_encoder.h
+ * \brief m2ap encoder procedures
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_ENCODER_H_
+#define M2AP_ENCODER_H_
+
+int m2ap_encode_pdu(M2AP_M2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
+__attribute__ ((warn_unused_result));
+
+#endif /* M2AP_ENCODER_H_ */
diff --git a/openair2/M2AP/m2ap_handler.c b/openair2/M2AP/m2ap_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..1221bcedb5a07b5d54317092eec6986bbb875f94
--- /dev/null
+++ b/openair2/M2AP/m2ap_handler.c
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_handler.c
+ * \brief m2ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m2ap_common.h"
+#include "m2ap_eNB_defs.h"
+//#include "m2ap_handler.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+//#include "m2ap_eNB_management_procedures.h"
+#include "m2ap_eNB_generate_messages.h"
+
+#include "m2ap_MCE_interface_management.h"
+#include "m2ap_eNB_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m2ap_message_decoded_callback m2ap_messages_callback[][3] = {
+  { eNB_handle_MBMS_SESSION_START_REQUEST, MCE_handle_MBMS_SESSION_START_RESPONSE, 0 }, /* MBMSSessionStart  */
+  { eNB_handle_MBMS_SESSION_STOP_REQUEST, MCE_handle_MBMS_SESSION_STOP_RESPONSE, 0 }, /* MBMSSessionStop */
+  { eNB_handle_MBMS_SCHEDULING_INFORMATION, MCE_handle_MBMS_SCHEDULING_INFORMATION_RESPONSE, 0 }, /* MBMSSchedulingInformation */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { MCE_handle_M2_SETUP_REQUEST,eNB_handle_M2_SETUP_RESPONSE,eNB_handle_M2_SETUP_FAILURE }, /* M2 Setup */
+  { 0, 0, 0 }, /* eNBConfigurationUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { 0, 0, 0 }, /* privateMessage */
+  { 0, 0, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MBMSServiceCounting */
+  { 0, 0, 0 }, /* MBMSServiceCountingResultReport */
+  { 0, 0, 0 } /* MBMSOverloadNotification */
+};
+
+static char *m2ap_direction2String(int m2ap_dir) {
+static char *m2ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m2ap_direction_String[m2ap_dir]);
+}
+
+
+int m2ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M2AP_M2AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  if (m2ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M2AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m2ap_messages_callback) / (3 * sizeof(
+        m2ap_message_decoded_callback))
+      || (pdu.present > M2AP_M2AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M2AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
+               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M2AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m2ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M2AP, "Calling handler with instance %d\n",instance);
+  ret = (*m2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair2/M2AP/m2ap_handler.h b/openair2/M2AP/m2ap_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..88fb26bc3e291225436c8b2ff69ec623a6327bdf
--- /dev/null
+++ b/openair2/M2AP/m2ap_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_handler.h
+ * \brief m2ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_ENB_OLD_HANDLERS_H_
+#define M2AP_ENB_OLD_HANDLERS_H_
+
+#include "m2ap_eNB_defs.h"
+
+void m2ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+int m2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+int m2ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M2AP_ENB_OLD_HANDLERS_H_ */
diff --git a/openair2/M2AP/m2ap_ids.c b/openair2/M2AP/m2ap_ids.c
new file mode 100644
index 0000000000000000000000000000000000000000..347ba36d821a833b5a507650d604e5da65193522
--- /dev/null
+++ b/openair2/M2AP/m2ap_ids.c
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "m2ap_ids.h"
+
+#include <string.h>
+
+void m2ap_id_manager_init(m2ap_id_manager *m)
+{
+  int i;
+  memset(m, 0, sizeof(m2ap_id_manager));
+  for (i = 0; i < M2AP_MAX_IDS; i++)
+    m->ids[i].rnti = -1;
+}
+
+int m2ap_allocate_new_id(m2ap_id_manager *m)
+{
+  int i;
+  for (i = 0; i < M2AP_MAX_IDS; i++)
+    if (m->ids[i].rnti == -1) {
+      m->ids[i].rnti = 0;
+      m->ids[i].id_source = -1;
+      m->ids[i].id_target = -1;
+      return i;
+    }
+  return -1;
+}
+
+void m2ap_release_id(m2ap_id_manager *m, int id)
+{
+  m->ids[id].rnti = -1;
+}
+
+int m2ap_find_id(m2ap_id_manager *m, int id_source, int id_target)
+{
+  int i;
+  for (i = 0; i < M2AP_MAX_IDS; i++)
+    if (m->ids[i].rnti != -1 &&
+        m->ids[i].id_source == id_source &&
+        m->ids[i].id_target == id_target)
+      return i;
+  return -1;
+}
+
+int m2ap_find_id_from_id_source(m2ap_id_manager *m, int id_source)
+{
+  int i;
+  for (i = 0; i < M2AP_MAX_IDS; i++)
+    if (m->ids[i].rnti != -1 &&
+        m->ids[i].id_source == id_source)
+      return i;
+  return -1;
+}
+
+int m2ap_find_id_from_rnti(m2ap_id_manager *m, int rnti)
+{
+  int i;
+  for (i = 0; i < M2AP_MAX_IDS; i++)
+    if (m->ids[i].rnti == rnti)
+      return i;
+  return -1;
+}
+
+void m2ap_set_ids(m2ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target)
+{
+  m->ids[ue_id].rnti      = rnti;
+  m->ids[ue_id].id_source = id_source;
+  m->ids[ue_id].id_target = id_target;
+}
+
+/* real type of target is m2ap_eNB_data_t * */
+void m2ap_id_set_target(m2ap_id_manager *m, int ue_id, void *target)
+{
+  m->ids[ue_id].target = target;
+}
+
+void m2ap_id_set_state(m2ap_id_manager *m, int ue_id, m2id_state_t state)
+{
+  m->ids[ue_id].state = state;
+}
+
+void m2ap_set_reloc_prep_timer(m2ap_id_manager *m, int ue_id, uint64_t time)
+{
+  m->ids[ue_id].t_reloc_prep_start = time;
+}
+
+void m2ap_set_reloc_overall_timer(m2ap_id_manager *m, int ue_id, uint64_t time)
+{
+  m->ids[ue_id].tm2_reloc_overall_start = time;
+}
+
+int m2ap_id_get_id_source(m2ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].id_source;
+}
+
+int m2ap_id_get_id_target(m2ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].id_target;
+}
+
+int m2ap_id_get_rnti(m2ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].rnti;
+}
+
+void *m2ap_id_get_target(m2ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].target;
+}
diff --git a/openair2/M2AP/m2ap_ids.h b/openair2/M2AP/m2ap_ids.h
new file mode 100644
index 0000000000000000000000000000000000000000..8603d67788263bd5b248791be2fad177edfe0510
--- /dev/null
+++ b/openair2/M2AP/m2ap_ids.h
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef M2AP_IDS_H_
+#define M2AP_IDS_H_
+
+#include <stdint.h>
+
+/* maximum number of simultaneous handovers, do not set too high */
+#define M2AP_MAX_IDS	16
+
+/*
+ * state:
+ * - when starting handover in source, UE is in state M2ID_STATE_SOURCE_PREPARE
+ * - after receiving HO_ack in source, UE is in state M2ID_STATE_SOURCE_OVERALL
+ * - in target, UE is in state X2ID_STATE_TARGET
+ * The state is used to check timers.
+ */
+typedef enum {
+  M2ID_STATE_SOURCE_PREPARE,
+  M2ID_STATE_SOURCE_OVERALL,
+  M2ID_STATE_TARGET
+} m2id_state_t;
+
+typedef struct {
+  int           rnti;             /* -1 when free */
+  int           id_source;
+  int           id_target;
+
+  /* the target eNB. Real type is m2ap_eNB_data_t * */
+  void          *target;
+
+  /* state: needed to check timers */
+  m2id_state_t  state;
+
+  /* timers */
+  uint64_t      t_reloc_prep_start;
+  uint64_t      tm2_reloc_overall_start;
+} m2ap_id;
+
+typedef struct {
+  m2ap_id ids[M2AP_MAX_IDS];
+} m2ap_id_manager;
+
+void m2ap_id_manager_init(m2ap_id_manager *m);
+int m2ap_allocate_new_id(m2ap_id_manager *m);
+void m2ap_release_id(m2ap_id_manager *m, int id);
+int m2ap_find_id(m2ap_id_manager *, int id_source, int id_target);
+int m2ap_find_id_from_id_source(m2ap_id_manager *, int id_source);
+int m2ap_find_id_from_rnti(m2ap_id_manager *, int rnti);
+void m2ap_set_ids(m2ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target);
+void m2ap_id_set_state(m2ap_id_manager *m, int ue_id, m2id_state_t state);
+/* real type of target is m2ap_eNB_data_t * */
+void m2ap_id_set_target(m2ap_id_manager *m, int ue_id, void *target);
+void m2ap_set_reloc_prep_timer(m2ap_id_manager *m, int ue_id, uint64_t time);
+void m2ap_set_reloc_overall_timer(m2ap_id_manager *m, int ue_id, uint64_t time);
+int m2ap_id_get_id_source(m2ap_id_manager *m, int ue_id);
+int m2ap_id_get_id_target(m2ap_id_manager *m, int ue_id);
+int m2ap_id_get_rnti(m2ap_id_manager *m, int ue_id);
+void *m2ap_id_get_target(m2ap_id_manager *m, int ue_id);
+
+#endif /* M2AP_IDS_H_ */
diff --git a/openair2/M2AP/m2ap_itti_messaging.c b/openair2/M2AP/m2ap_itti_messaging.c
new file mode 100644
index 0000000000000000000000000000000000000000..b9cfd329015b6792afa0b9218a7297fb90e1c888
--- /dev/null
+++ b/openair2/M2AP/m2ap_itti_messaging.c
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_itti_messaging.c
+ * \brief m2ap tasks for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+#include "m2ap_itti_messaging.h"
+
+void m2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream)
+{
+  MessageDef      *message_p;
+  sctp_data_req_t *sctp_data_req;
+
+  message_p = itti_alloc_new_message(TASK_M2AP_ENB, SCTP_DATA_REQ);
+
+  sctp_data_req = &message_p->ittiMsg.sctp_data_req;
+
+  sctp_data_req->assoc_id      = assoc_id;
+  sctp_data_req->buffer        = buffer;
+  sctp_data_req->buffer_length = buffer_length;
+  sctp_data_req->stream        = stream;
+
+  //LOG_W(M2AP,"assoc_id %d, stream %d\n",assoc_id,stream);
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+
+void m2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id)
+{
+  MessageDef               *message_p = NULL;
+  sctp_close_association_t *sctp_close_association_p = NULL;
+
+  message_p = itti_alloc_new_message(TASK_M2AP_ENB, SCTP_CLOSE_ASSOCIATION);
+  sctp_close_association_p = &message_p->ittiMsg.sctp_close_association;
+  sctp_close_association_p->assoc_id      = assoc_id;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+
+void m2ap_MCE_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream)
+{
+  MessageDef      *message_p;
+  sctp_data_req_t *sctp_data_req;
+
+  message_p = itti_alloc_new_message(TASK_M2AP_MCE, SCTP_DATA_REQ);
+
+  sctp_data_req = &message_p->ittiMsg.sctp_data_req;
+
+  sctp_data_req->assoc_id      = assoc_id;
+  sctp_data_req->buffer        = buffer;
+  sctp_data_req->buffer_length = buffer_length;
+  sctp_data_req->stream        = stream;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+
+void m2ap_MCE_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id)
+{
+  MessageDef               *message_p = NULL;
+  sctp_close_association_t *sctp_close_association_p = NULL;
+
+  message_p = itti_alloc_new_message(TASK_M2AP_MCE, SCTP_CLOSE_ASSOCIATION);
+  sctp_close_association_p = &message_p->ittiMsg.sctp_close_association;
+  sctp_close_association_p->assoc_id      = assoc_id;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
diff --git a/openair2/M2AP/m2ap_itti_messaging.h b/openair2/M2AP/m2ap_itti_messaging.h
new file mode 100644
index 0000000000000000000000000000000000000000..bdc416bca7bb33819aaef5cfa29b83d225ce67d2
--- /dev/null
+++ b/openair2/M2AP/m2ap_itti_messaging.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_itti_messaging.h
+ * \brief m2ap tasks for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_ENB_ITTI_MESSAGING_H_
+#define M2AP_ENB_ITTI_MESSAGING_H_
+
+void m2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+
+void m2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
+
+
+void m2ap_MCE_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+
+void m2ap_MCE_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
+
+
+
+
+#endif /* M2AP_ENB_ITTI_MESSAGING_H_ */
diff --git a/openair2/M2AP/m2ap_timers.c b/openair2/M2AP/m2ap_timers.c
new file mode 100644
index 0000000000000000000000000000000000000000..13ec6423ac46285fe386ea002735ebe3754e72f8
--- /dev/null
+++ b/openair2/M2AP/m2ap_timers.c
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "m2ap_timers.h"
+#include "assertions.h"
+#include "PHY/defs_common.h"         /* TODO: try to not include this */
+#include "m2ap_messages_types.h"
+#include "m2ap_eNB_defs.h"
+#include "m2ap_ids.h"
+#include "m2ap_eNB_management_procedures.h"
+#include "m2ap_eNB_generate_messages.h"
+
+void m2ap_timers_init(m2ap_timers_t *t, int t_reloc_prep, int tm2_reloc_overall)
+{
+  t->tti               = 0;
+  t->t_reloc_prep      = t_reloc_prep;
+  t->tm2_reloc_overall = tm2_reloc_overall;
+}
+
+void m2ap_check_timers(instance_t instance)
+{
+  //m2ap_eNB_instance_t          *instance_p;
+  //m2ap_timers_t                *t;
+  //m2ap_id_manager              *m;
+  //int                          i;
+  //m2ap_handover_cancel_cause_t cause;
+  //void                         *target;
+  //MessageDef                   *msg;
+  //int                          m2_ongoing;
+
+  //instance_p = m2ap_eNB_get_instance(instance);
+  //DevAssert(instance_p != NULL);
+
+  //t = &instance_p->timers;
+  //m = &instance_p->id_manager;
+
+  ///* increment subframe count */
+  //t->tti++;
+
+  //m2_ongoing = 0;
+
+  //for (i = 0; i < M2AP_MAX_IDS; i++) {
+  //  if (m->ids[i].rnti == -1) continue;
+  //  m2_ongoing++;
+
+  //  if (m->ids[i].state == M2ID_STATE_SOURCE_PREPARE &&
+  //      t->tti > m->ids[i].t_reloc_prep_start + t->t_reloc_prep) {
+  //    LOG_I(M2AP, "M2 timeout reloc prep\n");
+  //    /* t_reloc_prep timed out */
+  //    cause = M2AP_T_RELOC_PREP_TIMEOUT;
+  //    goto timeout;
+  //  }
+
+  //  if (m->ids[i].state == M2ID_STATE_SOURCE_OVERALL &&
+  //      t->tti > m->ids[i].tm2_reloc_overall_start + t->tm2_reloc_overall) {
+  //    LOG_I(M2AP, "M2 timeout reloc overall\n");
+  //    /* tm2_reloc_overall timed out */
+  //    cause = M2AP_TM2_RELOC_OVERALL_TIMEOUT;
+  //    goto timeout;
+  //  }
+
+  //  /* no timeout -> check next UE */
+  //  continue;
+
+  // timeout:
+  //  /* inform target about timeout */
+  //  target = m2ap_id_get_target(m, i);
+  //  m2ap_eNB_generate_m2_handover_cancel(instance_p, target, i, cause);
+
+  //  /* inform RRC of cancellation */
+  //  msg = itti_alloc_new_message(TASK_M2AP, M2AP_HANDOVER_CANCEL);
+  //  M2AP_HANDOVER_CANCEL(msg).rnti  = m2ap_id_get_rnti(m, i);
+  //  M2AP_HANDOVER_CANCEL(msg).cause = cause;
+  //  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+
+  //  /* remove UE from M2AP */
+  //  m2ap_release_id(m, i);
+  //}
+
+  //if (m2_ongoing && t->tti % 1000 == 0)
+  //  LOG_I(M2AP, "M2 has %d process ongoing\n", m2_ongoing);
+}
+
+uint64_t m2ap_timer_get_tti(m2ap_timers_t *t)
+{
+  return t->tti;
+}
diff --git a/openair2/M2AP/m2ap_timers.h b/openair2/M2AP/m2ap_timers.h
new file mode 100644
index 0000000000000000000000000000000000000000..d2875d92af654f44b0c4e6d926ac2c4a37d354ef
--- /dev/null
+++ b/openair2/M2AP/m2ap_timers.h
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef M2AP_TIMERS_H_
+#define M2AP_TIMERS_H_
+
+#include <stdint.h>
+#include "platform_types.h"
+
+typedef struct {
+  /* incremented every TTI (every millisecond when in realtime).
+   * Used to check timers.
+   * 64 bits gives us more than 500 million years of (realtime) processing.
+   * It should be enough.
+   */
+  uint64_t tti;
+
+  /* timer values (unit: TTI, ie. millisecond when in realtime) */
+  int      t_reloc_prep;
+  int      tm2_reloc_overall;
+} m2ap_timers_t;
+
+void m2ap_timers_init(m2ap_timers_t *t, int t_reloc_prep, int tm2_reloc_overall);
+void m2ap_check_timers(instance_t instance);
+uint64_t m2ap_timer_get_tti(m2ap_timers_t *t);
+
+#endif /* M2AP_TIMERS_H_ */
diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c
new file mode 100644
index 0000000000000000000000000000000000000000..32dfa5cc42cc8153134c27322b321f15dd1a1a0d
--- /dev/null
+++ b/openair2/MCE_APP/mce_app.c
@@ -0,0 +1,754 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*
+                                mce_app.c
+                             -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include "mce_app.h"
+#include "mce_config.h"
+#include "assertions.h"
+#include "common/ran_context.h"
+#include "targets/RT/USER/lte-softmodem.h"
+
+#include "common/utils/LOG/log.h"
+
+# include "intertask_interface.h"
+#   include "s1ap_eNB.h"
+#   include "sctp_eNB_task.h"
+#   include "gtpv1u_eNB_task.h"
+#   include "flexran_agent.h"
+
+#   include "x2ap_eNB.h"
+#   include "x2ap_messages_types.h"
+#   include "m2ap_eNB.h"
+#   include "m2ap_MCE.h"
+#   include "m2ap_messages_types.h"
+#   include "m3ap_MCE.h"
+#   include "m3ap_messages_types.h"
+#   define X2AP_ENB_REGISTER_RETRY_DELAY   10
+
+#include "openair1/PHY/INIT/phy_init.h"
+extern unsigned char NB_MCE_INST;
+
+extern RAN_CONTEXT_t RC;
+
+#   define MCE_REGISTER_RETRY_DELAY 10
+
+#include "targets/RT/USER/lte-softmodem.h"
+
+static m2ap_mbms_scheduling_information_t * m2ap_mbms_scheduling_information_local = NULL;
+static m2ap_setup_resp_t * m2ap_setup_resp_local = NULL;
+static m2ap_setup_req_t * m2ap_setup_req_local = NULL;
+
+
+/*------------------------------------------------------------------------------*/
+
+static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, uint32_t mce_id_end) {
+  uint32_t         mce_id;
+  MessageDef      *msg_p;
+  uint32_t         register_mce_pending = 0;
+
+  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+    {
+      // M3AP registration
+        /* note:  there is an implicit relationship between the data structure and the message name */
+        msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_REGISTER_MCE_REQ);
+        //RCconfig_S1(msg_p, mce_id);
+
+        //if (mce_id == 0) 
+		//RCconfig_gtpu();
+
+        //LOG_I(MCE_APP,"default drx %d\n",((M3AP_REGISTER_MCE_REQ(msg_p)).default_drx));
+
+        LOG_I(ENB_APP,"[MCE %d] MCE_app_register via M3AP for instance %d\n", mce_id, ENB_MODULE_ID_TO_INSTANCE(mce_id));
+        itti_send_msg_to_task (TASK_M3AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+
+      //if (NODE_IS_DU(node_type)) { // F1AP registration
+      //  // configure F1AP here for F1C
+      //  LOG_I(ENB_APP,"ngran_eNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n");
+      //  msg_p = itti_alloc_new_message (TASK_ENB_APP, F1AP_SETUP_REQ);
+      //  RCconfig_DU_F1(msg_p, enb_id);
+
+      //  LOG_I(ENB_APP,"[eNB %d] eNB_app_register via F1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
+      //  itti_send_msg_to_task (TASK_DU_F1, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+      //  // configure GTPu here for F1U
+      //}
+      //else { // S1AP registration
+      //  /* note:  there is an implicit relationship between the data structure and the message name */
+      //  msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ);
+      //  RCconfig_S1(msg_p, enb_id);
+
+      //  if (enb_id == 0) RCconfig_gtpu();
+
+      //  LOG_I(ENB_APP,"default drx %d\n",((S1AP_REGISTER_ENB_REQ(msg_p)).default_drx));
+
+      //  LOG_I(ENB_APP,"[eNB %d] eNB_app_register via S1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
+      //  itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+      //}
+
+      register_mce_pending++;
+    }
+  }
+
+  return register_mce_pending;
+}
+
+
+/*------------------------------------------------------------------------------*/
+//static uint32_t MCE_app_register_x2(uint32_t mce_id_start, uint32_t mce_id_end) {
+//  uint32_t         mce_id;
+//  MessageDef      *msg_p;
+//  uint32_t         register_mce_m2_pending = 0;
+//
+//  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+//    {
+//      msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ);
+//      RCconfig_X2(msg_p, mce_id);
+//      itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+//      register_mce_x2_pending++;
+//    }
+//  }
+//
+//  return register_mce_x2_pending;
+//}
+
+/*------------------------------------------------------------------------------*/
+//static uint32_t MCE_app_register_m2(uint32_t mce_id_start, uint32_t mce_id_end) {
+//  uint32_t         mce_id;
+//  MessageDef      *msg_p;
+//  uint32_t         register_mce_m2_pending = 0;
+//
+//  LOG_W(MCE_APP,"Register ...");
+//  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+//    {
+//  //	LOG_W(MCE_APP,"Register commes inside ...\n");
+//      msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_REGISTER_MCE_REQ);
+//      //RCconfig_M2_MCE(msg_p, mce_id);
+//      itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+//  //	LOG_W(MCE_APP,"Register sent ...\n");
+//      register_mce_m2_pending++;
+//    }
+//  }
+//
+//  return register_mce_m2_pending;
+//}
+//
+/*------------------------------------------------------------------------------*/
+static uint32_t MCE_app_register_m3(uint32_t mce_id_start, uint32_t mce_id_end) {
+  uint32_t         mce_id;
+  MessageDef      *msg_p;
+  uint32_t         register_mce_m3_pending = 0;
+
+  LOG_D(MCE_APP,"Register ...\n");
+  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+    {
+  //	LOG_W(MCE_APP,"Register commes inside ...\n");
+      msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_REGISTER_MCE_REQ);
+      RCconfig_M3(msg_p, mce_id);
+      itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+  	LOG_D(MCE_APP,"Register sent ...\n");
+      register_mce_m3_pending++;
+    }
+  }
+
+  return register_mce_m3_pending;
+}
+
+/***************************  M3AP MCE handle **********************************/
+//static uint32_t MCE_app_handle_m3ap_mbms_session_start_req(instance_t instance){
+//  	//uint32_t         mce_id=0;
+//  //	MessageDef      *msg_p;
+//  //      msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_MBMS_SESSION_START_RESP);
+//  //      itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	
+//	return 0;
+//}
+
+static uint32_t MCE_app_handle_m3ap_mbms_session_stop_req(instance_t instance){
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_MBMS_SESSION_STOP_RESP);
+        itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+
+static uint32_t MCE_app_handle_m3ap_mbms_session_update_req(instance_t instance){
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_MBMS_SESSION_UPDATE_RESP);
+        itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+//// end M3AP MCE handle **********************************/
+
+
+/***************************  M2AP MCE handle **********************************/
+static uint32_t MCE_app_handle_m2ap_setup_req(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_SETUP_RESP);
+	if(m2ap_setup_resp_local)
+		memcpy(&M2AP_SETUP_RESP(msg_p),m2ap_setup_resp_local,sizeof(m2ap_setup_resp_t));
+	else
+		RCconfig_M2_MCCH(msg_p,0);
+
+	
+        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+
+static uint32_t MCE_app_handle_m2ap_mbms_session_start_resp(instance_t instance){
+	MessageDef      *msg_p;
+  	msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_MBMS_SESSION_START_RESP); 
+	itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	return 0;
+}
+
+//// end M2AP MCE handle **********************************/
+
+
+/***************************  M2AP MCE send **********************************/
+static uint32_t MCE_app_send_m2ap_mbms_scheduling_information(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_MBMS_SCHEDULING_INFORMATION);
+	if(m2ap_mbms_scheduling_information_local)
+		memcpy(&M2AP_MBMS_SCHEDULING_INFORMATION(msg_p),m2ap_mbms_scheduling_information_local,sizeof(m2ap_mbms_scheduling_information_t));
+	else
+		RCconfig_M2_SCHEDULING(msg_p,0);
+        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+
+static uint32_t MCE_app_send_m2ap_session_start_req(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_MBMS_SESSION_START_REQ);
+        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+//static uint32_t MCE_app_send_m2ap_session_stop_req(instance_t instance){
+//	
+//  	//uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_MBMS_SESSION_STOP_REQ);
+//        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+//static uint32_t MCE_app_send_m2ap_mce_configuration_update(instance_t instance){
+//	
+//  	//uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_MCE_CONFIGURATION_UPDATE);
+//        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+//static uint32_t MCE_app_send_m2ap_enb_configuration_update_ack(instance_t instance){
+//	
+//  	//uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_ENB_CONFIGURATION_UPDATE_ACK);
+//        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+//static uint32_t MCE_app_send_m2ap_enb_configuration_update_failure(instance_t instance){
+//	
+//  	//uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_ENB_CONFIGURATION_UPDATE_FAILURE);
+//        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//} //// end M2AP MCE send **********************************/
+
+//static uint32_t MCE_app_send_MME_APP(instance_t instance){
+//	
+//  	//uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MCE_APP, MESSAGE_TEST);
+//        itti_send_msg_to_task (TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+
+//static uint32_t MCE_app_send_MME_APP2(instance_t instance){
+//	
+//  	//uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MCE_APP, MESSAGE_TEST);
+//        itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+
+/*------------------------------------------------------------------------------*/
+void *MCE_app_task(void *args_p) {
+  uint32_t                        mce_nb = 1;//RC.nb_inst; 
+  uint32_t                        mce_id_start = 0;
+  uint32_t                        mce_id_end = mce_id_start + mce_nb;
+  uint32_t                        register_mce_pending=0;
+  uint32_t                        registered_mce=0;
+  //long                            mce_register_retry_timer_id;
+  long 				  mce_scheduling_info_timer_id;
+  //uint32_t                        m3_register_mce_pending = 0;
+ // uint32_t                        x2_registered_mce = 0;
+ // long                            x2_mce_register_retry_timer_id;
+ // uint32_t                        m2_register_mce_pending = 0;
+ // uint32_t                        m2_registered_mce = 0;
+ // long                            m2_mce_register_retry_timer_id;
+  MessageDef                     *msg_p           = NULL;
+  instance_t                      instance;
+  int                             result;
+  /* for no gcc warnings */
+  (void)instance;
+  itti_mark_task_ready (TASK_MCE_APP);
+
+  /* Try to register each MCE */
+  // This assumes that node_type of all RRC instances is the same
+  if (EPC_MODE_ENABLED) {
+    register_mce_pending = MCE_app_register(RC.rrc[0]->node_type, mce_id_start, mce_id_end);
+  }
+
+    /* Try to register each MCE with each other */
+ // if (is_x2ap_enabled() && !NODE_IS_DU(RC.rrc[0]->node_type)) {
+ //   x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ // }
+ // MCE_app_send_MME_APP2(0);
+
+
+ if (is_m2ap_MCE_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) {
+  RCconfig_MCE();
+
+  if(!m2ap_mbms_scheduling_information_local)
+	m2ap_mbms_scheduling_information_local = (m2ap_mbms_scheduling_information_t*)calloc(1,sizeof(m2ap_mbms_scheduling_information_t));
+  if(m2ap_mbms_scheduling_information_local)
+  	RCconfig_m2_scheduling(m2ap_mbms_scheduling_information_local,0);
+
+  if(!m2ap_setup_resp_local)
+	m2ap_setup_resp_local = (m2ap_setup_resp_t*)calloc(1,sizeof(m2ap_setup_resp_t));
+  if(m2ap_setup_resp_local)
+	RCconfig_m2_mcch(m2ap_setup_resp_local,0);
+ }
+
+ // /* Try to register each MCE with MCE each other */
+ if (is_m3ap_MCE_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) {
+   	///*m3_register_mce_pending =*/ MCE_app_register_m3 (mce_id_start, mce_id_end);
+   }
+
+  do {
+    // Wait for a message
+    itti_receive_msg (TASK_MCE_APP, &msg_p);
+    instance = ITTI_MSG_INSTANCE (msg_p);
+
+    switch (ITTI_MSG_ID(msg_p)) {
+    case TERMINATE_MESSAGE:
+      LOG_W(MCE_APP, " *** Exiting MCE_APP thread\n");
+      itti_exit_task ();
+      break;
+
+    case MESSAGE_TEST:
+      LOG_I(MCE_APP, "Received %s\n", ITTI_MSG_NAME(msg_p));
+      break;
+
+    case SOFT_RESTART_MESSAGE:
+      //handle_reconfiguration(instance);
+      break;
+
+    case M3AP_REGISTER_MCE_CNF:
+      //AssertFatal(!NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received S1AP_REGISTER_ENB_CNF\n");
+          LOG_I(MCE_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
+                M3AP_REGISTER_MCE_CNF(msg_p).nb_mme);
+          DevAssert(register_mce_pending > 0);
+          register_mce_pending--;
+
+          /* Check if at least MCE is registered with one MME */
+          if (M3AP_REGISTER_MCE_CNF(msg_p).nb_mme > 0) {
+            registered_mce++;
+          }
+
+          /* Check if all register MCE requests have been processed */
+          if (register_mce_pending == 0) {
+            if (registered_mce == mce_nb) {
+              /* If all MCE are registered, start L2L1 task */
+             // MessageDef *msg_init_p;
+             // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
+             // itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
+            } else {
+              LOG_W(MCE_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n",
+                    mce_nb - registered_mce,  MCE_REGISTER_RETRY_DELAY);
+
+            //  /* Restart the MCE registration process in MCE_REGISTER_RETRY_DELAY seconds */
+            //  if (timer_setup (MCE_REGISTER_RETRY_DELAY, 0, TASK_MCE_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+            //                   NULL, &mce_register_retry_timer_id) < 0) {
+            //    LOG_E(MCE_APP, " Can not start MCE register retry timer, use \"sleep\" instead!\n");
+            //    sleep(MCE_REGISTER_RETRY_DELAY);
+            //    /* Restart the registration process */
+            //    registered_mce = 0;
+            //    register_mce_pending = MCE_app_register (RC.rrc[0]->node_type,mce_id_start, mce_id_end);
+            //  }
+            }
+          }
+
+      break;
+
+   case M3AP_MBMS_SESSION_START_REQ:
+        LOG_I(MCE_APP, "Received M3AP_MBMS_SESSION_START_REQ message %s\n", ITTI_MSG_NAME (msg_p));
+	//MCE_app_handle_m3ap_mbms_session_start_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
+	if(m2ap_setup_req_local)
+		if (timer_setup (2, 0, TASK_MCE_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+                               NULL, &mce_scheduling_info_timer_id) < 0) {
+   		}
+
+
+	break;
+
+   case M3AP_MBMS_SESSION_STOP_REQ:
+        LOG_I(MCE_APP, "Received M3AP_MBMS_SESSION_STOP_REQ message %s\n", ITTI_MSG_NAME (msg_p));
+	MCE_app_handle_m3ap_mbms_session_stop_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
+	break;
+
+   case M3AP_MBMS_SESSION_UPDATE_REQ:
+        LOG_I(MCE_APP, "Received M3AP_MBMS_SESSION_UPDATE_REQ message %s\n", ITTI_MSG_NAME (msg_p));
+	MCE_app_handle_m3ap_mbms_session_update_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
+	break;
+
+
+
+   case M3AP_SETUP_RESP:
+      LOG_I(MCE_APP, "Received M3AP_SETUP_RESP message %s\n", ITTI_MSG_NAME (msg_p));
+   //   //AssertFatal(NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received F1AP_REGISTER_ENB_CNF in CU/MCE\n");
+
+   //   //LOG_I(MCE_APP, "Received %s: associated ngran_MCE_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p),
+   //         //F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate);
+   //   
+   //   //handle_f1ap_setup_resp(&F1AP_SETUP_RESP(msg_p));
+   //   handle_m3ap_setup_resp(&M3AP_SETUP_RESP(msg_p));
+
+   //   DevAssert(register_mce_pending > 0);
+   //   register_mce_pending--;
+
+   //   /* Check if at least MCE is registered with one MME */
+   //   //if (M3AP_SETUP_RESP(msg_p).num_cells_to_activate > 0) {
+   //   //  registered_enb++;
+   //   //}
+
+   //   /* Check if all register MCE requests have been processed */
+   //   if (register_mce_pending == 0) {
+   //     if (registered_mce == mce_nb) {
+   //       /* If all MCE cells are registered, start L2L1 task */
+   //       MessageDef *msg_init_p;
+
+   //       //msg_init_p = itti_alloc_new_message (TASK_MCE_APP, INITIALIZE_MESSAGE);
+   //       //itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
+
+   //     } else {
+   //       LOG_W(MCE_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n",
+   //             mce_nb - registered_mce,  MCE_REGISTER_RETRY_DELAY);
+
+   //       /* Restart the MCE registration process in MCE_REGISTER_RETRY_DELAY seconds */
+   //       if (timer_setup (MCE_REGISTER_RETRY_DELAY, 0, TASK_MCE_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+   //                        NULL, &mce_register_retry_timer_id) < 0) {
+   //         LOG_E(ENB_APP, " Can not start MCE register retry timer, use \"sleep\" instead!\n");
+
+   //         sleep(MCE_REGISTER_RETRY_DELAY);
+   //         /* Restart the registration process */
+   //         registered_mce = 0;
+   //         register_mce_pending = MCE_app_register (RC.rrc[0]->node_type,mce_id_start, mce_id_end);//, enb_properties_p);
+   //       }
+   //     }
+   //   }
+
+      break;
+
+    case M3AP_DEREGISTERED_MCE_IND:
+      if (EPC_MODE_ENABLED) {
+  	LOG_W(MCE_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
+  	      M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme);
+  	/* TODO handle recovering of registration */
+      }
+
+      break;
+
+    case TIMER_HAS_EXPIRED:
+	      LOG_I(MCE_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
+
+	      if (TIMER_HAS_EXPIRED (msg_p).timer_id == mce_scheduling_info_timer_id/*mce_register_retry_timer_id*/) {
+		/* Restart the registration process */
+		//registered_mce = 0;
+		//register_mce_pending = MCE_app_register (RC.rrc[0]->node_type, mce_id_start, mce_id_end);
+		MCE_app_send_m2ap_mbms_scheduling_information(0);
+	      }
+
+	      //if (TIMER_HAS_EXPIRED (msg_p).timer_id == x2_mce_register_retry_timer_id) {
+	      //  /* Restart the registration process */
+	      //  x2_registered_mce = 0;
+	      //  x2_register_mce_pending = MCE_app_register_x2 (mce_id_start, mce_id_end);
+	      //}
+
+      break;
+
+ //   case X2AP_DEREGISTERED_ENB_IND:
+ //     LOG_W(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2);
+ //     /* TODO handle recovering of registration */
+ //     break;
+
+ //   case X2AP_REGISTER_ENB_CNF:
+ //     LOG_I(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           X2AP_REGISTER_ENB_CNF(msg_p).nb_x2);
+ //     DevAssert(x2_register_enb_pending > 0);
+ //     x2_register_enb_pending--;
+
+ //     /* Check if at least MCE is registered with one target MCE */
+ //     if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) {
+ //       x2_registered_enb++;
+ //     }
+
+ //     /* Check if all register MCE requests have been processed */
+ //     if (x2_register_enb_pending == 0) {
+ //       if (x2_registered_enb == enb_nb) {
+ //         /* If all MCE are registered, start RRC HO task */
+ //         } else {
+ //         uint32_t x2_not_associated = enb_nb - x2_registered_enb;
+ //         LOG_W(ENB_APP, " %d MCE %s not associated with the target\n",
+ //               x2_not_associated, x2_not_associated > 1 ? "are" : "is");
+
+ //         // timer to retry
+ //         /* Restart the MCE registration process in ENB_REGISTER_RETRY_DELAY seconds */
+ //         if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
+ //       		   INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
+ //       		   &x2_enb_register_retry_timer_id) < 0) {
+ //           LOG_E(ENB_APP, " Can not start MCE X2AP register: retry timer, use \"sleep\" instead!\n");
+ //           sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
+ //           /* Restart the registration process */
+ //           x2_registered_enb = 0;
+ //           x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ //         }
+ //       }
+ //     }
+
+ //     break;
+
+ //   case M2AP_DEREGISTERED_ENB_IND:
+ //     LOG_W(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           M2AP_DEREGISTERED_ENB_IND(msg_p).nb_m2);
+ //     /* TODO handle recovering of registration */
+ //     break;
+
+ //   case M2AP_REGISTER_ENB_CNF:
+ //     LOG_I(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           M2AP_REGISTER_ENB_CNF(msg_p).nb_m2);
+ //     DevAssert(m2_register_enb_pending > 0);
+ //     m2_register_enb_pending--;
+
+ //     /* Check if at least MCE is registered with one target MCE */
+ //     if (M2AP_REGISTER_ENB_CNF(msg_p).nb_m2 > 0) {
+ //       m2_registered_enb++;
+ //     }
+
+ //     /* Check if all register MCE requests have been processed */
+ //     if (m2_register_enb_pending == 0) {
+ //       if (m2_registered_enb == enb_nb) {
+ //         /* If all MCE are registered, start RRC HO task */
+ //         } else {
+ //         uint32_t m2_not_associated = enb_nb - m2_registered_enb;
+ //         LOG_W(ENB_APP, " %d MCE %s not associated with the target\n",
+ //               m2_not_associated, m2_not_associated > 1 ? "are" : "is");
+
+ //         // timer to retry
+ //         /* Restart the MCE registration process in ENB_REGISTER_RETRY_DELAY seconds */
+ //         //if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
+ //         //      	   INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
+ //         //      	   &x2_enb_register_retry_timer_id) < 0) {
+ //         //  LOG_E(ENB_APP, " Can not start MCE X2AP register: retry timer, use \"sleep\" instead!\n");
+ //         //  sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
+ //         //  /* Restart the registration process */
+ //         //  x2_registered_enb = 0;
+ //         //  x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ //         //}
+ //       }
+ //     }
+
+ //     break;
+   case M2AP_RESET:
+      LOG_I(MCE_APP, "Received M2AP_RESET message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+   case M2AP_SETUP_REQ:
+      LOG_I(MCE_APP, "Received M2AP_SETUP_REQ message %s\n", ITTI_MSG_NAME (msg_p));
+	if(!m2ap_setup_req_local)
+		m2ap_setup_req_local = (m2ap_setup_req_t*)calloc(1,sizeof(m2ap_setup_req_t));
+	if(m2ap_setup_req_local)
+		memcpy(m2ap_setup_req_local,&M2AP_SETUP_REQ(msg_p),sizeof(m2ap_setup_req_t));
+	MCE_app_handle_m2ap_setup_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
+	//MCE_app_send_m2ap_mbms_scheduling_information(0);
+	//if (timer_setup (2, 0, TASK_MCE_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+        //                       NULL, &mce_scheduling_info_timer_id) < 0) {
+   	//}
+
+
+   	/*m3_register_mce_pending =*/ MCE_app_register_m3 (mce_id_start, mce_id_end);
+
+	//MCE_app_send_m2ap_session_start_req(0);
+	break;
+
+   case M2AP_MBMS_SESSION_START_RESP:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_SESSION_START_RESP message %s\n", ITTI_MSG_NAME (msg_p));
+	//MCE_app_send_m2ap_session_stop_req(0);
+	MCE_app_handle_m2ap_mbms_session_start_resp(0);
+	break;
+
+   case M2AP_MBMS_SESSION_STOP_RESP:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_SESSION_STOP_RESP message %s\n", ITTI_MSG_NAME (msg_p));
+	//MCE_app_send_m2ap_session_start_req(0);
+	//MCE_app_handle_m2ap_mbms_session_start_resp(0);
+	//MCE_app_send_MME_APP(0);
+	break;
+
+   case M2AP_MBMS_SCHEDULING_INFORMATION_RESP:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_SCHEDULING_INFORMATION_RESP message %s\n", ITTI_MSG_NAME (msg_p));
+	MCE_app_send_m2ap_session_start_req(0);
+	break;
+
+   case M2AP_ENB_CONFIGURATION_UPDATE:
+      LOG_I(MCE_APP, "Received M2AP_ENB_CONFIGURATION_UPDATE message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+	
+   case M2AP_ERROR_INDICATION:
+      LOG_I(MCE_APP, "Received M2AP_ERROR_INDICATION message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+   case M2AP_MBMS_SESSION_UPDATE_RESP:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_SESSION_UPDATE_RESP message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+   case M2AP_MBMS_SESSION_UPDATE_FAILURE:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_SESSION_UPDATE_FAILURE message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+   case M2AP_MBMS_SERVICE_COUNTING_REPORT:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_SESSION_UPDATE_REPORT message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+   case M2AP_MBMS_OVERLOAD_NOTIFICATION:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_OVERLOAD_NOTIFICATION message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+   case M2AP_MBMS_SERVICE_COUNTING_RESP:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_SESSION_UPDATE_RESP message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+   case M2AP_MBMS_SERVICE_COUNTING_FAILURE:
+      LOG_I(MCE_APP, "Received M2AP_MBMS_SESSION_UPDATE_FAILURE message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+   case M2AP_MCE_CONFIGURATION_UPDATE_ACK:
+      LOG_I(MCE_APP, "Received M2AP_MCE_CONFIGURATION_UPDATE_ACK message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+   case M2AP_MCE_CONFIGURATION_UPDATE_FAILURE:
+      LOG_I(MCE_APP, "Received M2AP_MCE_CONFIGURATION_UPDATE_FAILURE message %s\n", ITTI_MSG_NAME (msg_p));
+	break;
+
+    default:
+      LOG_E(MCE_APP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
+      break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+  } while (1);
+
+  return NULL;
+}
+
+//void handle_reconfiguration(module_id_t mod_id) {
+//  struct timespec start, end;
+//  clock_gettime(CLOCK_MONOTONIC, &start);
+//  flexran_agent_info_t *flexran = RC.flexran[mod_id];
+//  LOG_I(ENB_APP, "lte-softmodem soft-restart requested\n");
+//
+//  if (ENB_WAIT == flexran->node_ctrl_state) {
+//    /* this is already waiting, just release */
+//    pthread_mutex_lock(&flexran->mutex_node_ctrl);
+//    flexran->node_ctrl_state = ENB_NORMAL_OPERATION;
+//    pthread_mutex_unlock(&flexran->mutex_node_ctrl);
+//    pthread_cond_signal(&flexran->cond_node_ctrl);
+//    return;
+//  }
+//
+//  if (stop_L1L2(mod_id) < 0) {
+//    LOG_E(ENB_APP, "can not stop lte-softmodem, aborting restart\n");
+//    return;
+//  }
+//
+//  /* node_ctrl_state should have value ENB_MAKE_WAIT only if this method is not
+//   * executed by the FlexRAN thread */
+//  if (ENB_MAKE_WAIT == flexran->node_ctrl_state) {
+//    LOG_I(ENB_APP, " * MCE %d: Waiting for FlexRAN RTController command *\n", mod_id);
+//    pthread_mutex_lock(&flexran->mutex_node_ctrl);
+//    flexran->node_ctrl_state = ENB_WAIT;
+//
+//    while (ENB_NORMAL_OPERATION != flexran->node_ctrl_state)
+//      pthread_cond_wait(&flexran->cond_node_ctrl, &flexran->mutex_node_ctrl);
+//
+//    pthread_mutex_unlock(&flexran->mutex_node_ctrl);
+//  }
+//
+//  if (restart_L1L2(mod_id) < 0) {
+//    LOG_E(ENB_APP, "can not restart, killing lte-softmodem\n");
+//    exit_fun("can not restart L1L2, killing lte-softmodem");
+//    return;
+//  }
+//
+//  clock_gettime(CLOCK_MONOTONIC, &end);
+//  end.tv_sec -= start.tv_sec;
+//
+//  if (end.tv_nsec >= start.tv_nsec) {
+//    end.tv_nsec -= start.tv_nsec;
+//  } else {
+//    end.tv_sec -= 1;
+//    end.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000;
+//  }
+//
+//  LOG_I(ENB_APP, "lte-softmodem restart succeeded in %ld.%ld s\n", end.tv_sec, end.tv_nsec / 1000000);
+//}
+
+
diff --git a/openair2/MCE_APP/mce_app.h b/openair2/MCE_APP/mce_app.h
new file mode 100644
index 0000000000000000000000000000000000000000..59146b9d0de7c0324f2803652a2a374cc8cc49f8
--- /dev/null
+++ b/openair2/MCE_APP/mce_app.h
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*
+                                mce_app.h
+                             -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#ifndef MCE_APP_H_
+#define MCE_APP_H_
+
+#include <stdint.h>
+#include "platform_types.h"
+
+
+void *MCE_app_task(void *args_p);
+
+//void handle_reconfiguration(module_id_t mod_id);
+
+#endif /* ENB_APP_H_ */
diff --git a/openair2/MCE_APP/mce_config.c b/openair2/MCE_APP/mce_config.c
new file mode 100644
index 0000000000000000000000000000000000000000..975f524ebd1816ec56a092e64116416aad458daf
--- /dev/null
+++ b/openair2/MCE_APP/mce_config.c
@@ -0,0 +1,512 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*
+  mce_config.c
+  -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : Vicomtech, Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#include <string.h>
+#include <inttypes.h>
+
+#include "common/utils/LOG/log.h"
+#include "assertions.h"
+#include "enb_config.h"
+#include "UTIL/OTG/otg.h"
+#include "UTIL/OTG/otg_externs.h"
+#include "intertask_interface.h"
+#include "s1ap_eNB.h"
+#include "sctp_eNB_task.h"
+#include "common/ran_context.h"
+#include "sctp_default_values.h"
+#include "LTE_SystemInformationBlockType2.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "LAYER2/MAC/mac_proto.h"
+#include "PHY/phy_extern.h"
+#include "PHY/INIT/phy_init.h"
+#include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
+#include "nfapi_vnf.h"
+#include "nfapi_pnf.h"
+
+#include "L1_paramdef.h"
+#include "MACRLC_paramdef.h"
+#include "common/config/config_userapi.h"
+#include "RRC_config_tools.h"
+#include "enb_paramdef.h"
+#include "proto_agent.h"
+
+#include "m3ap_MCE.h"
+
+
+
+int RCconfig_MCE(void ) {
+  //int               num_enbs                      = 0;
+  //char             *enb_interface_name_for_S1U    = NULL;
+  char               *mce_interface_name_for_m2_enb = NULL;
+  char               *mce_interface_name_for_m3_mme = NULL;
+  //char             *enb_ipv4_address_for_S1U      = NULL;
+  char               *mce_ipv4_address_for_m2c      = NULL;
+  char               *mce_ipv4_address_for_m3c      = NULL;
+  //uint32_t          enb_port_for_S1U              = 0;
+  uint32_t            mce_port_for_m2c              = 0;
+  uint32_t            mce_port_for_m3c              = 0;
+  char             *address                       = NULL;
+  char             *cidr                          = NULL;
+  //char gtpupath[MAX_OPTNAME_SIZE*2 + 8];
+  char mcepath[MAX_OPTNAME_SIZE*2 + 8];
+  //paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
+  //paramdef_t GTPUParams[]  = GTPUPARAMS_DESC;
+
+  paramdef_t   MCEParams[] = MCE_NETPARAMS_DESC;
+
+  ///* get number of active eNodeBs */
+  //config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL);
+  //num_enbs = ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt;
+  //AssertFatal (num_enbs >0,
+  //             "Failed to parse config file no active eNodeBs in %s \n", ENB_CONFIG_STRING_ACTIVE_ENBS);
+  //sprintf(gtpupath,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,0,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+  sprintf(mcepath,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+  //config_get( GTPUParams,sizeof(GTPUParams)/sizeof(paramdef_t),gtpupath);
+  config_get(MCEParams,sizeof(MCEParams)/sizeof(paramdef_t),mcepath);
+  //cidr = enb_ipv4_address_for_S1U;
+  cidr = mce_ipv4_address_for_m2c;
+  address = strtok(cidr, "/");
+
+  //LOG_W(MCE_APP,"cidr %s\n",cidr);
+  //LOG_W(MCE_APP,"address %s\n",address);
+  //LOG_W(MCE_APP,"mce_interface_name_for_m2_enb %s\n",mce_interface_name_for_m2_enb);
+  //LOG_W(MCE_APP,"mce_ipv4_address_for_m2c %s\n",mce_ipv4_address_for_m2c);
+  //LOG_W(MCE_APP,"mce_ipv4_address_for_m2c %s\n",*(MCEParams[1/*MCE_IPV4_ADDRESS_FOR_M2C_IDX*/].strptr));
+  //LOG_W(MCE_APP,"mce_port_for_m2c %d\n",mce_port_for_m2c);
+  //LOG_W(MCE_APP,"mce_interface_name_for_m3_mme %s\n",mce_interface_name_for_m3_mme);
+  //LOG_W(MCE_APP,"mce_ipv4_address_for_m3c %s\n",mce_ipv4_address_for_m3c);
+  //LOG_W(MCE_APP,"mce_port_for_m3c %d\n",mce_port_for_m3c);
+
+//   strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4_address,*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr));
+
+
+  if (address) {
+    MessageDef *message; 
+    AssertFatal((message = itti_alloc_new_message(TASK_MCE_APP, M2AP_MCE_SCTP_REQ))!=NULL,"");
+    //IPV4_STR_ADDR_TO_INT_NWBO ( address, M2AP_MCE_SCTP_REQ(message).mce_m2_ip_address, "BAD IP ADDRESS FORMAT FOR MCE M2_C !\n" );
+    M2AP_MCE_SCTP_REQ (message).mce_m2_ip_address.ipv6 = 0;
+    M2AP_MCE_SCTP_REQ (message).mce_m2_ip_address.ipv4 = 1;
+    strcpy( M2AP_MCE_SCTP_REQ (message).mce_m2_ip_address.ipv4_address, address);
+    //LOG_I(MCE_APP,"Configuring M2_C address : %s -> %x\n",address,M2AP_MCE_SCTP_REQ(message).mce_m2_ip_address);
+    M2AP_MCE_SCTP_REQ(message).mce_port_for_M2C = mce_port_for_m2c;
+    itti_send_msg_to_task (TASK_M2AP_MCE, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id) 
+  } else
+    LOG_E(MCE_APP,"invalid address for M2AP\n");
+  
+  return 0;
+}
+
+
+int RCconfig_M3(MessageDef *msg_p, uint32_t i) {
+  int l;
+  //int               num_enbs                      = 0;
+  //char             *enb_interface_name_for_S1U    = NULL;
+  char               *mce_interface_name_for_m2_enb = NULL;
+  char               *mce_interface_name_for_m3_mme = NULL;
+  //char             *enb_ipv4_address_for_S1U      = NULL;
+  char               *mce_ipv4_address_for_m2c      = NULL;
+  char               *mce_ipv4_address_for_m3c      = NULL;
+  //uint32_t          enb_port_for_S1U              = 0;
+  uint32_t            mce_port_for_m2c              = 0;
+  uint32_t            mce_port_for_m3c              = 0;
+  char             *address                       = NULL;
+  char             *cidr                          = NULL;
+
+
+  char mcepath[MAX_OPTNAME_SIZE*2 + 8];
+  paramdef_t   MCEParams[] = MCE_NETPARAMS_DESC;
+  paramdef_t M3Params[]  = M3PARAMS_DESC;
+  paramdef_t MCCHParams[]  = MCCH_PARAMS_DESC;
+
+  sprintf(mcepath,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+  config_get(MCEParams,sizeof(MCEParams)/sizeof(paramdef_t),mcepath);
+
+  paramlist_def_t M3ParamList = {MCE_CONFIG_STRING_TARGET_MME_M3_IP_ADDRESS,NULL,0};
+  paramlist_def_t MCCHParamList = {MCE_CONFIG_STRING_MCCH_CONFIG_PER_MBSFN_AREA,NULL,0};
+
+  char aprefix[MAX_OPTNAME_SIZE*80 + 8];
+  sprintf(aprefix,"%s.[%i]","MCEs",0);
+  /* Some default/random parameters */
+  M3AP_REGISTER_MCE_REQ (msg_p).MCE_id = i;
+  //M3AP_REGISTER_MCE_REQ (msg_p).MME_name = "kk";
+  sprintf(aprefix,"%s.[%i]","MCEs",0);
+  config_getlist( &M3ParamList,M3Params,sizeof(M3Params)/sizeof(paramdef_t),aprefix);
+  //printf("M3ParamList.numelt %d\n",M3ParamList.numelt);
+  M3AP_REGISTER_MCE_REQ (msg_p).nb_m3 = 0;
+  for (l = 0; l < M3ParamList.numelt; l++) {
+	M3AP_REGISTER_MCE_REQ (msg_p).nb_m3 += 1;
+	M3AP_REGISTER_MCE_REQ (msg_p).MCE_name         = strdup(*(M3ParamList.paramarray[l][MCE_MCE_NAME_IDX].strptr));
+
+        strcpy(M3AP_REGISTER_MCE_REQ (msg_p).target_mme_m3_ip_address[l].ipv4_address,*(M3ParamList.paramarray[l][MCE2_M3_IPV4_ADDRESS_IDX].strptr));
+        strcpy(M3AP_REGISTER_MCE_REQ (msg_p).target_mme_m3_ip_address[l].ipv6_address,*(M3ParamList.paramarray[l][MCE2_M3_IPV6_ADDRESS_IDX].strptr));
+
+        if (strcmp(*(M3ParamList.paramarray[l][MCE2_M3_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
+		M3AP_REGISTER_MCE_REQ (msg_p).target_mme_m3_ip_address[l].ipv4 = 1;
+		M3AP_REGISTER_MCE_REQ (msg_p).target_mme_m3_ip_address[l].ipv6 = 0;
+	} else if (strcmp(*(M3ParamList.paramarray[l][MCE2_M3_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
+		M3AP_REGISTER_MCE_REQ (msg_p).target_mme_m3_ip_address[l].ipv4 = 0;
+		M3AP_REGISTER_MCE_REQ (msg_p).target_mme_m3_ip_address[l].ipv6 = 1;
+	} else if (strcmp(*(M3ParamList.paramarray[l][MCE2_M3_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
+		M3AP_REGISTER_MCE_REQ (msg_p).target_mme_m3_ip_address[l].ipv4 = 1;
+		M3AP_REGISTER_MCE_REQ (msg_p).target_mme_m3_ip_address[l].ipv6 = 1;
+        }
+	M3AP_REGISTER_MCE_REQ (msg_p).sctp_out_streams = 2;
+	M3AP_REGISTER_MCE_REQ (msg_p).sctp_in_streams  = 2;
+  }
+
+  sprintf(aprefix,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+  config_get( MCEParams,sizeof(MCEParams)/sizeof(paramdef_t),aprefix);
+  M3AP_REGISTER_MCE_REQ (msg_p).mme_port_for_M3C = (uint32_t)*(MCEParams[MCE2_PORT_FOR_M3C_IDX].uptr);
+
+  if ((MCEParams[MCE2_IPV4_ADDR_FOR_M3C_IDX].strptr == NULL) || (M3AP_REGISTER_MCE_REQ (msg_p).mme_port_for_M3C == 0)) {
+      LOG_E(RRC,"Add eNB IPv4 address and/or port for M3C in the CONF file!\n");
+      exit(1);
+  }
+
+  cidr = *(MCEParams[MCE2_IPV4_ADDR_FOR_M3C_IDX].strptr);
+  address = strtok(cidr, "/");
+  M3AP_REGISTER_MCE_REQ (msg_p).mme_m3_ip_address.ipv6 = 0;
+  M3AP_REGISTER_MCE_REQ (msg_p).mme_m3_ip_address.ipv4 = 1;
+  strcpy(M3AP_REGISTER_MCE_REQ (msg_p).mme_m3_ip_address.ipv4_address, address);
+
+  sprintf(aprefix,"%s.[%i]","MCEs",0);
+  config_getlist( &MCCHParamList,MCCHParams,sizeof(MCCHParams)/sizeof(paramdef_t),aprefix);
+  //printf("MCCHParamList.numelt %d\n",MCCHParamList.numelt);
+  for (l = 0; l < MCCHParamList.numelt; l++) {
+        //M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].mbsfn_area = *(MCCHParamList.paramarray[l][MCCH_MBSFN_AREA_IDX].uptr);
+        //M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].pdcch_length = *(MCCHParamList.paramarray[l][MCCH_PDCCH_LENGTH_IDX].uptr);
+        //M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].repetition_period = *(MCCHParamList.paramarray[l][MCCH_REPETITION_PERIOD_IDX].uptr);
+        //M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].offset = *(MCCHParamList.paramarray[l][MCCH_OFFSET_IDX].uptr);
+        //M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].modification_period = *(MCCHParamList.paramarray[l][MCCH_MODIFICATION_PERIOD_IDX].uptr);
+        //M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].subframe_allocation_info = *(MCCHParamList.paramarray[l][MCCH_SF_ALLOCATION_INFO_IDX].uptr);
+        //M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].mcs = strdup(*(MCCHParamList.paramarray[l][MCCH_MCS_IDX].strptr));
+  }
+
+
+  
+
+
+    return 0;
+}
+int RCconfig_m2_mcch(m2ap_setup_resp_t * m2ap_setup_resp, uint32_t i) {
+  int l;
+
+  char mcepath[MAX_OPTNAME_SIZE*2 + 8];
+  paramdef_t MCCHParams[]  = MCCH_PARAMS_DESC;
+  paramdef_t   MCEParams[] = MCE_PARAMS_DESC;
+  paramdef_t PLNMParams[]  = MCE_PLMN_PARAMS_DESC;
+  paramlist_def_t MCCHParamList = {MCE_CONFIG_STRING_MCCH_CONFIG_PER_MBSFN_AREA,NULL,0};
+  char aprefix[MAX_OPTNAME_SIZE*80 + 8];
+  sprintf(mcepath,"%s.[%i]","MCEs",0);
+  config_get(MCEParams,sizeof(MCEParams)/sizeof(paramdef_t),mcepath);
+  m2ap_setup_resp->MCE_id = *(MCEParams[MCE_MCE_ID_IDX].uptr);
+  m2ap_setup_resp->MCE_name = strdup(*(MCEParams[MCE_MCE_NAME_IDX].strptr));;
+  sprintf(mcepath,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_PLMN);
+  config_get(PLNMParams,sizeof(PLNMParams)/sizeof(paramdef_t),mcepath);
+  m2ap_setup_resp->mcc = *(PLNMParams[MCE_CONFIG_STRING_MCC_IDX].uptr);
+  m2ap_setup_resp->mnc = *(PLNMParams[MCE_CONFIG_STRING_MNC_IDX].uptr);
+  m2ap_setup_resp->mnc_digit_length = *(PLNMParams[MCE_CONFIG_STRING_MNC_LENGTH_IDX].uptr);
+  //LOG_E(MCE_APP,"PLNM %d\n",*(PLNMParams[MCE_CONFIG_STRING_MCC_IDX].uptr));
+  //LOG_E(MCE_APP,"PLNM %d\n",*(PLNMParams[MCE_CONFIG_STRING_MNC_LENGTH_IDX].uptr));
+
+
+  sprintf(aprefix,"%s.[%i]","MCEs",0);
+  config_getlist( &MCCHParamList,MCCHParams,sizeof(MCCHParams)/sizeof(paramdef_t),aprefix);
+  //printf("MCCHParamList.numelt %d\n",MCCHParamList.numelt);
+  AssertFatal(MCCHParamList.numelt <= 8, "File wrong parsed\n");
+  for (l = 0; l < MCCHParamList.numelt; l++) {
+        m2ap_setup_resp->mcch_config_per_mbsfn[l].mbsfn_area = *(MCCHParamList.paramarray[l][MCCH_MBSFN_AREA_IDX].uptr);
+        m2ap_setup_resp->mcch_config_per_mbsfn[l].pdcch_length = *(MCCHParamList.paramarray[l][MCCH_PDCCH_LENGTH_IDX].uptr);
+        m2ap_setup_resp->mcch_config_per_mbsfn[l].repetition_period = *(MCCHParamList.paramarray[l][MCCH_REPETITION_PERIOD_IDX].uptr);
+        m2ap_setup_resp->mcch_config_per_mbsfn[l].offset = *(MCCHParamList.paramarray[l][MCCH_OFFSET_IDX].uptr);
+        m2ap_setup_resp->mcch_config_per_mbsfn[l].modification_period = *(MCCHParamList.paramarray[l][MCCH_MODIFICATION_PERIOD_IDX].uptr);
+        m2ap_setup_resp->mcch_config_per_mbsfn[l].subframe_allocation_info = *(MCCHParamList.paramarray[l][MCCH_SF_ALLOCATION_INFO_IDX].uptr);
+        m2ap_setup_resp->mcch_config_per_mbsfn[l].mcs = *(MCCHParamList.paramarray[l][MCCH_MCS_IDX].uptr);
+  }
+  m2ap_setup_resp->num_mcch_config_per_mbsfn = MCCHParamList.numelt;
+	return 0;
+}
+int RCconfig_M2_MCCH(MessageDef *msg_p, uint32_t i) {
+  int l;
+
+  char mcepath[MAX_OPTNAME_SIZE*2 + 8];
+  paramdef_t MCCHParams[]  = MCCH_PARAMS_DESC;
+  paramdef_t   MCEParams[] = MCE_PARAMS_DESC;
+  paramdef_t PLNMParams[]  = MCE_PLMN_PARAMS_DESC;
+  paramlist_def_t MCCHParamList = {MCE_CONFIG_STRING_MCCH_CONFIG_PER_MBSFN_AREA,NULL,0};
+  char aprefix[MAX_OPTNAME_SIZE*80 + 8];
+  sprintf(mcepath,"%s.[%i]","MCEs",0);
+  config_get(MCEParams,sizeof(MCEParams)/sizeof(paramdef_t),mcepath);
+  M2AP_SETUP_RESP (msg_p).MCE_id = *(MCEParams[MCE_MCE_ID_IDX].uptr);
+  M2AP_SETUP_RESP (msg_p).MCE_name = strdup(*(MCEParams[MCE_MCE_NAME_IDX].strptr));;
+  sprintf(mcepath,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_PLMN);
+  config_get(PLNMParams,sizeof(PLNMParams)/sizeof(paramdef_t),mcepath);
+  M2AP_SETUP_RESP (msg_p).mcc = *(PLNMParams[MCE_CONFIG_STRING_MCC_IDX].uptr);
+  M2AP_SETUP_RESP (msg_p).mnc = *(PLNMParams[MCE_CONFIG_STRING_MNC_IDX].uptr);
+  M2AP_SETUP_RESP (msg_p).mnc_digit_length = *(PLNMParams[MCE_CONFIG_STRING_MNC_LENGTH_IDX].uptr);
+  //LOG_E(MCE_APP,"PLNM %d\n",*(PLNMParams[MCE_CONFIG_STRING_MCC_IDX].uptr));
+  //LOG_E(MCE_APP,"PLNM %d\n",*(PLNMParams[MCE_CONFIG_STRING_MNC_LENGTH_IDX].uptr));
+
+
+  sprintf(aprefix,"%s.[%i]","MCEs",0);
+  config_getlist( &MCCHParamList,MCCHParams,sizeof(MCCHParams)/sizeof(paramdef_t),aprefix);
+  //printf("MCCHParamList.numelt %d\n",MCCHParamList.numelt);
+  AssertFatal(MCCHParamList.numelt <= 8, "File wrong parsed\n");
+  for (l = 0; l < MCCHParamList.numelt; l++) {
+        M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].mbsfn_area = *(MCCHParamList.paramarray[l][MCCH_MBSFN_AREA_IDX].uptr);
+        M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].pdcch_length = *(MCCHParamList.paramarray[l][MCCH_PDCCH_LENGTH_IDX].uptr);
+        M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].repetition_period = *(MCCHParamList.paramarray[l][MCCH_REPETITION_PERIOD_IDX].uptr);
+        M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].offset = *(MCCHParamList.paramarray[l][MCCH_OFFSET_IDX].uptr);
+        M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].modification_period = *(MCCHParamList.paramarray[l][MCCH_MODIFICATION_PERIOD_IDX].uptr);
+        M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].subframe_allocation_info = *(MCCHParamList.paramarray[l][MCCH_SF_ALLOCATION_INFO_IDX].uptr);
+        M2AP_SETUP_RESP(msg_p).mcch_config_per_mbsfn[l].mcs = *(MCCHParamList.paramarray[l][MCCH_MCS_IDX].uptr);
+  }
+  M2AP_SETUP_RESP(msg_p).num_mcch_config_per_mbsfn = MCCHParamList.numelt;
+
+
+	return 0;
+}
+int RCconfig_m2_scheduling(  m2ap_mbms_scheduling_information_t * m2ap_mbms_scheduling_information, uint32_t i) {
+  int l,j,k/*,m*/;
+  char mcepath[MAX_OPTNAME_SIZE*2 + 8];
+  paramdef_t MBMS_SCHE_Params[]  = MCE_MBMS_SCHEDULING_INFO_PARAMS_DESC;
+  sprintf(mcepath,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO);
+  //LOG_E(MCE_APP,"%s\n",mcepath);
+  config_get(MBMS_SCHE_Params,sizeof(MBMS_SCHE_Params)/sizeof(paramdef_t),mcepath);
+  //LOG_E(MCE_APP,"%s %d\n",mcepath, *(MBMS_SCHE_Params[MCE_CONFIG_STRING_MCCH_UPDATE_TIME_IDX].uptr));
+  m2ap_mbms_scheduling_information->mcch_update_time=*(MBMS_SCHE_Params[MCE_CONFIG_STRING_MCCH_UPDATE_TIME_IDX].uptr);
+
+  paramdef_t MBMS_CONFIGURATION_Params[] = MCE_MBMS_AREA_CONFIGURATION_LIST_PARAMS_DESC;
+  paramlist_def_t MBMS_AREA_CONFIGURATION_ParamList = {MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,NULL,0};
+  sprintf(mcepath,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO);
+  config_getlist(&MBMS_AREA_CONFIGURATION_ParamList,MBMS_CONFIGURATION_Params,sizeof(MBMS_CONFIGURATION_Params)/sizeof(paramdef_t),mcepath);
+  AssertFatal(MBMS_AREA_CONFIGURATION_ParamList.numelt <= 8, "File wrong parsed\n");
+  //LOG_E(MCE_APP,"%s\n",mcepath);
+  //LOG_E(MCE_APP,"MBMS_AREA_CONFIGURATION_ParamList.numelt %d\n",MBMS_AREA_CONFIGURATION_ParamList.numelt);
+
+  m2ap_mbms_scheduling_information->num_mbms_area_config_list = MBMS_AREA_CONFIGURATION_ParamList.numelt;
+  for (l = 0; l < MBMS_AREA_CONFIGURATION_ParamList.numelt; l++) {
+	m2ap_mbms_scheduling_information->mbms_area_config_list[l].common_sf_allocation_period = *(MBMS_AREA_CONFIGURATION_ParamList.paramarray[l][MCE_CONFIG_STRING_COMMON_SF_ALLOCATION_PERIOD_IDX].uptr);
+	m2ap_mbms_scheduling_information->mbms_area_config_list[l].mbms_area_id=*(MBMS_AREA_CONFIGURATION_ParamList.paramarray[l][MCE_CONFIG_STRING_MBMS_AREA_ID_IDX].uptr);
+  	char mcepath2[MAX_OPTNAME_SIZE*2 + 8];
+  	paramdef_t PMCH_Params[]  = MCE_MBMS_PMCH_CONFIGURATION_LIST_PARAMS_DESC;
+  	paramlist_def_t PMCH_ParamList = {MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST,NULL,0};
+  	sprintf(mcepath2,"%s.[%i].%s.%s.[%i]","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l);
+	//LOG_E(MCE_APP,"%s\n",mcepath2);
+  	config_getlist(&PMCH_ParamList,PMCH_Params,sizeof(PMCH_Params)/sizeof(paramdef_t),mcepath2);
+  	AssertFatal(PMCH_ParamList.numelt <= 8, "File wrong parsed\n");
+	m2ap_mbms_scheduling_information->mbms_area_config_list[l].num_pmch_config_list=PMCH_ParamList.numelt;
+	for(j = 0; j < PMCH_ParamList.numelt; j++){
+	m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].allocated_sf_end =	*(PMCH_ParamList.paramarray[j][MCE_CONFIG_STRING_ALLOCATED_SF_END_IDX].uptr);
+		m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].data_mcs = *(PMCH_ParamList.paramarray[j][MCE_CONFIG_STRING_DATA_MCS_IDX].uptr);
+	m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].mch_scheduling_period= *(PMCH_ParamList.paramarray[j][MCE_CONFIG_STRING_MCH_SCHEDULING_PERIOD_IDX].uptr);
+  		char mcepath3[MAX_OPTNAME_SIZE*2 + 8];
+		paramdef_t MBMS_SESSION_LIST_Params[] = MCE_MBMS_MBMS_SESSION_LIST_DESC;
+		paramlist_def_t MBMS_SESSION_LIST_ParamList = {MCE_CONFIG_STRING_MBMS_SESSION_LIST,NULL,0};
+  		sprintf(mcepath3,"%s.[%i].%s.%s.[%i].%s.[%i]","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l,MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST,j);
+  		config_getlist(&MBMS_SESSION_LIST_ParamList,MBMS_SESSION_LIST_Params,sizeof(MBMS_SESSION_LIST_Params)/sizeof(paramdef_t),mcepath3);
+		//LOG_E(MCE_APP,"%s ---- %d\n",mcepath3, MBMS_SESSION_LIST_ParamList.numelt);
+  		AssertFatal(MBMS_SESSION_LIST_ParamList.numelt <= 8, "File wrong parsed\n");
+		m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].num_mbms_session_list = MBMS_SESSION_LIST_ParamList.numelt;
+		for(k = 0; k < MBMS_SESSION_LIST_ParamList.numelt; k++ ){
+
+  			//char mcepath4[MAX_OPTNAME_SIZE*8 + 8];
+			//paramdef_t MBMS_SESSION_LIST_PER_PMCH_Params[] = MCE_MBMS_MBMS_SESSION_LIST_PER_PMCH_PARAMS_DESC;
+			//paramlist_def_t MBMS_SESSION_LIST_PER_PMCH_ParamList = {MCE_CONFIG_STRING_MBMS_SESSION_LIST_PER_PMCH,NULL,0};
+	        	//sprintf(mcepath4,"%s.[%i].%s.%s.[%i].%s.[%i].%s.[%i]","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l,MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST,j,MCE_CONFIG_STRING_MBMS_SESSION_LIST,k);
+			//LOG_E(MCE_APP,"%s\n",mcepath4);
+			//config_getlist(&MBMS_SESSION_LIST_PER_PMCH_ParamList,MBMS_SESSION_LIST_PER_PMCH_Params,sizeof(MBMS_SESSION_LIST_PER_PMCH_Params)/sizeof(paramdef_t),mcepath4);
+			//m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].num_mbms_session_per_pmch = MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt;
+			//for(m = 0; m < MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt; m++){
+
+			m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].service_id = 	
+			*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_SERVICE_ID_IDX].uptr);
+			uint32_t lcid =*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_LCID_IDX].uptr);
+			m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].lcid =lcid;	
+			//uint32_t service_id2=*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_LCID_IDX].uptr);
+			//m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].service_id2 =service_id2;
+			//LOG_E(MCE_APP,"lcid %ld\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_LCID_IDX].uptr));
+			//LOG_E(MCE_APP,"service_id %d\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_SERVICE_ID_IDX].uptr));
+
+			char mcepath5[MAX_OPTNAME_SIZE*8 + 8];
+			paramdef_t PLNMParams[]  = MCE_PLMN_PARAMS_DESC;
+			sprintf(mcepath5,"%s.[%i].%s.%s.[%i].%s.[%i].%s.[%i].%s","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l,MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST,j,MCE_CONFIG_STRING_MBMS_SESSION_LIST,k,MCE_CONFIG_STRING_PLMN);
+			config_get(PLNMParams,sizeof(PLNMParams)/sizeof(paramdef_t),mcepath5);
+			//LOG_E(MCE_APP,"PLNM %d\n",*(PLNMParams[MCE_CONFIG_STRING_MNC_LENGTH_IDX].uptr));
+			m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].mcc = 	*(PLNMParams[MCE_CONFIG_STRING_MCC_IDX].uptr);
+			m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].mnc = 	*(PLNMParams[MCE_CONFIG_STRING_MNC_IDX].uptr);
+			m2ap_mbms_scheduling_information->mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].mnc_length = 	*(PLNMParams[MCE_CONFIG_STRING_MNC_LENGTH_IDX].uptr);
+			
+			//}
+			//LOG_E(MCE_APP,"MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt %d\n",MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt);
+			//AssertFatal(MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt <= 8, "File wrong parsed\n");
+
+			//printf("%d\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_PLNM_IDENTITY_IDX].uptr));
+			//printf("%d\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_SERVICE_ID_IDX].uptr));
+			//printf("%d\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_LCID_IDX].uptr));
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+		}
+	}
+	paramdef_t MBSFN_SF_Params[]  = MCE_MBMS_MBMS_SF_CONFIGURATION_LIST_PARAMS_DESC;
+  	paramlist_def_t MBSFN_SF_ParamList = {MCE_CONFIG_STRING_MBMS_SF_CONFIGURATION_LIST,NULL,0};
+  	sprintf(mcepath2,"%s.[%i].%s.%s.[%i]","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l);
+	//LOG_E(MCE_APP,"%s\n",mcepath2);
+  	config_getlist(&MBSFN_SF_ParamList,MBSFN_SF_Params,sizeof(MBSFN_SF_Params)/sizeof(paramdef_t),mcepath2);
+  	AssertFatal(MBSFN_SF_ParamList.numelt <= 8, "File wrong parsed\n");
+
+	m2ap_mbms_scheduling_information->mbms_area_config_list[l].num_mbms_sf_config_list=MBSFN_SF_ParamList.numelt;
+	for(j = 0; j < MBSFN_SF_ParamList.numelt; j++){
+		m2ap_mbms_scheduling_information->mbms_area_config_list[l].mbms_sf_config_list[j].radioframe_allocation_period=*(MBSFN_SF_ParamList.paramarray[j][MCE_CONFIG_STRING_RADIOFRAME_ALLOCATION_PERIOD_IDX].uptr);
+		m2ap_mbms_scheduling_information->mbms_area_config_list[l].mbms_sf_config_list[j].radioframe_allocation_offset = *(MBSFN_SF_ParamList.paramarray[j][MCE_CONFIG_STRING_RADIOFRAME_ALLOOCATION_OFFSET_IDX].uptr);
+		if(strcmp(*(MBSFN_SF_ParamList.paramarray[j][MCE_CONFIG_STRING_NUM_FRAME_IDX].strptr),"oneFrame")==0){
+			m2ap_mbms_scheduling_information->mbms_area_config_list[l].mbms_sf_config_list[j].is_four_sf = 0;
+		}else{
+			m2ap_mbms_scheduling_information->mbms_area_config_list[l].mbms_sf_config_list[j].is_four_sf = 1;
+		}
+		m2ap_mbms_scheduling_information->mbms_area_config_list[l].mbms_sf_config_list[j].subframe_allocation = *(MBSFN_SF_ParamList.paramarray[j][MCE_CONFIG_STRING_SUBFRAME_ALLOCATION_IDX].uptr);
+	}
+
+
+  }
+	return 0;
+}
+int RCconfig_M2_SCHEDULING(MessageDef *msg_p, uint32_t i) {
+  int l,j,k/*,m*/;
+  char mcepath[MAX_OPTNAME_SIZE*2 + 8];
+  paramdef_t MBMS_SCHE_Params[]  = MCE_MBMS_SCHEDULING_INFO_PARAMS_DESC;
+  sprintf(mcepath,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO);
+  //LOG_E(MCE_APP,"%s\n",mcepath);
+  config_get(MBMS_SCHE_Params,sizeof(MBMS_SCHE_Params)/sizeof(paramdef_t),mcepath);
+  //LOG_E(MCE_APP,"%s %d\n",mcepath, *(MBMS_SCHE_Params[MCE_CONFIG_STRING_MCCH_UPDATE_TIME_IDX].uptr));
+  M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mcch_update_time=*(MBMS_SCHE_Params[MCE_CONFIG_STRING_MCCH_UPDATE_TIME_IDX].uptr);
+
+  paramdef_t MBMS_CONFIGURATION_Params[] = MCE_MBMS_AREA_CONFIGURATION_LIST_PARAMS_DESC;
+  paramlist_def_t MBMS_AREA_CONFIGURATION_ParamList = {MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,NULL,0};
+  sprintf(mcepath,"%s.[%i].%s","MCEs",0,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO);
+  config_getlist(&MBMS_AREA_CONFIGURATION_ParamList,MBMS_CONFIGURATION_Params,sizeof(MBMS_CONFIGURATION_Params)/sizeof(paramdef_t),mcepath);
+  AssertFatal(MBMS_AREA_CONFIGURATION_ParamList.numelt <= 8, "File wrong parsed\n");
+  //LOG_E(MCE_APP,"%s\n",mcepath);
+  //LOG_E(MCE_APP,"MBMS_AREA_CONFIGURATION_ParamList.numelt %d\n",MBMS_AREA_CONFIGURATION_ParamList.numelt);
+
+  M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).num_mbms_area_config_list = MBMS_AREA_CONFIGURATION_ParamList.numelt;
+  for (l = 0; l < MBMS_AREA_CONFIGURATION_ParamList.numelt; l++) {
+	M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].common_sf_allocation_period = *(MBMS_AREA_CONFIGURATION_ParamList.paramarray[l][MCE_CONFIG_STRING_COMMON_SF_ALLOCATION_PERIOD_IDX].uptr);
+	M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].mbms_area_id=*(MBMS_AREA_CONFIGURATION_ParamList.paramarray[l][MCE_CONFIG_STRING_MBMS_AREA_ID_IDX].uptr);
+  	char mcepath2[MAX_OPTNAME_SIZE*2 + 8];
+  	paramdef_t PMCH_Params[]  = MCE_MBMS_PMCH_CONFIGURATION_LIST_PARAMS_DESC;
+  	paramlist_def_t PMCH_ParamList = {MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST,NULL,0};
+  	sprintf(mcepath2,"%s.[%i].%s.%s.[%i]","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l);
+	//LOG_E(MCE_APP,"%s\n",mcepath2);
+  	config_getlist(&PMCH_ParamList,PMCH_Params,sizeof(PMCH_Params)/sizeof(paramdef_t),mcepath2);
+  	AssertFatal(PMCH_ParamList.numelt <= 8, "File wrong parsed\n");
+	M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].num_pmch_config_list=PMCH_ParamList.numelt;
+	for(j = 0; j < PMCH_ParamList.numelt; j++){
+	M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].allocated_sf_end =	*(PMCH_ParamList.paramarray[j][MCE_CONFIG_STRING_ALLOCATED_SF_END_IDX].uptr);
+		M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].data_mcs = *(PMCH_ParamList.paramarray[j][MCE_CONFIG_STRING_DATA_MCS_IDX].uptr);
+	M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].mch_scheduling_period= *(PMCH_ParamList.paramarray[j][MCE_CONFIG_STRING_MCH_SCHEDULING_PERIOD_IDX].uptr);
+  		char mcepath3[MAX_OPTNAME_SIZE*2 + 8];
+		paramdef_t MBMS_SESSION_LIST_Params[] = MCE_MBMS_MBMS_SESSION_LIST_DESC;
+		paramlist_def_t MBMS_SESSION_LIST_ParamList = {MCE_CONFIG_STRING_MBMS_SESSION_LIST,NULL,0};
+  		sprintf(mcepath3,"%s.[%i].%s.%s.[%i].%s.[%i]","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l,MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST,j);
+  		config_getlist(&MBMS_SESSION_LIST_ParamList,MBMS_SESSION_LIST_Params,sizeof(MBMS_SESSION_LIST_Params)/sizeof(paramdef_t),mcepath3);
+		//LOG_E(MCE_APP,"%s ---- %d\n",mcepath3, MBMS_SESSION_LIST_ParamList.numelt);
+  		AssertFatal(MBMS_SESSION_LIST_ParamList.numelt <= 8, "File wrong parsed\n");
+		M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].num_mbms_session_list = MBMS_SESSION_LIST_ParamList.numelt;
+		for(k = 0; k < MBMS_SESSION_LIST_ParamList.numelt; k++ ){
+
+  			//char mcepath4[MAX_OPTNAME_SIZE*8 + 8];
+			//paramdef_t MBMS_SESSION_LIST_PER_PMCH_Params[] = MCE_MBMS_MBMS_SESSION_LIST_PER_PMCH_PARAMS_DESC;
+			//paramlist_def_t MBMS_SESSION_LIST_PER_PMCH_ParamList = {MCE_CONFIG_STRING_MBMS_SESSION_LIST_PER_PMCH,NULL,0};
+	        	//sprintf(mcepath4,"%s.[%i].%s.%s.[%i].%s.[%i].%s.[%i]","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l,MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST,j,MCE_CONFIG_STRING_MBMS_SESSION_LIST,k);
+			//LOG_E(MCE_APP,"%s\n",mcepath4);
+			//config_getlist(&MBMS_SESSION_LIST_PER_PMCH_ParamList,MBMS_SESSION_LIST_PER_PMCH_Params,sizeof(MBMS_SESSION_LIST_PER_PMCH_Params)/sizeof(paramdef_t),mcepath4);
+			//M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].num_mbms_session_per_pmch = MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt;
+			//for(m = 0; m < MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt; m++){
+
+			M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].service_id = 	
+			*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_SERVICE_ID_IDX].uptr);
+			uint32_t lcid =*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_LCID_IDX].uptr);
+			M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].lcid =lcid;	
+			//uint32_t service_id2=*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_LCID_IDX].uptr);
+			//M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].service_id2 =service_id2;
+			//LOG_E(MCE_APP,"lcid %ld\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_LCID_IDX].uptr));
+			//LOG_E(MCE_APP,"service_id %d\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_MBMS_SERVICE_ID_IDX].uptr));
+
+			char mcepath5[MAX_OPTNAME_SIZE*8 + 8];
+			paramdef_t PLNMParams[]  = MCE_PLMN_PARAMS_DESC;
+			sprintf(mcepath5,"%s.[%i].%s.%s.[%i].%s.[%i].%s.[%i].%s","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l,MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST,j,MCE_CONFIG_STRING_MBMS_SESSION_LIST,k,MCE_CONFIG_STRING_PLMN);
+			config_get(PLNMParams,sizeof(PLNMParams)/sizeof(paramdef_t),mcepath5);
+			//LOG_E(MCE_APP,"PLNM %d\n",*(PLNMParams[MCE_CONFIG_STRING_MNC_LENGTH_IDX].uptr));
+			M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].mcc = 	*(PLNMParams[MCE_CONFIG_STRING_MCC_IDX].uptr);
+			M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].mnc = 	*(PLNMParams[MCE_CONFIG_STRING_MNC_IDX].uptr);
+			M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].pmch_config_list[j].mbms_session_list[k].mnc_length = 	*(PLNMParams[MCE_CONFIG_STRING_MNC_LENGTH_IDX].uptr);
+			
+			//}
+			//LOG_E(MCE_APP,"MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt %d\n",MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt);
+			//AssertFatal(MBMS_SESSION_LIST_PER_PMCH_ParamList.numelt <= 8, "File wrong parsed\n");
+
+			//printf("%d\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_PLNM_IDENTITY_IDX].uptr));
+			//printf("%d\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_SERVICE_ID_IDX].uptr));
+			//printf("%d\n",*(MBMS_SESSION_LIST_ParamList.paramarray[k][MCE_CONFIG_STRING_LCID_IDX].uptr));
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+			//*((MBMS_SESSION_LIST_ParamList[k][].uptr);
+		}
+	}
+	paramdef_t MBSFN_SF_Params[]  = MCE_MBMS_MBMS_SF_CONFIGURATION_LIST_PARAMS_DESC;
+  	paramlist_def_t MBSFN_SF_ParamList = {MCE_CONFIG_STRING_MBMS_SF_CONFIGURATION_LIST,NULL,0};
+  	sprintf(mcepath2,"%s.[%i].%s.%s.[%i]","MCEs",i,MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO,MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST,l);
+	//LOG_E(MCE_APP,"%s\n",mcepath2);
+  	config_getlist(&MBSFN_SF_ParamList,MBSFN_SF_Params,sizeof(MBSFN_SF_Params)/sizeof(paramdef_t),mcepath2);
+  	AssertFatal(MBSFN_SF_ParamList.numelt <= 8, "File wrong parsed\n");
+
+	M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].num_mbms_sf_config_list=MBSFN_SF_ParamList.numelt;
+	for(j = 0; j < MBSFN_SF_ParamList.numelt; j++){
+		M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].mbms_sf_config_list[j].radioframe_allocation_period=*(MBSFN_SF_ParamList.paramarray[j][MCE_CONFIG_STRING_RADIOFRAME_ALLOCATION_PERIOD_IDX].uptr);
+		M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].mbms_sf_config_list[j].radioframe_allocation_offset = *(MBSFN_SF_ParamList.paramarray[j][MCE_CONFIG_STRING_RADIOFRAME_ALLOOCATION_OFFSET_IDX].uptr);
+		if(strcmp(*(MBSFN_SF_ParamList.paramarray[j][MCE_CONFIG_STRING_NUM_FRAME_IDX].strptr),"oneFrame")==0){
+			M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].mbms_sf_config_list[j].is_four_sf = 0;
+		}else{
+			M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].mbms_sf_config_list[j].is_four_sf = 1;
+		}
+		M2AP_MBMS_SCHEDULING_INFORMATION(msg_p).mbms_area_config_list[l].mbms_sf_config_list[j].subframe_allocation = *(MBSFN_SF_ParamList.paramarray[j][MCE_CONFIG_STRING_SUBFRAME_ALLOCATION_IDX].uptr);
+	}
+
+
+  }
+
+  return 0;
+}
+
diff --git a/openair2/MCE_APP/mce_config.h b/openair2/MCE_APP/mce_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3394015406031da4c1f3d630de7dca57e2615fc
--- /dev/null
+++ b/openair2/MCE_APP/mce_config.h
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*
+                                mce_config.h
+                             -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH, Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#ifndef MCE_CONFIG_H_
+#define MCE_CONFIG_H_
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libconfig.h>
+
+#include "commonDef.h"
+#include "platform_types.h"
+#include "platform_constants.h"
+#include "PHY/impl_defs_lte.h"
+#include "PHY/defs_eNB.h"
+#include "s1ap_messages_types.h"
+#include "f1ap_messages_types.h"
+#include "LTE_SystemInformationBlockType2.h"
+#include "rrc_messages_types.h"
+#include "RRC/LTE/rrc_defs.h"
+#include <intertask_interface.h>
+#include "enb_paramdef.h"
+
+#define IPV4_STR_ADDR_TO_INT_NWBO(AdDr_StR,NwBo,MeSsAgE ) do {\
+            struct in_addr inp;\
+            if ( inet_aton(AdDr_StR, &inp ) < 0 ) {\
+                AssertFatal (0, MeSsAgE);\
+            } else {\
+                NwBo = inp.s_addr;\
+            }\
+        } while (0);
+
+
+void read_config_and_init(void);
+
+int RCconfig_MCE(void);
+int RCconfig_M3(MessageDef *msg_p, uint32_t i);
+int RCconfig_M2_MCCH(MessageDef *msg_p, uint32_t i);
+int RCconfig_m2_mcch(m2ap_setup_resp_t * m2ap_setup_resp, uint32_t i);
+int RCconfig_M2_SCHEDULING(MessageDef *msg_p, uint32_t i);
+int RCconfig_m2_scheduling(m2ap_mbms_scheduling_information_t *m2ap_mbms_scheduling_information, uint32_t i);
+
+
+#endif /* MCE_CONFIG_H_ */
+/** @} */
diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h
index ff264f921e7ac5370f5796e8bd807a662e7cea5c..b964ab565d8dd65bf6d2cd96fef5dfc48a7cd9e3 100644
--- a/openair2/PHY_INTERFACE/IF_Module.h
+++ b/openair2/PHY_INTERFACE/IF_Module.h
@@ -140,6 +140,9 @@ typedef struct IF_Module_s {
   void (*UL_indication)(UL_IND_t *UL_INFO);
   void (*schedule_response)(Sched_Rsp_t *Sched_INFO);
   void (*PHY_config_req)(PHY_Config_t *config_INFO);
+  void (*PHY_config_req)(PHY_Config_t* config_INFO);
+  void (*PHY_config_update_sib2_req)(PHY_Config_t* config_INFO);
+  void (*PHY_config_update_sib13_req)(PHY_Config_t* config_INFO);
   uint32_t CC_mask;
   uint16_t current_frame;
   uint8_t current_subframe;
diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c
index 930387c742489c1a413cd76b3bb3a56bb3f74502..14974c2e158d43adbd1275b036596555524905ef 100644
--- a/openair2/PHY_INTERFACE/phy_stub_UE.c
+++ b/openair2/PHY_INTERFACE/phy_stub_UE.c
@@ -1049,7 +1049,11 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
 }
 
 void phy_config_request(PHY_Config_t *phy_config) {
+}
 
+void phy_config_update_sib2_request(PHY_Config_t *phy_config) {
+}
+void phy_config_update_sib13_request(PHY_Config_t *phy_config) {
 }
 
 uint32_t from_earfcn(int eutra_bandP, uint32_t dl_earfcn) { return(0);}
diff --git a/openair2/RRC/LTE/L2_interface.c b/openair2/RRC/LTE/L2_interface.c
index 54dba6862883011e13e702d380e56bc01c202477..6e6eb0d1c9a77cf738ed1fdcba0a068616a39497 100644
--- a/openair2/RRC/LTE/L2_interface.c
+++ b/openair2/RRC/LTE/L2_interface.c
@@ -78,7 +78,7 @@ mac_rrc_data_req(
   carrier = &rrc->carrier[0];
   mib     = &carrier->mib;
 
-  if(Srb_id == BCCH_SI_MBMS) {
+  if((Srb_id & RAB_OFFSET) == BCCH_SI_MBMS){
     if (frameP%4 == 0) {
       memcpy(&buffer_pP[0],
              RC.rrc[Mod_idP]->carrier[CC_id].SIB1_MBMS,
@@ -206,7 +206,7 @@ mac_rrc_data_req(
            RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]);
 
     if (LOG_DEBUGFLAG(DEBUG_RRC)) {
-      LOG_D(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE \n",Mod_idP,frameP);
+      LOG_W(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE \n",Mod_idP,frameP);
 
       for (int i=0; i<RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]; i++) {
         LOG_T(RRC,"%x.",buffer_pP[i]);
@@ -299,10 +299,8 @@ mac_rrc_data_ind(
       if (ue_context_p->ue_context.Status != RRC_RECONFIGURED) {
         LOG_E(RRC,"[eNB %d] Received C-RNTI ,but UE %x status(%d) not RRC_RECONFIGURED\n",module_idP,rntiP,ue_context_p->ue_context.Status);
         return (-1);
-      } else {
-        rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt,ue_context_p,0);
-        ue_context_p->ue_context.Status = RRC_RECONFIGURED;
-      }
+      } 
+      rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt,ue_context_p,0);
     }
   }
 
diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c
index 48cc432a0653b54928c58ecced5a1ad356ab401a..14368508f778fb02af10a25d0fa5064fdc622415 100644
--- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c
@@ -231,7 +231,7 @@ uint8_t do_MIB_FeMBMS(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_
   mib_fembms->message.spare.bits_unused = 6;  // This makes a spare of 10 bits
   //TODO additionalNonBMSFNSubframes-r14  INTEGER (0..3) ?
   //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
-  xer_fprint(stdout, &asn_DEF_LTE_BCCH_BCH_Message_MBMS, (void *)mib_fembms);
+    //xer_fprint(stdout, &asn_DEF_LTE_BCCH_BCH_Message_MBMS, (void *)mib_fembms);
   //}
   enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_BCH_Message_MBMS,
                                    NULL,
@@ -586,7 +586,7 @@ uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier,
   }
 
   //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
-  xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, (void *)bcch_message);
+    //xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, (void *)bcch_message);
   //}
   enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS,
                                    NULL,
@@ -603,37 +603,123 @@ uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier,
 
   return((enc_rval.encoded+7)/8);
 }
+
 //-----------------------------------------------------------------------------
 /*
  * Generate the configuration structure for CDRX feature
  */
-LTE_DRX_Config_t *do_DrxConfig(uint8_t Mod_id,
-                               int CC_id,
-                               RrcConfigurationReq *configuration,
+LTE_DRX_Config_t *do_DrxConfig(int CC_id, 
+                               RrcConfigurationReq *configuration, 
                                LTE_UE_EUTRA_Capability_t *UEcap)
 //-----------------------------------------------------------------------------
 {
+  /* Check CC id */
+  if (CC_id >= MAX_NUM_CCs) {
+    LOG_E(RRC, "[do_DrxConfig] Invalid CC_id for DRX configuration\n");
+    return NULL;
+  }
+
+  /* No CDRX configuration */
+  if (configuration->radioresourceconfig[CC_id].drx_Config_present == LTE_DRX_Config_PR_NOTHING) {
+    return NULL;
+  }
+
+  /* CDRX not implemented for TDD */
+  if (configuration->frame_type[CC_id] == 1) {
+    LOG_E(RRC, "[do_DrxConfig] CDRX not implemented for TDD\n");
+    return NULL;
+  }
+
+  /* Need UE capabilities */  
+  if (!UEcap) {
+    LOG_E(RRC,"[do_DrxConfig] No UEcap pointer\n");
+    return NULL;
+  }
+
+  /* Check the UE capabilities, CDRX not implemented for Coverage Extension */
+  LTE_UE_EUTRA_Capability_v920_IEs_t	*cap_920 = NULL;
+  LTE_UE_EUTRA_Capability_v940_IEs_t	*cap_940 = NULL;
+  LTE_UE_EUTRA_Capability_v1020_IEs_t	*cap_1020 = NULL;
+  LTE_UE_EUTRA_Capability_v1060_IEs_t	*cap_1060 = NULL;
+  LTE_UE_EUTRA_Capability_v1090_IEs_t	*cap_1090 = NULL;
+  LTE_UE_EUTRA_Capability_v1130_IEs_t	*cap_1130 = NULL;
+  LTE_UE_EUTRA_Capability_v1170_IEs_t	*cap_1170 = NULL;
+  LTE_UE_EUTRA_Capability_v1180_IEs_t	*cap_1180 = NULL;
+  LTE_UE_EUTRA_Capability_v11a0_IEs_t	*cap_11a0 = NULL;
+  LTE_UE_EUTRA_Capability_v1250_IEs_t	*cap_1250 = NULL;
+  LTE_UE_EUTRA_Capability_v1260_IEs_t	*cap_1260 = NULL;
+  LTE_UE_EUTRA_Capability_v1270_IEs_t	*cap_1270 = NULL;
+  LTE_UE_EUTRA_Capability_v1280_IEs_t	*cap_1280 = NULL;
+  LTE_UE_EUTRA_Capability_v1310_IEs_t	*cap_1310 = NULL;
+  LTE_CE_Parameters_r13_t	*CE_param = NULL;
+  long *ce_a_param = NULL;
+
+  cap_920 = UEcap->nonCriticalExtension;
+  if (cap_920) {
+    cap_940 = cap_920->nonCriticalExtension;
+    if (cap_940) {
+      cap_1020 = cap_940->nonCriticalExtension;
+      if (cap_1020) {
+        cap_1060 = cap_1020->nonCriticalExtension;
+        if (cap_1060) {
+          cap_1090 = cap_1060->nonCriticalExtension;
+          if (cap_1090) {
+            cap_1130 = cap_1090->nonCriticalExtension;
+            if (cap_1130) {
+              cap_1170 = cap_1130->nonCriticalExtension;
+              if (cap_1170) {
+                cap_1180 = cap_1170->nonCriticalExtension;
+                if (cap_1180) {
+                  cap_11a0 = cap_1180->nonCriticalExtension;
+                  if (cap_11a0) {
+                    cap_1250 = cap_11a0->nonCriticalExtension;
+                    if (cap_1250) {
+                      cap_1260 = cap_1250->nonCriticalExtension;
+                      if (cap_1260) {
+                        cap_1270 = cap_1260->nonCriticalExtension;
+                        if (cap_1270) {
+                          cap_1280 = cap_1270->nonCriticalExtension;
+                          if (cap_1280) {
+                            cap_1310 = cap_1280->nonCriticalExtension;
+                            if (cap_1310) {
+                              CE_param = cap_1310->ce_Parameters_r13;
+                              if (CE_param) {
+                                ce_a_param = CE_param->ce_ModeA_r13;
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (ce_a_param) {
+    LOG_E(RRC,"[do_DrxConfig] Coverage Extension not supported by CDRX\n");
+    return NULL;
+  }
+
   LTE_DRX_Config_t *drxConfig = NULL;
   BIT_STRING_t *featureGroupIndicators = NULL;
   bool ueSupportCdrxShortFlag = false;
   bool ueSupportCdrxLongFlag = false;
 
   /* Check the UE capabilities for short and long CDRX cycles support */
-  if (UEcap) {
-    featureGroupIndicators = UEcap->featureGroupIndicators;
-
-    if (featureGroupIndicators) {
-      if (featureGroupIndicators->size > 1 || (featureGroupIndicators->size == 1 && featureGroupIndicators->bits_unused < 4)) {
-        ueSupportCdrxShortFlag = ((featureGroupIndicators->buf[0] & (uint8_t) 0x10) > 0);
-        ueSupportCdrxLongFlag = ((featureGroupIndicators->buf[0] & (uint8_t) 0x08) > 0);
-        LOG_I(RRC,"[do_DrxConfig] featureGroupIndicators->buf[0]: %x\n", featureGroupIndicators->buf[0]);
-      } else LOG_W(RRC,"[do_DrxConfig] Not enough featureGroupIndicators bits\n");
-    } else LOG_W(RRC,"[do_DrxConfig] No featureGroupIndicators pointer\n");
-  } else LOG_W(RRC,"[do_DrxConfig] No UEcap pointer\n");
-
-  if (configuration->radioresourceconfig[CC_id].drx_Config_present == LTE_DRX_Config_PR_NOTHING) {
-    return NULL;
-  }
+  featureGroupIndicators = UEcap->featureGroupIndicators;
+  if (featureGroupIndicators) {
+    if (featureGroupIndicators->size > 1 || (featureGroupIndicators->size == 1 && featureGroupIndicators->bits_unused < 4)) {
+      ueSupportCdrxShortFlag = ((featureGroupIndicators->buf[0] & (uint8_t) 0x10) > 0);
+      ueSupportCdrxLongFlag = ((featureGroupIndicators->buf[0] & (uint8_t) 0x08) > 0);
+      LOG_D(RRC,"[do_DrxConfig] featureGroupIndicators->buf[0]: %x\n", featureGroupIndicators->buf[0]);
+    } else LOG_W(RRC,"[do_DrxConfig] Not enough featureGroupIndicators bits\n");
+  } else LOG_W(RRC,"[do_DrxConfig] No featureGroupIndicators pointer\n");
 
   drxConfig = (LTE_DRX_Config_t *) malloc(sizeof(LTE_DRX_Config_t));
 
@@ -651,74 +737,75 @@ LTE_DRX_Config_t *do_DrxConfig(uint8_t Mod_id,
   if (drxConfig->present == LTE_DRX_Config_PR_release) {
     drxConfig->choice.release = (NULL_t) 0;
   } else {
-    drxConfig->choice.setup.onDurationTimer = configuration->radioresourceconfig[CC_id].drx_onDurationTimer;
-    drxConfig->choice.setup.drx_InactivityTimer = configuration->radioresourceconfig[CC_id].drx_InactivityTimer;
-    drxConfig->choice.setup.drx_RetransmissionTimer = configuration->radioresourceconfig[CC_id].drx_RetransmissionTimer;
-    drxConfig->choice.setup.longDRX_CycleStartOffset.present = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset_present;
-
-    switch (drxConfig->choice.setup.longDRX_CycleStartOffset.present) {
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf10:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf10 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+    struct LTE_DRX_Config__setup *choiceSetup = &drxConfig->choice.setup;
+    choiceSetup->onDurationTimer = configuration->radioresourceconfig[CC_id].drx_onDurationTimer;
+    choiceSetup->drx_InactivityTimer = configuration->radioresourceconfig[CC_id].drx_InactivityTimer;
+    choiceSetup->drx_RetransmissionTimer = configuration->radioresourceconfig[CC_id].drx_RetransmissionTimer;
+    choiceSetup->longDRX_CycleStartOffset.present = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset_present;
+
+    switch (choiceSetup->longDRX_CycleStartOffset.present) {
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf10:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf10 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf20:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf20 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf20:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf20 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf32:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf32 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf32:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf32 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf40:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf40 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf40:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf40 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf64:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf64 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf64:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf64 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf80:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf80 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf80:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf80 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf128:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf128 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf128:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf128 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf160:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf160 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf160:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf160 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf256:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf256 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf256:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf256 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf320:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf320 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf320:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf320 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf512:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf512 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf512:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf512 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf640:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf640 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf640:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf640 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf1024:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf1024 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf1024:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf1024 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf1280:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf1280 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf1280:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf1280 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf2048:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf2048 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf2048:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf2048 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
-      case  LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf2560:
-        drxConfig->choice.setup.longDRX_CycleStartOffset.choice.sf2560 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
+      case LTE_DRX_Config__setup__longDRX_CycleStartOffset_PR_sf2560:
+        choiceSetup->longDRX_CycleStartOffset.choice.sf2560 = configuration->radioresourceconfig[CC_id].drx_longDrx_CycleStartOffset;
         break;
 
       default:
@@ -727,12 +814,12 @@ LTE_DRX_Config_t *do_DrxConfig(uint8_t Mod_id,
 
     /* Short DRX cycle configuration */
     if (!ueSupportCdrxShortFlag || configuration->radioresourceconfig[CC_id].drx_shortDrx_ShortCycleTimer == 0) {
-      drxConfig->choice.setup.shortDRX = NULL;
+      choiceSetup->shortDRX = NULL;
     } else {
-      drxConfig->choice.setup.shortDRX = MALLOC(sizeof(struct LTE_DRX_Config__setup__shortDRX));
-      memset(drxConfig->choice.setup.shortDRX, 0, sizeof(struct LTE_DRX_Config__setup__shortDRX));
-      drxConfig->choice.setup.shortDRX->shortDRX_Cycle = configuration->radioresourceconfig[CC_id].drx_shortDrx_Cycle;
-      drxConfig->choice.setup.shortDRX->drxShortCycleTimer = configuration->radioresourceconfig[CC_id].drx_shortDrx_ShortCycleTimer;
+      choiceSetup->shortDRX = MALLOC(sizeof(struct LTE_DRX_Config__setup__shortDRX));
+      memset(choiceSetup->shortDRX, 0, sizeof(struct LTE_DRX_Config__setup__shortDRX));
+      choiceSetup->shortDRX->shortDRX_Cycle = configuration->radioresourceconfig[CC_id].drx_shortDrx_Cycle;
+      choiceSetup->shortDRX->drxShortCycleTimer = configuration->radioresourceconfig[CC_id].drx_shortDrx_ShortCycleTimer;
     }
   }
 
@@ -759,8 +846,8 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
   LTE_MCC_MNC_Digit_t *dummy_mnc_1;
   LTE_MCC_MNC_Digit_t *dummy_mnc_2;
   asn_enc_rval_t enc_rval;
-  LTE_SchedulingInfo_t *schedulingInfo;
-  LTE_SIB_Type_t *sib_type;
+  LTE_SchedulingInfo_t schedulingInfo,schedulingInfo2;
+  LTE_SIB_Type_t sib_type,sib_type2;
   uint8_t *buffer;
   LTE_BCCH_DL_SCH_Message_t *bcch_message;
   LTE_SystemInformationBlockType1_t **sib1;
@@ -785,15 +872,13 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
   if (PLMN_identity_info == NULL)
     exit(1);
 
-  schedulingInfo = CALLOC(1, sizeof(LTE_SchedulingInfo_t));
-
-  if (schedulingInfo == NULL)
-    exit(1);
-
-  sib_type = CALLOC(1, sizeof(LTE_SIB_Type_t));
-
-  if (sib_type == NULL)
-    exit(1);
+  memset(&PLMN_identity_info,0,num_plmn * sizeof(LTE_PLMN_IdentityInfo_t));
+  memset(&schedulingInfo,0,sizeof(LTE_SchedulingInfo_t));
+  memset(&sib_type,0,sizeof(LTE_SIB_Type_t));
+  if(configuration->eMBMS_M2_configured){
+       memset(&schedulingInfo2,0,sizeof(LTE_SchedulingInfo_t));
+       memset(&sib_type2,0,sizeof(LTE_SIB_Type_t));
+  }
 
   /* as per TS 36.311, up to 6 PLMN_identity_info are allowed in list -> add one by one */
   for (int i = 0; i < num_plmn; ++i) {
@@ -906,11 +991,19 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
 #else
     7;
 #endif
-  schedulingInfo->si_Periodicity=LTE_SchedulingInfo__si_Periodicity_rf8;
+  schedulingInfo.si_Periodicity=LTE_SchedulingInfo__si_Periodicity_rf8;
+  if(configuration->eMBMS_M2_configured){
+       schedulingInfo2.si_Periodicity=LTE_SchedulingInfo__si_Periodicity_rf8;
+  }
   // This is for SIB2/3
-  *sib_type = LTE_SIB_Type_sibType3;
-  ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list, sib_type);
-  ASN_SEQUENCE_ADD(&(*sib1)->schedulingInfoList.list, schedulingInfo);
+  sib_type=LTE_SIB_Type_sibType3;
+  ASN_SEQUENCE_ADD(&schedulingInfo.sib_MappingInfo.list,&sib_type);
+  ASN_SEQUENCE_ADD(&(*sib1)->schedulingInfoList.list,&schedulingInfo);
+  if(configuration->eMBMS_M2_configured){
+         sib_type2=LTE_SIB_Type_sibType13_v920;
+         ASN_SEQUENCE_ADD(&schedulingInfo2.sib_MappingInfo.list,&sib_type2);
+         ASN_SEQUENCE_ADD(&(*sib1)->schedulingInfoList.list,&schedulingInfo2);
+  }
   //  ASN_SEQUENCE_ADD(&schedulingInfo.sib_MappingInfo.list,NULL);
 #if defined(ENABLE_ITTI)
 
diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h
index 5203bc64ed2f584087189faf0d6dd77c6e023961..925f09416e2c94ec438c4d4c4c31dc870ac52ff5 100644
--- a/openair2/RRC/LTE/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.h
@@ -76,12 +76,11 @@ uint8_t do_MIB(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t phich
 uint8_t do_MIB_FeMBMS(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t additionalNonMBSFNSubframes, uint32_t frame);
 /**
 \brief Generate configuration structure for DRX_Config
-@param Mod_id Instance of eNB
 @param CC_id Id of component to configure
 @param configuration Pointer Configuration Request structure
 @param UEcap Pointer Configuration UE capablities
 @return DRX_Config structure pointer or NULL => error */
-LTE_DRX_Config_t *do_DrxConfig(uint8_t Mod_id, int CC_id, RrcConfigurationReq *configuration, LTE_UE_EUTRA_Capability_t *UEcap);
+LTE_DRX_Config_t *do_DrxConfig(int CC_id, RrcConfigurationReq *configuration, LTE_UE_EUTRA_Capability_t *UEcap);
 
 /**
 \brief Generate configuration for SIB1 (eNB).
diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c
index 66c4401e57c66238b25bd2214f4c2899312c9e4f..9383a726fb95ec203c2b8e9b953626fad5f11fe4 100644
--- a/openair2/RRC/LTE/rrc_UE.c
+++ b/openair2/RRC/LTE/rrc_UE.c
@@ -3545,7 +3545,7 @@ int decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index ) {
       case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2:
         if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&2) == 0) {
           UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=2;
-          new_sib=1;
+          //new_sib=1;
           memcpy( UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index], &typeandinfo->choice.sib2, sizeof(LTE_SystemInformationBlockType2_t) );
           LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB2 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
           dump_sib2( UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index] );
@@ -3613,7 +3613,58 @@ int decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index ) {
             }
 #endif
           }
-        }
+        }else{
+                       //LOG_W( RRC, "[UE %d] Received new SIB1/SIB2/SIB3 with MBMSs %d\n", ctxt_pP->module_id, ((&typeandinfo->choice.sib2)->mbsfn_SubframeConfigList == NULL ? 0:1) );
+               if((&typeandinfo->choice.sib2)->mbsfn_SubframeConfigList != NULL && (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&4096) == 0){
+                       LOG_W( RRC, "[UE %d] Received SIB2 with MBSFN SF Config\n", ctxt_pP->module_id );
+
+                       memcpy( UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index], &typeandinfo->choice.sib2, sizeof(LTE_SystemInformationBlockType2_t) );
+                       LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB2 params  eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
+                               ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id );
+                       rrc_mac_config_req_ue(ctxt_pP->module_id, 0, eNB_index,
+                               (LTE_RadioResourceConfigCommonSIB_t *)NULL,
+                                (struct LTE_PhysicalConfigDedicated *)NULL,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+                                (LTE_SCellToAddMod_r10_t *)NULL,
+#endif
+                                (LTE_MeasObjectToAddMod_t **)NULL,
+                                (LTE_MAC_MainConfig_t *)NULL,
+                                0,
+                                (struct LTE_LogicalChannelConfig *)NULL,
+                                (LTE_MeasGapConfig_t *)NULL,
+                                (LTE_TDD_Config_t *)NULL,
+                                (LTE_MobilityControlInfo_t *)NULL,
+                                NULL,
+                                NULL,
+                               NULL,
+                               NULL,
+                               NULL,
+                                UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->mbsfn_SubframeConfigList
+#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+                                ,0,
+                                (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
+                                (LTE_PMCH_InfoList_r9_t *)NULL
+#endif
+#ifdef CBA
+                                ,0,
+                                0
+#endif
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                                ,
+                                0,
+                                NULL,
+                                NULL
+#endif
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                        ,
+                        0,
+                        (struct LTE_NonMBSFN_SubframeConfig_r14 *)NULL,
+                        (LTE_MBSFN_AreaInfoList_r9_t *)NULL
+#endif
+                               );
+
+               }
+       }
 
         break; // case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2
 
@@ -3756,8 +3807,8 @@ int decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index ) {
                                 (struct LTE_NonMBSFN_SubframeConfig_r14 *)NULL,
                                 (LTE_MBSFN_AreaInfoList_r9_t *)NULL
                                );
-          break;
         }
+        break;
 
       //SIB18
       case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib18_v1250:
@@ -3823,19 +3874,30 @@ int decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index ) {
       default:
         break;
     }
+    if (new_sib == 1) {
+      UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt++;
+  
+      if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt == sib1->schedulingInfoList.list.count)
+        rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE );
+  
+      LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n",
+            UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus,
+            UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt,
+            sib1->schedulingInfoList.list.count);
+    }
   }
 
-  if (new_sib == 1) {
-    UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt++;
+  //if (new_sib == 1) {
+  //  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt++;
 
-    if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt == sib1->schedulingInfoList.list.count)
-      rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE );
+  //  if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt == sib1->schedulingInfoList.list.count)
+  //    rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE );
 
-    LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n",
-          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus,
-          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt,
-          sib1->schedulingInfoList.list.count);
-  }
+  //  LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n",
+  //        UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus,
+  //        UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt,
+  //        sib1->schedulingInfoList.list.count);
+  //}
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_OUT);
   return 0;
@@ -4158,7 +4220,7 @@ int decode_MCCH_Message( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB
           ctxt_pP->frame,
           mbsfn_sync_area);
     return 0; // avoid decoding to prevent memory bloating
-  } else {
+  } else if(UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State >= RRC_CONNECTED /*|| UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State == RRC_RECONFIGURED*/){
     dec_rval = uper_decode_complete(NULL,
                                     &asn_DEF_LTE_MCCH_Message,
                                     (void **)&mcch,
@@ -4256,7 +4318,8 @@ void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_index, f
                         (struct LTE_NonMBSFN_SubframeConfig_r14 *)NULL,
                         (LTE_MBSFN_AreaInfoList_r9_t *)NULL
                        );
-  UE_rrc_inst[ue_mod_idP].Info[eNB_index].MCCHStatus[mbsfn_sync_area] = 1;
+  if(UE_rrc_inst[ue_mod_idP].Info[eNB_index].State >= RRC_CONNECTED /*|| UE_rrc_inst[ue_mod_idP].Info[eNB_index].State == RRC_RECONFIGURED*/)
+  	UE_rrc_inst[ue_mod_idP].Info[eNB_index].MCCHStatus[mbsfn_sync_area] = 1;
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_idP, ENB_FLAG_NO, UE_rrc_inst[ue_mod_idP].Info[eNB_index].rnti, frameP, 0,eNB_index);
   // Config Radio Bearer for MBMS user data (similar way to configure for eNB side in init_MBMS function)
   rrc_pdcp_config_asn1_req(&ctxt,
diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c
index dbeaa9f6a548c2d329e5fbd4a9ece1c9f90c61c8..bf62fc3df2873cbb390fe34dc9c13edcd9e6c53b 100644
--- a/openair2/RRC/LTE/rrc_eNB.c
+++ b/openair2/RRC/LTE/rrc_eNB.c
@@ -83,6 +83,7 @@
 
 #include "rrc_eNB_S1AP.h"
 #include "rrc_eNB_GTPV1U.h"
+#include "rrc_eNB_M2AP.h"
 
 #include "pdcp.h"
 #include "gtpv1u_eNB_task.h"
@@ -2790,6 +2791,8 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t
   uint8_t   buffer[RRC_BUF_SIZE];
   uint16_t  size;
   int       i;
+  MessageDef *message_p = NULL;
+
   /* Configure SRB1/SRB2, PhysicalConfigDedicated, LTE_MAC_MainConfig for UE */
   eNB_RRC_INST                           *rrc_inst = RC.rrc[ctxt_pP->module_id];
   struct LTE_PhysicalConfigDedicated    **physicalConfigDedicated = &ue_context_pP->ue_context.physicalConfigDedicated;
@@ -2972,43 +2975,28 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t
   mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer =
     LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf200; // sf20 = 20 subframes // LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf1000
   mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = LTE_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB3;  // Value dB1 =1 dB, dB3 = 3 dB
+  /* CDRX Configuration */
+  mac_MainConfig->drx_Config = NULL;
+  rnti_t rnti = ue_context_pP->ue_id_rnti;
+  module_id_t module_id = ctxt_pP->module_id;
+  LOG_D(RRC, "Processing the DRX configuration in RRC Connection Reconfiguration\n");
 
-  if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) {
-    /* CDRX Configuration */
-    // Need to check if UE is a BR UE
-    rnti_t rnti = ue_context_pP->ue_id_rnti;
-    module_id_t module_id = ctxt_pP->module_id;
-    int UE_id = find_UE_id(module_id, rnti);
-    eNB_MAC_INST *mac = RC.mac[module_id];
-    UE_list_t *UE_list = &(mac->UE_list);
-
-    if (UE_id != -1) {
-      if ((rrc_inst->carrier[cc_id].sib1->tdd_Config == NULL) &&
-          (UE_list->UE_template[ue_context_pP->ue_context.primaryCC_id][UE_id].rach_resource_type == 0)) {
-        // CDRX can be only configured in case of FDD and non BR UE (09/04/19)
-        LOG_D(RRC, "Processing the DRX configuration in RRC Connection Reconfiguration\n");
-
-        /* Process the IE drx_Config */
-        if (cc_id < MAX_NUM_CCs) {
-          mac_MainConfig->drx_Config = do_DrxConfig(module_id, cc_id, &rrc_inst->configuration, UEcap); // drx_Config IE
-        } else {
-          LOG_E(RRC, "Invalid CC_id for DRX configuration\n");
-        }
+  /* Process the IE drx_Config */    
+  if (NODE_IS_MONOLITHIC(rrc_inst->node_type)) {
+    mac_MainConfig->drx_Config = do_DrxConfig(cc_id, &rrc_inst->configuration, UEcap); // drx_Config IE
 
-        /* Set timers and thresholds values in local MAC context of UE */
-        eNB_Config_Local_DRX(module_id, ue_context_pP->ue_id_rnti, mac_MainConfig->drx_Config);
-        LOG_D(RRC, "DRX configured in mac main config for RRC Connection Reconfiguration\n");
-      } else { // CDRX not implemented for TDD and LTE-M (09/04/19)
-        mac_MainConfig->drx_Config = NULL;
-      }
-    } else { // UE_id invalid
-      LOG_E(RRC, "Invalid UE_id found!\n");
-      mac_MainConfig->drx_Config = NULL;
+    if (mac_MainConfig->drx_Config == NULL) {
+      LOG_W(RRC, "drx_Configuration parameter is NULL, cannot configure local UE parameters or CDRX is deactivated\n");
+    } else {
+      /* Send DRX configuration to MAC task to configure timers of local UE context */
+      message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_MAC_DRX_CONFIG_REQ);
+      RRC_MAC_DRX_CONFIG_REQ(message_p).rnti = rnti;
+      RRC_MAC_DRX_CONFIG_REQ(message_p).drx_Configuration = mac_MainConfig->drx_Config;
+      itti_send_msg_to_task(TASK_MAC_ENB, module_id, message_p);
+      LOG_D(RRC, "DRX configured in MAC Main Configuration for RRC Connection Reconfiguration\n");
     }
-  } else { // No CDRX with the CU/DU split in this version
-    LOG_E(RRC, "CU/DU split activated\n");
-    mac_MainConfig->drx_Config = NULL;
   }
+  /* End of CDRX configuration */
 
   sr_ProhibitTimer_r9 = CALLOC(1, sizeof(long));
   *sr_ProhibitTimer_r9 = 0;   // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2 = 2*SR
@@ -3445,6 +3433,8 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
   uint8_t   buffer[RRC_BUF_SIZE];
   uint16_t  size;
   int       i;
+  MessageDef *message_p = NULL;
+
   /* Configure SRB1/SRB2, PhysicalConfigDedicated, LTE_MAC_MainConfig for UE */
   eNB_RRC_INST                           *rrc_inst = RC.rrc[ctxt_pP->module_id];
   struct LTE_PhysicalConfigDedicated    **physicalConfigDedicated = &ue_context_pP->ue_context.physicalConfigDedicated;
@@ -3490,8 +3480,34 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
   LTE_C_RNTI_t                           *cba_RNTI                         = NULL;
   int                                    measurements_enabled;
   uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id);   //Transaction_id,
-  uint8_t cc_id = ue_context_pP->ue_context.primaryCC_id;
-  LTE_UE_EUTRA_Capability_t *UEcap = ue_context_pP->ue_context.UE_Capability;
+
+#ifdef CBA // Contention Based Access
+  uint8_t                            *cba_RNTI_buf;
+  cba_RNTI = CALLOC(1, sizeof(LTE_C_RNTI_t));
+  cba_RNTI_buf = CALLOC(1, 2 * sizeof(uint8_t));
+  cba_RNTI->buf = cba_RNTI_buf;
+  cba_RNTI->size = 2;
+  cba_RNTI->bits_unused = 0;
+
+  /* Associate UEs to the CBA groups as a function of their UE id */
+  if (rrc_inst->num_active_cba_groups) {
+    cba_RNTI->buf[0] = rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups] & 0xff;
+    cba_RNTI->buf[1] = 0xff;
+    LOG_D(RRC, "[eNB %d] Frame %d: cba_RNTI = %x in group %d is attribued to UE %d\n",
+          enb_mod_idP,
+          frameP,
+          rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups],
+          ue_mod_idP % rrc_inst->num_active_cba_groups, ue_mod_idP);
+  } else {
+    cba_RNTI->buf[0] = 0x0;
+    cba_RNTI->buf[1] = 0x0;
+    LOG_D(RRC, "[eNB %d] Frame %d: no cba_RNTI is configured for UE %d\n",
+          enb_mod_idP,
+          frameP,
+          ue_mod_idP);
+  }
+#endif
+
   T(T_ENB_RRC_CONNECTION_RECONFIGURATION,
     T_INT(ctxt_pP->module_id),
     T_INT(ctxt_pP->frame),
@@ -3627,42 +3643,30 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
     LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf200; // sf20 = 20 subframes // LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf1000
   mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = LTE_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB3;  // Value dB1 =1 dB, dB3 = 3 dB
 
-  if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) {
-    /* CDRX Configuration */
-    // Need to check if UE is a BR UE
-    rnti_t rnti = ue_context_pP->ue_id_rnti;
-    module_id_t module_id = ctxt_pP->module_id;
-    int UE_id = find_UE_id(module_id, rnti);
-    eNB_MAC_INST *mac = RC.mac[module_id];
-    UE_list_t *UE_list = &(mac->UE_list);
-
-    if (UE_id != -1) {
-      if ((rrc_inst->carrier[cc_id].sib1->tdd_Config == NULL) &&
-          (UE_list->UE_template[ue_context_pP->ue_context.primaryCC_id][UE_id].rach_resource_type == 0)) {
-        // CDRX can be only configured in case of FDD and non BR UE (09/04/19)
-        LOG_D(RRC, "Processing the DRX configuration in RRC Connection Reconfiguration\n");
-
-        /* Process the IE drx_Config */
-        if (cc_id < MAX_NUM_CCs) {
-          mac_MainConfig->drx_Config = do_DrxConfig(module_id, cc_id, &rrc_inst->configuration, UEcap); // drx_Config IE
-        } else {
-          LOG_E(RRC, "Invalid CC_id for DRX configuration\n");
-        }
-
-        /* Set timers and thresholds values in local MAC context of UE */
-        eNB_Config_Local_DRX(module_id, ue_context_pP->ue_id_rnti, mac_MainConfig->drx_Config);
-        LOG_D(RRC, "DRX configured in mac main config for RRC Connection Reconfiguration\n");
-      } else { // CDRX not implemented for TDD and LTE-M (09/04/19)
-        mac_MainConfig->drx_Config = NULL;
-      }
-    } else { // UE_id invalid
-      LOG_E(RRC, "Invalid UE_id found!\n");
-      mac_MainConfig->drx_Config = NULL;
+  /* CDRX Configuration */
+  mac_MainConfig->drx_Config = NULL;
+  rnti_t rnti = ue_context_pP->ue_id_rnti;
+  module_id_t module_id = ctxt_pP->module_id;
+  uint8_t cc_id = ue_context_pP->ue_context.primaryCC_id;
+  LTE_UE_EUTRA_Capability_t *UEcap = ue_context_pP->ue_context.UE_Capability;
+  LOG_D(RRC, "Processing the DRX configuration in RRC Connection Reconfiguration\n");
+  
+  /* Process the IE drx_Config */
+  if (NODE_IS_MONOLITHIC(rrc_inst->node_type)) {
+    mac_MainConfig->drx_Config = do_DrxConfig(cc_id, &rrc_inst->configuration, UEcap); // drx_Config IE
+  
+    if (mac_MainConfig->drx_Config == NULL) {
+      LOG_W(RRC, "drx_Configuration parameter is NULL, cannot configure local UE parameters or CDRX is deactivated\n");
+    } else {
+      /* Send DRX configuration to MAC task to configure timers of local UE context */
+      message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_MAC_DRX_CONFIG_REQ);
+      RRC_MAC_DRX_CONFIG_REQ(message_p).rnti = rnti;
+      RRC_MAC_DRX_CONFIG_REQ(message_p).drx_Configuration = mac_MainConfig->drx_Config;
+      itti_send_msg_to_task(TASK_MAC_ENB, module_id, message_p);
+      LOG_D(RRC, "DRX configured in MAC Main Configuration for RRC Connection Reconfiguration\n");
     }
-  } else { // No CDRX with the CU/DU split in this version
-    LOG_E(RRC, "CU/DU split activated\n");
-    mac_MainConfig->drx_Config = NULL;
   }
+  /* End of CDRX configuration */
 
   sr_ProhibitTimer_r9 = CALLOC(1, sizeof(long));
   *sr_ProhibitTimer_r9 = 0;   // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2 = 2*SR
@@ -6034,26 +6038,31 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
   LTE_SRB_ToAddModList_t             *SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid];
   LTE_DRB_ToReleaseList_t            *DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid];
   LTE_DRB_Identity_t                 *drb_id_p      = NULL;
+
   ue_context_pP->ue_context.ue_reestablishment_timer = 0;
   ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // reset rrc inactivity timer
 
-  if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) {
-    /* CDRX: activated if ack was expected */
-    int UE_id_mac = find_UE_id(ctxt_pP->module_id, ue_context_pP->ue_context.rnti);
+  /* CDRX: activated when RRC Connection Reconfiguration Complete is received */
+  rnti_t rnti = ue_context_pP->ue_id_rnti;
+  module_id_t module_id = ctxt_pP->module_id;
+
+  if (NODE_IS_MONOLITHIC(RC.rrc[module_id]->node_type)) {
+    int UE_id_mac = find_UE_id(module_id, rnti);
 
     if (UE_id_mac == -1) {
-      LOG_E(RRC,PROTOCOL_RRC_CTXT_UE_FMT" rrc_eNB_process_RRCConnectionReconfigurationComplete without UE_id(MAC) rnti %x, let's return\n",PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ue_context_pP->ue_context.rnti);
+      LOG_E(RRC, "Can't find UE_id(MAC) of UE rnti %x\n", rnti);
       return;
     }
 
-    UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id_mac]);
+    UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[module_id]->UE_list.UE_sched_ctrl[UE_id_mac]);
 
     if (UE_scheduling_control->cdrx_waiting_ack == TRUE) {
       UE_scheduling_control->cdrx_waiting_ack = FALSE;
-      UE_scheduling_control->cdrx_configured = TRUE;
+      UE_scheduling_control->cdrx_configured = TRUE; // Set to TRUE when RRC Connection Reconfiguration is received
       LOG_I(RRC, "CDRX configuration activated after RRC Connection Reconfiguration Complete reception\n");
     }
-  } // No CDRX with the CU/DU split in this version of the code
+  }
+  /* End of CDRX processing */
 
   T(T_ENB_RRC_CONNECTION_RECONFIGURATION_COMPLETE,
     T_INT(ctxt_pP->module_id),
@@ -8543,6 +8552,43 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
       rrc_subframe_process(&RRC_SUBFRAME_PROCESS(msg_p).ctxt, RRC_SUBFRAME_PROCESS(msg_p).CC_id);
       break;
 
+    case M2AP_SETUP_RESP:
+       rrc_eNB_process_M2AP_SETUP_RESP(&ctxt,0/*CC_id*/,ENB_INSTANCE_TO_MODULE_ID(instance),&M2AP_SETUP_RESP(msg_p));
+      break;
+
+    case M2AP_MBMS_SCHEDULING_INFORMATION:
+       rrc_eNB_process_M2AP_MBMS_SCHEDULING_INFORMATION(&ctxt,0/*CC_id*/,ENB_INSTANCE_TO_MODULE_ID(instance),&M2AP_MBMS_SCHEDULING_INFORMATION(msg_p));
+       break;
+
+    case M2AP_MBMS_SESSION_START_REQ:
+       rrc_eNB_process_M2AP_MBMS_SESSION_START_REQ(&ctxt,0/*CC_id*/,ENB_INSTANCE_TO_MODULE_ID(instance),&M2AP_MBMS_SESSION_START_REQ(msg_p));
+       break;
+
+    case M2AP_MBMS_SESSION_STOP_REQ:
+       rrc_eNB_process_M2AP_MBMS_SESSION_STOP_REQ(&ctxt,&M2AP_MBMS_SESSION_STOP_REQ(msg_p));
+       break;
+
+    case M2AP_RESET:
+       rrc_eNB_process_M2AP_RESET(&ctxt,&M2AP_RESET(msg_p));
+       break;
+
+    case M2AP_ENB_CONFIGURATION_UPDATE_ACK:
+       rrc_eNB_process_M2AP_ENB_CONFIGURATION_UPDATE_ACK(&ctxt,&M2AP_ENB_CONFIGURATION_UPDATE_ACK(msg_p));
+       break;
+
+    case M2AP_ERROR_INDICATION:
+       rrc_eNB_process_M2AP_ERROR_INDICATION(&ctxt,&M2AP_ERROR_INDICATION(msg_p));
+       break;
+
+    case M2AP_MBMS_SERVICE_COUNTING_REQ:
+       rrc_eNB_process_M2AP_MBMS_SERVICE_COUNTING_REQ(&ctxt,&M2AP_MBMS_SERVICE_COUNTING_REQ(msg_p));
+       break;
+
+    case M2AP_MCE_CONFIGURATION_UPDATE:
+       rrc_eNB_process_M2AP_MCE_CONFIGURATION_UPDATE(&ctxt,&M2AP_MCE_CONFIGURATION_UPDATE(msg_p));
+       break;
+
+
     default:
       LOG_E(RRC, "[eNB %d] Received unexpected message %s\n", instance, msg_name_p);
       break;
diff --git a/openair2/RRC/LTE/rrc_eNB_M2AP.c b/openair2/RRC/LTE/rrc_eNB_M2AP.c
new file mode 100644
index 0000000000000000000000000000000000000000..ac68bbcbcddf026f23c5f076c0b82bf7af4b3c61
--- /dev/null
+++ b/openair2/RRC/LTE/rrc_eNB_M2AP.c
@@ -0,0 +1,1312 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file rrc_eNB_M2AP.c
+ * \brief rrc M2AP procedures for eNB
+ * \author Javier Morgade
+ * \version 0.1
+ * \company Vicomtech Spain
+ * \email: javier.morgade@ieee.org
+ */
+
+# include "rrc_defs.h"
+# include "rrc_extern.h"
+# include "RRC/LTE/MESSAGES/asn1_msg.h"
+# include "rrc_eNB_M2AP.h"
+//# include "rrc_eNB_UE_context.h"
+# include "msc.h"
+#   include "asn1_conversions.h"
+#   include "intertask_interface.h"
+# include "common/ran_context.h"
+
+extern RAN_CONTEXT_t RC;
+
+static m2ap_setup_resp_t * m2ap_setup_resp_g=NULL;
+static m2ap_mbms_scheduling_information_t *m2ap_mbms_scheduling_information_g=NULL;
+
+ 
+static void 
+rrc_M2AP_openair_rrc_top_init_MBMS(int eMBMS_active){
+  module_id_t         module_id;
+  int                 CC_id;
+  
+  (void)CC_id;
+  LOG_D(RRC, "[OPENAIR][INIT] Init function start: NB_eNB_INST=%d\n", RC.nb_inst);
+
+  if (RC.nb_inst > 0) {
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+    LOG_I(RRC,"[eNB] eMBMS active state is %d \n", eMBMS_active);
+
+    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
+      for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
+        RC.rrc[module_id]->carrier[CC_id].MBMS_flag = (uint8_t)eMBMS_active;
+      }
+    }
+
+#endif
+  }
+}
+
+
+
+static uint8_t rrc_M2AP_do_MBSFNAreaConfig(
+    uint8_t Mod_id,
+    uint8_t sync_area,
+    uint8_t *buffer,
+    LTE_MCCH_Message_t *mcch_message,
+    LTE_MBSFNAreaConfiguration_r9_t **mbsfnAreaConfiguration,
+    const m2ap_mbms_scheduling_information_t *const m2ap_mbms_scheduling_information
+) {
+  int i,j,k;
+
+  asn_enc_rval_t enc_rval;
+  LTE_MBSFN_SubframeConfig_t *mbsfn_SubframeConfig1;
+  LTE_PMCH_Info_r9_t *pmch_Info_1;
+  LTE_MBMS_SessionInfo_r9_t *mbms_Session_1;
+  // MBMS_SessionInfo_r9_t *mbms_Session_2;
+  //eNB_RRC_INST *rrc               = RC.rrc[Mod_id];
+  //rrc_eNB_carrier_data_t *carrier = &rrc->carrier[0];
+  memset(mcch_message,0,sizeof(LTE_MCCH_Message_t));
+  mcch_message->message.present = LTE_MCCH_MessageType_PR_c1;
+  mcch_message->message.choice.c1.present = LTE_MCCH_MessageType__c1_PR_mbsfnAreaConfiguration_r9;
+  *mbsfnAreaConfiguration = &mcch_message->message.choice.c1.choice.mbsfnAreaConfiguration_r9;
+  // Common Subframe Allocation (CommonSF-Alloc-r9)
+
+  for(i=0; i<m2ap_mbms_scheduling_information->num_mbms_area_config_list; i++){
+	  for(j=0;j < m2ap_mbms_scheduling_information->mbms_area_config_list[i].num_mbms_sf_config_list; j++){
+ 
+		  mbsfn_SubframeConfig1= CALLOC(1,sizeof(*mbsfn_SubframeConfig1));
+		  memset((void *)mbsfn_SubframeConfig1,0,sizeof(*mbsfn_SubframeConfig1));
+		  //
+		  mbsfn_SubframeConfig1->radioframeAllocationPeriod= m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_period;//LTE_MBSFN_SubframeConfig__radioframeAllocationPeriod_n4;
+		  mbsfn_SubframeConfig1->radioframeAllocationOffset= m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_offset;
+		  if(m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].is_four_sf){
+			  mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames;
+			  mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(3);
+                          mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation) & 0xFF);
+                          mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation>>8) & 0xFF);
+                          mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation>>16) & 0xFF);
+			  mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 3;
+			  mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 0;
+		
+
+   		  }else {
+			  mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame;
+			  mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(1);
+			  mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1;
+			  mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2;
+			  mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0] = (m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation & 0x3F)<<2;
+		  }
+
+		  ASN_SEQUENCE_ADD(&(*mbsfnAreaConfiguration)->commonSF_Alloc_r9.list,mbsfn_SubframeConfig1);
+	  }
+	  //  commonSF-AllocPeriod-r9
+	  (*mbsfnAreaConfiguration)->commonSF_AllocPeriod_r9= m2ap_mbms_scheduling_information->mbms_area_config_list[i].common_sf_allocation_period;//LTE_MBSFNAreaConfiguration_r9__commonSF_AllocPeriod_r9_rf16;
+	  // PMCHs Information List (PMCH-InfoList-r9)
+	  for(j=0; j < m2ap_mbms_scheduling_information->mbms_area_config_list[i].num_pmch_config_list; j++){
+		  // PMCH_1  Config
+		  pmch_Info_1 = CALLOC(1,sizeof(LTE_PMCH_Info_r9_t));
+		  memset((void *)pmch_Info_1,0,sizeof(LTE_PMCH_Info_r9_t));
+		  /*
+		   * take the value of last mbsfn subframe in this CSA period because there is only one PMCH in this mbsfn area
+		   * Note: this has to be set based on the subframeAllocation and CSA
+		   */
+		  pmch_Info_1->pmch_Config_r9.sf_AllocEnd_r9= m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].allocated_sf_end;
+		  pmch_Info_1->pmch_Config_r9.dataMCS_r9= m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].data_mcs;
+		  pmch_Info_1->pmch_Config_r9.mch_SchedulingPeriod_r9= LTE_PMCH_Config_r9__mch_SchedulingPeriod_r9_rf16;
+		  // MBMSs-SessionInfoList-r9
+		  for(k=0; k < m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].num_mbms_session_list; k++){
+			  //  pmch_Info_1->mbms_SessionInfoList_r9 = CALLOC(1,sizeof(struct MBMS_SessionInfoList_r9));
+			  //  Session 1
+			  mbms_Session_1 = CALLOC(1,sizeof(LTE_MBMS_SessionInfo_r9_t));
+			  memset(mbms_Session_1,0,sizeof(LTE_MBMS_SessionInfo_r9_t));
+			  // TMGI value
+			  mbms_Session_1->tmgi_r9.plmn_Id_r9.present= LTE_TMGI_r9__plmn_Id_r9_PR_plmn_Index_r9;
+			  mbms_Session_1->tmgi_r9.plmn_Id_r9.choice.plmn_Index_r9= 1;
+			  // Service ID
+			  //uint8_t TMGI[5] = {4,3,2,1,0};//TMGI is a string of octet, ref. TS 24.008 fig. 10.5.4a
+			  char buf[4];
+			  buf[0] = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id << 24;
+			  buf[1] = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id << 16;
+			  buf[2] = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id << 8;
+			  buf[3] = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id << 0;
+			  //INT32_TO_BUFFER(m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id,buf);
+			  memset(&mbms_Session_1->tmgi_r9.serviceId_r9,0,sizeof(OCTET_STRING_t));// need to check
+			  OCTET_STRING_fromBuf(&mbms_Session_1->tmgi_r9.serviceId_r9,(const char *)&buf[1],3);
+			  // Session ID is still missing here, it can be used as an rab id or mrb id
+			  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]= m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id; //1;
+			  // Logical Channel ID
+			  mbms_Session_1->logicalChannelIdentity_r9=m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid; //1;
+			  LOG_D(RRC,"lcid %lu %d\n",mbms_Session_1->logicalChannelIdentity_r9,m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].lcid);
+			  LOG_D(RRC,"service_id %d\n",m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mbms_session_list[k].service_id);
+			  ASN_SEQUENCE_ADD(&pmch_Info_1->mbms_SessionInfoList_r9.list,mbms_Session_1);
+		  }
+		  ASN_SEQUENCE_ADD(&(*mbsfnAreaConfiguration)->pmch_InfoList_r9.list,pmch_Info_1);
+	  }
+  }
+
+  if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
+    xer_fprint(stdout,&asn_DEF_LTE_MCCH_Message,(void *)mcch_message);
+  }
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_MCCH_Message,
+                                   NULL,
+                                   (void *)mcch_message,
+                                   buffer,
+                                   100);
+
+    if(enc_rval.encoded == -1) {
+    LOG_I(RRC, "[eNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n",
+          enc_rval.failed_type->name, enc_rval.encoded);
+    return -1;
+  }
+
+  LOG_I(RRC,"[eNB] MCCH Message Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+
+  if (enc_rval.encoded==-1) {
+    msg("[RRC] ASN1 : MCCH  encoding failed for MBSFNAreaConfiguration\n");
+    return(-1);
+  }
+
+  return((enc_rval.encoded+7)/8);
+  
+}
+
+static void rrc_M2AP_init_MBMS(
+  module_id_t enb_mod_idP, 
+  int CC_id,
+  frame_t frameP
+){
+   // init the configuration for MTCH
+  protocol_ctxt_t               ctxt;
+
+  if (RC.rrc[enb_mod_idP]->carrier[CC_id].MBMS_flag > 0) {
+    PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, enb_mod_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, 0,enb_mod_idP);
+    LOG_I(RRC, "[eNB %d] Frame %d : Radio Bearer config request for MBMS\n", enb_mod_idP, frameP);   //check the lcid
+    // Configuring PDCP and RLC for MBMS Radio Bearer
+    rrc_pdcp_config_asn1_req(&ctxt,
+                             (LTE_SRB_ToAddModList_t *)NULL,   // LTE_SRB_ToAddModList
+                             (LTE_DRB_ToAddModList_t *)NULL,   // LTE_DRB_ToAddModList
+                             (LTE_DRB_ToReleaseList_t *)NULL,
+                             0,     // security mode
+                             NULL,  // key rrc encryption
+                             NULL,  // key rrc integrity
+                             NULL   // key encryption
+                             , &(RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->pmch_InfoList_r9)
+                             ,NULL);
+
+    if (!NODE_IS_CU(RC.rrc[enb_mod_idP]->node_type)) {
+      rrc_rlc_config_asn1_req(&ctxt,
+                              NULL, // LTE_SRB_ToAddModList
+                              NULL,   // LTE_DRB_ToAddModList
+                              NULL,   // DRB_ToReleaseList
+                              &(RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->pmch_InfoList_r9)
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                              ,0, 0
+#endif
+                              );
+    }
+            //rrc_mac_config_req();
+  }
+}
+
+
+static void rrc_M2AP_init_MCCH(
+  const protocol_ctxt_t *const ctxt_pP,
+  uint8_t enb_mod_idP, 
+  int CC_id,
+ const m2ap_mbms_scheduling_information_t *const m2ap_mbms_scheduling_information
+){
+
+    int                                 sync_area = 0;
+    // initialize RRC_eNB_INST MCCH entry
+    eNB_RRC_INST *rrc = RC.rrc[enb_mod_idP];
+  
+    RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE =
+      malloc(RC.rrc[enb_mod_idP]->carrier[CC_id].num_mbsfn_sync_area * sizeof(uint8_t *));
+  
+    for (sync_area = 0; sync_area < RC.rrc[enb_mod_idP]->carrier[CC_id].num_mbsfn_sync_area; sync_area++) {
+      RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[sync_area] = 0;
+      RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE[sync_area] = (uint8_t *) malloc16(32);
+      AssertFatal(RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE[sync_area] != NULL,
+                  "[eNB %d]init_MCCH: FATAL, no memory for MCCH MESSAGE allocated \n", enb_mod_idP);
+      RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[sync_area] = rrc_M2AP_do_MBSFNAreaConfig(enb_mod_idP,
+          sync_area,
+          (uint8_t *)RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE[sync_area],
+          &RC.rrc[enb_mod_idP]->carrier[CC_id].mcch,
+          &RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message,
+	  m2ap_mbms_scheduling_information 
+      );
+      LOG_I(RRC, "mcch message pointer %p for sync area %d \n",
+            RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE[sync_area],
+            sync_area);
+      LOG_D(RRC, "[eNB %d] MCCH_MESSAGE  contents for Sync Area %d (partial)\n", enb_mod_idP, sync_area);
+      LOG_D(RRC, "[eNB %d] CommonSF_AllocPeriod_r9 %ld\n", enb_mod_idP,
+            RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->commonSF_AllocPeriod_r9);
+      LOG_D(RRC,
+            "[eNB %d] CommonSF_Alloc_r9.list.count (number of MBSFN Subframe Pattern) %d\n",
+            enb_mod_idP, RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->commonSF_Alloc_r9.list.count);
+      LOG_D(RRC, "[eNB %d] MBSFN Subframe Pattern: %02x (in hex)\n",
+            enb_mod_idP,
+            RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->commonSF_Alloc_r9.list.array[0]->subframeAllocation.
+            choice.oneFrame.buf[0]);
+      AssertFatal(RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[sync_area] != 255,
+                  "RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[sync_area] == 255");
+      RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESS[sync_area].Active = 1;
+    }
+
+
+   if (NODE_IS_MONOLITHIC(rrc->node_type)) {
+    rrc_mac_config_req_eNB(enb_mod_idP, CC_id,
+                           0,0,0,0,0,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                           0,
+#endif
+                           0,//rnti
+                           (LTE_BCCH_BCH_Message_t *)NULL,
+                           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+#endif
+                           (struct LTE_PhysicalConfigDedicated *)NULL,
+                           (LTE_SCellToAddMod_r10_t *)NULL,
+                         //(struct LTE_PhysicalConfigDedicatedSCell_r10 *)NULL,
+                           (LTE_MeasObjectToAddMod_t **) NULL,
+                           (LTE_MAC_MainConfig_t *) NULL,
+                           0,
+                           (struct LTE_LogicalChannelConfig *)NULL,
+                           (LTE_MeasGapConfig_t *) NULL,
+                           (LTE_TDD_Config_t *) NULL,
+                           (LTE_MobilityControlInfo_t *)NULL,
+                           (LTE_SchedulingInfoList_t *) NULL,
+                           0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL
+                           ,
+                           0,
+                           (LTE_MBSFN_AreaInfoList_r9_t *) NULL,
+                           (LTE_PMCH_InfoList_r9_t *) & (RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->pmch_InfoList_r9)
+#if (LTE_RRC_VERSION >= MAKE_VERSION(13, 0, 0))
+                           ,
+                           (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL
+#endif
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                        ,
+                        0,
+                        (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL,
+                        (LTE_SchedulingInfo_MBMS_r14_t *) NULL,
+                        (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
+                        (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
+                        (LTE_MBSFN_AreaInfoList_r9_t *) NULL
+#endif
+                        );
+  }
+  
+  return;
+}
+//static uint8_t rrc_M2AP_do_SIB1(
+//  			  const protocol_ctxt_t *const ctxt_pP,
+//			  uint8_t Mod_id, 
+//			  int CC_id,
+//  			  const m2ap_setup_resp_t *const m2ap_setup_resp,
+//  			  const m2ap_mbms_scheduling_information_t *const m2ap_mbms_scheduling_information
+//){
+//  int i/*,j,l*/;
+//  
+//  //eNB_RRC_INST *rrc = RC.rrc[ctxt_pP->module_id];
+//  //rrc_eNB_carrier_data_t *carrier=&rrc->carrier[CC_id];
+//
+//  asn_enc_rval_t enc_rval;
+//
+//  uint8_t *buffer;
+//
+//   LTE_SystemInformationBlockType1_t **sib1;
+//
+//  LTE_BCCH_DL_SCH_Message_t         *bcch_message = &RC.rrc[Mod_id]->carrier[CC_id].systemInformation;
+//
+//#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+//  if (ctxt_pP->brOption) {
+//    buffer       = RC.rrc[Mod_id]->carrier[CC_id].SIB1_BR;
+//    bcch_message = &RC.rrc[Mod_id]->carrier[CC_id].siblock1_BR;
+//    sib1         = &RC.rrc[Mod_id]->carrier[CC_id].sib1_BR;
+//  }
+//  else
+//#endif
+//    {
+//      buffer       = RC.rrc[Mod_id]->carrier[CC_id].SIB1;
+//      bcch_message = &RC.rrc[Mod_id]->carrier[CC_id].siblock1;
+//      sib1         = &RC.rrc[Mod_id]->carrier[CC_id].sib1;
+//    }
+//
+//    *sib1 = &bcch_message->message.choice.c1.choice.systemInformationBlockType1;
+//   
+//    uint8_t find_sib13=0;
+//    for(i=0; i<(*sib1)->schedulingInfoList.list.count; i++){
+//		//for(j=0; j<(*sib1)->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count;j++)
+//		//	if((*sib1)->schedulingInfoList.list.array[i]->sib_MappingInfo.list.array[j] == LTE_SIB_Type_sibType13_v920)
+//		//		find_sib13=1;
+//    }
+//    if(!find_sib13){
+//   	LTE_SchedulingInfo_t schedulingInfo;
+//   	LTE_SIB_Type_t sib_type;
+//        memset(&schedulingInfo,0,sizeof(LTE_SchedulingInfo_t));
+//        memset(&sib_type,0,sizeof(LTE_SIB_Type_t));
+//	
+//	schedulingInfo.si_Periodicity=LTE_SchedulingInfo__si_Periodicity_rf8;
+//	sib_type=LTE_SIB_Type_sibType13_v920;
+//	ASN_SEQUENCE_ADD(&(*sib1)->schedulingInfoList.list,&schedulingInfo);
+//    }
+//
+//    enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message,
+//                                   NULL,
+//                                   (void *)bcch_message,
+//                                   buffer,
+//                                   900);
+//  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+//               enc_rval.failed_type->name, enc_rval.encoded);
+//  LOG_W(RRC,"[eNB] SystemInformationBlockType1 Encoded %zd bits (%zd bytes) with new SIB13(%d) \n",enc_rval.encoded,(enc_rval.encoded+7)/8,find_sib13);
+//
+//
+//  RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_SIB1 = ((enc_rval.encoded+7)/8);
+//
+//     
+//  
+//
+//   return 0;
+//}
+
+
+
+static uint8_t rrc_M2AP_do_SIB23_SIB2(
+  			  const protocol_ctxt_t *const ctxt_pP,
+			  uint8_t Mod_id, 
+			  int CC_id,
+  			  const m2ap_mbms_scheduling_information_t *const m2ap_mbms_scheduling_information
+){
+
+  int i,j,l;
+  
+  eNB_RRC_INST *rrc = RC.rrc[ctxt_pP->module_id];
+  rrc_eNB_carrier_data_t *carrier=&rrc->carrier[CC_id];
+
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+  //struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib13_part=NULL;
+  LTE_MBSFN_SubframeConfigList_t *MBSFNSubframeConfigList/*,*MBSFNSubframeConfigList_copy*/;
+  //LTE_MBSFN_AreaInfoList_r9_t *MBSFNArea_list/*,*MBSFNArea_list_copy*/;
+#endif
+
+ asn_enc_rval_t enc_rval;
+
+ LTE_BCCH_DL_SCH_Message_t         *bcch_message = &RC.rrc[Mod_id]->carrier[CC_id].systemInformation;
+ uint8_t                       *buffer;
+ LTE_SystemInformationBlockType2_t **sib2;
+
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+  if(ctxt_pP->brOption){
+	buffer   = RC.rrc[Mod_id]->carrier[CC_id].SIB23_BR;	
+	sib2 	 =  &RC.rrc[Mod_id]->carrier[CC_id].sib2_BR;
+        LOG_I(RRC,"Running SIB2/3 Encoding for eMTC\n");
+
+  }else
+#endif
+  {
+	buffer   = RC.rrc[Mod_id]->carrier[CC_id].SIB23;	
+	sib2 	 =  &RC.rrc[Mod_id]->carrier[CC_id].sib2;
+  }
+
+
+
+  if (bcch_message) {
+    //memset(bcch_message,0,sizeof(LTE_BCCH_DL_SCH_Message_t));
+  } else {
+    LOG_E(RRC,"[eNB %d] BCCH_MESSAGE is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+  if (!sib2) {
+    LOG_E(RRC,"[eNB %d] sib2 is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+  //if (!sib3) {
+  //  LOG_E(RRC,"[eNB %d] sib3 is null, exiting\n", Mod_id);
+  //  exit(-1);
+  //}
+ 
+ for (i=0; i < bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count; i++) {
+    struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *typeandinfo;
+    typeandinfo = bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.array[i];
+    switch(typeandinfo->present) {
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_NOTHING: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib4: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib5: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib6: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib7: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib8: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib9: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib10: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib14_v1130: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib15_v1130: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib16_v1130: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib17_v1250: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib18_v1250: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib19_v1250: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib20_v1310: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib21_v1430: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2: 
+
+	LOG_I(RRC,"Adding MBSFN subframe Configuration 1 to SIB2, %p %p\n",&typeandinfo->choice.sib2,*sib2);
+
+	for(j=0; j < m2ap_mbms_scheduling_information->num_mbms_area_config_list ; j++) {
+
+    			(&typeandinfo->choice.sib2)->mbsfn_SubframeConfigList = CALLOC(1,sizeof(struct LTE_MBSFN_SubframeConfigList));
+    			MBSFNSubframeConfigList = (&typeandinfo->choice.sib2)->mbsfn_SubframeConfigList;
+
+		for(l=0; l < m2ap_mbms_scheduling_information->mbms_area_config_list[j].num_mbms_sf_config_list; l++){
+			LTE_MBSFN_SubframeConfig_t *sib2_mbsfn_SubframeConfig1;
+    			sib2_mbsfn_SubframeConfig1= CALLOC(1,sizeof(*sib2_mbsfn_SubframeConfig1));
+    			memset((void *)sib2_mbsfn_SubframeConfig1,0,sizeof(*sib2_mbsfn_SubframeConfig1));
+
+			sib2_mbsfn_SubframeConfig1->radioframeAllocationPeriod = m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].radioframe_allocation_period;
+			sib2_mbsfn_SubframeConfig1->radioframeAllocationOffset = m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].radioframe_allocation_offset;
+
+
+			if(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].is_four_sf){
+				sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames;
+
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(3);
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 3;
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 0;
+  	                        sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation) & 0xFF);
+                           	sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation>>8) & 0xFF);
+                           	sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation>>16) & 0xFF);
+
+			}else{
+				sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame;
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(1);
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1;
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2;
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation<<2);
+
+
+			}
+
+        		ASN_SEQUENCE_ADD(&MBSFNSubframeConfigList->list,sib2_mbsfn_SubframeConfig1);
+		}	
+	}
+
+	break;
+
+    }
+  }
+
+  
+ //xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message);
+
+ enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message,
+                                   NULL,
+                                   (void *)bcch_message,
+                                   buffer,
+                                   900);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+  LOG_I(RRC,"[eNB] MBMS SIB2 SystemInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+
+  if (enc_rval.encoded==-1) {
+    msg("[RRC] ASN1 : SI encoding failed for SIB23\n");
+    return(-1);
+  }
+
+ carrier->MBMS_flag =1;
+
+ if (NODE_IS_MONOLITHIC(rrc->node_type)) {
+    rrc_mac_config_req_eNB(ctxt_pP->module_id, CC_id,
+                           0,0,0,0,0,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                           0,
+#endif
+                           0,//rnti
+                           (LTE_BCCH_BCH_Message_t *)NULL,
+                           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+#endif
+                           (struct LTE_PhysicalConfigDedicated *)NULL,
+                           (LTE_SCellToAddMod_r10_t *)NULL,
+                         //(struct LTE_PhysicalConfigDedicatedSCell_r10 *)NULL,
+                           (LTE_MeasObjectToAddMod_t **) NULL,
+                           (LTE_MAC_MainConfig_t *) NULL,
+                           0,
+                           (struct LTE_LogicalChannelConfig *)NULL,
+                           (LTE_MeasGapConfig_t *) NULL,
+                           (LTE_TDD_Config_t *) NULL,
+                           (LTE_MobilityControlInfo_t *)NULL,
+                           (LTE_SchedulingInfoList_t *) NULL,
+			   0, NULL,
+			   (LTE_AdditionalSpectrumEmission_t *)NULL,
+ 			   (LTE_MBSFN_SubframeConfigList_t *) carrier->sib2->mbsfn_SubframeConfigList,
+                           carrier->MBMS_flag,
+                           (LTE_MBSFN_AreaInfoList_r9_t *) NULL,
+                           (LTE_PMCH_InfoList_r9_t *) NULL 
+#if (LTE_RRC_VERSION >= MAKE_VERSION(13, 0, 0))
+                           ,
+                           (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL
+#endif
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                        ,
+                        0,
+                        (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL,
+                        (LTE_SchedulingInfo_MBMS_r14_t *) NULL,
+                        (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
+                        (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
+                        (LTE_MBSFN_AreaInfoList_r9_t *) NULL
+#endif
+                        );
+  }
+
+  RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_SIB23 = ((enc_rval.encoded+7)/8);
+ 
+  return 0;
+}
+
+static uint8_t rrc_M2AP_do_SIB23_SIB13(
+  			  const protocol_ctxt_t *const ctxt_pP,
+			  uint8_t Mod_id, 
+			  int CC_id,
+  			  const m2ap_setup_resp_t *const m2ap_setup_resp
+){
+
+  int i;
+  eNB_RRC_INST *rrc = RC.rrc[ctxt_pP->module_id];
+  rrc_eNB_carrier_data_t *carrier=&rrc->carrier[CC_id];
+
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+  struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib13_part=NULL;
+  //LTE_MBSFN_SubframeConfigList_t *MBSFNSubframeConfigList;
+  LTE_MBSFN_AreaInfoList_r9_t *MBSFNArea_list;
+#endif
+
+ asn_enc_rval_t enc_rval;
+
+ LTE_BCCH_DL_SCH_Message_t         *bcch_message = &RC.rrc[Mod_id]->carrier[CC_id].systemInformation;
+ uint8_t                       *buffer;
+   LTE_SystemInformationBlockType2_t **sib2;
+
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+  if(ctxt_pP->brOption){
+	buffer   = RC.rrc[Mod_id]->carrier[CC_id].SIB23_BR;	
+	sib2 	 =  &RC.rrc[Mod_id]->carrier[CC_id].sib2_BR;
+        LOG_I(RRC,"Running SIB2/3 Encoding for eMTC\n");
+
+  }else
+#endif
+  {
+	buffer   = RC.rrc[Mod_id]->carrier[CC_id].SIB23;	
+	sib2 	 =  &RC.rrc[Mod_id]->carrier[CC_id].sib2;
+  }
+
+
+
+  if (bcch_message) {
+    //memset(bcch_message,0,sizeof(LTE_BCCH_DL_SCH_Message_t));
+  } else {
+    LOG_E(RRC,"[eNB %d] BCCH_MESSAGE is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+  if (!sib2) {
+    LOG_E(RRC,"[eNB %d] sib2 is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+  //if (!sib3) {
+  //  LOG_E(RRC,"[eNB %d] sib3 is null, exiting\n", Mod_id);
+  //  exit(-1);
+  //}
+
+ /*for (int i=0; i<(*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count; i++) {
+    struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *typeandinfo;
+    typeandinfo = (*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.array[i];
+    switch(typeandinfo->present) {
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2:
+	LTE_SystemInformationBlockType2_t *sib2 = &typeandinfo->choice.sib2
+	 LOG_I(RRC,"Adding MBSFN subframe Configuration 1 to SIB2\n");
+    	LTE_MBSFN_SubframeConfig_t *sib2_mbsfn_SubframeConfig1;
+    	(*sib2)->mbsfn_SubframeConfigList = CALLOC(1,sizeof(struct LTE_MBSFN_SubframeConfigList));
+    	MBSFNSubframeConfigList = (*sib2)->mbsfn_SubframeConfigList;
+    	sib2_mbsfn_SubframeConfig1= CALLOC(1,sizeof(*sib2_mbsfn_SubframeConfig1));
+    	memset((void *)sib2_mbsfn_SubframeConfig1,0,sizeof(*sib2_mbsfn_SubframeConfig1));
+    	sib2_mbsfn_SubframeConfig1->radioframeAllocationPeriod= LTE_MBSFN_SubframeConfig__radioframeAllocationPeriod_n4;
+    	sib2_mbsfn_SubframeConfig1->radioframeAllocationOffset= 1;
+    	sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame;
+    	sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(1);
+    	sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1;
+    	sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2;
+    	sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=0x38<<2;
+
+        ASN_SEQUENCE_ADD(&MBSFNSubframeConfigList->list,sib2_mbsfn_SubframeConfig1);
+
+
+	break;
+
+    }
+  }*/
+
+  
+#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+ LTE_SystemInformationBlockType13_r9_t   **sib13       = &RC.rrc[Mod_id]->carrier[CC_id].sib13;
+#endif
+
+  struct LTE_MBSFN_AreaInfo_r9 *MBSFN_Area1/*, *MBSFN_Area2*/;
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+ sib13_part = CALLOC(1,sizeof(struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+ memset(sib13_part,0,sizeof(struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+ sib13_part->present = LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920;
+
+ *sib13 = &sib13_part->choice.sib13_v920;
+#endif
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+ (*sib13)->notificationConfig_r9.notificationRepetitionCoeff_r9=LTE_MBMS_NotificationConfig_r9__notificationRepetitionCoeff_r9_n2;
+ (*sib13)->notificationConfig_r9.notificationOffset_r9=0;
+ (*sib13)->notificationConfig_r9.notificationSF_Index_r9=1;
+
+ //  MBSFN-AreaInfoList
+ MBSFNArea_list= &(*sib13)->mbsfn_AreaInfoList_r9;//CALLOC(1,sizeof(*MBSFNArea_list));
+ memset(MBSFNArea_list,0,sizeof(*MBSFNArea_list));
+
+for( i=0; i < m2ap_setup_resp->num_mcch_config_per_mbsfn; i++){
+ // MBSFN Area 1
+ MBSFN_Area1= CALLOC(1, sizeof(*MBSFN_Area1));
+ MBSFN_Area1->mbsfn_AreaId_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].mbsfn_area;
+ MBSFN_Area1->non_MBSFNregionLength= m2ap_setup_resp->mcch_config_per_mbsfn[i].pdcch_length;
+ MBSFN_Area1->notificationIndicator_r9= 0;
+ MBSFN_Area1->mcch_Config_r9.mcch_RepetitionPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].repetition_period;//LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__mcch_RepetitionPeriod_r9_rf32;
+ MBSFN_Area1->mcch_Config_r9.mcch_Offset_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].offset; // in accordance with mbsfn subframe configuration in sib2
+ MBSFN_Area1->mcch_Config_r9.mcch_ModificationPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].modification_period;
+
+ //  Subframe Allocation Info
+ MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf= MALLOC(1);
+ MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.size= 1;
+ MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf[0]=m2ap_setup_resp->mcch_config_per_mbsfn[i].subframe_allocation_info<<2;  // FDD: SF1
+ MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.bits_unused= 2;
+ MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].mcs;
+ ASN_SEQUENCE_ADD(&MBSFNArea_list->list,MBSFN_Area1);
+ }
+#endif
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+ ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list, sib13_part);
+#endif
+
+ //xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message);
+
+ enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message,
+                                   NULL,
+                                   (void *)bcch_message,
+                                   buffer,
+                                   900);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+  LOG_I(RRC,"[eNB] MBMS SIB13 SystemInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+
+  if (enc_rval.encoded==-1) {
+    msg("[RRC] ASN1 : SI encoding failed for SIB23\n");
+    return(-1);
+  }
+
+ if (NODE_IS_MONOLITHIC(rrc->node_type)) {
+    rrc_mac_config_req_eNB(ctxt_pP->module_id, CC_id,
+                           0,0,0,0,0,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                           0,
+#endif
+                           0,//rnti
+                           (LTE_BCCH_BCH_Message_t *)NULL,
+                           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+#endif
+                           (struct LTE_PhysicalConfigDedicated *)NULL,
+                           (LTE_SCellToAddMod_r10_t *)NULL,
+                         //(struct LTE_PhysicalConfigDedicatedSCell_r10 *)NULL,
+                           (LTE_MeasObjectToAddMod_t **) NULL,
+                           (LTE_MAC_MainConfig_t *) NULL,
+                           0,
+                           (struct LTE_LogicalChannelConfig *)NULL,
+                           (LTE_MeasGapConfig_t *) NULL,
+                           (LTE_TDD_Config_t *) NULL,
+                           (LTE_MobilityControlInfo_t *)NULL,
+                           (LTE_SchedulingInfoList_t *) NULL,
+                           0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL 
+                           ,
+                           0,
+                           (LTE_MBSFN_AreaInfoList_r9_t *) & carrier->sib13->mbsfn_AreaInfoList_r9,
+                           (LTE_PMCH_InfoList_r9_t *) NULL 
+#if (LTE_RRC_VERSION >= MAKE_VERSION(13, 0, 0))
+                           ,
+                           (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL
+#endif
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                        ,
+                        0,
+                        (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL,
+                        (LTE_SchedulingInfo_MBMS_r14_t *) NULL,
+                        (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
+                        (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
+                        (LTE_MBSFN_AreaInfoList_r9_t *) NULL
+#endif
+                        );
+  }
+
+  RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_SIB23 = ((enc_rval.encoded+7)/8);
+ 
+  return 0;
+}
+
+
+
+static uint8_t rrc_M2AP_do_SIB23_SIB2_SIB13(
+  			  const protocol_ctxt_t *const ctxt_pP,
+			  uint8_t Mod_id, 
+			  int CC_id,
+  			  const m2ap_setup_resp_t *const m2ap_setup_resp,
+  			  const m2ap_mbms_scheduling_information_t *const m2ap_mbms_scheduling_information
+){
+
+  int i,j,l;
+  
+  eNB_RRC_INST *rrc = RC.rrc[ctxt_pP->module_id];
+  rrc_eNB_carrier_data_t *carrier=&rrc->carrier[CC_id];
+
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+  struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib13_part=NULL;
+  LTE_MBSFN_SubframeConfigList_t *MBSFNSubframeConfigList/*,*MBSFNSubframeConfigList_copy*/;
+#endif
+
+ asn_enc_rval_t enc_rval;
+
+ LTE_BCCH_DL_SCH_Message_t         *bcch_message = &RC.rrc[Mod_id]->carrier[CC_id].systemInformation;
+ uint8_t                       *buffer;
+ LTE_SystemInformationBlockType2_t **sib2;
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+  LTE_MBSFN_AreaInfoList_r9_t *MBSFNArea_list/*,*MBSFNArea_list_copy*/;
+ LTE_SystemInformationBlockType13_r9_t   **sib13       = &RC.rrc[Mod_id]->carrier[CC_id].sib13;
+ struct LTE_MBSFN_AreaInfo_r9 *MBSFN_Area1;
+#endif
+
+
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+  if(ctxt_pP->brOption){
+	buffer   = RC.rrc[Mod_id]->carrier[CC_id].SIB23_BR;	
+	sib2 	 =  &RC.rrc[Mod_id]->carrier[CC_id].sib2_BR;
+        LOG_I(RRC,"Running SIB2/3 Encoding for eMTC\n");
+
+  }else
+#endif
+  {
+	buffer   = RC.rrc[Mod_id]->carrier[CC_id].SIB23;	
+	sib2 	 =  &RC.rrc[Mod_id]->carrier[CC_id].sib2;
+  }
+
+
+
+  if (bcch_message) {
+    //memset(bcch_message,0,sizeof(LTE_BCCH_DL_SCH_Message_t));
+  } else {
+    LOG_E(RRC,"[eNB %d] BCCH_MESSAGE is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+  if (!sib2) {
+    LOG_E(RRC,"[eNB %d] sib2 is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+  if(!sib13){
+    LOG_I(RRC,"[eNB %d] sib13 is null, it should get created\n",Mod_id);
+  }
+
+  //if (!sib3) {
+  //  LOG_E(RRC,"[eNB %d] sib3 is null, exiting\n", Mod_id);
+  //  exit(-1);
+  //}
+ 
+ for (i=0; i < bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count; i++) {
+    struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *typeandinfo;
+    typeandinfo = bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.array[i];
+    switch(typeandinfo->present) {
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_NOTHING: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib4: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib5: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib6: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib7: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib8: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib9: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib10: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920: 
+	*sib13=&typeandinfo->choice.sib13_v920;
+#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+	(*sib13)->notificationConfig_r9.notificationRepetitionCoeff_r9=LTE_MBMS_NotificationConfig_r9__notificationRepetitionCoeff_r9_n2;
+ 	(*sib13)->notificationConfig_r9.notificationOffset_r9=0;
+ 	(*sib13)->notificationConfig_r9.notificationSF_Index_r9=1;
+	//  MBSFN-AreaInfoList
+ 	MBSFNArea_list= &(*sib13)->mbsfn_AreaInfoList_r9;//CALLOC(1,sizeof(*MBSFNArea_list));
+ 	memset(MBSFNArea_list,0,sizeof(*MBSFNArea_list));
+
+	for( j=0; j < m2ap_setup_resp->num_mcch_config_per_mbsfn; j++){
+ 	   // MBSFN Area 1
+ 	   MBSFN_Area1= CALLOC(1, sizeof(*MBSFN_Area1));
+ 	   MBSFN_Area1->mbsfn_AreaId_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].mbsfn_area;
+ 	   MBSFN_Area1->non_MBSFNregionLength= m2ap_setup_resp->mcch_config_per_mbsfn[j].pdcch_length;
+ 	   MBSFN_Area1->notificationIndicator_r9= 0;
+ 	   MBSFN_Area1->mcch_Config_r9.mcch_RepetitionPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].repetition_period;//LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__mcch_RepetitionPeriod_r9_rf32;
+ 	   MBSFN_Area1->mcch_Config_r9.mcch_Offset_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].offset; // in accordance with mbsfn subframe configuration in sib2
+ 	   MBSFN_Area1->mcch_Config_r9.mcch_ModificationPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].modification_period;
+
+ 	   //  Subframe Allocation Info
+ 	   MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf= MALLOC(1);
+ 	   MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.size= 1;
+ 	   MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf[0]=m2ap_setup_resp->mcch_config_per_mbsfn[j].subframe_allocation_info<<2;  // FDD: SF1
+ 	   MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.bits_unused= 2;
+ 	   MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].mcs;
+ 	   ASN_SEQUENCE_ADD(&MBSFNArea_list->list,MBSFN_Area1);
+ 	}
+#endif
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib14_v1130: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib15_v1130: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib16_v1130: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib17_v1250: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib18_v1250: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib19_v1250: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib20_v1310: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib21_v1430: 
+	break;
+      case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2: 
+
+	LOG_I(RRC,"Adding MBSFN subframe Configuration 1 to SIB2, %p %p\n",&typeandinfo->choice.sib2,*sib2);
+
+	for(j=0; j < m2ap_mbms_scheduling_information->num_mbms_area_config_list ; j++) {
+
+    			(&typeandinfo->choice.sib2)->mbsfn_SubframeConfigList = CALLOC(1,sizeof(struct LTE_MBSFN_SubframeConfigList));
+    			MBSFNSubframeConfigList = (&typeandinfo->choice.sib2)->mbsfn_SubframeConfigList;
+
+		for(l=0; l < m2ap_mbms_scheduling_information->mbms_area_config_list[j].num_mbms_sf_config_list; l++){
+			LTE_MBSFN_SubframeConfig_t *sib2_mbsfn_SubframeConfig1;
+    			sib2_mbsfn_SubframeConfig1= CALLOC(1,sizeof(*sib2_mbsfn_SubframeConfig1));
+    			memset((void *)sib2_mbsfn_SubframeConfig1,0,sizeof(*sib2_mbsfn_SubframeConfig1));
+
+			sib2_mbsfn_SubframeConfig1->radioframeAllocationPeriod = m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].radioframe_allocation_period;
+			sib2_mbsfn_SubframeConfig1->radioframeAllocationOffset = m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].radioframe_allocation_offset;
+
+
+			if(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].is_four_sf){
+				sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames;
+
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(3);
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 3;
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 0;
+  	                        sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation) & 0xFF);
+                           	sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation>>8) & 0xFF);
+                           	sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation>>16) & 0xFF);
+
+			}else{
+				sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame;
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(1);
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1;
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2;
+    				sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation<<2);
+
+
+			}
+
+        		ASN_SEQUENCE_ADD(&MBSFNSubframeConfigList->list,sib2_mbsfn_SubframeConfig1);
+		}	
+	}
+
+	break;
+
+    }
+  }
+
+ if(*sib13==NULL){
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+    sib13_part = CALLOC(1,sizeof(struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+    memset(sib13_part,0,sizeof(struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+    sib13_part->present = LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920;
+
+    *sib13 = &sib13_part->choice.sib13_v920;
+#endif
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+   (*sib13)->notificationConfig_r9.notificationRepetitionCoeff_r9=LTE_MBMS_NotificationConfig_r9__notificationRepetitionCoeff_r9_n2;
+   (*sib13)->notificationConfig_r9.notificationOffset_r9=0;
+   (*sib13)->notificationConfig_r9.notificationSF_Index_r9=1;
+
+   //  MBSFN-AreaInfoList
+   MBSFNArea_list= &(*sib13)->mbsfn_AreaInfoList_r9;//CALLOC(1,sizeof(*MBSFNArea_list));
+   memset(MBSFNArea_list,0,sizeof(*MBSFNArea_list));
+
+   for( i=0; i < m2ap_setup_resp->num_mcch_config_per_mbsfn; i++){
+   // MBSFN Area 1
+   MBSFN_Area1= CALLOC(1, sizeof(*MBSFN_Area1));
+   MBSFN_Area1->mbsfn_AreaId_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].mbsfn_area;
+   MBSFN_Area1->non_MBSFNregionLength= m2ap_setup_resp->mcch_config_per_mbsfn[i].pdcch_length;
+   MBSFN_Area1->notificationIndicator_r9= 0;
+   MBSFN_Area1->mcch_Config_r9.mcch_RepetitionPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].repetition_period;//LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__mcch_RepetitionPeriod_r9_rf32;
+   MBSFN_Area1->mcch_Config_r9.mcch_Offset_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].offset; // in accordance with mbsfn subframe configuration in sib2
+   MBSFN_Area1->mcch_Config_r9.mcch_ModificationPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].modification_period;
+  
+   //  Subframe Allocation Info
+   MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf= MALLOC(1);
+   MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.size= 1;
+   MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf[0]=m2ap_setup_resp->mcch_config_per_mbsfn[i].subframe_allocation_info<<2;  // FDD: SF1
+   MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.bits_unused= 2;
+   MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].mcs;
+   ASN_SEQUENCE_ADD(&MBSFNArea_list->list,MBSFN_Area1);
+   }
+#endif
+
+#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+ ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list, sib13_part);
+#endif
+
+ }
+
+  
+ //xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message);
+
+ enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message,
+                                   NULL,
+                                   (void *)bcch_message,
+                                   buffer,
+                                   900);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+  LOG_I(RRC,"[eNB] MBMS SIB2 SystemInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+
+  if (enc_rval.encoded==-1) {
+    msg("[RRC] ASN1 : SI encoding failed for SIB23\n");
+    return(-1);
+  }
+
+ carrier->MBMS_flag =1;
+
+ if (NODE_IS_MONOLITHIC(rrc->node_type)) {
+    rrc_mac_config_req_eNB(ctxt_pP->module_id, CC_id,
+                           0,0,0,0,0,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                           0,
+#endif
+                           0,//rnti
+                           (LTE_BCCH_BCH_Message_t *)NULL,
+                           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                           (LTE_RadioResourceConfigCommonSIB_t *) NULL,
+#endif
+                           (struct LTE_PhysicalConfigDedicated *)NULL,
+                           (LTE_SCellToAddMod_r10_t *)NULL,
+                         //(struct LTE_PhysicalConfigDedicatedSCell_r10 *)NULL,
+                           (LTE_MeasObjectToAddMod_t **) NULL,
+                           (LTE_MAC_MainConfig_t *) NULL,
+                           0,
+                           (struct LTE_LogicalChannelConfig *)NULL,
+                           (LTE_MeasGapConfig_t *) NULL,
+                           (LTE_TDD_Config_t *) NULL,
+                           (LTE_MobilityControlInfo_t *)NULL,
+                           (LTE_SchedulingInfoList_t *) NULL,
+			   0, NULL,
+			   (LTE_AdditionalSpectrumEmission_t *)NULL,
+ 			   (LTE_MBSFN_SubframeConfigList_t *) carrier->sib2->mbsfn_SubframeConfigList,
+                           carrier->MBMS_flag,
+                           (LTE_MBSFN_AreaInfoList_r9_t *) & carrier->sib13->mbsfn_AreaInfoList_r9,
+                           (LTE_PMCH_InfoList_r9_t *) NULL 
+#if (LTE_RRC_VERSION >= MAKE_VERSION(13, 0, 0))
+                           ,
+                           (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL
+#endif
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                        ,
+                        0,
+                        (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL,
+                        (LTE_SchedulingInfo_MBMS_r14_t *) NULL,
+                        (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL,
+                        (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL,
+                        (LTE_MBSFN_AreaInfoList_r9_t *) NULL
+#endif
+                        );
+  }
+
+  RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_SIB23 = ((enc_rval.encoded+7)/8);
+ 
+  return 0;
+}
+
+
+int
+rrc_eNB_process_M2AP_SETUP_RESP(
+  const protocol_ctxt_t *const ctxt_pP,
+  int CC_id,
+  instance_t instance,
+  const m2ap_setup_resp_t *const m2ap_setup_resp
+)
+{
+ //protocol_ctxt_t 	ctxt;
+ //LOG_W(RRC,"instance %d\n",instance);
+ 
+ AssertFatal(RC.rrc[ctxt_pP->module_id]->carrier[0].SIB23 != NULL,"Memory fo SIB23 not allocated");
+ AssertFatal(m2ap_setup_resp != NULL, "m2ap_setup_resp memory not allocated");
+
+
+ pthread_mutex_lock(&RC.rrc[ctxt_pP->module_id]->cell_info_mutex);
+ //RC.rrc[ctxt_pP->module_id]->carrier[CC_id].num_mbsfn_sync_area = m2ap_setup_resp->num_mcch_config_per_mbsfn;
+ //rrc_M2AP_do_SIB23_SIB13(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_setup_resp); 
+ m2ap_setup_resp_g = (m2ap_setup_resp_t*)calloc(1,sizeof(m2ap_setup_resp_t));
+ memcpy(m2ap_setup_resp_g,m2ap_setup_resp,sizeof(m2ap_setup_resp_t));
+ pthread_mutex_unlock(&RC.rrc[ctxt_pP->module_id]->cell_info_mutex);
+
+ return 0;
+}
+
+
+int
+rrc_eNB_process_M2AP_MBMS_SCHEDULING_INFORMATION(
+  const protocol_ctxt_t *const ctxt_pP,
+  int CC_id,
+  instance_t instance,
+  const m2ap_mbms_scheduling_information_t *const m2ap_mbms_scheduling_information
+)
+{
+ //protocol_ctxt_t 	ctxt;
+ //LOG_W(RRC,"instance %d\n",instance);
+ 
+ AssertFatal(RC.rrc[ctxt_pP->module_id]->carrier[0].SIB23 != NULL,"Memory fo SIB23 not allocated");
+ AssertFatal(m2ap_mbms_scheduling_information != NULL, "m2ap_mbms_scheduling_information memory not allocated");
+
+ //RC.rrc[ctxt_pP->module_id]->carrier[CC_id].num_mbsfn_sync_area = m2ap_setup_resp->num_mcch_config_per_mbsfn;
+
+ pthread_mutex_lock(&RC.rrc[ctxt_pP->module_id]->cell_info_mutex);
+ m2ap_mbms_scheduling_information_g = (m2ap_mbms_scheduling_information_t*)calloc(1,sizeof(m2ap_mbms_scheduling_information_t));
+ memcpy(m2ap_mbms_scheduling_information_g,m2ap_mbms_scheduling_information,sizeof(m2ap_mbms_scheduling_information_t));
+
+ /*if(m2ap_setup_resp_g != NULL){
+	 RC.rrc[ctxt_pP->module_id]->carrier[CC_id].num_mbsfn_sync_area = m2ap_setup_resp_g->num_mcch_config_per_mbsfn;
+	 rrc_M2AP_do_SIB23_SIB2(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_mbms_scheduling_information); 
+	 rrc_M2AP_do_SIB23_SIB13(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_setup_resp_g); 
+	 rrc_M2AP_init_MCCH(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_mbms_scheduling_information); 
+	 rrc_M2AP_init_MBMS(ctxt_pP->module_id, CC_id, 0);
+	 rrc_M2AP_openair_rrc_top_init_MBMS(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].MBMS_flag);
+ }*/
+ MessageDef      *msg_p;
+ msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SCHEDULING_INFORMATION_RESP);
+ itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+
+ pthread_mutex_unlock(&RC.rrc[ctxt_pP->module_id]->cell_info_mutex);
+
+
+ return 0;
+}
+
+int
+rrc_eNB_process_M2AP_MBMS_SESSION_START_REQ(
+  const protocol_ctxt_t *const ctxt_pP,
+  int CC_id,
+  instance_t instance,
+  const m2ap_session_start_req_t *const m2ap_mbms_session_start_req
+)
+{
+ int split_cfg=0;
+ pthread_mutex_lock(&RC.rrc[ctxt_pP->module_id]->cell_info_mutex);
+ if(m2ap_setup_resp_g != NULL && m2ap_mbms_scheduling_information_g !=NULL ){
+	 RC.rrc[ctxt_pP->module_id]->carrier[CC_id].num_mbsfn_sync_area = m2ap_setup_resp_g->num_mcch_config_per_mbsfn;
+
+	 //rrc_M2AP_do_SIB1(ctxt_pP,ctxt_pP->module_id,CC_id,NULL,NULL);
+	if(split_cfg){
+	 rrc_M2AP_do_SIB23_SIB2(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_mbms_scheduling_information_g); 
+	 rrc_M2AP_do_SIB23_SIB13(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_setup_resp_g); 
+	}else{
+	 rrc_M2AP_do_SIB23_SIB2_SIB13(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_setup_resp_g,m2ap_mbms_scheduling_information_g); 
+	}
+	 rrc_M2AP_init_MCCH(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_mbms_scheduling_information_g); 
+	 rrc_M2AP_init_MBMS(ctxt_pP->module_id, CC_id, 0);
+	 rrc_M2AP_openair_rrc_top_init_MBMS(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].MBMS_flag);
+ }
+ pthread_mutex_unlock(&RC.rrc[ctxt_pP->module_id]->cell_info_mutex);
+
+ MessageDef      *msg_p;
+ msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SESSION_START_RESP);
+ itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+
+ return 0;
+}
+
+int
+rrc_eNB_process_M2AP_MBMS_SESSION_STOP_REQ(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_session_stop_req_t *const m2ap_session_stop_req
+)
+{
+ return 0;
+}
+
+int
+rrc_eNB_process_M2AP_RESET(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_reset_t *const m2ap_reset
+)
+{
+ return 0;
+}
+
+int
+rrc_eNB_process_M2AP_ENB_CONFIGURATION_UPDATE_ACK(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_enb_configuration_update_ack_t *const m2ap_enb_configuration_update_ack
+)
+{
+ return 0;
+}
+
+int
+rrc_eNB_process_M2AP_ERROR_INDICATION(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_error_indication_t *const m2ap_error_indication
+)
+{
+ return 0;
+}
+
+int
+rrc_eNB_process_M2AP_MBMS_SERVICE_COUNTING_REQ(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_mbms_service_counting_req_t *const m2ap_mbms_service_counting_req
+)
+{
+ return 0;
+}
+
+int
+rrc_eNB_process_M2AP_MCE_CONFIGURATION_UPDATE(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_mce_configuration_update_t *const m2ap_mce_configuration_update
+)
+{
+ return 0;
+}
+
+
+
+void rrc_eNB_send_M2AP_MBMS_SCHEDULING_INFORMATION_RESP(
+  const protocol_ctxt_t    *const ctxt_pP
+  //,const rrc_eNB_mbms_context_t *const rrc_eNB_mbms_context
+)
+{
+  MessageDef      *msg_p;
+  msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SCHEDULING_INFORMATION_RESP);
+  itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->instance), msg_p);
+}
+
+void rrc_eNB_send_M2AP_MBMS_SESSION_START_RESP(
+  const protocol_ctxt_t    *const ctxt_pP
+  //,const rrc_eNB_mbms_context_t *const rrc_eNB_mbms_context
+)
+{
+  MessageDef      *msg_p;
+  msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SESSION_START_RESP);
+  itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->instance), msg_p);
+}
+
+void rrc_eNB_send_M2AP_MBMS_SESSION_STOP_RESP(
+  const protocol_ctxt_t    *const ctxt_pP
+  //,const rrc_eNB_mbms_context_t *const rrc_eNB_mbms_context
+)
+{
+  MessageDef      *msg_p;
+  msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SESSION_STOP_RESP);
+  itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->instance), msg_p);
+}
+
+void rrc_eNB_send_M2AP_MBMS_SESSION_UPDATE_RESP(
+  const protocol_ctxt_t    *const ctxt_pP
+  //,const rrc_eNB_mbms_context_t *const rrc_eNB_mbms_context
+)
+{
+  MessageDef      *msg_p;
+  msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SESSION_UPDATE_RESP);
+  itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->instance), msg_p);
+}
diff --git a/openair2/RRC/LTE/rrc_eNB_M2AP.h b/openair2/RRC/LTE/rrc_eNB_M2AP.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b95aafb11cd4895ebfc186710531187edddc591
--- /dev/null
+++ b/openair2/RRC/LTE/rrc_eNB_M2AP.h
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file rrc_eNB_M2AP.h
+ * \brief rrc M2AP procedures for eNB
+ * \author Javier Morgade
+ * \version 0.1
+ * \company Vicomtech, Spain
+ * \email: javier.morgade@ieee.org
+ */
+
+#ifndef RRC_ENB_M2AP_H_
+#define RRC_ENB_M2AP_H_
+
+
+int
+rrc_eNB_process_M2AP_SETUP_RESP(
+  const protocol_ctxt_t *const ctxt_pP,
+  int CC_id,
+  instance_t instance,
+  const m2ap_setup_resp_t *const m2ap_setup_resp
+);
+
+int
+rrc_eNB_process_M2AP_MBMS_SCHEDULING_INFORMATION(
+  const protocol_ctxt_t *const ctxt_pP,
+  int CC_id,
+  instance_t instance,
+  const m2ap_mbms_scheduling_information_t *const m2ap_mbms_scheduling_information
+);
+
+int
+rrc_eNB_process_M2AP_MBMS_SESSION_START_REQ(
+  const protocol_ctxt_t *const ctxt_pP,
+  int CC_id,
+  instance_t instance,
+  const m2ap_session_start_req_t *const m2ap_session_start_req
+);
+
+int
+rrc_eNB_process_M2AP_MBMS_SESSION_STOP_REQ(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_session_stop_req_t *const m2ap_session_stop_req
+);
+
+int
+rrc_eNB_process_M2AP_RESET(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_reset_t *const m2ap_reset
+);
+
+int
+rrc_eNB_process_M2AP_ENB_CONFIGURATION_UPDATE_ACK(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_enb_configuration_update_ack_t *const m2ap_enb_configuration_update_ack
+);
+
+int
+rrc_eNB_process_M2AP_ERROR_INDICATION(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_error_indication_t *const m2ap_error_indication
+);
+
+int
+rrc_eNB_process_M2AP_MBMS_SERVICE_COUNTING_REQ(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_mbms_service_counting_req_t *const m2ap_mbms_service_counting_req
+);
+
+int
+rrc_eNB_process_M2AP_MCE_CONFIGURATION_UPDATE(
+  const protocol_ctxt_t *const ctxt_pP,
+  const m2ap_mce_configuration_update_t *const m2ap_mce_configuration_update
+);
+
+
+void rrc_eNB_send_M2AP_MBMS_SCHEDULING_INFORMATION_RESP(
+  const protocol_ctxt_t    *const ctxt_pP
+  //,const rrc_eNB_mbms_context_t *const rrc_eNB_mbms_context
+);
+
+void rrc_eNB_send_M2AP_MBMS_SESSION_START_RESP(
+  const protocol_ctxt_t    *const ctxt_pP
+  //,const rrc_eNB_mbms_context_t *const rrc_eNB_mbms_context
+);
+
+void rrc_eNB_send_M2AP_MBMS_SESSION_STOP_RESP(
+  const protocol_ctxt_t    *const ctxt_pP
+  //,const rrc_eNB_mbms_context_t *const rrc_eNB_mbms_context
+);
+
+void rrc_eNB_send_M2AP_MBMS_SESSION_UPDATE_RESP(
+  const protocol_ctxt_t    *const ctxt_pP
+  //,const rrc_eNB_mbms_context_t *const rrc_eNB_mbms_context
+);
+
+#endif /* RRC_ENB_M2AP_H_ */
diff --git a/openair2/RRC/NAS/nas_config.c b/openair2/RRC/NAS/nas_config.c
index 75d83fa52ec1970391a19e6b1ab8a29af969cfc8..c4bb52b1bbfcad81d53b2b3f0a514770062b5fe4 100644
--- a/openair2/RRC/NAS/nas_config.c
+++ b/openair2/RRC/NAS/nas_config.c
@@ -230,6 +230,87 @@ int NAS_config(char *interfaceName, char *ipAddress, char *networkMask, char *br
   return returnValue;
 }
 
+int nas_config_mbms(int interface_id, int thirdOctet, int fourthOctet, char *ifname) {
+  //char buf[5];
+  char ipAddress[20];
+  char broadcastAddress[20];
+  char interfaceName[20];
+  int returnValue;
+  //if(strcmp(ifname,"ue") == 0)
+       //sprintf(ipAddress, "%s.%d.%d", "20.0",thirdOctet,fourthOctet);
+  ////else
+       sprintf(ipAddress, "%s.%d.%d",baseNetAddress,thirdOctet,fourthOctet);
+
+  sprintf(broadcastAddress, "%s.%d.255",baseNetAddress, thirdOctet);
+  sprintf(interfaceName, "%s%s%d", (UE_NAS_USE_TUN || ENB_NAS_USE_TUN)?"oaitun_":ifname,
+          UE_NAS_USE_TUN?ifname/*"ue"*/: (ENB_NAS_USE_TUN?ifname/*"enb"*/:""),interface_id);
+  bringInterfaceUp(interfaceName, 0);
+  // sets the machine address
+  returnValue= setInterfaceParameter(interfaceName, ipAddress,SIOCSIFADDR);
+
+  // sets the machine network mask
+  if(!returnValue)
+    returnValue= setInterfaceParameter(interfaceName, netMask,SIOCSIFNETMASK);
+
+  // sets the machine broadcast address
+  if(!returnValue)
+    returnValue= setInterfaceParameter(interfaceName, broadcastAddress,SIOCSIFBRDADDR);
+
+  if(!returnValue)
+    bringInterfaceUp(interfaceName, 1);
+
+  if(!returnValue)
+    LOG_I(OIP,"Interface %s successfuly configured, ip address %s, mask %s broadcast address %s\n",
+          interfaceName, ipAddress, netMask, broadcastAddress);
+  else
+    LOG_E(OIP,"Interface %s couldn't be configured (ip address %s, mask %s broadcast address %s)\n",
+          interfaceName, ipAddress, netMask, broadcastAddress);
+
+  return returnValue;
+}
+
+int nas_config_mbms_s1(int interface_id, int thirdOctet, int fourthOctet, char *ifname) {
+  //char buf[5];
+  char ipAddress[20];
+  char broadcastAddress[20];
+  char interfaceName[20];
+  int returnValue;
+  //if(strcmp(ifname,"ue") == 0)
+       //sprintf(ipAddress, "%s.%d.%d", "20.0",thirdOctet,fourthOctet);
+  ////else
+       sprintf(ipAddress, "%s.%d.%d","10.0",thirdOctet,fourthOctet);
+
+  sprintf(broadcastAddress, "%s.%d.255","10.0", thirdOctet);
+  sprintf(interfaceName, "%s%s%d", "oaitun_",ifname,interface_id);
+  bringInterfaceUp(interfaceName, 0);
+  // sets the machine address
+  returnValue= setInterfaceParameter(interfaceName, ipAddress,SIOCSIFADDR);
+
+  // sets the machine network mask
+  if(!returnValue)
+    returnValue= setInterfaceParameter(interfaceName, "255.255.255.0",SIOCSIFNETMASK);
+  printf("returnValue %d\n",returnValue);
+
+  // sets the machine broadcast address
+  if(!returnValue)
+    returnValue= setInterfaceParameter(interfaceName, broadcastAddress,SIOCSIFBRDADDR);
+  printf("returnValue %d\n",returnValue);
+
+  if(!returnValue)
+    bringInterfaceUp(interfaceName, 1);
+  printf("returnValue %d\n",returnValue);
+
+  if(!returnValue)
+    LOG_I(OIP,"Interface %s successfuly configured, ip address %s, mask %s broadcast address %s\n",
+          interfaceName, ipAddress, "255.255.255.0", broadcastAddress);
+  else
+    LOG_E(OIP,"Interface %s couldn't be configured (ip address %s, mask %s broadcast address %s)\n",
+          interfaceName, ipAddress, "255.255.255.0", broadcastAddress);
+
+  return returnValue;
+}
+
+
 // non blocking full configuration of the interface (address, and the two lest octets of the address)
 int nas_config(int interface_id, int thirdOctet, int fourthOctet, char *ifname) {
   //char buf[5];
diff --git a/openair2/RRC/NAS/nas_config.h b/openair2/RRC/NAS/nas_config.h
index fdc3c98f1b0a3ccef3dc881f95c0beca926c2112..de84a854caf7766a7e81a2bbf23e10cfb8005f0f 100644
--- a/openair2/RRC/NAS/nas_config.h
+++ b/openair2/RRC/NAS/nas_config.h
@@ -63,6 +63,34 @@ int NAS_config(char *interfaceName, char *ipAddress, char *networkMask, char *br
  */
 int nas_config(int interface_id, int thirdOctet, int fourthOctet, char *ifsuffix);
 
+/*! \fn int  nas_config_mbms(char*, int, int)
+ * \brief This function initializes the nasmesh interface using the basic values,
+ * basic address, network mask and broadcast address, as the default configured
+ * ones
+ * \param[in] interfaceName, the name of the interface, e.g. nasmesh0 or nasmesh1
+ * \param[in] third octet of the ip address e.g. for the 10.1.2.3 address would be 2
+ * \param[in] fourth octet of the ip address e.g. for the 10.1.2.3 address would be 3
+ * \return 0 on success, otherwise 1, if couldn't open a socket and 2 if the ioctl fails
+ * \note
+ * @ingroup  ?????
+ */
+int nas_config_mbms(int interface_id, int thirdOctet, int fourthOctet, char *ifsuffix);
+
+/*! \fn int  nas_config_mbms_s1(char*, int, int)
+ * \brief This function initializes the nasmesh interface using the basic values,
+ * basic address, network mask and broadcast address, as the default configured
+ * ones
+ * \param[in] interfaceName, the name of the interface, e.g. nasmesh0 or nasmesh1
+ * \param[in] third octet of the ip address e.g. for the 10.1.2.3 address would be 2
+ * \param[in] fourth octet of the ip address e.g. for the 10.1.2.3 address would be 3
+ * \return 0 on success, otherwise 1, if couldn't open a socket and 2 if the ioctl fails
+ * \note
+ * @ingroup  ?????
+ */
+int nas_config_mbms_s1(int interface_id, int thirdOctet, int fourthOctet, char *ifsuffix);
+
+
+
 /*! \fn int  blocking_NAS_config(char*, char*, char*, char*)
  * \brief This function initializes the nasmesh interface, in a blocking way,
  * the system calls are interrupted
diff --git a/openair2/X2AP/x2ap_eNB_management_procedures.c b/openair2/X2AP/x2ap_eNB_management_procedures.c
index 986ca10902ba678c30a1578c95a1aa0881dfd309..469a76a2618a89029dc6f9516791e2264a460c04 100644
--- a/openair2/X2AP/x2ap_eNB_management_procedures.c
+++ b/openair2/X2AP/x2ap_eNB_management_procedures.c
@@ -129,8 +129,8 @@ struct x2ap_eNB_data_s *x2ap_get_eNB(x2ap_eNB_instance_t *instance_p,
   struct x2ap_eNB_data_s  temp;
   struct x2ap_eNB_data_s *found;
 
-printf("x2ap_get_eNB at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
-dump_trees();
+//printf("x2ap_get_eNB at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
+//dump_trees();
 
   memset(&temp, 0, sizeof(struct x2ap_eNB_data_s));
 
diff --git a/openair3/COMMON/messages_types.h b/openair3/COMMON/messages_types.h
index 56a16da554b7a0b34e583df2f1a7c48d210016c1..f91881bf114b177ce680da4349ae6fe285ba0e27 100644
--- a/openair3/COMMON/messages_types.h
+++ b/openair3/COMMON/messages_types.h
@@ -38,5 +38,7 @@
 #include "sgw_lite_messages_types.h"
 #include "udp_messages_types.h"
 #include "mme_app_messages_types.h"
+#include "m2ap_messages_types.h"
+
 
 #endif /* MESSAGES_TYPES_H_ */
diff --git a/openair3/M3AP/MESSAGES/ASN1/R14/m3ap-14.0.0.asn1 b/openair3/M3AP/MESSAGES/ASN1/R14/m3ap-14.0.0.asn1
new file mode 100644
index 0000000000000000000000000000000000000000..b5878c27be2e2ed8e6eb2b10af5a357ba8c5d437
--- /dev/null
+++ b/openair3/M3AP/MESSAGES/ASN1/R14/m3ap-14.0.0.asn1
@@ -0,0 +1,1065 @@
+-- **************************************************************
+--
+-- Elementary Procedure definitions
+--
+-- **************************************************************
+M3AP-PDU-Descriptions {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-PDU-Descriptions (0) }
+DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+IMPORTS
+ Criticality,
+ ProcedureCode
+FROM M3AP-CommonDataTypes
+ MBMSSessionStartRequest,
+ MBMSSessionStartResponse,
+ MBMSSessionStartFailure,
+ MBMSSessionStopRequest,
+ MBMSSessionStopResponse,
+ MBMSSessionUpdateRequest,
+ MBMSSessionUpdateResponse,
+ MBMSSessionUpdateFailure,
+ MCEConfigurationUpdate,
+ MCEConfigurationUpdateAcknowledge,
+ MCEConfigurationUpdateFailure,
+ M3SetupRequest,
+ M3SetupResponse,
+ M3SetupFailure,
+ ErrorIndication,
+ Reset,
+ ResetAcknowledge,
+ PrivateMessage
+FROM M3AP-PDU-Contents
+ id-mBMSsessionStart,
+ id-mBMSsessionStop,
+ id-mBMSsessionUpdate,
+ id-mCEConfigurationUpdate,
+ id-m3Setup,
+ id-errorIndication,
+ id-Reset,
+ id-privateMessage
+FROM M3AP-Constants;
+-- **************************************************************
+--
+-- Interface Elementary Procedure Class
+--
+-- **************************************************************
+M3AP-ELEMENTARY-PROCEDURE ::= CLASS {
+ &InitiatingMessage ,
+ &SuccessfulOutcome OPTIONAL,
+ &UnsuccessfulOutcome OPTIONAL,
+ &procedureCode ProcedureCode UNIQUE,
+ &criticality Criticality DEFAULT ignore
+}
+WITH SYNTAX {
+ INITIATING MESSAGE &InitiatingMessage
+ [SUCCESSFUL OUTCOME &SuccessfulOutcome]
+ [UNSUCCESSFUL OUTCOME &UnsuccessfulOutcome]
+ PROCEDURE CODE &procedureCode
+ [CRITICALITY &criticality]
+}
+-- **************************************************************
+--
+-- Interface PDU Definition
+--
+-- **************************************************************
+M3AP-PDU ::= CHOICE {
+ initiatingMessage InitiatingMessage,
+ successfulOutcome SuccessfulOutcome,
+ unsuccessfulOutcome UnsuccessfulOutcome,
+ ...
+}
+InitiatingMessage ::= SEQUENCE {
+ procedureCode M3AP-ELEMENTARY-PROCEDURE.&procedureCode ({M3AP-ELEMENTARY-PROCEDURES}),
+ criticality M3AP-ELEMENTARY-PROCEDURE.&criticality ({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+ value M3AP-ELEMENTARY-PROCEDURE.&InitiatingMessage ({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+SuccessfulOutcome ::= SEQUENCE {
+ procedureCode M3AP-ELEMENTARY-PROCEDURE.&procedureCode ({M3AP-ELEMENTARY-PROCEDURES}),
+ criticality M3AP-ELEMENTARY-PROCEDURE.&criticality ({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+ value M3AP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome ({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+UnsuccessfulOutcome ::= SEQUENCE {
+ procedureCode M3AP-ELEMENTARY-PROCEDURE.&procedureCode ({M3AP-ELEMENTARY-PROCEDURES}),
+ criticality M3AP-ELEMENTARY-PROCEDURE.&criticality ({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+ value M3AP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome ({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+-- **************************************************************
+--
+-- Interface Elementary Procedure List
+-- 
+-- **************************************************************
+M3AP-ELEMENTARY-PROCEDURES M3AP-ELEMENTARY-PROCEDURE ::= {
+ M3AP-ELEMENTARY-PROCEDURES-CLASS-1 |
+ M3AP-ELEMENTARY-PROCEDURES-CLASS-2 ,
+ ...
+}
+M3AP-ELEMENTARY-PROCEDURES-CLASS-1 M3AP-ELEMENTARY-PROCEDURE ::= {
+ mBMSsessionStart |
+ mBMSsessionStop |
+ mBMSsessionUpdate |
+ reset |
+ m3Setup |
+ mCEConfigurationUpdate ,
+ ...
+}
+M3AP-ELEMENTARY-PROCEDURES-CLASS-2 M3AP-ELEMENTARY-PROCEDURE ::= {
+ errorIndication |
+ privateMessage ,
+ ...
+}
+-- **************************************************************
+--
+-- Interface Elementary Procedures
+--
+-- **************************************************************
+mBMSsessionStart M3AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE MBMSSessionStartRequest
+ SUCCESSFUL OUTCOME MBMSSessionStartResponse
+ UNSUCCESSFUL OUTCOME MBMSSessionStartFailure
+ PROCEDURE CODE id-mBMSsessionStart
+ CRITICALITY reject
+}
+mBMSsessionStop M3AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE MBMSSessionStopRequest
+ SUCCESSFUL OUTCOME MBMSSessionStopResponse
+ PROCEDURE CODE id-mBMSsessionStop
+ CRITICALITY reject
+}
+mBMSsessionUpdate M3AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE MBMSSessionUpdateRequest
+ SUCCESSFUL OUTCOME MBMSSessionUpdateResponse
+ UNSUCCESSFUL OUTCOME MBMSSessionUpdateFailure
+ PROCEDURE CODE id-mBMSsessionUpdate
+ CRITICALITY reject
+} 
+errorIndication M3AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE ErrorIndication
+ PROCEDURE CODE id-errorIndication
+ CRITICALITY ignore
+}
+reset M3AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE Reset
+ SUCCESSFUL OUTCOME ResetAcknowledge
+ PROCEDURE CODE id-Reset
+ CRITICALITY reject
+}
+privateMessage M3AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE PrivateMessage
+ PROCEDURE CODE id-privateMessage
+ CRITICALITY ignore
+}
+mCEConfigurationUpdate M3AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE MCEConfigurationUpdate
+ SUCCESSFUL OUTCOME MCEConfigurationUpdateAcknowledge
+ UNSUCCESSFUL OUTCOME MCEConfigurationUpdateFailure
+ PROCEDURE CODE id-mCEConfigurationUpdate
+ CRITICALITY reject
+}
+m3Setup M3AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE M3SetupRequest
+ SUCCESSFUL OUTCOME M3SetupResponse
+ UNSUCCESSFUL OUTCOME M3SetupFailure
+ PROCEDURE CODE id-m3Setup
+ CRITICALITY reject
+}
+END 
+
+-- **************************************************************
+--
+-- PDU definitions for M3AP.
+--
+-- **************************************************************
+M3AP-PDU-Contents {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-PDU-Contents (1) }
+DEFINITIONS AUTOMATIC TAGS ::= 
+BEGIN
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+IMPORTS
+ Absolute-Time-ofMBMS-Data,
+ Cause,
+ CriticalityDiagnostics,
+ Global-MCE-ID,
+ MBMS-E-RAB-QoS-Parameters,
+ MBMS-Service-associatedLogicalM3-ConnectionItem,
+ MBMS-Service-Area,
+ MBMSServiceArea1,
+ MBMS-Session-Duration,
+ MBMS-Session-ID,
+ MCE-MBMS-M3AP-ID,
+ MCEname,
+ MinimumTimeToMBMSDataTransfer,
+ MME-MBMS-M3AP-ID,
+ TimeToWait,
+ TMGI,
+ TNL-Information,
+ Reestablishment,
+ MBMS-Cell-List
+FROM M3AP-IEs
+ PrivateIE-Container{},
+ ProtocolExtensionContainer{},
+ ProtocolIE-Container{},
+ ProtocolIE-ContainerList{},
+ ProtocolIE-ContainerPair{},
+ ProtocolIE-ContainerPairList{},
+ ProtocolIE-Single-Container{},
+ M3AP-PRIVATE-IES,
+ M3AP-PROTOCOL-EXTENSION,
+ M3AP-PROTOCOL-IES,
+ M3AP-PROTOCOL-IES-PAIR
+FROM M3AP-Containers
+ id-AllocationAndRetentionPriority,
+ id-MCE-MBMS-M3AP-ID,
+ id-MME-MBMS-M3AP-ID,
+ id-TMGI,
+ id-MBMS-Session-ID,
+ id-MBMS-E-RAB-QoS-Parameters,
+ id-MBMS-Session-Duration,
+ id-MBMS-Service-Area,
+ id-TNL-Information,
+id-Alternative-TNL-Information,
+ id-CriticalityDiagnostics,
+ id-Cause,
+ id-MBMS-Service-Area-List,
+ id-MBMS-Service-Area-List-Item,
+ id-TimeToWait,
+ id-ResetType,
+ id-MBMS-Service-associatedLogicalM3-ConnectionItem,
+ id-MBMS-Service-associatedLogicalM3-ConnectionListResAck,
+ id-MBMSServiceAreaList,
+ id-MinimumTimeToMBMSDataTransfer,
+ id-Time-ofMBMS-DataStop,
+ id-Time-ofMBMS-DataTransfer,
+ id-Global-MCE-ID,
+ id-MCEname,
+ id-Reestablishment,
+ id-MBMS-Cell-List,
+ maxnoofMBMSServiceAreaIdentitiesPerMCE,
+ maxnooferrors,
+ maxNrOfIndividualM3ConnectionsToReset
+FROM M3AP-Constants;
+-- **************************************************************
+--
+-- MBMS SESSION START REQUEST
+--
+-- **************************************************************
+MBMSSessionStartRequest ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{MBMSSessionStartRequest-IEs}},
+ ...
+}
+MBMSSessionStartRequest-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY reject TYPE MME-MBMS-M3AP-ID PRESENCE mandatory}|
+ { ID id-TMGI CRITICALITY reject TYPE TMGI PRESENCE mandatory}|
+ { ID id-MBMS-Session-ID CRITICALITY ignore TYPE MBMS-Session-ID PRESENCE optional}|
+ { ID id-MBMS-E-RAB-QoS-Parameters CRITICALITY reject TYPE MBMS-E-RAB-QoS-Parameters PRESENCE mandatory}|
+ { ID id-MBMS-Session-Duration CRITICALITY reject TYPE MBMS-Session-Duration PRESENCE mandatory}|
+ { ID id-MBMS-Service-Area CRITICALITY reject TYPE MBMS-Service-Area PRESENCE mandatory}|
+ { ID id-MinimumTimeToMBMSDataTransfer CRITICALITY reject TYPE MinimumTimeToMBMSDataTransfer PRESENCE mandatory}|
+ { ID id-TNL-Information CRITICALITY reject TYPE TNL-Information PRESENCE mandatory}|
+ { ID id-Time-ofMBMS-DataTransfer CRITICALITY ignore TYPE Absolute-Time-ofMBMS-Data PRESENCE optional}|
+ { ID id-Reestablishment CRITICALITY ignore TYPE Reestablishment PRESENCE optional}|
+ { ID id-Alternative-TNL-Information CRITICALITY ignore TYPE TNL-Information PRESENCE optional}|
+ { ID id-MBMS-Cell-List CRITICALITY reject TYPE MBMS-Cell-List PRESENCE optional},
+ ...
+}
+-- **************************************************************
+--
+-- MBMS SESSION START RESPONSE
+-- 
+-- **************************************************************
+MBMSSessionStartResponse ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{ MBMSSessionStartResponse-IEs}},
+ ...
+}
+MBMSSessionStartResponse-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY ignore TYPE MME-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-MCE-MBMS-M3AP-ID CRITICALITY ignore TYPE MCE-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional },
+ ...
+}
+-- **************************************************************
+--
+-- MBMS SESSION START FAILURE
+--
+-- **************************************************************
+MBMSSessionStartFailure ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{ MBMSSessionStartFailure-IEs}},
+ ...
+}
+MBMSSessionStartFailure-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY ignore TYPE MME-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory } |
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional },
+ ...
+}
+-- **************************************************************
+--
+-- MBMS SESSION STOP REQUEST
+--
+-- **************************************************************
+MBMSSessionStopRequest ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{MBMSSessionStopRequest-IEs}},
+ ...
+}
+MBMSSessionStopRequest-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY reject TYPE MME-MBMS-M3AP-ID PRESENCE mandatory}|
+ { ID id-MCE-MBMS-M3AP-ID CRITICALITY reject TYPE MCE-MBMS-M3AP-ID PRESENCE mandatory}|
+ { ID id-Time-ofMBMS-DataStop CRITICALITY ignore TYPE Absolute-Time-ofMBMS-Data PRESENCE optional},
+ ...
+}
+-- **************************************************************
+-- 
+-- MBMS SESSION STOP RESPONSE
+--
+-- **************************************************************
+MBMSSessionStopResponse ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{ MBMSSessionStopResponse-IEs}},
+ ...
+}
+MBMSSessionStopResponse-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY ignore TYPE MME-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-MCE-MBMS-M3AP-ID CRITICALITY ignore TYPE MCE-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional } ,
+ ...
+}
+-- **************************************************************
+--
+-- MBMS SESSION UPDATE REQUEST
+--
+-- **************************************************************
+MBMSSessionUpdateRequest ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{MBMSSessionUpdateRequest-IEs}},
+ ...
+}
+MBMSSessionUpdateRequest-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY reject TYPE MME-MBMS-M3AP-ID PRESENCE mandatory}|
+ { ID id-MCE-MBMS-M3AP-ID CRITICALITY reject TYPE MCE-MBMS-M3AP-ID PRESENCE mandatory}|
+ { ID id-TMGI CRITICALITY reject TYPE TMGI PRESENCE mandatory}|
+ { ID id-MBMS-Session-ID CRITICALITY ignore TYPE MBMS-Session-ID PRESENCE optional}|
+ { ID id-MBMS-E-RAB-QoS-Parameters CRITICALITY reject TYPE MBMS-E-RAB-QoS-Parameters PRESENCE mandatory}|
+ { ID id-MBMS-Session-Duration CRITICALITY reject TYPE MBMS-Session-Duration PRESENCE mandatory}|
+ { ID id-MBMS-Service-Area CRITICALITY ignore TYPE MBMS-Service-Area PRESENCE optional}|
+ { ID id-MinimumTimeToMBMSDataTransfer CRITICALITY reject TYPE MinimumTimeToMBMSDataTransfer PRESENCE mandatory}|
+ { ID id-TNL-Information CRITICALITY ignore TYPE TNL-Information PRESENCE optional}|
+ { ID id-Time-ofMBMS-DataTransfer CRITICALITY ignore TYPE Absolute-Time-ofMBMS-Data PRESENCE optional}|
+ { ID id-MBMS-Cell-List CRITICALITY reject TYPE MBMS-Cell-List PRESENCE optional},
+ ...
+}
+-- **************************************************************
+--
+-- MBMS SESSION UPDATE RESPONSE
+--
+-- **************************************************************
+MBMSSessionUpdateResponse ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{ MBMSSessionUpdateResponse-IEs}},
+ ...
+}
+MBMSSessionUpdateResponse-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY ignore TYPE MME-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-MCE-MBMS-M3AP-ID CRITICALITY ignore TYPE MCE-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional },
+ ...
+}
+-- **************************************************************
+--
+-- MBMS SESSION UPDATE FAILURE
+--
+-- **************************************************************
+MBMSSessionUpdateFailure ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{ MBMSSessionUpdateFailure-IEs}},
+ ...
+}
+MBMSSessionUpdateFailure-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY ignore TYPE MME-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-MCE-MBMS-M3AP-ID CRITICALITY ignore TYPE MCE-MBMS-M3AP-ID PRESENCE mandatory } |
+ { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory } |
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional },
+ ...
+}
+-- **************************************************************
+--
+-- ERROR INDICATION
+--
+-- **************************************************************
+ErrorIndication ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{ErrorIndication-IEs}},
+ ...
+}
+ErrorIndication-IEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MME-MBMS-M3AP-ID CRITICALITY ignore TYPE MME-MBMS-M3AP-ID PRESENCE optional } |
+ { ID id-MCE-MBMS-M3AP-ID CRITICALITY ignore TYPE MCE-MBMS-M3AP-ID PRESENCE optional } |
+ { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE optional } |
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional } ,
+ ...
+}
+-- **************************************************************
+--
+-- Reset
+--
+-- **************************************************************
+Reset ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {ResetIEs} },
+ ... 
+}
+ResetIEs M3AP-PROTOCOL-IES ::= {
+ { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }|
+ { ID id-ResetType CRITICALITY reject TYPE ResetType PRESENCE mandatory },
+ ...
+}
+ResetType ::= CHOICE {
+ m3-Interface ResetAll,
+ partOfM3-Interface MBMS-Service-associatedLogicalM3-ConnectionListRes,
+ ...
+}
+ResetAll ::= ENUMERATED {
+ reset-all,
+ ...
+}
+MBMS-Service-associatedLogicalM3-ConnectionListRes ::= SEQUENCE (SIZE(1.. maxNrOfIndividualM3ConnectionsToReset)) OF ProtocolIE-Single-Container {
+{ MBMS-Service-associatedLogicalM3-ConnectionItemRes } }
+MBMS-Service-associatedLogicalM3-ConnectionItemRes M3AP-PROTOCOL-IES ::= {
+ { ID id-MBMS-Service-associatedLogicalM3-ConnectionItem CRITICALITY reject TYPE MBMS-Service-associatedLogicalM3-ConnectionItem PRESENCE
+mandatory },
+ ...
+}
+-- **************************************************************
+--
+-- Reset Acknowledge
+--
+-- **************************************************************
+ResetAcknowledge ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {ResetAcknowledgeIEs} },
+ ...
+}
+ResetAcknowledgeIEs M3AP-PROTOCOL-IES ::= {
+ { ID id-MBMS-Service-associatedLogicalM3-ConnectionListResAck CRITICALITY ignore TYPE MBMS-Service-associatedLogicalM3-ConnectionListResAck PRESENCE optional }|
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional },
+ ...
+}
+MBMS-Service-associatedLogicalM3-ConnectionListResAck ::= SEQUENCE (SIZE(1.. maxNrOfIndividualM3ConnectionsToReset)) OF ProtocolIE-Single-Container
+{ { MBMS-Service-associatedLogicalM3-ConnectionItemResAck } }
+MBMS-Service-associatedLogicalM3-ConnectionItemResAck M3AP-PROTOCOL-IES ::= {
+{ ID id-MBMS-Service-associatedLogicalM3-ConnectionItem CRITICALITY ignore TYPE MBMS-Service-associatedLogicalM3-ConnectionItem PRESENCE
+mandatory },
+ ...
+}
+-- **************************************************************
+--
+-- PRIVATE MESSAGE
+--
+-- **************************************************************
+PrivateMessage ::= SEQUENCE {
+ privateIEs PrivateIE-Container {{PrivateMessage-IEs}},
+ ...
+}
+PrivateMessage-IEs M3AP-PRIVATE-IES ::= {
+ ...
+}
+-- **************************************************************
+--
+-- M3 SETUP ELEMENTARY PROCEDURE
+--
+-- **************************************************************
+-- **************************************************************
+--
+-- M3 Setup Request
+--
+-- **************************************************************
+M3SetupRequest ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {M3SetupRequestIEs} },
+ ...
+}
+M3SetupRequestIEs M3AP-PROTOCOL-IES ::= {
+ { ID id-Global-MCE-ID CRITICALITY reject TYPE Global-MCE-ID PRESENCE mandatory}|
+ { ID id-MCEname CRITICALITY ignore TYPE MCEname PRESENCE optional}|
+ { ID id-MBMSServiceAreaList CRITICALITY reject TYPE MBMSServiceAreaListItem PRESENCE mandatory},
+ ...
+}
+MBMSServiceAreaListItem ::= SEQUENCE (SIZE(1..maxnoofMBMSServiceAreaIdentitiesPerMCE)) OF MBMSServiceArea1
+-- **************************************************************
+--
+-- M3 Setup Response
+--
+-- ************************************************************** 
+M3SetupResponse ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {M3SetupResponseIEs} },
+ ...
+}
+M3SetupResponseIEs M3AP-PROTOCOL-IES ::= {
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional},
+ ...
+}
+-- **************************************************************
+--
+-- M3 Setup Failure
+--
+-- **************************************************************
+M3SetupFailure ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {M3SetupFailureIEs} },
+ ...
+}
+M3SetupFailureIEs M3AP-PROTOCOL-IES ::= {
+ { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory}|
+ { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional}|
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional},
+ ...
+}
+-- **************************************************************
+--
+-- MCE CONFIGURATION UPDATE ELEMENTARY PROCEDURE
+--
+-- **************************************************************
+-- **************************************************************
+--
+-- MCE Configuration Update
+--
+-- **************************************************************
+MCEConfigurationUpdate ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {MCEConfigurationUpdateIEs} },
+ ...
+}
+MCEConfigurationUpdateIEs M3AP-PROTOCOL-IES ::= {
+ { ID id-Global-MCE-ID CRITICALITY reject TYPE Global-MCE-ID PRESENCE optional}|
+ { ID id-MCEname CRITICALITY ignore TYPE MCEname PRESENCE optional}|
+ { ID id-MBMSServiceAreaList CRITICALITY reject TYPE MBMSServiceAreaListItem PRESENCE optional},
+ ...
+}
+-- **************************************************************
+--
+-- MCE Configuration Update Acknowledge
+--
+-- **************************************************************
+MCEConfigurationUpdateAcknowledge ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {MCEConfigurationUpdateAcknowledgeIEs} },
+ ...
+}
+MCEConfigurationUpdateAcknowledgeIEs M3AP-PROTOCOL-IES ::= {
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional },
+ ...
+}
+-- **************************************************************
+--
+-- MCE Configuration Update Failure
+--
+-- **************************************************************
+MCEConfigurationUpdateFailure ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {MCEConfigurationUpdateFailureIEs} },
+ ...
+}
+MCEConfigurationUpdateFailureIEs M3AP-PROTOCOL-IES ::= {
+ { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory}|
+ { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional}|
+ { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional},
+ ...
+}
+END
+
+-- **************************************************************
+--
+-- Information Element Definitions
+--
+-- **************************************************************
+M3AP-IEs {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-IEs (2) }
+DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN 
+IMPORTS
+ id-AllocationAndRetentionPriority,
+ maxnooferrors,
+ maxnoofCellsforMBMS
+FROM M3AP-Constants
+ Criticality,
+ ProcedureCode,
+ ProtocolIE-ID,
+ TriggeringMessage
+FROM M3AP-CommonDataTypes
+ ProtocolExtensionContainer{},
+ ProtocolIE-Single-Container{},
+ M3AP-PROTOCOL-EXTENSION,
+ M3AP-PROTOCOL-IES
+FROM M3AP-Containers;
+-- A
+Absolute-Time-ofMBMS-Data ::= BIT STRING (SIZE (64))
+AllocationAndRetentionPriority ::= SEQUENCE {
+ priorityLevel PriorityLevel,
+ pre-emptionCapability Pre-emptionCapability,
+ pre-emptionVulnerability Pre-emptionVulnerability,
+ iE-Extensions ProtocolExtensionContainer { {AllocationAndRetentionPriority-ExtIEs} } OPTIONAL
+}
+AllocationAndRetentionPriority-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+-- B
+BitRate ::= INTEGER (0..10000000000)
+-- C
+Cause ::= CHOICE {
+ radioNetwork CauseRadioNetwork,
+ transport CauseTransport,
+ nAS CauseNAS,
+ protocol CauseProtocol,
+ misc CauseMisc,
+ ...
+}
+CauseMisc ::= ENUMERATED {
+ control-processing-overload,
+ not-enough-user-plane-processing-resources,
+ hardware-failure,
+ om-intervention,
+unspecified,
+ ...
+}
+CauseNAS ::= ENUMERATED {
+ unspecified,
+ ...
+}
+CauseProtocol ::= ENUMERATED {
+ transfer-syntax-error,
+ abstract-syntax-error-reject,
+ abstract-syntax-error-ignore-and-notify,
+ message-not-compatible-with-receiver-state,
+ semantic-error,
+ abstract-syntax-error-falsely-constructed-message,
+ unspecified,
+ ...
+}
+CauseRadioNetwork ::= ENUMERATED {
+ unknown-or-already-allocated-MME-MBMS-M3AP-ID,
+ unknown-or-already-allocated-MCE-MBMS-M3AP-ID,
+ unknown-or-inconsistent-pair-of-MBMS-M3AP-IDs,
+ radio-resources-not-available,
+ invalid-QoS-combination,
+ interaction-with-other-procedure,
+ not-supported-QCI-value,
+ unspecified,
+ ...,
+ uninvolved-MCE
+}
+CauseTransport ::= ENUMERATED {
+ transport-resource-unavailable,
+ unspecified,
+ ...
+}
+CriticalityDiagnostics ::= SEQUENCE {
+ procedureCode ProcedureCode OPTIONAL,
+ triggeringMessage TriggeringMessage OPTIONAL,
+ procedureCriticality Criticality OPTIONAL,
+ iEsCriticalityDiagnostics CriticalityDiagnostics-IE-List OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer { {CriticalityDiagnostics-ExtIEs} } OPTIONAL,
+ ...
+}
+CriticalityDiagnostics-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+} 
+CriticalityDiagnostics-IE-List ::= SEQUENCE (SIZE (1..maxnooferrors)) OF
+ SEQUENCE {
+ iECriticality Criticality,
+ iE-ID ProtocolIE-ID,
+ typeOfError TypeOfError,
+ iE-Extensions ProtocolExtensionContainer { {CriticalityDiagnostics-IE-List-ExtIEs} } OPTIONAL,
+ ...
+}
+CriticalityDiagnostics-IE-List-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+-- D
+-- E
+ECGI ::= SEQUENCE {
+ pLMN-Identity PLMN-Identity,
+ eUTRANcellIdentifier EUTRANCellIdentifier,
+ iE-Extensions ProtocolExtensionContainer { {ECGI-ExtIEs} } OPTIONAL,
+ ...
+}
+ECGI-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+EUTRANCellIdentifier ::= BIT STRING (SIZE (28))
+ExtendedMCE-ID ::= OCTET STRING (SIZE(1))
+-- F
+-- G
+Global-MCE-ID ::= SEQUENCE {
+ pLMN-Identity PLMN-Identity,
+ mCE-ID MCE-ID,
+ extendedMCE-ID ExtendedMCE-ID OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer { {GlobalMCE-ID-ExtIEs} } OPTIONAL,
+ ...
+}
+GlobalMCE-ID-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+GBR-QosInformation ::= SEQUENCE {
+ mBMS-E-RAB-MaximumBitrateDL BitRate,
+ mBMS-E-RAB-GuaranteedBitrateDL BitRate,
+ iE-Extensions ProtocolExtensionContainer { { GBR-QosInformation-ExtIEs} } OPTIONAL,
+ ...
+} 
+GBR-QosInformation-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+GTP-TEID ::= OCTET STRING (SIZE (4))
+-- H
+-- I
+IPAddress ::= OCTET STRING (SIZE(4..16, ...))
+-- J
+-- K
+-- L
+-- M
+MBMS-Cell-List ::= SEQUENCE (SIZE(1.. maxnoofCellsforMBMS)) OF ECGI
+MBMS-E-RAB-QoS-Parameters ::= SEQUENCE {
+ qCI QCI,
+ gbrQosInformation GBR-QosInformation OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer { { MBMS-E-RAB-QoS-Parameters-ExtIEs} } OPTIONAL,
+ ...
+}
+MBMS-E-RAB-QoS-Parameters-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+-- Extension for Release 10 ARP support --
+ {ID id-AllocationAndRetentionPriority CRITICALITY ignore EXTENSION AllocationAndRetentionPriority PRESENCE mandatory},
+ ...
+}
+MBMS-Service-associatedLogicalM3-ConnectionItem ::= SEQUENCE {
+ mME-MBMS-M3AP-ID MME-MBMS-M3AP-ID OPTIONAL,
+ mCE-MBMS-M3AP-ID MCE-MBMS-M3AP-ID OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer { { MBMS-Service-associatedLogicalM3-ConnectionItemExtIEs} } OPTIONAL,
+ ...
+}
+MBMS-Service-associatedLogicalM3-ConnectionItemExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+MBMSServiceArea1 ::= OCTET STRING (SIZE (2))
+MBMS-Service-Area ::= OCTET STRING
+MBMS-Session-Duration ::= OCTET STRING (SIZE (3))
+MBMS-Session-ID ::= OCTET STRING (SIZE (1))
+MCE-MBMS-M3AP-ID ::= INTEGER (0..65535) 
+MCE-ID ::= OCTET STRING (SIZE(2))
+MCEname ::= PrintableString (SIZE (1..150,...))
+MinimumTimeToMBMSDataTransfer ::= OCTET STRING (SIZE (1))
+MME-MBMS-M3AP-ID ::= INTEGER (0..65535)
+-- N
+-- O
+-- P
+Pre-emptionCapability ::= ENUMERATED {
+ shall-not-trigger-pre-emption,
+ may-trigger-pre-emption
+}
+Pre-emptionVulnerability ::= ENUMERATED {
+ not-pre-emptable,
+ pre-emptable
+}
+PriorityLevel ::= INTEGER { spare (0), highest (1), lowest (14), no-priority (15) } (0..15)
+PLMN-Identity ::= OCTET STRING (SIZE(3))
+-- Q
+QCI ::= INTEGER (0..255)
+-- R
+Reestablishment ::= ENUMERATED {true, ...}
+-- S
+-- T
+TimeToWait ::= ENUMERATED {v1s, v2s, v5s, v10s, v20s, v60s, ...}
+TMGI ::= SEQUENCE {
+ pLMNidentity PLMN-Identity,
+ serviceID OCTET STRING (SIZE (3)),
+ iE-Extensions ProtocolExtensionContainer { {TMGI-ExtIEs} } OPTIONAL
+}
+TMGI-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+TNL-Information ::= SEQUENCE {
+ iPMCAddress IPAddress,
+ iPSourceAddress IPAddress,  gTP-DLTEID GTP-TEID,
+ iE-Extensions ProtocolExtensionContainer { {TNL-Information-ExtIEs} } OPTIONAL,
+ ...
+}
+TNL-Information-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+TypeOfError ::= ENUMERATED {
+ not-understood,
+ missing,
+ ...
+}
+-- U
+-- V
+-- W
+-- X
+-- Y
+-- Z
+END 
+
+-- **************************************************************
+--
+-- Common definitions
+--
+-- **************************************************************
+M3AP-CommonDataTypes {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-CommonDataTypes (3) }
+DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+-- **************************************************************
+--
+-- Extension constants
+--
+-- **************************************************************
+maxPrivateIEs INTEGER ::= 65535
+maxProtocolExtensions INTEGER ::= 65535
+maxProtocolIEs INTEGER ::= 65535
+-- ************************************************************** 
+--
+-- Common Data Types
+--
+-- **************************************************************
+Criticality ::= ENUMERATED { reject, ignore, notify }
+Presence ::= ENUMERATED { optional, conditional, mandatory }
+PrivateIE-ID ::= CHOICE {
+ local INTEGER (0.. maxPrivateIEs),
+ global OBJECT IDENTIFIER
+}
+ProcedureCode ::= INTEGER (0..255)
+ProtocolIE-ID ::= INTEGER (0..maxProtocolIEs)
+TriggeringMessage ::= ENUMERATED { initiating-message, successful-outcome, unsuccessful-outcome}
+END 
+
+-- **************************************************************
+--
+-- Constant definitions
+--
+-- **************************************************************
+M3AP-Constants {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-Constants (4) }
+DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+IMPORTS
+ ProcedureCode,
+ ProtocolIE-ID
+FROM M3AP-CommonDataTypes;
+-- **************************************************************
+--
+-- Elementary Procedures
+--
+-- **************************************************************
+id-mBMSsessionStart ProcedureCode ::= 0
+id-mBMSsessionStop ProcedureCode ::= 1
+id-errorIndication ProcedureCode ::= 2
+id-privateMessage ProcedureCode ::= 3
+id-Reset ProcedureCode ::= 4
+id-mBMSsessionUpdate ProcedureCode ::= 5
+id-mCEConfigurationUpdate ProcedureCode ::= 6
+id-m3Setup ProcedureCode ::= 7
+-- **************************************************************
+--
+-- Lists
+--
+-- **************************************************************
+maxnoofMBMSServiceAreaIdentitiesPerMCE INTEGER ::= 65536
+maxnooferrors INTEGER ::= 256
+maxNrOfIndividualM3ConnectionsToReset INTEGER ::= 256
+maxnoofCellsforMBMS INTEGER ::= 4096
+-- **************************************************************
+--
+-- IEs
+--
+-- **************************************************************
+id-MME-MBMS-M3AP-ID ProtocolIE-ID ::= 0
+id-MCE-MBMS-M3AP-ID ProtocolIE-ID ::= 1
+id-TMGI ProtocolIE-ID ::= 2
+id-MBMS-Session-ID ProtocolIE-ID ::= 3
+id-MBMS-E-RAB-QoS-Parameters ProtocolIE-ID ::= 4
+id-MBMS-Session-Duration ProtocolIE-ID ::= 5
+id-MBMS-Service-Area ProtocolIE-ID ::= 6
+id-TNL-Information ProtocolIE-ID ::= 7
+id-CriticalityDiagnostics ProtocolIE-ID ::= 8
+id-Cause ProtocolIE-ID ::= 9
+id-MBMS-Service-Area-List ProtocolIE-ID ::= 10
+id-MBMS-Service-Area-List-Item ProtocolIE-ID ::= 11
+id-TimeToWait ProtocolIE-ID ::= 12
+id-ResetType ProtocolIE-ID ::= 13
+id-MBMS-Service-associatedLogicalM3-ConnectionItem ProtocolIE-ID ::= 14
+id-MBMS-Service-associatedLogicalM3-ConnectionListResAck ProtocolIE-ID ::= 15
+id-MinimumTimeToMBMSDataTransfer ProtocolIE-ID ::= 16
+id-AllocationAndRetentionPriority ProtocolIE-ID ::= 17
+id-Global-MCE-ID ProtocolIE-ID ::= 18
+id-MCEname ProtocolIE-ID ::= 19
+id-MBMSServiceAreaList ProtocolIE-ID ::= 20
+id-Time-ofMBMS-DataTransfer ProtocolIE-ID ::= 21
+id-Time-ofMBMS-DataStop ProtocolIE-ID ::= 22
+id-Reestablishment ProtocolIE-ID ::= 23
+id-Alternative-TNL-Information ProtocolIE-ID ::= 24
+id-MBMS-Cell-List ProtocolIE-ID ::= 25
+END 
+-- **************************************************************
+--
+-- Container definitions
+--
+-- **************************************************************
+M3AP-Containers {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-Containers (5) }
+DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+IMPORTS
+ maxPrivateIEs,
+ maxProtocolExtensions,
+ maxProtocolIEs,
+ Criticality,
+ Presence,
+ PrivateIE-ID,
+ ProtocolIE-ID
+FROM M3AP-CommonDataTypes;
+-- **************************************************************
+--
+-- Class Definition for Protocol IEs
+--
+-- **************************************************************
+M3AP-PROTOCOL-IES ::= CLASS {
+ &id ProtocolIE-ID UNIQUE,
+ &criticality Criticality,
+ &Value,
+ &presence Presence
+}
+WITH SYNTAX {
+ ID &id
+ CRITICALITY &criticality
+ TYPE &Value
+ PRESENCE &presence
+} 
+-- **************************************************************
+--
+-- Class Definition for Protocol IEs
+--
+-- **************************************************************
+M3AP-PROTOCOL-IES-PAIR ::= CLASS {
+ &id ProtocolIE-ID UNIQUE,
+ &firstCriticality Criticality,
+ &FirstValue,
+ &secondCriticality Criticality,
+ &SecondValue,
+ &presence Presence
+}
+WITH SYNTAX {
+ ID &id
+ FIRST CRITICALITY &firstCriticality
+ FIRST TYPE &FirstValue
+ SECOND CRITICALITY &secondCriticality
+ SECOND TYPE &SecondValue
+ PRESENCE &presence
+}
+-- **************************************************************
+--
+-- Class Definition for Protocol Extensions
+--
+-- **************************************************************
+M3AP-PROTOCOL-EXTENSION ::= CLASS {
+ &id ProtocolIE-ID UNIQUE,
+ &criticality Criticality,
+ &Extension,
+ &presence Presence
+}
+WITH SYNTAX {
+ ID &id
+ CRITICALITY &criticality
+ EXTENSION &Extension
+ PRESENCE &presence
+}
+-- **************************************************************
+--
+-- Class Definition for Private IEs
+--
+-- **************************************************************
+M3AP-PRIVATE-IES ::= CLASS {
+ &id PrivateIE-ID,
+ &criticality Criticality,
+ &Value,
+ &presence Presence
+} 
+
+WITH SYNTAX {
+ ID &id
+ CRITICALITY &criticality
+ TYPE &Value
+ PRESENCE &presence
+}
+-- **************************************************************
+--
+-- Container for Protocol IEs
+--
+-- **************************************************************
+ProtocolIE-Container {M3AP-PROTOCOL-IES : IEsSetParam} ::=
+ SEQUENCE (SIZE (0..maxProtocolIEs)) OF
+ ProtocolIE-Field {{IEsSetParam}}
+ProtocolIE-Single-Container {M3AP-PROTOCOL-IES : IEsSetParam} ::=
+ ProtocolIE-Field {{IEsSetParam}}
+ProtocolIE-Field {M3AP-PROTOCOL-IES : IEsSetParam} ::= SEQUENCE {
+ id M3AP-PROTOCOL-IES.&id ({IEsSetParam}),
+ criticality M3AP-PROTOCOL-IES.&criticality ({IEsSetParam}{@id}),
+ value M3AP-PROTOCOL-IES.&Value ({IEsSetParam}{@id})
+}
+-- **************************************************************
+--
+-- Container for Protocol IE Pairs
+--
+-- **************************************************************
+ProtocolIE-ContainerPair {M3AP-PROTOCOL-IES-PAIR : IEsSetParam} ::=
+ SEQUENCE (SIZE (0..maxProtocolIEs)) OF
+ ProtocolIE-FieldPair {{IEsSetParam}}
+ProtocolIE-FieldPair {M3AP-PROTOCOL-IES-PAIR : IEsSetParam} ::= SEQUENCE {
+ id M3AP-PROTOCOL-IES-PAIR.&id ({IEsSetParam}),
+ firstCriticality M3AP-PROTOCOL-IES-PAIR.&firstCriticality ({IEsSetParam}{@id}),
+ firstValue M3AP-PROTOCOL-IES-PAIR.&FirstValue ({IEsSetParam}{@id}),
+ secondCriticality M3AP-PROTOCOL-IES-PAIR.&secondCriticality ({IEsSetParam}{@id}),
+ secondValue M3AP-PROTOCOL-IES-PAIR.&SecondValue ({IEsSetParam}{@id})
+}
+-- **************************************************************
+--
+-- Container Lists for Protocol IE Containers
+--
+-- **************************************************************
+ProtocolIE-ContainerList {INTEGER : lowerBound, INTEGER : upperBound, M3AP-PROTOCOL-IES : IEsSetParam} ::=
+ SEQUENCE (SIZE (lowerBound..upperBound)) OF
+ ProtocolIE-Container {{IEsSetParam}}
+ProtocolIE-ContainerPairList {INTEGER : lowerBound, INTEGER : upperBound, M3AP-PROTOCOL-IES-PAIR : IEsSetParam} ::=
+ SEQUENCE (SIZE (lowerBound..upperBound)) OF
+ ProtocolIE-ContainerPair {{IEsSetParam}}
+-- **************************************************************
+--
+-- Container for Protocol Extensions
+--
+-- **************************************************************
+ProtocolExtensionContainer {M3AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::=
+ SEQUENCE (SIZE (1..maxProtocolExtensions)) OF
+ ProtocolExtensionField {{ExtensionSetParam}}
+ProtocolExtensionField {M3AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= SEQUENCE {
+ id M3AP-PROTOCOL-EXTENSION.&id ({ExtensionSetParam}),
+ criticality M3AP-PROTOCOL-EXTENSION.&criticality ({ExtensionSetParam}{@id}),
+ extensionValue M3AP-PROTOCOL-EXTENSION.&Extension ({ExtensionSetParam}{@id})
+}
+-- **************************************************************
+--
+-- Container for Private IEs
+--
+-- **************************************************************
+PrivateIE-Container {M3AP-PRIVATE-IES : IEsSetParam} ::=
+ SEQUENCE (SIZE (1..maxPrivateIEs)) OF
+ PrivateIE-Field {{IEsSetParam}}
+PrivateIE-Field {M3AP-PRIVATE-IES : IEsSetParam} ::= SEQUENCE {
+ id M3AP-PRIVATE-IES.&id ({IEsSetParam}),
+ criticality M3AP-PRIVATE-IES.&criticality ({IEsSetParam}{@id}),
+ value M3AP-PRIVATE-IES.&Value ({IEsSetParam}{@id})
+}
+END 
+ 
diff --git a/openair3/M3AP/MESSAGES/ASN1/R14/m3ap-14.0.0.asn1.bak b/openair3/M3AP/MESSAGES/ASN1/R14/m3ap-14.0.0.asn1.bak
new file mode 100644
index 0000000000000000000000000000000000000000..fac7864ba3d4e4b699e26b522a5cb95f47d94096
--- /dev/null
+++ b/openair3/M3AP/MESSAGES/ASN1/R14/m3ap-14.0.0.asn1.bak
@@ -0,0 +1,1360 @@
+-- M3AP-PDU-Descriptions.asn
+--
+-- 3GPP TS 36.444 V13.2.0 (2016-03)
+-- http://www.3gpp.org/ftp/Specs/archive/36_series/36.444/36444-d20.zip
+--
+-- 9.3.3	Elementary Procedure Definitions
+--
+
+-- **************************************************************
+--
+-- Elementary Procedure definitions
+--
+-- **************************************************************
+
+M3AP-PDU-Descriptions {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-PDU-Descriptions (0) }
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+	Criticality,
+	ProcedureCode
+FROM M3AP-CommonDataTypes
+
+	MBMSSessionStartRequest,
+	MBMSSessionStartResponse,
+	MBMSSessionStartFailure,
+	MBMSSessionStopRequest,
+	MBMSSessionStopResponse,
+	MBMSSessionUpdateRequest,
+	MBMSSessionUpdateResponse,
+	MBMSSessionUpdateFailure,
+	MCEConfigurationUpdate,
+	MCEConfigurationUpdateAcknowledge,
+	MCEConfigurationUpdateFailure,
+	M3SetupRequest,
+	M3SetupResponse,
+	M3SetupFailure,
+	ErrorIndication,
+	Reset,
+	ResetAcknowledge,
+	PrivateMessage
+
+FROM M3AP-PDU-Contents
+
+	id-mBMSsessionStart,
+	id-mBMSsessionStop,
+	id-mBMSsessionUpdate,
+	id-mCEConfigurationUpdate,
+	id-m3Setup,
+	id-errorIndication,
+	id-Reset,
+	id-privateMessage
+FROM M3AP-Constants;
+
+
+-- **************************************************************
+--
+-- Interface Elementary Procedure Class
+--
+-- **************************************************************
+
+M3AP-ELEMENTARY-PROCEDURE ::= CLASS {
+	&InitiatingMessage				,
+	&SuccessfulOutcome				OPTIONAL,
+	&UnsuccessfulOutcome				OPTIONAL,
+	&procedureCode			ProcedureCode 	UNIQUE,
+	&criticality			Criticality 	DEFAULT ignore
+}
+WITH SYNTAX {
+	INITIATING MESSAGE		&InitiatingMessage
+	[SUCCESSFUL OUTCOME		&SuccessfulOutcome]
+	[UNSUCCESSFUL OUTCOME		&UnsuccessfulOutcome]
+	PROCEDURE CODE			&procedureCode
+	[CRITICALITY			&criticality]
+}
+
+-- **************************************************************
+--
+-- Interface PDU Definition
+--
+-- **************************************************************
+
+M3AP-PDU ::= CHOICE {
+	initiatingMessage	InitiatingMessage,
+	successfulOutcome	SuccessfulOutcome,
+	unsuccessfulOutcome	UnsuccessfulOutcome,
+	...
+}
+
+InitiatingMessage ::= SEQUENCE {
+	procedureCode	M3AP-ELEMENTARY-PROCEDURE.&procedureCode		({M3AP-ELEMENTARY-PROCEDURES}),
+	criticality		M3AP-ELEMENTARY-PROCEDURE.&criticality			({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+	value			M3AP-ELEMENTARY-PROCEDURE.&InitiatingMessage	({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+SuccessfulOutcome ::= SEQUENCE {
+	procedureCode	M3AP-ELEMENTARY-PROCEDURE.&procedureCode		({M3AP-ELEMENTARY-PROCEDURES}),
+	criticality		M3AP-ELEMENTARY-PROCEDURE.&criticality			({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+	value			M3AP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome	({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+UnsuccessfulOutcome ::= SEQUENCE {
+	procedureCode	M3AP-ELEMENTARY-PROCEDURE.&procedureCode		({M3AP-ELEMENTARY-PROCEDURES}),
+	criticality		M3AP-ELEMENTARY-PROCEDURE.&criticality			({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+	value			M3AP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome	({M3AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+
+-- **************************************************************
+--
+-- Interface Elementary Procedure List
+--
+-- **************************************************************
+
+M3AP-ELEMENTARY-PROCEDURES M3AP-ELEMENTARY-PROCEDURE ::= {
+	M3AP-ELEMENTARY-PROCEDURES-CLASS-1			|
+	M3AP-ELEMENTARY-PROCEDURES-CLASS-2			,
+	...
+}
+
+M3AP-ELEMENTARY-PROCEDURES-CLASS-1 M3AP-ELEMENTARY-PROCEDURE ::= {
+	mBMSsessionStart											|
+	mBMSsessionStop												|
+	mBMSsessionUpdate											|
+	reset														|
+	m3Setup														|
+	mCEConfigurationUpdate										,
+	...
+}
+
+M3AP-ELEMENTARY-PROCEDURES-CLASS-2 M3AP-ELEMENTARY-PROCEDURE ::= {
+	errorIndication							|
+	privateMessage							,
+	...
+
+}
+
+
+-- **************************************************************
+--
+-- Interface Elementary Procedures
+--
+-- **************************************************************
+
+mBMSsessionStart M3AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MBMSSessionStartRequest
+	SUCCESSFUL OUTCOME		MBMSSessionStartResponse
+	UNSUCCESSFUL OUTCOME	MBMSSessionStartFailure
+	PROCEDURE CODE			id-mBMSsessionStart
+	CRITICALITY				reject
+}
+
+mBMSsessionStop M3AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MBMSSessionStopRequest
+	SUCCESSFUL OUTCOME		MBMSSessionStopResponse
+	PROCEDURE CODE			id-mBMSsessionStop
+	CRITICALITY				reject
+}
+
+mBMSsessionUpdate M3AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MBMSSessionUpdateRequest
+	SUCCESSFUL OUTCOME		MBMSSessionUpdateResponse
+	UNSUCCESSFUL OUTCOME	MBMSSessionUpdateFailure
+	PROCEDURE CODE			id-mBMSsessionUpdate
+	CRITICALITY				reject
+}
+
+errorIndication M3AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		ErrorIndication
+	PROCEDURE CODE			id-errorIndication
+	CRITICALITY				ignore
+}
+
+reset M3AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE	Reset
+	SUCCESSFUL OUTCOME	ResetAcknowledge
+	PROCEDURE CODE		id-Reset
+	CRITICALITY			reject
+}
+
+privateMessage			M3AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		PrivateMessage
+	PROCEDURE CODE			id-privateMessage
+	CRITICALITY				ignore
+}
+
+mCEConfigurationUpdate M3AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		MCEConfigurationUpdate
+	SUCCESSFUL OUTCOME		MCEConfigurationUpdateAcknowledge
+	UNSUCCESSFUL OUTCOME	MCEConfigurationUpdateFailure
+	PROCEDURE CODE			id-mCEConfigurationUpdate
+	CRITICALITY				reject
+}
+
+
+m3Setup M3AP-ELEMENTARY-PROCEDURE ::= {
+	INITIATING MESSAGE		M3SetupRequest
+	SUCCESSFUL OUTCOME		M3SetupResponse
+	UNSUCCESSFUL OUTCOME	M3SetupFailure
+	PROCEDURE CODE			id-m3Setup
+	CRITICALITY				reject
+}
+
+END
+
+-- M3AP-PDU-Contents.asn
+--
+-- 3GPP TS 36.444 V13.2.0 (2016-03)
+-- http://www.3gpp.org/ftp/Specs/archive/36_series/36.444/36444-d20.zip
+--
+-- 9.3.4	PDU Definitions
+--
+
+-- **************************************************************
+--
+-- PDU definitions for M3AP.
+--
+-- **************************************************************
+
+M3AP-PDU-Contents {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-PDU-Contents (1) }
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+
+	Absolute-Time-ofMBMS-Data,
+	Cause,
+	CriticalityDiagnostics,
+	Global-MCE-ID,
+	MBMS-E-RAB-QoS-Parameters,
+	MBMS-Service-associatedLogicalM3-ConnectionItem,
+	MBMS-Service-Area,
+	MBMSServiceArea1,
+	MBMS-Session-Duration,
+	MBMS-Session-ID,
+	MCE-MBMS-M3AP-ID,
+	MCEname,
+	MinimumTimeToMBMSDataTransfer,
+	MME-MBMS-M3AP-ID,
+	TimeToWait,
+	TMGI,
+	TNL-Information,
+	Reestablishment,
+	MBMS-Cell-List
+
+FROM M3AP-IEs
+
+	PrivateIE-Container{},
+	ProtocolExtensionContainer{},
+	ProtocolIE-Container{},
+	ProtocolIE-ContainerList{},
+	ProtocolIE-ContainerPair{},
+	ProtocolIE-ContainerPairList{},
+	ProtocolIE-Single-Container{},
+	M3AP-PRIVATE-IES,
+	M3AP-PROTOCOL-EXTENSION,
+	M3AP-PROTOCOL-IES,
+	M3AP-PROTOCOL-IES-PAIR
+FROM M3AP-Containers
+
+	id-AllocationAndRetentionPriority,
+	id-MCE-MBMS-M3AP-ID,
+	id-MME-MBMS-M3AP-ID,
+	id-TMGI,
+	id-MBMS-Session-ID,
+	id-MBMS-E-RAB-QoS-Parameters,
+	id-MBMS-Session-Duration,
+	id-MBMS-Service-Area,
+	id-TNL-Information,
+	id-Alternative-TNL-Information,
+	id-CriticalityDiagnostics,
+	id-Cause,
+	id-MBMS-Service-Area-List,
+	id-MBMS-Service-Area-List-Item,
+	id-TimeToWait,
+	id-ResetType,
+	id-MBMS-Service-associatedLogicalM3-ConnectionItem,
+	id-MBMS-Service-associatedLogicalM3-ConnectionListResAck,
+	id-MBMSServiceAreaList,
+	id-MinimumTimeToMBMSDataTransfer,
+	id-Time-ofMBMS-DataStop,
+	id-Time-ofMBMS-DataTransfer,
+	id-Global-MCE-ID,
+	id-MCEname,
+	id-Reestablishment,
+	id-MBMS-Cell-List,
+	maxnoofMBMSServiceAreaIdentitiesPerMCE,
+	maxnooferrors,
+	maxNrOfIndividualM3ConnectionsToReset
+
+FROM M3AP-Constants;
+
+-- **************************************************************
+--
+-- MBMS SESSION START REQUEST
+--
+-- **************************************************************
+
+MBMSSessionStartRequest ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{MBMSSessionStartRequest-IEs}},
+	...
+}
+
+MBMSSessionStartRequest-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID					CRITICALITY reject	TYPE MME-MBMS-M3AP-ID						PRESENCE mandatory}|
+	{ ID id-TMGI								CRITICALITY reject	TYPE TMGI		 							PRESENCE mandatory}|
+	{ ID id-MBMS-Session-ID						CRITICALITY ignore	TYPE MBMS-Session-ID						PRESENCE optional}|
+	{ ID id-MBMS-E-RAB-QoS-Parameters			CRITICALITY reject	TYPE MBMS-E-RAB-QoS-Parameters			PRESENCE mandatory}|
+	{ ID id-MBMS-Session-Duration				CRITICALITY reject	TYPE MBMS-Session-Duration					PRESENCE mandatory}|
+	{ ID id-MBMS-Service-Area					CRITICALITY reject	TYPE MBMS-Service-Area						PRESENCE mandatory}|
+	{ ID id-MinimumTimeToMBMSDataTransfer		CRITICALITY reject	TYPE MinimumTimeToMBMSDataTransfer		PRESENCE mandatory}|
+	{ ID id-TNL-Information						CRITICALITY reject	TYPE TNL-Information						PRESENCE mandatory}|
+	{ ID id-Time-ofMBMS-DataTransfer			CRITICALITY ignore	TYPE Absolute-Time-ofMBMS-Data			PRESENCE optional}|
+	{ ID id-Reestablishment						CRITICALITY ignore	TYPE Reestablishment						PRESENCE optional}|
+	{ ID id-Alternative-TNL-Information			CRITICALITY ignore	TYPE TNL-Information						PRESENCE optional}|
+	{ ID id-MBMS-Cell-List						CRITICALITY reject	TYPE MBMS-Cell-List							PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- MBMS SESSION START RESPONSE
+--
+-- **************************************************************
+
+MBMSSessionStartResponse ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MBMSSessionStartResponse-IEs}},
+	...
+}
+
+MBMSSessionStartResponse-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MME-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-MCE-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  },
+	...
+}
+
+
+-- **************************************************************
+--
+-- MBMS SESSION START FAILURE
+--
+-- **************************************************************
+
+MBMSSessionStartFailure ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MBMSSessionStartFailure-IEs}},
+	...
+}
+
+MBMSSessionStartFailure-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MME-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-Cause								CRITICALITY ignore	TYPE Cause								PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  },
+	...
+}
+
+
+-- **************************************************************
+--
+-- MBMS SESSION STOP REQUEST
+--
+-- **************************************************************
+
+MBMSSessionStopRequest ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{MBMSSessionStopRequest-IEs}},
+	...
+}
+
+MBMSSessionStopRequest-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID				CRITICALITY reject	TYPE MME-MBMS-M3AP-ID					PRESENCE mandatory}|
+	{ ID id-MCE-MBMS-M3AP-ID				CRITICALITY reject	TYPE MCE-MBMS-M3AP-ID					PRESENCE mandatory}|
+	{ ID id-Time-ofMBMS-DataStop			CRITICALITY ignore	TYPE Absolute-Time-ofMBMS-Data			PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- MBMS SESSION STOP RESPONSE
+--
+-- **************************************************************
+
+MBMSSessionStopResponse ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MBMSSessionStopResponse-IEs}},
+	...
+}
+
+MBMSSessionStopResponse-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MME-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-MCE-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  } ,
+	...
+}
+
+-- **************************************************************
+--
+-- MBMS SESSION UPDATE REQUEST
+--
+-- **************************************************************
+
+MBMSSessionUpdateRequest ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{MBMSSessionUpdateRequest-IEs}},
+	...
+}
+
+MBMSSessionUpdateRequest-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID					CRITICALITY reject	TYPE MME-MBMS-M3AP-ID					PRESENCE mandatory}|
+	{ ID id-MCE-MBMS-M3AP-ID					CRITICALITY reject	TYPE MCE-MBMS-M3AP-ID					PRESENCE mandatory}|
+	{ ID id-TMGI								CRITICALITY reject	TYPE TMGI		 						PRESENCE mandatory}|
+	{ ID id-MBMS-Session-ID						CRITICALITY ignore	TYPE MBMS-Session-ID					PRESENCE optional}|
+	{ ID id-MBMS-E-RAB-QoS-Parameters			CRITICALITY reject	TYPE MBMS-E-RAB-QoS-Parameters		PRESENCE mandatory}|
+	{ ID id-MBMS-Session-Duration				CRITICALITY reject	TYPE MBMS-Session-Duration				PRESENCE mandatory}|
+	{ ID id-MBMS-Service-Area					CRITICALITY ignore	TYPE MBMS-Service-Area					PRESENCE optional}|
+	{ ID id-MinimumTimeToMBMSDataTransfer		CRITICALITY reject	TYPE MinimumTimeToMBMSDataTransfer	PRESENCE mandatory}|
+	{ ID id-TNL-Information						CRITICALITY ignore	TYPE TNL-Information					PRESENCE optional}|
+	{ ID id-Time-ofMBMS-DataTransfer			CRITICALITY ignore	TYPE Absolute-Time-ofMBMS-Data		PRESENCE optional}|
+	{ ID id-MBMS-Cell-List						CRITICALITY reject	TYPE MBMS-Cell-List						PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- MBMS SESSION UPDATE RESPONSE
+--
+-- **************************************************************
+
+MBMSSessionUpdateResponse ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MBMSSessionUpdateResponse-IEs}},
+	...
+}
+
+MBMSSessionUpdateResponse-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MME-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-MCE-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  },
+	...
+}
+
+-- **************************************************************
+--
+-- MBMS SESSION UPDATE FAILURE
+--
+-- **************************************************************
+
+MBMSSessionUpdateFailure ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ MBMSSessionUpdateFailure-IEs}},
+	...
+}
+
+MBMSSessionUpdateFailure-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MME-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-MCE-MBMS-M3AP-ID					CRITICALITY ignore	TYPE MCE-MBMS-M3AP-ID					PRESENCE mandatory } |
+	{ ID id-Cause								CRITICALITY ignore	TYPE Cause								PRESENCE mandatory } |
+	{ ID id-CriticalityDiagnostics				CRITICALITY ignore	TYPE CriticalityDiagnostics				PRESENCE optional  },
+	...
+}
+
+-- **************************************************************
+--
+-- ERROR INDICATION
+--
+-- **************************************************************
+
+ErrorIndication ::= SEQUENCE {
+	protocolIEs                     ProtocolIE-Container       {{ErrorIndication-IEs}},
+	...
+}
+
+ErrorIndication-IEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MME-MBMS-M3AP-ID				CRITICALITY ignore	TYPE MME-MBMS-M3AP-ID				PRESENCE optional	} |
+	{ ID id-MCE-MBMS-M3AP-ID				CRITICALITY ignore	TYPE MCE-MBMS-M3AP-ID				PRESENCE optional	} |
+	{ ID id-Cause							CRITICALITY ignore	TYPE Cause						PRESENCE optional	} |
+	{ ID id-CriticalityDiagnostics			CRITICALITY ignore	TYPE CriticalityDiagnostics		PRESENCE optional	} ,
+	...
+}
+
+
+-- **************************************************************
+--
+-- Reset
+--
+-- **************************************************************
+
+Reset ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container       { {ResetIEs} },
+	...
+}
+
+ResetIEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-Cause						CRITICALITY ignore	TYPE Cause						PRESENCE mandatory	}|
+	{ ID id-ResetType				CRITICALITY reject	TYPE ResetType			PRESENCE mandatory	},
+	...
+}
+
+ResetType ::= CHOICE {
+	m3-Interface		ResetAll,
+	partOfM3-Interface		MBMS-Service-associatedLogicalM3-ConnectionListRes,
+	...
+}
+
+
+
+ResetAll ::= ENUMERATED {
+	reset-all,
+	...
+}
+
+MBMS-Service-associatedLogicalM3-ConnectionListRes ::= SEQUENCE (SIZE(1.. maxNrOfIndividualM3ConnectionsToReset)) OF ProtocolIE-Single-Container { { MBMS-Service-associatedLogicalM3-ConnectionItemRes } }
+
+MBMS-Service-associatedLogicalM3-ConnectionItemRes 	M3AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Service-associatedLogicalM3-ConnectionItem	 CRITICALITY reject 	TYPE MBMS-Service-associatedLogicalM3-ConnectionItem 	PRESENCE mandatory },
+	...
+}
+
+
+-- **************************************************************
+--
+-- Reset Acknowledge
+--
+-- **************************************************************
+
+ResetAcknowledge ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container       { {ResetAcknowledgeIEs} },
+	...
+}
+
+ResetAcknowledgeIEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Service-associatedLogicalM3-ConnectionListResAck		CRITICALITY ignore	TYPE MBMS-Service-associatedLogicalM3-ConnectionListResAck			PRESENCE optional	}|
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional	},
+	...
+}
+
+MBMS-Service-associatedLogicalM3-ConnectionListResAck ::= SEQUENCE (SIZE(1.. maxNrOfIndividualM3ConnectionsToReset)) OF ProtocolIE-Single-Container { { MBMS-Service-associatedLogicalM3-ConnectionItemResAck } }
+
+MBMS-Service-associatedLogicalM3-ConnectionItemResAck	M3AP-PROTOCOL-IES ::= {
+	{ ID id-MBMS-Service-associatedLogicalM3-ConnectionItem	CRITICALITY ignore	TYPE MBMS-Service-associatedLogicalM3-ConnectionItem	PRESENCE mandatory },
+	...
+}
+
+-- **************************************************************
+--
+-- PRIVATE MESSAGE
+--
+-- **************************************************************
+
+PrivateMessage ::= SEQUENCE {
+	privateIEs		PrivateIE-Container  {{PrivateMessage-IEs}},
+	...
+}
+
+PrivateMessage-IEs M3AP-PRIVATE-IES ::= {
+	...
+}
+
+
+-- **************************************************************
+--
+-- M3 SETUP ELEMENTARY PROCEDURE
+--
+-- **************************************************************
+
+-- **************************************************************
+--
+-- M3 Setup Request
+--
+-- **************************************************************
+
+M3SetupRequest ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container       { {M3SetupRequestIEs} },
+	...
+}
+
+M3SetupRequestIEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-Global-MCE-ID			CRITICALITY reject	TYPE Global-MCE-ID					PRESENCE mandatory}|
+	{ ID id-MCEname					CRITICALITY ignore	TYPE MCEname						PRESENCE optional}|
+	{ ID id-MBMSServiceAreaList		CRITICALITY reject	TYPE MBMSServiceAreaListItem		PRESENCE mandatory},
+	...
+}
+
+
+MBMSServiceAreaListItem ::= SEQUENCE (SIZE(1..maxnoofMBMSServiceAreaIdentitiesPerMCE)) OF MBMSServiceArea1
+
+
+-- **************************************************************
+--
+-- M3 Setup Response
+--
+-- **************************************************************
+
+M3SetupResponse ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container       { {M3SetupResponseIEs} },
+	...
+}
+
+
+M3SetupResponseIEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- M3 Setup Failure
+--
+-- **************************************************************
+
+M3SetupFailure ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container       { {M3SetupFailureIEs} },
+	...
+}
+
+M3SetupFailureIEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-Cause						CRITICALITY ignore	TYPE Cause						PRESENCE mandatory}|
+	{ ID id-TimeToWait					CRITICALITY ignore	TYPE TimeToWait					PRESENCE optional}|
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics		PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- MCE CONFIGURATION UPDATE ELEMENTARY PROCEDURE
+--
+-- **************************************************************
+
+-- **************************************************************
+--
+-- MCE Configuration Update
+--
+-- **************************************************************
+
+MCEConfigurationUpdate ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container       { {MCEConfigurationUpdateIEs} },
+	...
+}
+
+MCEConfigurationUpdateIEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-Global-MCE-ID			CRITICALITY reject	TYPE Global-MCE-ID					PRESENCE optional}|
+	{ ID id-MCEname					CRITICALITY ignore	TYPE MCEname						PRESENCE optional}|
+	{ ID id-MBMSServiceAreaList		CRITICALITY reject	TYPE MBMSServiceAreaListItem		PRESENCE optional},
+	...
+}
+
+-- **************************************************************
+--
+-- MCE Configuration Update Acknowledge
+--
+-- **************************************************************
+
+MCEConfigurationUpdateAcknowledge ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container       { {MCEConfigurationUpdateAcknowledgeIEs} },
+	...
+}
+
+
+MCEConfigurationUpdateAcknowledgeIEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics			PRESENCE optional	},
+	...
+}
+
+-- **************************************************************
+--
+-- MCE Configuration Update Failure
+--
+-- **************************************************************
+
+MCEConfigurationUpdateFailure ::= SEQUENCE {
+	protocolIEs			ProtocolIE-Container       { {MCEConfigurationUpdateFailureIEs} },
+	...
+}
+
+MCEConfigurationUpdateFailureIEs M3AP-PROTOCOL-IES ::= {
+	{ ID id-Cause						CRITICALITY ignore	TYPE Cause						PRESENCE mandatory}|
+	{ ID id-TimeToWait					CRITICALITY ignore	TYPE TimeToWait					PRESENCE optional}|
+	{ ID id-CriticalityDiagnostics		CRITICALITY ignore	TYPE CriticalityDiagnostics		PRESENCE optional},
+	...
+}
+
+END
+
+-- M3AP-IEs.asn
+--
+-- 3GPP TS 36.444 V13.2.0 (2016-03)
+-- http://www.3gpp.org/ftp/Specs/archive/36_series/36.444/36444-d20.zip
+--
+-- 9.3.5	Information Element Definitions
+--
+
+-- **************************************************************
+--
+-- Information Element Definitions
+--
+-- **************************************************************
+
+M3AP-IEs {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-IEs (2) }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+IMPORTS
+	id-AllocationAndRetentionPriority,
+	maxnooferrors,
+	maxnoofCellsforMBMS
+
+FROM M3AP-Constants
+
+	Criticality,
+	ProcedureCode,
+	ProtocolIE-ID,
+	TriggeringMessage
+FROM M3AP-CommonDataTypes
+
+	ProtocolExtensionContainer{},
+	ProtocolIE-Single-Container{},
+	M3AP-PROTOCOL-EXTENSION,
+	M3AP-PROTOCOL-IES
+FROM M3AP-Containers;
+
+-- A
+
+Absolute-Time-ofMBMS-Data			::= BIT STRING (SIZE (64))
+
+AllocationAndRetentionPriority ::= SEQUENCE {
+	priorityLevel				PriorityLevel,
+	pre-emptionCapability		Pre-emptionCapability,
+	pre-emptionVulnerability	Pre-emptionVulnerability,
+	iE-Extensions				ProtocolExtensionContainer { {AllocationAndRetentionPriority-ExtIEs} } OPTIONAL
+}
+
+AllocationAndRetentionPriority-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+-- B
+
+BitRate	::= INTEGER (0..10000000000)
+
+-- C
+
+Cause ::= CHOICE {
+	radioNetwork		CauseRadioNetwork,
+	transport			CauseTransport,
+	nAS					CauseNAS,
+	protocol			CauseProtocol,
+	misc				CauseMisc,
+	...
+}
+
+CauseMisc ::= ENUMERATED {
+	control-processing-overload,
+	not-enough-user-plane-processing-resources,
+	hardware-failure,
+	om-intervention,
+	unspecified,
+	...
+}
+
+CauseNAS ::= ENUMERATED {
+	unspecified,
+	...
+}
+
+CauseProtocol ::= ENUMERATED {
+	transfer-syntax-error,
+	abstract-syntax-error-reject,
+	abstract-syntax-error-ignore-and-notify,
+	message-not-compatible-with-receiver-state,
+	semantic-error,
+	abstract-syntax-error-falsely-constructed-message,
+	unspecified,
+	...
+}
+
+CauseRadioNetwork ::= ENUMERATED {
+	unknown-or-already-allocated-MME-MBMS-M3AP-ID,
+	unknown-or-already-allocated-MCE-MBMS-M3AP-ID,
+	unknown-or-inconsistent-pair-of-MBMS-M3AP-IDs,
+	radio-resources-not-available,
+	invalid-QoS-combination,
+	interaction-with-other-procedure,
+	not-supported-QCI-value,
+	unspecified,
+	...,
+	uninvolved-MCE
+
+}
+
+CauseTransport ::= ENUMERATED {
+	transport-resource-unavailable,
+	unspecified,
+	...
+}
+
+CriticalityDiagnostics ::= SEQUENCE {
+	procedureCode					ProcedureCode					OPTIONAL,
+	triggeringMessage				TriggeringMessage				OPTIONAL,
+	procedureCriticality			Criticality						OPTIONAL,
+	iEsCriticalityDiagnostics		CriticalityDiagnostics-IE-List	OPTIONAL,
+	iE-Extensions					ProtocolExtensionContainer { {CriticalityDiagnostics-ExtIEs} }	OPTIONAL,
+	...
+}
+
+
+CriticalityDiagnostics-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+CriticalityDiagnostics-IE-List ::= SEQUENCE (SIZE (1..maxnooferrors)) OF
+	SEQUENCE {
+		iECriticality			Criticality,
+		iE-ID					ProtocolIE-ID,
+		typeOfError				TypeOfError,
+		iE-Extensions			ProtocolExtensionContainer { {CriticalityDiagnostics-IE-List-ExtIEs} } OPTIONAL,
+		...
+}
+
+CriticalityDiagnostics-IE-List-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+
+-- D
+-- E
+
+ECGI ::= SEQUENCE {
+	pLMN-Identity				PLMN-Identity,
+	eUTRANcellIdentifier		EUTRANCellIdentifier,
+	iE-Extensions				ProtocolExtensionContainer { {ECGI-ExtIEs} } OPTIONAL,
+	...
+}
+
+ECGI-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+EUTRANCellIdentifier ::= BIT STRING (SIZE (28))
+
+ExtendedMCE-ID ::= OCTET STRING (SIZE(1))
+
+-- F
+-- G
+
+Global-MCE-ID ::= SEQUENCE {
+	pLMN-Identity			PLMN-Identity,
+	mCE-ID					MCE-ID,
+	extendedMCE-ID			ExtendedMCE-ID	OPTIONAL,
+	iE-Extensions			ProtocolExtensionContainer { {GlobalMCE-ID-ExtIEs} } OPTIONAL,
+	...
+}
+
+GlobalMCE-ID-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+GBR-QosInformation ::= SEQUENCE {
+	mBMS-E-RAB-MaximumBitrateDL			BitRate,
+	mBMS-E-RAB-GuaranteedBitrateDL		BitRate,
+	iE-Extensions					ProtocolExtensionContainer { { GBR-QosInformation-ExtIEs} } OPTIONAL,
+	...
+}
+
+GBR-QosInformation-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+GTP-TEID					::= OCTET STRING (SIZE (4))
+
+-- H
+-- I
+
+IPAddress			::= OCTET STRING (SIZE(4..16, ...))
+
+-- J
+-- K
+-- L
+-- M
+
+MBMS-Cell-List ::= SEQUENCE (SIZE(1.. maxnoofCellsforMBMS)) OF ECGI
+
+MBMS-E-RAB-QoS-Parameters ::= SEQUENCE {
+	qCI								QCI,
+	gbrQosInformation				GBR-QosInformation													OPTIONAL,
+	iE-Extensions					ProtocolExtensionContainer { { MBMS-E-RAB-QoS-Parameters-ExtIEs} }	OPTIONAL,
+	...
+}
+
+MBMS-E-RAB-QoS-Parameters-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+-- Extension for Release 10 ARP support --
+	{ID id-AllocationAndRetentionPriority	CRITICALITY ignore	EXTENSION AllocationAndRetentionPriority	PRESENCE mandatory},
+	...
+}
+
+MBMS-Service-associatedLogicalM3-ConnectionItem ::= SEQUENCE {
+	mME-MBMS-M3AP-ID				MME-MBMS-M3AP-ID OPTIONAL,
+	mCE-MBMS-M3AP-ID				MCE-MBMS-M3AP-ID OPTIONAL,
+	iE-Extensions					ProtocolExtensionContainer { { MBMS-Service-associatedLogicalM3-ConnectionItemExtIEs} } OPTIONAL,
+	...
+}
+
+
+MBMS-Service-associatedLogicalM3-ConnectionItemExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+MBMSServiceArea1 ::= OCTET STRING (SIZE (2))
+
+MBMS-Service-Area			::= OCTET STRING
+
+
+MBMS-Session-Duration ::= OCTET STRING (SIZE (3))
+
+MBMS-Session-ID ::= OCTET STRING (SIZE (1))
+
+
+MCE-MBMS-M3AP-ID			::= INTEGER (0..65535)
+
+MCE-ID ::= OCTET STRING (SIZE(2))
+
+MCEname ::= PrintableString (SIZE (1..150,...))
+
+MinimumTimeToMBMSDataTransfer	::= OCTET STRING (SIZE (1))
+
+MME-MBMS-M3AP-ID		::= INTEGER (0..65535)
+
+-- N
+-- O
+-- P
+
+Pre-emptionCapability ::= ENUMERATED {
+	shall-not-trigger-pre-emption,
+	may-trigger-pre-emption
+}
+
+Pre-emptionVulnerability ::= ENUMERATED {
+	not-pre-emptable,
+	pre-emptable
+}
+
+PriorityLevel	::= INTEGER { spare (0), highest (1), lowest (14), no-priority (15) } (0..15)
+
+PLMN-Identity ::= OCTET STRING (SIZE(3))
+
+-- Q
+
+QCI ::= INTEGER (0..255)
+
+-- R
+
+Reestablishment ::= ENUMERATED {true, ...}
+
+-- S
+-- T
+
+TimeToWait ::= ENUMERATED {v1s, v2s, v5s, v10s, v20s, v60s, ...}
+
+TMGI ::= SEQUENCE {
+	pLMNidentity			PLMN-Identity,
+	serviceID				OCTET STRING (SIZE (3)),
+	iE-Extensions			ProtocolExtensionContainer { {TMGI-ExtIEs} } OPTIONAL
+}
+
+TMGI-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+
+TNL-Information ::= SEQUENCE {
+	iPMCAddress						IPAddress,
+	iPSourceAddress					IPAddress,
+	gTP-DLTEID						GTP-TEID,
+	iE-Extensions					ProtocolExtensionContainer { {TNL-Information-ExtIEs} } OPTIONAL,
+	...
+}
+
+TNL-Information-ExtIEs M3AP-PROTOCOL-EXTENSION ::= {
+	...
+}
+
+TypeOfError ::= ENUMERATED {
+	not-understood,
+	missing,
+	...
+}
+
+
+-- U
+-- V
+-- W
+-- X
+-- Y
+-- Z
+
+END
+
+-- M3AP-CommonDataTypes.asn
+--
+-- 3GPP TS 36.444 V13.2.0 (2016-03)
+-- http://www.3gpp.org/ftp/Specs/archive/36_series/36.444/36444-d20.zip
+--
+-- 9.3.6	Common Definitions
+--
+
+-- **************************************************************
+--
+-- Common definitions
+--
+-- **************************************************************
+
+M3AP-CommonDataTypes {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-CommonDataTypes (3)  }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- Extension constants
+--
+-- **************************************************************
+
+maxPrivateIEs 									INTEGER ::= 65535
+maxProtocolExtensions 							INTEGER ::= 65535
+maxProtocolIEs									INTEGER ::= 65535
+
+-- **************************************************************
+--
+-- Common Data Types
+--
+-- **************************************************************
+
+Criticality		::= ENUMERATED { reject, ignore, notify }
+
+Presence		::= ENUMERATED { optional, conditional, mandatory }
+
+PrivateIE-ID	::= CHOICE {
+	local				INTEGER (0.. maxPrivateIEs),
+	global				OBJECT IDENTIFIER
+}
+
+ProcedureCode		::= INTEGER (0..255)
+
+
+ProtocolIE-ID		::= INTEGER (0..maxProtocolIEs)
+
+
+TriggeringMessage	::= ENUMERATED { initiating-message, successful-outcome, unsuccessful-outcome}
+
+END
+
+-- M3AP-Containers.asn
+--
+-- 3GPP TS 36.444 V13.2.0 (2016-03)
+-- http://www.3gpp.org/ftp/Specs/archive/36_series/36.444/36444-d20.zip
+--
+-- 9.3.8	Container Definitions
+--
+
+-- **************************************************************
+--
+-- Container definitions
+--
+-- **************************************************************
+
+M3AP-Containers {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-Containers (5)  }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+	maxPrivateIEs,
+	maxProtocolExtensions,
+	maxProtocolIEs,
+	Criticality,
+	Presence,
+	PrivateIE-ID,
+	ProtocolIE-ID
+FROM M3AP-CommonDataTypes;
+
+-- **************************************************************
+--
+-- Class Definition for Protocol IEs
+--
+-- **************************************************************
+
+M3AP-PROTOCOL-IES ::= CLASS {
+	&id				ProtocolIE-ID 			UNIQUE,
+	&criticality	Criticality,
+	&Value,
+	&presence		Presence
+}
+WITH SYNTAX {
+	ID				&id
+	CRITICALITY		&criticality
+	TYPE			&Value
+	PRESENCE		&presence
+}
+
+-- **************************************************************
+--
+-- Class Definition for Protocol IEs
+--
+-- **************************************************************
+
+M3AP-PROTOCOL-IES-PAIR ::= CLASS {
+	&id						ProtocolIE-ID 		UNIQUE,
+	&firstCriticality		Criticality,
+	&FirstValue,
+	&secondCriticality		Criticality,
+	&SecondValue,
+	&presence				Presence
+}
+WITH SYNTAX {
+	ID						&id
+	FIRST CRITICALITY 		&firstCriticality
+	FIRST TYPE				&FirstValue
+	SECOND CRITICALITY 		&secondCriticality
+	SECOND TYPE				&SecondValue
+	PRESENCE				&presence
+}
+
+-- **************************************************************
+--
+-- Class Definition for Protocol Extensions
+--
+-- **************************************************************
+
+M3AP-PROTOCOL-EXTENSION ::= CLASS {
+	&id					ProtocolIE-ID 		UNIQUE,
+	&criticality		Criticality,
+	&Extension,
+	&presence			Presence
+}
+WITH SYNTAX {
+	ID					&id
+	CRITICALITY			&criticality
+	EXTENSION			&Extension
+	PRESENCE			&presence
+}
+
+-- **************************************************************
+--
+-- Class Definition for Private IEs
+--
+-- **************************************************************
+
+M3AP-PRIVATE-IES ::= CLASS {
+	&id					PrivateIE-ID,
+	&criticality		Criticality,
+	&Value,
+	&presence			Presence
+}
+WITH SYNTAX {
+	ID					&id
+	CRITICALITY			&criticality
+	TYPE				&Value
+	PRESENCE			&presence
+}
+
+-- **************************************************************
+--
+-- Container for Protocol IEs
+--
+-- **************************************************************
+
+ProtocolIE-Container {M3AP-PROTOCOL-IES : IEsSetParam} ::=
+	SEQUENCE (SIZE (0..maxProtocolIEs)) OF
+	ProtocolIE-Field {{IEsSetParam}}
+
+ProtocolIE-Single-Container {M3AP-PROTOCOL-IES : IEsSetParam} ::=
+	ProtocolIE-Field {{IEsSetParam}}
+
+ProtocolIE-Field {M3AP-PROTOCOL-IES : IEsSetParam} ::= SEQUENCE {
+	id				M3AP-PROTOCOL-IES.&id					({IEsSetParam}),
+	criticality		M3AP-PROTOCOL-IES.&criticality			({IEsSetParam}{@id}),
+	value			M3AP-PROTOCOL-IES.&Value	        	({IEsSetParam}{@id})
+}
+
+-- **************************************************************
+--
+-- Container for Protocol IE Pairs
+--
+-- **************************************************************
+
+ProtocolIE-ContainerPair {M3AP-PROTOCOL-IES-PAIR : IEsSetParam} ::=
+	SEQUENCE (SIZE (0..maxProtocolIEs)) OF
+	ProtocolIE-FieldPair {{IEsSetParam}}
+
+ProtocolIE-FieldPair {M3AP-PROTOCOL-IES-PAIR : IEsSetParam} ::= SEQUENCE {
+	id					M3AP-PROTOCOL-IES-PAIR.&id					({IEsSetParam}),
+	firstCriticality	M3AP-PROTOCOL-IES-PAIR.&firstCriticality	({IEsSetParam}{@id}),
+	firstValue			M3AP-PROTOCOL-IES-PAIR.&FirstValue	        ({IEsSetParam}{@id}),
+	secondCriticality	M3AP-PROTOCOL-IES-PAIR.&secondCriticality	({IEsSetParam}{@id}),
+	secondValue			M3AP-PROTOCOL-IES-PAIR.&SecondValue	        ({IEsSetParam}{@id})
+}
+
+-- **************************************************************
+--
+-- Container Lists for Protocol IE Containers
+--
+-- **************************************************************
+
+ProtocolIE-ContainerList {INTEGER : lowerBound, INTEGER : upperBound, M3AP-PROTOCOL-IES : IEsSetParam} ::=
+	SEQUENCE (SIZE (lowerBound..upperBound)) OF
+	ProtocolIE-Container {{IEsSetParam}}
+
+ProtocolIE-ContainerPairList {INTEGER : lowerBound, INTEGER : upperBound, M3AP-PROTOCOL-IES-PAIR : IEsSetParam} ::=
+	SEQUENCE (SIZE (lowerBound..upperBound)) OF
+	ProtocolIE-ContainerPair {{IEsSetParam}}
+
+-- **************************************************************
+--
+-- Container for Protocol Extensions
+--
+-- **************************************************************
+
+ProtocolExtensionContainer {M3AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::=
+	SEQUENCE (SIZE (1..maxProtocolExtensions)) OF
+	ProtocolExtensionField {{ExtensionSetParam}}
+
+ProtocolExtensionField {M3AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= SEQUENCE {
+	id					M3AP-PROTOCOL-EXTENSION.&id				({ExtensionSetParam}),
+	criticality			M3AP-PROTOCOL-EXTENSION.&criticality	({ExtensionSetParam}{@id}),
+	extensionValue		M3AP-PROTOCOL-EXTENSION.&Extension		({ExtensionSetParam}{@id})
+}
+
+-- **************************************************************
+--
+-- Container for Private IEs
+--
+-- **************************************************************
+
+PrivateIE-Container {M3AP-PRIVATE-IES : IEsSetParam} ::=
+	SEQUENCE (SIZE (1..maxPrivateIEs)) OF
+	PrivateIE-Field {{IEsSetParam}}
+
+PrivateIE-Field {M3AP-PRIVATE-IES : IEsSetParam} ::= SEQUENCE {
+	id				M3AP-PRIVATE-IES.&id			({IEsSetParam}),
+	criticality		M3AP-PRIVATE-IES.&criticality	({IEsSetParam}{@id}),
+	value			M3AP-PRIVATE-IES.&Value			({IEsSetParam}{@id})
+}
+
+END
+
+-- M3AP-Constants.asn
+--
+-- 3GPP TS 36.444 V13.2.0 (2016-03)
+-- http://www.3gpp.org/ftp/Specs/archive/36_series/36.444/36444-d20.zip
+--
+-- 9.3.7	Constant Definitions
+--
+
+-- **************************************************************
+--
+-- Constant definitions
+--
+-- **************************************************************
+
+M3AP-Constants {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) m3ap (5) version1 (1) m3ap-Constants (4) }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+IMPORTS
+	ProcedureCode,
+	ProtocolIE-ID
+FROM M3AP-CommonDataTypes;
+
+-- **************************************************************
+--
+-- Elementary Procedures
+--
+-- **************************************************************
+
+id-mBMSsessionStart												ProcedureCode ::= 0
+id-mBMSsessionStop												ProcedureCode ::= 1
+id-errorIndication												ProcedureCode ::= 2
+id-privateMessage												ProcedureCode ::= 3
+id-Reset														ProcedureCode ::= 4
+id-mBMSsessionUpdate											ProcedureCode ::= 5
+id-mCEConfigurationUpdate										ProcedureCode ::= 6
+id-m3Setup														ProcedureCode ::= 7
+
+
+
+-- **************************************************************
+--
+-- Lists
+--
+-- **************************************************************
+
+maxnoofMBMSServiceAreaIdentitiesPerMCE		INTEGER ::= 65536
+maxnooferrors								INTEGER ::= 256
+maxNrOfIndividualM3ConnectionsToReset		INTEGER ::= 256
+maxnoofCellsforMBMS							INTEGER ::= 4096
+
+-- **************************************************************
+--
+-- IEs
+--
+-- **************************************************************
+
+id-MME-MBMS-M3AP-ID															ProtocolIE-ID ::= 0
+id-MCE-MBMS-M3AP-ID															ProtocolIE-ID ::= 1
+id-TMGI																		ProtocolIE-ID ::= 2
+id-MBMS-Session-ID															ProtocolIE-ID ::= 3
+id-MBMS-E-RAB-QoS-Parameters												ProtocolIE-ID ::= 4
+id-MBMS-Session-Duration													ProtocolIE-ID ::= 5
+id-MBMS-Service-Area														ProtocolIE-ID ::= 6
+id-TNL-Information															ProtocolIE-ID ::= 7
+id-CriticalityDiagnostics													ProtocolIE-ID ::= 8
+id-Cause																	ProtocolIE-ID ::= 9
+id-MBMS-Service-Area-List													ProtocolIE-ID ::= 10
+id-MBMS-Service-Area-List-Item												ProtocolIE-ID ::= 11
+id-TimeToWait																ProtocolIE-ID ::= 12
+id-ResetType																ProtocolIE-ID ::= 13
+id-MBMS-Service-associatedLogicalM3-ConnectionItem							ProtocolIE-ID ::= 14
+id-MBMS-Service-associatedLogicalM3-ConnectionListResAck					ProtocolIE-ID ::= 15
+id-MinimumTimeToMBMSDataTransfer											ProtocolIE-ID ::= 16
+id-AllocationAndRetentionPriority											ProtocolIE-ID ::= 17
+id-Global-MCE-ID															ProtocolIE-ID ::= 18
+id-MCEname																	ProtocolIE-ID ::= 19
+id-MBMSServiceAreaList														ProtocolIE-ID ::= 20
+id-Time-ofMBMS-DataTransfer													ProtocolIE-ID ::= 21
+id-Time-ofMBMS-DataStop														ProtocolIE-ID ::= 22
+id-Reestablishment															ProtocolIE-ID ::= 23
+id-Alternative-TNL-Information												ProtocolIE-ID ::= 24
+id-MBMS-Cell-List															ProtocolIE-ID ::= 25
+END
diff --git a/openair3/M3AP/MESSAGES/ASN1/asn1tostruct.py b/openair3/M3AP/MESSAGES/ASN1/asn1tostruct.py
new file mode 100644
index 0000000000000000000000000000000000000000..b5a141349ba0fe694aa97d3bbcc74595c2b1ce29
--- /dev/null
+++ b/openair3/M3AP/MESSAGES/ASN1/asn1tostruct.py
@@ -0,0 +1,732 @@
+import re, os, sys, string
+import datetime
+import getopt
+import getpass
+
+version = "1.0.2"
+
+lines = ""
+iesDefs = {}
+ieofielist = {}
+outdir = './'
+
+filenames = []
+verbosity = 0
+prefix = ""
+
+FAIL = '\033[91m'
+WARN = '\033[93m'
+ENDC = '\033[0m'
+
+fileprefix = ""
+fileprefix_first_upper = ""
+
+def printFail(string):
+    sys.stderr.write(FAIL + string + ENDC + "\n")
+
+def printWarning(string):
+    print WARN + string + ENDC
+
+def printDebug(string):
+    if verbosity > 0:
+        print string
+
+def outputHeaderToFile(f, filename):
+    now = datetime.datetime.now()
+    f.write("""/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+""")
+    f.write("/*******************************************************************************\n")
+    f.write(" * This file had been created by asn1tostruct.py script v%s\n" % (version))
+    f.write(" * Please do not modify this file but regenerate it via script.\n")
+    f.write(" * Created on: %s by %s\n * from %s\n" % (str(now), getpass.getuser(), filenames))
+    f.write(" ******************************************************************************/\n")
+
+def lowerFirstCamelWord(word):
+    """ puts the first word in a CamelCase Word in lowercase.
+
+    I.e. CustomerID becomes customerID, XMLInfoTest becomes xmlInfoTest
+    """
+    newstr = ''
+    swapped = word.swapcase()
+    idx = 0
+
+    # if it's all-caps, return an all-lowered version
+    lowered = word.lower()
+
+    if swapped == lowered:
+        return lowered
+
+    for c in swapped:
+        if c in string.lowercase:
+            newstr += c
+            idx    += 1
+        else:
+            break
+    if idx < 2:
+        newstr += word[idx:]
+    else:
+        newstr = newstr[:-1]+ word[idx-1:]
+
+    return newstr
+
+def usage():
+    print "Python parser for asn1 v%s" % (version)
+    print "Usage: python asn1tostruct.py [options]"
+    print "Available options:"
+    print "-d        Enable script debug"
+    print "-f [file] Input file to parse"
+    print "-o [dir]  Output files to given directory"
+    print "-h        Print this help and return"
+
+try:
+    opts, args = getopt.getopt(sys.argv[1:], "df:ho:", ["debug", "file", "help", "outdir"])
+except getopt.GetoptError as err:
+    # print help information and exit:
+    usage()
+    sys.exit(2)
+
+for o, a in opts:
+    if o in ("-f", "--file"):
+        filenames.append(a)
+    if o in ("-d", "--debug"):
+        verbosity = 1
+    if o in ("-o", "--outdir"):
+        outdir = a
+        if outdir.rfind('/') != len(outdir):
+            outdir += '/'
+    if o in ("-h", "--help"):
+        usage()
+        sys.exit(2)
+
+for filename in filenames:
+    file = open(filename, 'r')
+    for line in file:
+        # Removing any comment
+        if line.find('--') >= 0:
+            line = line[:line.find('--')]
+        # Removing any carriage return
+        lines += re.sub('\r', '', line)
+
+    for m in re.findall(r'([a-zA-Z0-9-]+)\s*::=\s+SEQUENCE\s+\(\s*SIZE\s*\(\s*\d+\s*\.\.\s*[0-9a-zA-Z-]+\s*\)\s*\)\s*OF\s+[a-zA-Z-]+\s*\{\s*\{\s*([0-9a-zA-Z-]+)\s*\}\s*\}', lines, re.MULTILINE):
+        ieofielist[m[0]] = m[1]
+    for m in re.findall(r'([a-zA-Z0-9-]+)\s*::=\s+E-RAB-IE-ContainerList\s*\{\s*\{\s*([a-zA-Z0-9-]+)\s*\}\s*\}', lines, re.MULTILINE):
+        ieofielist[m[0]] = m[1]
+
+    for i in re.findall(r'([a-zA-Z0-9-]+)\s+([A-Z0-9-]+)\s*::=\s*\{\s+([\,\|\{\}\t\n\.{3}\ \-a-zA-Z0-9]+)\s+}\n', lines, re.MULTILINE):
+        ies = []
+        maxLength = 0
+        # TODO: handle extensions
+        if i[1].find('EXTENSION') >= 0:
+            continue
+        if fileprefix == "":
+            fileprefix = i[1][:i[1].find('-')].lower()
+        for j in re.findall(r'\s*\{\s*([a-zA-Z0-9-\ \t]+)\s*\}\s*[\|,]*', i[2], re.MULTILINE):
+            for k in re.findall(r'ID\s*([a-zA-Z0-9\-]+)\s*CRITICALITY\s*([a-zA-Z0-9\-]+)\s+[A-Z]+\s+([a-zA-Z0-9\-]+)\s*PRESENCE\s*([a-zA-Z0-9\-]+)', j, re.MULTILINE):
+                printDebug("Got new ie for message " + i[0] + ": " + str(k))
+                if len(k[2]) > maxLength:
+                    maxLength = len(k[2])
+                ies.append(k)
+
+        if len(ies) > 0:
+            iesDefs[i[0]] = { "length": maxLength, "ies": ies }
+        else:
+            printWarning("Didn't find any information element for message: " + i[0])
+
+if len(iesDefs) == 0:
+    printFail("No Information Element parsed, exiting")
+    sys.exit(0)
+
+fileprefix_first_upper = fileprefix[0].upper() + fileprefix[1:]
+
+f = open(outdir + fileprefix + '_ies_defs.h', 'w')
+outputHeaderToFile(f, filename)
+f.write("#include \"%s_common.h\"\n\n" % (fileprefix))
+f.write("#ifndef %s_IES_DEFS_H_\n#define %s_IES_DEFS_H_\n\n" % (fileprefix.upper(), fileprefix.upper()))
+f.write("/* Define the version of script used to generate this file */\n")
+f.write("#define %s_SCRIPT_VERSION (%s)\n\n" % (fileprefix.upper(), re.sub('\.', '', version)))
+
+for key in iesDefs:
+
+    if key not in ieofielist.values():
+        continue
+
+    for (i, j) in ieofielist.items():
+        if j == key:
+            break
+
+    f.write("typedef struct %sIEs_s {\n" % (re.sub('-', '_', i)))
+    f.write("    A_SEQUENCE_OF(struct %s_s) %s;\n" % (re.sub('IEs', '', re.sub('-', '_', ieofielist[i])), lowerFirstCamelWord(re.sub('IEs', '', re.sub('-', '_', ieofielist[i])))))
+    f.write("} %sIEs_t;\n\n" % (re.sub('-', '_', i)))
+
+for key in iesDefs:
+    keyupperunderscore = re.sub('-', '_', key.upper())
+    keylowerunderscore = re.sub('-', '_', key.lower())
+    shift = 0
+
+    if len(iesDefs[key]["ies"]) == 0:
+        continue
+
+    # Presence mask
+    for ie in iesDefs[key]["ies"]:
+        ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
+
+        if ie[3] == "optional" or ie[3] == "conditional":
+            f.write("#define {0:<{pad}} {1}\n".format("%s_%s_PRESENT" % (keyupperunderscore, ieupperunderscore), "(1 << %d)" % shift,
+            pad=iesDefs[key]["length"] + len(keyupperunderscore) + 9))
+            shift += 1
+    if (shift > 0):
+        f.write("\n")
+
+    f.write("typedef struct %s_s {\n" % (re.sub('-', '_', key)))
+    if (shift > 0):
+        f.write("    {0:<{pad}} {1};\n".format("uint16_t", "presenceMask", pad=iesDefs[key]["length"] + 2))
+    for ie in iesDefs[key]["ies"]:
+        ieunderscore = re.sub('-', '_', ie[2])
+        iename = re.sub('id-', '', ie[0])
+        ienameunderscore = lowerFirstCamelWord(re.sub('-', '_', iename))
+        if ie[2] in ieofielist:
+            f.write("    %sIEs_t %s;" % (re.sub('-', '_', ie[2]), ienameunderscore))
+        else:
+            f.write("    {0:<{pad}} {1};".format("%s_t" % ieunderscore, ienameunderscore, pad=iesDefs[key]["length"] + 2))
+        if ie[3] == "optional":
+            f.write(" ///< Optional field")
+        elif ie[3] == "conditional":
+            f.write(" ///< Conditional field")
+        f.write("\n")
+
+    f.write("} %s_t;\n\n" % (re.sub('-', '_', key)))
+
+f.write("typedef struct %s_message_s {\n" % (fileprefix))
+f.write("    %s_ProcedureCode_t procedureCode;\n" % (fileprefix_first_upper))
+f.write("    %s_Criticality_t   criticality;\n" % (fileprefix_first_upper))
+f.write("    uint8_t            direction;\n")
+f.write("    union {\n")
+
+messageList = iesDefs.keys()
+messageList.sort()
+for message in messageList:
+    if message in ieofielist.values():
+        continue
+    if len(iesDefs[message]["ies"]) == 0:
+        continue
+    f.write("        %s_t %s;\n" % (re.sub('-', '_', message), lowerFirstCamelWord(re.sub('-', '_', message))))
+f.write("    } msg;\n")
+f.write("} %s_message;\n\n" % (fileprefix))
+
+for key in iesDefs:
+    if key in ieofielist.values():
+        continue
+    structName = re.sub('ies', '', key)
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', re.sub('-IEs', '', key)))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    keylowerunderscore = re.sub('-', '_', key.lower())
+    firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    f.write("/* %s in iesDefs not in ieofielist.values()  */\n" % (key))
+    f.write("/** \\brief Decode function for %s ies.\n" % (key))
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write(" * \\param %s Pointer to ASN1 structure in which data will be stored\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write(" *  \\param any_p Pointer to the ANY value to decode.\n")
+    f.write(" **/\n")
+    f.write("int %s_decode_%s(\n" % (fileprefix, keylowerunderscore))
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write("    %s_t *%s,\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write("    ANY_t *any_p);\n\n")
+
+    if len(iesDefs[key]["ies"]) == 0:
+        continue
+
+    f.write("/* %s in iesDefs not in ieofielist.values()  */\n" % (key))
+    f.write("/** \\brief Encode function for %s ies.\n" % (key))
+    f.write(" *  \\param %s Pointer to the ASN1 structure.\n" % (firstlower))
+    f.write(" *  \\param %s Pointer to the IES structure.\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write(" **/\n")
+    f.write("int %s_encode_%s(\n" % (fileprefix, re.sub('-', '_', structName.lower())))
+    f.write("    %s_t *%s,\n" % (asn1cStruct, firstlower))
+    f.write("    %s_t *%s);\n\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
+
+
+for key in iesDefs:
+    if key not in ieofielist.values():
+        continue
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+    f.write("/* %s in iesDefs in ieofielist.values()  */\n" % (key))
+    f.write("/** \\brief Encode function for %s ies.\n" % (key))
+    f.write(" *  \\param %s Pointer to the ASN1 structure.\n" % (firstlower))
+    f.write(" *  \\param %s Pointer to the IES structure.\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write(" **/\n")
+    f.write("/* %s in iesDefs in ieofielist.values()  */\n" % (key))
+    f.write("int %s_encode_%s(\n" % (fileprefix, firstlower.lower()))
+    f.write("    %s_t *%s,\n" % (asn1cStruct, firstlower))
+    f.write("    %sIEs_t *%sIEs);\n\n" % (asn1cStruct, firstlower))
+    f.write("/** \\brief Decode function for %s ies.\n" % (key))
+    f.write(" *  \\param any_p Pointer to the ANY value to decode.\n")
+    f.write(" *  \\param callback Callback function called when any_p is successfully decoded.\n")
+    f.write(" **/\n")
+    f.write("/* %s in iesDefs in ieofielist.values()  */\n" % (key))
+    f.write("int %s_decode_%s(\n" % (fileprefix, firstlower.lower()))
+    f.write("    %sIEs_t *%sIEs,\n" % (asn1cStruct, firstlower))
+    f.write("    %s_t *%s);\n\n" % (asn1cStruct, lowerFirstCamelWord(asn1cStruct)))
+
+
+
+for key in iesDefs:
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    if key in ieofielist.values():
+        f.write("/** \\brief Display %s encapsulated IE using XER encoding.\n" % (asn1cStruct))
+        f.write(" *  \\param %s Pointer to the IES structure.\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+        f.write(" *  \\param file File descriptor to write output.\n")
+        f.write(" **/\n")
+        f.write("asn_enc_rval_t %s_xer_print_%s(\n" % (fileprefix, re.sub('item', 'list', firstlower.lower())))
+        f.write("    asn_app_consume_bytes_f *cb,\n")
+        f.write("    void *app_key,\n")
+        f.write("    %sIEs_t *%sIEs);\n\n" % (re.sub('item', 'list', asn1cStruct), firstlower))
+    else:
+        f.write("/** \\brief Display %s message using XER encoding.\n" % (asn1cStruct))
+        f.write(" *  \\param message_p Pointer to root message.\n")
+        f.write(" *  \\param file File descriptor to write output.\n")
+        f.write(" **/\n")
+        f.write("asn_enc_rval_t %s_xer_print_%s(\n" % (fileprefix, firstlower.lower()))
+        f.write("    asn_app_consume_bytes_f *cb,\n")
+        f.write("    void *app_key,\n")
+        f.write("    %s_message *message_p);\n\n" % (fileprefix))
+
+f.write("int %s_xer__print2sp(const void *buffer, size_t size, void *app_key);\n\n" % (fileprefix.lower()))
+f.write("int %s_xer__print2fp(const void *buffer, size_t size, void *app_key);\n\n" % (fileprefix.lower()))
+f.write("extern size_t %s_string_total_size;\n\n" % (fileprefix.lower()))
+f.write("#endif /* %s_IES_DEFS_H_ */\n\n" % (fileprefix.upper()))
+
+#Generate Decode functions
+f = open(outdir + fileprefix + '_decoder.c', 'w')
+outputHeaderToFile(f, filename)
+f.write("#include \"%s_common.h\"\n#include \"%s_ies_defs.h\"\n\n" % (fileprefix, fileprefix))
+for key in iesDefs:
+    if key in ieofielist.values():
+        continue
+    structName = re.sub('ies', '', key)
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
+    if asn1cStruct.rfind('_') == len(asn1cStruct) - 1:
+        asn1cStruct = asn1cStruct[:-1]
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    ielistname = re.sub('UE', 'ue', asn1cStruct)
+    ielistnamefirstlower = ielistname[:1].lower() + ielistname[1:]
+    asn1cStructfirstlower = asn1cStruct[:1].lower() + asn1cStruct[1:]
+    keyName = re.sub('-', '_', key)
+    keyupperunderscore = keyName.upper()
+    firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    iesaccess = ""
+    if key not in ieofielist.values():
+        iesaccess = "%s_ies." % (firstlower)
+
+    f.write("int %s_decode_%s(\n" % (fileprefix, re.sub('-', '_', structName.lower())))
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write("    %s_t *%s,\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
+    f.write("    ANY_t *any_p) {\n\n")
+
+    f.write("    %s_t  %s;\n    %s_t *%s_p = &%s;\n" % (asn1cStruct, asn1cStructfirstlower, asn1cStruct, asn1cStructfirstlower, asn1cStructfirstlower))
+    f.write("    int i, decoded = 0;\n")
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write("    int tempDecoded = 0;\n")
+
+    f.write("    assert(any_p != NULL);\n")
+    if len(iesDefs[key]["ies"]) != 0:
+        f.write("    assert(%s != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
+
+    f.write("    %s_DEBUG(\"Decoding message %s (%%s:%%d)\\n\", __FILE__, __LINE__);\n\n" % (fileprefix.upper(), re.sub('-', '_', keyName)))
+    f.write("    ANY_to_type_aper(any_p, &asn_DEF_%s, (void**)&%s_p);\n\n" % (asn1cStruct, asn1cStructfirstlower))
+    f.write("    for (i = 0; i < %s_p->%slist.count; i++) {\n" % (asn1cStructfirstlower, iesaccess))
+    f.write("        %s_IE_t *ie_p;\n" % (fileprefix[0].upper() + fileprefix[1:]))
+    f.write("        ie_p = %s_p->%slist.array[i];\n" % (asn1cStructfirstlower, iesaccess))
+    f.write("        switch(ie_p->id) {\n")
+    for ie in iesDefs[key]["ies"]:
+        iename = re.sub('id-', '', ie[0])
+        ienameunderscore = lowerFirstCamelWord(re.sub('-', '_', iename))
+        ienameunderscorefirstlower = lowerFirstCamelWord(ienameunderscore)
+        ietypesubst = re.sub('-', '', ie[2])
+        ietypeunderscore = re.sub('-', '_', ie[2])
+        ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
+
+        if ie[3] == "optional":
+            f.write("            /* Optional field */\n")
+        elif ie[3] == "conditional":
+            f.write("            /* Conditional field */\n")
+        f.write("            case %s_ProtocolIE_ID_%s:\n" % (fileprefix_first_upper, re.sub('-', '_', ie[0])))
+        f.write("            {\n")
+        f.write("                %s_t *%s_p = NULL;\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        if ie[3] != "mandatory":
+            f.write("                %s->presenceMask |= %s_%s_PRESENT;\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), keyupperunderscore, ieupperunderscore))
+        f.write("                tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_%s, (void**)&%s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        f.write("                if (tempDecoded < 0 || %s_p == NULL) {\n" % (lowerFirstCamelWord(ietypesubst)))
+        f.write("                    %s_ERROR(\"Decoding of IE %s failed\\n\");\n" % (fileprefix.upper(), ienameunderscore))
+        f.write("                    if (%s_p)\n" % (lowerFirstCamelWord(ietypesubst)))
+        f.write("                        ASN_STRUCT_FREE(asn_DEF_%s, %s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        f.write("                    return -1;\n")
+        f.write("                }\n")
+        f.write("                decoded += tempDecoded;\n")
+        f.write("                if (asn1_xer_print)\n")
+        f.write("                    xer_fprint(stdout, &asn_DEF_%s, %s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        if ie[2] in ieofielist.keys():
+            f.write("                if (%s_decode_%s(&%s->%s, %s_p) < 0) {\n" % (fileprefix, ietypeunderscore.lower(), lowerFirstCamelWord(re.sub('-', '_', key)), ienameunderscore, lowerFirstCamelWord(ietypesubst)))
+            f.write("                    %s_ERROR(\"Decoding of encapsulated IE %s failed\\n\");\n" % (fileprefix.upper(), lowerFirstCamelWord(ietypesubst)))
+            f.write("                    ASN_STRUCT_FREE(asn_DEF_%s, %s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+            f.write("                }\n")
+        else:
+            f.write("                memcpy(&%s->%s, %s_p, sizeof(%s_t));\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), ienameunderscore, lowerFirstCamelWord(ietypesubst), ietypeunderscore))
+            #f.write("                ASN_STRUCT_FREE(asn_DEF_%s, %s_p);\n" % (ietypeunderscore, lowerFirstCamelWord(ietypesubst)))
+        f.write("            } break;\n")
+    f.write("            default:\n")
+    f.write("                %s_ERROR(\"Unknown protocol IE id (%%d) for message %s\\n\", (int)ie_p->id);\n" % (fileprefix.upper(), re.sub('-', '_', structName.lower())))
+    f.write("                return -1;\n")
+    f.write("        }\n")
+    f.write("    }\n")
+    f.write("    return decoded;\n")
+    f.write("}\n\n")
+
+for key in iesDefs:
+    if key not in ieofielist.values():
+        continue
+
+    keyname = re.sub('IEs', '', re.sub('Item', 'List', key))
+
+    f.write("int %s_decode_%s(\n" % (fileprefix, re.sub('-', '_', keyname).lower()))
+    f.write("    %sIEs_t *%sIEs,\n" % (re.sub('-', '_', keyname), lowerFirstCamelWord(re.sub('-', '_', keyname))))
+    f.write("    %s_t *%s) {\n\n" % (re.sub('-', '_', keyname), lowerFirstCamelWord(re.sub('-', '_', keyname))))
+    f.write("    int i, decoded = 0;\n")
+    f.write("    int tempDecoded = 0;\n\n")
+
+    f.write("    assert(%s != NULL);\n" % (lowerFirstCamelWord(re.sub('-', '_', keyname))));
+    f.write("    assert(%sIEs != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', keyname))));
+
+    f.write("    for (i = 0; i < %s->list.count; i++) {\n" % (lowerFirstCamelWord(re.sub('-', '_', keyname))))
+    f.write("        %s_IE_t *ie_p = %s->list.array[i];\n" % (fileprefix[0].upper() + fileprefix[1:], lowerFirstCamelWord(re.sub('-', '_', keyname))))
+    f.write("        switch (ie_p->id) {\n")
+    for ie in iesDefs[key]["ies"]:
+        iename = re.sub('id-', '', ie[0])
+        ienameunderscore = lowerFirstCamelWord(re.sub('-', '_', iename))
+        f.write("            case %s_ProtocolIE_ID_%s:\n" % (fileprefix_first_upper, re.sub('-', '_', ie[0])))
+        f.write("            {\n")
+        f.write("                %s_t *%s_p = NULL;\n" % (re.sub('-', '_', ie[2]), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_%s, (void**)&%s_p);\n" % (re.sub('-', '_', ie[2]), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                if (tempDecoded < 0 || %s_p == NULL) {\n" % (lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                    %s_ERROR(\"Decoding of IE %s for message %s failed\\n\");\n" % (fileprefix.upper(), ienameunderscore, re.sub('-', '_', keyname)))
+        f.write("                    if (%s_p)\n" % (lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        #f.write("                        free(%s_p);\n" % (lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                        ASN_STRUCT_FREE(asn_DEF_%s, %s_p);\n" % (re.sub('-', '_', ie[2]), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                    return -1;\n")
+        f.write("                }\n")
+        f.write("                decoded += tempDecoded;\n")
+        f.write("                if (asn1_xer_print)\n")
+        f.write("                    xer_fprint(stdout, &asn_DEF_%s, %s_p);\n" % (re.sub('-', '_', ie[2]), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("                ASN_SEQUENCE_ADD(&%sIEs->%s, %s_p);\n" % (lowerFirstCamelWord(re.sub('-', '_', keyname)),
+        re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key))), lowerFirstCamelWord(re.sub('-', '', ie[2]))))
+        f.write("            } break;\n")
+    f.write("            default:\n")
+    f.write("                %s_ERROR(\"Unknown protocol IE id (%%d) for message %s\\n\", (int)ie_p->id);\n" % (fileprefix.upper(), re.sub('-', '_', structName.lower())))
+    f.write("                return -1;\n")
+    f.write("        }\n")
+    f.write("    }\n")
+    f.write("    return decoded;\n")
+    f.write("}\n\n")
+
+
+#Generate IES Encode functions
+f = open(outdir + fileprefix + '_encoder.c', 'w')
+outputHeaderToFile(f,filename)
+f.write("#include \"%s_common.h\"\n" % (fileprefix))
+f.write("#include \"%s_ies_defs.h\"\n\n" % (fileprefix))
+for key in iesDefs:
+    if key in ieofielist.values():
+        continue
+
+    structName = re.sub('ies', '', key)
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    if asn1cStruct.rfind('_') == len(asn1cStruct) - 1:
+        asn1cStruct = asn1cStruct[:-1]
+    asn1cStructfirstlower = asn1cStruct[:1].lower() + asn1cStruct[1:]
+    firstwordlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    iesaccess = ""
+    if key not in ieofielist.values():
+        iesaccess = "%s_ies." % (firstwordlower)
+
+    keyName = re.sub('-', '_', key)
+    keyupperunderscore = keyName.upper()
+    # No IE to encode...
+    if len(iesDefs[key]["ies"]) == 0:
+        continue
+
+    f.write("int %s_encode_%s(\n" % (fileprefix, re.sub('-', '_', structName.lower())))
+    f.write("    %s_t *%s,\n" % (asn1cStruct, firstwordlower))
+    f.write("    %s_t *%s) {\n\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
+
+    f.write("    %s_IE_t *ie;\n\n" % (fileprefix_first_upper))
+
+    f.write("    assert(%s != NULL);\n" % (firstwordlower));
+    f.write("    assert(%s != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', key))));
+
+    for ie in iesDefs[key]["ies"]:
+        iename = re.sub('-', '_', re.sub('id-', '', ie[0]))
+        ienameunderscore = re.sub('-', '_', iename)
+        ienamefirstwordlower = lowerFirstCamelWord(iename)
+        ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
+        ietypeunderscore = re.sub('-', '_', ie[2])
+
+        if ie[3] != "mandatory":
+            if ie[3] == "optional":
+                f.write("    /* Optional field */\n")
+            elif ie[3] == "conditional":
+                f.write("    /* Conditional field */\n")
+            f.write("    if (%s->presenceMask & %s_%s_PRESENT) {\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), keyupperunderscore, ieupperunderscore))
+            #f.write("        == %s_%s_PRESENT) {\n" % (keyupperunderscore, ieupperunderscore))
+            f.write("        if ((ie = %s_new_ie(%s_ProtocolIE_ID_%s,\n" % (fileprefix, fileprefix_first_upper, re.sub('-', '_', ie[0])))
+            f.write("                            %s_Criticality_%s,\n" % (fileprefix_first_upper, ie[1]))
+            f.write("                            &asn_DEF_%s,\n" % (ietypeunderscore))
+            f.write("                            &%s->%s)) == NULL) {\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower))
+            f.write("            return -1;\n")
+            f.write("        }\n")
+            f.write("        ASN_SEQUENCE_ADD(&%s->%slist, ie);\n" % (firstwordlower, iesaccess))
+            f.write("    }\n\n")
+        else:
+            if ie[2] in ieofielist.keys():
+                f.write("    %s_t %s;\n\n" % (ietypeunderscore, ienamefirstwordlower))
+                f.write("    memset(&%s, 0, sizeof(%s_t));\n" % (ienamefirstwordlower, ietypeunderscore))
+                f.write("\n")
+                f.write("    if (%s_encode_%s(&%s, &%s->%s) < 0) return -1;\n" % (fileprefix, ietypeunderscore.lower(), ienamefirstwordlower, lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower))
+            f.write("    if ((ie = %s_new_ie(%s_ProtocolIE_ID_%s,\n" % (fileprefix, fileprefix_first_upper, re.sub('-', '_', ie[0])))
+            f.write("                        %s_Criticality_%s,\n" % (fileprefix_first_upper, ie[1]))
+            f.write("                        &asn_DEF_%s,\n" % (ietypeunderscore))
+            if ie[2] in ieofielist.keys():
+                f.write("                          &%s)) == NULL) {\n" % (ienamefirstwordlower))
+            else:
+                f.write("                          &%s->%s)) == NULL) {\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower))
+            f.write("        return -1;\n")
+            f.write("    }\n")
+            f.write("    ASN_SEQUENCE_ADD(&%s->%slist, ie);\n\n" % (firstwordlower, iesaccess))
+            if ie[2] in ieofielist.keys():
+                f.write("    /* Free any dynamic allocation that is no more used */\n")
+                f.write("    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_%s, &%s);\n\n" % (ietypeunderscore, ienamefirstwordlower))
+
+    f.write("    return 0;\n")
+    f.write("}\n\n")
+
+for (key, value) in iesDefs.items():
+    if key not in ieofielist.values():
+        continue
+
+    ie = value["ies"][0]
+    ietypeunderscore = re.sub('-', '_', ie[2])
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', re.sub('-IEs', '', key)))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    firstwordlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    for (i, j) in ieofielist.items():
+        if j == key:
+            break
+    f.write("int %s_encode_%s(\n" % (fileprefix, re.sub('-', '_', i).lower()))
+    f.write("    %s_t *%s,\n" % (asn1cStruct, firstwordlower))
+    f.write("    %sIEs_t *%sIEs) {\n\n" % (re.sub('-', '_', i), lowerFirstCamelWord(re.sub('-', '_', i))))
+    f.write("    int i;\n")
+
+    f.write("    %s_IE_t *ie;\n\n" % (fileprefix_first_upper))
+
+    f.write("    assert(%s != NULL);\n" % (firstwordlower));
+    f.write("    assert(%sIEs != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', i))));
+
+    f.write("    for (i = 0; i < %sIEs->%s.count; i++) {\n" % (firstwordlower, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+    f.write("        if ((ie = %s_new_ie(%s_ProtocolIE_ID_%s,\n" % (fileprefix, fileprefix_first_upper, re.sub('-', '_', ie[0])))
+    f.write("                            %s_Criticality_%s,\n" % (fileprefix_first_upper, ie[1]))
+    f.write("                            &asn_DEF_%s,\n" % (ietypeunderscore))
+    f.write("                            %sIEs->%s.array[i])) == NULL) {\n" % (firstwordlower, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+    f.write("            return -1;\n")
+    f.write("        }\n")
+    f.write("        ASN_SEQUENCE_ADD(&%s->list, ie);\n" % (firstwordlower))
+    f.write("    }\n")
+    f.write("    return 0;\n")
+    f.write("}\n\n")
+
+#Generate xer print functions
+f = open(outdir + fileprefix + '_xer_print.c', 'w')
+outputHeaderToFile(f, filename)
+f.write("#include <stdlib.h>\n")
+f.write("#include <stdio.h>\n\n")
+f.write("#include <asn_application.h>\n#include <asn_internal.h>\n\n")
+f.write("#include \"%s_common.h\"\n#include \"%s_ies_defs.h\"\n\n" % (fileprefix, fileprefix))
+
+f.write("size_t %s_string_total_size = 0;\n\n" % (fileprefix.lower()))
+f.write("""int
+%s_xer__print2fp(const void *buffer, size_t size, void *app_key) {
+    FILE *stream = (FILE *)app_key;
+
+    if(fwrite(buffer, 1, size, stream) != size)
+        return -1;
+
+    return 0;
+}
+
+""" % (fileprefix.lower()))
+
+f.write("""int %s_xer__print2sp(const void *buffer, size_t size, void *app_key) {
+    char *string = (char *)app_key;
+
+    /* Copy buffer to the formatted string */
+    memcpy(&string[%s_string_total_size], buffer, size);
+
+    %s_string_total_size += size;
+
+    return 0;
+}
+
+""" % (fileprefix.lower(), fileprefix.lower(), fileprefix.lower()))
+
+f.write("""static asn_enc_rval_t
+xer_encode_local(asn_TYPE_descriptor_t *td, void *sptr,
+        asn_app_consume_bytes_f *cb, void *app_key, int indent) {
+    asn_enc_rval_t er, tmper;
+    const char *mname;
+    size_t mlen;
+    int xcan = 2;
+
+    if(!td || !sptr) goto cb_failed;
+
+    mname = td->xml_tag;
+    mlen = strlen(mname);
+
+    ASN__TEXT_INDENT(0, indent);
+    ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
+
+    tmper = td->op->xer_encoder(td, sptr, indent + 1, XER_F_BASIC, cb, app_key);
+    if(tmper.encoded == -1) return tmper;
+
+    ASN__CALLBACK3("</", 2, mname, mlen, ">\\n", xcan);
+
+    er.encoded = 4 + xcan + (2 * mlen) + tmper.encoded;
+
+    ASN__ENCODED_OK(er);
+cb_failed:
+    ASN__ENCODE_FAILED;
+}
+""")
+
+for (key, value) in iesDefs.items():
+    keyName = re.sub('-', '_', key)
+    keyupperunderscore = keyName.upper()
+    iesStructName = lowerFirstCamelWord(re.sub('-', '_', key))
+
+    ie = value["ies"][0]
+    ietypeunderscore = re.sub('-', '_', ie[2])
+
+    if key in ieofielist.values():
+        f.write("asn_enc_rval_t %s_xer_print_%s(\n" % (fileprefix, re.sub('ies', '', re.sub('item', 'list', re.sub('-', '_', key).lower()))))
+    else:
+        f.write("asn_enc_rval_t %s_xer_print_%s(\n" % (fileprefix, re.sub('ies', '', re.sub('-', '_', key).lower())))
+    #f.write("    FILE *file,\n")
+    f.write("    asn_app_consume_bytes_f *cb,\n")
+    f.write("    void *app_key,\n")
+    if key in ieofielist.values():
+        iesStructName = lowerFirstCamelWord(re.sub('Item', 'List', re.sub('-', '_', key)))
+        f.write("    %sIEs_t *%s) {\n\n" % (re.sub('IEs', '', re.sub('Item', 'List', re.sub('-', '_', key))), iesStructName))
+        f.write("    int i;\n")
+        f.write("    asn_enc_rval_t er;\n")
+    else:
+        f.write("    %s_message *message_p)\n{\n" % (fileprefix))
+        f.write("    %s_t *%s;\n" % (re.sub('-', '_', key), iesStructName))
+        f.write("    asn_enc_rval_t er;\n")
+        #f.write("    void *app_key = (void *)file;\n")
+        #f.write("    asn_app_consume_bytes_f *cb = %s_xer__print2fp;\n\n" % (fileprefix.lower()))
+
+        f.write("    %s = &message_p->msg.%s;\n\n" % (iesStructName, iesStructName))
+
+    if key in ieofielist.values():
+        # Increase indentation level
+        f.write("    for (i = 0; i < %s->%s.count; i++) {\n" % (iesStructName, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+        #f.write("        xer_fprint(file, &asn_DEF_%s, %s->%s.array[i]);\n" % (ietypeunderscore, iesStructName, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+        f.write("        er = xer_encode(&asn_DEF_%s, %s->%s.array[i], XER_F_BASIC, cb, app_key);\n" % (ietypeunderscore, iesStructName, re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
+        f.write("    }\n")
+    else:
+        f.write("    cb(\"<%s-PDU>\\n\", %d, app_key);\n" % (key, len("<%s-PDU>\n" % (key))))
+        f.write("    xer_encode_local(&asn_DEF_%s_Criticality, &message_p->criticality, cb, app_key, 1);\n" % fileprefix_first_upper)
+        f.write("    xer_encode_local(&asn_DEF_%s_ProcedureCode, &message_p->procedureCode, cb, app_key, 1);\n" % fileprefix_first_upper)
+
+        f.write("    cb(\"    <%s>\\n\", %d, app_key);\n" % (key, len("    <%s>\n" % (key))))
+
+        for ie in iesDefs[key]["ies"]:
+            iename = re.sub('-', '_', re.sub('id-', '', ie[0]))
+            ienameunderscore = re.sub('-', '_', iename)
+            ienamefirstwordlower = lowerFirstCamelWord(iename)
+            ietypeunderscore = re.sub('-', '_', ie[2])
+            ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
+
+            if ie[3] != "mandatory":
+                if ie[3] == "optional":
+                    f.write("    /* Optional field */\n")
+                elif ie[3] == "conditional":
+                    f.write("    /* Conditional field */\n")
+                f.write("    if (%s->presenceMask & %s_%s_PRESENT)\n    " % (iesStructName, keyupperunderscore, ieupperunderscore))
+
+            # Is it an encapsulated IE ?
+            if ie[2] in ieofielist.keys():
+                f.write("    %s_xer_print_%s(cb, app_key, &%s->%s);\n" % (fileprefix, re.sub('ies', '', re.sub('-', '_', ie[2]).lower()), iesStructName, ienamefirstwordlower))
+            else:
+                f.write("    xer_encode_local(&asn_DEF_%s, &%s->%s, cb, app_key, 2);\n" % (ietypeunderscore, iesStructName, ienamefirstwordlower))
+        f.write("    cb(\"    </%s>\\n\", %d, app_key);\n" % (key, len("    </%s>\n" % (key))))
+        f.write("    cb(\"</%s-PDU>\\n\", %d, app_key);\n" % (key, len("</%s-PDU>\n" % (key))))
+
+    f.write("    ASN__ENCODED_OK(er);\n")
+    #if key not in ieofielist.values():
+        #f.write("cb_failed:\n")
+        #f.write("    return er;\n")
+    f.write("}\n\n")
+
+
+#Generate xer print functions
+f = open(outdir + fileprefix + '_compare.c', 'w')
+outputHeaderToFile(f, filename)
+f.write("#include <stdlib.h>\n")
+f.write("#include <stdio.h>\n\n")
+f.write("#include <asn_application.h>\n#include <asn_internal.h>\n\n")
+f.write("#include \"%s_common.h\"\n#include \"%s_ies_defs.h\"\n" % (fileprefix, fileprefix))
+f.write("#include \"%s-ProtocolIE-ID.h\"\n\n" % (fileprefix_first_upper))
+
+
+for (key, value) in iesDefs.items():
+    if key not in ieofielist.values():
+        continue
+
+    ie = value["ies"][0]
+    ietypeunderscore = re.sub('-', '_', ie[2])
+    asn1cStruct = re.sub('-', '_', re.sub('IEs', '', re.sub('-IEs', '', key)))
+    asn1cStruct = re.sub('Item', 'List', asn1cStruct)
+    firstwordlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
+
+    for (i, j) in ieofielist.items():
+        if j == key:
+            break
+
+    f.write("extern asn_TYPE_descriptor_t asn_DEF_%s;\n" % (ietypeunderscore))
diff --git a/openair3/M3AP/m3ap_MCE.c b/openair3/M3AP/m3ap_MCE.c
new file mode 100644
index 0000000000000000000000000000000000000000..232b0c0ecec5842d85398dadabb7bf9a978d7aec
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE.c
@@ -0,0 +1,689 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE.c
+ * \brief m3ap tasks for MCE
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
+#include "intertask_interface.h"
+
+#include "m3ap_MCE.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_MCE_management_procedures.h"
+#include "m3ap_MCE_handler.h"
+//#include "m3ap_MCE_generate_messages.h"
+#include "m3ap_common.h"
+#include "m3ap_MCE_interface_management.h"
+#include "m3ap_ids.h"
+#include "m3ap_timers.h"
+
+#include "queue.h"
+#include "assertions.h"
+#include "conversions.h"
+
+struct m3ap_mce_map;
+struct m3ap_MCE_data_s;
+
+m3ap_setup_req_t * m3ap_mce_data_g;
+
+RB_PROTOTYPE(m3ap_mce_map, m3ap_MCE_data_s, entry, m3ap_MCE_compare_assoc_id);
+
+static
+void m3ap_MCE_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
+
+static
+void m3ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
+
+static
+void m3ap_MCE_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind);
+
+static
+void m3ap_MCE_handle_register_MCE(instance_t instance,
+                                  m3ap_register_mce_req_t *m3ap_register_MME);
+static
+void m3ap_MCE_register_MCE(m3ap_MCE_instance_t *instance_p,
+                           net_ip_address_t    *target_MME_ip_addr,
+                           net_ip_address_t    *local_ip_addr,
+                           uint16_t             in_streams,
+                           uint16_t             out_streams,
+                           uint32_t             mce_port_for_M3C,
+                           int                  multi_sd);
+
+//static
+//void m3ap_eNB_handle_handover_req(instance_t instance,
+//                                  m3ap_handover_req_t *m3ap_handover_req);
+//
+//static
+//void m3ap_eNB_handle_handover_req_ack(instance_t instance,
+//                                      m3ap_handover_req_ack_t *m3ap_handover_req_ack);
+//
+//static
+//void m3ap_eNB_ue_context_release(instance_t instance,
+//                                 m3ap_ue_context_release_t *m3ap_ue_context_release);
+//
+
+static
+void m3ap_MCE_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
+  int result;
+  DevAssert(sctp_data_ind != NULL);
+  m3ap_MCE_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
+                          sctp_data_ind->buffer, sctp_data_ind->buffer_length);
+  result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
+  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+}
+
+static
+void m3ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
+  m3ap_MCE_instance_t *instance_p;
+  m3ap_MCE_data_t *m3ap_mce_data_p;
+  DevAssert(sctp_new_association_resp != NULL);
+  //printf("m3ap_eNB_handle_sctp_association_resp at 1\n");
+  //dump_trees();
+  instance_p = m3ap_MCE_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  /* if the assoc_id is already known, it is certainly because an IND was received
+   * before. In this case, just update streams and return
+   */
+  if (sctp_new_association_resp->assoc_id != -1) {
+    m3ap_mce_data_p = m3ap_get_MCE(instance_p, sctp_new_association_resp->assoc_id,
+                                   sctp_new_association_resp->ulp_cnx_id);
+
+    if (m3ap_mce_data_p != NULL) {
+      /* some sanity check - to be refined at some point */
+      if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+        M3AP_ERROR("m3ap_mce_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
+        abort();
+      }
+
+      m3ap_mce_data_p->in_streams  = sctp_new_association_resp->in_streams;
+      m3ap_mce_data_p->out_streams = sctp_new_association_resp->out_streams;
+      return;
+    }
+  }
+
+  m3ap_mce_data_p = m3ap_get_MCE(instance_p, -1,
+                                 sctp_new_association_resp->ulp_cnx_id);
+  DevAssert(m3ap_mce_data_p != NULL);
+  //printf("m3ap_MCE_handle_sctp_association_resp at 2\n");
+  //dump_trees_m3();
+
+  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+    M3AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+              sctp_new_association_resp->sctp_state,
+              instance,
+              sctp_new_association_resp->ulp_cnx_id);
+    //m3ap_handle_m3_setup_message(instance_p, m3ap_enb_data_p,
+                                 //sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+    return;
+  }
+
+  //printf("m3ap_MCE_handle_sctp_association_resp at 3\n");
+  //dump_trees_m3();
+  /* Update parameters */
+  m3ap_mce_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
+  m3ap_mce_data_p->in_streams  = sctp_new_association_resp->in_streams;
+  m3ap_mce_data_p->out_streams = sctp_new_association_resp->out_streams;
+  //printf("m3ap_MCE_handle_sctp_association_resp at 4\n");
+  //dump_trees_m3();
+
+  m3ap_mce_data_g->assoc_id    = sctp_new_association_resp->assoc_id;
+  m3ap_mce_data_g->sctp_in_streams  = sctp_new_association_resp->in_streams;
+  m3ap_mce_data_g->sctp_out_streams = sctp_new_association_resp->out_streams;
+
+  /* Prepare new m3 Setup Request */
+  //m3ap_eNB_generate_m3_setup_request(instance_p, m3ap_enb_data_p);
+  MCE_send_M3_SETUP_REQUEST(instance_p, m3ap_mce_data_p);
+}
+
+static
+void m3ap_MCE_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) {
+  m3ap_MCE_instance_t *instance_p;
+  m3ap_MCE_data_t *m3ap_mce_data_p;
+  //printf("m3ap_MCE_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
+  //dump_trees_m3();
+  DevAssert(sctp_new_association_ind != NULL);
+  instance_p = m3ap_MCE_get_instance(instance);
+  DevAssert(instance_p != NULL);
+  m3ap_mce_data_p = m3ap_get_MCE(instance_p, sctp_new_association_ind->assoc_id, -1);
+
+  if (m3ap_mce_data_p != NULL) abort();
+
+  //  DevAssert(m3ap_mce_data_p != NULL);
+  if (m3ap_mce_data_p == NULL) {
+    /* Create new MCE descriptor */
+    m3ap_mce_data_p = calloc(1, sizeof(*m3ap_mce_data_p));
+    DevAssert(m3ap_mce_data_p != NULL);
+    m3ap_mce_data_p->cnx_id                = m3ap_MCE_fetch_add_global_cnx_id();
+    m3ap_mce_data_p->m3ap_MCE_instance = instance_p;
+    /* Insert the new descriptor in list of known eNB
+     * but not yet associated.
+     */
+    RB_INSERT(m3ap_mce_map, &instance_p->m3ap_mce_head, m3ap_mce_data_p);
+    m3ap_mce_data_p->state = M3AP_MCE_STATE_CONNECTED;
+    instance_p->m3_target_mme_nb++;
+
+    if (instance_p->m3_target_mme_pending_nb > 0) {
+      instance_p->m3_target_mme_pending_nb--;
+    }
+  } else {
+    M3AP_WARN("m3ap_mce_data_p already exists\n");
+  }
+
+  //printf("m3ap_MCE_handle_sctp_association_ind at 2\n");
+  //dump_trees_m3();
+  /* Update parameters */
+  m3ap_mce_data_p->assoc_id    = sctp_new_association_ind->assoc_id;
+  m3ap_mce_data_p->in_streams  = sctp_new_association_ind->in_streams;
+  m3ap_mce_data_p->out_streams = sctp_new_association_ind->out_streams;
+  //printf("m3ap_MCE_handle_sctp_association_ind at 3\n");
+  //dump_trees_m3();
+}
+
+int m3ap_MCE_init_sctp (m3ap_MCE_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t mce_port_for_M3C) {
+  // Create and alloc new message
+  MessageDef                             *message;
+  sctp_init_t                            *sctp_init  = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(local_ip_addr != NULL);
+  message = itti_alloc_new_message (TASK_M3AP_MCE, SCTP_INIT_MSG_MULTI_REQ);
+  sctp_init = &message->ittiMsg.sctp_init_multi;
+  sctp_init->port = mce_port_for_M3C;
+  sctp_init->ppid = M3AP_SCTP_PPID;
+  sctp_init->ipv4 = 1;
+  sctp_init->ipv6 = 0;
+  sctp_init->nb_ipv4_addr = 1;
+#if 0
+  memcpy(&sctp_init->ipv4_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+#endif
+  sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
+  /*
+   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+   * * * * Disable it for now.
+   */
+  sctp_init->nb_ipv6_addr = 0;
+  sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
+  return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
+}
+
+static void m3ap_MCE_register_MCE(m3ap_MCE_instance_t *instance_p,
+                                  net_ip_address_t    *target_MCE_ip_address,
+                                  net_ip_address_t    *local_ip_addr,
+                                  uint16_t             in_streams,
+                                  uint16_t             out_streams,
+                                  uint32_t         mce_port_for_M3C,
+                                  int                  multi_sd) {
+  MessageDef                       *message                   = NULL;
+  sctp_new_association_req_multi_t *sctp_new_association_req  = NULL;
+  m3ap_MCE_data_t                  *m3ap_mce_data             = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(target_MCE_ip_address != NULL);
+  message = itti_alloc_new_message(TASK_M3AP_MCE, SCTP_NEW_ASSOCIATION_REQ_MULTI);
+  sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi;
+  sctp_new_association_req->port = mce_port_for_M3C;
+  sctp_new_association_req->ppid = M3AP_SCTP_PPID;
+  sctp_new_association_req->in_streams  = in_streams;
+  sctp_new_association_req->out_streams = out_streams;
+  sctp_new_association_req->multi_sd = multi_sd;
+  memcpy(&sctp_new_association_req->remote_address,
+         target_MCE_ip_address,
+         sizeof(*target_MCE_ip_address));
+  memcpy(&sctp_new_association_req->local_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+  /* Create new MCE descriptor */
+  m3ap_mce_data = calloc(1, sizeof(*m3ap_mce_data));
+  DevAssert(m3ap_mce_data != NULL);
+  m3ap_mce_data->cnx_id                = m3ap_MCE_fetch_add_global_cnx_id();
+  sctp_new_association_req->ulp_cnx_id = m3ap_mce_data->cnx_id;
+  m3ap_mce_data->assoc_id          = -1;
+  m3ap_mce_data->m3ap_MCE_instance = instance_p;
+  /* Insert the new descriptor in list of known eNB
+   * but not yet associated.
+   */
+
+  m3ap_mce_data_g = (m3ap_setup_req_t*)calloc(1,sizeof(m3ap_setup_req_t));
+
+
+
+  RB_INSERT(m3ap_mce_map, &instance_p->m3ap_mce_head, m3ap_mce_data);
+  m3ap_mce_data->state = M3AP_MCE_STATE_WAITING;
+  instance_p->m3_target_mme_nb ++;
+  instance_p->m3_target_mme_pending_nb ++;
+  itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
+}
+
+static
+void m3ap_MCE_handle_register_MCE(instance_t instance,
+                                  m3ap_register_mce_req_t *m3ap_register_MCE) {
+  m3ap_MCE_instance_t *new_instance;
+  DevAssert(m3ap_register_MCE != NULL);
+  /* Look if the provided instance already exists */
+  new_instance = m3ap_MCE_get_instance(instance);
+
+  if (new_instance != NULL) {
+    /* Checks if it is a retry on the same MCE */
+    DevCheck(new_instance->MCE_id == m3ap_register_MCE->MCE_id, new_instance->MCE_id, m3ap_register_MCE->MCE_id, 0);
+    DevCheck(new_instance->cell_type == m3ap_register_MCE->cell_type, new_instance->cell_type, m3ap_register_MCE->cell_type, 0);
+    DevCheck(new_instance->tac == m3ap_register_MCE->tac, new_instance->tac, m3ap_register_MCE->tac, 0);
+    DevCheck(new_instance->mcc == m3ap_register_MCE->mcc, new_instance->mcc, m3ap_register_MCE->mcc, 0);
+    DevCheck(new_instance->mnc == m3ap_register_MCE->mnc, new_instance->mnc, m3ap_register_MCE->mnc, 0);
+    M3AP_WARN("MCE[%d] already registered\n", instance);
+  } else {
+    new_instance = calloc(1, sizeof(m3ap_MCE_instance_t));
+    DevAssert(new_instance != NULL);
+    RB_INIT(&new_instance->m3ap_mce_head);
+    /* Copy usefull parameters */
+    new_instance->instance         = instance;
+    new_instance->MCE_name         = m3ap_register_MCE->MCE_name;
+    new_instance->MCE_id           = m3ap_register_MCE->MCE_id;
+    new_instance->cell_type        = m3ap_register_MCE->cell_type;
+    new_instance->tac              = m3ap_register_MCE->tac;
+    new_instance->mcc              = m3ap_register_MCE->mcc;
+    new_instance->mnc              = m3ap_register_MCE->mnc;
+    new_instance->mnc_digit_length = m3ap_register_MCE->mnc_digit_length;
+    new_instance->num_cc           = m3ap_register_MCE->num_cc;
+
+    m3ap_id_manager_init(&new_instance->id_manager);
+    m3ap_timers_init(&new_instance->timers,
+                     m3ap_register_MCE->t_reloc_prep,
+                     m3ap_register_MCE->tm3_reloc_overall);
+
+    for (int i = 0; i< m3ap_register_MCE->num_cc; i++) {
+      new_instance->eutra_band[i]              = m3ap_register_MCE->eutra_band[i];
+      new_instance->downlink_frequency[i]      = m3ap_register_MCE->downlink_frequency[i];
+      new_instance->uplink_frequency_offset[i] = m3ap_register_MCE->uplink_frequency_offset[i];
+      new_instance->Nid_cell[i]                = m3ap_register_MCE->Nid_cell[i];
+      new_instance->N_RB_DL[i]                 = m3ap_register_MCE->N_RB_DL[i];
+      new_instance->frame_type[i]              = m3ap_register_MCE->frame_type[i];
+      new_instance->fdd_earfcn_DL[i]           = m3ap_register_MCE->fdd_earfcn_DL[i];
+      new_instance->fdd_earfcn_UL[i]           = m3ap_register_MCE->fdd_earfcn_UL[i];
+    }
+
+    DevCheck(m3ap_register_MCE->nb_m3 <= M3AP_MAX_NB_MCE_IP_ADDRESS,
+             M3AP_MAX_NB_MCE_IP_ADDRESS, m3ap_register_MCE->nb_m3, 0);
+    memcpy(new_instance->target_mme_m3_ip_address,
+           m3ap_register_MCE->target_mme_m3_ip_address,
+           m3ap_register_MCE->nb_m3 * sizeof(net_ip_address_t));
+    new_instance->nb_m3             = m3ap_register_MCE->nb_m3;
+    new_instance->mme_m3_ip_address = m3ap_register_MCE->mme_m3_ip_address;
+    new_instance->sctp_in_streams   = m3ap_register_MCE->sctp_in_streams;
+    new_instance->sctp_out_streams  = m3ap_register_MCE->sctp_out_streams;
+    new_instance->mce_port_for_M3C  = m3ap_register_MCE->mme_port_for_M3C;
+    /* Add the new instance to the list of MCE (meaningfull in virtual mode) */
+    m3ap_MCE_insert_new_instance(new_instance);
+    M3AP_INFO("Registered new MCE[%d] and %s MCE id %u\n",
+              instance,
+              m3ap_register_MCE->cell_type == CELL_MACRO_ENB ? "macro" : "home",
+              m3ap_register_MCE->MCE_id);
+
+    
+    printf("ipv4_address %s\n",m3ap_register_MCE->mme_m3_ip_address.ipv4_address);
+    /* initiate the SCTP listener */
+    if (m3ap_MCE_init_sctp(new_instance,&m3ap_register_MCE->mme_m3_ip_address,m3ap_register_MCE->mme_port_for_M3C) <  0 ) {
+      M3AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
+      return;
+    }
+
+    M3AP_INFO("MCE[%d] MCE id %u acting as a listner (server)\n",
+              instance, m3ap_register_MCE->MCE_id);
+  }
+}
+
+static
+void m3ap_MCE_handle_sctp_init_msg_multi_cnf(
+  instance_t instance_id,
+  sctp_init_msg_multi_cnf_t *m) {
+  m3ap_MCE_instance_t *instance;
+  int index;
+  DevAssert(m != NULL);
+  instance = m3ap_MCE_get_instance(instance_id);
+  DevAssert(instance != NULL);
+  instance->multi_sd = m->multi_sd;
+
+  /* Exit if CNF message reports failure.
+   * Failure means multi_sd < 0.
+   */
+  if (instance->multi_sd < 0) {
+    M3AP_ERROR("Error: be sure to properly configure M3 in your configuration file.\n");
+    DevAssert(instance->multi_sd >= 0);
+  }
+
+  /* Trying to connect to the provided list of MCE ip address */
+
+  for (index = 0; index < instance->nb_m3; index++) {
+    M3AP_INFO("MCE[%d] MCE id %u acting as an initiator (client)\n",
+              instance_id, instance->MCE_id);
+    m3ap_MCE_register_MCE(instance,
+                          &instance->target_mme_m3_ip_address[index],
+                          &instance->mme_m3_ip_address,
+                          instance->sctp_in_streams,
+                          instance->sctp_out_streams,
+                          instance->mce_port_for_M3C,
+                          instance->multi_sd);
+  }
+}
+
+//static
+//void m3ap_eNB_handle_handover_req(instance_t instance,
+//                                  m3ap_handover_req_t *m3ap_handover_req)
+//{
+//  m3ap_eNB_instance_t *instance_p;
+//  m3ap_eNB_data_t     *target;
+//  m3ap_id_manager     *id_manager;
+//  int                 ue_id;
+//
+//  int target_pci = m3ap_handover_req->target_physCellId;
+//
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_is_eNB_pci_in_list(target_pci);
+//  DevAssert(target != NULL);
+//
+//  /* allocate m3ap ID */
+//  id_manager = &instance_p->id_manager;
+//  ue_id = m3ap_allocate_new_id(id_manager);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not allocate a new M3AP UE ID\n");
+//    /* TODO: cancel handover: send (to be defined) message to RRC */
+//    exit(1);
+//  }
+//  /* id_source is ue_id, id_target is unknown yet */
+//  m3ap_set_ids(id_manager, ue_id, m3ap_handover_req->rnti, ue_id, -1);
+//  m3ap_id_set_state(id_manager, ue_id, M2ID_STATE_SOURCE_PREPARE);
+//  m3ap_set_reloc_prep_timer(id_manager, ue_id,
+//                            m3ap_timer_get_tti(&instance_p->timers));
+//  m3ap_id_set_target(id_manager, ue_id, target);
+//
+//  m3ap_eNB_generate_m3_handover_request(instance_p, target, m3ap_handover_req, ue_id);
+//}
+
+//static
+//void m3ap_eNB_handle_handover_req_ack(instance_t instance,
+//                                      m3ap_handover_req_ack_t *m3ap_handover_req_ack)
+//{
+//  /* TODO: remove this hack (the goal is to find the correct
+//   * eNodeB structure for the other end) - we need a proper way for RRC
+//   * and M3AP to identify eNodeBs
+//   * RRC knows about mod_id and M3AP knows about eNB_id (eNB_ID in
+//   * the configuration file)
+//   * as far as I understand.. CROUX
+//   */
+//  m3ap_eNB_instance_t *instance_p;
+//  m3ap_eNB_data_t     *target;
+//  int source_assoc_id = m3ap_handover_req_ack->source_assoc_id;
+//  int                 ue_id;
+//  int                 id_source;
+//  int                 id_target;
+//
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_get_eNB(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  /* rnti is a new information, save it */
+//  ue_id     = m3ap_handover_req_ack->m3_id_target;
+//  id_source = m3ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//  m3ap_set_ids(&instance_p->id_manager, ue_id, m3ap_handover_req_ack->rnti, id_source, id_target);
+//
+//  m3ap_eNB_generate_m3_handover_request_ack(instance_p, target, m3ap_handover_req_ack);
+//}
+//
+//static
+//void m3ap_eNB_ue_context_release(instance_t instance,
+//                                 m3ap_ue_context_release_t *m3ap_ue_context_release)
+//{
+//  m3ap_eNB_instance_t *instance_p;
+//  m3ap_eNB_data_t     *target;
+//  int source_assoc_id = m3ap_ue_context_release->source_assoc_id;
+//  int ue_id;
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_get_eNB(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  m3ap_eNB_generate_m3_ue_context_release(instance_p, target, m3ap_ue_context_release);
+//
+//  /* free the M3AP UE ID */
+//  ue_id = m3ap_find_id_from_rnti(&instance_p->id_manager, m3ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not find UE %x\n", m3ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  m3ap_release_id(&instance_p->id_manager, ue_id);
+//}
+
+uint8_t m3ap_m3setup[] = {
+  0x00, 0x07, 0x00, 0x23, 0x00, 0x00, 0x03, 0x00,
+  0x12, 0x00, 0x07, 0x40, 0x55, 0xf5, 0x01, 0x00,
+  0x25, 0x00, 0x00, 0x13, 0x40, 0x0a, 0x03, 0x80,
+  0x4d, 0x33, 0x2d, 0x65, 0x4e, 0x42, 0x33, 0x37,
+  0x00, 0x14, 0x00, 0x03, 0x01, 0x00, 0x01
+};
+
+uint8_t m3ap_start[] = {
+  0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00,
+  0x07, 0x00, 0x55, 0xf5, 0x01, 0x00, 0x00, 0x01,
+  0x00, 0x04, 0x00, 0x0d, 0x60, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 0x01,
+  0x7a, 0x00, 0x05, 0x00, 0x03, 0x07, 0x08, 0x00,
+  0x00, 0x06, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+  0x0e, 0x00, 0xe8, 0x0a, 0x0a, 0x0a, 0x00, 0x0a,
+  0xc8, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x01
+};
+
+
+void *m3ap_MCE_task(void *arg) {
+  MessageDef *received_msg = NULL;
+  int         result;
+  M3AP_DEBUG("Starting M3AP MCE layer\n");
+  m3ap_MCE_prepare_internal_data();
+  itti_mark_task_ready(TASK_M3AP_MCE);
+
+  while (1) {
+    itti_receive_msg(TASK_M3AP_MCE, &received_msg);
+
+    switch (ITTI_MSG_ID(received_msg)) {
+      case MESSAGE_TEST:
+//	LOG_W(M3AP,"MCE Received Test Message ... TODO\n");
+//	//MessageDef * message_p = itti_alloc_new_message(TASK_M3AP, MESSAGE_TEST);
+//	//itti_send_msg_to_task(TASK_M2AP_ENB, 1/*ctxt_pP->module_id*/, message_p);
+// 
+//        asn_dec_rval_t dec_ret;
+//
+//	
+//	uint8_t  *buffer;
+//  	uint32_t  len;
+//	M3AP_M3AP_PDU_t          pdu;
+//	memset(&pdu, 0, sizeof(pdu));
+//
+//	buffer = &m3ap_m3setup[0];
+//	//buffer = &m3ap_start[0];
+//  	len=8*4+7;
+//  	//len=8*9+7;
+//
+//	//if (m3ap_decode_pdu(&pdu, buffer, len) < 0) {
+//    	//	LOG_E(M3AP, "Failed to decode PDU\n");
+//    //re//turn -1;
+//  	//}
+//	M3AP_M3AP_PDU_t *pdu2 = &pdu;
+//	dec_ret = aper_decode(NULL,
+//                        &asn_DEF_M3AP_M3AP_PDU,
+//                        (void **)&pdu2,
+//                        buffer,
+//                        len,
+//                        0,
+//                        0);
+//
+//	LOG_W(M3AP,"Trying to print %d\n",(dec_ret.code == RC_OK));
+//	xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, &pdu);
+//	LOG_W(M3AP,"Trying to print out \n");
+
+        break;
+      case TERMINATE_MESSAGE:
+        M3AP_WARN(" *** Exiting M3AP thread\n");
+        itti_exit_task();
+        break;
+
+      case M3AP_SUBFRAME_PROCESS:
+        m3ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg));
+        break;
+
+      case M3AP_REGISTER_MCE_REQ:
+	        LOG_I(M3AP,"MCE Received M3AP_REGISTER_MCE_REQ Message\n");
+
+        m3ap_MCE_handle_register_MCE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M3AP_REGISTER_MCE_REQ(received_msg));
+        break;
+
+      case M3AP_MBMS_SESSION_START_RESP:
+	        LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_START_RESP Message\n");
+	MCE_send_MBMS_SESSION_START_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M3AP_MBMS_SESSION_START_RESP(received_msg));
+
+	break;
+		
+      case M3AP_MBMS_SESSION_STOP_RESP:
+	        LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_STOP_RESP Message\n");
+	MCE_send_MBMS_SESSION_STOP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M3AP_MBMS_SESSION_START_RESP(received_msg));
+
+	break;
+
+      case M3AP_MBMS_SESSION_UPDATE_RESP:
+	        LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_UPDATE_RESP Message\n");
+	//MCE_send_MBMS_SESSION_UPDATE_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     //&M3AP_MBMS_SESSION_START_RESP(received_msg));
+
+	break;
+
+	
+//      case M3AP_HANDOVER_REQ:
+//        m3ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                     &M3AP_HANDOVER_REQ(received_msg));
+//        break;
+//
+//      case M3AP_HANDOVER_REQ_ACK:
+//        m3ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                         &M3AP_HANDOVER_REQ_ACK(received_msg));
+//        break;
+//
+//      case M3AP_UE_CONTEXT_RELEASE:
+//        m3ap_eNB_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                                &M3AP_UE_CONTEXT_RELEASE(received_msg));
+//        break;
+//
+      case SCTP_INIT_MSG_MULTI_CNF:
+	        LOG_D(M3AP,"MCE Received SCTP_INIT_MSG_MULTI_CNF Message\n");
+
+        m3ap_MCE_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                                &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_RESP:
+	        LOG_D(M3AP,"MCE Received SCTP_NEW_ASSOCIATION_RESP Message\n");
+
+        m3ap_MCE_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                              &received_msg->ittiMsg.sctp_new_association_resp);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_IND:
+	        LOG_D(M3AP,"MCE Received SCTP_NEW_ASSOCIATION Message\n");
+
+        m3ap_MCE_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                             &received_msg->ittiMsg.sctp_new_association_ind);
+        break;
+
+      case SCTP_DATA_IND:
+	        LOG_D(M3AP,"MCE Received SCTP_DATA_IND Message\n");
+
+        m3ap_MCE_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                      &received_msg->ittiMsg.sctp_data_ind);
+        break;
+
+      default:
+        M3AP_ERROR("Received unhandled message: %d:%s\n",
+                   ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
+        break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    received_msg = NULL;
+  }
+
+  return NULL;
+}
+
+#include "common/config/config_userapi.h"
+
+int is_m3ap_MCE_enabled(void)
+{
+  static volatile int config_loaded = 0;
+  static volatile int enabled = 0;
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+  if (pthread_mutex_lock(&mutex)) goto mutex_error;
+
+  if (config_loaded) {
+    if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+    return enabled;
+  }
+
+  char *enable_m3 = NULL;
+  paramdef_t p[] = {
+   { "enable_mce_m3", "yes/no", 0, strptr:&enable_m3, defstrval:"", TYPE_STRING, 0 }
+  };
+
+  /* TODO: do it per module - we check only first MCE */
+  config_get(p, sizeof(p)/sizeof(paramdef_t), "MCEs.[0]");
+  if (enable_m3 != NULL && strcmp(enable_m3, "yes") == 0)
+    enabled = 1;
+
+  config_loaded = 1;
+
+  if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+
+  return enabled;
+
+mutex_error:
+  LOG_E(M3AP, "mutex error\n");
+  exit(1);
+}
diff --git a/openair3/M3AP/m3ap_MCE.h b/openair3/M3AP/m3ap_MCE.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a617776e3d7578bbc883ccfd59ebbc91185d62b
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB.h
+ * \brief m3ap tasks for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+/** @defgroup _m3ap_impl_ M3AP Layer Reference Implementation
+ * @ingroup _ref_implementation_
+ * @{
+ */
+
+#ifndef M3AP_MCE_H_
+#define M3AP_MCE_H_
+
+#include "m3ap_MCE_defs.h"
+
+
+int m3ap_MCE_init_sctp (m3ap_MCE_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t mce_port_for_M3C);
+
+void *m3ap_MCE_task(void *arg);
+
+int is_m3ap_MCE_enabled(void);
+
+#endif /* M3AP_H_ */
+
+/**
+ * @}
+ */
diff --git a/openair3/M3AP/m3ap_MCE_defs.h b/openair3/M3AP/m3ap_MCE_defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..18ad70a408b50739aedae4fa13ffee03711b2238
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_defs.h
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_defs.h
+ * \brief m3ap struct definitions for MCE
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "queue.h"
+#include "tree.h"
+
+#include "sctp_eNB_defs.h"
+
+#include "m3ap_ids.h" //looks X2AP specific for HO
+#include "m3ap_timers.h"
+
+#ifndef M3AP_MCE_DEFS_H_
+#define M3AP_MCE_DEFS_H_
+
+#define M3AP_MCE_NAME_LENGTH_MAX    (150)
+
+typedef enum {
+  /* Disconnected state: initial state for any association. */
+  M3AP_MCE_STATE_DISCONNECTED = 0x0,
+
+  /* State waiting for m2 Setup response message if the target MCE accepts or
+   * M3 Setup failure if rejects the MCE.
+   */
+  M3AP_MCE_STATE_WAITING     = 0x1,
+
+  /* The MCE is successfully connected to another MCE. */
+  M3AP_MCE_STATE_CONNECTED   = 0x2,
+
+  /* M3AP is ready, and the MCE is successfully connected to another MCE. */
+  M3AP_MCE_STATE_READY             = 0x3,
+
+  M3AP_MCE_STATE_OVERLOAD          = 0x4,
+
+  M3AP_MCE_STATE_RESETTING         = 0x5,
+
+  /* Max number of states available */
+  M3AP_MCE_STATE_MAX,
+} m3ap_MCE_state_t;
+
+/* Served PLMN identity element */
+/*struct plmn_identity_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+  STAILQ_ENTRY(plmn_identity_s) next;
+};*/
+
+/* Served group id element */
+/*struct served_group_id_s {
+  uint16_t mce_group_id;
+  STAILQ_ENTRY(served_group_id_s) next;
+};*/
+
+/* Served enn code for a particular MCE */
+/*struct mce_code_s {
+  uint8_t mce_code;
+  STAILQ_ENTRY(mce_code_s) next;
+};*/
+
+struct m3ap_MCE_instance_s;
+
+/* This structure describes association of a MCE to another MCE */
+typedef struct m3ap_MCE_data_s {
+  /* MCE descriptors tree, ordered by sctp assoc id */
+  RB_ENTRY(m3ap_MCE_data_s) entry;
+
+  /* This is the optional name provided by the MME */
+  char *MCE_name;
+
+  /*  target MCE ID */
+  uint32_t MCE_id;
+
+  /* Current MCE load information (if any). */
+  //m3ap_load_state_t overload_state;
+
+  /* Current MCE->MCE M3AP association state */
+  m3ap_MCE_state_t state;
+
+  /* Next usable stream for UE signalling */
+  int32_t nextstream;
+
+  /* Number of input/ouput streams */
+  uint16_t in_streams;
+  uint16_t out_streams;
+
+  /* Connexion id used between SCTP/M3AP */
+  uint16_t cnx_id;
+
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* Nid cells */
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* Only meaningfull in virtual mode */
+  struct m3ap_MCE_instance_s *m3ap_MCE_instance;
+} m3ap_MCE_data_t;
+
+typedef struct m3ap_MCE_instance_s {
+  /* used in simulation to store multiple MCE instances*/
+  STAILQ_ENTRY(m3ap_MCE_instance_s) m3ap_MCE_entries;
+
+  /* Number of target MCEs requested by MCE (tree size) */
+  uint32_t m3_target_mme_nb;
+  /* Number of target MCEs for which association is pending */
+  uint32_t m3_target_mme_pending_nb;
+  /* Number of target MCE successfully associated to MCE */
+  uint32_t m3_target_mme_associated_nb;
+  /* Tree of M3AP MCE associations ordered by association ID */
+  RB_HEAD(m3ap_mce_map, m3ap_MCE_data_s) m3ap_mce_head;
+
+  /* Tree of UE ordered by MCE_ue_m3ap_id's */
+  //  RB_HEAD(m3ap_ue_map, m3ap_MCE_ue_context_s) m3ap_ue_head;
+
+  /* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
+  instance_t instance;
+
+  /* Displayable name of MCE */
+  char *MCE_name;
+
+  /* Unique MCE_id to identify the MCE within EPC.
+   * In our case the MCE is a macro MCE so the id will be 20 bits long.
+   * For Home MCE id, this field should be 28 bits long.
+   */
+  uint32_t MCE_id;
+  /* The type of the cell */
+  cell_type_t cell_type;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t  mcc;
+  uint16_t  mnc;
+  uint8_t   mnc_digit_length;
+
+  /* CC params */
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int16_t                 N_RB_DL[MAX_NUM_CCs];
+  lte_frame_type_t        frame_type[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
+  net_ip_address_t target_mme_m3_ip_address[M3AP_MAX_NB_MCE_IP_ADDRESS];
+  uint8_t          nb_m3;
+  net_ip_address_t mme_m3_ip_address;
+  uint16_t         sctp_in_streams;
+  uint16_t         sctp_out_streams;
+  uint32_t         mce_port_for_M3C;
+  int              multi_sd;
+
+  m3ap_id_manager  id_manager;
+  m3ap_timers_t    timers;
+} m3ap_MCE_instance_t;
+
+typedef struct {
+  /* List of served MCEs
+   * Only used for virtual mode
+   */
+  STAILQ_HEAD(m3ap_MCE_instances_head_s, m3ap_MCE_instance_s) m3ap_MCE_instances_head;
+  /* Nb of registered MCEs */
+  uint8_t nb_registered_MCEs;
+
+  /* Generate a unique connexion id used between M3AP and SCTP */
+  uint16_t global_cnx_id;
+} m3ap_MCE_internal_data_t;
+
+int m3ap_MCE_compare_assoc_id(struct m3ap_MCE_data_s *p1, struct m3ap_MCE_data_s *p2);
+
+/* Generate the tree management functions */
+struct m3ap_MCE_map;
+struct m3ap_MCE_data_s;
+RB_PROTOTYPE(m3ap_MCE_map, m3ap_MCE_data_s, entry, m3ap_MCE_compare_assoc_id);
+
+
+#endif /* M3AP_MCE_DEFS_H_ */
diff --git a/openair3/M3AP/m3ap_MCE_generate_messages.h b/openair3/M3AP/m3ap_MCE_generate_messages.h
new file mode 100644
index 0000000000000000000000000000000000000000..0884e8216e0c2d1df0126674080321a19005ff98
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_generate_messages.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_generate_messages.h
+ * \brief m2ap procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_ENB_GENERATE_MESSAGES_H_
+#define M2AP_ENB_GENERATE_MESSAGES_H_
+
+#include "m2ap_eNB_defs.h"
+#include "m2ap_common.h"
+
+int m2ap_eNB_generate_m2_setup_request(m2ap_eNB_instance_t *instance_p,
+				       m2ap_eNB_data_t *m2ap_eNB_data_p);
+
+int m2ap_MCE_generate_m2_setup_response(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p);
+
+/*int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait);*/
+
+int m2ap_eNB_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value);
+
+//int m2ap_eNB_generate_m2_handover_request (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id);
+//
+//int m2ap_eNB_generate_m2_handover_request_ack (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack);
+//
+//int m2ap_eNB_generate_m2_ue_context_release (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                             m2ap_ue_context_release_t *m2ap_ue_context_release);
+//
+//int m2ap_eNB_generate_m2_handover_cancel (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause);
+
+#endif /*  M2AP_ENB_GENERATE_MESSAGES_H_ */
diff --git a/openair3/M3AP/m3ap_MCE_generate_messsages.c b/openair3/M3AP/m3ap_MCE_generate_messsages.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d8c7f385340b82e12416632ee1640d89004a167
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_generate_messsages.c
@@ -0,0 +1,808 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_generate_messages.c
+ * \brief m2ap procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+//#include "M2AP_LastVisitedCell-Item.h"
+
+#include "m2ap_common.h"
+#include "m2ap_eNB.h"
+#include "m2ap_eNB_generate_messages.h"
+#include "m2ap_encoder.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+#include "m2ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+int m2ap_eNB_generate_m2_setup_request(
+  m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p)
+{
+  module_id_t enb_mod_idP=0;
+  module_id_t du_mod_idP=0;
+
+  M2AP_M2AP_PDU_t          pdu;
+  M2AP_M2SetupRequest_t    *out;
+  M2AP_M2SetupRequest_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       i = 0;
+  int       j = 0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_M2SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M2SetupRequest;
+
+  /* mandatory */
+  /* c1. GlobalENB_ID (integer value) */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_GlobalENB_ID;
+  //ie->value.choice.GlobalENB_ID.eNB_ID = 1;//M2AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);
+  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                  &ie->value.choice.GlobalENB_ID.pLMN_Identity);
+  ie->value.choice.GlobalENB_ID.eNB_ID.present = M2AP_ENB_ID_PR_macro_eNB_ID;
+  MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
+                           &ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
+  M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
+          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  ///* mandatory */
+  ///* c2. GNB_eNB_ID (integrer value) */
+  //ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id                        = M2AP_ProtocolIE_ID_id_gNB_eNB_ID;
+  //ie->criticality               = M2AP_Criticality_reject;
+  //ie->value.present             = M2AP_M2SetupRequestIEs__value_PR_GNB_eNB_ID;
+  //asn_int642INTEGER(&ie->value.choice.GNB_eNB_ID, f1ap_du_data->gNB_eNB_id);
+  //ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional */
+  /* c3. ENBname */
+  if (m2ap_eNB_data_p->eNB_name != NULL) {
+    ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+    ie->id                        = M2AP_ProtocolIE_ID_id_ENBname;
+    ie->criticality               = M2AP_Criticality_ignore;
+    ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_ENBname;
+    //OCTET_STRING_fromBuf(&ie->value.choice.ENB_Name, m2ap_eNB_data_p->eNB_name,
+                         //strlen(m2ap_eNB_data_p->eNB_name));
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */
+  /* c4. serverd cells list */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_List;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_ENB_MBMS_Configuration_data_List;
+
+  int num_mbms_available = 1;//m2ap_du_data->num_mbms_available;
+  LOG_D(M2AP, "num_mbms_available = %d \n", num_mbms_available);
+
+ for (i=0;
+       i<num_mbms_available;
+       i++) {
+        /* mandatory */
+        /* 4.1 serverd cells item */
+
+        M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *mbms_configuration_data_list_item_ies;
+        mbms_configuration_data_list_item_ies = (M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *)calloc(1, sizeof(M2AP_ENB_MBMS_Configuration_data_ItemIEs_t));
+        mbms_configuration_data_list_item_ies->id = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_Item;
+        mbms_configuration_data_list_item_ies->criticality = M2AP_Criticality_reject;
+        mbms_configuration_data_list_item_ies->value.present = M2AP_ENB_MBMS_Configuration_data_ItemIEs__value_PR_ENB_MBMS_Configuration_data_Item;
+
+	M2AP_ENB_MBMS_Configuration_data_Item_t *mbms_configuration_data_item;
+	mbms_configuration_data_item = &mbms_configuration_data_list_item_ies->value.choice.ENB_MBMS_Configuration_data_Item;
+	{
+		MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                  &mbms_configuration_data_item->eCGI.pLMN_Identity);
+        	MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
+                                   &mbms_configuration_data_item->eCGI.eUTRANcellIdentifier);
+		M2AP_MBMS_Service_Area_t * mbms_service_area;
+		mbms_service_area = (M2AP_MBMS_Service_Area_t*)calloc(1,sizeof(M2AP_MBMS_Service_Area_t));
+		ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area);
+
+
+	}
+
+
+        //M2AP_ENB_MBMS_Configuration_data_Item_t mbms_configuration_data_item;
+        //memset((void *)&mbms_configuration_data_item, 0, sizeof(M2AP_ENB_MBMS_Configuration_data_Item_t));
+	
+	//M2AP_ECGI_t      eCGI;
+		//M2AP_PLMN_Identity_t     pLMN_Identity;
+		//M2AP_EUTRANCellIdentifier_t      eUTRANcellIdentifier
+	//M2AP_MBSFN_SynchronisationArea_ID_t      mbsfnSynchronisationArea;
+	//M2AP_MBMS_Service_Area_ID_List_t         mbmsServiceAreaList;
+
+
+	ASN_SEQUENCE_ADD(&ie->value.choice.ENB_MBMS_Configuration_data_List.list,mbms_configuration_data_list_item_ies);
+
+ }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  LOG_W(M2AP,"m2ap_eNB_data_p->assoc_id %d\n",m2ap_eNB_data_p->assoc_id);
+  /* encode */
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 setup request\n");
+    return -1;
+  }
+
+ 
+  LOG_W(M2AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M2AP_eNB,
+ // MSC_M2AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M2_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m2ap_eNB_data_p->ENBname);
+
+  m2ap_eNB_itti_send_sctp_data_req(instance_p, m2ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return 0;
+
+
+}
+
+//int m2ap_MCE_generate_m2_setup_response(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p)
+//{
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_M2SetupResponse_t              *out;
+//  M2AP_M2SetupResponse_Ies_t          *ie;
+//  //M2AP_PLMN_Identity_t                *plmn;
+//  //ServedCells__Member                 *servedCellMember;
+//  //M2AP_GU_Group_ID_t                  *gu;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  /* Prepare the M2AP message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_M2SetupResponse;
+//  out = &pdu.choice.successfulOutcome.value.choice.M2SetupResponse;
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GlobalENB_ID;
+//  //MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//  //                  &ie->value.choice.GlobalENB_ID.pLMN_Identity);
+//  //ie->value.choice.GlobalENB_ID.eNB_ID.present = M2AP_ENB_ID_PR_macro_eNB_ID;
+//  //MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
+//  //                           &ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
+//  //M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
+//  //          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
+//  //          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
+//  //          ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_ServedCells;
+//  //{
+//  //  for (int i = 0; i<instance_p->num_cc; i++){
+//  //    servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
+//  //    {
+//  //      servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
+//
+//  //      MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//  //                    &servedCellMember->servedCellInfo.cellId.pLMN_Identity);
+//  //      MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
+//  //                                 &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+//
+//  //      INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+//  //      plmn = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_PLMN_Identity_t));
+//  //      {
+//  //        MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
+//  //        ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
+//  //      }
+//
+//  //      if (instance_p->frame_type[i] == FDD) {
+//  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = M2AP_EUTRA_Mode_Info_PR_fDD;
+//  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
+//  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
+//  //        switch (instance_p->N_RB_DL[i]) {
+//  //          case 6:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+//  //            break;
+//  //          case 15:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+//  //            break;
+//  //          case 25:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+//  //            break;
+//  //          case 50:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+//  //            break;
+//  //          case 75:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+//  //            break;
+//  //          case 100:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+//  //            break;
+//  //          default:
+//  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+//  //            break;
+//  //        }
+//  //      }
+//  //      else {
+//  //        AssertFatal(0,"M2Setupresponse not supported for TDD!");
+//  //      }
+//  //    }
+//  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+//  //  }
+//  //}
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GUGroupIDList;
+//  //{
+//  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_GU_Group_ID_t));
+//  //  {
+//  //    MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//  //                  &gu->pLMN_Identity);
+//  //    //@TODO: consider to update this value
+//  //    INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
+//  //  }
+//  //  ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
+//  //}
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode M2 setup response\n");
+//    return -1;
+//  }
+//
+//  m2ap_eNB_data_p->state = M2AP_ENB_STATE_READY;
+//
+//  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 M2Setup/successfulOutcome assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 0);
+//
+//  return ret;
+//}
+
+//int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+//                                       uint32_t assoc_id,
+//                                       M2AP_Cause_PR cause_type,
+//                                       long cause_value,
+//                                       long time_to_wait)
+//{
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_M2SetupFailure_t              *out;
+//  M2AP_M2SetupFailure_Ies_t          *ie;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  /* Prepare the M2AP message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+//  pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+//  pdu.choice.unsuccessfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+//  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  //ie->criticality = M2AP_Criticality_ignore;
+//  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_Cause;
+//
+//  //m2ap_eNB_set_cause (&ie->value.choice.Cause, cause_type, cause_value);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional: consider to handle this later */
+//  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_TimeToWait;
+//  //ie->criticality = M2AP_Criticality_ignore;
+//  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_TimeToWait;
+//
+//  //if (time_to_wait > -1) {
+//  //  ie->value.choice.TimeToWait = time_to_wait;
+//  //}
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode M2 setup failure\n");
+//    return -1;
+//  }
+//
+//  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB,
+//  //                    MSC_M2AP_TARGET_ENB, NULL, 0,
+//  //                    "0 M2Setup/unsuccessfulOutcome  assoc_id %u cause %u value %u",
+//  //                    assoc_id, cause_type, cause_value);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
+//
+//  return ret;
+//}
+
+int m2ap_eNB_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value)
+{
+
+  DevAssert (cause_p != NULL);
+  cause_p->present = cause_type;
+
+  switch (cause_type) {
+  case M2AP_Cause_PR_radioNetwork:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_transport:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_protocol:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_misc:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+//int m2ap_eNB_generate_m2_handover_request (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id)
+//{
+//
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_HandoverRequest_t              *out;
+//  M2AP_HandoverRequest_IEs_t          *ie;
+//  M2AP_E_RABs_ToBeSetup_ItemIEs_t     *e_RABS_ToBeSetup_ItemIEs;
+//  M2AP_E_RABs_ToBeSetup_Item_t        *e_RABs_ToBeSetup_Item;
+//  M2AP_LastVisitedCell_Item_t         *lastVisitedCell_Item;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverRequest;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_Cause;
+//  ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetCell_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_ECGI;
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &ie->value.choice.ECGI.pLMN_Identity);
+//  MACRO_ENB_ID_TO_CELL_IDENTITY(m2ap_eNB_data_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_GUMMEI_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_GUMMEI;
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &ie->value.choice.GUMMEI.gU_Group_ID.pLMN_Identity);
+//  //@TODO: consider to update these values
+//  INT16_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
+//  MME_CODE_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_ContextInformation;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
+//  //@TODO: consider to update this value
+//  ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = m2ap_handover_req->mme_ue_s1ap_id;
+//
+//  KENB_STAR_TO_BIT_STRING(m2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
+//
+//  if (m2ap_handover_req->kenb_ncc >=0) { // Check this condition
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = m2ap_handover_req->kenb_ncc;
+//  }
+//  else {
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
+//  }
+//
+//  ENCRALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.encryption_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+//
+//  INTPROTALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.integrity_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
+//
+//  //@TODO: update with proper UEAMPR
+//  UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
+//  UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
+//  {
+//    for (int i=0;i<m2ap_handover_req->nb_e_rabs_tobesetup;i++) {
+//      e_RABS_ToBeSetup_ItemIEs = (M2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_ToBeSetup_ItemIEs_t));
+//      e_RABS_ToBeSetup_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
+//      e_RABS_ToBeSetup_ItemIEs->criticality = M2AP_Criticality_ignore;
+//      e_RABS_ToBeSetup_ItemIEs->value.present = M2AP_E_RABs_ToBeSetup_ItemIEs__value_PR_E_RABs_ToBeSetup_Item;
+//      e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
+//      {
+//        e_RABs_ToBeSetup_Item->e_RAB_ID = m2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = m2ap_handover_req->e_rab_param[i].qos.qci;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(m2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length/8);
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = m2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length%8;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf =
+//                        calloc(1,e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        memcpy (e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
+//                        m2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.buffer,
+//                        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        INT32_TO_OCTET_STRING(m2ap_handover_req->e_rabs_tobesetup[i].gtp_teid,&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID);
+//      }
+//      ASN_SEQUENCE_ADD(&ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list, e_RABS_ToBeSetup_ItemIEs);
+//    }
+//  }
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.UE_ContextInformation.rRC_Context, (char*) m2ap_handover_req->rrc_buffer, m2ap_handover_req->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_HistoryInformation;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
+//  //@TODO: consider to update this value
+//  {
+//   lastVisitedCell_Item = (M2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(M2AP_LastVisitedCell_Item_t));
+//   lastVisitedCell_Item->present = M2AP_LastVisitedCell_Item_PR_e_UTRAN_Cell;
+//   MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
+//   MACRO_ENB_ID_TO_CELL_IDENTITY(0, 0, &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
+//   lastVisitedCell_Item->choice.e_UTRAN_Cell.cellType.cell_Size = M2AP_Cell_Size_small;
+//   lastVisitedCell_Item->choice.e_UTRAN_Cell.time_UE_StayedInCell = 2;
+//   ASN_SEQUENCE_ADD(&ie->value.choice.UE_HistoryInformation.list, lastVisitedCell_Item);
+//  }
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover request\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_handover_request_ack (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack)
+//{
+//
+//  M2AP_M2AP_PDU_t                        pdu;
+//  M2AP_HandoverRequestAcknowledge_t      *out;
+//  M2AP_HandoverRequestAcknowledge_IEs_t  *ie;
+//  M2AP_E_RABs_Admitted_ItemIEs_t         *e_RABS_Admitted_ItemIEs;
+//  M2AP_E_RABs_Admitted_Item_t            *e_RABs_Admitted_Item;
+//  int                                    ue_id;
+//  int                                    id_source;
+//  int                                    id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id     = m2ap_handover_req_ack->m2_id_target;
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
+//  out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
+//
+//  {
+//      for (int i=0;i<m2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
+//        e_RABS_Admitted_ItemIEs = (M2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_Admitted_ItemIEs_t));
+//        e_RABS_Admitted_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
+//        e_RABS_Admitted_ItemIEs->criticality = M2AP_Criticality_ignore;
+//        e_RABS_Admitted_ItemIEs->value.present = M2AP_E_RABs_Admitted_ItemIEs__value_PR_E_RABs_Admitted_Item;
+//        e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
+//        {
+//          e_RABs_Admitted_Item->e_RAB_ID = m2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
+//        }
+//        ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_List.list, e_RABS_Admitted_ItemIEs);
+//      }
+//  }
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_TargeteNBtoSource_eNBTransparentContainer;
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.TargeteNBtoSource_eNBTransparentContainer, (char*) m2ap_handover_req_ack->rrc_buffer, m2ap_handover_req_ack->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover response\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_ue_context_release (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p, m2ap_ue_context_release_t *m2ap_ue_context_release)
+//{
+//
+//  M2AP_M2AP_PDU_t                pdu;
+//  M2AP_UEContextRelease_t        *out;
+//  M2AP_UEContextRelease_IEs_t    *ie;
+//  int                            ue_id;
+//  int                            id_source;
+//  int                            id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id = m2ap_find_id_from_rnti(&instance_p->id_manager, m2ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not find UE %x\n", m2ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP ue context relase message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_uEContextRelease;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_UEContextRelease;
+//  out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 UE Context Release\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_handover_cancel (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause)
+//{
+//  M2AP_M2AP_PDU_t              pdu;
+//  M2AP_HandoverCancel_t        *out;
+//  M2AP_HandoverCancel_IEs_t    *ie;
+//  int                          ue_id;
+//  int                          id_source;
+//  int                          id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id = m2_ue_id;
+//  id_source = ue_id;
+//  id_target = m2ap_id_get_id_target(&instance_p->id_manager, ue_id);
+//
+//  /* Prepare the M2AP handover cancel message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverCancel;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverCancel;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  if (id_target != -1) {
+//    ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//    ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//    ie->criticality = M2AP_Criticality_ignore;
+//    ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID_1;
+//    ie->value.choice.UE_M2AP_ID_1 = id_target;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_Cause;
+//  switch (cause) {
+//  case M2AP_T_RELOC_PREP_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_trelocprep_expiry;
+//    break;
+//  case M2AP_TX2_RELOC_OVERALL_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_tx2relocoverall_expiry;
+//    break;
+//  default:
+//    /* we can't come here */
+//    M2AP_ERROR("unhandled cancel cause\n");
+//    exit(1);
+//  }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 Handover Cancel\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
diff --git a/openair3/M3AP/m3ap_MCE_handler.c b/openair3/M3AP/m3ap_MCE_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..e733af28db32eea0fc9b42c0d49a5ea702a73500
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_handler.c
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_handler.c
+ * \brief m3ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_handler.h"
+#include "m3ap_decoder.h"
+#include "m3ap_ids.h"
+
+//#include "m3ap_MCE_management_procedures.h"
+#include "m3ap_MCE_generate_messages.h"
+
+//#include "m3ap_MME_interface_management.h"
+#include "m3ap_MCE_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m3ap_MCE_message_decoded_callback m3ap_MCE_messages_callback[][3] = {
+  { MCE_handle_MBMS_SESSION_START_REQUEST, 0, 0 }, /* MBMSSessionStart  */
+  { MCE_handle_MBMS_SESSION_STOP_REQUEST, 0, 0 }, /* MBMSSessionStop */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { 0, 0, 0 }, /* ??? */
+  { MCE_handle_MBMS_SESSION_UPDATE_REQUEST, 0, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { 0, MCE_handle_M3_SETUP_RESPONSE, 0 } /* M3 Setup */
+};
+
+static char *m3ap_direction2String(int m3ap_dir) {
+static char *m3ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m3ap_direction_String[m3ap_dir]);
+}
+
+
+int m3ap_MCE_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M3AP_M3AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  if (m3ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M3AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m3ap_MCE_messages_callback) / (3 * sizeof(
+        m3ap_message_decoded_callback))
+      || (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M3AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
+               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m3ap_MCE_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M3AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m3ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M3AP, "Calling handler with instance %d\n",instance);
+  ret = (*m3ap_MCE_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair3/M3AP/m3ap_MCE_handler.h b/openair3/M3AP/m3ap_MCE_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce4997e80d7d95b1acf08ad8c64a149aa3405f65
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_handler.h
+ * \brief m2ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_HANDLERS_H_
+#define M2AP_MCE_HANDLERS_H_
+
+#include "m2ap_MCE_defs.h"
+
+//void m3ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+//int m3ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            //const uint8_t * const data, const uint32_t data_length);
+
+int m3ap_MCE_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M2AP_MCE_HANDLERS_H_ */
diff --git a/openair3/M3AP/m3ap_MCE_interface_management.c b/openair3/M3AP/m3ap_MCE_interface_management.c
new file mode 100644
index 0000000000000000000000000000000000000000..2694846526373cfe9db8c6f81c4cebba74eca94e
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_interface_management.c
@@ -0,0 +1,756 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_interface_management.c
+ * \brief m3ap interface management for MCE
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "intertask_interface.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MCE.h"
+//#include "m3ap_MCE_generate_messages.h"
+#include "m3ap_encoder.h"
+#include "m3ap_decoder.h"
+#include "m3ap_ids.h"
+
+#include "m3ap_MCE_interface_management.h"
+
+
+#include "m3ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+
+//#include "m3ap_common.h"
+//#include "m3ap_encoder.h"
+//#include "m3ap_decoder.h"
+//#include "m3ap_itti_messaging.h"
+//#include "m3ap_MCE_interface_management.h"
+//#include "assertions.h"
+
+extern m3ap_setup_req_t * m3ap_mce_data_g;
+
+
+int MCE_handle_MBMS_SESSION_START_REQUEST(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M3AP_M3AP_PDU_t *pdu){
+//  LOG_W(M3AP, "MCE_handle_MBMS_SESSION_START_REQUEST assoc_id %d\n",assoc_id);
+//
+    MessageDef                         *message_p;
+//  M3AP_SessionStartRequest_t              *container;
+//  M3AP_SessionStartRequest_Ies_t           *ie;
+//  int i = 0;
+//
+//  DevAssert(pdu != NULL);
+//
+//  container = &pdu->choice.initiatingMessage.value.choice.SessionStartRequest;
+
+    message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_START_REQ);
+
+//
+//  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+//  if (stream != 0) {
+//    LOG_W(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+//              assoc_id, stream);
+//  }
+//
+
+    itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+//  if(1){
+//	MCE_send_MBMS_SESSION_START_RESPONSE(instance,assoc_id);
+//  }else
+//	MCE_send_MBMS_SESSION_START_FAILURE(instance,assoc_id);
+  return 0;
+  
+}
+
+int MCE_send_MBMS_SESSION_START_RESPONSE(instance_t instance, m3ap_session_start_resp_t * m3ap_session_start_resp){
+  //AssertFatal(1==0,"Not implemented yet\n");
+
+//	module_id_t mce_mod_idP;
+//  module_id_t enb_mod_idP;
+//
+//  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+//
+  M3AP_M3AP_PDU_t           pdu;
+  M3AP_MBMSSessionStartResponse_t    *out;
+  M3AP_MBMSSessionStartResponse_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M3AP_SuccessfulOutcome_t *)calloc(1, sizeof(M3AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_mBMSsessionStart;
+  pdu.choice.successfulOutcome.criticality   = M3AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_MBMSSessionStartResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.MBMSSessionStartResponse;
+  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStartResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MME_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStartResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartResponse_IEs__value_PR_MME_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M3AP, "Failed to encode M3 SessionStart Response\n");
+    return -1;
+  }
+//
+//
+//  LOG_W(M3AP,"pdu.present %d\n",pdu.present);
+// // MSC_LOG_TX_MESSAGE(
+// // MSC_M3AP_MCE,
+// // MSC_M3AP_MCE,
+// // (const char *)buffer,
+// // len,
+// // MSC_AS_TIME_FMT" M3_SETUP_REQUEST initiatingMessage MCEname %s",
+// // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+// // m3ap_MCE_data_p->MCEname);
+//
+   m3ap_MCE_itti_send_sctp_data_req(instance, m3ap_mce_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+
+
+int MCE_send_MBMS_SESSION_START_FAILURE(instance_t instance, m3ap_session_start_failure_t * m3ap_session_start_failure){
+//  module_id_t enb_mod_idP;
+//  module_id_t mce_mod_idP;
+//
+//  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+//
+//  M3AP_M3AP_PDU_t           pdu;
+//  M3AP_SessionStartFailure_t    *out;
+//  M3AP_SessionStartFailure_Ies_t *ie;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//
+//  /* Create */
+//  /* 0. Message Type */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M3AP_M3AP_PDU_PR_unsuccessfulOutcome;
+//  //pdu.choice.unsuccessfulOutcome = (M3AP_UnsuccessfulOutcome_t *)calloc(1, sizeof(M3AP_UnsuccessfulOutcome_t));
+//  pdu.choice.unsuccessfulOutcome.procedureCode = M3AP_ProcedureCode_id_sessionStart;
+//  pdu.choice.unsuccessfulOutcome.criticality   = M3AP_Criticality_reject;
+//  pdu.choice.unsuccessfulOutcome.value.present = M3AP_UnsuccessfulOutcome__value_PR_SessionStartFailure;
+//  out = &pdu.choice.unsuccessfulOutcome.value.choice.SessionStartFailure;
+//
+//  /* mandatory */
+//  /* c1. Transaction ID (integer value)*/
+// // ie = (M3AP_M3SetupFailure_Ies_t *)calloc(1, sizeof(M3AP_M3SetupFailure_Ies_t));
+// // ie->id                        = M3AP_ProtocolIE_ID_id_GlobalMCE_ID;
+// // ie->criticality               = M3AP_Criticality_reject;
+// // ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_GlobalMCE_ID;
+// // ie->value.choice.GlobalMCE_ID = M3AP_get_next_transaction_identifier(enb_mod_idP, mce_mod_idP);
+// // ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  /* c2. Cause */
+//  ie = (M3AP_M3SetupFailure_Ies_t *)calloc(1, sizeof(M3AP_SessionStartFailure_Ies_t));
+//  ie->id                        = M3AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality               = M3AP_Criticality_ignore;
+//  ie->value.present             = M3AP_SessionStartFailure_Ies__value_PR_Cause;
+//  ie->value.choice.Cause.present = M3AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M3AP_CauseRadioNetwork_unspecified;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//
+//     /* encode */
+//  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    LOG_E(M3AP, "Failed to encode M3 setup request\n");
+//    return -1;
+//  }
+//
+//  //mce_m3ap_itti_send_sctp_data_req(instance, m3ap_mce_data_from_enb->assoc_id, buffer, len, 0);
+//  m3ap_MCE_itti_send_sctp_data_req(instance,assoc_id,buffer,len,0);
+//
+
+  return 0;
+}
+
+int MCE_handle_MBMS_SESSION_STOP_REQUEST(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M3AP_M3AP_PDU_t *pdu){
+
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "MCE_handle_MBMS_SESSION_STOP_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M3AP_MBMSSessionStopRequest_t              *container;
+  //M3AP_MBMSSessionStopRequest_IEs_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.MBMSSessionStopRequest;
+
+  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_W(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  //if(1){
+	//MCE_send_MBMS_SESSION_STOP_RESPONSE(instance,assoc_id);
+  //}else
+	//MCE_send_MBMS_SESSION_STOP_FAILURE(instance,assoc_id);
+    message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_STOP_REQ);
+
+//
+//  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+//  if (stream != 0) {
+//    LOG_W(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+//              assoc_id, stream);
+//  }
+//
+
+    itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+
+  return 0;
+  
+}
+int MCE_send_MBMS_SESSION_STOP_RESPONSE(instance_t instance, m3ap_session_start_resp_t * m3ap_session_start_resp){
+//	module_id_t mce_mod_idP;
+//  module_id_t enb_mod_idP;
+//
+//  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+//
+  M3AP_M3AP_PDU_t           pdu;
+  M3AP_MBMSSessionStopResponse_t    *out;
+  M3AP_MBMSSessionStopResponse_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M3AP_SuccessfulOutcome_t *)calloc(1, sizeof(M3AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_mBMSsessionStop;
+  pdu.choice.successfulOutcome.criticality   = M3AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_MBMSSessionStopResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.MBMSSessionStopResponse;
+  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStopResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStopResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStopResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStopResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStopResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStopResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M3AP, "Failed to encode M3 SessionStop Response\n");
+    return -1;
+  }
+
+
+  LOG_D(M3AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M3AP_MCE,
+ // MSC_M3AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M3_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m3ap_MCE_data_p->MCEname);
+
+  m3ap_MCE_itti_send_sctp_data_req(instance, m3ap_mce_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+
+/*
+ * Session Update
+ */
+int MCE_handle_MBMS_SESSION_UPDATE_REQUEST(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M3AP_M3AP_PDU_t *pdu)
+{
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "MCE_handle_MBMS_SESSION_UPDATE_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M3AP_MBMSSessionUpdateRequest_t              *container;
+  //M3AP_MBMSSessionUpdateRequest_IEs_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.MBMSSessionUpdateRequest;
+
+  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  //if(1){
+	//MCE_send_MBMS_SESSION_STOP_RESPONSE(instance,assoc_id);
+  //}else
+	//MCE_send_MBMS_SESSION_STOP_FAILURE(instance,assoc_id);
+    message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_UPDATE_REQ);
+
+//
+//  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+//  if (stream != 0) {
+//    LOG_W(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+//              assoc_id, stream);
+//  }
+//
+
+    itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+
+
+	return 0;
+}
+
+int MCE_send_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, m3ap_mbms_session_update_resp_t * m3ap_mbms_session_update_resp){
+  M3AP_M3AP_PDU_t           pdu;
+  M3AP_MBMSSessionUpdateResponse_t    *out;
+  M3AP_MBMSSessionUpdateResponse_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M3AP_SuccessfulOutcome_t *)calloc(1, sizeof(M3AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_mBMSsessionUpdate;
+  pdu.choice.successfulOutcome.criticality   = M3AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_MBMSSessionUpdateResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.MBMSSessionUpdateResponse;
+  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionUpdateResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionUpdateResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M3AP, "Failed to encode M3 SessionUpdate Response\n");
+    return -1;
+  }
+
+
+  LOG_D(M3AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M3AP_MCE,
+ // MSC_M3AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M3_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m3ap_MCE_data_p->MCEname);
+
+  m3ap_MCE_itti_send_sctp_data_req(instance, m3ap_mce_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+int MCE_send_MBMS_SESSION_UPDATE_FAILURE(instance_t instance, m3ap_mbms_session_update_failure_t * m3ap_mbms_session_update_failure){
+	return 0;
+}
+
+/*
+    M3 Setup
+*/
+
+//uint8_t m3ap_m3setup_message[] = {0x00,0x07,0x00,0x23,0x00,0x00,0x03,0x00,0x12,0x00,0x07,0x40,0x55,0xf5,0x01,0x00,0x25,0x00,0x00,0x13,0x40,0x0a,0x03,0x80,0x4d,0x33,0x2d,0x65,0x4e,0x42,0x33,0x37,0x00,0x14,0x00,0x03,0x01,0x00,0x01};
+uint8_t m3ap_m3setup_message[] = {
+  0x00, 0x07, 0x00, 0x23, 0x00, 0x00, 0x03, 0x00,
+  0x12, 0x00, 0x07, 0x40, 0x55, 0xf5, 0x01, 0x00,
+  0x25, 0x00, 0x00, 0x13, 0x40, 0x0a, 0x03, 0x80,
+  0x4d, 0x33, 0x2d, 0x65, 0x4e, 0x42, 0x33, 0x37,
+  0x00, 0x14, 0x00, 0x03, 0x01, 0x00, 0x01
+};
+
+
+//uint8_t m3ap_start_message[] = {
+//  0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x07, 0x00,
+//  0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00,
+//  0x07, 0x00, 0x55, 0xf5, 0x01, 0x00, 0x00, 0x01,
+//  0x00, 0x04, 0x00, 0x0d, 0x60, 0x01, 0x00, 0x00,
+//  0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 0x01,
+//  0x7a, 0x00, 0x05, 0x00, 0x03, 0x07, 0x08, 0x00,
+//  0x00, 0x06, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00,
+//  0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+//  0x0e, 0x00, 0xe8, 0x0a, 0x0a, 0x0a, 0x00, 0x0a,
+//  0xc8, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x01
+//};
+//
+// SETUP REQUEST
+int MCE_send_M3_SETUP_REQUEST(m3ap_MCE_instance_t *instance_p, m3ap_MCE_data_t *m3ap_MCE_data_p) {
+//  module_id_t enb_mod_idP=0;
+//  module_id_t du_mod_idP=0;
+//
+  M3AP_M3AP_PDU_t          pdu;
+  M3AP_M3SetupRequest_t    *out;
+  M3AP_M3SetupRequestIEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+  //int       j = 0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M3AP_InitiatingMessage_t *)calloc(1, sizeof(M3AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+  pdu.choice.initiatingMessage.criticality   = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_M3SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M3SetupRequest;
+
+  /* mandatory */
+  /* c1. GlobalMCE_ID (integer value) */
+  ie = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_Global_MCE_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_M3SetupRequestIEs__value_PR_Global_MCE_ID;
+  //ie->value.choice.GlobalMCE_ID.MCE_ID = 1;//M3AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);
+  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                  &ie->value.choice.Global_MCE_ID.pLMN_Identity);
+  //ie->value.choice.Global_MCE_ID.MCE_ID.present = M3AP_MCE_ID_PR_macro_MCE_ID;
+ OCTET_STRING_fromBuf(&ie->value.choice.Global_MCE_ID.mCE_ID,"02",2);
+
+ // MACRO_ENB_ID_TO_BIT_STRING(instance_p->MCE_id,
+  //                         &ie->value.choice.Global_MCE_ID.mCE_ID);
+  //M3AP_INFO("%d -> %02x%02x%02x\n", instance_p->MCE_id,
+   //       ie->value.choice.Global_MCE_ID.mCE_ID.buf[0],
+    //      ie->value.choice.Global_MCE_ID.mCE_ID.buf[1],
+     //     ie->value.choice.Global_MCE_ID.mCE_ID.buf[2]);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  ///* mandatory */
+//  ///* c2. GNB_MCE_ID (integrer value) */
+//  //ie = (M3AP_M3SetupRequest_Ies_t *)calloc(1, sizeof(M3AP_M3SetupRequest_Ies_t));
+//  //ie->id                        = M3AP_ProtocolIE_ID_id_gNB_MCE_ID;
+//  //ie->criticality               = M3AP_Criticality_reject;
+//  //ie->value.present             = M3AP_M3SetupRequestIEs__value_PR_GNB_MCE_ID;
+//  //asn_int642INTEGER(&ie->value.choice.GNB_MCE_ID, f1ap_du_data->gNB_MCE_id);
+//  //ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//     /* optional */
+  /* c3. MCEname */
+  //m3ap_MCE_data_p->MCE_name="kk";
+  if (m3ap_MCE_data_p->MCE_name != NULL) {
+    ie = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+    ie->id                        = M3AP_ProtocolIE_ID_id_MCEname;
+    ie->criticality               = M3AP_Criticality_ignore;
+    ie->value.present             = M3AP_M3SetupRequestIEs__value_PR_MCEname;
+    OCTET_STRING_fromBuf(&ie->value.choice.MCEname, m3ap_MCE_data_p->MCE_name,
+                         strlen(m3ap_MCE_data_p->MCE_name));
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */ //but removed from asn definition (optional) since it crashes when decoding ???????????
+//	M3SetupRequestIEs M3AP-PROTOCOL-IES ::= {
+//		{ ID id-Global-MCE-ID                   CRITICALITY reject      TYPE Global-MCE-ID                                      PRESENCE mandatory}|
+//		{ ID id-MCEname                                 CRITICALITY ignore      TYPE MCEname                                            PRESENCE optional}|
+//		{ ID id-MBMSServiceAreaList             CRITICALITY reject      TYPE MBMSServiceAreaListItem            PRESENCE mandatory}, --> optional ??????????
+//		...
+//	}
+
+
+  /* M3AP_MBMSServiceAreaListItem_t */
+  ie = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMSServiceAreaList;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_M3SetupRequestIEs__value_PR_MBMSServiceAreaListItem;
+
+  //M3AP_MBMSServiceAreaListItem_t * m3ap_mbmsservicearealistitem = (M3AP_MBMSServiceAreaListItem_t*)calloc(1,sizeof(M3AP_MBMSServiceAreaListItem_t)); 
+
+  M3AP_MBMSServiceArea1_t * m3ap_mbmsservicearea1 = (M3AP_MBMSServiceArea1_t*)calloc(1,sizeof(M3AP_MBMSServiceArea1_t));
+  
+  OCTET_STRING_fromBuf(m3ap_mbmsservicearea1,"02",2);
+
+  //ASN_SEQUENCE_ADD(&m3ap_mbmsservicearealistitem->list,m3ap_mbmsservicearea1);
+
+  //ASN_SEQUENCE_ADD(&ie->value.choice.MBMSServiceAreaListItem,m3ap_mbmsservicearealistitem);
+  //ASN_SEQUENCE_ADD(&ie->value.choice.MBMSServiceAreaListItem.list,m3ap_mbmsservicearealistitem);
+  ASN_SEQUENCE_ADD(&ie->value.choice.MBMSServiceAreaListItem.list,m3ap_mbmsservicearea1);
+  
+  //ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+//
+//  /* mandatory */
+//  /* c4. serverd cells list */
+//  ie = (M3AP_M3SetupRequest_Ies_t *)calloc(1, sizeof(M3AP_M3SetupRequest_Ies_t));
+//  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_Configuration_data_List;
+//  ie->criticality               = M3AP_Criticality_reject;
+//  ie->value.present             = M3AP_M3SetupRequest_Ies__value_PR_MCE_MBMS_Configuration_data_List;
+//
+//  int num_mbms_available = 1;//m3ap_du_data->num_mbms_available;
+//  LOG_D(M3AP, "num_mbms_available = %d \n", num_mbms_available);
+//
+// for (i=0;
+//       i<num_mbms_available;
+//       i++) {
+//        /* mandatory */
+//        /* 4.1 serverd cells item */
+//
+//        M3AP_MCE_MBMS_Configuration_data_ItemIEs_t *mbms_configuration_data_list_item_ies;
+//        mbms_configuration_data_list_item_ies = (M3AP_MCE_MBMS_Configuration_data_ItemIEs_t *)calloc(1, sizeof(M3AP_MCE_MBMS_Configuration_data_ItemIEs_t));
+//        mbms_configuration_data_list_item_ies->id = M3AP_ProtocolIE_ID_id_MCE_MBMS_Configuration_data_Item;
+//        mbms_configuration_data_list_item_ies->criticality = M3AP_Criticality_reject;
+//        mbms_configuration_data_list_item_ies->value.present = M3AP_MCE_MBMS_Configuration_data_ItemIEs__value_PR_MCE_MBMS_Configuration_data_Item;
+//
+//        M3AP_MCE_MBMS_Configuration_data_Item_t *mbms_configuration_data_item;
+//        mbms_configuration_data_item = &mbms_configuration_data_list_item_ies->value.choice.MCE_MBMS_Configuration_data_Item;
+//        {
+//		/* M3AP_ECGI_t eCGI */
+//                MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                  &mbms_configuration_data_item->eCGI.pLMN_Identity);
+//                MACRO_MCE_ID_TO_CELL_IDENTITY(instance_p->MCE_id,0,
+//                                   &mbms_configuration_data_item->eCGI.eUTRANcellIdentifier);
+//		/* M3AP_MBSFN_SynchronisationArea_ID_t mbsfnSynchronisationArea */ 
+//		mbms_configuration_data_item->mbsfnSynchronisationArea=10000; //? long
+//		/* M3AP_MBMS_Service_Area_ID_List_t mbmsServiceAreaList */
+//                M3AP_MBMS_Service_Area_t * mbms_service_area,*mbms_service_area2;
+//                mbms_service_area = (M3AP_MBMS_Service_Area_t*)calloc(1,sizeof(M3AP_MBMS_Service_Area_t));
+//                mbms_service_area2 = (M3AP_MBMS_Service_Area_t*)calloc(1,sizeof(M3AP_MBMS_Service_Area_t));
+//		//memset(mbms_service_area,0,sizeof(OCTET_STRING_t));
+//		OCTET_STRING_fromBuf(mbms_service_area,"01",2);
+//                ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area);
+//		OCTET_STRING_fromBuf(mbms_service_area2,"02",2);
+//                ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area2);
+//
+//
+//        }
+//
+//
+//        //M3AP_MCE_MBMS_Configuration_data_Item_t mbms_configuration_data_item;
+//        //memset((void *)&mbms_configuration_data_item, 0, sizeof(M3AP_MCE_MBMS_Configuration_data_Item_t));
+//
+//        //M3AP_ECGI_t      eCGI;
+//                //M3AP_PLMN_Identity_t     pLMN_Identity;
+//                //M3AP_EUTRANCellIdentifier_t      eUTRANcellIdentifier
+//        //M3AP_MBSFN_SynchronisationArea_ID_t      mbsfnSynchronisationArea;
+//        //M3AP_MBMS_Service_Area_ID_List_t         mbmsServiceAreaList;
+//
+//
+//        ASN_SEQUENCE_ADD(&ie->value.choice.MCE_MBMS_Configuration_data_List.list,mbms_configuration_data_list_item_ies);
+//
+// }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  
+// LOG_W(M3AP,"m3ap_MCE_data_p->assoc_id %d\n",m3ap_MCE_data_p->assoc_id);
+//  /* encode */
+
+//    xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, &pdu);
+//    xer_fprint(stdout, &asn_DEF_M3AP_M3SetupRequest, &pdu.choice.initiatingMessage.value.choice.M3SetupRequest);
+//    xer_fprint(stdout, &asn_DEF_M3AP_M3SetupRequest, out);
+
+ if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+   LOG_E(M3AP, "Failed to encode M3 setup request\n");
+   return -1;
+ }
+
+ /* buffer = &m3ap_start_message[0];
+  len=8*9+7; 
+
+  buffer = &m3ap_m3setup_message[0];
+  len=8*4+7; */
+//
+//
+//  LOG_W(M3AP,"pdu.present %d\n",pdu.present);
+// // MSC_LOG_TX_MESSAGE(
+// // MSC_M3AP_MCE,
+// // MSC_M3AP_MCE,
+// // (const char *)buffer,
+// // len,
+// // MSC_AS_TIME_FMT" M3_SETUP_REQUEST initiatingMessage MCEname %s",
+// // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+// // m3ap_MCE_data_p->MCEname);
+//
+//
+////  buffer = &bytes[0];
+////  len = 40;
+////
+////  for(int i=0; i < len; i++ )
+////	printf("%02X",buffer[i]);
+////  printf("\n");
+////
+
+// M3AP_M3AP_PDU_t pdu2;
+//
+//  memset(&pdu2, 0, sizeof(pdu2));
+//
+//  for( i=0; i < len; i++)
+//        printf("%02X",buffer[i]);
+//  printf("\n");
+//
+//  if (m3ap_decode_pdu(&pdu2, buffer, len) < 0) {
+//    LOG_E(M3AP, "Failed to decode PDU\n");
+//    //return -1;
+//  }
+//
+
+  //printf("m3ap_MCE_data_p->assoc_id %d\n",m3ap_MCE_data_p->assoc_id);
+  m3ap_MCE_itti_send_sctp_data_req(instance_p->instance, m3ap_MCE_data_p->assoc_id, buffer, len, 0);
+
+  return 0;
+}
+
+
+
+int MCE_handle_M3_SETUP_RESPONSE(instance_t instance,
+				uint32_t               assoc_id,
+				uint32_t               stream,
+				M3AP_M3AP_PDU_t       *pdu)
+{
+
+   LOG_D(M3AP, "MCE_handle_M3_SETUP_RESPONSE\n");
+
+   AssertFatal(pdu->present == M3AP_M3AP_PDU_PR_successfulOutcome,
+	       "pdu->present != M3AP_M3AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M3AP_ProcedureCode_id_m3Setup,
+	       "pdu->choice.successfulOutcome.procedureCode != M3AP_ProcedureCode_id_M3Setup\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M3AP_Criticality_reject,
+	       "pdu->choice.successfulOutcome.criticality != M3AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M3AP_SuccessfulOutcome__value_PR_M3SetupResponse,
+	       "pdu->choice.successfulOutcome.value.present != M3AP_SuccessfulOutcome__value_PR_M3SetupResponse\n");
+
+   //M3AP_M3SetupResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.M3SetupResponse;
+
+
+   //M3AP_M3SetupResponseIEs_t *ie;
+   //int GlobalMCE_ID = -1;
+   //int num_cells_to_activate = 0;
+   //M3AP_Cells_to_be_Activated_List_Item_t *cell;
+
+   MessageDef *msg_p = itti_alloc_new_message (TASK_M3AP_MCE, M3AP_SETUP_RESP);
+
+  // LOG_D(M3AP, "M3AP: M3Setup-Resp: protocolIEs.list.count %d\n",
+  //       in->protocolIEs.list.count);
+  // for (int i=0;i < in->protocolIEs.list.count; i++) {
+  //   ie = in->protocolIEs.list.array[i];
+  // }
+   //AssertFatal(GlobalMCE_ID!=-1,"GlobalMCE_ID was not sent\n");
+   //AssertFatal(num_cells_to_activate>0,"No cells activated\n");
+   //M3AP_SETUP_RESP (msg_p).num_cells_to_activate = num_cells_to_activate;
+
+   //for (int i=0;i<num_cells_to_activate;i++)  
+   //  AssertFatal(M3AP_SETUP_RESP (msg_p).num_SI[i] > 0, "System Information %d is missing",i);
+
+   //MSC_LOG_RX_MESSAGE(
+   // MSC_M3AP_MCE,
+   // MSC_M3AP_CU,
+   // 0,
+   // 0,
+   // MSC_AS_TIME_FMT" MCE_handle_M3_SETUP_RESPONSE successfulOutcome assoc_id %d",
+   // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+   // assoc_id);
+ 
+   //LOG_D(M3AP, "Sending M3AP_SETUP_RESP ITTI message to MCE_APP with assoc_id (%d->%d)\n",
+   //      assoc_id,MCE_MOMCELE_ID_TO_INSTANCE(assoc_id));
+   itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p);
+
+   return 0;
+}
+
+// SETUP FAILURE
+int MCE_handle_M3_SETUP_FAILURE(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu) {
+  LOG_E(M3AP, "MCE_handle_M3_SETUP_FAILURE\n");
+  return 0;
+}
+
+
+
+
+
diff --git a/openair3/M3AP/m3ap_MCE_interface_management.h b/openair3/M3AP/m3ap_MCE_interface_management.h
new file mode 100644
index 0000000000000000000000000000000000000000..76e13bb8d87eb406566fa23c081570d4049ad550
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_interface_management.h
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_interface_management.h
+ * \brief m3ap interface management for MCE
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M3AP_MCE_INTERFACE_MANAGEMENT_H_
+#define M3AP_MCE_INTERFACE_MANAGEMENT_H_
+
+/*
+ * Session Start 
+ */
+
+int MCE_handle_MBMS_SESSION_START_REQUEST(instance_t instance, 
+					uint32_t assoc_id,
+                                	uint32_t stream,
+                                	M3AP_M3AP_PDU_t *pdu);
+int MCE_send_MBMS_SESSION_START_RESPONSE(instance_t instance, m3ap_session_start_resp_t * m3ap_session_start_resp);
+int MCE_send_MBMS_SESSION_START_FAILURE(instance_t instance, m3ap_session_start_failure_t * m3ap_session_start_failure);
+
+/*
+ * Session Stop
+ */
+
+int MCE_handle_MBMS_SESSION_STOP_REQUEST(instance_t instance, 
+					uint32_t assoc_id,
+                                	uint32_t stream,
+                                	M3AP_M3AP_PDU_t *pdu);
+
+/*
+ * Session Update
+ */
+int MCE_handle_MBMS_SESSION_UPDATE_REQUEST(instance_t instance, 
+					uint32_t assoc_id,
+                                	uint32_t stream,
+                                	M3AP_M3AP_PDU_t *pdu);
+
+int MCE_send_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, m3ap_mbms_session_update_resp_t * m3ap_mbms_session_update_resp);
+int MCE_send_MBMS_SESSION_UPDATE_FAILURE(instance_t instance, m3ap_mbms_session_update_failure_t * m3ap_mbms_session_update_failure);
+
+
+
+
+
+
+
+int MCE_send_MBMS_SESSION_STOP_RESPONSE(instance_t instance, m3ap_session_start_resp_t * m3ap_session_start_resp);
+
+/*
+ * Reset
+ */
+int MCE_handle_RESET(instance_t instance,
+                    uint32_t assoc_id,
+                    uint32_t stream,
+                    M3AP_M3AP_PDU_t *pdu);
+int MCE_send_RESET_ACKKNOWLEDGE(instance_t instance, M3AP_ResetAcknowledge_t *ResetAcknowledge);
+int MCE_send_RESET(instance_t instance, M3AP_Reset_t *Reset);
+int MCE_handle_RESET_ACKNOWLEDGE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+/*
+ * M3AP Setup
+ */
+int MCE_send_M3_SETUP_REQUEST( m3ap_MCE_instance_t *instance_p, m3ap_MCE_data_t *m3ap_MCE_data_p);
+
+int MCE_handle_M3_SETUP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+int MCE_handle_M3_SETUP_FAILURE(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu);
+
+/*
+ * Error Indication
+ */
+int MCE_send_ERROR_INDICATION(instance_t instance, M3AP_M3AP_PDU_t *pdu_p);
+int MCE_handle_ERROR_INDICATION(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu);
+
+
+
+
+#endif /* M3AP_MCE_INTERFACE_MANAGEMENT_H_ */
+
+
+
diff --git a/openair3/M3AP/m3ap_MCE_management_procedures.c b/openair3/M3AP/m3ap_MCE_management_procedures.c
new file mode 100644
index 0000000000000000000000000000000000000000..32901ca8692b46d6959f3893ec3645762c50220a
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_management_procedures.c
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_management_procedures.c
+ * \brief m3ap tasks for MCE
+ * \author Javier Morgade  <javier.morade@ieee.org>
+ * \date 2018
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "assertions.h"
+#include "conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_MCE.h"
+
+
+#define M3AP_DEBUG_LIST
+#ifdef M3AP_DEBUG_LIST
+#  define M3AP_MCE_LIST_OUT(x, args...) M3AP_DEBUG("[MCE]%*s"x"\n", 4*indent, "", ##args)
+#else
+#  define M3AP_MCE_LIST_OUT(x, args...)
+#endif
+
+static int                  indent = 0;
+
+
+m3ap_MCE_internal_data_t m3ap_MCE_internal_data;
+
+RB_GENERATE(m3ap_mce_map, m3ap_MCE_data_s, entry, m3ap_MCE_compare_assoc_id);
+
+int m3ap_MCE_compare_assoc_id(
+  struct m3ap_MCE_data_s *p1, struct m3ap_MCE_data_s *p2)
+{
+  if (p1->assoc_id == -1) {
+    if (p1->cnx_id < p2->cnx_id) {
+      return -1;
+    }
+
+    if (p1->cnx_id > p2->cnx_id) {
+      return 1;
+    }
+  } else {
+    if (p1->assoc_id < p2->assoc_id) {
+      return -1;
+    }
+
+    if (p1->assoc_id > p2->assoc_id) {
+      return 1;
+    }
+  }
+
+  /* Matching reference */
+  return 0;
+}
+
+uint16_t m3ap_MCE_fetch_add_global_cnx_id(void)
+{
+  return ++m3ap_MCE_internal_data.global_cnx_id;
+}
+
+void m3ap_MCE_prepare_internal_data(void)
+{
+  memset(&m3ap_MCE_internal_data, 0, sizeof(m3ap_MCE_internal_data));
+  STAILQ_INIT(&m3ap_MCE_internal_data.m3ap_MCE_instances_head);
+}
+
+void m3ap_MCE_insert_new_instance(m3ap_MCE_instance_t *new_instance_p)
+{
+  DevAssert(new_instance_p != NULL);
+
+  STAILQ_INSERT_TAIL(&m3ap_MCE_internal_data.m3ap_MCE_instances_head,
+                     new_instance_p, m3ap_MCE_entries);
+}
+
+void dump_tree_m3(m3ap_MCE_data_t *t)
+{
+  if (t == NULL) return;
+  printf("-----------------------\n");
+  printf("MCE id %d %s\n", t->MCE_id, t->MCE_name);
+  printf("state %d\n", t->state);
+  printf("nextstream %d\n", t->nextstream);
+  printf("in_streams %d out_streams %d\n", t->in_streams, t->out_streams);
+  printf("cnx_id %d assoc_id %d\n", t->cnx_id, t->assoc_id);
+  dump_tree_m3(t->entry.rbe_left);
+  dump_tree_m3(t->entry.rbe_right);
+}
+
+void dump_trees_m3(void)
+{
+m3ap_MCE_instance_t *zz;
+STAILQ_FOREACH(zz, &m3ap_MCE_internal_data.m3ap_MCE_instances_head,
+               m3ap_MCE_entries) {
+printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance);
+dump_tree_m3(zz->m3ap_mce_head.rbh_root);
+printf("---------------------------------------------\n");
+}
+}
+
+struct m3ap_MCE_data_s *m3ap_get_MCE(m3ap_MCE_instance_t *instance_p,
+				     int32_t assoc_id,
+				     uint16_t cnx_id)
+{
+  struct m3ap_MCE_data_s  temp;
+  struct m3ap_MCE_data_s *found;
+
+//printf("m3ap_get_MCE at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
+//dump_trees_m3();
+
+  memset(&temp, 0, sizeof(struct m3ap_MCE_data_s));
+
+  temp.assoc_id = assoc_id;
+  temp.cnx_id   = cnx_id;
+
+  if (instance_p == NULL) {
+    STAILQ_FOREACH(instance_p, &m3ap_MCE_internal_data.m3ap_MCE_instances_head,
+                   m3ap_MCE_entries) {
+      found = RB_FIND(m3ap_mce_map, &instance_p->m3ap_mce_head, &temp);
+
+      if (found != NULL) {
+        return found;
+      }
+    }
+  } else {
+    return RB_FIND(m3ap_mce_map, &instance_p->m3ap_mce_head, &temp);
+  }
+
+  return NULL;
+}
+
+
+m3ap_MCE_instance_t *m3ap_MCE_get_instance(instance_t instance)
+{
+  m3ap_MCE_instance_t *temp = NULL;
+
+  STAILQ_FOREACH(temp, &m3ap_MCE_internal_data.m3ap_MCE_instances_head,
+                 m3ap_MCE_entries) {
+    if (temp->instance == instance) {
+      /* Matching occurence */
+      return temp;
+    }
+  }
+
+  return NULL;
+}
+
+/// utility functions
+
+void m3ap_dump_MCE (m3ap_MCE_data_t  * MCE_ref);
+
+void
+m3ap_dump_MCE_list (void) {
+   m3ap_MCE_instance_t *inst = NULL;
+   struct m3ap_MCE_data_s *found = NULL;
+   struct m3ap_MCE_data_s temp;
+
+   memset(&temp, 0, sizeof(struct m3ap_MCE_data_s));
+
+  STAILQ_FOREACH (inst, &m3ap_MCE_internal_data.m3ap_MCE_instances_head,  m3ap_MCE_entries) {
+    found = RB_FIND(m3ap_mce_map, &inst->m3ap_mce_head, &temp);
+    m3ap_dump_MCE (found);
+  }
+}
+
+void m3ap_dump_MCE (m3ap_MCE_data_t  * MCE_ref) {
+
+  if (MCE_ref == NULL) {
+    return;
+  }
+
+  M3AP_MCE_LIST_OUT ("");
+  M3AP_MCE_LIST_OUT ("MCE name:          %s", MCE_ref->MCE_name == NULL ? "not present" : MCE_ref->MCE_name);
+  M3AP_MCE_LIST_OUT ("MCE STATE:         %07x", MCE_ref->state);
+  M3AP_MCE_LIST_OUT ("MCE ID:            %07x", MCE_ref->MCE_id);
+  indent++;
+  M3AP_MCE_LIST_OUT ("SCTP cnx id:     %d", MCE_ref->cnx_id);
+  M3AP_MCE_LIST_OUT ("SCTP assoc id:     %d", MCE_ref->assoc_id);
+  M3AP_MCE_LIST_OUT ("SCTP instreams:    %d", MCE_ref->in_streams);
+  M3AP_MCE_LIST_OUT ("SCTP outstreams:   %d", MCE_ref->out_streams);
+  indent--;
+}
+
+m3ap_MCE_data_t  * m3ap_is_MCE_pci_in_list (const uint32_t pci)
+{
+  m3ap_MCE_instance_t    *inst;
+  struct m3ap_MCE_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m3ap_MCE_internal_data.m3ap_MCE_instances_head, m3ap_MCE_entries) {
+    RB_FOREACH(elm, m3ap_mce_map, &inst->m3ap_mce_head) {
+      for (int i = 0; i<elm->num_cc; i++) {
+        if (elm->Nid_cell[i] == pci) {
+          return elm;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+m3ap_MCE_data_t  * m3ap_is_MCE_id_in_list (const uint32_t MCE_id)
+{
+  m3ap_MCE_instance_t    *inst;
+  struct m3ap_MCE_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m3ap_MCE_internal_data.m3ap_MCE_instances_head, m3ap_MCE_entries) {
+    RB_FOREACH(elm, m3ap_mce_map, &inst->m3ap_mce_head) {
+      if (elm->MCE_id == MCE_id)
+        return elm;
+    }
+  }
+  return NULL;
+}
+
+m3ap_MCE_data_t  * m3ap_is_MCE_assoc_id_in_list (const uint32_t sctp_assoc_id)
+{
+  m3ap_MCE_instance_t    *inst;
+  struct m3ap_MCE_data_s *found;
+  struct m3ap_MCE_data_s temp;
+
+  temp.assoc_id = sctp_assoc_id;
+  temp.cnx_id = -1;
+
+  STAILQ_FOREACH(inst, &m3ap_MCE_internal_data.m3ap_MCE_instances_head, m3ap_MCE_entries) {
+    found = RB_FIND(m3ap_mce_map, &inst->m3ap_mce_head, &temp);
+    if (found != NULL){
+      if (found->assoc_id == sctp_assoc_id) {
+	return found;
+      }
+    }
+  }
+  return NULL;
+}
diff --git a/openair3/M3AP/m3ap_MCE_management_procedures.h b/openair3/M3AP/m3ap_MCE_management_procedures.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d18df8c26d23877bd9fd1b9d2e3312fbff64d3c
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_management_procedures.h
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_management_procedures.h
+ * \brief m3ap tasks for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_MCE_MANAGEMENT_PROCEDURES_H_
+#define M3AP_MCE_MANAGEMENT_PROCEDURES_H
+
+void m3ap_MCE_prepare_internal_data(void);
+
+void dump_trees_m3(void);
+
+void m3ap_MCE_insert_new_instance(m3ap_MCE_instance_t *new_instance_p);
+
+m3ap_MCE_instance_t *m3ap_MCE_get_instance(uint8_t mod_id);
+
+uint16_t m3ap_MCE_fetch_add_global_cnx_id(void);
+
+
+m3ap_MCE_data_t* m3ap_is_MCE_id_in_list(uint32_t MCE_id);
+
+m3ap_MCE_data_t* m3ap_is_MCE_assoc_id_in_list(uint32_t sctp_assoc_id);
+
+m3ap_MCE_data_t* m3ap_is_MCE_pci_in_list (const uint32_t pci);
+
+struct m3ap_MCE_data_s *m3ap_get_MCE(m3ap_MCE_instance_t *instance_p,
+                                     int32_t assoc_id,
+                                     uint16_t cnx_id);
+
+#endif /* M3AP_MCE_MANAGEMENT_PROCEDURES_H_ */
diff --git a/openair3/M3AP/m3ap_MME.c b/openair3/M3AP/m3ap_MME.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbfe6e1327888a88825cd0cea14a5bb7f5230b50
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME.c
@@ -0,0 +1,730 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME.c
+ * \brief m3ap tasks for MME
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
+#include "intertask_interface.h"
+
+#include "m3ap_MME.h"
+#include "m3ap_MME_defs.h"
+#include "m3ap_MME_management_procedures.h"
+#include "m3ap_MME_handler.h"
+//#include "m3ap_MME_generate_messages.h"
+#include "m3ap_common.h"
+#include "m3ap_MME_interface_management.h"
+#include "m3ap_ids.h"
+#include "m3ap_timers.h"
+
+#include "queue.h"
+#include "assertions.h"
+#include "conversions.h"
+
+struct m3ap_mme_map;
+struct m3ap_MME_data_s;
+
+m3ap_setup_req_t *m3ap_mme_data_from_mce;
+
+RB_PROTOTYPE(m3ap_mme_map, m3ap_MME_data_s, entry, m3ap_MME_compare_assoc_id);
+
+static
+void m3ap_MME_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
+
+static
+void m3ap_MME_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
+
+static
+void m3ap_MME_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind);
+
+//static
+//void m3ap_MME_handle_register_MME(instance_t instance,
+//                                  m3ap_register_mce_req_t *m3ap_register_MME);
+static
+void m3ap_MME_register_MME(m3ap_MME_instance_t *instance_p,
+                           net_ip_address_t    *target_MME_ip_addr,
+                           net_ip_address_t    *local_ip_addr,
+                           uint16_t             in_streams,
+                           uint16_t             out_streams,
+                           uint32_t             mme_port_for_M3C,
+                           int                  multi_sd);
+
+//static
+//void m3ap_MME_handle_handover_req(instance_t instance,
+//                                  m3ap_handover_req_t *m3ap_handover_req);
+//
+//static
+//void m3ap_MME_handle_handover_req_ack(instance_t instance,
+//                                      m3ap_handover_req_ack_t *m3ap_handover_req_ack);
+//
+//static
+//void m3ap_MME_ue_context_release(instance_t instance,
+//                                 m3ap_ue_context_release_t *m3ap_ue_context_release);
+//
+
+static
+void m3ap_MME_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
+  int result;
+  DevAssert(sctp_data_ind != NULL);
+  m3ap_MME_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
+                          sctp_data_ind->buffer, sctp_data_ind->buffer_length);
+  result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
+  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+}
+
+static
+void m3ap_MME_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
+
+   DevAssert(sctp_new_association_resp != NULL);
+
+  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+    LOG_W(M3AP, "Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+              sctp_new_association_resp->sctp_state,
+              instance,
+              sctp_new_association_resp->ulp_cnx_id);
+
+    if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN)
+      //proto_agent_stop(instance);
+      //f1ap_handle_setup_message(instance, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+    return; // exit -1 for debugging
+  }
+
+   // go to an init func
+  m3ap_mme_data_from_mce = (m3ap_setup_req_t *)calloc(1, sizeof(m3ap_setup_req_t));
+  // save the assoc id
+  m3ap_mme_data_from_mce->assoc_id         = sctp_new_association_resp->assoc_id;
+  m3ap_mme_data_from_mce->sctp_in_streams  = sctp_new_association_resp->in_streams;
+  m3ap_mme_data_from_mce->sctp_out_streams = sctp_new_association_resp->out_streams;
+
+
+
+ // m3ap_MME_instance_t *instance_p;
+ // m3ap_MME_data_t *m3ap_mme_data_p;
+ // DevAssert(sctp_new_association_resp != NULL);
+ // printf("m3ap_MME_handle_sctp_association_resp at 1\n");
+ // dump_mme_trees_m3();
+ // instance_p = instance;//m3ap_MME_get_instance(instance);
+ // DevAssert(instance_p != NULL);
+
+ // /* if the assoc_id is already known, it is certainly because an IND was received
+ //  * before. In this case, just update streams and return
+ //  */
+ // if (sctp_new_association_resp->assoc_id != -1) {
+ //   m3ap_mme_data_p = m3ap_get_MME(instance_p, sctp_new_association_resp->assoc_id,
+ //                                  sctp_new_association_resp->ulp_cnx_id);
+
+ //   if (m3ap_mme_data_p != NULL) {
+ //     /* some sanity check - to be refined at some point */
+ //     if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+ //       M3AP_ERROR("m3ap_mme_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
+ //       abort();
+ //     }
+
+ //     m3ap_mme_data_p->in_streams  = sctp_new_association_resp->in_streams;
+ //     m3ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
+ //     return;
+ //   }
+ // }
+
+ // m3ap_mme_data_p = m3ap_get_MME(instance_p, -1,
+ //                                sctp_new_association_resp->ulp_cnx_id);
+ // DevAssert(m3ap_mme_data_p != NULL);
+ // printf("m3ap_MME_handle_sctp_association_resp at 2\n");
+ // dump_mme_trees_m3();
+
+ // if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+ //   M3AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+ //             sctp_new_association_resp->sctp_state,
+ //             instance,
+ //             sctp_new_association_resp->ulp_cnx_id);
+ //   //m3ap_eNB_handle_m3_setup_message(instance_p, m3ap_mme_data_p,
+ //                                //sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+ //   return;
+ // }
+
+ // printf("m3ap_MME_handle_sctp_association_resp at 3\n");
+ // dump_mme_trees_m3();
+ // /* Update parameters */
+ // m3ap_mme_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
+ // m3ap_mme_data_p->in_streams  = sctp_new_association_resp->in_streams;
+ // m3ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
+ // printf("m3ap_MME_handle_sctp_association_resp at 4\n");
+ // dump_mme_trees_m3();
+ // /* Prepare new m3 Setup Request */
+ // //m3ap_MME_generate_m3_setup_request(instance_p, m3ap_mme_data_p);
+}
+
+static
+void m3ap_MME_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) {
+  //m3ap_MME_instance_t *instance_p;
+  //m3ap_MME_data_t *m3ap_mme_data_p;
+  //printf("m3ap_MME_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
+  ///dump_mme_trees_m3();
+  ///DevAssert(sctp_new_association_ind != NULL);
+  ///instance_p = instance;//m3ap_MME_get_instance(instance);
+  ///DevAssert(instance_p != NULL);
+  ///m3ap_mme_data_p = m3ap_get_MME(instance_p, sctp_new_association_ind->assoc_id, -1);
+
+  ///if (m3ap_mme_data_p != NULL) abort();
+
+  /////  DevAssert(m3ap_enb_data_p != NULL);
+  ///if (m3ap_mme_data_p == NULL) {
+  ///  /* Create new MME descriptor */
+  ///  m3ap_mme_data_p = calloc(1, sizeof(*m3ap_mme_data_p));
+  ///  DevAssert(m3ap_mme_data_p != NULL);
+  ///  m3ap_mme_data_p->cnx_id                = m3ap_MME_fetch_add_global_cnx_id();
+  ///  m3ap_mme_data_p->m3ap_MME_instance = instance_p;
+  ///  /* Insert the new descriptor in list of known MME
+  ///   * but not yet associated.
+  ///   */
+  ///  RB_INSERT(m3ap_mme_map, &instance_p->m3ap_mme_head, m3ap_mme_data_p);
+  ///  m3ap_mme_data_p->state = M3AP_MME_STATE_CONNECTED;
+  ///  instance_p->m3_target_mme_nb++;
+
+  ///  if (instance_p->m3_target_mme_pending_nb > 0) {
+  ///    instance_p->m3_target_mme_pending_nb--;
+  ///  }
+  ///} else {
+  ///  M3AP_WARN("m3ap_mme_data_p already exists\n");
+  ///}
+
+  ///printf("m3ap_MME_handle_sctp_association_ind at 2\n");
+  ///dump_mme_trees_m3();
+  ////* Update parameters */
+  ///m3ap_mme_data_p->assoc_id    = sctp_new_association_ind->assoc_id;
+  ///m3ap_mme_data_p->in_streams  = sctp_new_association_ind->in_streams;
+  ///m3ap_mme_data_p->out_streams = sctp_new_association_ind->out_streams;
+  ///printf("m3ap_MME_handle_sctp_association_ind at 3\n");
+  ///dump_mme_trees_m3();
+}
+
+int m3ap_MME_init_sctp (m3ap_MME_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t mme_port_for_M3C) {
+  // Create and alloc new message
+  MessageDef                             *message;
+  sctp_init_t                            *sctp_init  = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(local_ip_addr != NULL);
+  message = itti_alloc_new_message (TASK_M3AP_MME, SCTP_INIT_MSG_MULTI_REQ);
+  sctp_init = &message->ittiMsg.sctp_init_multi;
+  sctp_init->port = mme_port_for_M3C;
+  sctp_init->ppid = M3AP_SCTP_PPID;
+  sctp_init->ipv4 = 1;
+  sctp_init->ipv6 = 0;
+  sctp_init->nb_ipv4_addr = 1;
+#if 0
+  memcpy(&sctp_init->ipv4_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+#endif
+  sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
+  /*
+   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+   * * * * Disable it for now.
+   */
+  sctp_init->nb_ipv6_addr = 0;
+  sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
+  return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
+}
+
+static void m3ap_MME_register_MME(m3ap_MME_instance_t *instance_p,
+                                  net_ip_address_t    *target_MME_ip_address,
+                                  net_ip_address_t    *local_ip_addr,
+                                  uint16_t             in_streams,
+                                  uint16_t             out_streams,
+                                  uint32_t             mme_port_for_M3C,
+                                  int                  multi_sd) {
+ // MessageDef                       *message                   = NULL;
+ // sctp_new_association_req_multi_t *sctp_new_association_req  = NULL;
+ // m3ap_MME_data_t                  *m3ap_mme_data             = NULL;
+ // DevAssert(instance_p != NULL);
+ // DevAssert(target_MME_ip_address != NULL);
+ // message = itti_alloc_new_message(TASK_M3AP_MME, SCTP_NEW_ASSOCIATION_REQ_MULTI);
+ // sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi;
+ // sctp_new_association_req->port = mme_port_for_M3C;
+ // sctp_new_association_req->ppid = M3AP_SCTP_PPID;
+ // sctp_new_association_req->in_streams  = in_streams;
+ // sctp_new_association_req->out_streams = out_streams;
+ // sctp_new_association_req->multi_sd = multi_sd;
+ // memcpy(&sctp_new_association_req->remote_address,
+ //        target_MME_ip_address,
+ //        sizeof(*target_MME_ip_address));
+ // memcpy(&sctp_new_association_req->local_address,
+ //        local_ip_addr,
+ //        sizeof(*local_ip_addr));
+ // /* Create new MME descriptor */
+ // m3ap_mme_data = calloc(1, sizeof(*m3ap_mme_data));
+ // DevAssert(m3ap_mme_data != NULL);
+ // m3ap_mme_data->cnx_id                = m3ap_MME_fetch_add_global_cnx_id();
+ // sctp_new_association_req->ulp_cnx_id = m3ap_mme_data->cnx_id;
+ // m3ap_mme_data->assoc_id          = -1;
+ // m3ap_mme_data->m3ap_MME_instance = instance_p;
+ // /* Insert the new descriptor in list of known MME
+ //  * but not yet associated.
+ //  */
+ // RB_INSERT(m3ap_mme_map, &instance_p->m3ap_mme_head, m3ap_mme_data);
+ // m3ap_mme_data->state = M3AP_MME_STATE_WAITING;
+ // instance_p->m3_target_mme_nb ++;
+ // instance_p->m3_target_mme_pending_nb ++;
+ // itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
+}
+
+//static
+//void m3ap_MME_handle_register_MME(instance_t instance,
+//                                  m3ap_register_mce_req_t *m3ap_register_MME) {
+//  m3ap_MME_instance_t *new_instance;
+//  DevAssert(m3ap_register_MME != NULL);
+//  /* Look if the provided instance already exists */
+//  new_instance = m3ap_MME_get_instance(instance);
+//
+//  if (new_instance != NULL) {
+//    /* Checks if it is a retry on the same MME */
+//    DevCheck(new_instance->MME_id == m3ap_register_MME->MME_id, new_instance->MME_id, m3ap_register_MME->MME_id, 0);
+//    DevCheck(new_instance->cell_type == m3ap_register_MME->cell_type, new_instance->cell_type, m3ap_register_MME->cell_type, 0);
+//    DevCheck(new_instance->tac == m3ap_register_MME->tac, new_instance->tac, m3ap_register_MME->tac, 0);
+//    DevCheck(new_instance->mcc == m3ap_register_MME->mcc, new_instance->mcc, m3ap_register_MME->mcc, 0);
+//    DevCheck(new_instance->mnc == m3ap_register_MME->mnc, new_instance->mnc, m3ap_register_MME->mnc, 0);
+//    M3AP_WARN("MME[%d] already registered\n", instance);
+//  } else {
+//    new_instance = calloc(1, sizeof(m3ap_MME_instance_t));
+//    DevAssert(new_instance != NULL);
+//    RB_INIT(&new_instance->m3ap_mme_head);
+//    /* Copy usefull parameters */
+//    new_instance->instance         = instance;
+//    new_instance->MME_name         = m3ap_register_MME->MME_name;
+//    new_instance->MME_id           = m3ap_register_MME->MME_id;
+//    new_instance->cell_type        = m3ap_register_MME->cell_type;
+//    new_instance->tac              = m3ap_register_MME->tac;
+//    new_instance->mcc              = m3ap_register_MME->mcc;
+//    new_instance->mnc              = m3ap_register_MME->mnc;
+//    new_instance->mnc_digit_length = m3ap_register_MME->mnc_digit_length;
+//    new_instance->num_cc           = m3ap_register_MME->num_cc;
+//
+//    m3ap_id_manager_init(&new_instance->id_manager);
+//    m3ap_timers_init(&new_instance->timers,
+//                     m3ap_register_MME->t_reloc_prep,
+//                     m3ap_register_MME->tm3_reloc_overall);
+//
+//    for (int i = 0; i< m3ap_register_MME->num_cc; i++) {
+//      new_instance->eutra_band[i]              = m3ap_register_MME->eutra_band[i];
+//      new_instance->downlink_frequency[i]      = m3ap_register_MME->downlink_frequency[i];
+//      new_instance->uplink_frequency_offset[i] = m3ap_register_MME->uplink_frequency_offset[i];
+//      new_instance->Nid_cell[i]                = m3ap_register_MME->Nid_cell[i];
+//      new_instance->N_RB_DL[i]                 = m3ap_register_MME->N_RB_DL[i];
+//      new_instance->frame_type[i]              = m3ap_register_MME->frame_type[i];
+//      new_instance->fdd_earfcn_DL[i]           = m3ap_register_MME->fdd_earfcn_DL[i];
+//      new_instance->fdd_earfcn_UL[i]           = m3ap_register_MME->fdd_earfcn_UL[i];
+//    }
+//
+//    DevCheck(m3ap_register_MME->nb_m3 <= M3AP_MAX_NB_MME_IP_ADDRESS,
+//             M3AP_MAX_NB_MME_IP_ADDRESS, m3ap_register_MME->nb_m3, 0);
+//    memcpy(new_instance->target_mme_m3_ip_address,
+//           m3ap_register_MME->target_mme_m3_ip_address,
+//           m3ap_register_MME->nb_m3 * sizeof(net_ip_address_t));
+//    new_instance->nb_m3             = m3ap_register_MME->nb_m3;
+//    new_instance->mme_m3_ip_address = m3ap_register_MME->mme_m3_ip_address;
+//    new_instance->sctp_in_streams   = m3ap_register_MME->sctp_in_streams;
+//    new_instance->sctp_out_streams  = m3ap_register_MME->sctp_out_streams;
+//    new_instance->mme_port_for_M3C  = m3ap_register_MME->mme_port_for_M3C;
+//    /* Add the new instance to the list of MME (meaningfull in virtual mode) */
+//    m3ap_MME_insert_new_instance(new_instance);
+//    M3AP_INFO("Registered new MME[%d] and %s MME id %u\n",
+//              instance,
+//              m3ap_register_MME->cell_type == CELL_MACRO_ENB ? "macro" : "home",
+//              m3ap_register_MME->MME_id);
+//
+//    /* initiate the SCTP listener */
+//    if (m3ap_MME_init_sctp(new_instance,&m3ap_register_MME->mme_m3_ip_address,m3ap_register_MME->mme_port_for_M3C) <  0 ) {
+//      M3AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
+//      return;
+//    }
+//
+//    M3AP_INFO("MME[%d] MME id %u acting as a listner (server)\n",
+//              instance, m3ap_register_MME->MME_id);
+//  }
+//}
+
+static
+void m3ap_MME_handle_sctp_init_msg_multi_cnf(
+  instance_t instance_id,
+  sctp_init_msg_multi_cnf_t *m) {
+  m3ap_MME_instance_t *instance;
+  int index;
+  DevAssert(m != NULL);
+  instance = m3ap_MME_get_instance(instance_id);
+  DevAssert(instance != NULL);
+  instance->multi_sd = m->multi_sd;
+
+  /* Exit if CNF message reports failure.
+   * Failure means multi_sd < 0.
+   */
+  if (instance->multi_sd < 0) {
+    M3AP_ERROR("Error: be sure to properly configure M2 in your configuration file.\n");
+    DevAssert(instance->multi_sd >= 0);
+  }
+
+  /* Trying to connect to the provided list of MME ip address */
+
+  for (index = 0; index < instance->nb_m3; index++) {
+    M3AP_INFO("MME[%d] MME id %u acting as an initiator (client)\n",
+              instance_id, instance->MME_id);
+    m3ap_MME_register_MME(instance,
+                          &instance->target_mme_m3_ip_address[index],
+                          &instance->mme_m3_ip_address,
+                          instance->sctp_in_streams,
+                          instance->sctp_out_streams,
+                          instance->mme_port_for_M3C,
+                          instance->multi_sd);
+  }
+}
+
+//static
+//void m3ap_MME_handle_handover_req(instance_t instance,
+//                                  m3ap_handover_req_t *m3ap_handover_req)
+//{
+//  m3ap_MME_instance_t *instance_p;
+//  m3ap_MME_data_t     *target;
+//  m3ap_id_manager     *id_manager;
+//  int                 ue_id;
+//
+//  int target_pci = m3ap_handover_req->target_physCellId;
+//
+//  instance_p = m3ap_MME_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_is_MME_pci_in_list(target_pci);
+//  DevAssert(target != NULL);
+//
+//  /* allocate m3ap ID */
+//  id_manager = &instance_p->id_manager;
+//  ue_id = m3ap_allocate_new_id(id_manager);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not allocate a new M3AP UE ID\n");
+//    /* TODO: cancel handover: send (to be defined) message to RRC */
+//    exit(1);
+//  }
+//  /* id_source is ue_id, id_target is unknown yet */
+//  m3ap_set_ids(id_manager, ue_id, m3ap_handover_req->rnti, ue_id, -1);
+//  m3ap_id_set_state(id_manager, ue_id, M2ID_STATE_SOURCE_PREPARE);
+//  m3ap_set_reloc_prep_timer(id_manager, ue_id,
+//                            m3ap_timer_get_tti(&instance_p->timers));
+//  m3ap_id_set_target(id_manager, ue_id, target);
+//
+//  m3ap_MME_generate_m3_handover_request(instance_p, target, m3ap_handover_req, ue_id);
+//}
+
+//static
+//void m3ap_MME_handle_handover_req_ack(instance_t instance,
+//                                      m3ap_handover_req_ack_t *m3ap_handover_req_ack)
+//{
+//  /* TODO: remove this hack (the goal is to find the correct
+//   * eNodeB structure for the other end) - we need a proper way for RRC
+//   * and M3AP to identify eNodeBs
+//   * RRC knows about mod_id and M3AP knows about MME_id (MME_ID in
+//   * the configuration file)
+//   * as far as I understand.. CROUX
+//   */
+//  m3ap_MME_instance_t *instance_p;
+//  m3ap_MME_data_t     *target;
+//  int source_assoc_id = m3ap_handover_req_ack->source_assoc_id;
+//  int                 ue_id;
+//  int                 id_source;
+//  int                 id_target;
+//
+//  instance_p = m3ap_MME_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_get_MME(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  /* rnti is a new information, save it */
+//  ue_id     = m3ap_handover_req_ack->m3_id_target;
+//  id_source = m3ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//  m3ap_set_ids(&instance_p->id_manager, ue_id, m3ap_handover_req_ack->rnti, id_source, id_target);
+//
+//  m3ap_MME_generate_m3_handover_request_ack(instance_p, target, m3ap_handover_req_ack);
+//}
+//
+//static
+//void m3ap_MME_ue_context_release(instance_t instance,
+//                                 m3ap_ue_context_release_t *m3ap_ue_context_release)
+//{
+//  m3ap_MME_instance_t *instance_p;
+//  m3ap_MME_data_t     *target;
+//  int source_assoc_id = m3ap_ue_context_release->source_assoc_id;
+//  int ue_id;
+//  instance_p = m3ap_MME_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_get_MME(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  m3ap_MME_generate_m3_ue_context_release(instance_p, target, m3ap_ue_context_release);
+//
+//  /* free the M3AP UE ID */
+//  ue_id = m3ap_find_id_from_rnti(&instance_p->id_manager, m3ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not find UE %x\n", m3ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  m3ap_release_id(&instance_p->id_manager, ue_id);
+//}
+
+void MME_task_send_sctp_init_req(instance_t enb_id, m3ap_mme_sctp_req_t * m3ap_mme_sctp_req) {
+  // 1. get the itti msg, and retrive the enb_id from the message
+  // 2. use RC.rrc[enb_id] to fill the sctp_init_t with the ip, port
+  // 3. creat an itti message to init
+
+  MessageDef  *message_p = NULL;
+
+  message_p = itti_alloc_new_message (TASK_M3AP_MME, SCTP_INIT_MSG);
+if(m3ap_mme_sctp_req==NULL) {
+  LOG_I(M3AP, "M3AP_SCTP_REQ(create socket)\n");
+  message_p->ittiMsg.sctp_init.port = M3AP_PORT_NUMBER;
+  message_p->ittiMsg.sctp_init.ppid = M3AP_SCTP_PPID;
+  message_p->ittiMsg.sctp_init.ipv4 = 1;
+  message_p->ittiMsg.sctp_init.ipv6 = 0;
+  message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
+  //message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+  message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr("127.0.0.8");
+
+}else{
+
+  LOG_I(M3AP, "M3AP_SCTP_REQ(create socket) %s\n",m3ap_mme_sctp_req->mme_m3_ip_address.ipv4_address);
+ message_p->ittiMsg.sctp_init.port = m3ap_mme_sctp_req->mme_port_for_M3C;
+  message_p->ittiMsg.sctp_init.ppid = M3AP_SCTP_PPID;
+  message_p->ittiMsg.sctp_init.ipv4 = 1;
+  message_p->ittiMsg.sctp_init.ipv6 = 0;
+  message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
+  //message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+  message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(m3ap_mme_sctp_req->mme_m3_ip_address.ipv4_address);
+ } 
+
+  /*
+   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+   * * * * Disable it for now.
+   */
+  message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0;
+  message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1";
+
+  itti_send_msg_to_task(TASK_SCTP, enb_id, message_p);
+}
+
+void *m3ap_MME_task(void *arg) {
+  MessageDef *received_msg = NULL;
+  int         result;
+  M3AP_DEBUG("Starting M3AP layer\n");
+  m3ap_MME_prepare_internal_data();
+  itti_mark_task_ready(TASK_M3AP_MME);
+
+  //MME_task_send_sctp_init_req(0,NULL);
+
+
+  while (1) {
+    itti_receive_msg(TASK_M3AP_MME, &received_msg);
+
+    switch (ITTI_MSG_ID(received_msg)) {
+      case MESSAGE_TEST:
+	LOG_W(M3AP,"MME Received MESSAGE_TEST Message\n");
+	//MessageDef * message_p = itti_alloc_new_message(TASK_M3AP_MME, MESSAGE_TEST);
+        //itti_send_msg_to_task(TASK_M3AP, 1/*ctxt_pP->module_id*/, message_p);
+	break;
+      case TERMINATE_MESSAGE:
+        M3AP_WARN(" *** Exiting M3AP thread\n");
+        itti_exit_task();
+        break;
+
+//      case M3AP_SUBFRAME_PROCESS:
+//        m3ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg));
+//        break;
+//
+//      case M3AP_REGISTER_MME_REQ:
+//	LOG_W(M3AP,"MME Received M3AP_REGISTER_MME_REQ Message\n");
+//        m3ap_MME_handle_register_MME(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                     &M3AP_REGISTER_MME_REQ(received_msg));
+//        break;
+//
+
+      case M3AP_MME_SCTP_REQ:
+  	MME_task_send_sctp_init_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+				    &M3AP_MME_SCTP_REQ(received_msg));
+	break;
+
+      case M3AP_SETUP_RESP:
+	LOG_I(M3AP,"MME Received M3AP_SETUP_RESP Message\n");
+	MME_send_M3_SETUP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+				    &M3AP_SETUP_RESP(received_msg));
+	break;
+//	break;
+//
+//      case M3AP_SETUP_FAILURE:
+//	LOG_W(M3AP,"MME Received M3AP_SETUP_FAILURE Message\n");
+//	MME_send_M2_SETUP_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//				    &M3AP_SETUP_FAILURE(received_msg));
+//	break;
+//
+//      case M3AP_MBMS_SCHEDULING_INFORMATION:
+//	LOG_W(M3AP,"MME Received M3AP_MBMS_SCHEDULING_INFORMATION Message\n");
+//        MME_send_MBMS_SCHEDULING_INFORMATION(0,
+//						&M3AP_MBMS_SCHEDULING_INFORMATION(received_msg));
+//
+       case M3AP_MBMS_SESSION_START_REQ:
+	LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_START_REQ Message\n");
+        MME_send_MBMS_SESSION_START_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+						&M3AP_MBMS_SESSION_START_REQ(received_msg));
+	break;
+//
+       case M3AP_MBMS_SESSION_STOP_REQ:
+	LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_STOP_REQ Message\n");
+        MME_send_MBMS_SESSION_STOP_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+						&M3AP_MBMS_SESSION_STOP_REQ(received_msg));
+	break;
+//	
+       case M3AP_MBMS_SESSION_UPDATE_REQ:
+	LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_UPDATE_REQ Message\n");
+       // MME_send_MBMS_SESSION_UPDATE_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+	//					&M3AP_MBMS_SESSION_UPDATE_REQ(received_msg));
+	break;
+//
+//       case M3AP_RESET:
+//	LOG_W(M3AP,"MME Received M3AP_RESET Message\n");
+//        MME_send_RESET(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//						&M3AP_RESET(received_msg));
+//	break;
+//
+//       case M3AP_ENB_CONFIGURATION_UPDATE_ACK:
+//	LOG_W(M3AP,"MME Received M3AP_ENB_CONFIGURATION_UPDATE_ACK Message\n");
+//        MME_send_ENB_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//						&M3AP_ENB_CONFIGURATION_UPDATE_ACK(received_msg));
+//	break;
+//
+//       case M3AP_ENB_CONFIGURATION_UPDATE_FAILURE:
+//	LOG_W(M3AP,"MME Received M3AP_ENB_CONFIGURATION_UPDATE_FAILURE Message\n");
+//        MME_send_ENB_CONFIGURATION_UPDATE_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//						&M3AP_ENB_CONFIGURATION_UPDATE_FAILURE(received_msg))//	break;
+//
+//
+//       case M3AP_MME_CONFIGURATION_UPDATE:
+//	LOG_W(M3AP,"MME Received M3AP_MME_CONFIGURATION_UPDATE Message\n");
+//        MME_send_MME_CONFIGURATION_UPDATE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//						&M3AP_MME_CONFIGURATION_UPDATE(received_msg));
+//	break;
+//
+
+//      case M3AP_HANDOVER_REQ:
+//        m3ap_MME_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                     &M3AP_HANDOVER_REQ(received_msg));
+//        break;
+//
+//      case M3AP_HANDOVER_REQ_ACK:
+//        m3ap_MME_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                         &M3AP_HANDOVER_REQ_ACK(received_msg));
+//        break;
+//
+//      case M3AP_UE_CONTEXT_RELEASE:
+//        m3ap_MME_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                                &M3AP_UE_CONTEXT_RELEASE(received_msg));
+//        break;
+//
+      case SCTP_INIT_MSG_MULTI_CNF:
+        LOG_E(M3AP,"MME Received SCTP_INIT_MSG_MULTI_CNF Message ... shoudn't be happening ... it doesn't at leaast with M2AP_MCEC\n");
+        m3ap_MME_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                               &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_RESP:
+        LOG_D(M3AP,"MME Received SCTP_NEW_ASSOCIATION_RESP Message\n");
+        m3ap_MME_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                              &received_msg->ittiMsg.sctp_new_association_resp);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_IND:
+        LOG_D(M3AP,"MME Received SCTP_NEW_ASSOCIATION Message\n");
+        m3ap_MME_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                             &received_msg->ittiMsg.sctp_new_association_ind);
+        break;
+
+      case SCTP_DATA_IND:
+        LOG_D(M3AP,"MME Received SCTP_DATA_IND Message\n");
+        m3ap_MME_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                      &received_msg->ittiMsg.sctp_data_ind);
+        break;
+
+      default:
+        M3AP_ERROR("MME Received unhandled message: %d:%s\n",
+                   ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
+        break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    received_msg = NULL;
+  }
+
+  return NULL;
+}
+
+#include "common/config/config_userapi.h"
+
+int is_m3ap_MME_enabled(void)
+{
+  static volatile int config_loaded = 0;
+  static volatile int enabled = 0;
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+  if (pthread_mutex_lock(&mutex)) goto mutex_error;
+
+  if (config_loaded) {
+    if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+    return enabled;
+  }
+
+  char *enable_m3 = NULL;
+  paramdef_t p[] = {
+   { "enable_mme_m3", "yes/no", 0, strptr:&enable_m3, defstrval:"", TYPE_STRING, 0 }
+  };
+
+  /* TODO: do it per module - we check only first MME */
+  config_get(p, sizeof(p)/sizeof(paramdef_t), "MMEs.[0]");
+  if (enable_m3 != NULL && strcmp(enable_m3, "yes") == 0)
+    enabled = 1;
+
+  config_loaded = 1;
+
+  if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+
+  return enabled;
+
+mutex_error:
+  LOG_E(M3AP, "mutex error\n");
+  exit(1);
+}
diff --git a/openair3/M3AP/m3ap_MME.h b/openair3/M3AP/m3ap_MME.h
new file mode 100644
index 0000000000000000000000000000000000000000..f5d1b158e430a2445aff3a97869985a83c0e2abb
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME.h
+ * \brief m3ap tasks for MME
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+/** @defgroup _m3ap_impl_ M3AP Layer Reference Implementation
+ * @ingroup _ref_implementation_
+ * @{
+ */
+
+#ifndef M3AP_MME_H_
+#define M3AP_MME_H_
+
+#include "m3ap_MME_defs.h"
+
+
+int m3ap_MME_init_sctp (m3ap_MME_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t enb_port_for_M3C);
+
+void *m3ap_MME_task(void *arg);
+
+int is_m3ap_MME_enabled(void);
+
+#endif /* M3AP_MCE_H_ */
+
+/**
+ * @}
+ */
diff --git a/openair3/M3AP/m3ap_MME_defs.h b/openair3/M3AP/m3ap_MME_defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b5725655de153cd605793838ce27aa9df2b31af
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_defs.h
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME_defs.h
+ * \brief m2ap struct definitions for MME
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "queue.h"
+#include "tree.h"
+
+#include "sctp_eNB_defs.h"
+
+#include "m3ap_ids.h" //looks X2AP specific for HO
+#include "m3ap_timers.h"
+
+#ifndef M3AP_MME_DEFS_H_
+#define M3AP_MME_DEFS_H_
+
+#define M3AP_MME_NAME_LENGTH_MAX    (150)
+
+typedef enum {
+  /* Disconnected state: initial state for any association. */
+  M3AP_MME_STATE_DISCONNECTED = 0x0,
+
+  /* State waiting for m2 Setup response message if the target MME accepts or
+   * M2 Setup failure if rejects the MME.
+   */
+  M3AP_MME_STATE_WAITING     = 0x1,
+
+  /* The MME is successfully connected to another MME. */
+  M3AP_MME_STATE_CONNECTED   = 0x2,
+
+  /* M3AP is ready, and the MME is successfully connected to another MME. */
+  M3AP_MME_STATE_READY             = 0x3,
+
+  M3AP_MME_STATE_OVERLOAD          = 0x4,
+
+  M3AP_MME_STATE_RESETTING         = 0x5,
+
+  /* Max number of states available */
+  M3AP_MME_STATE_MAX,
+} m3ap_MME_state_t;
+
+/* Served PLMN identity element */
+/*struct plmn_identity_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+  STAILQ_ENTRY(plmn_identity_s) next;
+};*/
+
+/* Served group id element */
+/*struct served_group_id_s {
+  uint16_t mce_group_id;
+  STAILQ_ENTRY(served_group_id_s) next;
+};*/
+
+/* Served enn code for a particular MME */
+/*struct mce_code_s {
+  uint8_t mce_code;
+  STAILQ_ENTRY(mce_code_s) next;
+};*/
+
+struct m3ap_MME_instance_s;
+
+/* This structure describes association of a MME to another MME */
+typedef struct m3ap_MME_data_s {
+  /* MME descriptors tree, ordered by sctp assoc id */
+  RB_ENTRY(m3ap_MME_data_s) entry;
+
+  /* This is the optional name provided by the MME */
+  char *MME_name;
+
+  /*  target MME ID */
+  uint32_t MME_id;
+
+  /* Current MME load information (if any). */
+  //m3ap_load_state_t overload_state;
+
+  /* Current MME->MME M3AP association state */
+  m3ap_MME_state_t state;
+
+  /* Next usable stream for UE signalling */
+  int32_t nextstream;
+
+  /* Number of input/ouput streams */
+  uint16_t in_streams;
+  uint16_t out_streams;
+
+  /* Connexion id used between SCTP/M3AP */
+  uint16_t cnx_id;
+
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* Nid cells */
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* Only meaningfull in virtual mode */
+  struct m3ap_MME_instance_s *m3ap_MME_instance;
+} m3ap_MME_data_t;
+
+typedef struct m3ap_MME_instance_s {
+  /* used in simulation to store multiple MME instances*/
+  STAILQ_ENTRY(m3ap_MME_instance_s) m3ap_MME_entries;
+
+  /* Number of target MMEs requested by MME (tree size) */
+  uint32_t m2_target_mce_nb;
+  /* Number of target MMEs for which association is pending */
+  uint32_t m2_target_mce_pending_nb;
+  /* Number of target MME successfully associated to MME */
+  uint32_t m2_target_mce_associated_nb;
+  /* Tree of M3AP MME associations ordered by association ID */
+  RB_HEAD(m3ap_mme_map, m3ap_MME_data_s) m3ap_mme_head;
+
+  /* Tree of UE ordered by MME_ue_m3ap_id's */
+  //  RB_HEAD(m3ap_ue_map, m3ap_MME_ue_context_s) m3ap_ue_head;
+
+  /* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
+  instance_t instance;
+
+  /* Displayable name of MME */
+  char *MME_name;
+
+  /* Unique MME_id to identify the MME within EPC.
+   * In our case the MME is a macro MME so the id will be 20 bits long.
+   * For Home MME id, this field should be 28 bits long.
+   */
+  uint32_t MME_id;
+  /* The type of the cell */
+  cell_type_t cell_type;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t  mcc;
+  uint16_t  mnc;
+  uint8_t   mnc_digit_length;
+
+  /* CC params */
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int16_t                 N_RB_DL[MAX_NUM_CCs];
+  lte_frame_type_t        frame_type[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
+  net_ip_address_t target_mme_m3_ip_address[M3AP_MAX_NB_MME_IP_ADDRESS];
+  uint8_t          nb_m3;
+  net_ip_address_t mme_m3_ip_address;
+  uint16_t         sctp_in_streams;
+  uint16_t         sctp_out_streams;
+  uint32_t         mme_port_for_M3C;
+  int              multi_sd;
+
+  m3ap_id_manager  id_manager;
+  m3ap_timers_t    timers;
+} m3ap_MME_instance_t;
+
+typedef struct {
+  /* List of served MMEs
+   * Only used for virtual mode
+   */
+  STAILQ_HEAD(m3ap_MME_instances_head_s, m3ap_MME_instance_s) m3ap_MME_instances_head;
+  /* Nb of registered MMEs */
+  uint8_t nb_registered_MMEs;
+
+  /* Generate a unique connexion id used between M3AP and SCTP */
+  uint16_t global_cnx_id;
+} m3ap_MME_internal_data_t;
+
+int m3ap_MME_compare_assoc_id(struct m3ap_MME_data_s *p1, struct m3ap_MME_data_s *p2);
+
+/* Generate the tree management functions */
+struct m3ap_MME_map;
+struct m3ap_MME_data_s;
+RB_PROTOTYPE(m3ap_MME_map, m3ap_MME_data_s, entry, m3ap_MME_compare_assoc_id);
+
+
+#endif /* M3AP_MME_DEFS_H_ */
diff --git a/openair3/M3AP/m3ap_MME_generate_messages.c b/openair3/M3AP/m3ap_MME_generate_messages.c
new file mode 100644
index 0000000000000000000000000000000000000000..a28097cf1afe014dbc74681c0f5a1fa55b57a71b
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_generate_messages.c
@@ -0,0 +1,804 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_generate_messages.c
+ * \brief m2ap procedures for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+//#include "M2AP_LastVisitedCell-Item.h"
+
+#include "m2ap_common.h"
+#include "m2ap_MCE.h"
+#include "m2ap_MCE_generate_messages.h"
+#include "m2ap_encoder.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+#include "m2ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+int m2ap_MCE_generate_m2_setup_request(
+  m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupRequest_t              *out;
+  M2AP_M2SetupRequest_Ies_t          *ie;
+  //M2AP_PLMN_Identity_t               *plmn;
+  //ServedCells__Member                *servedCellMember;
+  //M2AP_GU_Group_ID_t                 *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(m2ap_MCE_data_p != NULL);
+
+  m2ap_MCE_data_p->state = M2AP_MCE_STATE_WAITING;
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_M2SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M2SetupRequest;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GlobalMCE_ID;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_IEs__value_PR_GlobalMCE_ID;
+  //MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &ie->value.choice.GlobalMCE_ID.pLMN_Identity);
+  //ie->value.choice.GlobalMCE_ID.MCE_ID.present = M2AP_MCE_ID_PR_macro_MCE_ID;
+  //MACRO_MCE_ID_TO_BIT_STRING(instance_p->MCE_id,
+  //                           &ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID);
+  //M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->MCE_id,
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[0],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[1],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_IEs__value_PR_ServedCells;
+  //{
+  //  for (int i = 0; i<instance_p->num_cc; i++){
+  //    servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
+  //    {
+  //      servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
+
+  //      MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                    &servedCellMember->servedCellInfo.cellId.pLMN_Identity);
+  //      MACRO_MCE_ID_TO_CELL_IDENTITY(instance_p->MCE_id,0,
+  //                                 &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+
+  //      INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+  //      plmn = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_PLMN_Identity_t));
+  //      {
+  //        MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
+  //        ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
+  //      }
+
+  //      if (instance_p->frame_type[i] == FDD) {
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = M2AP_EUTRA_Mode_Info_PR_fDD;
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
+  //        switch (instance_p->N_RB_DL[i]) {
+  //          case 6:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            break;
+  //          case 15:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            break;
+  //          case 25:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            break;
+  //          case 50:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            break;
+  //          case 75:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            break;
+  //          case 100:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            break;
+  //          default:
+  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+  //            break;
+  //        }
+  //      }
+  //      else {
+  //        AssertFatal(0,"M2Setuprequest not supported for TDD!");
+  //      }
+  //    }
+  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+  //  }
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_IEs__value_PR_GUGroupIDList;
+  //{
+  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_GU_Group_ID_t));
+  //  {
+  //    MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &gu->pLMN_Identity);
+  //    //@TODO: consider to update this value
+  //    INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
+  //  }
+  //  ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup request\n");
+    return -1;
+  }
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 M2Setup/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_generate_m2_setup_response(m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupResponse_t              *out;
+  M2AP_M2SetupResponse_Ies_t          *ie;
+  //M2AP_PLMN_Identity_t                *plmn;
+  //ServedCells__Member                 *servedCellMember;
+  //M2AP_GU_Group_ID_t                  *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(m2ap_MCE_data_p != NULL);
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_M2SetupResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.M2SetupResponse;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GlobalMCE_ID;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GlobalMCE_ID;
+  //MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &ie->value.choice.GlobalMCE_ID.pLMN_Identity);
+  //ie->value.choice.GlobalMCE_ID.MCE_ID.present = M2AP_MCE_ID_PR_macro_MCE_ID;
+  //MACRO_MCE_ID_TO_BIT_STRING(instance_p->MCE_id,
+  //                           &ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID);
+  //M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->MCE_id,
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[0],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[1],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_ServedCells;
+  //{
+  //  for (int i = 0; i<instance_p->num_cc; i++){
+  //    servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
+  //    {
+  //      servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
+
+  //      MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                    &servedCellMember->servedCellInfo.cellId.pLMN_Identity);
+  //      MACRO_MCE_ID_TO_CELL_IDENTITY(instance_p->MCE_id,0,
+  //                                 &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+
+  //      INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+  //      plmn = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_PLMN_Identity_t));
+  //      {
+  //        MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
+  //        ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
+  //      }
+
+  //      if (instance_p->frame_type[i] == FDD) {
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = M2AP_EUTRA_Mode_Info_PR_fDD;
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
+  //        servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
+  //        switch (instance_p->N_RB_DL[i]) {
+  //          case 6:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            break;
+  //          case 15:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            break;
+  //          case 25:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            break;
+  //          case 50:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            break;
+  //          case 75:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            break;
+  //          case 100:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            break;
+  //          default:
+  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+  //            break;
+  //        }
+  //      }
+  //      else {
+  //        AssertFatal(0,"M2Setupresponse not supported for TDD!");
+  //      }
+  //    }
+  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+  //  }
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GUGroupIDList;
+  //{
+  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_GU_Group_ID_t));
+  //  {
+  //    MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &gu->pLMN_Identity);
+  //    //@TODO: consider to update this value
+  //    INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
+  //  }
+  //  ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup response\n");
+    return -1;
+  }
+
+  m2ap_MCE_data_p->state = M2AP_MCE_STATE_READY;
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 M2Setup/successfulOutcome assoc_id %u", m2ap_MCE_data_p->assoc_id);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupFailure_t              *out;
+  M2AP_M2SetupFailure_Ies_t          *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+  pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.unsuccessfulOutcome.criticality = M2AP_Criticality_reject;
+  pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_Cause;
+  //ie->criticality = M2AP_Criticality_ignore;
+  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_Cause;
+
+  //m2ap_MCE_set_cause (&ie->value.choice.Cause, cause_type, cause_value);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional: consider to handle this later */
+  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_TimeToWait;
+  //ie->criticality = M2AP_Criticality_ignore;
+  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_TimeToWait;
+
+  //if (time_to_wait > -1) {
+  //  ie->value.choice.TimeToWait = time_to_wait;
+  //}
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup failure\n");
+    return -1;
+  }
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE,
+  //                    MSC_M2AP_TARGET_MCE, NULL, 0,
+  //                    "0 M2Setup/unsuccessfulOutcome  assoc_id %u cause %u value %u",
+  //                    assoc_id, cause_type, cause_value);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value)
+{
+
+  DevAssert (cause_p != NULL);
+  cause_p->present = cause_type;
+
+  switch (cause_type) {
+  case M2AP_Cause_PR_radioNetwork:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_transport:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_protocol:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_misc:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+//int m2ap_MCE_generate_m2_handover_request (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id)
+//{
+//
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_HandoverRequest_t              *out;
+//  M2AP_HandoverRequest_IEs_t          *ie;
+//  M2AP_E_RABs_ToBeSetup_ItemIEs_t     *e_RABS_ToBeSetup_ItemIEs;
+//  M2AP_E_RABs_ToBeSetup_Item_t        *e_RABs_ToBeSetup_Item;
+//  M2AP_LastVisitedCell_Item_t         *lastVisitedCell_Item;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverRequest;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_Cause;
+//  ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetCell_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_ECGI;
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &ie->value.choice.ECGI.pLMN_Identity);
+//  MACRO_MCE_ID_TO_CELL_IDENTITY(m2ap_MCE_data_p->MCE_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_GUMMEI_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_GUMMEI;
+//  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &ie->value.choice.GUMMEI.gU_Group_ID.pLMN_Identity);
+//  //@TODO: consider to update these values
+//  INT16_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
+//  MME_CODE_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_ContextInformation;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
+//  //@TODO: consider to update this value
+//  ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = m2ap_handover_req->mme_ue_s1ap_id;
+//
+//  KMCE_STAR_TO_BIT_STRING(m2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
+//
+//  if (m2ap_handover_req->kenb_ncc >=0) { // Check this condition
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = m2ap_handover_req->kenb_ncc;
+//  }
+//  else {
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
+//  }
+//
+//  ENCRALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.encryption_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+//
+//  INTPROTALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.integrity_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
+//
+//  //@TODO: update with proper UEAMPR
+//  UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
+//  UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
+//  {
+//    for (int i=0;i<m2ap_handover_req->nb_e_rabs_tobesetup;i++) {
+//      e_RABS_ToBeSetup_ItemIEs = (M2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_ToBeSetup_ItemIEs_t));
+//      e_RABS_ToBeSetup_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
+//      e_RABS_ToBeSetup_ItemIEs->criticality = M2AP_Criticality_ignore;
+//      e_RABS_ToBeSetup_ItemIEs->value.present = M2AP_E_RABs_ToBeSetup_ItemIEs__value_PR_E_RABs_ToBeSetup_Item;
+//      e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
+//      {
+//        e_RABs_ToBeSetup_Item->e_RAB_ID = m2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = m2ap_handover_req->e_rab_param[i].qos.qci;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(m2ap_handover_req->e_rabs_tobesetup[i].MCE_addr.length/8);
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = m2ap_handover_req->e_rabs_tobesetup[i].MCE_addr.length%8;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf =
+//                        calloc(1,e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        memcpy (e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
+//                        m2ap_handover_req->e_rabs_tobesetup[i].MCE_addr.buffer,
+//                        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        INT32_TO_OCTET_STRING(m2ap_handover_req->e_rabs_tobesetup[i].gtp_teid,&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID);
+//      }
+//      ASN_SEQUENCE_ADD(&ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list, e_RABS_ToBeSetup_ItemIEs);
+//    }
+//  }
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.UE_ContextInformation.rRC_Context, (char*) m2ap_handover_req->rrc_buffer, m2ap_handover_req->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_HistoryInformation;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
+//  //@TODO: consider to update this value
+//  {
+//   lastVisitedCell_Item = (M2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(M2AP_LastVisitedCell_Item_t));
+//   lastVisitedCell_Item->present = M2AP_LastVisitedCell_Item_PR_e_UTRAN_Cell;
+//   MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                       &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
+//   MACRO_MCE_ID_TO_CELL_IDENTITY(0, 0, &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
+//   lastVisitedCell_Item->choice.e_UTRAN_Cell.cellType.cell_Size = M2AP_Cell_Size_small;
+//   lastVisitedCell_Item->choice.e_UTRAN_Cell.time_UE_StayedInCell = 2;
+//   ASN_SEQUENCE_ADD(&ie->value.choice.UE_HistoryInformation.list, lastVisitedCell_Item);
+//  }
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover request\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_handover_request_ack (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack)
+//{
+//
+//  M2AP_M2AP_PDU_t                        pdu;
+//  M2AP_HandoverRequestAcknowledge_t      *out;
+//  M2AP_HandoverRequestAcknowledge_IEs_t  *ie;
+//  M2AP_E_RABs_Admitted_ItemIEs_t         *e_RABS_Admitted_ItemIEs;
+//  M2AP_E_RABs_Admitted_Item_t            *e_RABs_Admitted_Item;
+//  int                                    ue_id;
+//  int                                    id_source;
+//  int                                    id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id     = m2ap_handover_req_ack->m2_id_target;
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
+//  out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
+//
+//  {
+//      for (int i=0;i<m2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
+//        e_RABS_Admitted_ItemIEs = (M2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_Admitted_ItemIEs_t));
+//        e_RABS_Admitted_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
+//        e_RABS_Admitted_ItemIEs->criticality = M2AP_Criticality_ignore;
+//        e_RABS_Admitted_ItemIEs->value.present = M2AP_E_RABs_Admitted_ItemIEs__value_PR_E_RABs_Admitted_Item;
+//        e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
+//        {
+//          e_RABs_Admitted_Item->e_RAB_ID = m2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
+//        }
+//        ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_List.list, e_RABS_Admitted_ItemIEs);
+//      }
+//  }
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetMCEtoSource_MCETransparentContainer;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_TargetMCEtoSource_MCETransparentContainer;
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.TargetMCEtoSource_MCETransparentContainer, (char*) m2ap_handover_req_ack->rrc_buffer, m2ap_handover_req_ack->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover response\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_ue_context_release (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p, m2ap_ue_context_release_t *m2ap_ue_context_release)
+//{
+//
+//  M2AP_M2AP_PDU_t                pdu;
+//  M2AP_UEContextRelease_t        *out;
+//  M2AP_UEContextRelease_IEs_t    *ie;
+//  int                            ue_id;
+//  int                            id_source;
+//  int                            id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id = m2ap_find_id_from_rnti(&instance_p->id_manager, m2ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not find UE %x\n", m2ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP ue context relase message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_uEContextRelease;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_UEContextRelease;
+//  out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 UE Context Release\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_handover_cancel (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause)
+//{
+//  M2AP_M2AP_PDU_t              pdu;
+//  M2AP_HandoverCancel_t        *out;
+//  M2AP_HandoverCancel_IEs_t    *ie;
+//  int                          ue_id;
+//  int                          id_source;
+//  int                          id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id = m2_ue_id;
+//  id_source = ue_id;
+//  id_target = m2ap_id_get_id_target(&instance_p->id_manager, ue_id);
+//
+//  /* Prepare the M2AP handover cancel message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverCancel;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverCancel;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  if (id_target != -1) {
+//    ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//    ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//    ie->criticality = M2AP_Criticality_ignore;
+//    ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID_1;
+//    ie->value.choice.UE_M2AP_ID_1 = id_target;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_Cause;
+//  switch (cause) {
+//  case M2AP_T_RELOC_PREP_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_trelocprep_expiry;
+//    break;
+//  case M2AP_TX2_RELOC_OVERALL_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_tx2relocoverall_expiry;
+//    break;
+//  default:
+//    /* we can't come here */
+//    M2AP_ERROR("unhandled cancel cause\n");
+//    exit(1);
+//  }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 Handover Cancel\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
diff --git a/openair3/M3AP/m3ap_MME_generate_messages.h b/openair3/M3AP/m3ap_MME_generate_messages.h
new file mode 100644
index 0000000000000000000000000000000000000000..1632dc807acc307de1af06650f2f824272239c7a
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_generate_messages.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_generate_messages.h
+ * \brief m2ap procedures for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_GENERATE_MESSAGES_H_
+#define M2AP_MCE_GENERATE_MESSAGES_H_
+
+#include "m2ap_MCE_defs.h"
+#include "m2ap_common.h"
+
+int m2ap_MCE_generate_m2_setup_request(m2ap_MCE_instance_t *instance_p,
+				       m2ap_MCE_data_t *m2ap_MCE_data_p);
+
+int m2ap_MCE_generate_m2_setup_response(m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p);
+
+int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait);
+
+int m2ap_MCE_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value);
+
+//int m2ap_MCE_generate_m2_handover_request (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id);
+//
+//int m2ap_MCE_generate_m2_handover_request_ack (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack);
+//
+//int m2ap_MCE_generate_m2_ue_context_release (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                             m2ap_ue_context_release_t *m2ap_ue_context_release);
+//
+//int m2ap_MCE_generate_m2_handover_cancel (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause);
+
+#endif /*  M2AP_MCE_GENERATE_MESSAGES_H_ */
diff --git a/openair3/M3AP/m3ap_MME_handler.c b/openair3/M3AP/m3ap_MME_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..9af8cbe14fc351e39f73162ae13b2c4473c42673
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_handler.c
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_handler.c
+ * \brief m3ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MME_defs.h"
+#include "m3ap_handler.h"
+#include "m3ap_decoder.h"
+#include "m3ap_ids.h"
+
+#include "m3ap_MME_management_procedures.h"
+//#include "m3ap_MCE_generate_messages.h"
+
+#include "m3ap_MME_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m3ap_MCE_message_decoded_callback m3ap_MME_messages_callback[][3] = {
+  { 0, MME_handle_MBMS_SESSION_START_RESPONSE, 0 }, /* MBMSSessionStart  */
+  { 0, MME_handle_MBMS_SESSION_STOP_RESPONSE, 0 }, /* MBMSSessionStop */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { 0, 0, 0 }, /* ??? */
+  { 0, MME_handle_MBMS_SESSION_UPDATE_RESPONSE, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { MME_handle_M3_SETUP_REQUEST, 0, 0 } /* M3 Setup */
+};
+
+static char *m3ap_direction2String(int m3ap_dir) {
+static char *m3ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m3ap_direction_String[m3ap_dir]);
+}
+
+
+int m3ap_MME_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M3AP_M3AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+ 
+  if (m3ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M3AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m3ap_MME_messages_callback) / (3 * sizeof(
+        m3ap_message_decoded_callback))
+      || (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M3AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
+               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m3ap_MME_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M3AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m3ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M3AP, "Calling handler with instance %d\n",instance);
+  ret = (*m3ap_MME_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair3/M3AP/m3ap_MME_handler.h b/openair3/M3AP/m3ap_MME_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..feabfe256c44adced52b8d3d6948581d7c97a00a
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_handler.h
+ * \brief m3ap handler procedures for MME
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_MME_HANDLERS_H_
+#define M3AP_MME_HANDLERS_H_
+
+#include "m3ap_MME_defs.h"
+
+//void m3ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+//int m3ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            //const uint8_t * const data, const uint32_t data_length);
+
+int m3ap_MME_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M3AP_MME_HANDLERS_H_ */
diff --git a/openair3/M3AP/m3ap_MME_interface_management.c b/openair3/M3AP/m3ap_MME_interface_management.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5cb03cf263cf0444f9d155ea9b5c1634e881981
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_interface_management.c
@@ -0,0 +1,1162 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME_interface_management.c
+ * \brief m3ap interface management for MME
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "m3ap_common.h"
+#include "m3ap_encoder.h"
+#include "m3ap_decoder.h"
+#include "m3ap_itti_messaging.h"
+#include "m3ap_MME_interface_management.h"
+
+#include "conversions.h"
+
+#include "M3AP_ECGI.h"
+
+extern m3ap_setup_req_t *m3ap_mme_data_from_mce;
+
+
+
+uint8_t m3ap_start_message[] = {
+  0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00,
+  0x07, 0x00, 0x55, 0xf5, 0x01, 0x00, 0x00, 0x01,
+  0x00, 0x04, 0x00, 0x0d, 0x60, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 0x01,
+  0x7a, 0x00, 0x05, 0x00, 0x03, 0x07, 0x08, 0x00,
+  0x00, 0x06, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+  0x0e, 0x00, 0xe8, 0x0a, 0x0a, 0x0a, 0x00, 0x0a,
+  0xc8, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x01
+};
+
+
+/*
+ * MBMS Session start
+ */
+int MME_send_MBMS_SESSION_START_REQUEST(instance_t instance/*, uint32_t assoc_id*/,m3ap_session_start_req_t* m3ap_session_start_req){
+
+  //AssertFatal(1==0,"Not implemented yet\n");
+    
+  //module_id_t enb_mod_idP=0;
+  //module_id_t du_mod_idP=0;
+
+  M3AP_M3AP_PDU_t          pdu; 
+  M3AP_MBMSSessionStartRequest_t       *out;
+  M3AP_MBMSSessionStartRequest_IEs_t   *ie;
+
+  uint8_t *buffer;
+  uint32_t len;
+  //int	   i=0; 
+  //int 	   j=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M3AP_InitiatingMessage_t *)calloc(1, sizeof(M3AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_mBMSsessionStart;
+  pdu.choice.initiatingMessage.criticality   = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_MBMSSessionStartRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.MBMSSessionStartRequest; 
+
+  /* mandatory */
+  /* c1. MME_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MME_MBMS_M3AP_ID;
+  //ie->value.choice.MME_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. TMGI */ 
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_TMGI; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_TMGI;
+  M3AP_TMGI_t	*tmgi 		= &ie->value.choice.TMGI;
+  {
+	  MCC_MNC_TO_PLMNID(0,0,3,&tmgi->pLMNidentity);
+	  uint8_t TMGI[5] = {4,3,2,1,0};
+	  OCTET_STRING_fromBuf(&tmgi->serviceID,(const char*)&TMGI[2],3);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2. MBMS_Session_ID */
+  if(0){
+	  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Session_ID;
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_Session_ID;
+	  //M3AP_MBMS_Session_ID_t * mbms_session_id = &ie->value.choice.MBMS_Session_ID;
+
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* mandatory */
+  /* c2. MBMS_E_RAB_QoS_Parameters */ 
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_E_RAB_QoS_Parameters; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_E_RAB_QoS_Parameters;
+  M3AP_MBMS_E_RAB_QoS_Parameters_t * mbms_e_rab_qos_parameters = &ie->value.choice.MBMS_E_RAB_QoS_Parameters;
+  {
+	//M3AP_QCI_t * qci = &mbms_e_rab_qos_parameters->qCI; //long
+	mbms_e_rab_qos_parameters->qCI = 1;
+	//struct M3AP_GBR_QosInformation  *gbrQosInformation;     /* OPTIONAL */
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2. MBMS_Session_Duration */ 
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Session_Duration; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_Session_Duration; 
+  M3AP_MBMS_Session_Duration_t * mbms_session_duration = &ie->value.choice.MBMS_Session_Duration;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(mbms_session_duration,(const char*)&duration[2],3);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2 MBMS_Service_Area */
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Service_Area;
+  ie->criticality               = M3AP_Criticality_ignore;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_Service_Area;
+  M3AP_MBMS_Service_Area_t * mbms_service_area = &ie->value.choice.MBMS_Service_Area;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(mbms_service_area,(const char*)&duration[2],1);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2 MinimumTimeToMBMSDataTransfer */
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MinimumTimeToMBMSDataTransfer; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MinimumTimeToMBMSDataTransfer; 
+  M3AP_MinimumTimeToMBMSDataTransfer_t * minimumtimetombmsdatatransfer = &ie->value.choice.MinimumTimeToMBMSDataTransfer;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(minimumtimetombmsdatatransfer,(const char*)&duration[2],1);
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2 TNL_Information */
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_TNL_Information; 
+  ie->criticality               = M3AP_Criticality_ignore;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_TNL_Information; 
+  M3AP_TNL_Information_t * tnl_information = &ie->value.choice.TNL_Information;
+  {
+        //OCTET_STRING_fromBuf(&tnl_information->iPMCAddress,"1204",strlen("1234"));
+        //OCTET_STRING_fromBuf(&tnl_information->iPSourceAddress,"1204",strlen("1234"));
+        //OCTET_STRING_fromBuf(&tnl_information->gTP_DLTEID,"1204",strlen("1234"));
+	uint32_t gtp_dlteid = 1;
+	GTP_TEID_TO_ASN1(gtp_dlteid,&tnl_information->gTP_DLTEID);
+	//tnl_information->iPMCAddress.buf = calloc(4,sizeof(uint8_t));
+	//tnl_information->iPMCAddress.buf[0]
+	//tnl_information->iPMCAddress.buf[1]
+	//tnl_information->iPMCAddress.buf[2]
+	//tnl_information->iPMCAddress.buf[3]
+	//tnl_information->iPMCAddress.buf.size = 4;
+	uint32_t ip= (224<<24) | (0) << 16 | (0) << 8 | (2);
+	INT32_TO_OCTET_STRING(ip,&tnl_information->iPMCAddress);
+	ip= (224<<24) | (0) << 16 | (0) << 8 | (2);
+	INT32_TO_OCTET_STRING(ip,&tnl_information->iPSourceAddress);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2 Time_ofMBMS_DataTransfer */
+  if(0){
+	  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_Time_ofMBMS_DataTransfer; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_Absolute_Time_ofMBMS_Data; 
+	  //M3AP_Absolute_Time_ofMBMS_Data_t * absolute_time_ofmbms_data	= &ie->value.choice.Absolute_Time_ofMBMS_Data;
+	  //{
+		//char duration[5] = {4,3,2,1,0};
+		//OCTET_STRING_fromBuf(absolute_time_ofmbms_data,(const char*)&duration[2],3);
+	  //}
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* optional */
+  /* c2 MBMS_Cell_List */
+  if(0){
+	  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Cell_List; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_Cell_List; 
+	  M3AP_MBMS_Cell_List_t * mbms_cell_list = &ie->value.choice.MBMS_Cell_List;
+	  M3AP_ECGI_t * ecgi = (M3AP_ECGI_t*)calloc(1,sizeof(M3AP_ECGI_t));	
+	  {
+		//MCC_MNC_TO_PLMNID(0,0,3,ecgi->pLMN_Identity);
+		//MACRO_ENB_ID_TO_CELL_IDENTITY(1,0,ecgi->eUTRANcellIdentifier);
+		ASN_SEQUENCE_ADD(&mbms_cell_list->list,ecgi);
+	  }
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* encode */
+  if (m3ap_encode_pdu(&pdu,&buffer,&len) < 0){
+        return -1;
+  }
+
+  
+//  buffer = &m3ap_start_message[0];
+//  len=8*9+7;
+//
+  m3ap_MME_itti_send_sctp_data_req(instance, m3ap_mme_data_from_mce->assoc_id, buffer, len, 0);
+  
+  return 0;
+
+}
+
+int MME_handle_MBMS_SESSION_START_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu){
+//  AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "MME_handle_MBMS_SESSION_START_RESPONSE\n");
+
+   AssertFatal(pdu->present == M3AP_M3AP_PDU_PR_successfulOutcome,
+               "pdu->present != M3AP_M3AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M3AP_ProcedureCode_id_mBMSsessionStart,
+               "pdu->choice.successfulOutcome->procedureCode != M3AP_ProcedureCode_id_sessionStart\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M3AP_Criticality_reject,
+               "pdu->choice.successfulOutcome->criticality != M3AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M3AP_SuccessfulOutcome__value_PR_MBMSSessionStartResponse,
+               "pdu->choice.successfulOutcome.value.present != M3AP_SuccessfulOutcome__value_PR_MBMSSessionStartResponse\n");
+
+
+  M3AP_MBMSSessionStartResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.MBMSSessionStartResponse;
+  M3AP_MBMSSessionStartResponse_IEs_t  *ie;
+  int MME_MBMS_M3AP_ID=-1;
+  int MCE_MBMS_M3AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_START_RESP); //TODO
+
+  LOG_D(M3AP, "M3AP: SessionStart-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionStartResponse_IEs__value_PR_MME_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_sessionStartResponse_IEs__value_PR_MME_MBMS_M3AP_ID\n");
+       MME_MBMS_M3AP_ID=ie->value.choice.MME_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: SessionStart-Resp: MME_MBMS_M3AP_ID %d\n",
+             MME_MBMS_M3AP_ID);
+       break;
+      case M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionStartResponse_IEs__value_PR_MCE_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_sessionStartResponse_IEs__value_PR_MCE_MBMS_M3AP_ID\n");
+       MCE_MBMS_M3AP_ID=ie->value.choice.MCE_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: SessionStart-Resp: MCE_MBMS_M3AP_ID %d\n",
+             MCE_MBMS_M3AP_ID);
+       break;
+     }
+  }
+
+  //AssertFatal(MME_MBMS_M3AP_ID!=-1,"MME_MBMS_M3AP_ID was not sent\n");
+  //AssertFatal(MCE_MBMS_M3AP_ID!=-1,"MCE_MBMS_M3AP_ID was not sent\n");
+  ////M3AP_SESSION_START_RESP(msg_p).
+////  MSC_LOG_RX_MESSAGE(
+////    MSC_M3AP_MME,
+////    MSC_M3AP_MCE,
+  //      //return 0;
+////    0,
+////    0,
+////    MSC_AS_TIME_FMT" MME_handle_M2_SESSION_START_RESPONSE successfulOutcome assoc_id %d",
+////    0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+////    assoc_id);
+////
+  // LOG_W(M3AP, "Sending M3AP_SESSION_START_RESP ITTI message to MCE_APP with assoc_id (%d->%d)\n",
+  //       assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id));
+  itti_send_msg_to_task(TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g);
+  return 0;
+
+}
+int MME_handle_MBMS_SESSION_START_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+/*
+ * MBMS Session stop
+ */
+int MME_send_MBMS_SESSION_STOP_REQUEST(instance_t instance, m3ap_session_stop_req_t* m3ap_session_stop_req){
+
+    
+ // module_id_t enb_mod_idP=0;
+ // module_id_t du_mod_idP=0;
+
+  M3AP_M3AP_PDU_t          pdu; 
+  M3AP_MBMSSessionStopRequest_t        *out;
+  M3AP_MBMSSessionStopRequest_IEs_t    *ie;
+
+  uint8_t *buffer;
+  uint32_t len;
+  //int	   i=0; 
+  //int 	   j=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M3AP_InitiatingMessage_t *)calloc(1, sizeof(M3AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_mBMSsessionStop;
+  pdu.choice.initiatingMessage.criticality   = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_MBMSSessionStopRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.MBMSSessionStopRequest; 
+
+  /* mandatory */
+  /* c1. MME_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStopRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStopRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStopRequest_IEs__value_PR_MME_MBMS_M3AP_ID;
+  //ie->value.choice.MME_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStopRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStopRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStopRequest_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  /* encode */
+  if (m3ap_encode_pdu(&pdu,&buffer,&len) < 0){
+        return -1;
+  }
+
+  //MME_m3ap_itti_send_sctp_data_req(instance, m3ap_mce_data_from_mce->assoid,buffer,len,0); 
+  m3ap_MME_itti_send_sctp_data_req(instance, m3ap_mme_data_from_mce->assoc_id,buffer,len,0);
+  return 0;
+
+
+                        
+}
+
+int MME_handle_MBMS_SESSION_STOP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu){
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "eNB_handle_MBMS_SESSION_STOP_RESPONSE\n");
+
+   AssertFatal(pdu->present == M3AP_M3AP_PDU_PR_successfulOutcome,
+	       "pdu->present != M3AP_M3AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M3AP_ProcedureCode_id_mBMSsessionStop,
+	       "pdu->choice.successfulOutcome->procedureCode != M3AP_ProcedureCode_id_sessionStop\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M3AP_Criticality_reject,
+	       "pdu->choice.successfulOutcome->criticality != M3AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M3AP_SuccessfulOutcome__value_PR_MBMSSessionStopResponse,
+	       "pdu->choice.successfulOutcome->value.present != M3AP_SuccessfulOutcome__value_PR_MBMSSessionStopResponse\n");
+
+
+  M3AP_MBMSSessionStopResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.MBMSSessionStopResponse;
+  M3AP_MBMSSessionStopResponse_IEs_t  *ie;
+  int MME_MBMS_M3AP_ID=-1;
+  int MCE_MBMS_M3AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_STOP_RESP); //TODO
+
+  LOG_D(M3AP, "M3AP: MBMSSessionStop-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionStopResponse_IEs__value_PR_MME_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_MBMSStopResponse_IEs__value_PR_MME_MBMS_M3AP_ID\n");
+       MME_MBMS_M3AP_ID=ie->value.choice.MME_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: MBMSSessionStop-Resp: MME_MBMS_M3AP_ID %d\n",
+             MME_MBMS_M3AP_ID);
+       break;
+      case M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionStopResponse_IEs__value_PR_MCE_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_MBMSStopResponse_IEs__value_PR_MCE_MBMS_M3AP_ID\n");
+       MCE_MBMS_M3AP_ID=ie->value.choice.MCE_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: MBMSSessionStop-Resp: MCE_MBMS_M3AP_ID %d\n",
+             MCE_MBMS_M3AP_ID);
+       break;
+     }
+  }
+
+  //AssertFatal(MME_MBMS_M3AP_ID!=-1,"MME_MBMS_M3AP_ID was not sent\n");
+  //AssertFatal(MCE_MBMS_M3AP_ID!=-1,"MCE_MBMS_M3AP_ID was not sent\n");
+ // M3AP_SESSION_STOP_RESP(msg_p).
+ // MSC_LOG_RX_MESSAGE(
+ //   MSC_M3AP_MME,
+ //   MSC_M3AP_MCE,
+ //   0,
+ //   0,
+ //   MSC_AS_TIME_FMT" MME_handle_M2_SESSION_STOP_RESPONSE successfulOutcome assoc_id %d",
+ //   0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ //   assoc_id);
+
+ //  LOG_D(M3AP, "Sending M3AP_SESSION_START_RESP ITTI message to MCE_APP with assoc_id (%d->%d)\n",
+ //        assoc_id,MCE_MODULE_ID_TO_INSTANCE(assoc_id));
+   itti_send_msg_to_task(TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g);
+// //                      
+	return 0;
+}
+
+
+
+int MME_handle_MBMS_SESSION_STOP_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+                      
+}
+
+
+
+
+
+/*
+ * Reset
+ */
+
+int MME_send_RESET(instance_t instance, m3ap_reset_t * m3ap_reset) {
+  AssertFatal(1==0,"Not implemented yet\n");
+  //M3AP_Reset_t     Reset;
+                        
+}
+
+
+int MME_handle_RESET_ACKKNOWLEDGE(instance_t instance,
+                                  uint32_t assoc_id,
+                                  uint32_t stream,
+                                  M3AP_M3AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+int MME_handle_RESET(instance_t instance,
+                     uint32_t assoc_id,
+                     uint32_t stream,
+                     M3AP_M3AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+int MME_send_RESET_ACKNOWLEDGE(instance_t instance, M3AP_ResetAcknowledge_t *ResetAcknowledge) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+/*
+ *    M3 Setup
+ */
+int MME_handle_M3_SETUP_REQUEST(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu)
+{
+  LOG_D(M2AP, "MCE_handle_M3_SETUP_REQUEST assoc_id %d\n",assoc_id);
+
+  //AssertFatal(1==0,"Not implemented yet\n");
+//  LOG_W(M3AP, "MME_handle_M3_SETUP_REQUEST assoc_id %d\n",assoc_id);
+//
+    MessageDef                         *message_p;
+//  M3AP_M3SetupRequest_t              *container;
+//  M3AP_M3SetupRequestIEs_t           *ie;
+//  int i = 0,j=0;
+//
+//  DevAssert(pdu != NULL);
+//
+//  container = &pdu->choice.initiatingMessage.value.choice.M3SetupRequest;
+//
+//  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+//  if (stream != 0) {
+//    LOG_W(M3AP, "[SCTP %d] Received m3 setup request on stream != 0 (%d)\n",
+//              assoc_id, stream);
+//  }
+//
+    message_p = itti_alloc_new_message(TASK_M3AP_MME, M3AP_SETUP_REQ); 
+    //printf("M3AP_SETUP_REQ(message_p).assoc_id %d\n",M3AP_SETUP_REQ(message_p).assoc_id);
+//  
+//  /* assoc_id */
+    M3AP_SETUP_REQ(message_p).assoc_id = assoc_id;
+//
+// /* GlobalMCE_id */
+// // this function exits if the ie is mandatory
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupRequestIEs_t, ie, container,
+//                             M3AP_ProtocolIE_ID_id_Global_MCE_ID, true);
+//  asn_INTEGER2ulong(&ie->value.choice.GlobalMCE_ID, &M3AP_SETUP_REQ(message_p).GlobalMCE_ID);
+//  LOG_W(M3AP, "M3AP_SETUP_REQ(message_p).GlobalMCE_ID %lu \n", M3AP_SETUP_REQ(message_p).GlobalMCE_ID);
+//
+//  /* MCE_name */
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupRequestIEs_t, ie, container,
+//                              M3AP_ProtocolIE_ID_id_MCEname, true);
+//  M3AP_SETUP_REQ(message_p).MCEname = calloc(ie->value.choice.MCEname.size + 1, sizeof(char));
+//  memcpy(M3AP_SETUP_REQ(message_p).MCEname, ie->value.choice.MCEname.buf,
+//         ie->value.choice.MCEname.size);
+//
+//  /* Convert the mme name to a printable string */
+//  M3AP_SETUP_REQ(message_p).MCEname[ie->value.choice.MCEname.size] = '\0';
+//  LOG_W(M3AP, "M3AP_SETUP_REQ(message_p).gNB_DU_name %s \n", M3AP_SETUP_REQ(message_p).MCEname);
+//   /* MCE_MBMS_Configuration_data_List */
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupRequestIEs_t, ie, container,
+//                              M3AP_ProtocolIE_ID_id_MCE_MBMS_Configuration_data_List, true);
+//  M3AP_SETUP_REQ(message_p).num_mbms_available = ie->value.choice.MCE_MBMS_Configuration_data_List.list.count;
+//  LOG_W(M3AP, "M3AP_SETUP_REQ(message_p).num_mbms_available %d \n",
+//        M3AP_SETUP_REQ(message_p).num_mbms_available);
+//  int num_mbms_available = M3AP_SETUP_REQ(message_p).num_mbms_available;
+//  for (i=0; i<num_mbms_available; i++) {
+//	 M3AP_MCE_MBMS_Configuration_data_Item_t *mbms_configuration_item_p;
+//         mbms_configuration_item_p = &(((M3AP_MCE_MBMS_Configuration_data_ItemIEs_t *)ie->value.choice.MCE_MBMS_Configuration_data_List.list.array[i])->value.choice.MCE_MBMS_Configuration_data_Item);
+//    /* eCGI */
+//       //mbms_configuration_item_p->eCGI ... (M3AP_ECGI_t)
+//
+//    OCTET_STRING_TO_INT16(&(mbms_configuration_item_p->eCGI.pLMN_Identity),M3AP_SETUP_REQ(message_p).plmn_identity[i]);
+//    //OCTET_STRING_TO_INT16(&(mbms_configuration_item_p->eCGI.eUTRANcellIdentifier),M3AP_SETUP_REQ(message_p).eutran_cell_identifier[i]);
+//    /* mbsfnSynchronisationArea */
+//       //mbms_configuration_item_p->mbsfnSynchronisationArea ... (M3AP_MBSFN_SynchronisationArea_ID_t)
+//
+//    M3AP_SETUP_REQ(message_p).mbsfn_synchronization_area[i]=mbms_configuration_item_p->mbsfnSynchronisationArea;
+//    /* mbmsServiceAreaList */
+//       //mbms_configuration_item_p->mbmsServiceAreaList ... (M3AP_MBMS_Service_Area_ID_List_t)
+//   for(j=0;j<1;j++){
+//   	//OCTET_STRING_TO_INT16(&(mbms_configuration_item_p->mbmsServiceAreaList.list.array[j]), M3AP_SETUP_REQ(message_p).service_area_id[i][j]);
+//   }
+//
+// }
+//    
+////    /* tac */
+////    OCTET_STRING_TO_INT16(&(served_celles_item_p->served_Cell_Information.fiveGS_TAC), M3AP_SETUP_REQ(message_p).tac[i]);
+////    LOG_D(M3AP, "M3AP_SETUP_REQ(message_p).tac[%d] %d \n",
+////          i, M3AP_SETUP_REQ(message_p).tac[i]);
+////
+////    /* - nRCGI */
+////    TBCD_TO_MCC_MNC(&(served_celles_item_p->served_Cell_Information.nRCGI.pLMN_Identity), M3AP_SETUP_REQ(message_p).mcc[i],
+////                    M3AP_SETUP_REQ(message_p).mnc[i],
+////                    M3AP_SETUP_REQ(message_p).mnc_digit_length[i]);
+////    
+////    
+////    // NR cellID
+////    BIT_STRING_TO_NR_CELL_IDENTITY(&served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity,
+////				   M3AP_SETUP_REQ(message_p).nr_cellid[i]);
+////    LOG_D(M3AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
+////          M3AP_SETUP_REQ(message_p).mcc[i],
+////          M3AP_SETUP_REQ(message_p).mnc[i],
+////          (long long unsigned int)M3AP_SETUP_REQ(message_p).nr_cellid[i]);
+////    LOG_D(M3AP, "nr_cellId : %x %x %x %x %x\n",
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[0],
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[1],
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[2],
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[3],
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[4]);
+////    /* - nRPCI */
+////    M3AP_SETUP_REQ(message_p).nr_pci[i] = served_celles_item_p->served_Cell_Information.nRPCI;
+////    LOG_D(M3AP, "M3AP_SETUP_REQ(message_p).nr_pci[%d] %d \n",
+////          i, M3AP_SETUP_REQ(message_p).nr_pci[i]);
+////  
+////    // System Information
+////    /* mib */
+////    M3AP_SETUP_REQ(message_p).mib[i] = calloc(served_celles_item_p->gNB_DU_System_Information->mIB_message.size + 1, sizeof(char));
+////    memcpy(M3AP_SETUP_REQ(message_p).mib[i], served_celles_item_p->gNB_DU_System_Information->mIB_message.buf,
+////           served_celles_item_p->gNB_DU_System_Information->mIB_message.size);
+////    /* Convert the mme name to a printable string */
+////    M3AP_SETUP_REQ(message_p).mib[i][served_celles_item_p->gNB_DU_System_Information->mIB_message.size] = '\0';
+////    M3AP_SETUP_REQ(message_p).mib_length[i] = served_celles_item_p->gNB_DU_System_Information->mIB_message.size;
+////    LOG_D(M3AP, "M3AP_SETUP_REQ(message_p).mib[%d] %s , len = %d \n",
+////          i, M3AP_SETUP_REQ(message_p).mib[i], M3AP_SETUP_REQ(message_p).mib_length[i]);
+////
+////    /* sib1 */
+////    M3AP_SETUP_REQ(message_p).sib1[i] = calloc(served_celles_item_p->gNB_DU_System_Information->sIB1_message.size + 1, sizeof(char));
+////    memcpy(M3AP_SETUP_REQ(message_p).sib1[i], served_celles_item_p->gNB_DU_System_Information->sIB1_message.buf,
+////           served_celles_item_p->gNB_DU_System_Information->sIB1_message.size);
+////    /* Convert the mme name to a printable string */
+////    M3AP_SETUP_REQ(message_p).sib1[i][served_celles_item_p->gNB_DU_System_Information->sIB1_message.size] = '\0';
+////    M3AP_SETUP_REQ(message_p).sib1_length[i] = served_celles_item_p->gNB_DU_System_Information->sIB1_message.size;
+////    LOG_D(M3AP, "M3AP_SETUP_REQ(message_p).sib1[%d] %s , len = %d \n",
+////          i, M3AP_SETUP_REQ(message_p).sib1[i], M3AP_SETUP_REQ(message_p).sib1_length[i]);
+////  }
+//
+//
+    //printf("m3ap_mme_data_from_mce->assoc_id %d %d\n",m3ap_mme_data_from_mce->assoc_id,assoc_id);
+    *m3ap_mme_data_from_mce = M3AP_SETUP_REQ(message_p);
+    //printf("m3ap_mme_data_from_mce->assoc_id %d %d\n",m3ap_mme_data_from_mce->assoc_id,assoc_id);
+//
+////  MSC_LOG_TX_MESSAGE(
+////  MSC_M3AP_MME,
+////  MSC_RRC_MCE,
+////  0,
+////  0,
+////  MSC_AS_TIME_FMT" MME_handle_M3_SETUP_REQUEST",
+////  0,0//MSC_AS_TIME_ARGS(ctxt_pP),
+////  );
+////
+    itti_send_msg_to_task(TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+//  if (num_mbms_available > 0) {
+//    itti_send_msg_to_task(TASK_MME_APP, MCE_MODULE_ID_TO_INSTANCE(instance), message_p);
+//  } else {
+//       //MME_send_M3_SETUP_FAILURE(instance);
+//       return -1;
+//  }
+////  return 0;
+//    //TEST POINT MME -> eNB
+//    if(1){
+//	printf("instance %d\n",instance);
+//	//MME_send_M3_SETUP_RESPONSE(instance,assoc_id,m3ap_mce_data_from_enb->assoc_id);
+//	//MME_send_MBMS_SESSION_START_REQUEST(instance,assoc_id);
+//	//MME_send_MBMS_SESSION_STOP_REQUEST(instance,assoc_id);
+//	//MME_send_MBMS_SCHEDULING_INFORMATION(instance,assoc_id,NULL); //TODO
+//    }
+//    else 
+//	MME_send_M3_SETUP_FAILURE(instance,assoc_id);
+//
+    return 0;
+}
+
+int MME_send_M3_SETUP_RESPONSE(instance_t instance, /*uint32_t assoc_id,*/
+                               m3ap_setup_resp_t *m3ap_setup_resp) {
+ M3AP_M3AP_PDU_t           pdu;
+ M3AP_M3SetupResponse_t    *out;
+ M3AP_M3SetupResponseIEs_t *ie;
+
+ uint8_t  *buffer;
+ uint32_t  len;
+ //int       i = 0;
+
+ /* Create */
+ /* 0. Message Type */
+ memset(&pdu, 0, sizeof(pdu));
+ pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+ //pdu.choice.successfulOutcome = (M3AP_SuccessfulOutcome_t *)calloc(1, sizeof(M3AP_SuccessfulOutcome_t));
+ pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+ pdu.choice.successfulOutcome.criticality   = M3AP_Criticality_reject;
+ pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_M3SetupResponse;
+ out = &pdu.choice.successfulOutcome.value.choice.M3SetupResponse;
+
+ /* mandatory */
+  /* c4. CriticalityDiagnostics*/
+  if (0) {
+    ie = (M3AP_M3SetupResponseIEs_t *)calloc(1, sizeof(M3AP_M3SetupResponseIEs_t));
+    ie->id                        = M3AP_ProtocolIE_ID_id_CriticalityDiagnostics;
+    ie->criticality               = M3AP_Criticality_ignore;
+    ie->value.present             = M3AP_M3SetupFailureIEs__value_PR_CriticalityDiagnostics;
+    ie->value.choice.CriticalityDiagnostics.procedureCode = (M3AP_ProcedureCode_t *)calloc(1, sizeof(M3AP_ProcedureCode_t));
+    *ie->value.choice.CriticalityDiagnostics.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+    ie->value.choice.CriticalityDiagnostics.triggeringMessage = (M3AP_TriggeringMessage_t *)calloc(1, sizeof(M3AP_TriggeringMessage_t));
+    *ie->value.choice.CriticalityDiagnostics.triggeringMessage = M3AP_TriggeringMessage_initiating_message;
+    ie->value.choice.CriticalityDiagnostics.procedureCriticality = (M3AP_Criticality_t *)calloc(1, sizeof(M3AP_Criticality_t));
+    *ie->value.choice.CriticalityDiagnostics.procedureCriticality = M3AP_Criticality_reject;
+    //ie->value.choice.CriticalityDiagnostics.transactionID = (M2AP_TransactionID_t *)calloc(1, sizeof(M3AP_TransactionID_t));
+    //*ie->value.choice.CriticalityDiagnostics.transactionID = 0;
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* encode */
+  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M3AP, "Failed to encode M3 response\n");
+    return -1;
+  }
+
+  //printf(",m3ap_mme_data_from_mce->assoc_id %d\n",m3ap_mme_data_from_mce->assoc_id);
+
+  m3ap_MME_itti_send_sctp_data_req(instance,m3ap_mme_data_from_mce->assoc_id,buffer,len,0);
+
+  return 0;
+}
+
+int MME_send_M3_SETUP_FAILURE(instance_t instance,m3ap_setup_failure_t* m3ap_setup_failure) {
+  AssertFatal(1==0,"Not implemented yet\n");
+  
+//  module_id_t enb_mod_idP;
+//  module_id_t mce_mod_idP;
+//
+//  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+//
+//  M3AP_M3AP_PDU_t           pdu;
+//  M3AP_M3SetupFailure_t    *out;
+//  M3AP_M3SetupFailureIEs_t *ie;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//
+//  /* Create */
+//  /* 0. Message Type */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M3AP_M3AP_PDU_PR_unsuccessfulOutcome;
+//  //pdu.choice.unsuccessfulOutcome = (M3AP_UnsuccessfulOutcome_t *)calloc(1, sizeof(M3AP_UnsuccessfulOutcome_t));
+//  pdu.choice.unsuccessfulOutcome.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+//  pdu.choice.unsuccessfulOutcome.criticality   = M3AP_Criticality_reject;
+//  pdu.choice.unsuccessfulOutcome.value.present = M3AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+//  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+//
+//  /* mandatory */
+//  /* c1. Transaction ID (integer value)*/
+// // ie = (M3AP_M3SetupFailure_Ies_t *)calloc(1, sizeof(M3AP_M3SetupFailure_Ies_t));
+// // ie->id                        = M3AP_ProtocolIE_ID_id_GlobalMCE_ID;
+// // ie->criticality               = M3AP_Criticality_reject;
+// // ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_GlobalMCE_ID;
+// // ie->value.choice.GlobalMCE_ID = M3AP_get_next_transaction_identifier(enb_mod_idP, mce_mod_idP);
+// // ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  /* c2. Cause */
+//  ie = (M3AP_M3SetupFailureIEs_t *)calloc(1, sizeof(M3AP_M3SetupFailureIEs_t));
+//  ie->id                        = M3AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality               = M3AP_Criticality_ignore;
+//  ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_Cause;
+//  ie->value.choice.Cause.present = M3AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M3AP_CauseRadioNetwork_unspecified;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  /* c3. TimeToWait */
+//  if (0) {
+//    ie = (M3AP_M3SetupFailureIEs_t *)calloc(1, sizeof(M3AP_M3SetupFailureIEs_t));
+//    ie->id                        = M3AP_ProtocolIE_ID_id_TimeToWait;
+//    ie->criticality               = M3AP_Criticality_ignore;
+//    ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_TimeToWait;
+//    ie->value.choice.TimeToWait = M3AP_TimeToWait_v10s;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* optional */
+//  /* c4. CriticalityDiagnostics*/
+//  if (0) {
+//    ie = (M3AP_M3SetupFailureIEs_t *)calloc(1, sizeof(M3AP_M3SetupFailureIEs_t));
+//    ie->id                        = M3AP_ProtocolIE_ID_id_CriticalityDiagnostics;
+//    ie->criticality               = M3AP_Criticality_ignore;
+//    ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_CriticalityDiagnostics;
+//    ie->value.choice.CriticalityDiagnostics.procedureCode = (M3AP_ProcedureCode_t *)calloc(1, sizeof(M3AP_ProcedureCode_t));
+//    *ie->value.choice.CriticalityDiagnostics.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+//    ie->value.choice.CriticalityDiagnostics.triggeringMessage = (M3AP_TriggeringMessage_t *)calloc(1, sizeof(M3AP_TriggeringMessage_t));
+//    *ie->value.choice.CriticalityDiagnostics.triggeringMessage = M3AP_TriggeringMessage_initiating_message;
+//    ie->value.choice.CriticalityDiagnostics.procedureCriticality = (M3AP_Criticality_t *)calloc(1, sizeof(M3AP_Criticality_t));
+//    *ie->value.choice.CriticalityDiagnostics.procedureCriticality = M3AP_Criticality_reject;
+//    //ie->value.choice.CriticalityDiagnostics.transactionID = (M3AP_TransactionID_t *)calloc(1, sizeof(M3AP_TransactionID_t));
+//    //*ie->value.choice.CriticalityDiagnostics.transactionID = 0;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* encode */
+//  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    LOG_E(M3AP, "Failed to encode M2 setup request\n");
+//    return -1;
+//  }
+//
+//  //mce_m3ap_itti_send_sctp_data_req(instance, m3ap_mce_data_from_enb->assoc_id, buffer, len, 0);
+//  m3ap_MME_itti_send_sctp_data_req(instance,m3ap_mme_data_from_mce->assoc_id,buffer,len,0);
+
+  return 0;
+}
+
+/*
+ * MME Configuration Update
+ */
+
+
+int MME_handle_MME_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+int MME_handle_MME_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+/*
+ * MCE Configuration Update
+ */
+
+
+int MME_handle_MCE_CONFIGURATION_UPDATE(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+
+
+
+/*
+ * Error Indication
+ */
+
+int MME_handle_ERROR_INDICATION(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+
+
+}
+
+int MME_send_ERROR_INDICATION(instance_t instance, M3AP_ErrorIndication_t *ErrorIndication) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+
+/*
+ * Session Update Request
+ */
+int MME_send_MBMS_SESSION_UPDATE_REQUEST(instance_t instance, m3ap_mbms_session_update_req_t * m3ap_mbms_session_update_req){
+  M3AP_M3AP_PDU_t          pdu; 
+  M3AP_MBMSSessionUpdateRequest_t        *out;
+  M3AP_MBMSSessionUpdateRequest_IEs_t    *ie;
+
+  uint8_t *buffer;
+  uint32_t len;
+  //int	   i=0; 
+  //int 	   j=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M3AP_InitiatingMessage_t *)calloc(1, sizeof(M3AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_mBMSsessionUpdate;
+  pdu.choice.initiatingMessage.criticality   = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_MBMSSessionUpdateRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.MBMSSessionUpdateRequest; 
+
+  /* mandatory */
+  /* c1. MME_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MME_MBMS_M3AP_ID;
+  //ie->value.choice.MME_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+   /* mandatory */
+  /* c2. TMGI */ 
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_TMGI; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_TMGI;
+  M3AP_TMGI_t	*tmgi 		= &ie->value.choice.TMGI;
+  {
+	  MCC_MNC_TO_PLMNID(0,0,3,&tmgi->pLMNidentity);
+	  uint8_t TMGI[5] = {4,3,2,1,0};
+	  OCTET_STRING_fromBuf(&tmgi->serviceID,(const char*)&TMGI[2],3);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2. MBMS_Session_ID */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Session_ID;
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_Session_ID;
+	  //M3AP_MBMS_Session_ID_t * mbms_session_id = &ie->value.choice.MBMS_Session_ID;
+
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* mandatory */
+  /* c2. MBMS_E_RAB_QoS_Parameters */ 
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_E_RAB_QoS_Parameters; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_E_RAB_QoS_Parameters;
+  M3AP_MBMS_E_RAB_QoS_Parameters_t * mbms_e_rab_qos_parameters = &ie->value.choice.MBMS_E_RAB_QoS_Parameters;
+  {
+	//M3AP_QCI_t * qci = &mbms_e_rab_qos_parameters->qCI; //long
+	mbms_e_rab_qos_parameters->qCI=1;
+	//struct M3AP_GBR_QosInformation  *gbrQosInformation;     /* OPTIONAL */
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2. MBMS_Session_Duration */ 
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Session_Duration; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_Session_Duration; 
+  M3AP_MBMS_Session_Duration_t * mbms_session_duration = &ie->value.choice.MBMS_Session_Duration;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(mbms_session_duration,(const char*)&duration[2],3);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2 MBMS_Service_Area */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Service_Area;
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_Service_Area;
+	  //M3AP_MBMS_Service_Area_t * mbms_service_area = &ie->value.choice.MBMS_Service_Area;
+
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* mandatory */
+  /* c2 MinimumTimeToMBMSDataTransfer */
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MinimumTimeToMBMSDataTransfer; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MinimumTimeToMBMSDataTransfer; 
+  M3AP_MinimumTimeToMBMSDataTransfer_t * minimumtimetombmsdatatransfer = &ie->value.choice.MinimumTimeToMBMSDataTransfer;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(minimumtimetombmsdatatransfer,(const char*)&duration[2],1);
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2 TNL_Information */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_TNL_Information; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_TNL_Information; 
+	  M3AP_TNL_Information_t * tnl_information = &ie->value.choice.TNL_Information;
+	  {
+		OCTET_STRING_fromBuf(&tnl_information->iPMCAddress,"1204",strlen("1234"));
+		OCTET_STRING_fromBuf(&tnl_information->iPSourceAddress,"1204",strlen("1234"));
+		OCTET_STRING_fromBuf(&tnl_information->gTP_DLTEID,"1204",strlen("1234"));
+	  }
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* optional */
+  /* c2 Time_ofMBMS_DataTransfer */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_Time_ofMBMS_DataTransfer; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_Absolute_Time_ofMBMS_Data; 
+	  //M3AP_Absolute_Time_ofMBMS_Data_t * absolute_time_ofmbms_data	= &ie->value.choice.Absolute_Time_ofMBMS_Data;
+	  //{
+		//char duration[5] = {4,3,2,1,0};
+		//OCTET_STRING_fromBuf(absolute_time_ofmbms_data,(const char*)&duration[2],3);
+	  //}
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* optional */
+  /* c2 MBMS_Cell_List */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Cell_List; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_Cell_List; 
+	  M3AP_MBMS_Cell_List_t * mbms_cell_list = &ie->value.choice.MBMS_Cell_List;
+	  M3AP_ECGI_t * ecgi = (M3AP_ECGI_t*)calloc(1,sizeof(M3AP_ECGI_t));	
+	  {
+		//MCC_MNC_TO_PLMNID(0,0,3,ecgi->pLMN_Identity);
+		//MACRO_ENB_ID_TO_CELL_IDENTITY(1,0,ecgi->eUTRANcellIdentifier);
+		ASN_SEQUENCE_ADD(&mbms_cell_list->list,ecgi);
+	  }
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* encode */
+  if (m3ap_encode_pdu(&pdu,&buffer,&len) < 0){
+        return -1;
+  }
+
+  //MME_m3ap_itti_send_sctp_data_req(instance, m3ap_mce_data_from_mce->assoid,buffer,len,0); 
+  m3ap_MME_itti_send_sctp_data_req(instance, m3ap_mme_data_from_mce->assoc_id,buffer,len,0);
+  return 0;
+
+
+
+}
+
+
+
+int MME_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M3AP_M3AP_PDU_t *pdu){
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "MME_handle_MBMS_SESSION_UPDATE_RESPONSE\n");
+
+   AssertFatal(pdu->present == M3AP_M3AP_PDU_PR_successfulOutcome,
+               "pdu->present != M3AP_M3AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M3AP_ProcedureCode_id_mBMSsessionUpdate,
+               "pdu->choice.successfulOutcome->procedureCode != M3AP_ProcedureCode_id_sessionUpdate\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M3AP_Criticality_reject,
+               "pdu->choice.successfulOutcome->criticality != M3AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M3AP_SuccessfulOutcome__value_PR_MBMSSessionUpdateResponse,
+               "pdu->choice.successfulOutcome.value.present != M3AP_SuccessfulOutcome__value_PR_MBMSSessionUpdateResponse\n");
+
+
+  M3AP_MBMSSessionUpdateResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.MBMSSessionUpdateResponse;
+  M3AP_MBMSSessionUpdateResponse_IEs_t  *ie;
+  int MME_MBMS_M3AP_ID=-1;
+  int MCE_MBMS_M3AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_UPDATE_RESP); //TODO
+
+  LOG_D(M3AP, "M3AP: SessionUpdate-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionUpdateResponse_IEs__value_PR_MME_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_sessionUpdateResponse_IEs__value_PR_MME_MBMS_M3AP_ID\n");
+       MME_MBMS_M3AP_ID=ie->value.choice.MME_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: SessionUpdate-Resp: MME_MBMS_M3AP_ID %d\n",
+             MME_MBMS_M3AP_ID);
+       break;
+      case M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionUpdateResponse_IEs__value_PR_MCE_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_sessionUpdateResponse_IEs__value_PR_MCE_MBMS_M3AP_ID\n");
+       MCE_MBMS_M3AP_ID=ie->value.choice.MCE_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: SessionUpdate-Resp: MCE_MBMS_M3AP_ID %d\n",
+             MCE_MBMS_M3AP_ID);
+       break;
+     }
+  }
+
+  //AssertFatal(MME_MBMS_M3AP_ID!=-1,"MME_MBMS_M3AP_ID was not sent\n");
+  //AssertFatal(MCE_MBMS_M3AP_ID!=-1,"MCE_MBMS_M3AP_ID was not sent\n");
+  ////M3AP_SESSION_START_RESP(msg_p).
+////  MSC_LOG_RX_MESSAGE(
+////    MSC_M3AP_MME,
+////    MSC_M3AP_MCE,
+  //      //return 0;
+////    0,
+////    0,
+////    MSC_AS_TIME_FMT" MME_handle_M2_SESSION_START_RESPONSE successfulOutcome assoc_id %d",
+////    0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+////    assoc_id);
+////
+  // LOG_W(M3AP, "Sending M3AP_SESSION_START_RESP ITTI message to MCE_APP with assoc_id (%d->%d)\n",
+  //       assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id));
+  itti_send_msg_to_task(TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g);
+
+  return 0;
+
+}
+
+
+
+int MME_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+int MME_handle_MBMS_SERVICE_COUNTING_RESPONSE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+int MME_handle_MBMS_SESSION_COUNTING_FAILURE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+/*
+ * Service Counting Results Report
+ */
+
+int MME_handle_MBMS_SESSION_COUNTING_RESULTS_REPORT(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+/*
+ * Overload Notification
+ */
+int MME_handle_MBMS_OVERLOAD_NOTIFICATION(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+ 
+}
+
+
+
+
diff --git a/openair3/M3AP/m3ap_MME_interface_management.h b/openair3/M3AP/m3ap_MME_interface_management.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3765182ce41ca0eb0b4ddd95c70b5001197881f
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_interface_management.h
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME_interface_management.h
+ * \brief m3ap interface management for MME
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M3AP_MME_INTERFACE_MANAGEMENT_H_
+#define M3AP_MME_INTERFACE_MANAGEMENT_H_
+/*
+ * MBMS Session start
+ */
+int MME_send_MBMS_SESSION_START_REQUEST(instance_t instance/*,
+                                uint32_t assoc_id*/,m3ap_session_start_req_t* m3ap_session_start_req);
+int MME_handle_MBMS_SESSION_START_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+int MME_handle_MBMS_SESSION_START_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+/*
+ * MBMS Session stop
+ */
+int MME_send_MBMS_SESSION_STOP_REQUEST(instance_t instance,
+                                m3ap_session_stop_req_t* m3ap_session_stop_req);
+
+int MME_handle_MBMS_SESSION_STOP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+/*
+ * Update 
+ */
+int MME_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+int MME_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+
+
+/*
+ * Reset
+ */
+int MME_send_RESET(instance_t instance, m3ap_reset_t * m3ap_reset);
+
+int MME_handle_RESET_ACKKNOWLEDGE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+int MME_handle_RESET(instance_t instance,
+                    uint32_t assoc_id,
+                    uint32_t stream,
+                    M3AP_M3AP_PDU_t *pdu);
+int MME_send_RESET_ACKNOWLEDGE(instance_t instance, M3AP_ResetAcknowledge_t *ResetAcknowledge);
+
+/*
+ * M3AP Setup
+ */
+int MME_handle_M3_SETUP_REQUEST(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu);
+
+int MME_send_M3_SETUP_RESPONSE(instance_t instance,/*uint32_t assoc_id,*/  m3ap_setup_resp_t *m3ap_setup_resp);
+
+int MME_send_M3_SETUP_FAILURE(instance_t instance, /*uint32_t assoc_id*/ m3ap_setup_failure_t * m3ap_setup_failure);
+
+
+
+
+
+
+#endif /* M3AP_MME_INTERFACE_MANAGEMENT_H_ */
+
+
+
diff --git a/openair3/M3AP/m3ap_MME_management_procedures.c b/openair3/M3AP/m3ap_MME_management_procedures.c
new file mode 100644
index 0000000000000000000000000000000000000000..11d29242494534450f23b2ec305ba141d4e19b5f
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_management_procedures.c
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME_management_procedures.c
+ * \brief m3ap tasks for MME
+ * \author Javier Morgade  <javier.morade@ieee.org>
+ * \date 2018
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "assertions.h"
+#include "conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MME_defs.h"
+#include "m3ap_MME.h"
+
+
+#define M3AP_DEBUG_LIST
+#ifdef M3AP_DEBUG_LIST
+#  define M3AP_MME_LIST_OUT(x, args...) M3AP_DEBUG("[MME]%*s"x"\n", 4*indent, "", ##args)
+#else
+#  define M3AP_MME_LIST_OUT(x, args...)
+#endif
+
+static int                  indent = 0;
+
+
+m3ap_MME_internal_data_t m3ap_MME_internal_data;
+
+RB_GENERATE(m3ap_mme_map, m3ap_MME_data_s, entry, m3ap_MME_compare_assoc_id);
+
+int m3ap_MME_compare_assoc_id(
+  struct m3ap_MME_data_s *p1, struct m3ap_MME_data_s *p2)
+{
+  if (p1->assoc_id == -1) {
+    if (p1->cnx_id < p2->cnx_id) {
+      return -1;
+    }
+
+    if (p1->cnx_id > p2->cnx_id) {
+      return 1;
+    }
+  } else {
+    if (p1->assoc_id < p2->assoc_id) {
+      return -1;
+    }
+
+    if (p1->assoc_id > p2->assoc_id) {
+      return 1;
+    }
+  }
+
+  /* Matching reference */
+  return 0;
+}
+
+uint16_t m3ap_MME_fetch_add_global_cnx_id(void)
+{
+  return ++m3ap_MME_internal_data.global_cnx_id;
+}
+
+void m3ap_MME_prepare_internal_data(void)
+{
+  memset(&m3ap_MME_internal_data, 0, sizeof(m3ap_MME_internal_data));
+  STAILQ_INIT(&m3ap_MME_internal_data.m3ap_MME_instances_head);
+}
+
+void m3ap_MME_insert_new_instance(m3ap_MME_instance_t *new_instance_p)
+{
+  DevAssert(new_instance_p != NULL);
+
+  STAILQ_INSERT_TAIL(&m3ap_MME_internal_data.m3ap_MME_instances_head,
+                     new_instance_p, m3ap_MME_entries);
+}
+
+void dump_mme_tree_m2(m3ap_MME_data_t *t)
+{
+  if (t == NULL) return;
+  printf("-----------------------\n");
+  printf("MME id %d %s\n", t->MME_id, t->MME_name);
+  printf("state %d\n", t->state);
+  printf("nextstream %d\n", t->nextstream);
+  printf("in_streams %d out_streams %d\n", t->in_streams, t->out_streams);
+  printf("cnx_id %d assoc_id %d\n", t->cnx_id, t->assoc_id);
+  dump_mme_tree_m2(t->entry.rbe_left);
+  dump_mme_tree_m2(t->entry.rbe_right);
+}
+
+void dump_mme_trees_m2(void)
+{
+m3ap_MME_instance_t *zz;
+STAILQ_FOREACH(zz, &m3ap_MME_internal_data.m3ap_MME_instances_head,
+               m3ap_MME_entries) {
+printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance);
+dump_mme_tree_m2(zz->m3ap_mme_head.rbh_root);
+printf("---------------------------------------------\n");
+}
+}
+
+struct m3ap_MME_data_s *m3ap_get_MME(m3ap_MME_instance_t *instance_p,
+				     int32_t assoc_id,
+				     uint16_t cnx_id)
+{
+  struct m3ap_MME_data_s  temp;
+  struct m3ap_MME_data_s *found;
+
+printf("m3ap_get_MME at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
+dump_mme_trees_m2();
+
+  memset(&temp, 0, sizeof(struct m3ap_MME_data_s));
+
+  temp.assoc_id = assoc_id;
+  temp.cnx_id   = cnx_id;
+
+  if (instance_p == NULL) {
+    STAILQ_FOREACH(instance_p, &m3ap_MME_internal_data.m3ap_MME_instances_head,
+                   m3ap_MME_entries) {
+      found = RB_FIND(m3ap_mme_map, &instance_p->m3ap_mme_head, &temp);
+
+      if (found != NULL) {
+        return found;
+      }
+    }
+  } else {
+    return RB_FIND(m3ap_mme_map, &instance_p->m3ap_mme_head, &temp);
+  }
+
+  return NULL;
+}
+
+
+m3ap_MME_instance_t *m3ap_MME_get_instance(instance_t instance)
+{
+  m3ap_MME_instance_t *temp = NULL;
+
+  STAILQ_FOREACH(temp, &m3ap_MME_internal_data.m3ap_MME_instances_head,
+                 m3ap_MME_entries) {
+    if (temp->instance == instance) {
+      /* Matching occurence */
+      return temp;
+    }
+  }
+
+  return NULL;
+}
+
+/// utility functions
+
+void m3ap_dump_MME (m3ap_MME_data_t  * MME_ref);
+
+void
+m3ap_dump_MME_list (void) {
+   m3ap_MME_instance_t *inst = NULL;
+   struct m3ap_MME_data_s *found = NULL;
+   struct m3ap_MME_data_s temp;
+
+   memset(&temp, 0, sizeof(struct m3ap_MME_data_s));
+
+  STAILQ_FOREACH (inst, &m3ap_MME_internal_data.m3ap_MME_instances_head,  m3ap_MME_entries) {
+    found = RB_FIND(m3ap_mme_map, &inst->m3ap_mme_head, &temp);
+    m3ap_dump_MME (found);
+  }
+}
+
+void m3ap_dump_MME (m3ap_MME_data_t  * MME_ref) {
+
+  if (MME_ref == NULL) {
+    return;
+  }
+
+  M3AP_MME_LIST_OUT ("");
+  M3AP_MME_LIST_OUT ("MME name:          %s", MME_ref->MME_name == NULL ? "not present" : MME_ref->MME_name);
+  M3AP_MME_LIST_OUT ("MME STATE:         %07x", MME_ref->state);
+  M3AP_MME_LIST_OUT ("MME ID:            %07x", MME_ref->MME_id);
+  indent++;
+  M3AP_MME_LIST_OUT ("SCTP cnx id:     %d", MME_ref->cnx_id);
+  M3AP_MME_LIST_OUT ("SCTP assoc id:     %d", MME_ref->assoc_id);
+  M3AP_MME_LIST_OUT ("SCTP instreams:    %d", MME_ref->in_streams);
+  M3AP_MME_LIST_OUT ("SCTP outstreams:   %d", MME_ref->out_streams);
+  indent--;
+}
+
+m3ap_MME_data_t  * m3ap_is_MME_pci_in_list (const uint32_t pci)
+{
+  m3ap_MME_instance_t    *inst;
+  struct m3ap_MME_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m3ap_MME_internal_data.m3ap_MME_instances_head, m3ap_MME_entries) {
+    RB_FOREACH(elm, m3ap_mme_map, &inst->m3ap_mme_head) {
+      for (int i = 0; i<elm->num_cc; i++) {
+        if (elm->Nid_cell[i] == pci) {
+          return elm;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+m3ap_MME_data_t  * m3ap_is_MME_id_in_list (const uint32_t MME_id)
+{
+  m3ap_MME_instance_t    *inst;
+  struct m3ap_MME_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m3ap_MME_internal_data.m3ap_MME_instances_head, m3ap_MME_entries) {
+    RB_FOREACH(elm, m3ap_mme_map, &inst->m3ap_mme_head) {
+      if (elm->MME_id == MME_id)
+        return elm;
+    }
+  }
+  return NULL;
+}
+
+m3ap_MME_data_t  * m3ap_is_MME_assoc_id_in_list (const uint32_t sctp_assoc_id)
+{
+  m3ap_MME_instance_t    *inst;
+  struct m3ap_MME_data_s *found;
+  struct m3ap_MME_data_s temp;
+
+  temp.assoc_id = sctp_assoc_id;
+  temp.cnx_id = -1;
+
+  STAILQ_FOREACH(inst, &m3ap_MME_internal_data.m3ap_MME_instances_head, m3ap_MME_entries) {
+    found = RB_FIND(m3ap_mme_map, &inst->m3ap_mme_head, &temp);
+    if (found != NULL){
+      if (found->assoc_id == sctp_assoc_id) {
+	return found;
+      }
+    }
+  }
+  return NULL;
+}
diff --git a/openair3/M3AP/m3ap_MME_management_procedures.h b/openair3/M3AP/m3ap_MME_management_procedures.h
new file mode 100644
index 0000000000000000000000000000000000000000..e966ee1f17eb3ed982ee6e556b149b9607dc4339
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_management_procedures.h
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_management_procedures.h
+ * \brief m3ap tasks for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_MME_MANAGEMENT_PROCEDURES_H_
+#define M3AP_MME_MANAGEMENT_PROCEDURES_H
+
+void m3ap_MME_prepare_internal_data(void);
+
+void dump_trees_m2(void);
+
+void m3ap_MME_insert_new_instance(m3ap_MME_instance_t *new_instance_p);
+
+m3ap_MME_instance_t *m3ap_MME_get_instance(uint8_t mod_id);
+
+uint16_t m3ap_MME_fetch_add_global_cnx_id(void);
+
+void m3ap_MME_prepare_internal_data(void);
+
+m3ap_MME_data_t* m3ap_is_MME_id_in_list(uint32_t MME_id);
+
+m3ap_MME_data_t* m3ap_is_MME_assoc_id_in_list(uint32_t sctp_assoc_id);
+
+m3ap_MME_data_t* m3ap_is_MME_pci_in_list (const uint32_t pci);
+
+struct m3ap_MME_data_s *m3ap_get_MME(m3ap_MME_instance_t *instance_p,
+                                     int32_t assoc_id,
+                                     uint16_t cnx_id);
+
+#endif /* M3AP_MME_MANAGEMENT_PROCEDURES_H_ */
diff --git a/openair3/M3AP/m3ap_common.c b/openair3/M3AP/m3ap_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..55019976389592985734c4e2c3c4b826792b5fc1
--- /dev/null
+++ b/openair3/M3AP/m3ap_common.c
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_common.c
+ * \brief m3ap procedures for both eNB and MCE
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "m3ap_common.h"
+#include "M3AP_M3AP-PDU.h"
+
+int asn_debug = 0;
+int asn1_xer_print = 0;
+
+#if defined(EMIT_ASN_DEBUG_EXTERN)
+inline void ASN_DEBUG(const char *fmt, ...)
+{
+  if (asn_debug) {
+    int adi = asn_debug_indent;
+    va_list ap;
+    va_start(ap, fmt);
+    fprintf(stderr, "[ASN1]");
+
+    while(adi--) fprintf(stderr, " ");
+
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, "\n");
+    va_end(ap);
+  }
+}
+#endif
+
+ssize_t m3ap_generate_initiating_message(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M3AP_ProcedureCode_t    procedureCode,
+  M3AP_Criticality_t      criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr)
+{
+  M3AP_M3AP_PDU_t pdu;
+  ssize_t    encoded;
+  memset(&pdu, 0, sizeof(M3AP_M3AP_PDU_t));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = procedureCode;
+  pdu.choice.initiatingMessage.criticality   = criticality;
+  ANY_fromType_aper((ANY_t *)&pdu.choice.initiatingMessage.value, td, sptr);
+
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, (void *)&pdu);
+  }
+
+  /* We can safely free list of IE from sptr */
+  ASN_STRUCT_FREE_CONTENTS_ONLY(*td, sptr);
+
+  if ((encoded = aper_encode_to_new_buffer(&asn_DEF_M3AP_M3AP_PDU, 0, &pdu,
+                 (void **)buffer)) < 0) {
+    return -1;
+  }
+
+  *length = encoded;
+  return encoded;
+}
+
+
+ssize_t m3ap_generate_unsuccessfull_outcome(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M3AP_ProcedureCode_t         procedureCode,
+  M3AP_Criticality_t           criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr)
+{
+  M3AP_M3AP_PDU_t pdu;
+  ssize_t    encoded;
+  memset(&pdu, 0, sizeof(M3AP_M3AP_PDU_t));
+  pdu.present = M3AP_M3AP_PDU_PR_unsuccessfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = procedureCode;
+  pdu.choice.successfulOutcome.criticality   = criticality;
+  ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr);
+
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, (void *)&pdu);
+  }
+
+  /* We can safely free list of IE from sptr */
+  ASN_STRUCT_FREE_CONTENTS_ONLY(*td, sptr);
+
+  if ((encoded = aper_encode_to_new_buffer(&asn_DEF_M3AP_M3AP_PDU, 0, &pdu,
+                 (void **)buffer)) < 0) {
+    return -1;
+  }
+
+  *length = encoded;
+  return encoded;
+}
+
+void m3ap_handle_criticality(M3AP_Criticality_t criticality)
+{
+
+}
+
diff --git a/openair3/M3AP/m3ap_common.h b/openair3/M3AP/m3ap_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f68510314fa31b18148a222e7769cdd17990c49
--- /dev/null
+++ b/openair3/M3AP/m3ap_common.h
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#if HAVE_CONFIG_H_
+# include "config.h"
+#endif
+
+#include "M3AP_ProtocolIE-Field.h"
+#include "M3AP_M3AP-PDU.h"
+#include "M3AP_InitiatingMessage.h"
+#include "M3AP_SuccessfulOutcome.h"
+#include "M3AP_UnsuccessfulOutcome.h"
+#include "M3AP_ProtocolIE-FieldPair.h"
+#include "M3AP_ProtocolIE-ContainerPair.h"
+#include "M3AP_ProtocolExtensionField.h"
+#include "M3AP_ProtocolExtensionContainer.h"
+#include "M3AP_asn_constant.h"
+#include "intertask_interface.h"
+
+#ifndef M3AP_COMMON_H_
+#define M3AP_COMMON_H_
+
+/** @defgroup _m3ap_impl_ M3AP Layer Reference Implementation
+ * @ingroup _ref_implementation_
+ * @{
+ */
+
+/* Checking version of ASN1C compiler */
+#if (ASN1C_ENVIRONMENT_VERSION < 923)
+# error "You are compiling m3ap with the wrong version of ASN1C"
+#endif
+
+#ifndef M3AP_PORT
+# define M3AP_PORT 36444
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+extern int asn1_xer_print;
+
+#if defined(ENB_MODE)
+# include "common/utils/LOG/log.h"
+# include "m3ap_default_values.h"
+# define M3AP_INFO(x, args...) LOG_I(M3AP, x, ##args)
+# define M3AP_ERROR(x, args...) LOG_E(M3AP, x, ##args)
+# define M3AP_WARN(x, args...)  LOG_W(M3AP, x, ##args)
+# define M3AP_DEBUG(x, args...) LOG_D(M3AP, x, ##args)
+#else
+# define M3AP_INFO(x, args...) do { fprintf(stdout, "[M3AP][I]"x, ##args); } while(0)
+# define M3AP_ERROR(x, args...) do { fprintf(stdout, "[M3AP][E]"x, ##args); } while(0)
+# define M3AP_WARN(x, args...)  do { fprintf(stdout, "[M3AP][W]"x, ##args); } while(0)
+# define M3AP_DEBUG(x, args...) do { fprintf(stdout, "[M3AP][D]"x, ##args); } while(0)
+#endif
+
+#define M3AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \
+  do {\
+    IE_TYPE **ptr; \
+    ie = NULL; \
+    for (ptr = container->protocolIEs.list.array; \
+         ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \
+         ptr++) { \
+      if((*ptr)->id == IE_ID) { \
+        ie = *ptr; \
+        break; \
+      } \
+    } \
+    if (mandatory) DevAssert(ie != NULL); \
+  } while(0)
+
+/** \brief Function callback prototype.
+ **/
+typedef int (*m3ap_message_decoded_callback)(
+  instance_t instance,
+  uint32_t assocId,
+  uint32_t stream,
+  M3AP_M3AP_PDU_t *pdu);
+
+
+/** \brief Function callback prototype.
+ **/
+typedef int (*m3ap_MCE_message_decoded_callback)(
+  instance_t instance,
+  uint32_t assocId,
+  uint32_t stream,
+  M3AP_M3AP_PDU_t *pdu);
+
+/** \brief Function callback prototype.
+ **/
+typedef int (*m3ap_MME_message_decoded_callback)(
+  instance_t instance,
+  uint32_t assocId,
+  uint32_t stream,
+  M3AP_M3AP_PDU_t *pdu);
+
+
+
+/** \brief Encode a successfull outcome message
+ \param buffer pointer to buffer in which data will be encoded
+ \param length pointer to the length of buffer
+ \param procedureCode Procedure code for the message
+ \param criticality Criticality of the message
+ \param td ASN1C type descriptor of the sptr
+ \param sptr Deferenced pointer to the structure to encode
+ @returns size in bytes encded on success or 0 on failure
+ **/
+ssize_t m3ap_generate_successfull_outcome(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M3AP_ProcedureCode_t         procedureCode,
+  M3AP_Criticality_t           criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr);
+
+/** \brief Encode an initiating message
+ \param buffer pointer to buffer in which data will be encoded
+ \param length pointer to the length of buffer
+ \param procedureCode Procedure code for the message
+ \param criticality Criticality of the message
+ \param td ASN1C type descriptor of the sptr
+ \param sptr Deferenced pointer to the structure to encode
+ @returns size in bytes encded on success or 0 on failure
+ **/
+ssize_t m3ap_generate_initiating_message(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M3AP_ProcedureCode_t    procedureCode,
+  M3AP_Criticality_t      criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr);
+
+/** \brief Encode an unsuccessfull outcome message
+ \param buffer pointer to buffer in which data will be encoded
+ \param length pointer to the length of buffer
+ \param procedureCode Procedure code for the message
+ \param criticality Criticality of the message
+ \param td ASN1C type descriptor of the sptr
+ \param sptr Deferenced pointer to the structure to encode
+ @returns size in bytes encded on success or 0 on failure
+ **/
+ssize_t m3ap_generate_unsuccessfull_outcome(
+  uint8_t               **buffer,
+  uint32_t               *length,
+  M3AP_ProcedureCode_t         procedureCode,
+  M3AP_Criticality_t           criticality,
+  asn_TYPE_descriptor_t  *td,
+  void                   *sptr);
+
+/** \brief Handle criticality
+ \param criticality Criticality of the IE
+ @returns void
+ **/
+void m3ap_handle_criticality(M3AP_Criticality_t criticality);
+
+#endif /* M3AP_COMMON_H_ */
diff --git a/openair3/M3AP/m3ap_decoder.c b/openair3/M3AP/m3ap_decoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..cee0a5ff41d1582ee16d53e0f26c7e61c0f1f905
--- /dev/null
+++ b/openair3/M3AP/m3ap_decoder.c
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_decoder.c
+ * \brief m3ap decoder procedures 
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+
+#include "assertions.h"
+#include "intertask_interface.h"
+#include "m3ap_common.h"
+#include "m3ap_decoder.h"
+
+static int m3ap_decode_initiating_message(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.initiatingMessage.procedureCode) {
+    case M3AP_ProcedureCode_id_mBMSsessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_errorIndication:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_privateMessage:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_Reset:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mCEConfigurationUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    default:
+      M3AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
+                  (int)pdu->choice.initiatingMessage.procedureCode);
+      AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n",
+                   (int)pdu->choice.initiatingMessage.procedureCode);
+      return -1;
+  }
+
+  return 0;
+
+}
+
+
+static int m3ap_decode_successful_outcome(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.successfulOutcome.procedureCode) {
+    case M3AP_ProcedureCode_id_mBMSsessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_successfuloutcome_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_succesfuloutcome_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_errorIndication:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_privateMessage:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_Reset:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mCEConfigurationUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_succesfuloutcome_message!\n");
+      break;
+    default:
+      M3AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
+                  (int)pdu->choice.successfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+static int m3ap_decode_unsuccessful_outcome(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
+    case M3AP_ProcedureCode_id_mBMSsessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_errorIndication:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_privateMessage:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_Reset:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mCEConfigurationUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    default:
+       M3AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
+                  (int)pdu->choice.unsuccessfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+int m3ap_decode_pdu(M3AP_M3AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
+{
+  asn_dec_rval_t dec_ret;
+
+  DevAssert(buffer != NULL);
+
+  dec_ret = aper_decode(NULL,
+                        &asn_DEF_M3AP_M3AP_PDU,
+                        (void **)&pdu,
+                        buffer,
+                        length,
+                        0,
+                        0);
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, pdu);
+  }
+
+  if (dec_ret.code != RC_OK) {
+    M3AP_ERROR("Failed to decode pdu\n");
+    return -1;
+  }
+
+  switch(pdu->present) {
+    case M3AP_M3AP_PDU_PR_initiatingMessage:
+      return m3ap_decode_initiating_message(pdu);
+
+    case M3AP_M3AP_PDU_PR_successfulOutcome:
+      return m3ap_decode_successful_outcome(pdu);
+
+    case M3AP_M3AP_PDU_PR_unsuccessfulOutcome:
+      return m3ap_decode_unsuccessful_outcome(pdu);
+
+    default:
+      M3AP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present);
+      break;
+  }
+
+
+  return -1;
+}
diff --git a/openair3/M3AP/m3ap_decoder.h b/openair3/M3AP/m3ap_decoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d228a1ceb1a69270b2ce171d2cab0cf2315b209
--- /dev/null
+++ b/openair3/M3AP/m3ap_decoder.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_decoder.h
+ * \brief m3ap decoder procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_DECODER_H_
+#define M3AP_DECODER_H_
+
+int m3ap_decode_pdu(M3AP_M3AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
+__attribute__ ((warn_unused_result));
+
+#endif /* M3AP_DECODER_H_ */
diff --git a/openair3/M3AP/m3ap_default_values.h b/openair3/M3AP/m3ap_default_values.h
new file mode 100644
index 0000000000000000000000000000000000000000..79c78d5b96ffb2c26b16323bac12a53d00869ad2
--- /dev/null
+++ b/openair3/M3AP/m3ap_default_values.h
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_default_values.h
+ * \brief default values for m3ap procedures
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M3AP_DEFAULT_VALUES_H_
+#define M3AP_DEFAULT_VALUES_H_
+
+#define ENB_TAC (1)
+#define ENB_MCC (208)
+#define ENB_MNC (92)
+
+#define ENB_NAME        "Eurecom ENB"
+#define ENB_NAME_FORMAT (ENB_NAME" %u")
+
+#define M3AP_PORT_NUMBER        (36444)
+#define M3AP_SCTP_PPID          (44)
+
+#endif /* M3AP_DEFAULT_VALUES_H_ */
+
diff --git a/openair3/M3AP/m3ap_encoder.c b/openair3/M3AP/m3ap_encoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e1cbf80af545024ceaf642d65d0d9316604eb4d
--- /dev/null
+++ b/openair3/M3AP/m3ap_encoder.c
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_encoder.c
+ * \brief m3ap encoder procedures
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "assertions.h"
+#include "conversions.h"
+#include "intertask_interface.h"
+#include "m3ap_common.h"
+#include "m3ap_encoder.h"
+
+int m3ap_encode_pdu(M3AP_M3AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
+{
+  ssize_t    encoded;
+
+  DevAssert(pdu != NULL);
+  DevAssert(buffer != NULL);
+  DevAssert(len != NULL);
+
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, (void *)pdu);
+  }
+
+  encoded = aper_encode_to_new_buffer(&asn_DEF_M3AP_M3AP_PDU, 0, pdu, (void **)buffer);
+
+  if (encoded < 0) {
+    return -1;
+  }
+
+  *len = encoded;
+
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, pdu);
+  return encoded;
+}
diff --git a/openair3/M3AP/m3ap_encoder.h b/openair3/M3AP/m3ap_encoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..db444a611e12680364364f12f4afc349629f08ab
--- /dev/null
+++ b/openair3/M3AP/m3ap_encoder.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_encoder.h
+ * \brief m3ap encoder procedures
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_ENCODER_H_
+#define M3AP_ENCODER_H_
+
+int m3ap_encode_pdu(M3AP_M3AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
+__attribute__ ((warn_unused_result));
+
+#endif /* M3AP_ENCODER_H_ */
diff --git a/openair3/M3AP/m3ap_handler.c b/openair3/M3AP/m3ap_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..832aa0dbacc55b9385eb47a00685257b8af2c5ea
--- /dev/null
+++ b/openair3/M3AP/m3ap_handler.c
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_handler.c
+ * \brief m3ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_handler.h"
+#include "m3ap_decoder.h"
+#include "m3ap_ids.h"
+
+#include "m3ap_MCE_management_procedures.h"
+//#include "m3ap_MCE_generate_messages.h"
+
+#include "m3ap_MME_interface_management.h"
+#include "m3ap_MCE_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m3ap_message_decoded_callback m3ap_messages_callback[][3] = {
+  { MCE_handle_MBMS_SESSION_START_REQUEST, MME_handle_MBMS_SESSION_START_RESPONSE, 0 }, /* MBMSSessionStart  */
+  { MCE_handle_MBMS_SESSION_STOP_REQUEST, MME_handle_MBMS_SESSION_STOP_RESPONSE, 0 }, /* MBMSSessionStop */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { 0, 0, 0 }, /* ??? */
+  { MCE_handle_MBMS_SESSION_UPDATE_REQUEST, MME_handle_MBMS_SESSION_UPDATE_RESPONSE, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { MME_handle_M3_SETUP_REQUEST, MCE_handle_M3_SETUP_RESPONSE, 0 } /* M3 Setup */
+};
+
+char *m3ap_direction2String(int m3ap_dir) {
+static char *m3ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m3ap_direction_String[m3ap_dir]);
+}
+
+
+int m3ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M3AP_M3AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  int i=0; 
+  for( i=0; i < data_length; i++)
+	printf("%02X",data[i]);
+  printf("\n");
+
+  if (m3ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M3AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m3ap_messages_callback) / (3 * sizeof(
+        m3ap_message_decoded_callback))
+      || (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M3AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
+               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m3ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M3AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m3ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M3AP, "Calling handler with instance %d\n",instance);
+  ret = (*m3ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair3/M3AP/m3ap_handler.h b/openair3/M3AP/m3ap_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b01307807ab8f2500f6e4cce4b21d653ab92d3d
--- /dev/null
+++ b/openair3/M3AP/m3ap_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_handler.h
+ * \brief m2ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_OLD_HANDLERS_H_
+#define M2AP_MCE_OLD_HANDLERS_H_
+
+#include "m2ap_eNB_defs.h"
+
+//void m3ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+//int m3ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            //const uint8_t * const data, const uint32_t data_length);
+
+int m3ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M2AP_MCE_HANDLERS_H_ */
diff --git a/openair3/M3AP/m3ap_ids.c b/openair3/M3AP/m3ap_ids.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e0a9f2106b28e1d02b9f595e830a1e8aa8f4241
--- /dev/null
+++ b/openair3/M3AP/m3ap_ids.c
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "m3ap_ids.h"
+
+#include <string.h>
+
+void m3ap_id_manager_init(m3ap_id_manager *m)
+{
+  int i;
+  memset(m, 0, sizeof(m3ap_id_manager));
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    m->ids[i].rnti = -1;
+}
+
+int m3ap_allocate_new_id(m3ap_id_manager *m)
+{
+  int i;
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    if (m->ids[i].rnti == -1) {
+      m->ids[i].rnti = 0;
+      m->ids[i].id_source = -1;
+      m->ids[i].id_target = -1;
+      return i;
+    }
+  return -1;
+}
+
+void m3ap_release_id(m3ap_id_manager *m, int id)
+{
+  m->ids[id].rnti = -1;
+}
+
+int m3ap_find_id(m3ap_id_manager *m, int id_source, int id_target)
+{
+  int i;
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    if (m->ids[i].rnti != -1 &&
+        m->ids[i].id_source == id_source &&
+        m->ids[i].id_target == id_target)
+      return i;
+  return -1;
+}
+
+int m3ap_find_id_from_id_source(m3ap_id_manager *m, int id_source)
+{
+  int i;
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    if (m->ids[i].rnti != -1 &&
+        m->ids[i].id_source == id_source)
+      return i;
+  return -1;
+}
+
+int m3ap_find_id_from_rnti(m3ap_id_manager *m, int rnti)
+{
+  int i;
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    if (m->ids[i].rnti == rnti)
+      return i;
+  return -1;
+}
+
+void m3ap_set_ids(m3ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target)
+{
+  m->ids[ue_id].rnti      = rnti;
+  m->ids[ue_id].id_source = id_source;
+  m->ids[ue_id].id_target = id_target;
+}
+
+/* real type of target is m3ap_eNB_data_t * */
+void m3ap_id_set_target(m3ap_id_manager *m, int ue_id, void *target)
+{
+  m->ids[ue_id].target = target;
+}
+
+void m3ap_id_set_state(m3ap_id_manager *m, int ue_id, m3id_state_t state)
+{
+  m->ids[ue_id].state = state;
+}
+
+void m3ap_set_reloc_prep_timer(m3ap_id_manager *m, int ue_id, uint64_t time)
+{
+  m->ids[ue_id].t_reloc_prep_start = time;
+}
+
+void m3ap_set_reloc_overall_timer(m3ap_id_manager *m, int ue_id, uint64_t time)
+{
+  m->ids[ue_id].tm3_reloc_overall_start = time;
+}
+
+int m3ap_id_get_id_source(m3ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].id_source;
+}
+
+int m3ap_id_get_id_target(m3ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].id_target;
+}
+
+int m3ap_id_get_rnti(m3ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].rnti;
+}
+
+void *m3ap_id_get_target(m3ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].target;
+}
diff --git a/openair3/M3AP/m3ap_ids.h b/openair3/M3AP/m3ap_ids.h
new file mode 100644
index 0000000000000000000000000000000000000000..bc5a3c38980b95b0b16e6bb9b850874c7e1c7293
--- /dev/null
+++ b/openair3/M3AP/m3ap_ids.h
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef M3AP_IDS_H_
+#define M3AP_IDS_H_
+
+#include <stdint.h>
+
+/* maximum number of simultaneous handovers, do not set too high */
+#define M3AP_MAX_IDS	16
+
+/*
+ * state:
+ * - when starting handover in source, UE is in state M3ID_STATE_SOURCE_PREPARE
+ * - after receiving HO_ack in source, UE is in state M3ID_STATE_SOURCE_OVERALL
+ * - in target, UE is in state X2ID_STATE_TARGET
+ * The state is used to check timers.
+ */
+typedef enum {
+  M3ID_STATE_SOURCE_PREPARE,
+  M3ID_STATE_SOURCE_OVERALL,
+  M3ID_STATE_TARGET
+} m3id_state_t;
+
+typedef struct {
+  int           rnti;             /* -1 when free */
+  int           id_source;
+  int           id_target;
+
+  /* the target eNB. Real type is m3ap_eNB_data_t * */
+  void          *target;
+
+  /* state: needed to check timers */
+  m3id_state_t  state;
+
+  /* timers */
+  uint64_t      t_reloc_prep_start;
+  uint64_t      tm3_reloc_overall_start;
+} m3ap_id;
+
+typedef struct {
+  m3ap_id ids[M3AP_MAX_IDS];
+} m3ap_id_manager;
+
+void m3ap_id_manager_init(m3ap_id_manager *m);
+int m3ap_allocate_new_id(m3ap_id_manager *m);
+void m3ap_release_id(m3ap_id_manager *m, int id);
+int m3ap_find_id(m3ap_id_manager *, int id_source, int id_target);
+int m3ap_find_id_from_id_source(m3ap_id_manager *, int id_source);
+int m3ap_find_id_from_rnti(m3ap_id_manager *, int rnti);
+void m3ap_set_ids(m3ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target);
+void m3ap_id_set_state(m3ap_id_manager *m, int ue_id, m3id_state_t state);
+/* real type of target is m3ap_eNB_data_t * */
+void m3ap_id_set_target(m3ap_id_manager *m, int ue_id, void *target);
+void m3ap_set_reloc_prep_timer(m3ap_id_manager *m, int ue_id, uint64_t time);
+void m3ap_set_reloc_overall_timer(m3ap_id_manager *m, int ue_id, uint64_t time);
+int m3ap_id_get_id_source(m3ap_id_manager *m, int ue_id);
+int m3ap_id_get_id_target(m3ap_id_manager *m, int ue_id);
+int m3ap_id_get_rnti(m3ap_id_manager *m, int ue_id);
+void *m3ap_id_get_target(m3ap_id_manager *m, int ue_id);
+
+#endif /* M3AP_IDS_H_ */
diff --git a/openair3/M3AP/m3ap_itti_messaging.c b/openair3/M3AP/m3ap_itti_messaging.c
new file mode 100644
index 0000000000000000000000000000000000000000..b90674764075e2e5b9e4f3a8b037ae7674320061
--- /dev/null
+++ b/openair3/M3AP/m3ap_itti_messaging.c
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_itti_messaging.c
+ * \brief m3ap tasks for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+#include "m3ap_itti_messaging.h"
+
+void m3ap_MCE_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream)
+{
+  MessageDef      *message_p;
+  sctp_data_req_t *sctp_data_req;
+
+  message_p = itti_alloc_new_message(TASK_M3AP_MCE, SCTP_DATA_REQ);
+
+  sctp_data_req = &message_p->ittiMsg.sctp_data_req;
+
+  sctp_data_req->assoc_id      = assoc_id;
+  sctp_data_req->buffer        = buffer;
+  sctp_data_req->buffer_length = buffer_length;
+  sctp_data_req->stream        = stream;
+
+  //LOG_W(M3AP,"assoc_id %d, stream %d\n",assoc_id,stream);
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+
+void m3ap_MCE_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id)
+{
+  MessageDef               *message_p = NULL;
+  sctp_close_association_t *sctp_close_association_p = NULL;
+
+  message_p = itti_alloc_new_message(TASK_M3AP_MCE, SCTP_CLOSE_ASSOCIATION);
+  sctp_close_association_p = &message_p->ittiMsg.sctp_close_association;
+  sctp_close_association_p->assoc_id      = assoc_id;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+
+void m3ap_MME_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream)
+{
+  MessageDef      *message_p;
+  sctp_data_req_t *sctp_data_req;
+
+  message_p = itti_alloc_new_message(TASK_M3AP_MME, SCTP_DATA_REQ);
+
+  sctp_data_req = &message_p->ittiMsg.sctp_data_req;
+
+  sctp_data_req->assoc_id      = assoc_id;
+  sctp_data_req->buffer        = buffer;
+  sctp_data_req->buffer_length = buffer_length;
+  sctp_data_req->stream        = stream;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+
+void m3ap_MME_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id)
+{
+  MessageDef               *message_p = NULL;
+  sctp_close_association_t *sctp_close_association_p = NULL;
+
+  message_p = itti_alloc_new_message(TASK_M3AP_MME, SCTP_CLOSE_ASSOCIATION);
+  sctp_close_association_p = &message_p->ittiMsg.sctp_close_association;
+  sctp_close_association_p->assoc_id      = assoc_id;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
diff --git a/openair3/M3AP/m3ap_itti_messaging.h b/openair3/M3AP/m3ap_itti_messaging.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a4069da9b33a27a99a9addc67f00f958fe26a42
--- /dev/null
+++ b/openair3/M3AP/m3ap_itti_messaging.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_itti_messaging.h
+ * \brief m3ap tasks for MME
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_MCE_ITTI_MESSAGING_H_
+#define M3AP_MCE_ITTI_MESSAGING_H_
+
+void m3ap_MCE_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+
+void m3ap_MCE_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
+
+
+void m3ap_MME_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+
+void m3ap_MME_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
+
+
+
+
+#endif /* M3AP_MCE_ITTI_MESSAGING_H_ */
diff --git a/openair3/M3AP/m3ap_timers.c b/openair3/M3AP/m3ap_timers.c
new file mode 100644
index 0000000000000000000000000000000000000000..39498cc8eb01f70e356ea4108e875c347e496b4a
--- /dev/null
+++ b/openair3/M3AP/m3ap_timers.c
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "m3ap_timers.h"
+#include "assertions.h"
+#include "PHY/defs_common.h"         /* TODO: try to not include this */
+#include "m3ap_messages_types.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_ids.h"
+#include "m3ap_MCE_management_procedures.h"
+//#include "m3ap_eNB_generate_messages.h"
+
+void m3ap_timers_init(m3ap_timers_t *t, int t_reloc_prep, int tm3_reloc_overall)
+{
+  t->tti               = 0;
+  t->t_reloc_prep      = t_reloc_prep;
+  t->tm3_reloc_overall = tm3_reloc_overall;
+}
+
+void m3ap_check_timers(instance_t instance)
+{
+  //m3ap_eNB_instance_t          *instance_p;
+  //m3ap_timers_t                *t;
+  //m3ap_id_manager              *m;
+  //int                          i;
+  //m3ap_handover_cancel_cause_t cause;
+  //void                         *target;
+  //MessageDef                   *msg;
+  //int                          m2_ongoing;
+
+  //instance_p = m3ap_eNB_get_instance(instance);
+  //DevAssert(instance_p != NULL);
+
+  //t = &instance_p->timers;
+  //m = &instance_p->id_manager;
+
+  ///* increment subframe count */
+  //t->tti++;
+
+  //m2_ongoing = 0;
+
+  //for (i = 0; i < M3AP_MAX_IDS; i++) {
+  //  if (m->ids[i].rnti == -1) continue;
+  //  m2_ongoing++;
+
+  //  if (m->ids[i].state == M2ID_STATE_SOURCE_PREPARE &&
+  //      t->tti > m->ids[i].t_reloc_prep_start + t->t_reloc_prep) {
+  //    LOG_I(M3AP, "M2 timeout reloc prep\n");
+  //    /* t_reloc_prep timed out */
+  //    cause = M3AP_T_RELOC_PREP_TIMEOUT;
+  //    goto timeout;
+  //  }
+
+  //  if (m->ids[i].state == M2ID_STATE_SOURCE_OVERALL &&
+  //      t->tti > m->ids[i].tm2_reloc_overall_start + t->tm2_reloc_overall) {
+  //    LOG_I(M3AP, "M2 timeout reloc overall\n");
+  //    /* tm2_reloc_overall timed out */
+  //    cause = M3AP_TM2_RELOC_OVERALL_TIMEOUT;
+  //    goto timeout;
+  //  }
+
+  //  /* no timeout -> check next UE */
+  //  continue;
+
+  // timeout:
+  //  /* inform target about timeout */
+  //  target = m3ap_id_get_target(m, i);
+  //  m3ap_eNB_generate_m2_handover_cancel(instance_p, target, i, cause);
+
+  //  /* inform RRC of cancellation */
+  //  msg = itti_alloc_new_message(TASK_M3AP, M3AP_HANDOVER_CANCEL);
+  //  M3AP_HANDOVER_CANCEL(msg).rnti  = m3ap_id_get_rnti(m, i);
+  //  M3AP_HANDOVER_CANCEL(msg).cause = cause;
+  //  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+
+  //  /* remove UE from M3AP */
+  //  m3ap_release_id(m, i);
+  //}
+
+  //if (m2_ongoing && t->tti % 1000 == 0)
+  //  LOG_I(M3AP, "M2 has %d process ongoing\n", m2_ongoing);
+}
+
+uint64_t m3ap_timer_get_tti(m3ap_timers_t *t)
+{
+  return t->tti;
+}
diff --git a/openair3/M3AP/m3ap_timers.h b/openair3/M3AP/m3ap_timers.h
new file mode 100644
index 0000000000000000000000000000000000000000..95dcbfc9d96fec69164bb9be12eb02e137283f4d
--- /dev/null
+++ b/openair3/M3AP/m3ap_timers.h
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef M3AP_TIMERS_H_
+#define M3AP_TIMERS_H_
+
+#include <stdint.h>
+#include "platform_types.h"
+
+typedef struct {
+  /* incremented every TTI (every millisecond when in realtime).
+   * Used to check timers.
+   * 64 bits gives us more than 500 million years of (realtime) processing.
+   * It should be enough.
+   */
+  uint64_t tti;
+
+  /* timer values (unit: TTI, ie. millisecond when in realtime) */
+  int      t_reloc_prep;
+  int      tm3_reloc_overall;
+} m3ap_timers_t;
+
+void m3ap_timers_init(m3ap_timers_t *t, int t_reloc_prep, int tm3_reloc_overall);
+void m3ap_check_timers(instance_t instance);
+uint64_t m3ap_timer_get_tti(m3ap_timers_t *t);
+
+#endif /* M3AP_TIMERS_H_ */
diff --git a/openair3/MME_APP/enb_paramdef_mme.h b/openair3/MME_APP/enb_paramdef_mme.h
new file mode 100644
index 0000000000000000000000000000000000000000..3d65036553bc6579b96ac2fdb512441fc6b70daa
--- /dev/null
+++ b/openair3/MME_APP/enb_paramdef_mme.h
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file openair2/ENB_APP/enb_paramdef_mce.h
+ * \brief definition of configuration parameters for MME modules 
+ * \author Javier MORGADE
+ * \date 2019
+ * \version 0.1
+ * \company VICOMTECH Spain
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "common/config/config_paramdesc.h"
+#include "RRC_paramsvalues.h"
+
+#define ENB_CONFIG_STRING_MME_PARAMETERS                                  "mme_parameters"
+//#define ENB_CONFIG_STRING_SCHEDULING_INFO_BR                               "scheduling_info_br"
+//#define ENB_CONFIG_STRING_RSRP_RANGE_LIST                                  "rsrp_range_list"
+//#define ENB_CONFIG_STRING_PRACH_CONFIG_COMMON_V1310                        "prach_ConfigCommon_v1310"
+//#define ENB_CONFIG_STRING_MPDCCH_START_SF_CSS_RA_R13                       "mpdcch_startSF_CSS_RA_r13"
+//#define ENB_CONFIG_STRING_MPDCCH_START_SF_CSS_RA_R13_VAL                   "mpdcch_startSF_CSS_RA_r13_val"
+//#define ENB_CONFIG_STRING_PRACH_HOPPING_OFFSET_R13                         "prach_HoppingOffset_r13"
+//#define ENB_CONFIG_STRING_SCHEDULING_INFO_SIB1_BR_R13                      "schedulingInfoSIB1_BR_r13"
+//#define ENB_CONFIG_STRING_CELL_SELECTION_INFO_CE_R13                       "cellSelectionInfoCE_r13"
+//#define ENB_CONFIG_STRING_Q_RX_LEV_MIN_CE_R13                              "q_RxLevMinCE_r13"
+//#define ENB_CONFIG_STRING_BANDWIDTH_REDUCED_ACCESS_RELATED_INFO_R13        "bandwidthReducedAccessRelatedInfo_r13"
+//#define ENB_CONFIG_STRING_SI_WINDOW_LENGTH_BR_R13                          "si_WindowLength_BR_r13"
+//#define ENB_CONFIG_STRING_SI_REPETITION_PATTERN_R13                        "si_RepetitionPattern_r13"
+//#define ENB_CONFIG_STRING_FDD_DOWNLINK_OR_TDD_SUBFRAME_BITMAP_BR_R13       "fdd_DownlinkOrTddSubframeBitmapBR_r13"
+//#define ENB_CONFIG_STRING_FDD_DOWNLINK_OR_TDD_SUBFRAME_BITMAP_BR_VAL_R13   "fdd_DownlinkOrTddSubframeBitmapBR_val_r13"
+//#define ENB_CONFIG_STRING_START_SYMBOL_BR_R13                              "startSymbolBR_r13"
+//#define ENB_CONFIG_STRING_SI_HOPPING_CONFIG_COMMON_R13                     "si_HoppingConfigCommon_r13"
+//#define ENB_CONFIG_STRING_SI_VALIDITY_TIME_R13                             "si_ValidityTime_r13"
+//#define ENB_CONFIG_STRING_FREQ_HOPPING_PARAMETERS_DL_R13                   "freqHoppingParametersDL_r13"
+//#define ENB_CONFIG_STRING_MPDCCH_PDSCH_HOPPING_NB_R13                      "mpdcch_pdsch_HoppingNB_r13"
+//#define ENB_CONFIG_STRING_INTERVAL_DL_HOPPING_CONFIG_COMMON_MODE_A_R13     "interval_DLHoppingConfigCommonModeA_r13"
+//#define ENB_CONFIG_STRING_INTERVAL_DL_HOPPING_CONFIG_COMMON_MODE_A_R13_VAL "interval_DLHoppingConfigCommonModeA_r13_val"
+//#define ENB_CONFIG_STRING_INTERVAL_DL_HOPPING_CONFIG_COMMON_MODE_B_R13     "interval_DLHoppingConfigCommonModeB_r13"
+//#define ENB_CONFIG_STRING_INTERVAL_DL_HOPPING_CONFIG_COMMON_MODE_B_R13_VAL "interval_DLHoppingConfigCommonModeB_r13_val"
+//#define ENB_CONFIG_STRING_MPDCCH_PDSCH_HOPPING_OFFSET_R13                  "mpdcch_pdsch_HoppingOffset_r13"
+//#define ENB_CONFIG_STRING_PREAMBLE_TRANSMAX_CE_R13                         "preamble_TransMax_ce_r13"
+//#define ENB_CONFIG_STRING_PREAMBLE_TRANSMAX_CE_R13_VAL                     "preamble_TransMax_ce_r13_val"
+//#define ENB_CONFIG_STRING_PDSCH_MAX_NUM_REPETITION_CE_MODE_A_R13           "pdsch_maxNumRepetitionCEmodeA_r13"
+//#define ENB_CONFIG_STRING_PDSCH_MAX_NUM_REPETITION_CE_MODE_B_R13           "pdsch_maxNumRepetitionCEmodeB_r13"
+//#define ENB_CONFIG_STRING_PUSCH_MAX_NUM_REPETITION_CE_MODE_A_R13           "pusch_maxNumRepetitionCEmodeA_r13"
+//#define ENB_CONFIG_STRING_PUSCH_MAX_NUM_REPETITION_CE_MODE_B_R13           "pusch_maxNumRepetitionCEmodeB_r13"
+//#define ENB_CONFIG_STRING_PUSCH_HOPPING_OFFSET_V1310                       "pusch_HoppingOffset_v1310"
+//#define ENB_CONFIG_STRING_SYSTEM_INFO_VALUE_TAG_LIST                       "system_info_value_tag_SI"
+//#define ENB_CONFIG_STRING_FIRST_PREAMBLE_R13                               "firstPreamble_r13"
+//#define ENB_CONFIG_STRING_LAST_PREAMBLE_R13                                "lastPreamble_r13"
+//#define ENB_CONFIG_STRING_RA_RESPONSE_WINDOW_SIZE_R13                      "ra_ResponseWindowSize_r13"
+//#define ENB_CONFIG_STRING_MAC_CONTENTION_RESOLUTION_TIMER_R13              "mac_ContentionResolutionTimer_r13"
+//#define ENB_CONFIG_STRING_RAR_HOPPING_CONFIG_R13                           "rar_HoppingConfig_r13"
+//#define ENB_CONFIG_STRING_RACH_CE_LEVELINFOLIST_R13                        "rach_CE_LevelInfoList_r13"
+//#define ENB_CONFIG_STRING_PRACH_CONFIG_INDEX_BR                            "prach_config_index_br"
+//#define ENB_CONFIG_STRING_PRACH_FREQ_OFFSET_BR                             "prach_freq_offset_br"
+//#define ENB_CONFIG_STRING_PRACH_STARTING_SUBFRAME_R13                      "prach_StartingSubframe_r13"
+//#define ENB_CONFIG_STRING_MAX_NUM_PER_PREAMBLE_ATTEMPT_CE_R13              "maxNumPreambleAttemptCE_r13"
+//#define ENB_CONFIG_STRING_NUM_REPETITION_PER_PREAMBLE_ATTEMPT_R13          "numRepetitionPerPreambleAttempt_r13"
+//#define ENB_CONFIG_STRING_MPDCCH_NUM_REPETITION_RA_R13                     "mpdcch_NumRepetition_RA_r13"
+//#define ENB_CONFIG_STRING_PRACH_HOPPING_CONFIG_R13                         "prach_HoppingConfig_r13"
+//#define ENB_CONFIG_SRING_MAX_AVAILABLE_NARROW_BAND                         "max_available_narrow_band"
+//#define ENB_CONFIG_STRING_PRACH_PARAMETERS_CE_R13                          "prach_parameters_ce_r13"							
+//#define ENB_CONFIG_STRING_PUCCH_INFO_VALUE                                 "pucch_info_value"
+//#define ENB_CONFIG_STRING_N1PUCCH_AN_INFOLIST_R13                          "n1PUCCH_AN_InfoList_r13"
+//#define ENB_CONFIG_STRING_PCCH_CONFIG_V1310                                "pcch_config_v1310"
+//#define ENB_CONFIG_STRING_PAGING_NARROWBANDS_R13                           "paging_narrowbands_r13"
+//#define ENB_CONFIG_STRING_MPDCCH_NUMREPETITION_PAGING_R13                  "mpdcch_numrepetition_paging_r13"
+//#define ENB_CONFIG_STRING_NB_V1310                                         "nb_v1310"
+//#define ENB_CONFIG_STRING_SIB2_FREQ_HOPPINGPARAMETERS_R13                  "sib2_freq_hoppingParameters_r13" 
+
+typedef struct ccparams_MME_s {
+  /// indicator that eMTC is configured for this cell
+  int32_t        MME_configured;
+ // /// the SIB2 parameters for eMTC SIB2
+ // ccparams_lte_t ccparams;
+ // int            si_Narrowband_r13;
+ // int            si_TBS_r13;
+ // int            systemInfoValueTagSi_r13;
+ // int            firstPreamble_r13;
+ // int            lastPreamble_r13;
+ // int            ra_ResponseWindowSize_r13;
+ // int            mac_ContentionResolutionTimer_r13;
+ // int            rar_HoppingConfig_r13;
+ // int            rsrp_range_br;
+ // int            prach_config_index_br;
+ // int            prach_freq_offset_br;
+ // int            prach_StartingSubframe_r13;
+ // int            maxNumPreambleAttemptCE_r13;
+ // int            numRepetitionPerPreambleAttempt_r13;
+ // int            mpdcch_NumRepetition_RA_r13;
+ // int            prach_HoppingConfig_r13;
+ // int           *maxavailablenarrowband;
+ // int            pucch_info_value;
+ // int            paging_narrowbands_r13;
+ // int            mpdcch_numrepetition_paging_r13;
+ // int            nb_v1310;
+ // char          *pucch_NumRepetitionCE_Msg4_Level0_r13;
+ // char          *pucch_NumRepetitionCE_Msg4_Level1_r13;
+ // char          *pucch_NumRepetitionCE_Msg4_Level2_r13;
+ // char          *pucch_NumRepetitionCE_Msg4_Level3_r13;
+ // int            sib2_mpdcch_pdsch_hoppingNB_r13;
+ // char          *sib2_interval_DLHoppingConfigCommonModeA_r13;
+ // int            sib2_interval_DLHoppingConfigCommonModeA_r13_val;
+ // char          *sib2_interval_DLHoppingConfigCommonModeB_r13;
+ // int            sib2_interval_DLHoppingConfigCommonModeB_r13_val;
+ // char          *sib2_interval_ULHoppingConfigCommonModeA_r13;
+ // int            sib2_interval_ULHoppingConfigCommonModeA_r13_val;
+ // char          *sib2_interval_ULHoppingConfigCommonModeB_r13;
+ // int            sib2_interval_ULHoppingConfigCommonModeB_r13_val;
+ // int            sib2_mpdcch_pdsch_hoppingOffset_r13;
+ // int            pusch_HoppingOffset_v1310;
+ // int            hyperSFN_r13;
+ // int            eDRX_Allowed_r13;
+ // int            q_RxLevMinCE_r13;
+ // int            q_QualMinRSRQ_CE_r13;
+ // char          *si_WindowLength_BR_r13;
+ // char          *si_RepetitionPattern_r13;
+ // int            startSymbolBR_r13;
+ // char          *si_HoppingConfigCommon_r13;
+ // char          *si_ValidityTime_r13;
+ // char          *mpdcch_pdsch_HoppingNB_r13;
+ // int            interval_DLHoppingConfigCommonModeA_r13_val;
+ // int            interval_DLHoppingConfigCommonModeB_r13_val;
+ // int            mpdcch_pdsch_HoppingOffset_r13;
+ // char          *preambleTransMax_CE_r13;
+ // int            prach_HoppingOffset_r13;
+ // int            schedulingInfoSIB1_BR_r13;
+ // int64_t        fdd_DownlinkOrTddSubframeBitmapBR_val_r13;
+ // char          *cellSelectionInfoCE_r13;
+ // char          *bandwidthReducedAccessRelatedInfo_r13;
+ // char          *fdd_DownlinkOrTddSubframeBitmapBR_r13;
+ // char          *fdd_UplinkSubframeBitmapBR_r13;
+ // char          *freqHoppingParametersDL_r13;
+ // char          *interval_DLHoppingConfigCommonModeA_r13;
+ // char          *interval_DLHoppingConfigCommonModeB_r13;
+ // char          *prach_ConfigCommon_v1310;
+ // char          *mpdcch_startSF_CSS_RA_r13;
+ // char          *mpdcch_startSF_CSS_RA_r13_val;
+ // char          *pdsch_maxNumRepetitionCEmodeA_r13;
+ // char          *pdsch_maxNumRepetitionCEmodeB_r13;
+ // char          *pusch_maxNumRepetitionCEmodeA_r13;
+ // char          *pusch_maxNumRepetitionCEmodeB_r13;
+} ccparams_MME_t;
+
+
+#define MMEPARAMS_DESC(MMEconfig) {					\
+  {"MME_configured",                                              NULL,   0,           iptr:&MMEconfig->MME_configured,                             defintval:0,                       TYPE_UINT,         0} \
+}
+
+#define MMEPARAMS_CHECK                 {                                     \
+             { .s5= {NULL }}						     \
+}
+
diff --git a/openair3/MME_APP/mme_app.c b/openair3/MME_APP/mme_app.c
new file mode 100644
index 0000000000000000000000000000000000000000..534aec8b34d7ca9ea94c15df7b28f5c37e3efef1
--- /dev/null
+++ b/openair3/MME_APP/mme_app.c
@@ -0,0 +1,580 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*
+                                mme_app.c
+                             -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include "mme_app.h"
+#include "mme_config.h"
+#include "assertions.h"
+#include "common/ran_context.h"
+#include "targets/RT/USER/lte-softmodem.h"
+
+#include "common/utils/LOG/log.h"
+
+# include "intertask_interface.h"
+#   include "s1ap_eNB.h"
+#   include "sctp_eNB_task.h"
+#   include "gtpv1u_eNB_task.h"
+#   include "flexran_agent.h"
+
+#   include "x2ap_eNB.h"
+#   include "x2ap_messages_types.h"
+#   include "m2ap_eNB.h"
+#   include "m3ap_MME.h"
+#   include "m2ap_messages_types.h"
+//#   include "m3ap_eNB.h"
+#   include "m3ap_messages_types.h"
+#   define X2AP_ENB_REGISTER_RETRY_DELAY   10
+
+#include "openair1/PHY/INIT/phy_init.h"
+extern unsigned char NB_MCE_INST;
+
+extern RAN_CONTEXT_t RC;
+
+#   define MCE_REGISTER_RETRY_DELAY 10
+
+#include "targets/RT/USER/lte-softmodem.h"
+
+
+
+
+/*------------------------------------------------------------------------------*/
+
+//static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, uint32_t mce_id_end) {
+//  uint32_t         mce_id;
+//  MessageDef      *msg_p;
+//  uint32_t         register_mce_pending = 0;
+//
+//  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+//    {
+//      // M3AP registration
+//        /* note:  there is an implicit relationship between the data structure and the message name */
+//        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_REGISTER_MCE_REQ);
+//        //RCconfig_S1(msg_p, mce_id);
+//
+//        //if (mce_id == 0) 
+//		//RCconfig_gtpu();
+//
+//        //LOG_I(MME_APP,"default drx %d\n",((M3AP_REGISTER_MCE_REQ(msg_p)).default_drx));
+//
+//        LOG_I(ENB_APP,"[MCE %d] MCE_app_register via M3AP for instance %d\n", mce_id, ENB_MODULE_ID_TO_INSTANCE(mce_id));
+//        itti_send_msg_to_task (TASK_M3AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+//
+//      //if (NODE_IS_DU(node_type)) { // F1AP registration
+//      //  // configure F1AP here for F1C
+//      //  LOG_I(ENB_APP,"ngran_eNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n");
+//      //  msg_p = itti_alloc_new_message (TASK_ENB_APP, F1AP_SETUP_REQ);
+//      //  RCconfig_DU_F1(msg_p, enb_id);
+//
+//      //  LOG_I(ENB_APP,"[eNB %d] eNB_app_register via F1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
+//      //  itti_send_msg_to_task (TASK_DU_F1, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+//      //  // configure GTPu here for F1U
+//      //}
+//      //else { // S1AP registration
+//      //  /* note:  there is an implicit relationship between the data structure and the message name */
+//      //  msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ);
+//      //  RCconfig_S1(msg_p, enb_id);
+//
+//      //  if (enb_id == 0) RCconfig_gtpu();
+//
+//      //  LOG_I(ENB_APP,"default drx %d\n",((S1AP_REGISTER_ENB_REQ(msg_p)).default_drx));
+//
+//      //  LOG_I(ENB_APP,"[eNB %d] eNB_app_register via S1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
+//      //  itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+//      //}
+//
+//      register_mce_pending++;
+//    }
+//  }
+//
+//  return register_mce_pending;
+//}
+
+
+/*------------------------------------------------------------------------------*/
+//static uint32_t MCE_app_register_x2(uint32_t mce_id_start, uint32_t mce_id_end) {
+//  uint32_t         mce_id;
+//  MessageDef      *msg_p;
+//  uint32_t         register_mce_m2_pending = 0;
+//
+//  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+//    {
+//      msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ);
+//      RCconfig_X2(msg_p, mce_id);
+//      itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+//      register_mce_x2_pending++;
+//    }
+//  }
+//
+//  return register_mce_x2_pending;
+//}
+
+/*------------------------------------------------------------------------------*/
+//static uint32_t MCE_app_register_m2(uint32_t mce_id_start, uint32_t mce_id_end) {
+//  uint32_t         mce_id;
+//  MessageDef      *msg_p;
+//  uint32_t         register_mce_m2_pending = 0;
+//
+//  LOG_W(MME_APP,"Register ...");
+//  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+//    {
+//  //	LOG_W(MME_APP,"Register commes inside ...\n");
+//      msg_p = itti_alloc_new_message (TASK_MME_APP, M2AP_REGISTER_MCE_REQ);
+//      //RCconfig_M2_MCE(msg_p, mce_id);
+//      itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+//  //	LOG_W(MME_APP,"Register sent ...\n");
+//      register_mce_m2_pending++;
+//    }
+//  }
+//
+//  return register_mce_m2_pending;
+//}
+//
+//
+//
+static uint32_t MME_app_handle_m3ap_setup_req(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_SETUP_RESP);
+        itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+static uint32_t MME_app_handle_m3ap_session_start_resp(instance_t instance){
+	
+  
+	return 0;
+}
+//
+//static uint32_t MME_app_handle_m3ap_session_stop_resp(instance_t instance){
+//	
+//  
+//	return 0;
+//}
+
+
+
+//
+//static uint32_t MCE_app_send_m2ap_mbms_scheduling_information(instance_t instance){
+//	
+//  	uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MME_APP, M2AP_MBMS_SCHEDULING_INFORMATION);
+//        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+//
+static uint32_t MME_app_send_m3ap_session_start_req(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_START_REQ);
+        itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+//static uint32_t MME_app_send_m3ap_session_stop_req(instance_t instance){
+//	
+//  	//uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_STOP_REQ);
+//        itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+static uint32_t MME_app_send_m3ap_session_update_req(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_UPDATE_REQ);
+        itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+/*------------------------------------------------------------------------------*/
+void *MME_app_task(void *args_p) {
+  //uint32_t                        mce_nb = RC.nb_inst; 
+  //uint32_t                        mce_id_start = 0;
+  //uint32_t                        mce_id_end = mce_id_start + mce_nb;
+  //uint32_t                        register_mce_pending=0;
+  //uint32_t                        registered_mce=0;
+  //long                            mce_register_retry_timer_id;
+  //uint32_t                        m2_register_mce_pending = 0;
+ // uint32_t                        x2_registered_mce = 0;
+ // long                            x2_mce_register_retry_timer_id;
+ // uint32_t                        m2_register_mce_pending = 0;
+ // uint32_t                        m2_registered_mce = 0;
+ // long                            m2_mce_register_retry_timer_id;
+  long                            m3_mme_register_session_start_timer_id;
+  MessageDef                     *msg_p           = NULL;
+  instance_t                      instance;
+  int                             result;
+  /* for no gcc warnings */
+  (void)instance;
+  itti_mark_task_ready (TASK_MME_APP);
+
+  /* Try to register each MCE */
+  // This assumes that node_type of all RRC instances is the same
+  if (EPC_MODE_ENABLED) {
+    //register_mce_pending = MCE_app_register(RC.rrc[0]->node_type, mce_id_start, mce_id_end);
+  }
+
+    /* Try to register each MCE with each other */
+ // if (is_x2ap_enabled() && !NODE_IS_DU(RC.rrc[0]->node_type)) {
+ //   x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ // }
+  if ( is_m3ap_MME_enabled() ){
+ 	RCconfig_MME();
+  }
+ // /* Try to register each MCE with MCE each other */
+ //if (is_m3ap_MME_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) {
+   //m2_register_mce_pending = MCE_app_register_m2 (mce_id_start, mce_id_end);
+ //}
+
+  do {
+    // Wait for a message
+    itti_receive_msg (TASK_MME_APP, &msg_p);
+    instance = ITTI_MSG_INSTANCE (msg_p);
+
+    switch (ITTI_MSG_ID(msg_p)) {
+    case TERMINATE_MESSAGE:
+      LOG_W(MME_APP, " *** Exiting MME_APP thread\n");
+      itti_exit_task ();
+      break;
+
+    case MESSAGE_TEST:
+      LOG_I(MME_APP, "MME_APP Received %s\n", ITTI_MSG_NAME(msg_p));
+      break;
+
+    case SOFT_RESTART_MESSAGE:
+      //handle_reconfiguration(instance);
+      break;
+
+    case M3AP_REGISTER_MCE_CNF: //M3AP_REGISTER_MCE_CNF debería
+      //AssertFatal(!NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received S1AP_REGISTER_ENB_CNF\n");
+       // if (EPC_MODE_ENABLED) {
+       //   LOG_I(MME_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
+       //         M3AP_REGISTER_MCE_CNF(msg_p).nb_mme);
+       //   DevAssert(register_mce_pending > 0);
+       //   register_mce_pending--;
+
+       //   /* Check if at least MCE is registered with one MME */
+       //   if (M3AP_REGISTER_MCE_CNF(msg_p).nb_mme > 0) {
+       //     registered_mce++;
+       //   }
+
+       //   /* Check if all register MCE requests have been processed */
+       //   if (register_mce_pending == 0) {
+       //     if (registered_mce == mce_nb) {
+       //       /* If all MCE are registered, start L2L1 task */
+       //      // MessageDef *msg_init_p;
+       //      // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
+       //      // itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
+       //     } else {
+       //       LOG_W(MME_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n",
+       //             mce_nb - registered_mce,  MCE_REGISTER_RETRY_DELAY);
+
+       //       /* Restart the MCE registration process in MCE_REGISTER_RETRY_DELAY seconds */
+       //       if (timer_setup (MCE_REGISTER_RETRY_DELAY, 0, TASK_MME_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+       //                        NULL, &mce_register_retry_timer_id) < 0) {
+       //         LOG_E(MME_APP, " Can not start MCE register retry timer, use \"sleep\" instead!\n");
+       //         sleep(MCE_REGISTER_RETRY_DELAY);
+       //         /* Restart the registration process */
+       //         registered_mce = 0;
+       //         register_mce_pending = MCE_app_register (RC.rrc[0]->node_type,mce_id_start, mce_id_end);
+       //       }
+       //     }
+       //   }
+       // } /* if (EPC_MODE_ENABLED) */
+
+      break;
+
+   // case M3AP_SETUP_RESP:
+   //   //AssertFatal(NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received F1AP_REGISTER_ENB_CNF in CU/MCE\n");
+
+   //   //LOG_I(MME_APP, "Received %s: associated ngran_MCE_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p),
+   //         //F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate);
+   //   
+   //   //handle_f1ap_setup_resp(&F1AP_SETUP_RESP(msg_p));
+   //   handle_m3ap_setup_resp(&M3AP_SETUP_RESP(msg_p));
+
+   //   DevAssert(register_mce_pending > 0);
+   //   register_mce_pending--;
+
+   //   /* Check if at least MCE is registered with one MME */
+   //   //if (M3AP_SETUP_RESP(msg_p).num_cells_to_activate > 0) {
+   //   //  registered_enb++;
+   //   //}
+
+   //   /* Check if all register MCE requests have been processed */
+   //   if (register_mce_pending == 0) {
+   //     if (registered_mce == mce_nb) {
+   //       /* If all MCE cells are registered, start L2L1 task */
+   //       MessageDef *msg_init_p;
+
+   //       //msg_init_p = itti_alloc_new_message (TASK_MME_APP, INITIALIZE_MESSAGE);
+   //       //itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
+
+   //     } else {
+   //       LOG_W(MME_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n",
+   //             mce_nb - registered_mce,  MCE_REGISTER_RETRY_DELAY);
+
+   //       /* Restart the MCE registration process in MCE_REGISTER_RETRY_DELAY seconds */
+   //       if (timer_setup (MCE_REGISTER_RETRY_DELAY, 0, TASK_MME_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+   //                        NULL, &mce_register_retry_timer_id) < 0) {
+   //         LOG_E(ENB_APP, " Can not start MCE register retry timer, use \"sleep\" instead!\n");
+
+   //         sleep(MCE_REGISTER_RETRY_DELAY);
+   //         /* Restart the registration process */
+   //         registered_mce = 0;
+   //         register_mce_pending = MCE_app_register (RC.rrc[0]->node_type,mce_id_start, mce_id_end);//, enb_properties_p);
+   //       }
+   //     }
+   //   }
+
+   //   break;
+
+    case M3AP_DEREGISTERED_MCE_IND: //M3AP_DEREGISTERED_MCE_IND debería
+      if (EPC_MODE_ENABLED) {
+  	LOG_W(MME_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
+  	      M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme);
+  	/* TODO handle recovering of registration */
+      }
+
+      break;
+
+    case TIMER_HAS_EXPIRED:
+        //if (EPC_MODE_ENABLED) {
+	//      LOG_I(MME_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
+
+	//      if (TIMER_HAS_EXPIRED (msg_p).timer_id == mce_register_retry_timer_id) {
+	//	/* Restart the registration process */
+	//	registered_mce = 0;
+	//	//register_mce_pending = MCE_app_register (RC.rrc[0]->node_type, mce_id_start, mce_id_end);
+	//      }
+
+	//      //if (TIMER_HAS_EXPIRED (msg_p).timer_id == x2_mce_register_retry_timer_id) {
+	//      //  /* Restart the registration process */
+	//      //  x2_registered_mce = 0;
+	//      //  x2_register_mce_pending = MCE_app_register_x2 (mce_id_start, mce_id_end);
+	//      //}
+        //} /* if (EPC_MODE_ENABLED) */
+	if(TIMER_HAS_EXPIRED(msg_p).timer_id == m3_mme_register_session_start_timer_id){
+		MME_app_send_m3ap_session_start_req(0);
+	}
+
+      break;
+
+ //   case X2AP_DEREGISTERED_ENB_IND:
+ //     LOG_W(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2);
+ //     /* TODO handle recovering of registration */
+ //     break;
+
+ //   case X2AP_REGISTER_ENB_CNF:
+ //     LOG_I(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           X2AP_REGISTER_ENB_CNF(msg_p).nb_x2);
+ //     DevAssert(x2_register_enb_pending > 0);
+ //     x2_register_enb_pending--;
+
+ //     /* Check if at least MCE is registered with one target MCE */
+ //     if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) {
+ //       x2_registered_enb++;
+ //     }
+
+ //     /* Check if all register MCE requests have been processed */
+ //     if (x2_register_enb_pending == 0) {
+ //       if (x2_registered_enb == enb_nb) {
+ //         /* If all MCE are registered, start RRC HO task */
+ //         } else {
+ //         uint32_t x2_not_associated = enb_nb - x2_registered_enb;
+ //         LOG_W(ENB_APP, " %d MCE %s not associated with the target\n",
+ //               x2_not_associated, x2_not_associated > 1 ? "are" : "is");
+
+ //         // timer to retry
+ //         /* Restart the MCE registration process in ENB_REGISTER_RETRY_DELAY seconds */
+ //         if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
+ //       		   INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
+ //       		   &x2_enb_register_retry_timer_id) < 0) {
+ //           LOG_E(ENB_APP, " Can not start MCE X2AP register: retry timer, use \"sleep\" instead!\n");
+ //           sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
+ //           /* Restart the registration process */
+ //           x2_registered_enb = 0;
+ //           x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ //         }
+ //       }
+ //     }
+
+ //     break;
+
+ //   case M2AP_DEREGISTERED_ENB_IND:
+ //     LOG_W(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           M2AP_DEREGISTERED_ENB_IND(msg_p).nb_m2);
+ //     /* TODO handle recovering of registration */
+ //     break;
+
+ //   case M2AP_REGISTER_ENB_CNF:
+ //     LOG_I(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           M2AP_REGISTER_ENB_CNF(msg_p).nb_m2);
+ //     DevAssert(m2_register_enb_pending > 0);
+ //     m2_register_enb_pending--;
+
+ //     /* Check if at least MCE is registered with one target MCE */
+ //     if (M2AP_REGISTER_ENB_CNF(msg_p).nb_m2 > 0) {
+ //       m2_registered_enb++;
+ //     }
+
+ //     /* Check if all register MCE requests have been processed */
+ //     if (m2_register_enb_pending == 0) {
+ //       if (m2_registered_enb == enb_nb) {
+ //         /* If all MCE are registered, start RRC HO task */
+ //         } else {
+ //         uint32_t m2_not_associated = enb_nb - m2_registered_enb;
+ //         LOG_W(ENB_APP, " %d MCE %s not associated with the target\n",
+ //               m2_not_associated, m2_not_associated > 1 ? "are" : "is");
+
+ //         // timer to retry
+ //         /* Restart the MCE registration process in ENB_REGISTER_RETRY_DELAY seconds */
+ //         //if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
+ //         //      	   INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
+ //         //      	   &x2_enb_register_retry_timer_id) < 0) {
+ //         //  LOG_E(ENB_APP, " Can not start MCE X2AP register: retry timer, use \"sleep\" instead!\n");
+ //         //  sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
+ //         //  /* Restart the registration process */
+ //         //  x2_registered_enb = 0;
+ //         //  x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ //         //}
+ //       }
+ //     }
+
+ //     break;
+	case M3AP_RESET:
+	LOG_I(MME_APP,"Received M3AP_RESET message %s\n",ITTI_MSG_NAME(msg_p));	
+	break;
+
+	case M3AP_SETUP_REQ:
+	LOG_I(MME_APP,"Received M3AP_REQ message %s\n",ITTI_MSG_NAME(msg_p));	
+	MME_app_handle_m3ap_setup_req(0);
+	if(timer_setup(1,0,TASK_MME_APP,INSTANCE_DEFAULT,TIMER_ONE_SHOT,NULL,&m3_mme_register_session_start_timer_id)<0){
+	}
+	//MME_app_send_m3ap_session_start_req(0);
+	break;
+
+	case M3AP_MBMS_SESSION_START_RESP:
+	LOG_I(MME_APP,"Received M3AP_MBMS_SESSION_START_RESP message %s\n",ITTI_MSG_NAME(msg_p));
+	MME_app_handle_m3ap_session_start_resp(0);
+	//MME_app_send_m3ap_session_stop_req(0);
+	break;
+
+	case M3AP_MBMS_SESSION_STOP_RESP:
+	LOG_I(MME_APP,"Received M3AP_MBMS_SESSION_STOP_RESP message %s\n",ITTI_MSG_NAME(msg_p));
+	MME_app_send_m3ap_session_update_req(0);
+	break;
+
+	case M3AP_MBMS_SESSION_UPDATE_RESP:
+	LOG_I(MME_APP,"Received M3AP_MBMS_SESSION_UPDATE_RESP message %s\n",ITTI_MSG_NAME(msg_p));
+	// trigger something new here !!!!!!
+	break;
+ 
+	case M3AP_MBMS_SESSION_UPDATE_FAILURE:
+	LOG_I(MME_APP,"Received M3AP_MBMS_SESSION_UPDATE_FAILURE message %s\n",ITTI_MSG_NAME(msg_p));	
+	break;
+ 
+	case M3AP_MCE_CONFIGURATION_UPDATE:
+	LOG_I(MME_APP,"Received M3AP_MCE_CONFIGURATION_UPDATE message %s\n",ITTI_MSG_NAME(msg_p)); 	   
+	break;
+ 
+    default:
+      LOG_E(MME_APP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
+      break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+  } while (1);
+
+  return NULL;
+}
+
+//void handle_reconfiguration(module_id_t mod_id) {
+//  struct timespec start, end;
+//  clock_gettime(CLOCK_MONOTONIC, &start);
+//  flexran_agent_info_t *flexran = RC.flexran[mod_id];
+//  LOG_I(ENB_APP, "lte-softmodem soft-restart requested\n");
+//
+//  if (ENB_WAIT == flexran->node_ctrl_state) {
+//    /* this is already waiting, just release */
+//    pthread_mutex_lock(&flexran->mutex_node_ctrl);
+//    flexran->node_ctrl_state = ENB_NORMAL_OPERATION;
+//    pthread_mutex_unlock(&flexran->mutex_node_ctrl);
+//    pthread_cond_signal(&flexran->cond_node_ctrl);
+//    return;
+//  }
+//
+//  if (stop_L1L2(mod_id) < 0) {
+//    LOG_E(ENB_APP, "can not stop lte-softmodem, aborting restart\n");
+//    return;
+//  }
+//
+//  /* node_ctrl_state should have value ENB_MAKE_WAIT only if this method is not
+//   * executed by the FlexRAN thread */
+//  if (ENB_MAKE_WAIT == flexran->node_ctrl_state) {
+//    LOG_I(ENB_APP, " * MCE %d: Waiting for FlexRAN RTController command *\n", mod_id);
+//    pthread_mutex_lock(&flexran->mutex_node_ctrl);
+//    flexran->node_ctrl_state = ENB_WAIT;
+//
+//    while (ENB_NORMAL_OPERATION != flexran->node_ctrl_state)
+//      pthread_cond_wait(&flexran->cond_node_ctrl, &flexran->mutex_node_ctrl);
+//
+//    pthread_mutex_unlock(&flexran->mutex_node_ctrl);
+//  }
+//
+//  if (restart_L1L2(mod_id) < 0) {
+//    LOG_E(ENB_APP, "can not restart, killing lte-softmodem\n");
+//    exit_fun("can not restart L1L2, killing lte-softmodem");
+//    return;
+//  }
+//
+//  clock_gettime(CLOCK_MONOTONIC, &end);
+//  end.tv_sec -= start.tv_sec;
+//
+//  if (end.tv_nsec >= start.tv_nsec) {
+//    end.tv_nsec -= start.tv_nsec;
+//  } else {
+//    end.tv_sec -= 1;
+//    end.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000;
+//  }
+//
+//  LOG_I(ENB_APP, "lte-softmodem restart succeeded in %ld.%ld s\n", end.tv_sec, end.tv_nsec / 1000000);
+//}
+
+
diff --git a/openair3/MME_APP/mme_app.h b/openair3/MME_APP/mme_app.h
new file mode 100644
index 0000000000000000000000000000000000000000..796bfa796c24300630c60e3e61c398ec29864e3e
--- /dev/null
+++ b/openair3/MME_APP/mme_app.h
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*
+                                mme_app.h
+                             -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#ifndef MME_APP_H_
+#define MME_APP_H_
+
+#include <stdint.h>
+#include "platform_types.h"
+
+
+void *MME_app_task(void *args_p);
+
+//void handle_reconfiguration(module_id_t mod_id);
+
+#endif /* MME_APP_H_ */
diff --git a/openair3/MME_APP/mme_config.c b/openair3/MME_APP/mme_config.c
new file mode 100644
index 0000000000000000000000000000000000000000..04dba6756755a1e1c2ffa024a53c325a13d6218a
--- /dev/null
+++ b/openair3/MME_APP/mme_config.c
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*
+  mme_config.c
+  -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH, Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#include <string.h>
+#include <inttypes.h>
+
+#include "common/utils/LOG/log.h"
+#include "assertions.h"
+#include "mme_config.h"
+#include "UTIL/OTG/otg.h"
+#include "UTIL/OTG/otg_externs.h"
+#include "intertask_interface.h"
+#include "s1ap_eNB.h"
+#include "sctp_eNB_task.h"
+#include "common/ran_context.h"
+#include "sctp_default_values.h"
+#include "LTE_SystemInformationBlockType2.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "LAYER2/MAC/mac_proto.h"
+#include "PHY/phy_extern.h"
+#include "PHY/INIT/phy_init.h"
+#include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
+#include "nfapi_vnf.h"
+#include "nfapi_pnf.h"
+
+#include "L1_paramdef.h"
+#include "MACRLC_paramdef.h"
+#include "common/config/config_userapi.h"
+#include "RRC_config_tools.h"
+#include "enb_paramdef.h"
+#include "proto_agent.h"
+
+int RCconfig_MME(void ) {
+  //int               num_enbs                      = 0;
+  //char             *enb_interface_name_for_S1U    = NULL;
+  char               *mme_interface_name_for_m3_mce = NULL;
+  //char             *enb_ipv4_address_for_S1U      = NULL;
+  char               *mme_ipv4_address_for_m3c      = NULL;
+  //uint32_t          enb_port_for_S1U              = 0;
+  uint32_t            mme_port_for_m3c              = 0;
+  char             *address                       = NULL;
+  char             *cidr                          = NULL;
+  //char gtpupath[MAX_OPTNAME_SIZE*2 + 8];
+  char mmepath[MAX_OPTNAME_SIZE*2 + 8];
+  //paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
+  //paramdef_t GTPUParams[]  = GTPUPARAMS_DESC;
+
+  paramdef_t   MMEParams[] = MME_NETPARAMS_DESC;
+
+  ///* get number of active eNodeBs */
+  //config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL);
+  //num_enbs = ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt;
+  //AssertFatal (num_enbs >0,
+  //             "Failed to parse config file no active eNodeBs in %s \n", ENB_CONFIG_STRING_ACTIVE_ENBS);
+  //sprintf(gtpupath,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,0,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+  sprintf(mmepath,"%s.[%i].%s","MMEs",0,MME_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+  //config_get( GTPUParams,sizeof(GTPUParams)/sizeof(paramdef_t),gtpupath);
+  config_get(MMEParams,sizeof(MMEParams)/sizeof(paramdef_t),mmepath);
+  //cidr = enb_ipv4_address_for_S1U;
+  cidr = mme_ipv4_address_for_m3c;
+  address = strtok(cidr, "/");
+
+  //LOG_W(MME_APP,"cidr %s\n",cidr);
+  //LOG_W(MME_APP,"address %s\n",address);
+  //LOG_W(MME_APP,"mme_interface_name_for_m3_mce %s\n",mme_interface_name_for_m3_mce);
+  //LOG_W(MME_APP,"mme_ipv4_address_for_m3c %s\n",mme_ipv4_address_for_m3c);
+  //LOG_W(MME_APP,"mme_port_for_m3c %d\n",mme_port_for_m3c);
+
+  if (address) {
+    MessageDef *message;
+    AssertFatal((message = itti_alloc_new_message(TASK_MME_APP, M3AP_MME_SCTP_REQ))!=NULL,"");
+    M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv6 = 0;
+    M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv4 = 1;
+    strcpy( M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv4_address, address);
+    LOG_I(MME_APP,"Configuring M3_C address : %s\n",address/*,M3AP_MME_SCTP_REQ(message).mme_m3_ip_address*/);
+    M3AP_MME_SCTP_REQ(message).mme_port_for_M3C = mme_port_for_m3c;
+    itti_send_msg_to_task (TASK_M3AP_MME, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id)
+  } else
+    LOG_E(MCE_APP,"invalid address for M2AP\n");
+
+
+
+  return 0;
+}
+
diff --git a/openair3/MME_APP/mme_config.h b/openair3/MME_APP/mme_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..97b2fae03246fb2597aad893c690c04d92f66a2a
--- /dev/null
+++ b/openair3/MME_APP/mme_config.h
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*
+  mme_config.h
+  AUTHOR  : Javier Morgade
+  COMPANY : Vicomtech, Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#ifndef MME_CONFIG_H_
+#define MME_CONFIG_H_
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libconfig.h>
+
+#include "commonDef.h"
+#include "platform_types.h"
+#include "platform_constants.h"
+#include "PHY/impl_defs_lte.h"
+#include "PHY/defs_eNB.h"
+#include "s1ap_messages_types.h"
+#include "f1ap_messages_types.h"
+#include "LTE_SystemInformationBlockType2.h"
+#include "rrc_messages_types.h"
+#include "RRC/LTE/rrc_defs.h"
+#include <intertask_interface.h>
+#include "enb_paramdef.h"
+
+int RCconfig_MME(void);
+
+#endif /* MME_CONFIG_H_ */
+/** @} */
diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c
index cfc2bc22155235a41d439581d71d795450e53310..cbbd30b62ca5ecc07287fec616e84c82b8f79eb2 100644
--- a/targets/COMMON/create_tasks.c
+++ b/targets/COMMON/create_tasks.c
@@ -26,11 +26,11 @@
 # include "common/ran_context.h"
 
 #ifdef OPENAIR2
-    #include "sctp_eNB_task.h"
-    #include "x2ap_eNB.h"
-    #include "s1ap_eNB.h"
-    #include "udp_eNB_task.h"
-    #include "gtpv1u_eNB_task.h"
+  #include "sctp_eNB_task.h"
+  #include "x2ap_eNB.h"
+  #include "s1ap_eNB.h"
+  #include "udp_eNB_task.h"
+  #include "gtpv1u_eNB_task.h"
   #if ENABLE_RAL
     #include "lteRALue.h"
     #include "lteRALenb.h"
@@ -40,6 +40,7 @@
 # include "f1ap_cu_task.h"
 # include "f1ap_du_task.h"
 # include "enb_app.h"
+# include "openair2/LAYER2/MAC/mac_proto.h"
 
 extern RAN_CONTEXT_t RC;
 
@@ -63,7 +64,6 @@ int create_tasks(uint32_t enb_nb) {
     AssertFatal(rc >= 0, "Create task for SCTP failed\n");
   }
 
-
   if (EPC_MODE_ENABLED && !NODE_IS_DU(type)) {
     rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL);
     AssertFatal(rc >= 0, "Create task for S1AP failed\n");
@@ -91,5 +91,11 @@ int create_tasks(uint32_t enb_nb) {
     AssertFatal(rc >= 0, "Create task for DU F1AP failed\n");
   }
 
+  if (!NODE_IS_CU(type)) {
+    LOG_I(MAC,"Creating MAC eNB Task\n");
+    rc = itti_create_task(TASK_MAC_ENB, mac_enb_task, NULL);
+    AssertFatal(rc >= 0, "Create task for MAC eNB failed\n");
+  }
+
   return 0;
 }
diff --git a/targets/COMMON/create_tasks.h b/targets/COMMON/create_tasks.h
index ff1d9ace5199fbc0dbf3bf8b9cc7a52f1db983c5..339f4aaa8f5fdaa1d0a8c2839afda9586e9f2053 100644
--- a/targets/COMMON/create_tasks.h
+++ b/targets/COMMON/create_tasks.h
@@ -28,6 +28,7 @@ extern void *l2l1_task(void *arg);
 
 int create_tasks(uint32_t enb_nb);
 int create_tasks_ue(uint32_t ue_nb);
+int create_tasks_mbms(uint32_t enb_nb);
 #endif
 
 #endif /* CREATE_TASKS_H_ */
diff --git a/targets/COMMON/create_tasks_mbms.c b/targets/COMMON/create_tasks_mbms.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f81592b96640211e55f9590c8a611c81990c1a8
--- /dev/null
+++ b/targets/COMMON/create_tasks_mbms.c
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+# include "intertask_interface.h"
+# include "create_tasks.h"
+# include "common/utils/LOG/log.h"
+# include "targets/RT/USER/lte-softmodem.h"
+# include "common/ran_context.h"
+
+#ifdef OPENAIR2
+    #include "sctp_eNB_task.h"
+    #include "x2ap_eNB.h"
+    #include "s1ap_eNB.h"
+    #include "udp_eNB_task.h"
+    #include "gtpv1u_eNB_task.h"
+    #include "m2ap_eNB.h"
+    #include "m2ap_MCE.h"
+    #include "m3ap_MME.h"
+    #include "m3ap_MCE.h"
+  #if ENABLE_RAL
+    #include "lteRALue.h"
+    #include "lteRALenb.h"
+  #endif
+  #include "RRC/LTE/rrc_defs.h"
+#endif
+# include "f1ap_cu_task.h"
+# include "f1ap_du_task.h"
+# include "enb_app.h"
+# include "mce_app.h"
+# include "mme_app.h"
+
+//extern RAN_CONTEXT_t RC;
+
+int create_tasks_mbms(uint32_t enb_nb) {
+ // LOG_D(ENB_APP, "%s(enb_nb:%d\n", __FUNCTION__, enb_nb);
+ // ngran_node_t type = RC.rrc[0]->node_type;
+  int rc;
+
+  if (enb_nb == 0) return 0;
+
+  if(!EPC_MODE_ENABLED){
+    rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
+    AssertFatal(rc >= 0, "Create task for SCTP failed\n");
+  }
+
+
+  LOG_I(MME_APP, "Creating MME_APP eNB Task\n");
+  rc = itti_create_task (TASK_MME_APP, MME_app_task, NULL);
+  AssertFatal(rc >= 0, "Create task for MME APP failed\n");
+
+  if (is_m3ap_MME_enabled()) {
+	  rc = itti_create_task(TASK_M3AP_MME, m3ap_MME_task, NULL);
+	  AssertFatal(rc >= 0, "Create task for M3AP MME failed\n");
+  }
+
+  LOG_I(MCE_APP, "Creating MCE_APP eNB Task\n");
+  rc = itti_create_task (TASK_MCE_APP, MCE_app_task, NULL);
+  AssertFatal(rc >= 0, "Create task for MCE APP failed\n");
+
+  
+//  LOG_I(ENB_APP, "Creating ENB_APP eNB Task\n");
+//  rc = itti_create_task (TASK_ENB_APP, eNB_app_task, NULL);
+//  AssertFatal(rc >= 0, "Create task for eNB APP failed\n");
+//
+//  LOG_I(RRC,"Creating RRC eNB Task\n");
+//  rc = itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL);
+//  AssertFatal(rc >= 0, "Create task for RRC eNB failed\n");
+//
+//  if (EPC_MODE_ENABLED) {
+//    rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
+//    AssertFatal(rc >= 0, "Create task for SCTP failed\n");
+//  }
+// rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
+//    AssertFatal(rc >= 0, "Create task for SCTP failed\n");
+//
+//
+//  if (EPC_MODE_ENABLED && !NODE_IS_DU(type)) {
+//    rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL);
+//    AssertFatal(rc >= 0, "Create task for S1AP failed\n");
+//    if (!(get_softmodem_params()->emulate_rf)){
+//      rc = itti_create_task(TASK_UDP, udp_eNB_task, NULL);
+//      AssertFatal(rc >= 0, "Create task for UDP failed\n");
+//    }
+//    rc = itti_create_task(TASK_GTPV1_U, gtpv1u_eNB_task, NULL);
+//    AssertFatal(rc >= 0, "Create task for GTPV1U failed\n");
+//    if (is_x2ap_enabled()) {
+//      rc = itti_create_task(TASK_X2AP, x2ap_task, NULL);
+//      AssertFatal(rc >= 0, "Create task for X2AP failed\n");
+//    } else {
+//      LOG_I(X2AP, "X2AP is disabled.\n");
+//    }
+//  }
+////
+    if(!EPC_MODE_ENABLED){
+   // rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
+   // AssertFatal(rc >= 0, "Create task for SCTP failed\n");
+    rc = itti_create_task(TASK_UDP, udp_eNB_task, NULL);
+      AssertFatal(rc >= 0, "Create task for UDP failed\n");
+    rc = itti_create_task(TASK_GTPV1_U, gtpv1u_eNB_task, NULL);
+    AssertFatal(rc >= 0, "Create task for GTPV1U failed\n");
+    }
+///
+//  if (NODE_IS_CU(type)) {
+//    rc = itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL);
+//    AssertFatal(rc >= 0, "Create task for CU F1AP failed\n");
+//  }
+//
+//  if (NODE_IS_DU(type)) {
+//    rc = itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL);
+//    AssertFatal(rc >= 0, "Create task for DU F1AP failed\n");
+//  }
+//
+
+  if (is_m3ap_MCE_enabled()) {
+     rc = itti_create_task(TASK_M3AP_MCE, m3ap_MCE_task, NULL);
+     AssertFatal(rc >= 0, "Create task for M3AP MCE failed\n");
+
+  }
+  if (is_m2ap_MCE_enabled()) {
+     rc = itti_create_task(TASK_M2AP_MCE, m2ap_MCE_task, NULL);
+     AssertFatal(rc >= 0, "Create task for M2AP failed\n");
+  }
+
+  if (is_m2ap_eNB_enabled()) {
+     rc = itti_create_task(TASK_M2AP_ENB, m2ap_eNB_task, NULL);
+     AssertFatal(rc >= 0, "Create task for M2AP failed\n");
+  }
+
+   return 0;
+}
diff --git a/targets/COMMON/create_tasks_mbms.h b/targets/COMMON/create_tasks_mbms.h
new file mode 100644
index 0000000000000000000000000000000000000000..339f4aaa8f5fdaa1d0a8c2839afda9586e9f2053
--- /dev/null
+++ b/targets/COMMON/create_tasks_mbms.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef CREATE_TASKS_H_
+#define CREATE_TASKS_H_
+
+#if defined(ENABLE_ITTI)
+/* External declaration of L2L1 task that depend on the target */
+extern void *l2l1_task(void *arg);
+
+int create_tasks(uint32_t enb_nb);
+int create_tasks_ue(uint32_t ue_nb);
+int create_tasks_mbms(uint32_t enb_nb);
+#endif
+
+#endif /* CREATE_TASKS_H_ */
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 87001d2fc6718be7b6c711c5d32568203013e3f3..c718d9251afb211a188c9347fd6f54382de24018 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -1255,6 +1255,8 @@ void init_eNB(int single_thread_flag,
       AssertFatal((eNB->if_inst         = IF_Module_init(inst))!=NULL,"Cannot register interface");
       eNB->if_inst->schedule_response   = schedule_response;
       eNB->if_inst->PHY_config_req      = phy_config_request;
+      eNB->if_inst->PHY_config_update_sib2_req      = phy_config_update_sib2_request;
+      eNB->if_inst->PHY_config_update_sib13_req      = phy_config_update_sib13_request;
       memset((void *)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO));
       memset((void *)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO));
       LOG_I(PHY,"Setting indication lists\n");
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index e81b1ddc062e5a5a549cff43a59252fdf7b0e998..084543e39661deeb1df6337acffa830bd51440fc 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -97,6 +97,8 @@ static int DEFBFW[] = {0x00007fff};
 
 #include "pdcp.h"
 
+#define MBMS_EXPERIMENTAL
+
 extern volatile int oai_exit;
 extern int emulate_rf;
 extern int numerology;
@@ -1881,10 +1883,19 @@ static void *ru_thread( void *param ) {
 
         AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n");
 #endif
-
-        // wakeup all eNB processes waiting for this RU
-        if (ru->num_eNB>0) wakeup_L1s(ru);
-
+	// wakeup all eNB processes waiting for this RU
+	if (ru->num_eNB>0) wakeup_L1s(ru);
+
+#ifdef MBMS_EXPERIMENTAL
+	//Workaround ... this must be properly handled
+	if(ru->if_south==LOCAL_RF && ru->function==eNodeB_3GPP && RC.eNB[0][0]!=NULL){
+		if(ru->frame_parms.num_MBSFN_config!=RC.eNB[0][0]->frame_parms.num_MBSFN_config){
+			ru->frame_parms = RC.eNB[0][0]->frame_parms;//->frame_parms;
+			LOG_W(PHY,"RU MBSFN SF PARAMS Updated\n");
+		}
+	}
+#endif
+	
 #ifndef PHY_TX_THREAD
 
         if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_eNB==0) {
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 24a15816a20f08597d5c59f2b759c096bd86c90d..5fd2768ddee4b6ebe1cc7a50c47a80a5adbe7df1 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -494,6 +494,8 @@ void init_pdcp(void) {
     if (IS_SOFTMODEM_NOS1)
       pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT  ;
 
+    pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT;
+
     pdcp_module_init(pdcp_initmask);
 
     if (NODE_IS_CU(RC.rrc[0]->node_type)) {
@@ -707,6 +709,8 @@ int main ( int argc, char **argv )
     pthread_mutex_unlock(&sync_mutex);
     config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
   }
+  create_tasks_mbms(1);
+
   // wait for end of program
   LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
   // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file
diff --git a/targets/RT/USER/ru_control.c b/targets/RT/USER/ru_control.c
index d13abfc75323041f9a107b1a5b9fbe615244cc78..e01749b294d49b7f366bb442a26e47812f0a62f6 100644
--- a/targets/RT/USER/ru_control.c
+++ b/targets/RT/USER/ru_control.c
@@ -483,6 +483,27 @@ void configure_rru(int idx,
   phy_init_RU(ru);
 }
 
+static int send_update_rru(RU_t * ru, LTE_DL_FRAME_PARMS * fp){
+  //ssize_t      msg_len/*,len*/;
+  int i;
+  //LTE_DL_FRAME_PARMS *fp = &RC.eNB[0][0]->frame_parms;
+  RRU_CONFIG_msg_t rru_config_msg;
+  memset((void *)&rru_config_msg,0,sizeof(rru_config_msg));
+  rru_config_msg.type = RRU_config_update;
+  rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
+  LOG_I(PHY,"Sending RAU tick to RRU %d %lu bytes\n",ru->idx,rru_config_msg.len);
+
+  RRU_config_t       *config       = (RRU_config_t *)&rru_config_msg.msg[0];
+  config->num_MBSFN_config=fp->num_MBSFN_config;
+  for(i=0; i < fp->num_MBSFN_config; i++){
+       config->MBSFN_config[i] = fp->MBSFN_config[i];
+       LOG_W(PHY,"Configuration send to RAU (num MBSFN %d, MBSFN_SubframeConfig[%d] pattern is %x )\n",config->num_MBSFN_config,i,config->MBSFN_config[i].mbsfn_SubframeConfig);
+
+  }
+  AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
+                "RU %d cannot access remote radio\n",ru->idx);
+  return 0;
+}
 
 void* ru_thread_control( void* param )
 {
@@ -491,6 +512,7 @@ void* ru_thread_control( void* param )
   RRU_CONFIG_msg_t   rru_config_msg;
   ssize_t            msg_len;
   int                len;
+  int 		     ru_sf_update=0; // SF config update flag (MBSFN)
 
   // Start IF device if any
   if (ru->start_if) {
@@ -512,6 +534,16 @@ void* ru_thread_control( void* param )
       if (ru->state == RU_IDLE && ru->if_south != LOCAL_RF)
 	send_tick(ru);
 
+      if (ru->state == RU_RUN && ru->if_south != LOCAL_RF){
+	LTE_DL_FRAME_PARMS *fp = &RC.eNB[0][0]->frame_parms;	
+	LOG_D(PHY,"Check MBSFN SF changes\n");
+	if(fp->num_MBSFN_config != ru_sf_update){
+		ru_sf_update = fp->num_MBSFN_config;
+		LOG_W(PHY,"RU SF should be updated ... calling send_update_rru(ru)\n");
+		send_update_rru(ru,fp);
+	}
+      }
+
 	
       if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
 					       &rru_config_msg,
@@ -646,6 +678,30 @@ void* ru_thread_control( void* param )
 		}
 	      }		
 	      break;
+	    case RRU_config_update: //RRU
+	      if (ru->if_south == LOCAL_RF){
+		LOG_W(PHY,"Configuration update received from RAU \n");
+
+	    	msg_len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
+
+		LOG_W(PHY,"New MBSFN config received from RAU --- num_MBSFN_config %d\n",((RRU_config_t *)&rru_config_msg.msg[0])->num_MBSFN_config);
+	        ru->frame_parms.num_MBSFN_config = ((RRU_config_t *)&rru_config_msg.msg[0])->num_MBSFN_config;
+	        for(int i=0; i < ((RRU_config_t *)&rru_config_msg.msg[0])->num_MBSFN_config; i++){
+		 ru->frame_parms.MBSFN_config[i].mbsfn_SubframeConfig=((RRU_config_t *)&rru_config_msg.msg[0])->MBSFN_config[i].mbsfn_SubframeConfig;
+		  LOG_W(PHY,"Configuration received from RAU (num MBSFN %d, MBSFN_SubframeConfig[%d] pattern is %x )\n",
+		       ((RRU_config_t *)&rru_config_msg.msg[0])->num_MBSFN_config,
+		       i,
+		       ((RRU_config_t *)&rru_config_msg.msg[0])->MBSFN_config[i].mbsfn_SubframeConfig
+		       );
+		}
+	      } else LOG_E(PHY,"Received RRU_config msg...Ignoring\n");
+		break;
+	    case RRU_config_update_ok: //RAU
+	      if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_update_ok msg...Ignoring\n");
+	      else{
+			LOG_W(PHY,"Received RRU_config_update_ok msg...\n");
+	      }		
+	      break;
 
 	    case RRU_start: // RRU
 	      if (ru->if_south == LOCAL_RF){