From 90231b57ad8e6a6954b2b7738cf0493b4571d5ad Mon Sep 17 00:00:00 2001
From: gauthier <gauthier@mycompany.com>
Date: Tue, 23 Jun 2015 13:14:50 +0000
Subject: [PATCH] Still under construction

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7642 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 .../mme_test_s1_generate_scenario_from_pcap   | 210 +++++++++++
 openair-cn/TEST/oaisim_mme_test_s1c_s1ap.c    | 337 ++++++++++++++++++
 openair-cn/TEST/oaisim_mme_test_s1c_s1ap.h    |  60 ++++
 .../TEST/oaisim_mme_test_s1c_scenario.c       | 286 +++++++++++++++
 4 files changed, 893 insertions(+)
 create mode 100755 openair-cn/TEST/mme_test_s1_generate_scenario_from_pcap
 create mode 100755 openair-cn/TEST/oaisim_mme_test_s1c_s1ap.c
 create mode 100755 openair-cn/TEST/oaisim_mme_test_s1c_s1ap.h
 create mode 100755 openair-cn/TEST/oaisim_mme_test_s1c_scenario.c

diff --git a/openair-cn/TEST/mme_test_s1_generate_scenario_from_pcap b/openair-cn/TEST/mme_test_s1_generate_scenario_from_pcap
new file mode 100755
index 00000000000..6a3e61091f2
--- /dev/null
+++ b/openair-cn/TEST/mme_test_s1_generate_scenario_from_pcap
@@ -0,0 +1,210 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+################################################################################
+#    OpenAirInterface
+#    Copyright(c) 1999 - 2014 Eurecom
+#
+#    OpenAirInterface is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#
+#    OpenAirInterface is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with OpenAirInterface.The full GNU General Public License is
+#    included in this distribution in the file called "COPYING". If not,
+#    see <http://www.gnu.org/licenses/>.
+#
+#   Contact Information
+#   OpenAirInterface Admin: openair_admin@eurecom.fr
+#   OpenAirInterface Tech : openair_tech@eurecom.fr
+#   OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+#
+#   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+#
+################################################################################
+import sys
+import subprocess
+import re
+import socket
+import datetime
+from datetime import date
+import os, errno
+import argparse
+
+
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--pcap_file", "-p", type=str,help="input pcap file to be translated")
+args = parser.parse_args()
+
+pcap_file = args.pcap_file.strip()
+
+pcap_dissected_file = subprocess.check_output(["tshark", '-V', '-r' , pcap_file], stderr=subprocess.STDOUT)
+pcap_hex_file = subprocess.check_output(["tshark", '-x', '-O', 'sctp', '-r', pcap_file])
+pcap_dissected_list = []
+
+# split file content in lines
+lines = pcap_dissected_file.splitlines()
+message     = {}
+item_index  = 0;
+item_string = " "
+fsm_state="search_frame"
+for line in lines:
+    print ("INPUT LINE:  %s " % line)
+    line = line.strip()
+    if line != "":       
+        if fsm_state == "search_frame":
+            if line.startswith("Frame"):
+                message = {}
+                partition = line.split(' ',3)
+                message['frame'] = int(partition[1].strip(':'))
+                fsm_state = "search_ip"
+                print("Found Frame %d" % (message['frame']))
+                
+        elif fsm_state == "search_ip":
+            if line.startswith("Internet Protocol Version"):
+                fsm_state = "fill_ip"
+                message['ip_fields'] = 0
+                print("Found in Frame %d IP" % (message['frame']))
+
+        elif fsm_state == "fill_ip":
+            if line.startswith("Header length"):
+                partition = line.split(' ',4)
+                message['ip_header_length'] = int(partition[2])
+                message['ip_fields'] += 1
+                print("Found in Frame %d IP header length %d" % (message['frame'], int(partition[2])))
+            if line.startswith("Total Length"):
+                partition = line.split(' ',4)
+                message['ip_total_length'] = int(partition[2])
+                message['ip_fields'] += 1
+                print("Found in Frame %d IP Total Length %d" % (message['frame'], int(partition[2])))
+            if line.startswith("Protocol"):
+                partition = line.split(' ',4)
+                if partition[1] != "SCTP":
+                    print("Error did not found in Frame %d SCTP" % (message['frame'])))
+                    fsm_state="search_frame"
+                    continue
+                else:
+                    message['ip_protocol'] = partition[1]
+                    message['ip_fields'] += 1
+                    print("Found in Frame %d SCTP" % (message['frame'])))
+            if message['ip_fields'] == 3:
+                fsm_state = "search_sctp"
+                print("in Frame %d searching S1AP" % (message['frame'])))
+                        
+        elif fsm_state == "search_sctp":
+            if line.startswith("Internet Protocol Version"):
+                fsm_state = "fill_sctp"
+                message['sctp_fields'] = 0
+                
+        elif fsm_state == "fill_sctp":
+            if line.startswith("Source port"):
+                partition = line.split(' ',4)
+                message['Source port'] = int(partition[2])
+                message['sctp_fields'] += 1
+            elif line.startswith("Destination port"):
+                partition = line.split(' ',4)
+                message['Destination port'] = int(partition[2])
+                message['sctp_fields'] += 1
+            elif line.startswith("Chunk length"):
+                partition = line.split(' ',4)
+                message['Chunk length'] = int(partition[2])
+                message['sctp_fields'] += 1
+            elif line.startswith("Stream Identifier"):
+                partition = line.split(' ',4)
+                message['Stream Identifier'] = int(partition[2])
+                message['sctp_fields'] += 1
+            elif line.startswith("Stream sequence number"):
+                partition = line.split(' ',4)
+                message['Stream sequence number'] = int(partition[3])
+                message['sctp_fields'] += 1
+            elif line.startswith("Chunk padding"):
+                partition = line.split(' ',4)
+                message['Chunk padding'] = int(partition[2])
+                message['sctp_fields'] += 1
+            if message['sctp_fields'] == 6:
+                fsm_state = "search_s1ap"
+                
+        elif fsm_state == "search_s1ap":
+            if line.startswith("S1 Application Protocol"):
+                fsm_state = "fill_s1ap"
+                message['s1ap_fields'] = 0
+                print("in Frame %d Filling S1AP" % (message['frame'])))
+                        
+        elif fsm_state == "fill_s1ap":
+            if line.startswith("S1AP-PDU:"):
+                partition = line.split(' ')
+                message['Pdu'] = partition[1]
+                message['s1ap_fields'] += 1
+            elif line.startswith("procedureCode:"):
+                partition = line.split(' ')
+                message['procedureCode:'] = partition[1]
+                message['s1ap_fields'] += 1
+            elif line.startswith("protocolIEs"):
+                partition = line.split(' ')
+                message['protocolIEs'] = int(partition[1])
+                message['items'] = {}
+            elif line.startswith("Item"):
+                partition = line.split(' ')
+                item_index  = partition[1].trim(':')
+                item_string = partition[2]
+                message['items'][item_string] = ' '
+                print("Found in Frame %d S1AP Item %d %s" % (message['frame'], item_index, item_string)))
+                if item_string == id-E-RABToBeSetupListCtxtSUReq:
+                elif item_string == id-E-RABToBeSetupListCtxtSUReq:
+            elif line.startswith("nAS-PDU"):
+                partition = line.split(' ')
+                nas_bytes = partition[1].trim('.')
+                message['items'].append
+                print("Found in Frame %d Stream sequence number" % (message['frame'], int(partition[3])))
+
+            if message['s1ap_fields'] == 6:
+                pcap_dissected_list.append(message)
+                fsm_state = "search_frame"
+
+for message in pcap_dissected_list:
+    print("Message:\n" )
+    print("    %s" % (message))
+
+lines = pcap_hex_file.splitlines()
+message = {}
+message_index = 0
+fsm_state="search_frame"
+for line in lines:
+    print ("INPUT LINE:  %s " % line)
+    line = line.strip()
+    if line != "":       
+        if fsm_state == "search_frame":
+            if line.startswith("Frame"):
+                partition = line.split(' ',3)
+                fsm_state = "search_s1ap"
+                                
+        elif fsm_state == "search_s1ap":
+            if line.startswith("S1 Application Protocol"):
+                fsm_state = "fill_s1ap"
+                message = pcap_dissected_list[message_index]
+                message['s1ap_byte_offset'] = 0
+                message['dumped'] = []
+                message_index += 1
+                        
+        elif fsm_state == "fill_s1ap":
+            if not line.startswith("Frame"):
+                bytes = line.split(' ')
+                byte_index = int(bytes[0],16)
+                if byte_index ==  message['s1ap_byte_offset']:
+                    message['s1ap_byte_offset'] += 16
+                    for byte in bytes:
+                        message['dumped'].append(byte)
+                        message['s1ap_byte_offset'] += 1
+                else:
+                    fsm_state="search_frame"
+            
+print ("  %s " % ( pcap_dissected_list ) )
+
diff --git a/openair-cn/TEST/oaisim_mme_test_s1c_s1ap.c b/openair-cn/TEST/oaisim_mme_test_s1c_s1ap.c
new file mode 100755
index 00000000000..a46c8fa6b49
--- /dev/null
+++ b/openair-cn/TEST/oaisim_mme_test_s1c_s1ap.c
@@ -0,0 +1,337 @@
+/*******************************************************************************
+    OpenAirInterface
+    Copyright(c) 1999 - 2014 Eurecom
+
+    OpenAirInterface is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+
+    OpenAirInterface is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenAirInterface.The full GNU General Public License is
+    included in this distribution in the file called "COPYING". If not,
+    see <http://www.gnu.org/licenses/>.
+
+   Contact Information
+   OpenAirInterface Admin: openair_admin@eurecom.fr
+   OpenAirInterface Tech : openair_tech@eurecom.fr
+   OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+
+   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+*******************************************************************************/
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <linux/sched.h>
+#include <signal.h>
+#include <execinfo.h>
+#include <getopt.h>
+#include <syscall.h>
+
+
+#include "tree.h"
+#include "queue.h"
+#include "intertask_interface.h"
+#include "s1ap_eNB_default_values.h"
+#include "s1ap_common.h"
+#include "s1ap_ies_defs.h"
+#include "s1ap_eNB_defs.h"
+#include "s1ap_eNB_management_procedures.h"
+#include "assertions.h"
+
+#include "platform_types.h"
+#include "oaisim_mme_test_s1c.h"
+
+
+void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind)
+{
+  int result;
+
+  DevAssert(sctp_data_ind != NULL);
+  mme_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream,
+          sctp_data_ind->buffer, sctp_data_ind->buffer_length);
+
+  result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
+  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+}
+
+
+void s1ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream)
+{
+  MessageDef      *message_p;
+  sctp_data_req_t *sctp_data_req;
+
+  message_p = itti_alloc_new_message(TASK_S1AP, SCTP_DATA_REQ);
+
+  sctp_data_req = &message_p->ittiMsg.sctp_data_req;
+
+  sctp_data_req->assoc_id      = assoc_id;
+  sctp_data_req->buffer        = buffer;
+  sctp_data_req->buffer_length = buffer_length;
+  sctp_data_req->stream        = stream;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shutdown)
+{
+  if (sctp_shutdown) {
+    /* A previously connected MME has been shutdown */
+
+    /* TODO check if it was used by some eNB and send a message to inform these eNB if there is no more associated MME */
+    if (mme_desc_p->state == S1AP_ENB_STATE_CONNECTED) {
+      mme_desc_p->state = S1AP_ENB_STATE_DISCONNECTED;
+
+      if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb > 0) {
+        /* Decrease associated MME number */
+        mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb --;
+      }
+
+      /* If there are no more associated MME, inform eNB app */
+      if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb == 0) {
+        MessageDef                 *message_p;
+
+        message_p = itti_alloc_new_message(TASK_S1AP, S1AP_DEREGISTERED_ENB_IND);
+        S1AP_DEREGISTERED_ENB_IND(message_p).nb_mme = 0;
+        itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p);
+      }
+    }
+  } else {
+    /* Check that at least one setup message is pending */
+    DevCheck(mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb > 0, mme_desc_p->s1ap_eNB_instance->instance,
+             mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb, 0);
+
+    if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb > 0) {
+      /* Decrease pending messages number */
+      mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb --;
+    }
+
+    /* If there are no more pending messages, inform eNB app */
+    if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb == 0) {
+      MessageDef                 *message_p;
+
+      message_p = itti_alloc_new_message(TASK_S1AP, S1AP_REGISTER_ENB_CNF);
+      S1AP_REGISTER_ENB_CNF(message_p).nb_mme = mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb;
+      itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p);
+    }
+  }
+}
+
+void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
+{
+  s1ap_eNB_instance_t *instance_p;
+  s1ap_eNB_mme_data_t *s1ap_mme_data_p;
+
+  DevAssert(sctp_new_association_resp != NULL);
+
+  instance_p = s1ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1,
+                                     sctp_new_association_resp->ulp_cnx_id);
+  DevAssert(s1ap_mme_data_p != NULL);
+
+  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+    S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+              sctp_new_association_resp->sctp_state,
+              instance,
+              sctp_new_association_resp->ulp_cnx_id);
+
+    s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+
+    return;
+  }
+
+  /* Update parameters */
+  s1ap_mme_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
+  s1ap_mme_data_p->in_streams  = sctp_new_association_resp->in_streams;
+  s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
+
+  /* Prepare new S1 Setup Request */
+  mme_test_s1_start_test(instance_p, s1ap_mme_data_p);
+}
+
+void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
+                                  net_ip_address_t    *mme_ip_address,
+                                  net_ip_address_t    *local_ip_addr)
+{
+  MessageDef                 *message_p                   = NULL;
+  sctp_new_association_req_t *sctp_new_association_req_p  = NULL;
+  s1ap_eNB_mme_data_t        *s1ap_mme_data_p             = NULL;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(mme_ip_address != NULL);
+
+  message_p = itti_alloc_new_message(TASK_S1AP, SCTP_NEW_ASSOCIATION_REQ);
+
+  sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req;
+
+  sctp_new_association_req_p->port = S1AP_PORT_NUMBER;
+  sctp_new_association_req_p->ppid = S1AP_SCTP_PPID;
+
+  memcpy(&sctp_new_association_req_p->remote_address,
+         mme_ip_address,
+         sizeof(*mme_ip_address));
+
+  memcpy(&sctp_new_association_req_p->local_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+
+  /* Create new MME descriptor */
+  s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p));
+  DevAssert(s1ap_mme_data_p != NULL);
+
+  s1ap_mme_data_p->cnx_id                = s1ap_eNB_fetch_add_global_cnx_id();
+  sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
+
+  s1ap_mme_data_p->assoc_id          = -1;
+  s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
+
+  STAILQ_INIT(&s1ap_mme_data_p->served_gummei);
+
+  /* Insert the new descriptor in list of known MME
+   * but not yet associated.
+   */
+  RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p);
+  s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
+  instance_p->s1ap_mme_nb ++;
+  instance_p->s1ap_mme_pending_nb ++;
+
+  itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
+}
+
+
+
+void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB)
+{
+  s1ap_eNB_instance_t *new_instance;
+  uint8_t index;
+
+  DevAssert(s1ap_register_eNB != NULL);
+
+  /* Look if the provided instance already exists */
+  new_instance = s1ap_eNB_get_instance(instance);
+
+  if (new_instance != NULL) {
+    /* Checks if it is a retry on the same eNB */
+    DevCheck(new_instance->eNB_id == s1ap_register_eNB->eNB_id, new_instance->eNB_id, s1ap_register_eNB->eNB_id, 0);
+    DevCheck(new_instance->cell_type == s1ap_register_eNB->cell_type, new_instance->cell_type, s1ap_register_eNB->cell_type, 0);
+    DevCheck(new_instance->tac == s1ap_register_eNB->tac, new_instance->tac, s1ap_register_eNB->tac, 0);
+    DevCheck(new_instance->mcc == s1ap_register_eNB->mcc, new_instance->mcc, s1ap_register_eNB->mcc, 0);
+    DevCheck(new_instance->mnc == s1ap_register_eNB->mnc, new_instance->mnc, s1ap_register_eNB->mnc, 0);
+    DevCheck(new_instance->mnc_digit_length == s1ap_register_eNB->mnc_digit_length, new_instance->mnc_digit_length, s1ap_register_eNB->mnc_digit_length, 0);
+    DevCheck(new_instance->default_drx == s1ap_register_eNB->default_drx, new_instance->default_drx, s1ap_register_eNB->default_drx, 0);
+  } else {
+    new_instance = calloc(1, sizeof(s1ap_eNB_instance_t));
+    DevAssert(new_instance != NULL);
+
+    RB_INIT(&new_instance->s1ap_ue_head);
+    RB_INIT(&new_instance->s1ap_mme_head);
+
+    /* Copy usefull parameters */
+    new_instance->instance         = instance;
+    new_instance->eNB_name         = s1ap_register_eNB->eNB_name;
+    new_instance->eNB_id           = s1ap_register_eNB->eNB_id;
+    new_instance->cell_type        = s1ap_register_eNB->cell_type;
+    new_instance->tac              = s1ap_register_eNB->tac;
+    new_instance->mcc              = s1ap_register_eNB->mcc;
+    new_instance->mnc              = s1ap_register_eNB->mnc;
+    new_instance->mnc_digit_length = s1ap_register_eNB->mnc_digit_length;
+    new_instance->default_drx      = s1ap_register_eNB->default_drx;
+
+    /* Add the new instance to the list of eNB (meaningfull in virtual mode) */
+    s1ap_eNB_insert_new_instance(new_instance);
+
+    S1AP_DEBUG("Registered new eNB[%d] and %s eNB id %u\n",
+               instance,
+               s1ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
+               s1ap_register_eNB->eNB_id);
+  }
+
+  DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS,
+           S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0);
+
+  /* Trying to connect to provided list of MME ip address */
+  for (index = 0; index < s1ap_register_eNB->nb_mme; index++) {
+    s1ap_eNB_register_mme(new_instance, &s1ap_register_eNB->mme_ip_address[index],
+                          &s1ap_register_eNB->enb_ip_address);
+  }
+}
+
+
+
+
+void *s1ap_eNB_task(void *arg)
+{
+  MessageDef *received_msg = NULL;
+  int         result;
+
+  S1AP_DEBUG("Starting S1AP layer\n");
+
+  s1ap_eNB_prepare_internal_data();
+
+  itti_mark_task_ready(TASK_S1AP);
+
+  while (1) {
+    itti_receive_msg(TASK_S1AP, &received_msg);
+
+    switch (ITTI_MSG_ID(received_msg)) {
+    case TERMINATE_MESSAGE:
+      itti_exit_task();
+      break;
+
+    case S1AP_REGISTER_ENB_REQ: {
+      /* Register a new eNB.
+       * in Virtual mode eNBs will be distinguished using the mod_id/
+       * Each eNB has to send an S1AP_REGISTER_ENB message with its
+       * own parameters.
+       */
+      s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                   &S1AP_REGISTER_ENB_REQ(received_msg));
+    }
+    break;
+
+    case SCTP_NEW_ASSOCIATION_RESP: {
+      s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                            &received_msg->ittiMsg.sctp_new_association_resp);
+    }
+    break;
+
+    case SCTP_DATA_IND: {
+      s1ap_eNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind);
+    }
+    break;
+
+
+
+    default:
+      S1AP_ERROR("Received unhandled message: %d:%s\n",
+                 ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
+      break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+
+    received_msg = NULL;
+  }
+
+  return NULL;
+}
diff --git a/openair-cn/TEST/oaisim_mme_test_s1c_s1ap.h b/openair-cn/TEST/oaisim_mme_test_s1c_s1ap.h
new file mode 100755
index 00000000000..43d2681c9a2
--- /dev/null
+++ b/openair-cn/TEST/oaisim_mme_test_s1c_s1ap.h
@@ -0,0 +1,60 @@
+/*******************************************************************************
+    OpenAirInterface
+    Copyright(c) 1999 - 2014 Eurecom
+
+    OpenAirInterface is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+
+    OpenAirInterface is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenAirInterface.The full GNU General Public License is
+    included in this distribution in the file called "COPYING". If not,
+    see <http://www.gnu.org/licenses/>.
+
+   Contact Information
+   OpenAirInterface Admin: openair_admin@eurecom.fr
+   OpenAirInterface Tech : openair_tech@eurecom.fr
+   OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+
+   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+*******************************************************************************/
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <linux/sched.h>
+#include <signal.h>
+#include <execinfo.h>
+#include <getopt.h>
+#include <syscall.h>
+
+void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind);
+
+void s1ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shutdown);
+
+void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
+
+void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
+                                  net_ip_address_t    *mme_ip_address,
+                                  net_ip_address_t    *local_ip_addr);
+void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB);
+void *s1ap_eNB_task(void *arg);
diff --git a/openair-cn/TEST/oaisim_mme_test_s1c_scenario.c b/openair-cn/TEST/oaisim_mme_test_s1c_scenario.c
new file mode 100755
index 00000000000..416ac999042
--- /dev/null
+++ b/openair-cn/TEST/oaisim_mme_test_s1c_scenario.c
@@ -0,0 +1,286 @@
+/*******************************************************************************
+    OpenAirInterface
+    Copyright(c) 1999 - 2014 Eurecom
+
+    OpenAirInterface is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+
+    OpenAirInterface is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenAirInterface.The full GNU General Public License is
+    included in this distribution in the file called "COPYING". If not,
+    see <http://www.gnu.org/licenses/>.
+
+   Contact Information
+   OpenAirInterface Admin: openair_admin@eurecom.fr
+   OpenAirInterface Tech : openair_tech@eurecom.fr
+   OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+
+   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+*******************************************************************************/
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "oaisim_mme_test_s1c_scenario.h"
+
+int        scenario_index         = 0;
+int        scenario_message_index = 0;
+int        debug                  = 0;
+int        error_count            = 0;
+int        break_on_error         = 0;
+
+
+extern s1ap_message_test_t s1ap_scenario1[];
+
+s1ap_message_test_t s1ap_scenarios[][] = {s1ap_scenario1};
+
+/* -1 means invalid */
+static const signed char hex_digits[0x100] = {
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
+  -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+};
+
+//------------------------------------------------------------------------------
+void
+fail (const char *format, ...)
+//------------------------------------------------------------------------------
+{
+  char str[1024];
+  va_list arg_ptr;
+
+  va_start (arg_ptr, format);
+  vsnprintf ( str, sizeof(str), format, arg_ptr);
+  va_end (arg_ptr);
+  fputs(str, stderr);
+  error_count++;
+
+  if (break_on_error)
+    exit (1);
+}
+
+//------------------------------------------------------------------------------
+void
+success (const char *format, ...)
+//------------------------------------------------------------------------------
+{
+  char str[1024];
+  va_list arg_ptr;
+
+  va_start (arg_ptr, format);
+  vsnprintf ( str, sizeof(str), format, arg_ptr);
+  va_end (arg_ptr);
+  fputs(str, stderr);
+}
+
+//------------------------------------------------------------------------------
+void
+escapeprint (const char *str, size_t len)
+//------------------------------------------------------------------------------
+{
+  size_t i;
+
+  printf (" (length %d bytes):\n\t", (int) len);
+
+  for (i = 0; i < len; i++) {
+    if (((str[i] & 0xFF) >= 'A' && (str[i] & 0xFF) <= 'Z') ||
+        ((str[i] & 0xFF) >= 'a' && (str[i] & 0xFF) <= 'z') ||
+        ((str[i] & 0xFF) >= '0' && (str[i] & 0xFF) <= '9')
+        || (str[i] & 0xFF) == ' ' || (str[i] & 0xFF) == '.')
+      printf ("%c", (str[i] & 0xFF));
+    else
+      printf ("\\x%02X", (str[i] & 0xFF));
+
+    if ((i + 1) % 16 == 0 && (i + 1) < len)
+      printf ("'\n\t'");
+  }
+
+  printf ("\n");
+}
+
+//------------------------------------------------------------------------------
+void
+hexprint (const void *_str, size_t len)
+//------------------------------------------------------------------------------
+{
+  size_t i;
+  const char* str = _str;
+
+  printf ("\t;; ");
+
+  for (i = 0; i < len; i++) {
+    printf ("%02x ", (str[i] & 0xFF));
+
+    if ((i + 1) % 8 == 0)
+      printf (" ");
+
+    if ((i + 1) % 16 == 0 && i + 1 < len)
+      printf ("\n\t;; ");
+  }
+
+  printf ("\n");
+}
+
+//------------------------------------------------------------------------------
+void
+binprint (const void *_str, size_t len)
+//------------------------------------------------------------------------------
+{
+  size_t i;
+  const char* str = _str;
+
+  printf ("\t;; ");
+
+  for (i = 0; i < len; i++) {
+    printf ("%d%d%d%d%d%d%d%d ",
+            (str[i] & 0xFF) & 0x80 ? 1 : 0,
+            (str[i] & 0xFF) & 0x40 ? 1 : 0,
+            (str[i] & 0xFF) & 0x20 ? 1 : 0,
+            (str[i] & 0xFF) & 0x10 ? 1 : 0,
+            (str[i] & 0xFF) & 0x08 ? 1 : 0,
+            (str[i] & 0xFF) & 0x04 ? 1 : 0,
+            (str[i] & 0xFF) & 0x02 ? 1 : 0, (str[i] & 0xFF) & 0x01 ? 1 : 0);
+
+    if ((i + 1) % 3 == 0)
+      printf (" ");
+
+    if ((i + 1) % 6 == 0 && i + 1 < len)
+      printf ("\n\t;; ");
+  }
+
+  printf ("\n");
+}
+
+//------------------------------------------------------------------------------
+int
+compare_buffer(const uint8_t *buffer, const uint32_t length_buffer,
+               const uint8_t *pattern, const uint32_t length_pattern)
+//------------------------------------------------------------------------------
+{
+  int i;
+
+  if (length_buffer != length_pattern) {
+    printf("Length mismatch, expecting %d bytes, got %d bytes\n", length_pattern,
+           length_buffer);
+    hexprint(buffer, length_buffer);
+    return -1;
+  }
+
+  for (i = 0; i < length_buffer; i++) {
+    if (pattern[i] != buffer[i]) {
+      printf("Expecting:\n");
+      hexprint(pattern, length_pattern);
+      printf("Received:\n");
+      hexprint(buffer, length_buffer);
+      printf("Mismatch fount in byte %d\nExpecting 0x%02x, got 0x%02x\n",
+             i, pattern[i], buffer[i]);
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+//------------------------------------------------------------------------------
+unsigned
+decode_hex_length(const char *h)
+//------------------------------------------------------------------------------
+{
+  const unsigned char *hex = (const unsigned char *) h;
+  unsigned count;
+  unsigned i;
+
+  for (count = i = 0; hex[i]; i++) {
+    if (isspace(hex[i]))
+      continue;
+
+    if (hex_digits[hex[i]] < 0)
+      abort();
+
+    count++;
+  }
+
+  if (count % 2)
+    abort();
+
+  return count / 2;
+}
+
+//------------------------------------------------------------------------------
+int
+decode_hex(uint8_t *dst, const char *h)
+//------------------------------------------------------------------------------
+{
+  const unsigned char *hex = (const unsigned char *) h;
+  unsigned i = 0;
+
+  for (;;) {
+    int high, low;
+
+    while (*hex && isspace(*hex))
+      hex++;
+
+    if (!*hex)
+      return 1;
+
+    high = hex_digits[*hex++];
+
+    if (high < 0)
+      return 0;
+
+    while (*hex && isspace(*hex))
+      hex++;
+
+    if (!*hex)
+      return 0;
+
+    low = hex_digits[*hex++];
+
+    if (low < 0)
+      return 0;
+
+    dst[i++] = (high << 4) | low;
+  }
+}
+
+//------------------------------------------------------------------------------
+uint8_t *
+decode_hex_dup(const char *hex)
+//------------------------------------------------------------------------------
+{
+  uint8_t *p;
+  unsigned length = decode_hex_length(hex);
+
+  p = malloc(length * sizeof(uint8_t));
+
+  if (decode_hex(p, hex))
+    return p;
+  else {
+    free(p);
+    return NULL;
+  }
+}
+
-- 
GitLab