diff --git a/common/utils/ocp_itti/all_msg.h b/common/utils/ocp_itti/all_msg.h
new file mode 100644
index 0000000000000000000000000000000000000000..e296502909592e8bcd8e6484391ad11af5421b49
--- /dev/null
+++ b/common/utils/ocp_itti/all_msg.h
@@ -0,0 +1,14 @@
+#include "openair2/COMMON/phy_messages_def.h"
+#include "openair2/COMMON/mac_messages_def.h"
+#include "openair2/COMMON/rlc_messages_def.h"
+#include "openair2/COMMON/pdcp_messages_def.h"
+#include "openair2/COMMON/rrc_messages_def.h"
+#include "openair2/COMMON/nas_messages_def.h"
+#if ENABLE_RAL
+  #include "openair2/COMMON/ral_messages_def.h"
+#endif
+#include "openair2/COMMON/s1ap_messages_def.h"
+#include "openair2/COMMON/x2ap_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.cpp b/common/utils/ocp_itti/intertask_interface.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..89353310b139a07763600a15a8f35e01f31c9bb5
--- /dev/null
+++ b/common/utils/ocp_itti/intertask_interface.cpp
@@ -0,0 +1,394 @@
+/*
+  Author: Laurent THOMAS, Open Cells
+  copyleft: OpenAirInterface Software Alliance
+*/
+#include <vector>
+#include <map>
+#include <sys/eventfd.h>
+
+
+#include <intertask_interface.h>
+
+typedef struct timer_elm_s {
+  timer_type_t      type;     ///< Timer type
+  long              instance;
+  long duration;
+  uint64_t timeout;
+  void              *timer_arg; ///< Optional argument that will be passed when timer expires
+} timer_elm_t ;
+
+typedef struct task_list_s {
+  task_info_t admin;
+  pthread_t thread;
+  pthread_mutex_t queue_cond_lock;
+  std::vector<MessageDef *> message_queue;
+  std::map<long,timer_elm_t> timer_map;
+  uint64_t next_timer=UINT64_MAX;
+  struct epoll_event  *events =NULL;
+  int nb_fd_epoll=0;
+  int nb_events=0;
+  int epoll_fd=-1;
+  int sem_fd=-1;
+} task_list_t;
+
+int timer_expired(int fd);
+task_list_t tasks[TASK_MAX];
+
+extern "C" {
+  void *pool_buffer_init (void) {
+    return 0;
+  }
+
+  void *pool_buffer_clean (void *arg) {
+    //-----------------------------------------------------------------------------
+    return 0;
+  }
+
+  void free_mem_block (mem_block_t *leP, const char *caller) {
+    AssertFatal(leP!=NULL,"");
+    free(leP);
+  }
+
+  mem_block_t *get_free_mem_block (uint32_t sizeP, const char *caller) {
+    mem_block_t *ptr=(mem_block_t *)malloc(sizeP+sizeof(mem_block_t));
+    ptr->data=((unsigned char *)ptr)+sizeof(mem_block_t);
+    ptr->size=sizeP;
+    return ptr;
+  }
+
+  void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size) {
+    void *ptr = NULL;
+    AssertFatal ((ptr=malloc (size)) != NULL, "Memory allocation of %zu bytes failed (%d -> %d)!\n",
+                 size, origin_task_id, destination_task_id);
+    return ptr;
+  }
+
+  int itti_free(task_id_t task_id, void *ptr) {
+    AssertFatal (ptr != NULL, "Trying to free a NULL pointer (%d)!\n", task_id);
+    free (ptr);
+    return (EXIT_SUCCESS);
+  }
+
+  MessageDef *itti_alloc_new_message_sized(task_id_t origin_task_id, MessagesIds message_id, MessageHeaderSize size) {
+    MessageDef *temp = (MessageDef *)itti_malloc (origin_task_id, TASK_UNKNOWN, sizeof(MessageHeader) + size);
+    temp->ittiMsgHeader.messageId = message_id;
+    temp->ittiMsgHeader.originTaskId = origin_task_id;
+    temp->ittiMsgHeader.ittiMsgSize = size;
+    return temp;
+  }
+
+  MessageDef *itti_alloc_new_message(task_id_t origin_task_id, MessagesIds message_id) {
+    int size=sizeof(MessageHeader) + messages_info[message_id].size;
+    MessageDef *temp = (MessageDef *)itti_malloc (origin_task_id, TASK_UNKNOWN, size);
+    temp->ittiMsgHeader.messageId = message_id;
+    temp->ittiMsgHeader.originTaskId = origin_task_id;
+    temp->ittiMsgHeader.ittiMsgSize = size;
+    return temp;
+    //return itti_alloc_new_message_sized(origin_task_id, message_id, messages_info[message_id].size);
+  }
+
+  static inline int itti_send_msg_to_task_locked(task_id_t destination_task_id, instance_t instance, MessageDef *message) {
+    task_list_t *t=tasks+destination_task_id;
+    message->ittiMsgHeader.destinationTaskId = destination_task_id;
+    message->ittiMsgHeader.instance = instance;
+    message->ittiMsgHeader.lte_time.frame = 0;
+    message->ittiMsgHeader.lte_time.slot = 0;
+    int message_id = message->ittiMsgHeader.messageId;
+    size_t s=t->message_queue.size();
+
+    if ( s > t->admin.queue_size )
+      LOG_E(TMR,"Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s );
+
+    if ( s > 50 )
+      LOG_I(TMR,"Queue for %s task size: %ld\n",itti_get_task_name(destination_task_id), s+1);
+
+    t->message_queue.insert(t->message_queue.begin(), message);
+    eventfd_t sem_counter = 1;
+    AssertFatal ( sizeof(sem_counter) == write(t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
+    LOG_D(TMR,"sent messages id=%d to %s\n",message_id, t->admin.name);
+    return 0;
+  }
+
+  int itti_send_msg_to_task(task_id_t destination_task_id, instance_t instance, MessageDef *message) {
+    task_list_t *t=&tasks[destination_task_id];
+    pthread_mutex_lock (&t->queue_cond_lock);
+    int ret=itti_send_msg_to_task_locked(destination_task_id, instance, message);
+    pthread_mutex_unlock (&t->queue_cond_lock);
+
+    while ( t->message_queue.size()>0 && t->admin.func != NULL )
+      t->admin.func(NULL);
+
+    return ret;
+  }
+
+  void itti_subscribe_event_fd(task_id_t task_id, int fd) {
+    struct epoll_event event;
+    task_list_t *t=&tasks[task_id];
+    t->nb_fd_epoll++;
+    t->events = (struct epoll_event *)realloc((void *)t->events,
+                t->nb_fd_epoll * sizeof(struct epoll_event));
+    event.events  = EPOLLIN | EPOLLERR;
+    event.data.u64 = 0;
+    event.data.fd  = fd;
+    AssertFatal(epoll_ctl(t->epoll_fd, EPOLL_CTL_ADD, fd, &event) == 0,
+                "epoll_ctl (EPOLL_CTL_ADD) failed for task %s, fd %d: %s!\n",
+                itti_get_task_name(task_id), fd, strerror(errno));
+  }
+
+  void itti_unsubscribe_event_fd(task_id_t task_id, int fd) {
+    task_list_t *t=&tasks[task_id];
+    AssertFatal (epoll_ctl(t->epoll_fd, EPOLL_CTL_DEL, fd, NULL) == 0,
+                 "epoll_ctl (EPOLL_CTL_DEL) failed for task %s, fd %d: %s!\n",
+                 itti_get_task_name(task_id), fd, strerror(errno));
+    t->nb_fd_epoll--;
+  }
+
+  static inline int itti_get_events_locked(task_id_t task_id, struct epoll_event **events) {
+    task_list_t *t=&tasks[task_id];
+    uint64_t current_time=0;
+
+    do {
+      if ( t->next_timer != UINT64_MAX ) {
+        struct timespec tp;
+        clock_gettime(CLOCK_MONOTONIC, &tp);
+        current_time=(uint64_t)tp.tv_sec*1000+tp.tv_nsec/(1000*1000);
+
+        if ( t->next_timer < current_time) {
+          t->next_timer=UINT64_MAX;
+
+          // Proceed expired timer
+          for ( auto it=t->timer_map.begin() ; it != t->timer_map.end() ; ++it ) {
+            if ( it->second.timeout < current_time ) {
+              MessageDef *message = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
+              message->ittiMsg.timer_has_expired.timer_id=it->first;
+              message->ittiMsg.timer_has_expired.arg=it->second.timer_arg;
+
+              if (itti_send_msg_to_task_locked(task_id, it->second.instance, message) < 0) {
+                LOG_W(TMR,"Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id);
+                free(message);
+                t->timer_map.erase(it);
+                return -1;
+              }
+
+              if ( it->second.type==TIMER_PERIODIC ) {
+                it->second.timeout+=it->second.duration;
+
+                if (it->second.timeout < t->next_timer)
+                  t->next_timer=it->second.timeout;
+              } else
+                t->timer_map.erase(it);
+            } else if (it->second.timeout < t->next_timer)
+              t->next_timer=it->second.timeout;
+          }
+        }
+      }
+
+      int epoll_timeout = -1;
+
+      if ( t->next_timer != UINT64_MAX )
+        epoll_timeout = t->next_timer-current_time;
+
+      pthread_mutex_unlock(&t->queue_cond_lock);
+      LOG_D(TMR,"enter blocking wait for %s\n", itti_get_task_name(task_id));
+      t->nb_events = epoll_wait(t->epoll_fd,t->events,t->nb_fd_epoll, epoll_timeout);
+    } while (t->nb_events  < 0 && (errno == EINTR || errno == EAGAIN ) );
+
+    AssertFatal (t->nb_events >=0,
+                 "epoll_wait failed for task %s, nb fds %d, timeout %lu: %s!\n",
+                 itti_get_task_name(task_id), t->nb_fd_epoll, t->next_timer != UINT64_MAX ? t->next_timer-current_time : -1, strerror(errno));
+    LOG_D(TMR,"receive on %d descriptors for %s\n", t->nb_events, itti_get_task_name(task_id));
+
+    if (t->nb_events == 0)
+      /* No data to read -> return */
+      return 0;
+
+    for (int i = 0; i < t->nb_events; i++) {
+      /* Check if there is an event for ITTI for the event fd */
+      if ((t->events[i].events & EPOLLIN) &&
+          (t->events[i].data.fd == t->sem_fd)) {
+        eventfd_t   sem_counter;
+        /* Read will always return 1 */
+        AssertFatal( sizeof(sem_counter) == read (t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
+        /* Mark that the event has been processed */
+        t->events[i].events &= ~EPOLLIN;
+      }
+    }
+
+    *events = t->events;
+    return t->nb_events;
+  }
+
+  int itti_get_events(task_id_t task_id, struct epoll_event **events) {
+    pthread_mutex_lock(&tasks[task_id].queue_cond_lock);
+    return itti_get_events_locked(task_id, events);
+  }
+
+  void itti_receive_msg(task_id_t task_id, MessageDef **received_msg) {
+    // Reception of one message, blocking caller
+    task_list_t *t=&tasks[task_id];
+    pthread_mutex_lock(&t->queue_cond_lock);
+
+    // Weird condition to deal with crap legacy itti interface
+    if ( t->nb_fd_epoll == 1 ) {
+      while (t->message_queue.empty()) {
+        itti_get_events_locked(task_id, &t->events);
+        pthread_mutex_lock(&t->queue_cond_lock);
+      }
+    } else {
+      if (t->message_queue.empty()) {
+        itti_get_events_locked(task_id, &t->events);
+        pthread_mutex_lock(&t->queue_cond_lock);
+      }
+    }
+
+    // Legacy design: we return even if we have no message
+    // in this case, *received_msg is NULL
+    if (t->message_queue.empty()) {
+      *received_msg=NULL;
+      LOG_D(TMR,"task %s received even from other fd (total fds: %d), returning msg NULL\n",t->admin.name, t->nb_fd_epoll);
+    } else {
+      *received_msg=t->message_queue.back();
+      t->message_queue.pop_back();
+      LOG_D(TMR,"task %s received a message\n",t->admin.name);
+    }
+
+    pthread_mutex_unlock (&t->queue_cond_lock);
+  }
+
+  void itti_poll_msg(task_id_t task_id, MessageDef **received_msg) {
+    //reception of one message, non-blocking
+    task_list_t *t=&tasks[task_id];
+    pthread_mutex_lock(&t->queue_cond_lock);
+
+    if (!t->message_queue.empty()) {
+      LOG_D(TMR,"task %s received a message in polling mode\n",t->admin.name);
+      *received_msg=t->message_queue.back();
+      t->message_queue.pop_back();
+    } else
+      *received_msg=NULL;
+
+    pthread_mutex_unlock (&t->queue_cond_lock);
+  }
+
+  int itti_create_task(task_id_t task_id, void *(*start_routine)(void *), void *args_p) {
+    task_list_t *t=&tasks[task_id];
+    AssertFatal ( pthread_create (&t->thread, NULL, start_routine, args_p) ==0,
+                  "Thread creation for task %d failed!\n", task_id);
+    pthread_setname_np( t->thread, itti_get_task_name(task_id) );
+    LOG_I(TMR,"Created Posix thread %s\n",  itti_get_task_name(task_id) );
+    return 0;
+  }
+
+  void itti_exit_task(void) {
+    pthread_exit (NULL);
+  }
+
+  void itti_terminate_tasks(task_id_t task_id) {
+    // Sends Terminate signals to all tasks.
+    itti_send_terminate_message (task_id);
+    pthread_exit (NULL);
+  }
+
+  int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
+                const message_info_t *messages_info) {
+    AssertFatal(TASK_MAX<UINT16_MAX, "Max itti tasks");
+
+    for(int i=0; i<task_max; ++i) {
+      LOG_I(TMR,"Starting itti queue: %s as task %d\n", tasks_info[i].name, i);
+      pthread_mutex_init(&tasks[i].queue_cond_lock, NULL);
+      memcpy(&tasks[i].admin, &tasks_info[i], sizeof(task_info_t));
+      AssertFatal( ( tasks[i].epoll_fd = epoll_create1(0) ) >=0, "");
+      AssertFatal( ( tasks[i].sem_fd = eventfd(0, EFD_SEMAPHORE) ) >=0, "");
+      itti_subscribe_event_fd((task_id_t)i, tasks[i].sem_fd);
+
+      if (tasks[i].admin.threadFunc != NULL)
+        itti_create_task((task_id_t)i, tasks[i].admin.threadFunc, NULL);
+    }
+
+    return 0;
+  }
+
+  int timer_setup(
+    uint32_t      interval_sec,
+    uint32_t      interval_us,
+    task_id_t     task_id,
+    int32_t       instance,
+    timer_type_t  type,
+    void         *timer_arg,
+    long         *timer_id) {
+    task_list_t *t=&tasks[task_id];
+
+    do {
+      // set the taskid in the timer id to keep compatible with the legacy API
+      // timer_remove() takes only the timer id as parameter
+      *timer_id=(random()%UINT16_MAX) << 16 | task_id ;
+    } while ( t->timer_map.find(*timer_id) != t->timer_map.end());
+
+    /* Allocate new timer list element */
+    timer_elm_t timer;
+    struct timespec tp;
+    clock_gettime(CLOCK_MONOTONIC, &tp);
+
+    if (interval_us%1000 != 0)
+      LOG_W(TMR, "Can't set timer precision below 1ms, rounding it\n");
+
+    timer.duration  = interval_sec*1000+interval_us/1000;
+    timer.timeout= ((uint64_t)tp.tv_sec*1000+tp.tv_nsec/(1000*1000)+timer.duration);
+    timer.instance  = instance;
+    timer.type      = type;
+    timer.timer_arg = timer_arg;
+    pthread_mutex_lock (&t->queue_cond_lock);
+    t->timer_map[*timer_id]= timer;
+
+    if (timer.timeout < t->next_timer)
+      t->next_timer=timer.timeout;
+
+    eventfd_t sem_counter = 1;
+    AssertFatal ( sizeof(sem_counter) == write(t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
+    pthread_mutex_unlock (&t->queue_cond_lock);
+    return 0;
+  }
+
+  int timer_remove(long timer_id) {
+    task_id_t task_id=(task_id_t)(timer_id&0xffff);
+    int ret;
+    pthread_mutex_lock (&tasks[task_id].queue_cond_lock);
+    ret=tasks[task_id].timer_map.erase(timer_id);
+    pthread_mutex_unlock (&tasks[task_id].queue_cond_lock);
+
+    if (ret==1)
+      return 0;
+    else {
+      LOG_W(TMR, "tried to remove a non existing timer\n");
+      return 1;
+    }
+  }
+
+  const char *itti_get_message_name(MessagesIds message_id) {
+    return messages_info[message_id].name;
+  }
+
+  const char *itti_get_task_name(task_id_t task_id) {
+    return tasks[task_id].admin.name;
+  }
+
+  // void for compatibility
+  void itti_send_terminate_message(task_id_t task_id) {
+  }
+
+  void itti_wait_tasks_end(void) {
+    while(1)
+      sleep(24*3600);
+  }
+
+  void itti_update_lte_time(uint32_t frame, uint8_t slot) {}
+  void itti_set_task_real_time(task_id_t task_id) {}
+  void itti_mark_task_ready(task_id_t task_id) {
+    // Function meaning is clear, but legacy implementation is wrong
+    // keep it void is fine: today implementation accepts messages in the queue before task is ready
+  }
+  void itti_wait_ready(int wait_tasks) {
+    // Stupid function, kept for compatibility (the parameter is meaningless!!!)
+  }
+  int signal_mask(void) { return 0;}
+}
diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..4a8402716b59f061352a19efc7dafa758c60530b
--- /dev/null
+++ b/common/utils/ocp_itti/intertask_interface.h
@@ -0,0 +1,536 @@
+/*
+  Author: Laurent THOMAS, Open Cells
+  Copyleft: OpenAirInterface software alliance
+*/
+#ifndef INTERTASK_INTERFACE_H_
+#define INTERTASK_INTERFACE_H_
+#include <stdint.h>
+#include <sys/epoll.h>
+
+#include <mem_block.h>
+#include <assertions.h>
+
+
+typedef enum timer_type_s {
+  TIMER_PERIODIC,
+  TIMER_ONE_SHOT,
+  TIMER_TYPE_MAX,
+} timer_type_t;
+
+typedef struct {
+  void *arg;
+  long  timer_id;
+} timer_has_expired_t;
+
+typedef struct {
+  uint32_t      interval_sec;
+  uint32_t      interval_us;
+  long     task_id;
+  int32_t       instance;
+  timer_type_t  type;
+  void         *timer_arg;
+  long          timer_id;
+} timer_create_t;
+
+typedef struct {
+  long     task_id;
+  long          timer_id;
+} timer_delete_t;
+
+
+typedef struct itti_lte_time_s {
+  uint32_t frame;
+  uint8_t slot;
+} itti_lte_time_t;
+
+
+typedef struct IttiMsgEmpty_s {
+} IttiMsgEmpty;
+
+typedef struct IttiMsgText_s {
+  uint32_t  size;
+  char      text[];
+} IttiMsgText;
+
+#include <openair2/COMMON/phy_messages_types.h>
+#include <openair2/COMMON/mac_messages_types.h>
+#include <openair2/COMMON/rlc_messages_types.h>
+#include <openair2/COMMON/pdcp_messages_types.h>
+#include <openair2/COMMON/networkDef.h>
+#include <openair2/COMMON/as_message.h>
+#include <openair2/RRC/LTE/rrc_types.h>
+#include <openair2/COMMON/rrc_messages_types.h>
+
+#include <openair3/NAS/COMMON/UTIL/OctetString.h>
+#include <openair3/NAS/COMMON/IES/AccessPointName.h>
+#include <openair3/NAS/COMMON/IES/AdditionalUpdateResult.h>
+#include <openair3/NAS/COMMON/IES/AdditionalUpdateType.h>
+#include <openair3/NAS/COMMON/IES/ApnAggregateMaximumBitRate.h>
+#include <openair3/NAS/COMMON/IES/AuthenticationFailureParameter.h>
+#include <openair3/NAS/COMMON/IES/AuthenticationParameterAutn.h>
+#include <openair3/NAS/COMMON/IES/AuthenticationParameterRand.h>
+#include <openair3/NAS/COMMON/IES/AuthenticationResponseParameter.h>
+#include <openair3/NAS/COMMON/IES/CipheringKeySequenceNumber.h>
+#include <openair3/NAS/COMMON/IES/Cli.h>
+#include <openair3/NAS/COMMON/IES/CsfbResponse.h>
+#include <openair3/NAS/COMMON/IES/DaylightSavingTime.h>
+#include <openair3/NAS/COMMON/IES/DetachType.h>
+#include <openair3/NAS/COMMON/IES/DrxParameter.h>
+#include <openair3/NAS/COMMON/IES/EmergencyNumberList.h>
+#include <openair3/NAS/COMMON/IES/EmmCause.h>
+#include <openair3/NAS/COMMON/IES/EpsAttachResult.h>
+#include <openair3/NAS/COMMON/IES/EpsAttachType.h>
+#include <openair3/NAS/COMMON/IES/EpsBearerContextStatus.h>
+#include <openair3/NAS/COMMON/IES/EpsBearerIdentity.h>
+#include <openair3/NAS/COMMON/IES/EpsMobileIdentity.h>
+#include <openair3/NAS/COMMON/IES/EpsNetworkFeatureSupport.h>
+#include <openair3/NAS/COMMON/IES/EpsQualityOfService.h>
+#include <openair3/NAS/COMMON/IES/EpsUpdateResult.h>
+#include <openair3/NAS/COMMON/IES/EpsUpdateType.h>
+#include <openair3/NAS/COMMON/IES/EsmCause.h>
+#include <openair3/NAS/COMMON/IES/EsmInformationTransferFlag.h>
+#include <openair3/NAS/COMMON/IES/EsmMessageContainer.h>
+#include <openair3/NAS/COMMON/IES/GprsTimer.h>
+#include <openair3/NAS/COMMON/IES/GutiType.h>
+#include <openair3/NAS/COMMON/IES/IdentityType2.h>
+#include <openair3/NAS/COMMON/IES/ImeisvRequest.h>
+#include <openair3/NAS/COMMON/IES/KsiAndSequenceNumber.h>
+#include <openair3/NAS/COMMON/IES/LcsClientIdentity.h>
+#include <openair3/NAS/COMMON/IES/LcsIndicator.h>
+#include <openair3/NAS/COMMON/IES/LinkedEpsBearerIdentity.h>
+#include <openair3/NAS/COMMON/IES/LlcServiceAccessPointIdentifier.h>
+#include <openair3/NAS/COMMON/IES/LocationAreaIdentification.h>
+#include <openair3/NAS/COMMON/IES/MessageType.h>
+#include <openair3/NAS/COMMON/IES/MobileIdentity.h>
+#include <openair3/NAS/COMMON/IES/MobileStationClassmark2.h>
+#include <openair3/NAS/COMMON/IES/MobileStationClassmark3.h>
+#include <openair3/NAS/COMMON/IES/MsNetworkCapability.h>
+#include <openair3/NAS/COMMON/IES/MsNetworkFeatureSupport.h>
+#include <openair3/NAS/COMMON/IES/NasKeySetIdentifier.h>
+#include <openair3/NAS/COMMON/IES/NasMessageContainer.h>
+#include <openair3/NAS/COMMON/IES/NasRequestType.h>
+#include <openair3/NAS/COMMON/IES/NasSecurityAlgorithms.h>
+#include <openair3/NAS/COMMON/IES/NetworkName.h>
+#include <openair3/NAS/COMMON/IES/Nonce.h>
+#include <openair3/NAS/COMMON/IES/PacketFlowIdentifier.h>
+#include <openair3/NAS/COMMON/IES/PagingIdentity.h>
+#include <openair3/NAS/COMMON/IES/PdnAddress.h>
+#include <openair3/NAS/COMMON/IES/PdnType.h>
+#include <openair3/NAS/COMMON/IES/PlmnList.h>
+#include <openair3/NAS/COMMON/IES/ProcedureTransactionIdentity.h>
+#include <openair3/NAS/COMMON/IES/ProtocolConfigurationOptions.h>
+#include <openair3/NAS/COMMON/IES/ProtocolDiscriminator.h>
+#include <openair3/NAS/COMMON/IES/PTmsiSignature.h>
+#include <openair3/NAS/COMMON/IES/QualityOfService.h>
+#include <openair3/NAS/COMMON/IES/RadioPriority.h>
+#include <openair3/NAS/COMMON/IES/SecurityHeaderType.h>
+#include <openair3/NAS/COMMON/IES/ServiceType.h>
+#include <openair3/NAS/COMMON/IES/ShortMac.h>
+#include <openair3/NAS/COMMON/IES/SsCode.h>
+#include <openair3/NAS/COMMON/IES/SupportedCodecList.h>
+#include <openair3/NAS/COMMON/IES/TimeZoneAndTime.h>
+#include <openair3/NAS/COMMON/IES/TimeZone.h>
+#include <openair3/NAS/COMMON/IES/TmsiStatus.h>
+#include <openair3/NAS/COMMON/IES/TrackingAreaIdentity.h>
+#include <openair3/NAS/COMMON/IES/TrackingAreaIdentityList.h>
+#include <openair3/NAS/COMMON/IES/TrafficFlowAggregateDescription.h>
+#include <openair3/NAS/COMMON/IES/TrafficFlowTemplate.h>
+#include <openair3/NAS/COMMON/IES/TransactionIdentifier.h>
+#include <openair3/NAS/COMMON/IES/UeNetworkCapability.h>
+#include <openair3/NAS/COMMON/IES/UeRadioCapabilityInformationUpdateNeeded.h>
+#include <openair3/NAS/COMMON/IES/UeSecurityCapability.h>
+#include <openair3/NAS/COMMON/IES/VoiceDomainPreferenceAndUeUsageSetting.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextAccept.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextReject.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceAllocationReject.h>
+#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceAllocationRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceModificationReject.h>
+#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceModificationRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/DeactivateEpsBearerContextAccept.h>
+#include <openair3/NAS/COMMON/ESM/MSG/DeactivateEpsBearerContextRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/esm_cause.h>
+#include <openair3/NAS/COMMON/ESM/MSG/EsmInformationRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/EsmInformationResponse.h>
+#include <openair3/NAS/COMMON/ESM/MSG/EsmStatus.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextAccept.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextReject.h>
+#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/PdnConnectivityReject.h>
+#include <openair3/NAS/COMMON/ESM/MSG/PdnConnectivityRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/PdnDisconnectReject.h>
+#include <openair3/NAS/COMMON/ESM/MSG/PdnDisconnectRequest.h>
+#include <openair3/NAS/COMMON/ESM/MSG/esm_msgDef.h>
+#include <openair3/NAS/COMMON/ESM/MSG/esm_msg.h>
+
+#include <openair3/NAS/COMMON/EMM/MSG/AttachAccept.h>
+#include <openair3/NAS/COMMON/EMM/MSG/AttachComplete.h>
+#include <openair3/NAS/COMMON/EMM/MSG/AttachReject.h>
+#include <openair3/NAS/COMMON/EMM/MSG/AttachRequest.h>
+#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationFailure.h>
+#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationReject.h>
+#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.h>
+#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationResponse.h>
+#include <openair3/NAS/COMMON/EMM/MSG/CsServiceNotification.h>
+#include <openair3/NAS/COMMON/EMM/MSG/DetachAccept.h>
+#include <openair3/NAS/COMMON/EMM/MSG/DetachRequest.h>
+#include <openair3/NAS/COMMON/EMM/MSG/DownlinkNasTransport.h>
+#include <openair3/NAS/COMMON/EMM/MSG/emm_cause.h>
+#include <openair3/NAS/COMMON/EMM/MSG/EmmInformation.h>
+#include <openair3/NAS/COMMON/EMM/MSG/EmmStatus.h>
+#include <openair3/NAS/COMMON/EMM/MSG/ExtendedServiceRequest.h>
+#include <openair3/NAS/COMMON/EMM/MSG/GutiReallocationCommand.h>
+#include <openair3/NAS/COMMON/EMM/MSG/GutiReallocationComplete.h>
+#include <openair3/NAS/COMMON/EMM/MSG/IdentityRequest.h>
+#include <openair3/NAS/COMMON/EMM/MSG/IdentityResponse.h>
+#include <openair3/NAS/COMMON/EMM/MSG/NASSecurityModeCommand.h>
+#include <openair3/NAS/COMMON/EMM/MSG/NASSecurityModeComplete.h>
+#include <openair3/NAS/COMMON/EMM/MSG/SecurityModeReject.h>
+#include <openair3/NAS/COMMON/EMM/MSG/ServiceReject.h>
+#include <openair3/NAS/COMMON/EMM/MSG/ServiceRequest.h>
+#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateAccept.h>
+#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateComplete.h>
+#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateReject.h>
+#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateRequest.h>
+#include <openair3/NAS/COMMON/EMM/MSG/UplinkNasTransport.h>
+#include <openair3/NAS/COMMON/EMM/MSG/emm_msgDef.h>
+#include <openair3/NAS/COMMON/EMM/MSG/emm_msg.h>
+
+#include <openair3/NAS/COMMON/API/NETWORK/nas_message.h>
+#include <openair2/COMMON/nas_messages_types.h>
+#if ENABLE_RAL
+  #include <ral_messages_types.h>
+#endif
+#include <openair2/COMMON/s1ap_messages_types.h>
+#include <openair2/COMMON/x2ap_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>
+#include <openair3/SCTP/sctp_eNB_task.h>
+#include <openair3/NAS/UE/nas_proc_defs.h>
+#include <openair3/NAS/UE/ESM/esmData.h>
+#include <openair3/NAS/COMMON/UTIL/nas_timer.h>
+#include <openair3/NAS/UE/ESM/esm_pt_defs.h>
+#include <openair3/NAS/UE/EMM/emm_proc_defs.h>
+#include <openair3/NAS/UE/EMM/emmData.h>
+#include <openair3/NAS/UE/EMM/IdleMode_defs.h>
+#include <openair3/NAS/UE/EMM/emm_fsm_defs.h>
+#include <openair3/NAS/UE/EMM/emmData.h>
+#include <openair3/NAS/COMMON/securityDef.h>
+#include <openair3/NAS/UE/EMM/Authentication.h>
+#include <openair3/NAS/UE/EMM/SecurityModeControl.h>
+#include <openair3/NAS/UE/API/USIM/usim_api.h>
+#include <openair3/NAS/COMMON/userDef.h>
+#include <openair3/NAS/UE/API/USER/at_command.h>
+#include <openair3/NAS/UE/API/USER/at_response.h>
+#include <openair3/NAS/UE/API/USER/user_api_defs.h>
+#include <openair3/NAS/UE/EMM/LowerLayer_defs.h>
+#include <openair3/NAS/UE/user_defs.h>
+#include <openair3/NAS/UE/nas_ue_task.h>
+#include <openair3/S1AP/s1ap_eNB.h>
+//#include <proto.h>
+
+/*
+  static const char *const messages_definition_xml = {
+  #include <messages_xml.h>
+  };
+*/
+
+typedef uint32_t MessageHeaderSize;
+typedef uint32_t itti_message_types_t;
+typedef unsigned long message_number_t;
+#define MESSAGE_NUMBER_SIZE (sizeof(unsigned long))
+
+typedef enum task_priorities_e {
+  TASK_PRIORITY_MAX       = 100,
+  TASK_PRIORITY_MAX_LEAST = 85,
+  TASK_PRIORITY_MED_PLUS  = 70,
+  TASK_PRIORITY_MED       = 55,
+  TASK_PRIORITY_MED_LEAST = 40,
+  TASK_PRIORITY_MIN_PLUS  = 25,
+  TASK_PRIORITY_MIN       = 10,
+} task_priorities_t;
+
+typedef struct {
+  task_priorities_t priority;
+  unsigned int queue_size;
+  /* Printable name */
+  char name[256];
+  void *(*func)(void *) ;
+  void *(*threadFunc)(void *) ;
+} task_info_t;
+//
+//TASK_DEF(TASK_RRC_ENB,  TASK_PRIORITY_MED,  200, NULL,NULL)
+//TASK_DEF(TASK_RRC_ENB,  TASK_PRIORITY_MED,  200, NULL, NULL)
+//TASK_DEF(TASK_GTPV1_U,  TASK_PRIORITY_MED,  1000,NULL, NULL)
+//TASK_DEF(TASK_UDP,      TASK_PRIORITY_MED,  1000, NULL, NULL)
+
+#define FOREACH_TASK(TASK_DEF) \
+  TASK_DEF(TASK_UNKNOWN,  TASK_PRIORITY_MED, 50, NULL, NULL)  \
+  TASK_DEF(TASK_TIMER,    TASK_PRIORITY_MED, 10, NULL, NULL)   \
+  TASK_DEF(TASK_L2L1,     TASK_PRIORITY_MAX, 200, NULL, NULL)   \
+  TASK_DEF(TASK_BM,       TASK_PRIORITY_MED, 200, NULL, NULL)   \
+  TASK_DEF(TASK_PHY_ENB,  TASK_PRIORITY_MED, 200, NULL, NULL)   \
+  TASK_DEF(TASK_MAC_ENB,  TASK_PRIORITY_MED, 200, NULL, NULL)   \
+  TASK_DEF(TASK_RLC_ENB,  TASK_PRIORITY_MED, 200, NULL, NULL)   \
+  TASK_DEF(TASK_RRC_ENB_NB_IoT,  TASK_PRIORITY_MED, 200, NULL, NULL) \
+  TASK_DEF(TASK_PDCP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL)   \
+  TASK_DEF(TASK_RRC_ENB,  TASK_PRIORITY_MED,  200, NULL,NULL)\
+  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_SCTP,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_ENB_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)  \
+  TASK_DEF(TASK_RLC_UE,   TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_PDCP_UE,  TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_RRC_UE,   TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_NAS_UE,   TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_RAL_UE,   TASK_PRIORITY_MED,  200, NULL, NULL)  \
+  TASK_DEF(TASK_MSC,      TASK_PRIORITY_MED,  200, NULL, NULL)\
+  TASK_DEF(TASK_GTPV1_U,  TASK_PRIORITY_MED,  1000,NULL, NULL)\
+  TASK_DEF(TASK_UDP,      TASK_PRIORITY_MED,  1000, NULL, NULL)\
+  TASK_DEF(TASK_MAX,      TASK_PRIORITY_MED,  200, NULL, NULL)
+
+#define TASK_DEF(TaskID, pRIO, qUEUEsIZE, FuNc, ThreadFunc)          { pRIO, qUEUEsIZE, #TaskID, FuNc, ThreadFunc },
+
+/* Map task id to printable name. */
+static const task_info_t tasks_info[] = {
+  FOREACH_TASK(TASK_DEF)
+};
+
+#define TASK_ENUM(TaskID, pRIO, qUEUEsIZE, FuNc,ThreadFunc ) TaskID,
+//! Tasks id of each task
+typedef enum {
+  FOREACH_TASK(TASK_ENUM)
+} task_id_t;
+
+
+typedef task_id_t thread_id_t;
+
+typedef enum message_priorities_e {
+  MESSAGE_PRIORITY_MAX       = 100,
+  MESSAGE_PRIORITY_MAX_LEAST = 85,
+  MESSAGE_PRIORITY_MED_PLUS  = 70,
+  MESSAGE_PRIORITY_MED       = 55,
+  MESSAGE_PRIORITY_MED_LEAST = 40,
+  MESSAGE_PRIORITY_MIN_PLUS  = 25,
+  MESSAGE_PRIORITY_MIN       = 10,
+} message_priorities_t;
+
+
+#define FOREACH_MSG(INTERNAL_MSG)         \
+  INTERNAL_MSG(TIMER_HAS_EXPIRED,  MESSAGE_PRIORITY_MED, timer_has_expired_t, timer_has_expired) \
+  INTERNAL_MSG(INITIALIZE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, initialize_message)  \
+  INTERNAL_MSG(ACTIVATE_MESSAGE,   MESSAGE_PRIORITY_MED, IttiMsgEmpty, activate_message) \
+  INTERNAL_MSG(DEACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, deactivate_message)  \
+  INTERNAL_MSG(TERMINATE_MESSAGE,  MESSAGE_PRIORITY_MAX, IttiMsgEmpty, terminate_message) \
+  INTERNAL_MSG(MESSAGE_TEST,       MESSAGE_PRIORITY_MED, IttiMsgEmpty, message_test)
+
+/* This enum defines messages ids. Each one is unique. */
+typedef enum {
+#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) iD,
+  FOREACH_MSG(MESSAGE_DEF)
+#include <all_msg.h>
+#undef MESSAGE_DEF
+  MESSAGES_ID_MAX,
+} MessagesIds;
+
+typedef union msg_s {
+#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) sTRUCT fIELDnAME;
+  FOREACH_MSG(MESSAGE_DEF)
+#include <all_msg.h>
+#undef MESSAGE_DEF
+} msg_t;
+
+typedef struct MessageHeader_s {
+  MessagesIds messageId;          /**< Unique message id as referenced in enum MessagesIds */
+  task_id_t  originTaskId;        /**< ID of the sender task */
+  task_id_t  destinationTaskId;   /**< ID of the destination task */
+  instance_t instance;            /**< Task instance for virtualization */
+  itti_lte_time_t lte_time;
+  MessageHeaderSize ittiMsgSize;         /**< Message size (not including header size) */
+} MessageHeader;
+
+typedef struct message_info_s {
+  int id;
+  message_priorities_t priority;
+  /* Message payload size */
+  MessageHeaderSize size;
+  /* Printable name */
+  const char name[256];
+} message_info_t;
+
+/* Map message id to message information */
+static const message_info_t messages_info[] = {
+#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) { iD, pRIO, sizeof(sTRUCT), #iD },
+  FOREACH_MSG(MESSAGE_DEF)
+#include <all_msg.h>
+#undef MESSAGE_DEF
+};
+
+typedef struct __attribute__ ((__packed__)) MessageDef_s {
+  MessageHeader ittiMsgHeader; /**< Message header */
+  msg_t         ittiMsg;
+} MessageDef;
+
+
+
+/* Extract the instance from a message */
+#define ITTI_MESSAGE_GET_INSTANCE(mESSAGE)  ((mESSAGE)->ittiMsgHeader.instance)
+#define ITTI_MSG_ID(mSGpTR)                 ((mSGpTR)->ittiMsgHeader.messageId)
+#define ITTI_MSG_ORIGIN_ID(mSGpTR)          ((mSGpTR)->ittiMsgHeader.originTaskId)
+#define ITTI_MSG_DESTINATION_ID(mSGpTR)     ((mSGpTR)->ittiMsgHeader.destinationTaskId)
+#define ITTI_MSG_INSTANCE(mSGpTR)           ((mSGpTR)->ittiMsgHeader.instance)
+#define ITTI_MSG_NAME(mSGpTR)               itti_get_message_name(ITTI_MSG_ID(mSGpTR))
+#define ITTI_MSG_ORIGIN_NAME(mSGpTR)        itti_get_task_name(ITTI_MSG_ORIGIN_ID(mSGpTR))
+#define ITTI_MSG_DESTINATION_NAME(mSGpTR)   itti_get_task_name(ITTI_MSG_DESTINATION_ID(mSGpTR))
+#define TIMER_HAS_EXPIRED(mSGpTR)           (mSGpTR)->ittiMsg.timer_has_expired
+
+#define INSTANCE_DEFAULT    (UINT16_MAX - 1)
+
+static inline int64_t clock_difftime_ns(struct timespec start, struct timespec end) {
+  return (int64_t)( end.tv_sec-start.tv_sec) * (int64_t)(1000*1000*1000) + end.tv_nsec-start.tv_nsec;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \brief Send a message to a task (could be itself)
+  \param task_id Task ID
+  \param instance Instance of the task used for virtualization
+  \param message Pointer to the message to send
+  @returns -1 on failure, 0 otherwise
+ **/
+int itti_send_msg_to_task(task_id_t task_id, instance_t instance, MessageDef *message);
+
+/** \brief Add a new fd to monitor.
+   NOTE: it is up to the user to read data associated with the fd
+    \param task_id Task ID of the receiving task
+    \param fd The file descriptor to monitor
+ **/
+void itti_subscribe_event_fd(task_id_t task_id, int fd);
+
+/** \brief Remove a fd from the list of fd to monitor
+    \param task_id Task ID of the task
+    \param fd The file descriptor to remove
+ **/
+void itti_unsubscribe_event_fd(task_id_t task_id, int fd);
+
+/** \brief Return the list of events excluding the fd associated with itti
+    \param task_id Task ID of the task
+    \param events events list
+    @returns number of events to handle
+ **/
+int itti_get_events(task_id_t task_id, struct epoll_event **events);
+
+/** \brief Retrieves a message in the queue associated to task_id.
+   If the queue is empty, the thread is blocked till a new message arrives.
+  \param task_id Task ID of the receiving task
+  \param received_msg Pointer to the allocated message
+ **/
+void itti_receive_msg(task_id_t task_id, MessageDef **received_msg);
+
+/** \brief Try to retrieves a message in the queue associated to task_id.
+  \param task_id Task ID of the receiving task
+  \param received_msg Pointer to the allocated message
+ **/
+void itti_poll_msg(task_id_t task_id, MessageDef **received_msg);
+
+/** \brief Start thread associated to the task
+   \param task_id task to start
+   \param start_routine entry point for the task
+   \param args_p Optional argument to pass to the start routine
+   @returns -1 on failure, 0 otherwise
+ **/
+int itti_create_task(task_id_t task_id,
+                     void *(*start_routine) (void *),
+                     void *args_p);
+
+/** \brief Exit the current task.
+ **/
+void itti_exit_task(void);
+
+/** \brief Initiate termination of all tasks.
+   \param task_id task that is completed
+ **/
+void itti_terminate_tasks(task_id_t task_id);
+
+// Void for legacy compatibility
+void itti_wait_ready(int wait_tasks);
+void itti_mark_task_ready(task_id_t task_id);
+
+/** \brief Return the printable string associated with the message
+   \param message_id Id of the message
+ **/
+const char *itti_get_message_name(MessagesIds message_id);
+
+/** \brief Return the printable string associated with a task id
+   \param thread_id Id of the task
+ **/
+const char *itti_get_task_name(task_id_t task_id);
+
+/** \brief Alloc and memset(0) a new itti message.
+   \param origin_task_id Task ID of the sending task
+   \param message_id Message ID
+   @returns NULL in case of failure or newly allocated mesage ref
+ **/
+MessageDef *itti_alloc_new_message(
+  task_id_t         origin_task_id,
+  MessagesIds       message_id);
+
+/** \brief Alloc and memset(0) a new itti message.
+   \param origin_task_id Task ID of the sending task
+   \param message_id Message ID
+   \param size size of the payload to send
+   @returns NULL in case of failure or newly allocated mesage ref
+ **/
+MessageDef *itti_alloc_new_message_sized(
+  task_id_t         origin_task_id,
+  MessagesIds       message_id,
+  MessageHeaderSize size);
+
+/** \brief handle signals and wait for all threads to join when the process complete.
+   This function should be called from the main thread after having created all ITTI tasks.
+ **/
+void itti_wait_tasks_end(void);
+#define  THREAD_MAX 0 //for compatibility
+void itti_set_task_real_time(task_id_t task_id);
+
+/** \brief Send a termination message to all tasks.
+   \param task_id task that is broadcasting the message.
+ **/
+void itti_send_terminate_message(task_id_t task_id);
+
+void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size);
+void *calloc_or_fail(size_t size);
+void *malloc_or_fail(size_t size);
+int memory_read(const char *datafile, void *data, size_t size);
+int itti_free(task_id_t task_id, void *ptr);
+
+int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
+              const message_info_t *messages_info);
+int timer_setup(
+  uint32_t      interval_sec,
+  uint32_t      interval_us,
+  task_id_t     task_id,
+  int32_t       instance,
+  timer_type_t  type,
+  void         *timer_arg,
+  long         *timer_id);
+
+
+int timer_remove(long timer_id);
+#define timer_stop timer_remove
+int signal_handle(int *end);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* INTERTASK_INTERFACE_H_ */