diff --git a/configure.ac b/configure.ac index 366793a09..84807c034 100644 --- a/configure.ac +++ b/configure.ac @@ -466,6 +466,7 @@ AC_CONFIG_FILES([support/logrotate/Makefile]) AC_CONFIG_FILES([support/newsyslog/nextepc.conf]) AC_CONFIG_FILES([support/newsyslog/Makefile]) AC_CONFIG_FILES([support/Makefile]) +AC_CONFIG_FILES([test/rx/Makefile]) AC_CONFIG_FILES([test/Makefile]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/test/Makefile.am b/test/Makefile.am index 6cc888652..d8ae221f4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,5 +1,7 @@ ## Process this file with automake to produce Makefile.in. +SUBDIRS = rx + bin_PROGRAMS = testepc testepc_SOURCES = \ diff --git a/test/rx/Makefile.am b/test/rx/Makefile.am new file mode 100644 index 000000000..2e36e876a --- /dev/null +++ b/test/rx/Makefile.am @@ -0,0 +1,31 @@ +## Process this file with automake to produce Makefile.in. + +bin_PROGRAMS = testrx + +testrx_SOURCES = \ + abts.h abts_tests.h testutil.h \ + abts.c testutil.c testpacket.h testpacket.c \ + volte_test.c \ + $(NULL) + +testrx_LDADD = \ + $(top_srcdir)/src/libepc.la \ + $(NULL) + +AM_CPPFLAGS = \ + -I$(top_srcdir)/lib/core/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/lib/s1ap/asn1c \ + -I$(top_srcdir)/lib/@FREEDIAMETER_DIR@/include \ + @MONGOC_CFLAGS@ \ + $(NULL) + +AM_CFLAGS = \ + -Wall -Werror \ + -Wno-unused-function -Wno-unused-variable \ + @OSCPPFLAGS@ \ + $(NULL) + +MAINTAINERCLEANFILES = Makefile.in +MOSTLYCLEANFILES = core *.stackdump diff --git a/test/rx/abts.c b/test/rx/abts.c new file mode 100644 index 000000000..d9d0d0d7f --- /dev/null +++ b/test/rx/abts.c @@ -0,0 +1,501 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "abts.h" +#include "abts_tests.h" +#include "testutil.h" + +#include "core_debug.h" +#include "core_pkbuf.h" + +#define ABTS_STAT_SIZE 6 +static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'}; +static int curr_char; +static int verbose = 1; +static int exclude = 0; +static int quiet = 0; +static int list_tests = 0; +int test_only_control_plane = 0; + +const char **testlist = NULL; + +static int find_test_name(const char *testname) { + int i; + for (i = 0; testlist[i] != NULL; i++) { + if (!strcmp(testlist[i], testname)) { + return 1; + } + } + return 0; +} + +/* Determine if the test should be run at all */ +static int should_test_run(const char *testname) { + int found = 0; + if (list_tests == 1) { + return 0; + } + if (testlist == NULL) { + return 1; + } + found = find_test_name(testname); + if ((found && !exclude) || (!found && exclude)) { + return 1; + } + return 0; +} + +static void reset_status(void) +{ + curr_char = 0; +} + +static void update_status(void) +{ + if (!quiet) { + curr_char = (curr_char + 1) % ABTS_STAT_SIZE; + fprintf(stdout, "\b%c", status[curr_char]); + fflush(stdout); + } +} + +static void end_suite(abts_suite *suite) +{ + if (suite != NULL) { + sub_suite *last = suite->tail; + if (!quiet) { + fprintf(stdout, "\b"); + fflush(stdout); + } + if (last->failed == 0) { + fprintf(stdout, "SUCCESS\n"); + fflush(stdout); + } + else { + fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test); + fflush(stdout); + } + } +} + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full) +{ + sub_suite *subsuite; + char *p; + const char *suite_name; + curr_char = 0; + + /* Only end the suite if we actually ran it */ + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + subsuite = core_malloc(sizeof(*subsuite)); + subsuite->num_test = 0; + subsuite->failed = 0; + subsuite->next = NULL; + /* suite_name_full may be an absolute path depending on __FILE__ + * expansion */ + suite_name = strrchr(suite_name_full, '/'); + if (suite_name) { + suite_name++; + } else { + suite_name = suite_name_full; + } + p = strrchr(suite_name, '.'); + if (p) { + subsuite->name = memcpy(core_calloc(p - suite_name + 1, 1), + suite_name, p - suite_name); + } + else { + subsuite->name = suite_name; + } + + if (list_tests) { + fprintf(stdout, "%s\n", subsuite->name); + } + + subsuite->not_run = 0; + + if (suite == NULL) { + suite = core_malloc(sizeof(*suite)); + suite->head = subsuite; + suite->tail = subsuite; + } + else { + suite->tail->next = subsuite; + suite->tail = subsuite; + } + + if (!should_test_run(subsuite->name)) { + subsuite->not_run = 1; + return suite; + } + + reset_status(); + fprintf(stdout, "%-20s: ", subsuite->name); + update_status(); + fflush(stdout); + + return suite; +} + +void abts_run_test(abts_suite *ts, test_func f, void *value) +{ + abts_case tc; + sub_suite *ss; + + if (!should_test_run(ts->tail->name)) { + return; + } + ss = ts->tail; + + tc.failed = 0; + tc.suite = ss; + + ss->num_test++; + update_status(); + + f(&tc, value); + + if (tc.failed) { + ss->failed++; + } +} + +static int report(abts_suite *suite) +{ + int count = 0; + sub_suite *dptr; + + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + for (dptr = suite->head; dptr; dptr = dptr->next) { + count += dptr->failed; + } + + if (list_tests) { + return 0; + } + + if (count == 0) { + printf("All tests passed.\n"); + return 0; + } + + dptr = suite->head; + fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); + fprintf(stdout, "===================================================\n"); + while (dptr != NULL) { + if (dptr->failed != 0) { + float percent = ((float)dptr->failed / (float)dptr->num_test); + fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, + dptr->num_test, dptr->failed, percent * 100); + } + dptr = dptr->next; + } + return 1; +} + +static void abts_free(abts_suite *suite) +{ + sub_suite *ptr = NULL, *next_ptr = NULL; + + ptr = suite->head; + while (ptr != NULL) { + next_ptr = ptr->next; + + core_free((void*)ptr->name); + core_free(ptr); + ptr = next_ptr; + } + + core_free(suite); +} + +void abts_log_message(const char *fmt, ...) +{ + va_list args; + update_status(); + + if (verbose) { + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + fflush(stderr); + } +} + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected != actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = TRUE; + if (verbose) { + /* Note that the comparison is type-exact, reporting must be a best-fit */ + fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno, + (unsigned long)expected, (unsigned long)actual); + fflush(stderr); + } +} + +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!expected && !actual) return; + if (expected && actual) + if (!strcmp(expected, actual)) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!strncmp(expected, actual, n)) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_ptr_null(abts_case *tc, const void *ptr, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (ptr == NULL) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: Expected NULL, but saw <%p>\n", lineno, ptr); + fflush(stderr); + } +} + +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (ptr != NULL) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: Expected not NULL, but saw <%p>\n", lineno, ptr); + fflush(stderr); + } +} + +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_fail(abts_case *tc, const char *message, int lineno) +{ + update_status(); + if (tc->failed) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_assert(abts_case *tc, const char *message, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (condition) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_true(abts_case *tc, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (condition) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno); + fflush(stderr); + } +} + +void abts_false(abts_case *tc, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!condition) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: Condition is true, but expected false\n", lineno); + fflush(stderr); + } +} + +void abts_not_impl(abts_case *tc, const char *message, int lineno) +{ + update_status(); + + tc->suite->not_impl++; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +int main(int argc, const char *const argv[]) { + int i; + int rv; + int list_provided = 0; + abts_suite *suite = NULL; + const char *config_path = NULL; + + d_trace_global_off(); + d_log_set_level(D_MSG_TO_STDOUT, D_LOG_LEVEL_ERROR); + + quiet = !isatty(STDOUT_FILENO); + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-v")) { + verbose = 1; + continue; + } + if (!strcmp(argv[i], "-x")) { + exclude = 1; + continue; + } + if (!strcmp(argv[i], "-l")) { + list_tests = 1; + continue; + } + if (!strcmp(argv[i], "-q")) { + quiet = 1; + continue; + } + if (!strcmp(argv[i], "-t")) { + d_trace_global_on(); + d_log_set_level(D_MSG_TO_STDOUT, D_LOG_LEVEL_FULL); + continue; + } + if (!strcmp(argv[i], "-f")) { + config_path = argv[++i]; + continue; + } + if (!strcmp(argv[i], "-c")) { + test_only_control_plane = 1; + continue; + } + if (argv[i][0] == '-') { + fprintf(stderr, "Invalid option: `%s'\n", argv[i]); + exit(1); + } + list_provided = 1; + } + + rv = test_initialize((char*)config_path); + if (rv != CORE_OK) + return EXIT_FAILURE; + + if (list_provided) { + /* Waste a little space here, because it is easier than counting the + * number of tests listed. Besides it is at most three char *. + */ + testlist = core_calloc(argc + 1, sizeof(char *)); + for (i = 1; i < argc; i++) { + testlist[i - 1] = argv[i]; + } + } + + for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) { + suite = alltests[i].func(suite); + } + + rv = report(suite); + + abts_free(suite); + + core_free(testlist); + return rv; +} + diff --git a/test/rx/abts.h b/test/rx/abts.h new file mode 100644 index 000000000..211805077 --- /dev/null +++ b/test/rx/abts.h @@ -0,0 +1,112 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif + +#ifndef ABTS_H +#define ABTS_H + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +struct sub_suite { + const char *name; + int num_test; + int failed; + int not_run; + int not_impl; + struct sub_suite *next; +}; +typedef struct sub_suite sub_suite; + +struct abts_suite { + sub_suite *head; + sub_suite *tail; +}; +typedef struct abts_suite abts_suite; + +struct abts_case { + int failed; + sub_suite *suite; +}; +typedef struct abts_case abts_case; + +typedef void (*test_func)(abts_case *tc, void *data); + +#define ADD_SUITE(suite) abts_add_suite(suite, __FILE__); + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name); +void abts_run_test(abts_suite *ts, test_func f, void *value); +void abts_log_message(const char *fmt, ...); + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno); +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno); +void abts_ptr_null(abts_case *tc, const void *ptr, int lineno); +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno); +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno); +void abts_true(abts_case *tc, int condition, int lineno); +void abts_false(abts_case *tc, int condition, int lineno); +void abts_fail(abts_case *tc, const char *message, int lineno); +void abts_not_impl(abts_case *tc, const char *message, int lineno); +void abts_assert(abts_case *tc, const char *message, int condition, int lineno); +void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno); + +/* Convenience macros. Ryan hates these! */ +#define ABTS_INT_EQUAL(a, b, c) abts_int_equal(a, b, c, __LINE__) +#define ABTS_INT_NEQUAL(a, b, c) abts_int_nequal(a, b, c, __LINE__) +#define ABTS_STR_EQUAL(a, b, c) abts_str_equal(a, b, c, __LINE__) +#define ABTS_STR_NEQUAL(a, b, c, d) abts_str_nequal(a, b, c, d, __LINE__) +#define ABTS_PTR_NULL(a, b) abts_ptr_null(a, b, __LINE__) +#define ABTS_PTR_NOTNULL(a, b) abts_ptr_notnull(a, b, __LINE__) +#define ABTS_PTR_EQUAL(a, b, c) abts_ptr_equal(a, b, c, __LINE__) +#define ABTS_TRUE(a, b) abts_true(a, b, __LINE__); +#define ABTS_FALSE(a, b) abts_false(a, b, __LINE__); +#define ABTS_FAIL(a, b) abts_fail(a, b, __LINE__); +#define ABTS_NOT_IMPL(a, b) abts_not_impl(a, b, __LINE__); +#define ABTS_ASSERT(a, b, c) abts_assert(a, b, c, __LINE__); + +#define ABTS_SIZE_EQUAL(a, b, c) abts_size_equal(a, b, c, __LINE__) + + +abts_suite *run_tests(abts_suite *suite); +abts_suite *run_tests1(abts_suite *suite); + + +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/test/rx/abts_tests.h b/test/rx/abts_tests.h new file mode 100644 index 000000000..7323d0299 --- /dev/null +++ b/test/rx/abts_tests.h @@ -0,0 +1,29 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_TEST_INCLUDES +#define APR_TEST_INCLUDES + +#include "abts.h" +#include "testutil.h" + +const struct testlist { + abts_suite *(*func)(abts_suite *suite); +} alltests[] = { + {test_volte}, +}; + +#endif /* APR_TEST_INCLUDES */ diff --git a/test/rx/testpacket.c b/test/rx/testpacket.c new file mode 100644 index 000000000..41c0cd79f --- /dev/null +++ b/test/rx/testpacket.c @@ -0,0 +1,1986 @@ +#define TRACE_MODULE _testpacket + +#include "core_debug.h" +#include "core_lib.h" + +#include "mme/s1ap_build.h" +#include "mme/s1ap_conv.h" +#include "mme/s1ap_path.h" + +#include "gtp/gtp_message.h" +#include "gtp/gtp_conv.h" +#include "gtp/gtp_node.h" +#include "gtp/gtp_path.h" + +#include "app/context.h" +#include "mme/mme_context.h" + +extern int test_only_control_plane; + +#define TEST_ENB_ADDR "127.0.0.5" +#if LINUX == 1 +#define TEST_ENB_ADDR6 "fe80::1%lo" +#else +#define TEST_ENB_ADDR6 "fe80::1%lo0" +#endif +static c_sockaddr_t *test_enb_addr = NULL; +static c_sockaddr_t *test_enb_addr6 = NULL; + +status_t testpacket_init() +{ + status_t rv; + + rv = core_getaddrinfo(&test_enb_addr, + AF_INET, TEST_ENB_ADDR, GTPV1_U_UDP_PORT, 0); + d_assert(rv == CORE_OK, return CORE_ERROR,); + +/* There is no default link-local address, + * If you want to test it, you need set the IPv6 address in some interface */ +#if LINUX != 1 + rv = core_getaddrinfo(&test_enb_addr6, + AF_INET6, TEST_ENB_ADDR6, GTPV1_U_UDP_PORT, 0); + d_assert(rv == CORE_OK, return CORE_ERROR,); +#endif + + return CORE_OK; +} + +status_t testpacket_final() +{ + if (test_enb_addr) + { + core_freeaddrinfo(test_enb_addr); + test_enb_addr = NULL; + } + if (test_enb_addr6) + { + core_freeaddrinfo(test_enb_addr6); + test_enb_addr6 = NULL; + } + + return CORE_OK; +} + +status_t tests1ap_enb_connect(sock_id *new) +{ + status_t rv; + sock_node_t *snode = NULL; + + snode = list_first(&mme_self()->s1ap_list); + if (!snode) snode = list_first(&mme_self()->s1ap_list6); + d_assert(snode, return CORE_ERROR,); + + rv = sctp_client(new, SOCK_STREAM, snode->list); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + return CORE_OK; +} + +status_t tests1ap_enb_close(sock_id id) +{ + return s1ap_delete(id); +} + +status_t tests1ap_enb_read(sock_id id, pkbuf_t *recvbuf) +{ + return s1ap_recv(id, recvbuf); +} + +status_t tests1ap_enb_send(sock_id id, pkbuf_t *sendbuf) +{ + return s1ap_send(id, sendbuf, NULL); +} + +status_t tests1ap_build_setup_req( + pkbuf_t **pkbuf, S1ap_ENB_ID_PR present, c_uint32_t enb_id) +{ + int erval = -1; + int tac = 12345; + + s1ap_message_t message; + S1ap_S1SetupRequestIEs_t *ies; + S1ap_PLMNidentity_t *plmnIdentity; + S1ap_SupportedTAs_Item_t *supportedTA; + + memset(&message, 0, sizeof(s1ap_message_t)); + + ies = &message.s1ap_S1SetupRequestIEs; + + s1ap_uint32_to_ENB_ID(present, enb_id, &ies->global_ENB_ID.eNB_ID); + s1ap_buffer_to_OCTET_STRING(&mme_self()->served_gummei[0].plmn_id[0], + PLMN_ID_LEN, &ies->global_ENB_ID.pLMNidentity); + + supportedTA = (S1ap_SupportedTAs_Item_t *) + core_calloc(1, sizeof(S1ap_SupportedTAs_Item_t)); + if (mme_self()->served_tai[0].list2.tai[0].tac) + tac = mme_self()->served_tai[0].list2.tai[0].tac; + else + tac = mme_self()->served_tai[0].list0.tai[0].tac[0]; + s1ap_uint16_to_OCTET_STRING(tac, &supportedTA->tAC); + plmnIdentity = (S1ap_PLMNidentity_t *) + core_calloc(1, sizeof(S1ap_PLMNidentity_t)); + s1ap_buffer_to_OCTET_STRING(&mme_self()->served_gummei[0].plmn_id[0], + PLMN_ID_LEN, plmnIdentity); + ASN_SEQUENCE_ADD(&supportedTA->broadcastPLMNs, plmnIdentity); + + ASN_SEQUENCE_ADD(&ies->supportedTAs, supportedTA); + + ies->defaultPagingDRX = S1ap_PagingDRX_v64; + + message.direction = S1AP_PDU_PR_initiatingMessage; + message.procedureCode = S1ap_ProcedureCode_id_S1Setup; + + erval = s1ap_encode_pdu(pkbuf, &message); + s1ap_free_pdu(&message); + + if (erval < 0) + { + d_error("s1ap_encode_error : (%d)", erval); + return CORE_ERROR; + } + + return CORE_OK; +} + +#define TESTS1AP_MAX_MESSAGE 32 + +status_t tests1ap_build_initial_ue_msg(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000c405800000500 0800020001001a00 302f177ca0b38802 0741020809101010" + "3254869104e060c0 4000050221d031d1 5c0a003103e5e034 9011035758a65d01" + "00004300060000f1 1030390064400800 00f1101079baf000 86400130", + + "000c40809c00" + "0005000800030002 00001a0073721711 a73a12070741020b f600f11000020100" + "00000105e060c040 0100210221d011d1 271a808021100100 0010810600000000" + "830600000000000d 00000a005255f501 10225c0a003103e5 c03e1355f501aaaa" + "11035758a6200b60 1404ef65233b8878 d290400804026004 00021f025d0107e0" + "004300060000f110 3039006440080055 f5010019d0100086 400130", + + "000c40809c00" + "0005000800030001 00001a007372178c 3e3cff070741020b f600f11000020100" + "00000905e060c040 0100210204d011d1 271a808021100100 0010810600000000" + "830600000000000d 00000a005255f501 10225c0a003103e5 c03e1355f501aaaa" + "11035758a6200b60 1404ef65233b8878 d290400804026004 00021f025d0107e0" + "004300060000f110 3039006440080055 f5010019d0100086 400130", + + + "000c406800000500 080002001f001a00 403f074172080910 10103254866202e0" + "600021023cd011d1 271a808021100100 0010810600000000 830600000000000d" + "00000a005c0a0090 11034f18a6f15d01 00004300060000f1 1030390064400800" + "00f110002343d000 86400130", + + "000c405300000500 080003001100001a 002a2917acba67c4 8207410108091010" + "103254866205f0f0 000000000e023cd0 11d1270780000a00 000d00c100430006" + "0000f11030390064 40080000f1109d67 aa500086400130", + + "000c405300000500 080003002100001a 002a2917bcba67c4 8207410108091010" + "000000003005f0f0 000000000e023cd0 11d1270780000a00 000d00c100430006" + "0000f11030390064 40080000f1109d67 aa500086400130", + + + "000c" + "404c000005000800 020002001a002423 0741710809101010 3254767905f0f000" + "0000000e0201d011 d1270780000a0000 0d00c10043000600 00f1103039006440" + "080000f11054f640 100086400130", + "", + "000c" + "4070000005000800 020001001a004847 0741720809101000 0000002004f07000" + "000023020ed03127 1d80802110010000 1081060000000083 0600000000000d00" + "000300000a005c0a 003103e5e0349011 035758a65d010000 4300060000f11030" + "39006440080000f1 100019b010008640 0130", + + "000c" + "4068000005000800 020001001a00403f 0741720809101010 3254861002e06000" + "210207d011d1271a 8080211001000010 8106000000008306 00000000000d0000" + "0a005c0a00901103 4f18a6f15d010000 4300060000f11030 39006440080000f1" + "1004615380008640 0130", + + "000c" + "4080830000060008 0002000c001a0050 4f1744b524490507 41020bf600f11000" + "0201010003e802e0 6000210204d011d1 271a808021100100 0010810600000000" + "830600000000000d 00000a005200f110 30395c0a00901103 4f18a6f15d0100e0" + "004300060000f110 3039006440080000 f110001f20a00086 400130004b000700" + "00f110000201", + + "", + + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 92, + 161, + 161, + + 108, + 87, + 87, + + 80, + 0, + 116, + + 108, + 136, + 0, + + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_identity_response(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "", + "", + "000d" + "403f000005000000 05c00100009f0008 0003000100001a00 121117d7e3248b57" + "0756080910101032 5486510064400800 00f11054f6401000 4340060000f1105b" + "a0", + + "", + "", + "", + + "", + "", + "", + + "", + "000d" + "403e000005000000 05c0020000c40008 0002000c001a0012 1117c07eb5f50607" + "5608091010103254 8651006440080000 f110001f20a00043 40060000f1103039", + }; + + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 0, + 0, + 67, + + 0, + 0, + 0, + + 0, + 0, + 0, + + 0, + 66, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_authentication_response(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d403e00000500 000005c00100009d 000800020001001a 001211177c0bca9d" + "030753086a91970e 838fd07900644008 0000f1101079baf0 004340060000f110" + "5ba0", + "", + "", + + "000d403500000500 0000020001000800 02001f001a000c0b 07530831c964f076" + "1378760064400800 00f110002343d000 4340060000f11030 39", + "", + "", + + "000d" + "4038000005000000 05c0020000c80008 00020002001a000c 0b0753087dc78e7c" + "421f9eb900644008 0000f11054f64010 004340060000f110 2b67", + "", + "000d" + "4035000005000000 0200010008000200 01001a000c0b0753 08d8b388ddacaa1f" + "36006440080000f1 100019b010004340 060000f1100001", + + + "000d" + "4038000005000000 05c0010001da0008 00020001001a000c 0b0753084ce11ef1" + "24b1854500644008 0000f11004615380 004340060000f110 5ba0", + + "000d" + "403e000005000000 05c0020000c40008 0002000c001a0012 1117deff957c0707" + "5308e3b925330735 7093006440080000 f110001f20a00043 40060000f1103039", + + }; + + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 66, + 0, + 0, + + 57, + 0, + 0, + + 60, + 0, + 57, + + 60, + 66, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + + +status_t tests1ap_build_authentication_failure(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "", + "", + "", + + "", + "", + "000d" + "403d000005000000 0200030008000200 21001a001413075c 15300e 61640edcfb" + "605d25911423ee1f 9e006440080000f1 100019b010004340 060000f1100001", + + "", + "", + "", + + "", + "", + "", + + }; + + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 0, + 0, + 0, + + 0, + 0, + 65, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_security_mode_complete(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d403500000500 000005c00100009d 000800020001001a 000908476b8f5f64" + "00075e0064400800 00f1101079baf000 4340060000f1105b a0", + "", + "", + + "000d403200000500 0000020001000800 02001f001a000908 473c0c819e00075e" + "006440080000f110 002343d000434006 0000f1103039", + "", + "", + + "000d" + "4035000005000000 05c0020000c80008 00020002001a0009 0847c0eb1eb80007" + "5e006440080000f1 1054f64010004340 060000f1102b67", + "", + "000d" + "4032000005000000 0200010008000200 01001a00090847c8 38f8d700075e0064" + "40080000f1100019 b010004340060000 f1100001", + + + "000d" + "4035000005000000 05c0010001da0008 00020001001a0009 0847d3b0ef030007" + "5e006440080000f1 1004615380004340 060000f1105ba0", + + "000d" + "4035000005000000 05c0020000c40008 0002000c001a0009 084790282df90007" + "5e006440080000f1 10001f20a0004340 060000f1103039", + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 57, + 0, + 0, + + 54, + 0, + 0, + + 57, + 0, + 54, + + 57, + 57, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_esm_information_response(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d40808d000005 00000005c0010000 9d00080002000100 1a006160275c0667" + "58010221da280908 696e7465726e6574 274a80c223150100 001510c09a2626c0" + "9a2626c09a2626c0 9a2626c223150200 0015103d3dda5c72 4cc497354ae64653" + "45a8088021100100 0010810600000000 830600000000000d 00000a0000644008" + "0000f1101079baf0 004340060000f110 5ba0", + "000d40808d000005 00000005c0010000 9d00080002000100 1a00616027c963b5" + "1b010221da280908 696e7465726e6574 274a80c223150100 001510c09a2626c0" + "9a2626c09a2626c0 9a2626c223150200 0015103d3dda5c72 4cc497354ae64653" + "45a8088021100100 0010810600000000 830600000000000d 00000a0000644008" + "0000f1101079baf0 004340060000f110 5ba0", + "", + + "000d403e00000500 0000020001000800 02001f001a001514 27505a0b5301023c" + "da280908696e7465 726e657400644008 0000f110002343d0 004340060000f110" + "3039", + "000d403e00000500 0000020001000800 02001f001a001514 27b531c64f01023c" + "da280908696e7465 726e657400644008 0000f110002343d0 004340060000f110" + "3039", + "", + + "000d" + "4041000005000000 05c0020000c80008 00020002001a0015 142793b2bedc0102" + "01da280908696e74 65726e6574006440 080000f11054f640 10004340060000f1" + "102b67", + "", + "", + + + "000d" + "4041000005000000 05c0010001da0008 00020001001a0015 14279a2476c80102" + "07da280908696e74 65726e6574006440 080000f110046153 80004340060000f1" + "105ba0", + + "000d" + "4041000005000000 05c0020000c40008 0002000c001a0015 14274f280bff0102" + "04da280908696e74 65726e6574006440 080000f110001f20 a0004340060000f1" + "103039", + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 146, + 146, + 0, + + 66, + 66, + 0, + + 69, + 0, + 0, + + 69, + 69, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_ue_capability_info_indication(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "0016" + "40809c0000030000 0005c00100009d00 0800020001004a40 8085808304040003" + "04ec598007000820 81839b4e1e3ff8ff f1ffc7ff8ffe3ffc 7ff1ffe3ff8fff1f" + "fc7ff8ffe3ffc7ff 1ffdfd3ffa7a2060 090e194e9525c8c2 fd80000000e03fe7" + "ff5f60000000384f e9ffd3d800000002 1033035758a66014 042f6513b8800d2f" + "0831c1a53432b259 ef989007000cdd9c 6331200e0019a332 c662401c003200", + "", + "", + + "0016402d00000300 0000020001000800 02001f004a401a19 00b801014c598080" + "9c000bf06ec4d001 40302c0000000000 000000", + "", + "", + + "0016" + "403f000003000000 05c0020000c80008 00020002004a4029 28013001023cd980" + "00bc000ff06ec4d0 0141b82c00000000 07d404000ef08020 00012a0300008800" + "00", + + "0016" + "403f000003000000 05c0020000c70008 00020004004a4029 28013001023cd980" + "00bc000ff06ec4d0 0141b82c00000000 07d404000ef08020 00012a0300008800" + "00", + + "", + + + "0016" + "4030000003000000 05c0010001da0008 00020001004a401a 1900b801014c5980" + "809c000bf06ec4d0 0140302c00000000 0000", + + "0016" + "4030000003000000 05c0020000c40008 0002000c004a401a 1900b801014c5980" + "0018000bf06ec4d0 0100302c00000000 0000", + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 161, + 0, + 0, + + 51, + 0, + 0, + + 67, + 67, + 0, + + 52, + 52, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_initial_context_setup_response( + pkbuf_t **pkbuf, + c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, + c_uint8_t ebi, c_uint32_t teid) +{ + int erval = -1; + + status_t rv; + gtp_f_teid_t f_teid; + ip_t ip; + int len; + + s1ap_message_t message; + S1ap_InitialContextSetupResponseIEs_t *ies = NULL; + S1ap_E_RABSetupItemCtxtSURes_t *e_rab = NULL; + + memset(&message, 0, sizeof(s1ap_message_t)); + + ies = &message.s1ap_InitialContextSetupResponseIEs; + + message.direction = S1AP_PDU_PR_successfulOutcome; + message.procedureCode = S1ap_ProcedureCode_id_InitialContextSetup; + + ies->mme_ue_s1ap_id = mme_ue_s1ap_id; + ies->eNB_UE_S1AP_ID = enb_ue_s1ap_id; + + e_rab = (S1ap_E_RABSetupItemCtxtSURes_t *) + core_calloc(1, sizeof(S1ap_E_RABSetupItemCtxtSURes_t)); + e_rab->e_RAB_ID = ebi; + + rv = gtp_sockaddr_to_f_teid(test_enb_addr, test_enb_addr6, &f_teid, &len); + d_assert(rv == CORE_OK, return CORE_ERROR,); + rv = gtp_f_teid_to_ip(&f_teid, &ip); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + rv = s1ap_ip_to_BIT_STRING(&ip, &e_rab->transportLayerAddress); + d_assert(rv == CORE_OK, return CORE_ERROR,); + s1ap_uint32_to_OCTET_STRING(teid, &e_rab->gTP_TEID); + + ASN_SEQUENCE_ADD(&ies->e_RABSetupListCtxtSURes, e_rab); + + erval = s1ap_encode_pdu(pkbuf, &message); + s1ap_free_pdu(&message); + + if (erval < 0) + { + d_error("s1ap_encode_error : (%d)", erval); + return CORE_ERROR; + } + + return CORE_OK; +} + +status_t tests1ap_build_attach_complete(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d" + "403a000005000000 05c00100009d0008 00020001001a000e 0d27c183eb950207" + "4300035200c20064 40080000f1101079 baf0004340060000 f1105ba0", + + "000d" + "403a000005000000 05c00100009e0008 00020002001a000e 0d27e8a2a3f10207" + "4300035200c20064 40080000f1101079 baf0004340060000 f1105ba0", + + "", + + + "", + "000d" + "403a000005000000 05c0010000020008 00020011001a000e 0d27225d92bb0207" + "4300035200c20064 40080000f1101079 baf0004340060000 f1105ba0", + "", + + "000d" + "403a000005000000 05c0020000c80008 00020002001a000e 0d27f190fc2b0207" + "4300035200c20064 40080000f11054f6 4010004340060000 f1102b67", + "", + "", + + "000d" + "403a000005000000 05c0010001da0008 00020001001a000e 0d272e3456f70207" + "4300035200c20064 40080000f1100461 5380004340060000 f1105ba0", + + "000d" + "403a000005000000 05c0020000c40008 0002000c001a000e 0d276a543e560207" + "4300035200c20064 40080000f110001f 20a0004340060000 f1103039", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 62, + 62, + 0, + + 0, + 62, + 0, + + 62, + 0, + 0, + + 62, + 62, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_emm_status(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "", + "", + "", + + "000d403300000500 0000020001000800 02001f001a000a09 27574292cc020760" + "65006440080000f1 10002343d0004340 060000f1103039", + + "", + "", + + "", + "", + "", + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 0, + 0, + 0, + + 55, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_detach_request(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000c404900000600 080003000100001a 001615172ba435db 040745090bf600f1" + "10000201020003e6 004300060000f110 2b67006440080000 f1109d67aa500086" + "4001300060000600 40020003e6", + + "", + "", + + "" + "" + "" + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 77, + 0, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_ue_context_release_request(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "", + "", + "", + + "", + "", + "", + + "0012" + "4018000003000000 05c0020000c80008 0002000200024002 0280", + + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 0, + 0, + 0, + + 0, + 0, + 0, + + 28, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_ue_context_release_complete(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "2017001300000200 004005c00100009d 00084003400527", + + "", + + "2017" + "0012000002000040 05c00100009f0008 40020001", + + "", + "", + "", + + "2017" + "0012000002000040 05c0020000c80008 40020002", + "", + "", + + + "2017" + "0012000002000040 05c0020000c40008 4002000c", + + "2017" + "0012000002000040 05c0020000c50008 40020008", + + "2017" + "0012000002000040 05c0020000c70008 40020008", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 23, + 0, + 23, + + 0, + 0, + 0, + + 22, + 0, + 0, + + 22, + 22, + 22, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_service_request(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "", + "", + "", + + "", + "", + "", + + "000c" + "4037000006000800 020004001a000504 c704d4b800430006 0000f1102b670064" + "40080000f11054f6 4010008640014000 6000060040000000 03", + + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 0, + 0, + 0, + + 0, + 0, + 0, + + 59, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_pdn_connectivity_request( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d40680000" + "0500000005c08000 0107000800030001 00001a003b3a277c 81dab50a0205d011" + "281208696e746572 6e6574036e673204 6d6e6574271a8080 2110010000108106" + "0000000083060000 0000000d00000a00 006440080055f501 0019d01000434006" + "0055f5011022", + "000d40680000" + "0500000005c08000 0107000800030001 00001a003b3a2710 3fdafa0a0209d011" + "281208706e746572 6e6574036e673204 6d6e6574271a8080 2110010000108106" + "0000000083060000 0000000d00000a00 006440080055f501 0019d01000434006" + "0055f5011022", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 108, + 108, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_pdn_disconnectivity_request( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d40380000" + "0500000005c08000 0108000800030001 00001a000b0a2732 423c53040206d206" + "006440080055f501 0019d01000434006 0055f5011022", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 60, + 0, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_e_rab_setup_response( + pkbuf_t **pkbuf, + c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, + c_uint8_t ebi, c_uint32_t teid) +{ + int erval = -1; + + status_t rv; + gtp_f_teid_t f_teid; + ip_t ip; + int len; + + s1ap_message_t message; + S1ap_E_RABSetupResponseIEs_t *ies = NULL; + S1ap_E_RABSetupItemBearerSURes_t *e_rab = NULL; + + memset(&message, 0, sizeof(s1ap_message_t)); + + ies = &message.s1ap_E_RABSetupResponseIEs; + + message.direction = S1AP_PDU_PR_successfulOutcome; + message.procedureCode = S1ap_ProcedureCode_id_E_RABSetup; + + ies->mme_ue_s1ap_id = mme_ue_s1ap_id; + ies->eNB_UE_S1AP_ID = enb_ue_s1ap_id; + + e_rab = (S1ap_E_RABSetupItemBearerSURes_t *) + core_calloc(1, sizeof(S1ap_E_RABSetupItemBearerSURes_t)); + e_rab->e_RAB_ID = ebi; + + rv = gtp_sockaddr_to_f_teid(test_enb_addr, test_enb_addr6, &f_teid, &len); + d_assert(rv == CORE_OK, return CORE_ERROR,); + rv = gtp_f_teid_to_ip(&f_teid, &ip); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + rv = s1ap_ip_to_BIT_STRING(&ip, &e_rab->transportLayerAddress); + d_assert(rv == CORE_OK, return CORE_ERROR,); + s1ap_uint32_to_OCTET_STRING(teid, &e_rab->gTP_TEID); + + ies->presenceMask |= + S1AP_E_RABSETUPRESPONSEIES_E_RABSETUPLISTBEARERSURES_PRESENT; + ASN_SEQUENCE_ADD(&ies->e_RABSetupListBearerSURes, e_rab); + + erval = s1ap_encode_pdu(pkbuf, &message); + s1ap_free_pdu(&message); + + if (erval < 0) + { + d_error("s1ap_encode_error : (%d)", erval); + return CORE_ERROR; + } + + return CORE_OK; +} + +status_t tests1ap_build_e_rab_release_response(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "2007001d0000" + "0300004005c08000 0108000840030001 000045400600000f 40010c", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 33, + 0, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_activate_default_bearer_accept( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d40370000" + "0500000005c08000 0107000800030001 00001a000a0927e7 f5bb400b6200c200" + "6440080055f50100 19d0100043400600 55f5011022", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 59, + 0, + 0, + + 0, + 0, + 0, + + 59, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_activate_dedicated_bearer_accept( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d403700000500" + "000005c00200003c 0008000300010000 1a000a0927078a5f 34037200c6006440" + "080000f1109d67aa 50004340060000f1 102b67", + "000d403700000500" + "000005c00200003c 0008000300010000 1a000a0927c035da 96036200c6006440" + "080000f1109d67aa 50004340060000f1 102b67", + "", + + "", + "", + "", + + "", + "", + "", + + "000d403700000500" + "000005c00200003c 0008000300010000 1a000a0927a27f49 d6036200c6006440" + "080000f1109d67aa 50004340060000f1 102b67", + + "000d" + "4036000005000000 05c0020000c40008 0002000c001a000a 0927e3c77e000362" + "00c6006440080000 f110001f20a00043 40060000f1103039", + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 59, + 59, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + + 59, + 58, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_deactivate_bearer_accept( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d40370000" + "0500000005c08000 0108000800030001 00001a000a09274c b2ebbd056200ce00" + "6440080055f50100 19d0100043400600 55f5011022", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 59, + 0, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_path_switch_request( + pkbuf_t **pkbuf, + c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, + int num_of_bearer, c_uint8_t ebi, c_uint32_t teid) +{ + int erval = -1; + + status_t rv; + int i; + enb_ue_t *enb_ue = NULL; + mme_ue_t *mme_ue = NULL; + + s1ap_message_t message; + S1ap_PathSwitchRequestIEs_t *ies = + &message.s1ap_PathSwitchRequestIEs; + S1ap_E_RABToBeSwitchedDLItem_t *e_rab = NULL; + S1ap_EUTRAN_CGI_t *eutran_cgi = &ies->eutran_cgi; + + memset(&message, 0, sizeof(s1ap_message_t)); + + ies->eNB_UE_S1AP_ID = enb_ue_s1ap_id; + ies->sourceMME_UE_S1AP_ID = mme_ue_s1ap_id; + + enb_ue = enb_ue_find_by_mme_ue_s1ap_id(mme_ue_s1ap_id); + d_assert(enb_ue, return CORE_ERROR,); + mme_ue = enb_ue->mme_ue; + d_assert(mme_ue, return CORE_ERROR,); + + for (i = 0; i < num_of_bearer; i++) + { + gtp_f_teid_t f_teid; + ip_t ip; + int len; + + e_rab = (S1ap_E_RABToBeSwitchedDLItem_t *) + core_calloc(1, sizeof(S1ap_E_RABToBeSwitchedDLItem_t)); + e_rab->e_RAB_ID = ebi+i; + + rv = gtp_sockaddr_to_f_teid( + test_enb_addr, test_enb_addr6, &f_teid, &len); + d_assert(rv == CORE_OK, return CORE_ERROR,); + rv = gtp_f_teid_to_ip(&f_teid, &ip); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + rv = s1ap_ip_to_BIT_STRING(&ip, &e_rab->transportLayerAddress); + d_assert(rv == CORE_OK, return CORE_ERROR,); + s1ap_uint32_to_OCTET_STRING(teid+i, &e_rab->gTP_TEID); + + ASN_SEQUENCE_ADD(&ies->e_RABToBeSwitchedDLList, e_rab); + } + + s1ap_buffer_to_OCTET_STRING( + &mme_ue->e_cgi.plmn_id, PLMN_ID_LEN, &ies->eutran_cgi.pLMNidentity); + eutran_cgi->cell_ID.size = 4; + eutran_cgi->cell_ID.buf = core_calloc( + eutran_cgi->cell_ID.size, sizeof(c_uint8_t)); + d_assert(eutran_cgi->cell_ID.buf, return CORE_ERROR,); + eutran_cgi->cell_ID.buf[0] = (mme_ue->e_cgi.cell_id >> 24); + eutran_cgi->cell_ID.buf[1] = (mme_ue->e_cgi.cell_id >> 16); + eutran_cgi->cell_ID.buf[2] = (mme_ue->e_cgi.cell_id >> 8); + eutran_cgi->cell_ID.buf[3] = (mme_ue->e_cgi.cell_id); + eutran_cgi->cell_ID.bits_unused = 4; + + s1ap_uint16_to_OCTET_STRING( + mme_ue->tai.tac, &ies->tai.tAC); + s1ap_buffer_to_OCTET_STRING( + &mme_ue->tai.plmn_id, PLMN_ID_LEN, &ies->tai.pLMNidentity); + + ies->ueSecurityCapabilities.encryptionAlgorithms.size = 2; + ies->ueSecurityCapabilities.encryptionAlgorithms.buf = + core_calloc(ies->ueSecurityCapabilities.encryptionAlgorithms.size, + sizeof(c_uint8_t)); + ies->ueSecurityCapabilities.encryptionAlgorithms.bits_unused = 0; + ies->ueSecurityCapabilities.encryptionAlgorithms.buf[0] = + (mme_ue->ue_network_capability.eea << 1); + + ies->ueSecurityCapabilities.integrityProtectionAlgorithms.size = 2; + ies->ueSecurityCapabilities.integrityProtectionAlgorithms.buf = + core_calloc(ies->ueSecurityCapabilities. + integrityProtectionAlgorithms.size, sizeof(c_uint8_t)); + ies->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused = 0; + ies->ueSecurityCapabilities.integrityProtectionAlgorithms.buf[0] = + (mme_ue->ue_network_capability.eia << 1); + + message.procedureCode = S1ap_ProcedureCode_id_PathSwitchRequest; + message.direction = S1AP_PDU_PR_initiatingMessage; + + erval = s1ap_encode_pdu(pkbuf, &message); + s1ap_free_pdu(&message); + + if (erval < 0) + { + d_error("s1ap_encode_error : (%d)", erval); + return CORE_ERROR; + } + + return CORE_OK; +} + +status_t tests1ap_build_handover_required( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "0000" + "0081030000060000 0005c0020000c400 080002000c000100 0100000240020220" + "0004000d0000f110 0000043000f11030 3900680080d080ce 4080ab0f1014c598" + "00018000bf06ec4d 00100302c0000000 000015a800140672 0af00348f10013d0" + "3bc58414903bc588 09401de2c2100440 13f212249010127d ad808fd50398381c" + "08fd503983805f50 37868baa010c846f b057874162d62e82 1f42f2e159f821d0" + "9c0009e28aa1a001 2d888026d0600040 8008066072003e41 5250d46210208184" + "3423c135002214d6 dfb0a0b06502c402 000004008177faab 4677235334a0e867" + "213e804030000100 4e40024500004e40 0246000000f11000 043a000000f11000" + "1f20a0000022", + + "0000" + "00810e0000060000 0005c0020000c500 0800020008000100 0100000240020220" + "0004000d0000f110 00001f2000f11030 3900680080db80d9 4080ab0f1014c598" + "00018000bf06ec4d 00100302c0000000 000015a800140672 0af003e8f10013d0" + "3bc58414903bc588 09401de2c2100440 13f212249010127d ad808fd50398381c" + "08fd503983805f50 37868baa010c846f b057874162d62e82 1f42f2e159f821d0" + "9c0009e28aa1a001 2d888050d1bc0040 8008066072000874 1250d46210208184" + "3423c135002214d6 dfb0a0b06502c402 000004008177faab 4677235334a0e867" + "2134804030000100 4e40024500004e40 0246000000f11000 1f20a10000f11000" + "043a000000350000 f110001f20a00000 22", + + "0000" + "0081190000060000 0005c0020000c600 080002000d000100 0100000240020220" + "0004000d0000f110 0000043000f11030 3900680080e680e4 4080ab0f1014c598" + "00018000bf06ec4d 00100302c0000000 000015a800140672 0af00348f10013d0" + "3bc58414903bc588 09401de2c2100440 13f212249010127d ad808fd50398381c" + "08fd503983805f50 37868baa010c846f b057874162d62e82 1f42f2e159f821d0" + "9c0009e28aa1a001 2d888050514c0040 8008066072003e41 5250d46210208184" + "3423c135002214d6 dfb0a0b06502c402 000004008177faab 4677235334a0e867" + "213e804030000100 4e40024500004e40 0246000000f11000 043a020000f11000" + "1f20a00000340000 f11000043a000000 350000f110001f20 a0000022", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 264, + 275, + 286, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +CORE_DECLARE(status_t) tests1ap_build_handover_request_ack( + pkbuf_t **pkbuf, + c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, + int num_of_bearer, c_uint8_t ebi, c_uint32_t teid) +{ + char hexbuf[MAX_SDU_LEN]; + char *payload = + "00 80810bf900d8af40 00a0339057801f47 88009e81de2c20a4" + "81de2c404a00ef16 2000010044013f21 2249008093efd243 3914cd2aa0a0142f" + "f2214d6dfb82c194 0b10080000020040 bbfd55aeab41ad80 8fd50398381c08fd" + "503983804d037868 baa016423342bc3a 18b58fa084ca833f a17970acfc10e84e" + "0004f14550d00096 c88900"; + int erval = -1; + + status_t rv; + int i; + + s1ap_message_t message; + S1ap_HandoverRequestAcknowledgeIEs_t *ies = + &message.s1ap_HandoverRequestAcknowledgeIEs; + S1ap_E_RABAdmittedItem_t *e_rab = NULL; + S1ap_Target_ToSource_TransparentContainer_t *container = + &ies->target_ToSource_TransparentContainer; + + memset(&message, 0, sizeof(s1ap_message_t)); + + ies->eNB_UE_S1AP_ID = enb_ue_s1ap_id; + ies->mme_ue_s1ap_id = mme_ue_s1ap_id; + + for (i = 0; i < num_of_bearer; i++) + { + gtp_f_teid_t f_teid; + ip_t ip; + int len; + + e_rab = (S1ap_E_RABAdmittedItem_t *) + core_calloc(1, sizeof(S1ap_E_RABAdmittedItem_t)); + e_rab->e_RAB_ID = ebi+i; + + rv = gtp_sockaddr_to_f_teid( + test_enb_addr, test_enb_addr6, &f_teid, &len); + d_assert(rv == CORE_OK, return CORE_ERROR,); + rv = gtp_f_teid_to_ip(&f_teid, &ip); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + rv = s1ap_ip_to_BIT_STRING(&ip, &e_rab->transportLayerAddress); + d_assert(rv == CORE_OK, return CORE_ERROR,); + s1ap_uint32_to_OCTET_STRING(teid+i, &e_rab->gTP_TEID); + + e_rab->dL_transportLayerAddress = + (S1ap_TransportLayerAddress_t *) + core_calloc(1, sizeof(S1ap_TransportLayerAddress_t)); + rv = s1ap_ip_to_BIT_STRING(&ip, e_rab->dL_transportLayerAddress); + d_assert(rv == CORE_OK, return CORE_ERROR,); + e_rab->dL_gTP_TEID = (S1ap_GTP_TEID_t *) + core_calloc(1, sizeof(S1ap_GTP_TEID_t)); + s1ap_uint32_to_OCTET_STRING(teid+i+10, e_rab->dL_gTP_TEID); + + e_rab->uL_S1ap_TransportLayerAddress = + (S1ap_TransportLayerAddress_t *) + core_calloc(1, sizeof(S1ap_TransportLayerAddress_t)); + rv = s1ap_ip_to_BIT_STRING(&ip, e_rab->uL_S1ap_TransportLayerAddress); + d_assert(rv == CORE_OK, return CORE_ERROR,); + e_rab->uL_S1ap_GTP_TEID = (S1ap_GTP_TEID_t *) + core_calloc(1, sizeof(S1ap_GTP_TEID_t)); + s1ap_uint32_to_OCTET_STRING(teid+i+20, e_rab->uL_S1ap_GTP_TEID); + + ASN_SEQUENCE_ADD(&ies->e_RABAdmittedList, e_rab); + } + + s1ap_buffer_to_OCTET_STRING( + CORE_HEX(payload, strlen(payload), hexbuf), 132, container); + + message.procedureCode = S1ap_ProcedureCode_id_HandoverResourceAllocation; + message.direction = S1AP_PDU_PR_successfulOutcome; + + erval = s1ap_encode_pdu(pkbuf, &message); + s1ap_free_pdu(&message); + + if (erval < 0) + { + d_error("s1ap_encode_error : (%d)", erval); + return CORE_ERROR; + } + + return CORE_OK; +} + +status_t tests1ap_build_handover_request_ack_static( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "2001" + "0080e80000040000 4005c0020000c500 0840020008001240 47010014401f78a1" + "f07f000001010007 080f807f00000101 0007090f807f0000 010100070a001440" + "1f78c1f07f000001 010007100f807f00 0001010007110f80 7f00000101000712" + "007b008086808400 80810bf900d8af40 00a0339057801f47 88009e81de2c20a4" + "81de2c404a00ef16 2000010044013f21 2249008093efd243 3914cd2aa0a0142f" + "f2214d6dfb82c194 0b10080000020040 bbfd55aeab41ad80 8fd50398381c08fd" + "503983804d037868 baa016423342bc3a 18b58fa084ca833f a17970acfc10e84e" + "0004f14550d00096 c88900", + + "2001" + "0080e80000040000 4005c0020000c600 084002000d001240 47010014401f78a1" + "f00a01237b010009 080f800a01237b01 0009090f800a0123 7b0100090a001440" + "1f78c1f00a01237b 010009100f800a01 237b010009110f80 0a01237b01000912" + "007b008086808400 80810bf900d8af40 00a0339057801a47 88009e81de2c20a4" + "81de2c404a00ef16 2000010044013f21 2249008093effa43 3914cd2aa0a0140f" + "f2214d6dfb82c194 0b10080000020040 bbfd55aeab01ad80 8fd50398381c08fd" + "503983804d037868 baa016423342bc3a 18b58fa084ca833f a17970acfc10e84e" + "0004f14550d00096 c88980", + + "2001" + "0080e80000040000 4005c0020000c700 0840020009001240 47010014401f78a1" + "f00a01237c010008 080f800a01237c01 0008090f800a0123 7c0100080a001440" + "1f78c1f00a01237c 010008100f800a01 237c010008110f80 0a01237c01000812" + "007b008086808400 80810bf900d8af40 00a0339057801f47 88009e81de2c20a4" + "81de2c404a00ef16 2000010044013f21 2249008093efd243 3914cd2aa0a0144f" + "f2214d6dfb82c194 0b10080000020040 bbfd55aeab81ad80 8fd50398381c08fd" + "503983804d037868 baa016423342bc3a 18b58fa084ca833f a17970acfc10e84e" + "0004f14550d00096 c88a00", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 237, + 237, + 237, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_enb_status_transfer( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "0018" + "4027000003000000 05c0020000c40008 0002000c005a0011 00000059400b0500" + "004b000000001100 00", + "0018" + "4027000003000000 05c0020000c50008 00020008005a0011 00000059400b0500" + "00a8000000004100 00", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 43, + 43, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_handover_notify(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "0002" + "4028000004000000 05c0020000c50008 0002000800644008 0000f11000043a00" + "004340060000f110 3039", + "0002" + "4028000004000000 05c0020000c60008 0002000d00644008 0000f110001f20a0" + "004340060000f110 3039", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 44, + 44, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_handover_cancel(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "0004" + "0018000003000000 05c0020000c60008 0002000d00024002 0120", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 28, + 0, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t testgtpu_enb_connect(sock_id *new) +{ + char buf[INET_ADDRSTRLEN]; + status_t rv; + c_sockaddr_t *addr = NULL; + int family = AF_UNSPEC; + + if (test_only_control_plane) return CORE_OK; + + family = AF_INET6; + if (context_self()->parameter.no_ipv6) family = AF_INET; + else if (context_self()->parameter.prefer_ipv4) family = AF_INET; + else if (test_enb_addr6 == NULL) family = AF_INET; + + rv = udp_socket(new, family); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + if (family == AF_INET) addr = test_enb_addr; + else if (family == AF_INET6) addr = test_enb_addr6; + else + d_assert(0, return CORE_ERROR,); + + d_assert(addr, return CORE_ERROR,); + rv = sock_bind(*new, addr); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + return CORE_OK; +} + +status_t testgtpu_enb_close(sock_id sock) +{ + if (test_only_control_plane) return CORE_OK; + + return sock_delete(sock); +} + +status_t testgtpu_enb_send(pkbuf_t *sendbuf) +{ + status_t rv; + sock_id sock = 0; + hash_index_t *hi = NULL; + mme_ue_t *mme_ue = NULL; + mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; + + c_sockaddr_t sgw; + ssize_t sent; + + if (test_only_control_plane) return 0; + + hi = mme_ue_first(); + d_assert(hi, return -1,); + mme_ue = mme_ue_this(hi); + d_assert(mme_ue, return -1,); + sess = mme_sess_first(mme_ue); + d_assert(sess, return -1,); + bearer = mme_bearer_first(sess); + d_assert(bearer, return -1,); + + memset(&sgw, 0, sizeof(c_sockaddr_t)); + sgw.c_sa_port = htons(GTPV1_U_UDP_PORT); + if (bearer->sgw_s1u_ip.ipv6) + { + sgw.c_sa_family = AF_INET6; + if (bearer->sgw_s1u_ip.ipv4) + memcpy(sgw.sin6.sin6_addr.s6_addr, + bearer->sgw_s1u_ip.both.addr6, IPV6_LEN); + else + memcpy(sgw.sin6.sin6_addr.s6_addr, + bearer->sgw_s1u_ip.addr6, IPV6_LEN); + rv = sock_fill_scope_id_in_local(&sgw); + d_assert(rv == CORE_OK, return CORE_ERROR,); + } + else + { + sgw.c_sa_family = AF_INET; + sgw.sin.sin_addr.s_addr = bearer->sgw_s1u_ip.addr; + } + + rv = udp_client(&sock, &sgw); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + sent = core_send(sock, sendbuf->payload, sendbuf->len, 0); + pkbuf_free(sendbuf); + if (sent < 0 || sent != sendbuf->len) + return CORE_ERROR; + + sock_delete(sock); + + return CORE_OK; +} + +status_t testgtpu_enb_read(sock_id sock, pkbuf_t *recvbuf) +{ + int rc = 0; + + if (test_only_control_plane) return 0; + + while(1) + { + rc = core_recv(sock, recvbuf->payload, recvbuf->len, 0); + if (rc == -2) + { + continue; + } + else if (rc <= 0) + { + if (errno == EAGAIN) + { + continue; + } + break; + } + else + { + break; + } + } + recvbuf->len = rc; + + return CORE_OK; +} + +c_uint16_t in_cksum(c_uint16_t *addr, int len); /* from pgw_gtp_path.c */ + +status_t testgtpu_build_ping( + pkbuf_t **sendbuf, const char *src_ip, const char *dst_ip) +{ + status_t rv; + pkbuf_t *pkbuf = NULL; + gtp_header_t *gtp_h = NULL; + ipsubnet_t src_ipsub, dst_ipsub; + + if (test_only_control_plane) return CORE_OK; + + d_assert(src_ip, return CORE_ERROR,); + d_assert(dst_ip, return CORE_ERROR,); + rv = core_ipsubnet(&src_ipsub, src_ip, NULL); + d_assert(rv == CORE_OK, return CORE_ERROR,); + rv = core_ipsubnet(&dst_ipsub, dst_ip, NULL); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + pkbuf = pkbuf_alloc(0, 200 /* enough for ICMP; use smaller buffer */); + d_assert(pkbuf, return CORE_ERROR,); + memset(pkbuf->payload, 0, pkbuf->len); + + gtp_h = (gtp_header_t *)pkbuf->payload; + gtp_h->flags = 0x30; + gtp_h->type = GTPU_MSGTYPE_GPDU; + gtp_h->teid = htonl(1); + + if (dst_ipsub.family == AF_INET) + { + struct ip *ip_h = NULL; + struct icmp *icmp_h = NULL; + + gtp_h->length = htons(sizeof *ip_h + ICMP_MINLEN); + + ip_h = (struct ip *)(pkbuf->payload + GTPV1U_HEADER_LEN); + icmp_h = (struct icmp *)((c_uint8_t *)ip_h + sizeof *ip_h); + + ip_h->ip_v = 4; + ip_h->ip_hl = 5; + ip_h->ip_tos = 0; + ip_h->ip_id = rand(); + ip_h->ip_off = 0; + ip_h->ip_ttl = 255; + ip_h->ip_p = IPPROTO_ICMP; + ip_h->ip_len = gtp_h->length; + ip_h->ip_src.s_addr = src_ipsub.sub[0]; + ip_h->ip_dst.s_addr = dst_ipsub.sub[0]; + ip_h->ip_sum = in_cksum((c_uint16_t *)ip_h, sizeof *ip_h); + + icmp_h->icmp_type = 8; + icmp_h->icmp_seq = rand(); + icmp_h->icmp_id = rand(); + icmp_h->icmp_cksum = in_cksum((c_uint16_t *)icmp_h, ICMP_MINLEN); + } + else if (dst_ipsub.family == AF_INET6) + { + struct ip6_hdr *ip6_h = NULL; + struct icmp6_hdr *icmp6_h = NULL; + c_uint16_t plen = 0; + c_uint8_t nxt = 0; + c_uint8_t *p = NULL; + + gtp_h->length = htons(sizeof *ip6_h + sizeof *icmp6_h); + plen = htons(sizeof *icmp6_h); + nxt = IPPROTO_ICMPV6; + + p = (c_uint8_t *)pkbuf->payload + GTPV1U_HEADER_LEN; + ip6_h = (struct ip6_hdr *)p; + icmp6_h = (struct icmp6_hdr *)((c_uint8_t *)ip6_h + sizeof *ip6_h); + + memcpy(p, src_ipsub.sub, sizeof src_ipsub.sub); + p += sizeof src_ipsub.sub; + memcpy(p, dst_ipsub.sub, sizeof dst_ipsub.sub); + p += sizeof dst_ipsub.sub; + p += 2; memcpy(p, &plen, 2); p += 2; + p += 3; *p = nxt; p += 1; + + icmp6_h->icmp6_type = ICMP6_ECHO_REQUEST; + icmp6_h->icmp6_seq = rand(); + icmp6_h->icmp6_id = rand(); + + icmp6_h->icmp6_cksum = in_cksum( + (c_uint16_t *)ip6_h, sizeof *ip6_h + sizeof *icmp6_h); + + ip6_h->ip6_flow = htonl(0x60000001); + ip6_h->ip6_plen = plen; + ip6_h->ip6_nxt = nxt;; + ip6_h->ip6_hlim = 0xff; + memcpy(ip6_h->ip6_src.s6_addr, src_ipsub.sub, sizeof src_ipsub.sub); + memcpy(ip6_h->ip6_dst.s6_addr, dst_ipsub.sub, sizeof dst_ipsub.sub); + } + else + d_assert(0, return CORE_ERROR,); + + *sendbuf = pkbuf; + + return CORE_OK; +} + +status_t testgtpu_build_slacc_rs(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "32ff003400000001 00000000 6000000000083aff cafe000000000000 0000000000000001" + "ff02000000000000 0000000000000002 8500b0b800000000", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 60, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + diff --git a/test/rx/testpacket.h b/test/rx/testpacket.h new file mode 100644 index 000000000..3f61854e0 --- /dev/null +++ b/test/rx/testpacket.h @@ -0,0 +1,93 @@ +#ifndef __TESTS1AP_H__ +#define __TESTS1AP_H__ + +#include "core_network.h" +#include "core_pkbuf.h" + +#include "s1ap/s1ap_message.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +CORE_DECLARE(status_t) testpacket_init(); +CORE_DECLARE(status_t) testpacket_final(); + +CORE_DECLARE(status_t) tests1ap_enb_connect(sock_id *new); +CORE_DECLARE(status_t) tests1ap_enb_close(sock_id id); +CORE_DECLARE(status_t) tests1ap_enb_send(sock_id id, pkbuf_t *sendbuf); +CORE_DECLARE(status_t) tests1ap_enb_read(sock_id id, pkbuf_t *recvbuf); + +CORE_DECLARE(status_t) tests1ap_build_setup_req( + pkbuf_t **pkbuf, S1ap_ENB_ID_PR present, c_uint32_t enb_id); +CORE_DECLARE(status_t) tests1ap_build_initial_ue_msg(pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_identity_response(pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_authentication_response( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_authentication_failure( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_security_mode_complete( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_esm_information_response( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_ue_capability_info_indication( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_initial_context_setup_response( + pkbuf_t **pkbuf, + c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, + c_uint8_t ebi, c_uint32_t teid); +CORE_DECLARE(status_t) tests1ap_build_attach_complete(pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_emm_status(pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_detach_request(pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_ue_context_release_request( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_ue_context_release_complete( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_service_request( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_pdn_connectivity_request( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_pdn_disconnectivity_request( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_e_rab_setup_response( + pkbuf_t **pkbuf, + c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, + c_uint8_t ebi, c_uint32_t teid); +CORE_DECLARE(status_t) tests1ap_build_e_rab_release_response( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_activate_default_bearer_accept( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_activate_dedicated_bearer_accept( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_deactivate_bearer_accept( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_path_switch_request( + pkbuf_t **pkbuf, + c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, + int num_of_bearer, c_uint8_t ebi, c_uint32_t teid); +CORE_DECLARE(status_t) tests1ap_build_handover_required(pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_handover_request_ack( + pkbuf_t **pkbuf, + c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, + int num_of_bearer, c_uint8_t ebi, c_uint32_t teid); +CORE_DECLARE(status_t) tests1ap_build_handover_request_ack_static( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_enb_status_transfer( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_handover_notify(pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_handover_cancel(pkbuf_t **pkbuf, int i); + +CORE_DECLARE(status_t) testgtpu_enb_connect(sock_id *new); +CORE_DECLARE(status_t) testgtpu_enb_close(sock_id sock); +CORE_DECLARE(status_t) testgtpu_enb_read(sock_id sock, pkbuf_t *recvbuf); +CORE_DECLARE(status_t) testgtpu_enb_send(pkbuf_t *sendbuf); + +CORE_DECLARE(status_t) testgtpu_build_ping(pkbuf_t **sendbuf, + const char *src_ip, const char *dst_ip); +CORE_DECLARE(status_t) testgtpu_build_slacc_rs(pkbuf_t **sendbuf, int i); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TESTS1AP_H__ */ diff --git a/test/rx/testutil.c b/test/rx/testutil.c new file mode 100644 index 000000000..6c0f627fb --- /dev/null +++ b/test/rx/testutil.c @@ -0,0 +1,70 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core_general.h" +#include "core_debug.h" +#include "core_semaphore.h" +#include "fd/fd_lib.h" + +#include "app/app.h" +#include "app/context.h" +#include "testpacket.h" +#include "abts.h" +#include "testutil.h" + +static int connected_count = 0; +static void test_fd_logger_handler(enum fd_hook_type type, struct msg * msg, + struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, + void * regdata) +{ + if (type == HOOK_PEER_CONNECT_SUCCESS) + { + connected_count++; + } +} + +void test_terminate(void) +{ + d_trace_global_on(); + + testpacket_final(); + app_terminate(); + core_terminate(); +} + +status_t test_initialize(char *config_path) +{ + status_t rv; + + fd_logger_register(test_fd_logger_handler); + + atexit(test_terminate); + + core_initialize(); + rv = app_initialize(config_path, NULL); + testpacket_init(); + if (rv == CORE_OK) + { + while(1) + { + if (connected_count == 1) break; + core_sleep(time_from_msec(50)); + } + } + + return rv; +} + diff --git a/test/rx/testutil.h b/test/rx/testutil.h new file mode 100644 index 000000000..6f5e448d5 --- /dev/null +++ b/test/rx/testutil.h @@ -0,0 +1,62 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core_general.h" +#include "abts.h" + +#ifndef __TEST_UTIL__ +#define __TEST_UTIL__ + +/* XXX: FIXME - these all should become much more utilitarian + * and part of core, itself + */ + +#ifdef WIN32 +#ifdef BINPATH +#define TESTBINPATH APR_STRINGIFY(BINPATH) "/" +#else +#define TESTBINPATH "" +#endif +#else +#define TESTBINPATH "./" +#endif + +#ifdef WIN32 +#define EXTENSION ".exe" +#elif NETWARE +#define EXTENSION ".nlm" +#else +#define EXTENSION +#endif + +#define STRING_MAX 8096 + +/* Some simple functions to make the test apps easier to write and + * a bit more consistent... + */ + +/* Assert that RV is an CORE_OK value; else fail giving strerror + * for RV and CONTEXT message. */ +void core_assert_ok(abts_case* tc, const char *context, + status_t rv, int lineno); +#define CORE_ASSERT_OK(tc, ctxt, rv) \ + core_assert_ok(tc, ctxt, rv, __LINE__) + +status_t test_initialize(char *config_path); + +abts_suite *test_volte(abts_suite *suite); + +#endif /* __TESTUTIL_H__ */ diff --git a/test/rx/volte_test.c b/test/rx/volte_test.c new file mode 100644 index 000000000..3cdc7b60e --- /dev/null +++ b/test/rx/volte_test.c @@ -0,0 +1,588 @@ + +#include "core_debug.h" +#include "core_pkbuf.h" +#include "core_lib.h" +#include + +#include "app/context.h" +#include "mme/mme_context.h" +#include "s1ap/s1ap_message.h" + +#include "testutil.h" +#include "testpacket.h" + +static void volte_test1(abts_case *tc, void *data) +{ + status_t rv; + sock_id sock; + pkbuf_t *sendbuf; + pkbuf_t *recvbuf; + s1ap_message_t message; + int i; + int msgindex = 0; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + c_int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2b\" }," + "\"imsi\" : \"001010123456819\"," + "\"pdn\" : [" + "{ \"apn\" : \"internet\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd32\" }," + "\"qos\" : {" + "\"qci\" : 9," + "\"arp\" : {" + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 1," + "\"pre_emption_capability\" : 1 } }," + "\"type\" : 2 }," + "{ \"apn\" : \"internet.ng2.mnet\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2c\" }," + "\"pcc_rule\" : [" + "{ \"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2d\" }," + "\"qos\" : {" + "\"qci\" : 1," + "\"gbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"64\" }," + "\"uplink\" : { \"$numberLong\" : \"44\" } }," + "\"mbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"64\" }," + "\"uplink\" : { \"$numberLong\" : \"44\" } }," + "\"arp\" : {" + "\"priority_level\" : 3," + "\"pre_emption_vulnerability\" : 0," + "\"pre_emption_capability\" : 0 } }," + "\"flow\" : [" + "{ \"direction\" : 2," + "\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23454\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd31\" } }," + "{ \"direction\" : 1," + "\"description\" : \"permit out udp from any 50020 to 10.200.136.98/32 1-65535\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd30\" } }," + "{ \"direction\" : 2," + "\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23455\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2f\" } }," + "{ \"direction\" : 1," + "\"description\" : \"permit out udp from any 50021 to 10.200.136.98/32 1-65535\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2e\" } } ]" + "} ]," + "\"ambr\" : {" + "\"downlink\" : { \"$numberLong\" : \"35840\" }," + "\"uplink\" : { \"$numberLong\" : \"15360\" } }," + "\"qos\" : {" + "\"qci\" : 6," + "\"arp\" : {" + "\"priority_level\" : 6," + "\"pre_emption_vulnerability\" : 1," + "\"pre_emption_capability\" : 1 } }," + "\"type\" : 2 }" + "]," + "\"ambr\" : {" + "\"downlink\" : { \"$numberLong\" : \"1024000\" }," + "\"uplink\" : { \"$numberLong\" : \"1024000\" } }," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2," + "\"subscriber_status\" : 0," + "\"access_restriction_data\" : 32," + "\"security\" : {" + "\"k\" : \"465B5CE8 B199B49F AA5F0A2E E238A6BC\"," + "\"op\" : \"5F1D289C 5D354D0A 140C2548 F5F3E3BA\"," + "\"amf\" : \"8000\"," + "\"sqn\" : { \"$numberLong\" : \"64\" }, " + "\"rand\" : \"20080C38 18183B52 2614162C 07601D0D\" }, " + "\"__v\" : 0" + "}"; + + /* eNB connects to MME */ + rv = tests1ap_enb_connect(&sock); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Send S1-Setup Reqeust */ + rv = tests1ap_build_setup_req( + &sendbuf, S1ap_ENB_ID_PR_macroENB_ID, 0x54f64); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = s1ap_decode_pdu(&message, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + s1ap_free_pdu(&message); + pkbuf_free(recvbuf); + + collection = mongoc_client_get_collection( + context_self()->db_client, + context_self()->db_name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + doc = bson_new_from_json((const uint8_t *)json, -1, &error);; + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_insert(collection, + MONGOC_INSERT_NONE, doc, NULL, &error)); + bson_destroy(doc); + + doc = BCON_NEW("imsi", BCON_UTF8("001010123456819")); + ABTS_PTR_NOTNULL(tc, doc); + do + { + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + } while (count == 0); + bson_destroy(doc); + + /*********************************************************************** + * Attach Request : Known IMSI, Integrity Protected, No Security Context + * Send Initial-UE Message + Attach Request + PDN Connectivity */ + rv = tests1ap_build_initial_ue_msg(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive Authentication Request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send Authentication Response */ + rv = tests1ap_build_authentication_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive Security mode Command */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send Security mode Complete */ + rv = tests1ap_build_security_mode_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive ESM Information Request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send ESM Information Response */ + rv = tests1ap_build_esm_information_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send UE Capability Info Indication */ + rv = tests1ap_build_ue_capability_info_indication(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Send Initial Context Setup Response */ + rv = tests1ap_build_initial_context_setup_response(&sendbuf, + 16777373, 1, 5, 1); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + rv = tests1ap_build_attach_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive EMM information */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send PDN Connectivity Request */ + rv = tests1ap_build_pdn_connectivity_request(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Receive E-RAB Setup Request + + * Activate default EPS bearer context request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send E-RAB Setup Response */ + rv = tests1ap_build_e_rab_setup_response(&sendbuf, 33554492, 1, 6, 2); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Send Activate default EPS bearer context accept */ + rv = tests1ap_build_activate_default_bearer_accept(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send Activate dedicated EPS bearer context accept */ + rv = tests1ap_build_activate_dedicated_bearer_accept(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Send E-RAB Setup Response */ + rv = tests1ap_build_e_rab_setup_response(&sendbuf, 33554492, 1, 7, 3); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Send PDN disconnectivity request */ + rv = tests1ap_build_pdn_disconnectivity_request(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive E-RAB Release Command + + * Deactivate EPS bearer context request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send E-RAB Release Response */ + rv = tests1ap_build_e_rab_release_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Deactivate EPS bearer context accept */ + rv = tests1ap_build_deactivate_bearer_accept(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Send INVALID PDN Connectivity Request */ + rv = tests1ap_build_pdn_connectivity_request(&sendbuf, msgindex+1); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive PDN Connectivity Reject */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8("001010123456819")); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + bson_destroy(doc); + + mongoc_collection_destroy(collection); + + /* eNB disonncect from MME */ + rv = tests1ap_enb_close(sock); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); +} + +static void volte_test2(abts_case *tc, void *data) +{ + status_t rv; + sock_id sock; + pkbuf_t *sendbuf; + pkbuf_t *recvbuf; + s1ap_message_t message; + int i; + int msgindex = 0; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + c_int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2b\" }," + "\"imsi\" : \"001010123456819\"," + "\"pdn\" : [" + "{ \"apn\" : \"internet.ng2.mnet\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd32\" }," + "\"qos\" : {" + "\"qci\" : 9," + "\"arp\" : {" + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 1," + "\"pre_emption_capability\" : 1 } }," + "\"type\" : 2 }," + "{ \"apn\" : \"internet\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2c\" }," + "\"pcc_rule\" : [" + "{ \"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2d\" }," + "\"qos\" : {" + "\"qci\" : 1," + "\"gbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"64\" }," + "\"uplink\" : { \"$numberLong\" : \"44\" } }," + "\"mbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"64\" }," + "\"uplink\" : { \"$numberLong\" : \"44\" } }," + "\"arp\" : {" + "\"priority_level\" : 3," + "\"pre_emption_vulnerability\" : 0," + "\"pre_emption_capability\" : 0 } }," + "\"flow\" : [" + "{ \"direction\" : 2," + "\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/32 23454\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd31\" } }," + "{ \"direction\" : 1," + "\"description\" : \"permit out ip from 45.45.0.1 to any\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd30\" } }," + "{ \"direction\" : 2," + "\"description\" : \"permit out udp from any 1-65535 to 10.200.136.98/24 23455\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2f\" } }," + "{ \"direction\" : 1," + "\"description\" : \"permit out ip from cafe::1 to any\"," + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2e\" } } ]" + "} ]," + "\"ambr\" : {" + "\"downlink\" : { \"$numberLong\" : \"35840\" }," + "\"uplink\" : { \"$numberLong\" : \"15360\" } }," + "\"qos\" : {" + "\"qci\" : 6," + "\"arp\" : {" + "\"priority_level\" : 6," + "\"pre_emption_vulnerability\" : 1," + "\"pre_emption_capability\" : 1 } }," + "\"type\" : 2 }" + "]," + "\"ambr\" : {" + "\"downlink\" : { \"$numberLong\" : \"1024000\" }," + "\"uplink\" : { \"$numberLong\" : \"1024000\" } }," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2," + "\"subscriber_status\" : 0," + "\"access_restriction_data\" : 32," + "\"security\" : {" + "\"k\" : \"465B5CE8 B199B49F AA5F0A2E E238A6BC\"," + "\"op\" : \"5F1D289C 5D354D0A 140C2548 F5F3E3BA\"," + "\"amf\" : \"8000\"," + "\"sqn\" : { \"$numberLong\" : \"64\" }, " + "\"rand\" : \"20080C38 18183B52 2614162C 07601D0D\" }, " + "\"__v\" : 0" + "}"; + + /* eNB connects to MME */ + rv = tests1ap_enb_connect(&sock); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Send S1-Setup Reqeust */ + rv = tests1ap_build_setup_req( + &sendbuf, S1ap_ENB_ID_PR_macroENB_ID, 0x54f64); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = s1ap_decode_pdu(&message, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + s1ap_free_pdu(&message); + pkbuf_free(recvbuf); + + collection = mongoc_client_get_collection( + context_self()->db_client, + context_self()->db_name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + doc = bson_new_from_json((const uint8_t *)json, -1, &error);; + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_insert(collection, + MONGOC_INSERT_NONE, doc, NULL, &error)); + bson_destroy(doc); + + doc = BCON_NEW("imsi", BCON_UTF8("001010123456819")); + ABTS_PTR_NOTNULL(tc, doc); + do + { + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + } while (count == 0); + bson_destroy(doc); + + /*********************************************************************** + * Attach Request : Known IMSI, Integrity Protected, No Security Context + * Send Initial-UE Message + Attach Request + PDN Connectivity */ + rv = tests1ap_build_initial_ue_msg(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive Authentication Request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send Authentication Response */ + rv = tests1ap_build_authentication_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive Security mode Command */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send Security mode Complete */ + rv = tests1ap_build_security_mode_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive ESM Information Request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send ESM Information Response */ + rv = tests1ap_build_esm_information_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send UE Capability Info Indication */ + rv = tests1ap_build_ue_capability_info_indication(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Send Initial Context Setup Response */ + rv = tests1ap_build_initial_context_setup_response(&sendbuf, + 16777373, 1, 5, 1); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + rv = tests1ap_build_attach_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + /* Receive EMM information */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send E-RAB Setup Response */ + rv = tests1ap_build_e_rab_setup_response(&sendbuf, 33554492, 1, 6, 2); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Send Activate dedicated EPS bearer context accept */ + rv = tests1ap_build_activate_dedicated_bearer_accept(&sendbuf, msgindex+1); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + +#if 0 /* TFT Rule Tester */ + core_sleep(time_from_msec(300)); + + /* Send GTP-U ICMP Packet */ +#if 1 + rv = testgtpu_build_ping(&sendbuf, "45.45.0.2", "45.45.0.1"); +#else + rv = testgtpu_build_ping(&sendbuf, "cafe::2", "cafe::1"); +#endif + rv = testgtpu_enb_send(sendbuf); + + core_sleep(time_from_msec(300)); +#endif + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8("001010123456819")); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + bson_destroy(doc); + + mongoc_collection_destroy(collection); + + /* eNB disonncect from MME */ + rv = tests1ap_enb_close(sock); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); +} + +abts_suite *test_volte(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, volte_test1, NULL); + abts_run_test(suite, volte_test2, NULL); + + return suite; +}