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 0000000000..6a3e61091f
--- /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 .
+#
+# 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 0000000000..a46c8fa6b4
--- /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 .
+
+ 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#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 0000000000..43d2681c9a
--- /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 .
+
+ 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+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 0000000000..416ac99904
--- /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 .
+
+ 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
+#include
+#include
+#include
+
+#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;
+ }
+}
+