diff --git a/common/ran_context.h b/common/ran_context.h
index 85c22467f67932d2b09ab3ad3ca44c5c8cbfc6c0..c0b58d2af2cc79bc09b179245a1d3e132b278ad9 100644
--- a/common/ran_context.h
+++ b/common/ran_context.h
@@ -103,8 +103,6 @@ typedef struct {
   pthread_mutex_t ru_mutex;
   /// condition variable for signaling setup completion of an RU
   pthread_cond_t ru_cond;
-  
-  struct cudu_params_s cudu;
 } RAN_CONTEXT_t;
 
 
diff --git a/common/utils/itti/backtrace.h b/common/utils/itti/backtrace.h
index 9a77767cf4a11ede13185e9140b475e2f404adba..b4620b6bedd0d19d322bb87e68f22c67a82fb244 100644
--- a/common/utils/itti/backtrace.h
+++ b/common/utils/itti/backtrace.h
@@ -24,7 +24,7 @@
 #ifndef BACKTRACE_H_
 #define BACKTRACE_H_
 
-void display_backtrace(void);
+void display_backtrace();
 
 void backtrace_handle_signal(siginfo_t *info);
 
diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h
index f08a9534d485e624acaa8547d3625d374db22e41..80da410facb49b498a03317c0fbd818baf2c6777 100644
--- a/openair2/COMMON/f1ap_messages_def.h
+++ b/openair2/COMMON/f1ap_messages_def.h
@@ -39,6 +39,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE                , MESSAGE_PRIORITY_MED, f1ap_ul_r
 /* RRC -> F1AP  messages */
 MESSAGE_DEF(F1AP_DL_RRC_MESSAGE              , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t              , f1ap_dl_rrc_message )
 //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req )
+MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_req_t, f1ap_ue_context_setup_req)
 
 
 
diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h
index 97254319061789628d904d24835ceaf55520b3dd..d133aab66e68af8ae44e5888d8293c52754f2893 100644
--- a/openair2/COMMON/f1ap_messages_types.h
+++ b/openair2/COMMON/f1ap_messages_types.h
@@ -22,6 +22,8 @@
 #ifndef F1AP_MESSAGES_TYPES_H_
 #define F1AP_MESSAGES_TYPES_H_
 
+#include "rlc.h"
+
 //-------------------------------------------------------------------------------------------//
 // Defines to access message fields.
 
@@ -33,6 +35,7 @@
 
 #define F1AP_INITIAL_UL_RRC_MESSAGE(mSGpTR)        (mSGpTR)->ittiMsg.f1ap_initial_ul_rrc_message
 #define F1AP_UL_RRC_MESSAGE(mSGpTR)                (mSGpTR)->ittiMsg.f1ap_ul_rrc_message
+#define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR)          (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req
 #define F1AP_UE_CONTEXT_RELEASE_RESP(mSGpTR)       (mSGpTR)->ittiMsg.f1ap_ue_context_release_resp
 #define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR)  (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp
 #define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR)  (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail
@@ -249,8 +252,31 @@ typedef struct f1ap_ul_rrc_message_s {
   int      rrc_container_length;
 } f1ap_ul_rrc_message_t;
 
-/*typedef struct f1ap_ue_context_setup_req_s {
- 
-  } f1ap_ue_context_setup_req_t;*/
+typedef struct f1ap_up_tnl_s {
+  in_addr_t tl_address; // currently only IPv4 supported
+  uint32_t  gtp_teid;
+} f1ap_up_tnl_t;
+
+typedef struct f1ap_drb_to_be_setup_s {
+  uint8_t        drb_id;
+  f1ap_up_tnl_t  up_ul_tnl[2];
+  uint8_t        up_ul_tnl_length;
+  rlc_mode_t     rlc_mode;
+} f1ap_drb_to_be_setup_t;
+
+typedef struct f1ap_ue_context_setup_req_s {
+  uint32_t gNB_CU_ue_id;
+  uint32_t *gNB_DU_ue_id;
+  // SpCell Info
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+  uint64_t nr_cellid;
+  uint32_t servCellId;
+  uint8_t *cu_to_du_rrc_information;
+  uint8_t  cu_to_du_rrc_information_length;
+  f1ap_drb_to_be_setup_t *drbs_to_be_setup;
+  uint8_t  drbs_to_be_setup_length;
+} f1ap_ue_context_setup_req_t;
 
 #endif /* F1AP_MESSAGES_TYPES_H_ */
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 872a5ff3581619fb75e2695874b82ca955bc0692..c9e67a7eceb952e05879a7bdd9b0f3dfa0f9e76d 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -416,132 +416,6 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) {
 }
 
 
-void RCconfig_cudu() {
-  int               j;
-  char 		    *transport_type;
-  char 		    *du_type;
-  char 		    *balancing;
-  
-  
-   
-  pthread_t myid = pthread_self();
-  printf("CONFIG my id is %u\n", myid);
-  
-  paramdef_t DU_Params[] = DUPARAMS_DESC;
-  paramdef_t CU_Params[] = CUPARAMS_DESC;
-  paramlist_def_t DU_ParamList = {CONFIG_STRING_DU_LIST,NULL,0};
-  paramlist_def_t CU_ParamList = {CONFIG_STRING_CU_LIST,NULL,0};
-  
-  config_getlist( &DU_ParamList,DU_Params,sizeof(DU_Params)/sizeof(paramdef_t), NULL);    
-  config_getlist( &CU_ParamList,CU_Params,sizeof(CU_Params)/sizeof(paramdef_t), NULL); 
-
-  paramdef_t CU_Bal[] = CU_BAL_DESC;
-  paramlist_def_t CU_BalList = {CONFIG_STRING_CU_BALANCING, NULL, 0}; 
-  config_get(&CU_Bal, sizeof(CU_Bal)/sizeof(paramdef_t),NULL);
-
-  //printf("%s\n", strdup(*(CU_Bal[0].strptr)));
-  
-  balancing = strdup(*(CU_Bal[0].strptr));
-  if (strcmp(balancing, "ALL") == 0)
-  {
-    RC.cudu.cu_balancing = CU_BALANCING_ALL;
-  }
-  else if (strcmp(balancing, "ROUND_ROBIN") == 0)
-  {
-    RC.cudu.cu_balancing = CU_BALANCING_ROUND_ROBIN;
-  }
-  else
-  {
-    RC.cudu.cu_balancing = atoi(balancing) - 1;
-  }
-	     
-  // DU Parameters
-  RC.cudu.local_du.du_interface = strdup(*(DU_ParamList.paramarray[0][DU_INTERFACE_F1U].strptr));
-  RC.cudu.local_du.du_ipv4_address = strdup(*(DU_ParamList.paramarray[0][DU_ADDRESS_F1U].strptr));
-  RC.cudu.local_du.du_port = *(DU_ParamList.paramarray[0][DU_PORT_F1U].iptr);
-  transport_type = strdup(*(DU_ParamList.paramarray[0][DU_TYPE_F1U].strptr));
-  
-  if (strcmp(transport_type, "TCP") == 0)
-  {
-    RC.cudu.local_du.tcp = 1;
-    RC.cudu.local_du.udp = 0;
-    RC.cudu.local_du.sctp = 0;
-  }
-  else if (strcmp(transport_type, "UDP") == 0)
-  {
-    RC.cudu.local_du.tcp = 0;
-    RC.cudu.local_du.udp = 1;
-    RC.cudu.local_du.sctp = 0;
-  }
-  else if (strcmp(transport_type, "SCTP") == 0)
-  {
-    RC.cudu.local_du.tcp = 0;
-    RC.cudu.local_du.udp = 0;
-    RC.cudu.local_du.sctp = 1;
-  }
-  else
-  {
-    RC.cudu.local_du.tcp = 1;
-    RC.cudu.local_du.udp = 0;
-    RC.cudu.local_du.sctp = 0;
-  }
-    
-  //CU Parameters
-  j =  CU_ParamList.numelt;
-  RC.cudu.serving_dus = j;
-  for (int k=0; k<j; k++)
-  {
-    RC.cudu.cu[k].cu_interface = strdup(*(CU_ParamList.paramarray[k][CU_INTERFACE_F1U].strptr));
-    RC.cudu.cu[k].cu_ipv4_address = strdup(*(CU_ParamList.paramarray[k][CU_ADDRESS_F1U].strptr));
-    RC.cudu.cu[k].cu_port = *(CU_ParamList.paramarray[k][CU_PORT_F1U].iptr);
-    RC.cudu.cu[k].cu_id = k;
-    du_type = strdup(*(CU_ParamList.paramarray[k][DU_TECH].strptr));
-    transport_type = strdup(*(CU_ParamList.paramarray[k][CU_TYPE_F1U].strptr));
-    if (strcmp(transport_type, "TCP") == 0)
-    {
-      RC.cudu.cu[k].tcp = 1;
-      RC.cudu.cu[k].udp = 0;
-      RC.cudu.cu[k].sctp = 0;
-    }
-    else if (strcmp(transport_type, "UDP") == 0)
-    {
-      RC.cudu.cu[k].tcp = 0;
-      RC.cudu.cu[k].udp = 1;
-      RC.cudu.cu[k].sctp = 0;
-    }
-    else if (strcmp(transport_type, "SCTP") == 0)
-    {
-      RC.cudu.cu[k].tcp = 0;
-      RC.cudu.cu[k].udp = 0;
-      RC.cudu.cu[k].sctp = 1;
-    }
-    else
-    {
-      RC.cudu.cu[k].tcp = 1;
-      RC.cudu.cu[k].udp = 0;
-      RC.cudu.cu[k].sctp = 0;
-    }
-    if (strcmp(du_type, "LTE") == 0)
-    {
-      RC.cudu.cu[k].du_type = DU_TYPE_LTE;
-    }
-    else if (strcmp(du_type, "WiFi") == 0)
-    {
-      RC.cudu.cu[k].du_type = DU_TYPE_WIFI;
-    }
-    else
-    {
-      RC.cudu.cu[k].du_type = DU_TYPE_LTE;
-    }
-  }
- 
-}
-
-cudu_params_t *get_cudu_config()
-{
-    return &(RC.cudu);
-}
-	       
 int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc) {
 
   int               num_enbs                      = 0;
@@ -2828,8 +2702,6 @@ void RCConfig(void) {
   
   char aprefix[MAX_OPTNAME_SIZE*2 + 8];  
   
-  //  RCconfig_cudu();
-
 /* get global parameters, defined outside any section in the config file */
  
   printf("Getting ENBSParams\n");
diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h
index cdca8bd2405fe0fb8e3775664f99444b2878770f..715ef4448379b36a0266e1ae66c5ecd413356780 100644
--- a/openair2/ENB_APP/enb_config.h
+++ b/openair2/ENB_APP/enb_config.h
@@ -82,37 +82,16 @@ typedef struct mme_ip_address_s {
 
 
 
-typedef struct du_interfaces {
-  char *du_interface;
-  char *du_ipv4_address;
-  uint16_t du_port;
-
-  
-  unsigned tcp:1;
-  unsigned udp:1;
-  unsigned sctp:1;
-  
-}du_interfaces_t;
-
-typedef struct cu_interfaces {
-  char *cu_interface;
-  char *cu_ipv4_address;
-  uint16_t cu_port;
-  uint8_t  du_type;
-  uint8_t  cu_id;
-  
-  unsigned tcp:1;
-  unsigned udp:1;
-  unsigned sctp:1;
-  
-}cu_interfaces_t;
-
-typedef struct cudu_params_s {
-  du_interfaces_t local_du;
-  cu_interfaces_t cu[MAX_DU];
-  uint8_t 	  serving_dus;
-  uint8_t 	  cu_balancing;
-}cudu_params_t;
+typedef struct du_params {
+  const char   *remote_ipv4_address;
+  const int16_t remote_port;
+} du_params_t;
+
+typedef struct cu_params {
+  const char    *local_interface;
+  const char    *local_ipv4_address;
+  const uint16_t local_port;
+} cu_params_t;
 
 typedef struct ru_config_s {
   // indicates if local or remote rf is used (1 == LOCAL)
@@ -145,11 +124,7 @@ void                          ru_config_display(void);
 
 int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc);
 int RCconfig_S1(MessageDef *msg_p, uint32_t i);
-int RCconfig_DU_F1(MessageDef *msg_p, uint32_t i);
-int RCconfig_CU_F1(uint32_t i);
 
-void RCconfig_cudu(void);
-cudu_params_t *get_cudu_config(void);
 void read_config_and_init(void);
 int RCconfig_X2(MessageDef *msg_p, uint32_t i);
 
diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c
index 7198effdad29c185ae56055da57d246998518778..75f59c837aa30884e8cde7338dc94233c3deac10 100644
--- a/openair2/F1AP/f1ap_cu_interface_management.c
+++ b/openair2/F1AP/f1ap_cu_interface_management.c
@@ -633,12 +633,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_
        F1AP_CP_TransportLayerAddress_t transportLayerAddress;
        memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
        transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address;
-       TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
+       TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
        
        // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
        // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port;
        // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t));
-       // TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
+       // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
 
        gnb_cu_tnl_association_to_add_item.tNLAssociationTransportLayerAddress = transportLayerAddress;
 
@@ -680,12 +680,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_
        F1AP_CP_TransportLayerAddress_t transportLayerAddress;
        memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
        transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address;
-       TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
+       TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
        
        // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
        // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port;
        // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t));
-       // TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
+       // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
 
        gnb_cu_tnl_association_to_remove_item.tNLAssociationTransportLayerAddress = transportLayerAddress;
    
@@ -722,12 +722,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_
        F1AP_CP_TransportLayerAddress_t transportLayerAddress;
        memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
        transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address;
-       TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
+       TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
        
        // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
        // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port;
        // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t));
-       // TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
+       // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
 
        gnb_cu_tnl_association_to_update_item.tNLAssociationTransportLayerAddress = transportLayerAddress;
    
diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c
index 49398f91a1890ac4d19739596c7edd34c22ca8f2..82f97e475881ca326a7cd42963e6323397fdf764 100644
--- a/openair2/F1AP/f1ap_cu_ue_context_management.c
+++ b/openair2/F1AP/f1ap_cu_ue_context_management.c
@@ -36,20 +36,17 @@
 #include "f1ap_itti_messaging.h"
 #include "f1ap_cu_ue_context_management.h"
 
-//void CU_send_UE_CONTEXT_SETUP_REQUEST(F1AP_UEContextSetupRequest_t *UEContextSetupRequest) {
-int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
+extern f1ap_setup_req_t *f1ap_du_data_from_du;
+
+int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
+                                     f1ap_ue_context_setup_req_t *f1ap_ue_context_setup_req) {
   F1AP_F1AP_PDU_t                 pdu;
   F1AP_UEContextSetupRequest_t    *out;
   F1AP_UEContextSetupRequestIEs_t *ie;
 
   uint8_t  *buffer;
   uint32_t  len;
-  int       i = 0;
-
-  // for test
-  int mcc = 208;
-  int mnc = 93;
-  int mnc_digit_length = 8;
+  int       i = 0, j = 0;
 
   /* Create */
   /* 0. Message Type */
@@ -67,17 +64,17 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
   ie->id                             = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
   ie->criticality                    = F1AP_Criticality_reject;
   ie->value.present                  = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID;
-  ie->value.choice.GNB_CU_UE_F1AP_ID = 126L;
+  ie->value.choice.GNB_CU_UE_F1AP_ID = f1ap_ue_context_setup_req->gNB_CU_ue_id;
   ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
 
   /* optional */
   /* c2. GNB_DU_UE_F1AP_ID */
-  if (0) {
+  if (f1ap_ue_context_setup_req->gNB_DU_ue_id) {
     ie = (F1AP_UEContextSetupRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextSetupRequestIEs_t));
     ie->id                             = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
     ie->criticality                    = F1AP_Criticality_ignore;
     ie->value.present                  = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID;
-    ie->value.choice.GNB_DU_UE_F1AP_ID = 651L;
+    ie->value.choice.GNB_DU_UE_F1AP_ID = *f1ap_ue_context_setup_req->gNB_DU_ue_id;
     ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
   }
 
@@ -89,9 +86,11 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
   ie->value.present                  = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI;
   /* - nRCGI */
   F1AP_NRCGI_t nRCGI;
-  MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length,
-                                       &nRCGI.pLMN_Identity);
-  NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity);
+  MCC_MNC_TO_PLMNID(f1ap_ue_context_setup_req->mcc,
+                    f1ap_ue_context_setup_req->mnc,
+                    f1ap_ue_context_setup_req->mnc_digit_length,
+                    &nRCGI.pLMN_Identity);
+  NR_CELL_ID_TO_BIT_STRING(f1ap_ue_context_setup_req->nr_cellid, &nRCGI.nRCellIdentity);
 
   ie->value.choice.NRCGI = nRCGI;
 
@@ -141,7 +140,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
   ie->value.present                  = F1AP_UEContextSetupRequestIEs__value_PR_Candidate_SpCell_List;
 
   for (i=0;
-       i<1;
+       i<0;
        i++) {
 
     F1AP_Candidate_SpCell_ItemIEs_t *candidate_spCell_item_ies;
@@ -156,9 +155,12 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
 
     /* - candidate_SpCell_ID */
     F1AP_NRCGI_t nRCGI;
-    MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length,
-                                       &nRCGI.pLMN_Identity);
-    NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity);
+    /* TODO add correct mcc/mnc */
+    MCC_MNC_TO_PLMNID(f1ap_ue_context_setup_req->mcc,
+                      f1ap_ue_context_setup_req->mnc,
+                      f1ap_ue_context_setup_req->mnc_digit_length,
+                      &nRCGI.pLMN_Identity);
+    NR_CELL_ID_TO_BIT_STRING(f1ap_ue_context_setup_req->nr_cellid, &nRCGI.nRCellIdentity);
 
     candidate_spCell_item.candidate_SpCell_ID = nRCGI;
 
@@ -198,7 +200,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
     
     ie->value.choice.ResourceCoordinationTransferContainer.buf = malloc(4);
     ie->value.choice.ResourceCoordinationTransferContainer.size = 4;
-    *ie->value.choice.ResourceCoordinationTransferContainer.buf = "123";
+    strncpy(ie->value.choice.ResourceCoordinationTransferContainer.buf, "123", 3);
 
 
     OCTET_STRING_fromBuf(&ie->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as",
@@ -215,7 +217,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
   ie->value.present                  = F1AP_UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List;
 
   for (i=0;
-       i<1;
+       i<0;
        i++) {
      //
      F1AP_SCell_ToBeSetup_ItemIEs_t *scell_toBeSetup_item_ies;
@@ -230,8 +232,11 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
 
      //   /* - sCell_ID */
      F1AP_NRCGI_t nRCGI;
-     MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length,
-                                        &nRCGI.pLMN_Identity);
+     /* TODO correct MCC/MNC */
+     MCC_MNC_TO_PLMNID(f1ap_ue_context_setup_req->mcc,
+                       f1ap_ue_context_setup_req->mnc,
+                       f1ap_ue_context_setup_req->mnc_digit_length,
+                       &nRCGI.pLMN_Identity);
      NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity);
 
      scell_toBeSetup_item.sCell_ID = nRCGI;
@@ -254,7 +259,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
   ie->value.present                  = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List;
 
   for (i=0;
-       i<1;
+       i<0;
        i++) {
     //
     F1AP_SRBs_ToBeSetup_ItemIEs_t *srbs_toBeSetup_item_ies;
@@ -284,9 +289,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
   ie->criticality                    = F1AP_Criticality_reject;
   ie->value.present                  = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List;
 
-  for (i=0;
-       i<1;
-       i++) {
+  for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; i++) {
     //
     F1AP_DRBs_ToBeSetup_ItemIEs_t *drbs_toBeSetup_item_ies;
     drbs_toBeSetup_item_ies = (F1AP_DRBs_ToBeSetup_ItemIEs_t *)calloc(1, sizeof(F1AP_DRBs_ToBeSetup_ItemIEs_t));
@@ -299,7 +302,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
     memset((void *)&drbs_toBeSetup_item, 0, sizeof(F1AP_DRBs_ToBeSetup_Item_t));
 
     /* dRBID */
-    drbs_toBeSetup_item.dRBID = 30L;
+    drbs_toBeSetup_item.dRBID = f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id;
 
     /* qoSInformation */
     drbs_toBeSetup_item.qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS;
@@ -307,30 +310,35 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
     drbs_toBeSetup_item.qoSInformation.choice.eUTRANQoS->qCI = 254L;
 
     /* ULTunnels_ToBeSetup_List */
-    int maxnoofULTunnels = 1; // 2;
-    for (i=0;
-            i<maxnoofULTunnels;
-            i++) {
-            /*  ULTunnels_ToBeSetup_Item */
-            F1AP_ULUPTNLInformation_ToBeSetup_Item_t *uLUPTNLInformation_ToBeSetup_Item;
+    for (j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) {
+      f1ap_up_tnl_t *up_tnl = &f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j];
+      /*  ULTunnels_ToBeSetup_Item */
+      F1AP_ULUPTNLInformation_ToBeSetup_Item_t *uLUPTNLInformation_ToBeSetup_Item;
 
-            // gTPTunnel
-            uLUPTNLInformation_ToBeSetup_Item = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)calloc(1, sizeof(F1AP_ULUPTNLInformation_ToBeSetup_Item_t));
-            uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
-            F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
+      // gTPTunnel
+      uLUPTNLInformation_ToBeSetup_Item = calloc(1, sizeof(F1AP_ULUPTNLInformation_ToBeSetup_Item_t));
+      uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present =
+          F1AP_UPTransportLayerInformation_PR_gTPTunnel;
+      F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
 
-            TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
+      TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(up_tnl->tl_address, &gTPTunnel->transportLayerAddress);
 
-            OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1234",
-                           strlen("1234"));
-            
-            uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel = gTPTunnel;
+      INT32_TO_OCTET_STRING(up_tnl->gtp_teid, &gTPTunnel->gTP_TEID);
+
+      uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel = gTPTunnel;
 
-            ASN_SEQUENCE_ADD(&drbs_toBeSetup_item.uLUPTNLInformation_ToBeSetup_List.list, uLUPTNLInformation_ToBeSetup_Item);
+      ASN_SEQUENCE_ADD(&drbs_toBeSetup_item.uLUPTNLInformation_ToBeSetup_List.list, uLUPTNLInformation_ToBeSetup_Item);
     }
 
     /* rLCMode */
-    drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_um; // enum
+    /* TODO use rlc_mode from f1ap_drb_to_be_setup */
+    switch (f1ap_ue_context_setup_req->drbs_to_be_setup[i].rlc_mode) {
+    case RLC_MODE_AM:
+      drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_am;
+      break;
+    default:
+      drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_um;
+    }
 
     /* OPTIONAL */
     /* ULConfiguration */
@@ -445,7 +453,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) {
 
   /* optional */
   /* c3. NRCGI */
-  if (1) {
+  if (0) {
     ie = (F1AP_UEContextModificationRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextModificationRequestIEs_t));
     ie->id                             = F1AP_ProtocolIE_ID_id_SpCell_ID;
     ie->criticality                    = F1AP_Criticality_ignore;
@@ -703,7 +711,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) {
             uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
             F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
 
-            TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
+            TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
 
             OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "4567",
                              strlen("4567"));
@@ -771,7 +779,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) {
             uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
             F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
 
-            TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
+            TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
 
             OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204",
                                  strlen("1204"));
diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.h b/openair2/F1AP/f1ap_cu_ue_context_management.h
index f103a170737d7e7a65d454e4b6cb05e80098c479..9e25309aa9d2ad61b56e86a9a249c7f56bb1b3ce 100644
--- a/openair2/F1AP/f1ap_cu_ue_context_management.h
+++ b/openair2/F1AP/f1ap_cu_ue_context_management.h
@@ -36,7 +36,8 @@
 /*
  * UE Context Setup
  */
-int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance);
+int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
+                                     f1ap_ue_context_setup_req_t *f1ap_ue_context_setup_req);
 
 int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t       instance,
                                         uint32_t         assoc_id,
diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c
index d4d10202066b529bc09590c8f6b54250dbf6a30e..76aa4299a1255b2ea88d1b905a9cd380309d7c34 100644
--- a/openair2/F1AP/f1ap_du_ue_context_management.c
+++ b/openair2/F1AP/f1ap_du_ue_context_management.c
@@ -41,8 +41,91 @@ extern f1ap_setup_req_t *f1ap_du_data;
 int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t       instance,
                                        uint32_t         assoc_id,
                                        uint32_t         stream,
-                                       F1AP_F1AP_PDU_t *pdu) {
-  AssertFatal(1==0,"Not implemented yet\n");
+                                       F1AP_F1AP_PDU_t *pdu)
+{
+  MessageDef                      *msg_p; // message to RRC
+  F1AP_UEContextSetupRequest_t    *container;
+  F1AP_UEContextSetupRequestIEs_t *ie;
+  int i;
+
+  DevAssert(pdu);
+
+  msg_p = itti_alloc_new_message(TASK_DU_F1, F1AP_UE_CONTEXT_SETUP_REQ);
+	f1ap_ue_context_setup_req_t *f1ap_ue_context_setup_req;
+	f1ap_ue_context_setup_req = &F1AP_UE_CONTEXT_SETUP_REQ(msg_p);
+
+  container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest;
+
+  F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container,
+                             F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
+  f1ap_ue_context_setup_req->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
+
+  F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container,
+                             F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, false);
+  if (ie) {
+    f1ap_ue_context_setup_req->gNB_DU_ue_id = malloc(sizeof(uint32_t));
+    if (f1ap_ue_context_setup_req->gNB_DU_ue_id)
+      *f1ap_ue_context_setup_req->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
+  } else {
+    f1ap_ue_context_setup_req->gNB_DU_ue_id = NULL;
+  }
+
+  F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container,
+                             F1AP_ProtocolIE_ID_id_SpCell_ID, true);
+  PLMNID_TO_MCC_MNC(&ie->value.choice.NRCGI.pLMN_Identity,
+										f1ap_ue_context_setup_req->mcc,
+										f1ap_ue_context_setup_req->mnc,
+                    f1ap_ue_context_setup_req->mnc_digit_length);
+  BIT_STRING_TO_NR_CELL_IDENTITY(&ie->value.choice.NRCGI.nRCellIdentity, f1ap_ue_context_setup_req->nr_cellid);
+
+  /* TODO: decode candidate SpCell */
+
+  /* TODO: decode CUtoDURRCInformation */
+
+  /* TODO: Candidate_SpCell_List */
+
+  /* TODO: SCell_ToBeSetup_List */
+
+  /* TODO: SRBs_ToBeSetup_List */
+
+  /* Decode DRBs_ToBeSetup_List */
+  F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container,
+                             F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List, true);
+  f1ap_ue_context_setup_req->drbs_to_be_setup_length = ie->value.choice.DRBs_ToBeSetup_List.list.count;
+  f1ap_ue_context_setup_req->drbs_to_be_setup = calloc(f1ap_ue_context_setup_req->drbs_to_be_setup_length,
+                                                       sizeof(f1ap_drb_to_be_setup_t));
+  AssertFatal(f1ap_ue_context_setup_req->drbs_to_be_setup,
+              "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n");
+  for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; ++i) {
+    f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_req->drbs_to_be_setup[i];
+    F1AP_DRBs_ToBeSetup_Item_t *drbs_tobesetup_item_p;
+    drbs_tobesetup_item_p = &((F1AP_DRBs_ToBeSetup_ItemIEs_t *)ie->value.choice.DRBs_ToBeSetup_List.list.array[i])->value.choice.DRBs_ToBeSetup_Item;
+
+    drb_p->drb_id = drbs_tobesetup_item_p->dRBID;
+
+    /* TODO in the following, assume only one UP UL TNL is present.
+     * this matches/assumes OAI CU implementation, can be up to 2! */
+    drb_p->up_ul_tnl_length = 1;
+    AssertFatal(drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0,
+                "no UL UP TNL Information in DRBs to be Setup list\n");
+    F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0];
+    F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel;
+    BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address);
+    OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].gtp_teid);
+
+    switch (drbs_tobesetup_item_p->rLCMode) {
+    case F1AP_RLCMode_rlc_am:
+      drb_p->rlc_mode = RLC_MODE_AM;
+      break;
+    default:
+      drb_p->rlc_mode = RLC_MODE_TM;
+      break;
+    }
+  }
+
+  AssertFatal(0, "check configuration, send to appropriate handler\n");
+
+  return 0;
 }
 
 //void DU_send_UE_CONTEXT_SETUP_RESPONSE(F1AP_UEContextSetupResponse_t *UEContextSetupResponse) {
@@ -153,7 +236,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(instance_t instance) {
        // *transportLayerAddress.buf = 123;
        // dLUPTNLInformation_ToBeSetup_Item.dL_GTP_Tunnel_EndPoint.transportLayerAddress = transportLayerAddress;
 
-       TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
+       TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
 
        OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204",
                              strlen("1204"));
@@ -441,7 +524,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) {
         dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
         F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
 
-        TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
+        TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
 
         OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204",
                              strlen("1204"));
@@ -495,7 +578,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) {
         dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
         F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
 
-        TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
+        TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
 
         OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204",
                               strlen("1204"));
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index 4f1b7f3d00b6a8f3ae5afc8e45cb5f9ffa3e4e8c..e3fec20747d3bf932d0125d15033002830bfe5d2 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -375,50 +375,23 @@ boolean_t pdcp_data_req(
 
     LOG_F(PDCP,"\n");
 #ifndef UETARGET
-    static cudu_params_t *cudu = NULL;
-    if (ctxt_pP->enb_flag == 1)
-    {
-	if (cudu == NULL) 
-	{
-	  cudu = get_cudu_config();
-	}
-	static int agent_started = 1;
-	if (agent_started == 1)
-	{
-	    for (int k =0; k<cudu->serving_dus; k++)
-	    { 
-	      proto_agent_start(0, cudu->cu[k].cu_id, cudu->cu[k].du_type, cudu);
-	    }
-	    agent_started = 0;
-	}
-    }
     if ((pdcp_pdu_p!=NULL) && (srb_flagP == 0) && (ctxt_pP->enb_flag == 1))
     {
 
-      if (cudu->cu_balancing == CU_BALANCING_ALL)
       {
-	for (int j =0; j<cudu->serving_dus; j++)
-	{
-	  proto_agent_send_rlc_data_req(0,cudu->cu[j].du_type, ctxt_pP, srb_flagP, MBMS_FLAG_NO,rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
-	}
-    rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p
+        LOG_E(PDCP, "proto_agent_send_rlc_data_req()\n");
+        {
+          //proto_agent_send_rlc_data_req(0,cudu->cu[j].du_type, ctxt_pP, srb_flagP,
+              //MBMS_FLAG_NO,rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
+        }
+    //rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p
 #if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
-                             ,sourceL2Id
-                             ,destinationL2Id
+                             //,sourceL2Id
+                             //,destinationL2Id
 #endif
-                             );
+                             //);
 
       }
-      else if (cudu->cu_balancing == CU_BALANCING_ROUND_ROBIN)
-      {
-	int selected_du = select_du(cudu->serving_dus);
-	proto_agent_send_rlc_data_req(cudu->cu[selected_du].cu_id,cudu->cu[selected_du].du_type,ctxt_pP, srb_flagP, MBMS_FLAG_NO,rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
-      }
-	else
-	{
-	    int index = cudu->cu_balancing;
-	    proto_agent_send_rlc_data_req(cudu->cu[index].cu_id,cudu->cu[index].du_type,ctxt_pP, srb_flagP, MBMS_FLAG_NO,rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
-	}
     
     free_mem_block(pdcp_pdu_p, __FUNCTION__);
     rlc_status = ack_result;
diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent.c b/openair2/LAYER2/PROTO_AGENT/proto_agent.c
index fd809d5f9a4aabac6137d069de5c753f64ab56af..ee12cd62578248dde7514e3ed22c7f04030591e2 100644
--- a/openair2/LAYER2/PROTO_AGENT/proto_agent.c
+++ b/openair2/LAYER2/PROTO_AGENT/proto_agent.c
@@ -45,251 +45,80 @@
 proto_agent_instance_t proto_agent[MAX_DU];
 proto_agent_instance_t proto_server[MAX_DU];
 
-char in_ip[40];
-static uint16_t in_port;
-char local_cache[40];
-
-void *send_thread(void *args);
-//void *receive_thread(void *args);
 pthread_t new_thread(void *(*f)(void *), void *b);
-pthread_t cu_thread[MAX_DU], du_thread;
-Protocol__FlexsplitMessage *proto_agent_timeout_fsp(void* args);
 
-mod_id_t client_mod[MAX_DU], server_mod;
-proto_agent_async_channel_t *client_channel[MAX_DU], *server_channel;
-proto_recv_t client_info[MAX_DU];
+Protocol__FlexsplitMessage *proto_agent_timeout_fsp(void* args);
 
 #define TEST_MOD 0
 
-uint8_t tcp = 0;
-uint8_t udp = 0;
-uint8_t sctp = 0;
-char *link_type = NULL;
-
-
 #define ECHO
 
-/* Thread continuously listening for incomming packets */
-/*
-void *receive_thread(void *args) {
-
-  proto_agent_instance_t         *d = args;
-  void                  *data;
-  int                   size;
-  int                   priority;
-  err_code_t             err_code = 0;
-
-  Protocol__FlexsplitMessage *msg;
-
-  while (1) {
-    if (proto_agent_msg_recv(d->enb_id, PROTO_AGENT_DEFAULT, &data, &size, &priority)) {
-      err_code = PROTOCOL__FLEXSPLIT_ERR__MSG_ENQUEUING;
-      goto error;
-    }
-
-    LOG_D(PROTO_AGENT, "Received message with size %d and priority %d, calling message handle\n", size, priority);
-
-    msg=proto_agent_handle_message(d->enb_id, data, size);
-
-    if (msg == NULL)
-    {
-        LOG_D(PROTO_AGENT, "msg to send back is NULL\n");
-    }
-    
-    if (msg != NULL){
-      if (proto_agent_msg_send(d->enb_id, PROTO_AGENT_DEFAULT, msg, size, priority)) {
-	err_code = PROTOCOL__FLEXSPLIT_ERR__MSG_ENQUEUING;
-	goto error;
-      }
-      LOG_D(PROTO_AGENT, "sent message with size %d\n", size);
-    }
-  }
-
-  return NULL;
-
-error:
-  LOG_E(PROTO_AGENT, "receive_thread: error %d occured\n",err_code);
-  return NULL;
-}
-*/
-
-/* utility function to create a thread */
-/*
-pthread_t new_thread(void *(*f)(void *), void *b) {
-  pthread_t t;
-  pthread_attr_t att;
-
-  if (pthread_attr_init(&att)){ 
-    fprintf(stderr, "pthread_attr_init err\n"); 
-    exit(1); 
-  }
-  if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) { 
-    fprintf(stderr, "pthread_attr_setdetachstate err\n"); 
-    exit(1); 
-  }
-  if (pthread_create(&t, &att, f, b)) { 
-    fprintf(stderr, "pthread_create err\n"); 
-    exit(1); 
-  }
-  if (pthread_attr_destroy(&att)) { 
-    fprintf(stderr, "pthread_attr_destroy err\n"); 
-    exit(1); 
-  }
-
-  return t;
-}
-*/
-/* Function to be called as a thread: 
-   it is calling the proto_agent_server with 
-   the appropriate arguments 
-*/
-
-void * proto_server_init(void *args)
-{
-   //printf( "Initializing server thread for listening connections\n");
-   mod_id_t mod_id = (mod_id_t) 0;
-   cudu_params_t* cudu = NULL;
-   cudu = get_cudu_config();
-   proto_server_start(mod_id, (const cudu_params_t*) cudu);
-   return NULL;
-}
-
 /*  Server side function; upon a new connection 
     reception, sends the hello packets
 */
-int proto_server_start(mod_id_t mod_id, const cudu_params_t* cudu){
-  
+int proto_server_start(mod_id_t mod_id, const cu_params_t *cu)
+{
   int channel_id;
-  char *peer_address = NULL;
-  
-  proto_server[mod_id].enb_id = mod_id;
+
+  DevAssert(cu->local_interface);
+  DevAssert(cu->local_ipv4_address);
+  DevAssert(cu->local_port > 1024); // "unprivileged" port
   
-  server_mod = mod_id;
+  proto_server[mod_id].mod_id = mod_id;
 
-  if (cudu->local_du.du_ipv4_address != NULL)
-  {
-    //LOG_D(PROTO_AGENT, "DU ADDRESS IS %s\n",cudu->local_du.du_ipv4_address);
-    peer_address = strdup(cudu->local_du.du_ipv4_address);
-    strcpy(in_ip, cudu->local_du.du_ipv4_address);
-  }
-  else
-  {
-    strcpy(in_ip, DEFAULT_PROTO_AGENT_IPv4_ADDRESS);
-    //LOG_D(PROTO_AGENT, "Cannot read DU address from conf file, setting the default (%s)\n", DEFAULT_PROTO_AGENT_IPv4_ADDRESS);
-  }
-  if (cudu->local_du.du_port != 0)
-    in_port = cudu->local_du.du_port;
-  else
-  {
-    in_port = DEFAULT_PROTO_AGENT_PORT;
-    //LOG_D(PROTO_AGENT, "Cannot read DU port from conf file, setting the default (%d)\n", DEFAULT_PROTO_AGENT_PORT);
-  }
+  /* Initialize the channel container */
 
-  if(cudu->local_du.tcp == 1)
-  {
-      tcp = 1;
-      link_type = strdup("TCP");
-      LOG_D(PROTO_AGENT, "Starting PROTO agent SERVER for module id %d on ipv4 %s, port %d over TCP\n",
-	proto_server[mod_id].enb_id,
-	in_ip,
-	in_port);
-  }
-  else if(cudu->local_du.udp  == 1)
-  {
-      udp = 1;      
-      link_type = strdup("UDP");
-      LOG_D(PROTO_AGENT, "Starting PROTO agent SERVER for module id %d on ipv4 %s, port %d over UDP\n",
-	proto_server[mod_id].enb_id,
-	in_ip,
-	in_port);
-  }
-  else if(cudu->local_du.sctp  == 1)
-  {
-      sctp = 1;
-      link_type = strdup("SCTP");
-      LOG_D(PROTO_AGENT, "Starting PROTO agent SERVER for module id %d on ipv4 %s, port %d over SCTP\n",
-	proto_server[mod_id].enb_id,
-	in_ip,
-	in_port);
-  }
-  else
-  {
-      tcp = 1;
-      link_type = strdup("TCP");
-      LOG_D(PROTO_AGENT, "Starting PROTO agent SERVER for module id %d on ipv4 %s, port %d over TCP\n",
-	proto_server[mod_id].enb_id,
-	in_ip,
-	in_port);
-    
-  }  
-  
-  /*
-   * Initialize the channel container
-   */
+  /* TODO only initialize the first time */
   proto_agent_init_channel_container();
 
   /*Create the async channel info*/
-  proto_agent_async_channel_t *channel_info = proto_server_async_channel_info(mod_id, in_ip, in_port, link_type, peer_address);
+  proto_agent_async_channel_t *channel_info;
+  channel_info = proto_server_async_channel_info(mod_id, cu->local_ipv4_address, cu->local_port);
   
-  server_channel = channel_info;
-
-  /*Create a channel using the async channel info*/
+  /* Create a channel using the async channel info */
   channel_id = proto_agent_create_channel((void *) channel_info,
 					proto_agent_async_msg_send,
 					proto_agent_async_msg_recv,
 					proto_agent_async_release);
-
-  if (channel_id <= 0) {
-    goto error;
-  }
+  if (channel_id <= 0) goto error;
 
   proto_agent_channel_t *channel = proto_agent_get_channel(channel_id);
-  
-    
-  if (tcp == 1) channel->type = 0;
-  else if (udp == 1) channel->type = 1;
-  else if (sctp == 1) channel->type = 2;
-  else channel->type = 0;
-  
-  if (channel == NULL) {
-    goto error;
-  }
+  if (!channel) goto error;
+  proto_server[mod_id].channel = channel;
 
-  /*Register the channel for all underlying agents (use ENB_AGENT_MAX)*/
+  /* Register the channel for all underlying agents (use ENB_AGENT_MAX) */
   proto_agent_register_channel(mod_id, channel, ENB_AGENT_MAX);
 
   // Code for sending the HELLO/ECHO_REQ message once a connection is established
-  uint8_t *msg = NULL;
-  Protocol__FlexsplitMessage *init_msg=NULL;
-  int msg_flag = 0;
-
-  if (udp == 0)
-  {
-    // If the comm is not UDP, allow the server to send the first packet over the channel
-    //printf( "Proto agent Server: Calling the echo_request packet constructor\n");
-    msg_flag = proto_agent_echo_request(mod_id, NULL, &init_msg);
-    if (msg_flag != 0)
-    goto error;
-  
-    int msgsize = 0;
-    if (init_msg != NULL)
-      msg = proto_agent_pack_message(init_msg, &msgsize);
-
-    if (msg!= NULL)
-    {
-      LOG_D(PROTO_AGENT, "Server sending the message over the async channel\n");
-      proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, (void *) channel_info);
-    }
-    /* After sending the message, wait for any replies; 
-      the server thread blocks until it reads any data 
-      over the channel
-    */
-
-  }
+  //uint8_t *msg = NULL;
+  //Protocol__FlexsplitMessage *init_msg=NULL;
+
+  //if (udp == 0)
+  //{
+  //  // If the comm is not UDP, allow the server to send the first packet over the channel
+  //  //printf( "Proto agent Server: Calling the echo_request packet constructor\n");
+  //  msg_flag = proto_agent_echo_request(mod_id, NULL, &init_msg);
+  //  if (msg_flag != 0)
+  //  goto error;
+  //
+  //  int msgsize = 0;
+  //  if (init_msg != NULL)
+  //    msg = proto_agent_pack_message(init_msg, &msgsize);
+
+  //  if (msg!= NULL)
+  //  {
+  //    LOG_D(PROTO_AGENT, "Server sending the message over the async channel\n");
+  //    proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, (void *) channel_info);
+  //  }
+  //  /* After sending the message, wait for any replies;
+  //    the server thread blocks until it reads any data
+  //    over the channel
+  //  */
+
+  //}
+
+  proto_server[mod_id].recv_thread = new_thread(proto_server_receive, &proto_server[mod_id]);
 
-  
-  du_thread=new_thread(proto_server_receive, &proto_server[mod_id]);
-  LOG_D(PROTO_AGENT, "server ends with thread_id %lu\n",du_thread);
   return 0;
 
 error:
@@ -298,139 +127,67 @@ error:
 
 }
 
-int proto_agent_start(uint8_t enb_id, mod_id_t cu_id, uint8_t type_id, cudu_params_t *cudu){
-  
+int proto_agent_start(mod_id_t mod_id, const du_params_t *du)
+{
   int channel_id;
-  char *peer_address = NULL;
- // cudu_params_t *cudu = get_cudu_config();
-  
-  proto_agent[cu_id].enb_id = cu_id;
-  client_mod[cu_id] = cu_id; // FIXME: Allow for multiple types, now it will allow for DUs of different type per mod_id
-  
-  client_info[cu_id].type_id = type_id;
-  client_info[cu_id].mod_id = cu_id;
+
+  DevAssert(du->remote_ipv4_address);
+  DevAssert(du->remote_port > 1024); // "unprivileged" port
   
-  /* 
-   * check the configuration - Getting all the values from the config file
-   */ 
+  proto_agent[mod_id].mod_id = mod_id;
   
-  if (cudu->cu[cu_id].cu_ipv4_address != NULL)
-  {
-    strcpy(in_ip, cudu->cu[cu_id].cu_ipv4_address); 
-    peer_address = strdup(cudu->cu[cu_id].cu_ipv4_address);
-  }
-  else
-  {
-    strcpy(in_ip, DEFAULT_PROTO_AGENT_IPv4_ADDRESS);
-    LOG_D(PROTO_AGENT, "Cannot read DU address from conf file, setting the default (%s)\n", DEFAULT_PROTO_AGENT_IPv4_ADDRESS);
-  }
-  if (cudu->cu[cu_id].cu_port != 0)
-    in_port = cudu->cu[cu_id].cu_port;
-  else
-  {
-    in_port = DEFAULT_PROTO_AGENT_PORT;
-    LOG_D(PROTO_AGENT, "Cannot read DU port from conf file, setting the default (%d)\n", DEFAULT_PROTO_AGENT_PORT);
-  }
-
-  if(cudu->cu[cu_id].tcp == 1)
-  {
-      tcp = 1;
-      link_type = strdup("TCP");
-      LOG_D(PROTO_AGENT, "Starting PROTO agent client for module id %d on ipv4 %s, port %d over TCP\n",
-	proto_server[cu_id].enb_id,
-	in_ip,
-	in_port);
-  }
-  else if(cudu->cu[cu_id].udp == 1)
-  {
-      udp = 1;      
-      link_type = strdup("UDP");
-      LOG_D(PROTO_AGENT, "Starting PROTO agent client for module id %d on ipv4 %s, port %d over UDP\n",
-	proto_server[cu_id].enb_id,
-	in_ip,
-	in_port);
-  }
-  else if(cudu->cu[cu_id].sctp == 1)
-  {
-      sctp = 1;
-      link_type = strdup("SCTP");
-      LOG_D(PROTO_AGENT, "Starting PROTO agent client for module id %d on ipv4 %s, port %d over SCTP\n",
-	proto_server[cu_id].enb_id,
-	in_ip,
-	in_port);
-  }
-  else
-  {
-      tcp = 1;
-      link_type = strdup("TCP");
-      LOG_D(PROTO_AGENT, "Starting PROTO agent client for module id %d on ipv4 %s, port %d over TCP\n",
-	proto_server[cu_id].enb_id,
-	in_ip,
-	in_port);
-    
-  }  
-
-  /*
-   * Initialize the channel container
-   */
+  /* TODO only initialize the first time */
   proto_agent_init_channel_container();
 
   /*Create the async channel info*/
   
-  proto_agent_async_channel_t *channel_info = proto_agent_async_channel_info(cu_id, in_ip, in_port, link_type, peer_address);
-  client_channel[cu_id] = channel_info;
+  proto_agent_async_channel_t *channel_info = proto_agent_async_channel_info(mod_id, du->remote_ipv4_address, du->remote_port);
+  if (!channel_info) goto error;
+
   /*Create a channel using the async channel info*/
   channel_id = proto_agent_create_channel((void *) channel_info, 
 					proto_agent_async_msg_send, 
 					proto_agent_async_msg_recv,
 					proto_agent_async_release);
-  if (channel_id <= 0) {
-    goto error;
-  }
+  if (channel_id <= 0) goto error;
 
   proto_agent_channel_t *channel = proto_agent_get_channel(channel_id);
+  if (!channel) goto error;
+  proto_agent[mod_id].channel = channel;
 
-  if (channel == NULL) {
-    goto error;
-  }
-  
-  if (tcp == 1) channel->type = 0;
-  else if (udp == 1) channel->type = 1;
-  else if (sctp == 1) channel->type = 2;
-  else channel->type = 0;
-
-  /*Register the channel for all underlying agents (use ENB_AGENT_MAX)*/
-  proto_agent_register_channel(cu_id, channel, ENB_AGENT_MAX);
+  /* Register the channel for all underlying agents (use ENB_AGENT_MAX) */
+  proto_agent_register_channel(mod_id, channel, ENB_AGENT_MAX);
 
-  uint8_t *msg = NULL;
-  Protocol__FlexsplitMessage *init_msg=NULL;
-  int msg_flag;
+  //uint8_t *msg = NULL;
+  //Protocol__FlexsplitMessage *init_msg=NULL;
+  //int msg_flag;
   
   // In the case of UDP comm, start the echo request from the client side; the server thread should be blocked until it reads the SRC port of the 1st packet
-  if (udp == 1)
-  {
-    msg_flag = proto_agent_echo_request(cu_id, NULL, &init_msg);  
-
-
-
-    if (msg_flag != 0)
-      goto error;
-    
-    int msgsize = 0;
-    if (init_msg != NULL)
-      msg = proto_agent_pack_message(init_msg, &msgsize);
-
-    if (msg!= NULL)
-    {
-      LOG_D(PROTO_AGENT, "Client sending the ECHO_REQUEST message over the async channel\n");
-      proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, (void *) channel_info);
-    }
-  }
+  //if (udp == 1)
+  //{
+  //  msg_flag = proto_agent_echo_request(cu_id, NULL, &init_msg);
+
+
+
+  //  if (msg_flag != 0)
+  //    goto error;
+  //
+  //  int msgsize = 0;
+  //  if (init_msg != NULL)
+  //    msg = proto_agent_pack_message(init_msg, &msgsize);
+
+  //  if (msg!= NULL)
+  //  {
+  //    LOG_D(PROTO_AGENT, "Client sending the ECHO_REQUEST message over the async channel\n");
+  //    proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, (void *) channel_info);
+  //  }
+  //}
+  //
   /* After sending the message, wait for any replies; 
      the server thread blocks until it reads any data 
      over the channel
   */
-  cu_thread[cu_id]=new_thread(proto_client_receive, (void *) &client_info[cu_id]);
+  proto_agent[mod_id].recv_thread = new_thread(proto_client_receive, &proto_agent[mod_id]);
   return 0;
 
 error:
@@ -439,31 +196,33 @@ error:
 
 }
 
-void 
-proto_agent_send_hello(void)
-{
-  uint8_t *msg = NULL;
-  Protocol__FlexsplitMessage *init_msg=NULL;
-  int msg_flag = 0;
-
-  
-  //printf( "PDCP agent: Calling the HELLO packet constructor\n");
-  msg_flag = proto_agent_hello(proto_agent[TEST_MOD].enb_id, NULL, &init_msg);
-  
-  int msgsize = 0;
-  if (msg_flag == 0)
-  {
-    proto_agent_serialize_message(init_msg, &msg, &msgsize);
-  }
-  
-  LOG_D(PROTO_AGENT, "Agent sending the message over the async channel\n");
-  proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, (void *) client_channel[TEST_MOD]);
-}
+//void
+//proto_agent_send_hello(void)
+//{
+//  uint8_t *msg = NULL;
+//  Protocol__FlexsplitMessage *init_msg=NULL;
+//  int msg_flag = 0;
+//
+//
+//  //printf( "PDCP agent: Calling the HELLO packet constructor\n");
+//  msg_flag = proto_agent_hello(proto_agent[TEST_MOD].mod_id, NULL, &init_msg);
+//
+//  int msgsize = 0;
+//  if (msg_flag == 0)
+//  {
+//    proto_agent_serialize_message(init_msg, &msg, &msgsize);
+//  }
+//
+//  LOG_D(PROTO_AGENT, "Agent sending the message over the async channel\n");
+//  proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, (void *) client_channel[TEST_MOD]);
+//}
 
 
 void
-proto_agent_send_rlc_data_req(uint8_t mod_id, uint8_t type_id, const protocol_ctxt_t* const ctxt_pP, const srb_flag_t srb_flagP, const MBMS_flag_t MBMS_flagP, const rb_id_t rb_idP, const mui_t muiP, 
-			      confirm_t confirmP, sdu_size_t sdu_sizeP, mem_block_t *sdu_pP)
+proto_agent_send_rlc_data_req(const protocol_ctxt_t* const ctxt_pP,
+        const srb_flag_t srb_flagP, const MBMS_flag_t MBMS_flagP,
+        const rb_id_t rb_idP, const mui_t muiP,
+        confirm_t confirmP, sdu_size_t sdu_sizeP, mem_block_t *sdu_pP)
 {
   
   //LOG_D(PROTO_AGENT, "PROTOPDCP: sending the data req over the async channel\n");
@@ -472,6 +231,7 @@ proto_agent_send_rlc_data_req(uint8_t mod_id, uint8_t type_id, const protocol_ct
   Protocol__FlexsplitMessage *init_msg=NULL;
 
   int msg_flag = 0;
+  mod_id_t mod_id = ctxt_pP->module_id;
   
   //printf( "PDCP agent: Calling the PDCP DATA REQ constructor\n");
  
@@ -488,7 +248,7 @@ proto_agent_send_rlc_data_req(uint8_t mod_id, uint8_t type_id, const protocol_ct
   args->sdu_p = malloc(sdu_sizeP);
   memcpy(args->sdu_p, sdu_pP->data, sdu_sizeP);
 
-  msg_flag = proto_agent_pdcp_data_req(type_id, (void *) args, &init_msg);
+  msg_flag = proto_agent_pdcp_data_req(mod_id, (void *) args, &init_msg);
   if (msg_flag != 0)
     goto error;
   
@@ -502,7 +262,8 @@ proto_agent_send_rlc_data_req(uint8_t mod_id, uint8_t type_id, const protocol_ct
     LOG_D(PROTO_AGENT, "Sending the pdcp data_req message over the async channel\n");
   
     if (msg!=NULL)
-      proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, (void *) client_channel[mod_id]);
+      proto_agent_async_msg_send((void *)msg, (int) msgsize, 1,
+                                 proto_agent[mod_id].channel->channel_info);
   
   }
   else
@@ -529,6 +290,7 @@ proto_agent_send_pdcp_data_ind(const protocol_ctxt_t* const ctxt_pP, const srb_f
 
   
   int msg_flag = 0;
+  mod_id_t mod_id = ctxt_pP->module_id;
   
   //printf( "PDCP agent: Calling the PDCP_DATA_IND constructor\n");
  
@@ -543,7 +305,7 @@ proto_agent_send_pdcp_data_ind(const protocol_ctxt_t* const ctxt_pP, const srb_f
   args->sdu_p = malloc(sdu_sizeP);
   memcpy(args->sdu_p, sdu_pP->data, sdu_sizeP);
 
-  msg_flag = proto_agent_pdcp_data_ind(proto_server[server_mod].enb_id, (void *) args, &init_msg);
+  msg_flag = proto_agent_pdcp_data_ind(mod_id, (void *) args, &init_msg);
   if (msg_flag != 0)
     goto error;
 
@@ -556,7 +318,7 @@ proto_agent_send_pdcp_data_ind(const protocol_ctxt_t* const ctxt_pP, const srb_f
     if (msg!=NULL)
     {
       LOG_D(PROTO_AGENT, "Sending the pdcp data_ind message over the async channel\n");
-      proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, (void *) server_channel);
+      proto_agent_async_msg_send((void *)msg, (int) msgsize, 1, proto_server[mod_id].channel->channel_info);
     }
   }
   else
@@ -577,7 +339,7 @@ error:
 void *
 proto_server_receive(void *args)
 {
-  proto_agent_instance_t *d = args;
+  proto_agent_instance_t *inst = args;
   void                  *data = NULL;
   int                   size;
   int                   priority;
@@ -591,14 +353,14 @@ proto_server_receive(void *args)
     msg = NULL;
     ser_msg = NULL;
     
-    if (proto_agent_async_msg_recv(&data, &size, &priority, server_channel)){
+    if (proto_agent_async_msg_recv(&data, &size, &priority, inst->channel->channel_info)){
       err_code = PROTOCOL__FLEXSPLIT_ERR__MSG_ENQUEUING;
       goto error;
     }
 
     LOG_D(PROTO_AGENT, "Server side Received message with size %d and priority %d, calling message handle\n", size, priority);
 
-    msg=proto_agent_handle_message(d->enb_id, data, size);
+    msg=proto_agent_handle_message(inst->mod_id, data, size);
 
     if (msg == NULL)
     {
@@ -611,9 +373,9 @@ proto_server_receive(void *args)
   
     LOG_D(PROTO_AGENT, "Server sending the reply message over the async channel\n");
     if (ser_msg != NULL){
-      if (proto_agent_async_msg_send((void *)ser_msg, (int) size, 1, (void *) server_channel)){
-	err_code = PROTOCOL__FLEXSPLIT_ERR__MSG_ENQUEUING;
-	goto error;
+      if (proto_agent_async_msg_send((void *)ser_msg, (int) size, 1, inst->channel->channel_info)){
+        err_code = PROTOCOL__FLEXSPLIT_ERR__MSG_ENQUEUING;
+        goto error;
       }
       LOG_D(PROTO_AGENT, "sent message with size %d\n", size);
     }
@@ -631,12 +393,9 @@ error:
 void *
 proto_client_receive(void *args)
 {
-  
-  proto_recv_t*         recv = args;
-  mod_id_t 	      recv_mod = recv->mod_id;
+  AssertFatal(0, "check proto_client_receive\n");
+  proto_agent_instance_t *inst = args;
 
-  LOG_D(PROTO_AGENT, "\n\nrecv mod is %u\n\n",recv_mod);  
-  //proto_agent_instance_t         *d = &proto_agent[TEST_MOD];
   void                  *data = NULL;
   int                   size;
   int                   priority;
@@ -651,19 +410,16 @@ proto_client_receive(void *args)
     msg = NULL;
     ser_msg = NULL;
 
-    while(client_channel[recv_mod] == NULL)
-    {
-	//just wait
-    }
-    LOG_D(PROTO_AGENT, "Will receive packets\n");
-    if (proto_agent_async_msg_recv(&data, &size, &priority, client_channel[recv_mod])){
+    if (proto_agent_async_msg_recv(&data, &size, &priority, inst->channel->channel_info)){
       err_code = PROTOCOL__FLEXSPLIT_ERR__MSG_ENQUEUING;
       goto error;
     }
 
-    LOG_D(PROTO_AGENT, "Client Received message with size %d and priority %d, calling message handle with mod_id %u\n", size, priority, recv_mod);
+    LOG_D(PROTO_AGENT,
+          "Client Received message with size %d and priority %d, calling message handle with mod_id %u\n",
+          size, priority, inst->mod_id);
 
-    msg=proto_agent_handle_message(recv_mod, data, size);
+    msg = proto_agent_handle_message(inst->mod_id, data, size);
 
     if (msg == NULL)
     {
@@ -676,9 +432,9 @@ proto_client_receive(void *args)
     LOG_D(PROTO_AGENT, "Server sending the reply message over the async channel\n");
 
     if (ser_msg != NULL){
-      if (proto_agent_async_msg_send((void *)ser_msg, (int) size, 1, (void *) client_channel[recv_mod])){
-	err_code = PROTOCOL__FLEXSPLIT_ERR__MSG_ENQUEUING;
-	goto error;
+      if (proto_agent_async_msg_send((void *)ser_msg, (int) size, 1, inst->channel->channel_info)){
+        err_code = PROTOCOL__FLEXSPLIT_ERR__MSG_ENQUEUING;
+        goto error;
       }
       LOG_D(PROTO_AGENT, "sent message with size %d\n", size);
     }
@@ -692,19 +448,3 @@ error:
   return NULL;
   
 }
-
-
-uint8_t select_du(uint8_t max_dus)
-{
-    static uint8_t selected = 0;
-    if (selected < max_dus -1 )
-    {
-      selected++;
-    }
-    else
-    {
-      selected = 0;
-    }
-    return selected;
-}
-
diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent.h b/openair2/LAYER2/PROTO_AGENT/proto_agent.h
index 520a438aa73743eef24cd0f72ed9ad7a8a1c7a84..7b69b82379bebd6cfe267da27270da6feb9719d1 100644
--- a/openair2/LAYER2/PROTO_AGENT/proto_agent.h
+++ b/openair2/LAYER2/PROTO_AGENT/proto_agent.h
@@ -45,24 +45,17 @@ void * proto_server_init(void *args);
 void * proto_server_receive(void *args);
 void * proto_client_receive(void *args);
 
-int proto_agent_start(uint8_t enb_id, mod_id_t mod_id, uint8_t type_id, cudu_params_t *cudu);
-int proto_server_start(mod_id_t mod_id, const cudu_params_t* cudu);
+int proto_agent_start(mod_id_t mod_id, const du_params_t *du);
+int proto_server_start(mod_id_t mod_id, const cu_params_t* cu);
 
 int proto_agent_stop(mod_id_t mod_id);
 
 void *proto_agent_task(void *args);
 
-uint8_t select_du(uint8_t max_dus);
-typedef struct 
-{
-  mod_id_t mod_id;
-  uint8_t type_id;
-}proto_recv_t;
-
-void proto_agent_send_rlc_data_req(uint8_t mod_id, uint8_t type_id,
-    const protocol_ctxt_t* const ctxt_pP, const srb_flag_t srb_flagP,
-    const MBMS_flag_t MBMS_flagP, const rb_id_t rb_idP, const mui_t muiP,
-    confirm_t confirmP, sdu_size_t sdu_sizeP, mem_block_t *sdu_pP);
+void proto_agent_send_rlc_data_req( const protocol_ctxt_t* const ctxt_pP,
+    const srb_flag_t srb_flagP, const MBMS_flag_t MBMS_flagP,
+    const rb_id_t rb_idP, const mui_t muiP, confirm_t confirmP,
+    sdu_size_t sdu_sizeP, mem_block_t *sdu_pP);
 
 void proto_agent_send_pdcp_data_ind(const protocol_ctxt_t* const ctxt_pP,
     const srb_flag_t srb_flagP, const MBMS_flag_t MBMS_flagP,
diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c
index 07c528da5bfc72a7228388234b4d0f80759243c2..9bf861b0564b33444f542759d4b0437dd97e406b 100644
--- a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c
+++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c
@@ -34,61 +34,35 @@
 
 #include "common/utils/LOG/log.h"
 
-uint16_t proto_udp = 0;
-uint16_t proto_tcp = 0;
-uint16_t proto_sctp = 0;
-
-proto_agent_async_channel_t * proto_server_async_channel_info(mod_id_t mod_id, char *dst_ip, uint16_t dst_port, const char* type, const char *peer_addr) {
-
+proto_agent_async_channel_t *
+proto_server_async_channel_info(mod_id_t mod_id, const char *ip, uint16_t port)
+{
+  LOG_E(PROTO_AGENT, "does not bind to specific address at the moment, ignoring %s\n", ip);
   proto_agent_async_channel_t *channel;
-  channel = (proto_agent_async_channel_t *) malloc(sizeof(proto_agent_channel_t));
-
-  channel->port = dst_port;
-  channel->peer_addr = NULL;
+  channel = malloc(sizeof(proto_agent_channel_t));
   
   if (channel == NULL)
     goto error;
 
+  channel->port = port;
+  channel->peer_addr = NULL;
+
   channel->enb_id = mod_id;
-  /*Create a socket*/
-  if (strcmp(type, "TCP") == 0)
-  {
-    proto_tcp = 1;
-    printf("PROTO_AGENT: sTARTING TCP SERVER\n");
-    channel->link = new_link_server(dst_port);
-    channel->type = 0;
-  }
-  else if (strcmp(type, "UDP") == 0)
-  {
-    proto_udp = 1;
-    //channel->link = new_udp_link_server(dst_port);
-    channel->link = new_link_udp_server(dst_port);
-    channel->type = 1;
-    channel->peer_addr = peer_addr;
-  }
-  else if (strcmp(type, "SCTP") == 0)
-  {
-    proto_sctp = 1;
-    //channel->link = new_sctp_link_server(dst_port);
-    channel->link = new_link_sctp_server(dst_port);
-    channel->type = 2;
-  }
+  channel->link = new_link_udp_server(port);
   
   if (channel->link == NULL) goto error;
   
-   /* 
-   * create a message queue
-   */ 
-  
   channel->send_queue = new_message_queue();
   if (channel->send_queue == NULL) goto error;
   channel->receive_queue = new_message_queue();
   if (channel->receive_queue == NULL) goto error;
 
-   /* 
-   * create a link manager 
-   */  
-  channel->manager = create_link_manager(channel->send_queue, channel->receive_queue, channel->link, channel->type, channel->peer_addr, channel->port);
+  channel->manager = create_link_manager(channel->send_queue,
+                                         channel->receive_queue,
+                                         channel->link,
+                                         CHANNEL_UDP,
+                                         channel->peer_addr,
+                                         channel->port);
   if (channel->manager == NULL) goto error;
   
   return channel;
@@ -99,55 +73,34 @@ proto_agent_async_channel_t * proto_server_async_channel_info(mod_id_t mod_id, c
 }
 
 
-proto_agent_async_channel_t * proto_agent_async_channel_info(mod_id_t mod_id, char *dst_ip, uint16_t dst_port, const char* type, const char *peer_addr) {
-
+proto_agent_async_channel_t *
+proto_agent_async_channel_info(mod_id_t mod_id, const char *dst_ip, uint16_t dst_port)
+{
   proto_agent_async_channel_t *channel;
   channel = (proto_agent_async_channel_t *) malloc(sizeof(proto_agent_channel_t));
-  
-  channel->port = dst_port;
-  channel->peer_addr = NULL;
-  
+
   if (channel == NULL)
     goto error;
 
+  channel->port = dst_port;
+  channel->peer_addr = dst_ip;
+
   channel->enb_id = mod_id;
-  /*Create a socket*/
-  if (strcmp(type, "TCP") == 0)
-  {
-    proto_tcp = 1;
-    channel->link = new_link_client(dst_ip, dst_port);
-    channel->type = 0;
-  }
-  else if (strcmp(type, "UDP") == 0)
-  {
-    proto_udp = 1;
-    channel->link = new_link_udp_client(dst_ip, dst_port);
-    channel->type = 1;
-    channel->peer_addr = peer_addr;
-  }
-  else if (strcmp(type, "SCTP") == 0)
-  {
-    proto_sctp = 1;
-    channel->link = new_link_sctp_client(dst_ip, dst_port);;
-    channel->type = 2;
-  }
-  
+  channel->link = new_link_udp_client(channel->peer_addr, channel->port);
  
   if (channel->link == NULL) goto error;
   
-   /* 
-   * create a message queue
-   */ 
-  
   channel->send_queue = new_message_queue();
   if (channel->send_queue == NULL) goto error;
   channel->receive_queue = new_message_queue();
   if (channel->receive_queue == NULL) goto error;
   
-   /* 
-   * create a link manager 
-   */  
-  channel->manager = create_link_manager(channel->send_queue, channel->receive_queue, channel->link, channel->type, channel->peer_addr, channel->port);
+  channel->manager = create_link_manager(channel->send_queue,
+                                         channel->receive_queue,
+                                         channel->link,
+                                         CHANNEL_UDP,
+                                         channel->peer_addr,
+                                         channel->port);
   if (channel->manager == NULL) goto error;
   
   return channel;
@@ -157,28 +110,20 @@ proto_agent_async_channel_t * proto_agent_async_channel_info(mod_id_t mod_id, ch
   return NULL;
 }
 
-int proto_agent_async_msg_send(void *data, int size, int priority, void *channel_info) {
+int proto_agent_async_msg_send(void *data, int size, int priority, void *channel_info)
+{
   proto_agent_async_channel_t *channel = channel_info;
-
   return message_put(channel->send_queue, data, size, priority);
 }
 
-int proto_agent_async_msg_recv(void **data, int *size, int *priority, void *channel_info) {
-  proto_agent_async_channel_t *channel;
-  channel = (proto_agent_async_channel_t *)channel_info;
-
-  if (channel == NULL)
-    return 0;   
-  else if (channel->type < 0)
-    return 0;
-  else if (channel->receive_queue == NULL)
-    return 0;  
-  else
-    return message_get(channel->receive_queue, data, size, priority);
-
+int proto_agent_async_msg_recv(void **data, int *size, int *priority, void *channel_info)
+{
+  proto_agent_async_channel_t *channel = channel_info;
+  return message_get(channel->receive_queue, data, size, priority);
 }
 
-void proto_agent_async_release(proto_agent_channel_t *channel) {
+void proto_agent_async_release(proto_agent_channel_t *channel)
+{
   proto_agent_async_channel_t *channel_info;
   channel_info = (proto_agent_async_channel_t *) channel->channel_info;
 
diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h
index c7a72d298306fa612bf0c21df3c42f41454c147d..681fb83b1b853a531f8568901ab6468812a2984c 100644
--- a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h
+++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h
@@ -39,10 +39,9 @@
 
 #include "proto_agent_net_comm.h"
 
-typedef struct {
-  mod_id_t            enb_id;
-  uint16_t         type; // 0-> TCP, 1-> UDP, 2->SCTP
-  char 		  *peer_addr;
+typedef struct proto_agent_async_channel_s {
+  mod_id_t         enb_id;
+  const char      *peer_addr;
   int		   port;
   socket_link_t   *link;
   message_queue_t *send_queue;
@@ -50,8 +49,8 @@ typedef struct {
   link_manager_t  *manager;
 } proto_agent_async_channel_t;
 
-proto_agent_async_channel_t * proto_agent_async_channel_info(mod_id_t mod_id, char *dst_ip, uint16_t dst_port, const char* type, const char *peer_addr);
-proto_agent_async_channel_t * proto_server_async_channel_info(mod_id_t mod_id, char *dst_ip, uint16_t dst_port, const char* type, const char *peer_addr);
+proto_agent_async_channel_t * proto_agent_async_channel_info(mod_id_t mod_id, const char *dst_ip, uint16_t dst_port);
+proto_agent_async_channel_t * proto_server_async_channel_info(mod_id_t mod_id, const char *ip, uint16_t _port);
 
 int proto_agent_async_msg_send(void *data, int size, int priority, void *channel_info);
 
diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c
index d89c0b09ae0d21e591095f9cc737861a4b2b3b66..147af52a127e0fa24fa2e68e2693d764a42b6ae2 100644
--- a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c
+++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c
@@ -45,11 +45,6 @@
 #include "RRC/LTE/rrc_extern.h"
 #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
 #include "rrc_eNB_UE_context.h"
-//#include "LAYER2/PDCP_v10.1.0/pdcp_primitives.h"
-
-void * enb[NUM_MAX_ENB];
-void * enb_ue[NUM_MAX_ENB];
-void * enb_rrc[NUM_MAX_ENB];
 
 /*
  * message primitives
diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h
index 2202390749031a24d065bb0c82b68f0acd5ebe66..0e0302002c774c15f9c619aa45851dbe75abff64 100644
--- a/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h
+++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h
@@ -98,9 +98,9 @@ typedef enum {
 typedef uint8_t xid_t;  
 typedef uint8_t mod_id_t;  // module or enb id 
 typedef uint8_t lcid_t;
-typedef int32_t  err_code_t; 
-
+typedef int32_t err_code_t;
 
+#define CHANNEL_UDP 1
 
 typedef struct {
   /* general info */ 
@@ -113,12 +113,16 @@ typedef struct {
   uint32_t rx_msg[NUM_MAX_ENB];
   uint32_t tx_msg[NUM_MAX_ENB];
 
-}proto_agent_info_t;
+} proto_agent_info_t;
 
-typedef struct {
-  mod_id_t enb_id;
+/* forward declaration */
+struct proto_agent_channel_s;
+
+typedef struct proto_agent_instance_s {
+  mod_id_t    mod_id;
   proto_agent_info_t agent_info;
-  
-}proto_agent_instance_t;
+  struct proto_agent_channel_s *channel;
+  pthread_t   recv_thread;
+} proto_agent_instance_t;
 
 #endif 
diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h
index b489c64416130b04c08bbf2b079aec7d6143da95..6647de6e1bc89346fe13cc5c52dd556d27377646 100644
--- a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h
+++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h
@@ -41,16 +41,18 @@
 #include "tree.h"
 #define ENB_AGENT_MAX 9
 
+/* forward declaration */
+struct proto_agent_async_channel_s;
+
 /*Channel related information used for Tx/Rx of protocol messages*/
 typedef struct proto_agent_channel_s {
   RB_ENTRY(proto_agent_channel_s) entry;
-int channel_id;
-void *channel_info;
-uint16_t type; // 0-> TCP, 1-> UDP, 2->SCTP
-/*Callbacks for channel message Tx and Rx*/
-int (*msg_send)(void *data, int size, int priority, void *channel_info);
-int (*msg_recv)(void **data, int *size, int *priority, void *channel_info);
-void (*release)(struct proto_agent_channel_s *channel);
+  int channel_id;
+  struct proto_agent_async_channel_s *channel_info;
+  /*Callbacks for channel message Tx and Rx*/
+  int (*msg_send)(void *data, int size, int priority, void *channel_info);
+  int (*msg_recv)(void **data, int *size, int *priority, void *channel_info);
+  void (*release)(struct proto_agent_channel_s *channel);
 } proto_agent_channel_t;
 
 typedef struct proto_agent_channel_instance_s{
diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c
index d40fc99e1375bf091c8dc5a76d8e25f5c2669a5f..793e1406417b2d0cb7672fb477c65d3751c1a963 100644
--- a/openair2/LAYER2/RLC/rlc.c
+++ b/openair2/LAYER2/RLC/rlc.c
@@ -63,17 +63,18 @@ async_server_thread_init (void)
   //create log_list
   //log_list_init(&log_list);
 
+  AssertFatal(0, "this should not be reached!\n");
   async_server_shutdown = 0;
 
   if ((pthread_mutex_init (&async_server_lock, NULL) != 0)
       || (pthread_cond_init (&async_server_notify, NULL) != 0)) {
     return;
   }
-  if (pthread_create (&async_server_thread, NULL, proto_server_init, (void*) NULL)
-      != 0) {
-    async_server_thread_finalize();
-    return;
-  }
+  //if (pthread_create (&async_server_thread, NULL, proto_server_init, (void*) NULL)
+  //    != 0) {
+  //  async_server_thread_finalize();
+  //  return;
+  //}
 
 
 }
diff --git a/openair2/UTIL/ASYNC_IF/link_manager.c b/openair2/UTIL/ASYNC_IF/link_manager.c
index 9e636ea1e27a6f5c20d1465f71d1816f9d69f0ea..7486fbd1710caa630a1d625111d96853a9ec19d8 100644
--- a/openair2/UTIL/ASYNC_IF/link_manager.c
+++ b/openair2/UTIL/ASYNC_IF/link_manager.c
@@ -97,7 +97,7 @@ link_manager_t *create_link_manager(
         message_queue_t *receive_queue,
         socket_link_t   *link,
 	uint16_t        type,
-        char            *peer_addr,
+        const char      *peer_addr,
         int             port      )
 {
   link_manager_t *ret = NULL;
diff --git a/openair2/UTIL/ASYNC_IF/link_manager.h b/openair2/UTIL/ASYNC_IF/link_manager.h
index 391458e088155e9e47e6070799510eac9fa2c5d3..f7efc928676fafadd92335b61fb2ffb845505448 100644
--- a/openair2/UTIL/ASYNC_IF/link_manager.h
+++ b/openair2/UTIL/ASYNC_IF/link_manager.h
@@ -58,7 +58,7 @@ link_manager_t *create_link_manager(
         message_queue_t *receive_queue,
         socket_link_t   *link,
 	uint16_t        type,
-        char            *peer_addr,
+        const char      *peer_addr,
         int             port);
 
 void destroy_link_manager(link_manager_t *);
diff --git a/openair2/UTIL/ASYNC_IF/socket_link.c b/openair2/UTIL/ASYNC_IF/socket_link.c
index 8f06ed15ff5b5ba2d1b9d2fa48c6f3a75ac086ef..e7100a2797cfa4eb8ff5984775bd5fb8ddc86252 100644
--- a/openair2/UTIL/ASYNC_IF/socket_link.c
+++ b/openair2/UTIL/ASYNC_IF/socket_link.c
@@ -115,7 +115,7 @@ error:
   return NULL;
 }
 
-socket_link_t *new_link_client(char *server, int port)
+socket_link_t *new_link_client(const char *server, int port)
 {
   socket_link_t      *ret = NULL;
   struct sockaddr_in addr;
@@ -208,7 +208,7 @@ error:
 }
 
 
-socket_link_t *new_link_udp_client(char *server, int port){
+socket_link_t *new_link_udp_client(const char *server, int port){
 
   socket_link_t      *ret = NULL;
   ret = calloc(1, sizeof(socket_link_t));
@@ -307,7 +307,7 @@ error:
   return NULL;
 }
 
-socket_link_t *new_link_sctp_client(char *server, int port)
+socket_link_t *new_link_sctp_client(const char *server, int port)
 {
 
   socket_link_t      *ret = NULL;
diff --git a/openair2/UTIL/ASYNC_IF/socket_link.h b/openair2/UTIL/ASYNC_IF/socket_link.h
index c2cf3d3c105ce25e1955a8e43a4e2b10e4718aa7..1ce5c27424a67b8f01feb5412a43ce57bab5a483 100644
--- a/openair2/UTIL/ASYNC_IF/socket_link.h
+++ b/openair2/UTIL/ASYNC_IF/socket_link.h
@@ -47,11 +47,11 @@ typedef struct {
 } socket_link_t;
 
 socket_link_t *new_link_server(int port);
-socket_link_t *new_link_client(char *server, int port);
+socket_link_t *new_link_client(const char *server, int port);
 socket_link_t *new_link_udp_server(int port);
-socket_link_t *new_link_udp_client(char *server, int port);
+socket_link_t *new_link_udp_client(const char *server, int port);
 socket_link_t *new_link_sctp_server(int port);
-socket_link_t *new_link_sctp_client(char *server, int port);
+socket_link_t *new_link_sctp_client(const char *server, int port);
 int link_send_packet(socket_link_t *link, void *data, int size, uint16_t proto_type, char *peer_addr, int port);
 int link_receive_packet(socket_link_t *link, void **data, int *size, uint16_t proto_type, char *peer_addr, int port);
 int close_link(socket_link_t *link);
diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h
index 71ca1616fd55e3c957f3ee89f4721e95b5a75a31..e2773aeedf19544921e1069d4ee451271f259496 100644
--- a/openair3/UTILS/conversions.h
+++ b/openair3/UTILS/conversions.h
@@ -196,6 +196,17 @@ do {                                                                           \
     (oCTETsTRING)->size = 3;                                                   \
 } while(0)
 
+#define PLMNID_TO_MCC_MNC(oCTETsTRING, mCC, mNC, mNCdIGITlENGTH)                  \
+do {                                                                              \
+    mCC = ((oCTETsTRING)->buf[0] & 0x0F) * 100 +                                  \
+          ((oCTETsTRING)->buf[0] >> 4 & 0x0F) * 10 +                              \
+          ((oCTETsTRING)->buf[1] & 0x0F);                                         \
+    mNCdIGITlENGTH = ((oCTETsTRING)->buf[1] >> 4 & 0x0F) == 0xF ? 2 : 3;          \
+    mNC = (mNCdIGITlENGTH == 2 ? 0 : ((oCTETsTRING)->buf[1] >> 4 & 0x0F) * 100) + \
+          ((oCTETsTRING)->buf[2] & 0x0F) * 10 +                                   \
+          ((oCTETsTRING)->buf[2] >> 4 & 0x0F);                                    \
+} while (0)
+
 #define MCC_MNC_TO_TBCD(mCC, mNC, mNCdIGITlENGTH, tBCDsTRING)        \
 do {                                                                 \
     char _buf[3];                                                    \
@@ -260,7 +271,7 @@ do {                                                                    \
 
 
 /* TS 38.473 v15.2.1 section 9.3.1.32:
- * C RNTI
+ * C RNTI is BIT_STRING(16)
  */
 #define C_RNTI_TO_BIT_STRING(mACRO, bITsTRING)          \
 do {                                                    \
@@ -272,21 +283,31 @@ do {                                                    \
 } while(0)
 
 
-/* TS 38.473 v15.1.1 section 9.3.2.1:
- * TRANSPORT LAYER ADDRESS
+/* TS 38.473 v15.1.1 section 9.3.2.3:
+ * TRANSPORT LAYER ADDRESS for IPv4 is 32bit (TS 38.414)
  */
-#define TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(mACRO, bITsTRING)    \
+#define TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(mACRO, bITsTRING)    \
 do {                                                    \
-    (bITsTRING)->buf = calloc(5, sizeof(uint8_t));      \
-    (bITsTRING)->buf[0] = (mACRO) >> 28;                \
-    (bITsTRING)->buf[1] = (mACRO) >> 20;                \
-    (bITsTRING)->buf[2] = (mACRO) >> 12;                \
-    (bITsTRING)->buf[3] = (mACRO) >> 4;                 \
-    (bITsTRING)->buf[4] = ((mACRO) & 0x0f) << 4;        \
-    (bITsTRING)->size = 5;                              \
-    (bITsTRING)->bits_unused = 4;                       \
+    (bITsTRING)->buf = calloc(4, sizeof(uint8_t));      \
+    (bITsTRING)->buf[0] = (mACRO) >> 24 & 0xFF;         \
+    (bITsTRING)->buf[1] = (mACRO) >> 16 & 0xFF;         \
+    (bITsTRING)->buf[2] = (mACRO) >> 8 & 0xFF;          \
+    (bITsTRING)->buf[3] = (mACRO) >> 4 & 0xFF;          \
+    (bITsTRING)->size = 4;                              \
+    (bITsTRING)->bits_unused = 0;                       \
 } while(0)
 
+#define BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(bITsTRING, mACRO)    \
+do {                                                                    \
+    DevCheck((bITsTRING)->size == 4, (bITsTRING)->size, 4, 0);          \
+    DevCheck((bITsTRING)->bits_unused == 0, (bITsTRING)->bits_unused, 0, 0); \
+    mACRO = ((bITsTRING)->buf[0] << 24) +                               \
+            ((bITsTRING)->buf[1] << 16) +                               \
+            ((bITsTRING)->buf[2] << 8) +                                \
+            ((bITsTRING)->buf[3]);                                      \
+} while (0)
+
+
 /* TS 38.473 v15.1.1 section 9.3.1.12:
  * NR CELL ID
  */