diff --git a/src/mme/emm-handler.c b/src/mme/emm-handler.c index 5e2e78d31..10a703854 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.c @@ -19,6 +19,7 @@ #include "nas/nas-message.h" #include "mme-event.h" +#include "mme-sm.h" #include "mme-kdf.h" #include "nas-security.h" diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index fd44ab69e..c943252d4 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -236,6 +236,17 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) } OGS_FSM_TRAN(s, &emm_state_de_registered); + return; + case NAS_UPLINK_NAS_TRANSPORT: + ogs_debug("[EMM] Uplink NAS Transport"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + if (MME_SGSAP_IS_CONNECTED(mme_ue)) { + sgsap_send_uplink_unitdata(mme_ue, + &message->emm.uplink_nas_transport.nas_message_container); + } else { + ogs_warn("No connection of MSC/VLR"); + } + return; default: ogs_warn("Unknown message[%d]", message->emm.h.message_type); diff --git a/src/mme/sgsap-build.c b/src/mme/sgsap-build.c index 54fae3837..909a95002 100644 --- a/src/mme/sgsap-build.c +++ b/src/mme/sgsap-build.c @@ -277,3 +277,33 @@ ogs_pkbuf_t *sgsap_build_reset_ack(mme_vlr_t *vlr) return pkbuf; } + +ogs_pkbuf_t *sgsap_build_uplink_unidata( + mme_ue_t *mme_ue, nas_message_container_t *nas_message_container) +{ + mme_vlr_t *vlr = NULL; + ogs_tlv_t *root = NULL; + ogs_pkbuf_t *pkbuf = NULL; + + ogs_assert(mme_ue); + vlr = mme_ue->vlr; + ogs_assert(vlr); + ogs_assert(nas_message_container); + + root = ogs_tlv_add(NULL, SGSAP_IE_IMSI_TYPE, SGSAP_IE_IMSI_LEN, 0, + &mme_ue->nas_mobile_identity_imsi); + + ogs_tlv_add(root, SGSAP_IE_NAS_MESSAGE_CONTAINER_TYPE, + nas_message_container->length, 0, nas_message_container->buffer); + + pkbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); + ogs_pkbuf_put_u8(pkbuf, SGSAP_UPLINK_UNITDATA); + ogs_pkbuf_put(pkbuf, MAX_SDU_LEN-1); + + ogs_pkbuf_trim(pkbuf, 1+ogs_tlv_render(root, + pkbuf->data+1, MAX_SDU_LEN-1, OGS_TLV_MODE_T1_L1)); + + ogs_tlv_free_all(root); + + return pkbuf; +} diff --git a/src/mme/sgsap-build.h b/src/mme/sgsap-build.h index 15d83433b..0524a5229 100644 --- a/src/mme/sgsap-build.h +++ b/src/mme/sgsap-build.h @@ -35,6 +35,8 @@ ogs_pkbuf_t *sgsap_build_paging_reject( int nas_mobile_identity_imsi_len, uint8_t sgs_cause); ogs_pkbuf_t *sgsap_build_service_request(mme_ue_t *mme_ue, uint8_t emm_mode); ogs_pkbuf_t *sgsap_build_reset_ack(mme_vlr_t *vlr); +ogs_pkbuf_t *sgsap_build_uplink_unidata( + mme_ue_t *mme_ue, nas_message_container_t *nas_message_container); #ifdef __cplusplus } diff --git a/src/mme/sgsap-path.c b/src/mme/sgsap-path.c index be925de1f..3f0b0927f 100644 --- a/src/mme/sgsap-path.c +++ b/src/mme/sgsap-path.c @@ -210,3 +210,23 @@ int sgsap_send_reset_ack(mme_vlr_t *vlr) return OGS_OK; } + +int sgsap_send_uplink_unitdata( + mme_ue_t *mme_ue, nas_message_container_t *nas_message_container) +{ + int rv; + ogs_pkbuf_t *pkbuf = NULL; + ogs_assert(mme_ue); + ogs_assert(nas_message_container); + + ogs_debug("[SGSAP] UPLINK-UNITDATA"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + ogs_log_hexdump(OGS_LOG_DEBUG, + nas_message_container->buffer, nas_message_container->length); + + pkbuf = sgsap_build_uplink_unidata(mme_ue, nas_message_container); + rv = sgsap_send_to_vlr(mme_ue, pkbuf); + ogs_assert(rv == OGS_OK); + + return OGS_OK; +} diff --git a/src/mme/sgsap-path.h b/src/mme/sgsap-path.h index cc6d6a035..98af44bee 100644 --- a/src/mme/sgsap-path.h +++ b/src/mme/sgsap-path.h @@ -48,6 +48,8 @@ int sgsap_send_detach_indication(mme_ue_t *mme_ue); int sgsap_send_mo_csfb_indication(mme_ue_t *mme_ue); int sgsap_send_service_request(mme_ue_t *mme_ue, uint8_t emm_mode); int sgsap_send_reset_ack(mme_vlr_t *vlr); +int sgsap_send_uplink_unitdata( + mme_ue_t *mme_ue, nas_message_container_t *nas_message_container); #ifdef __cplusplus } diff --git a/src/mme/sgsap-types.h b/src/mme/sgsap-types.h index 0761c031a..1c82fc104 100644 --- a/src/mme/sgsap-types.h +++ b/src/mme/sgsap-types.h @@ -27,6 +27,8 @@ extern "C" { #define SGSAP_PAGING_REQUEST 1 #define SGSAP_PAGING_REJECT 2 #define SGSAP_SERVICE_REQUEST 6 +#define SGSAP_DOWNLINK_UNITDATA 7 +#define SGSAP_UPLINK_UNITDATA 8 #define SGSAP_LOCATION_UPDATE_REQUEST 9 #define SGSAP_LOCATION_UPDATE_ACCEPT 10 #define SGSAP_LOCATION_UPDATE_REJECT 11 @@ -38,6 +40,7 @@ extern "C" { #define SGSAP_RESET_INDICATION 21 #define SGSAP_RESET_ACK 22 #define SGSAP_MO_CSFB_INDICIATION 24 +#define SGSAP_REELASE_REQUEST 27 #define SGSAP_IE_IMSI_TYPE 1 #define SGSAP_IE_IMSI_LEN MAX_IMSI_LEN @@ -59,6 +62,7 @@ extern "C" { #define SGSAP_IE_EPS_DETACH_INDICATION_LEN 1 #define SGSAP_IE_IMSI_DETACH_INDICATION_TYPE 17 #define SGSAP_IE_IMSI_DETACH_INDICATION_LEN 1 +#define SGSAP_IE_NAS_MESSAGE_CONTAINER_TYPE 22 #define SGSAP_IE_SERVICE_INDICATOR_TYPE 32 #define SGSAP_IE_SERVICE_INDICATOR_LEN 1 #define SGSAP_IE_TAI_TYPE 35 diff --git a/tests/Makefile.am b/tests/Makefile.am index 0a021037f..f34e1027a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -45,6 +45,7 @@ testcsfb_SOURCES = \ csfb/abts-main.c csfb/test-app.c \ csfb/mo-idle-test.c csfb/mt-idle-test.c \ csfb/mo-active-test.c csfb/mt-active-test.c \ + csfb/mo-sms-test.c \ $(NULL) testcsfb_LDADD = $(top_srcdir)/src/libepc.la diff --git a/tests/common/test-packet.c b/tests/common/test-packet.c index e15ccc3c1..ff27edf53 100644 --- a/tests/common/test-packet.c +++ b/tests/common/test-packet.c @@ -3080,6 +3080,49 @@ int tests1ap_build_s1_reset(ogs_pkbuf_t **pkbuf, int i) return OGS_OK; } +int tests1ap_build_uplink_nas_transport(ogs_pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d40809d000005 0000000200010008 00020001001a0074 7327f908d4bd0307" + "636a390167000300 0581005155f55d11 030c914477680205 490000055ad2e2b1" + "252d467ff6de6c47 efd568375b303613 166fb51c6d160cc2 8ab462b006a3d98a" + "31da90060b0673c5 9c512684158bb119 2c88b3058b37e1ad 081bca84c1582d07" + "93ede4bddc6d2693 e566371b00644008 0009f1070019b010 004340060009f107" + "0007", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 162, + 0, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); + ogs_pkbuf_put_data(*pkbuf, + OGS_HEX(payload[i], strlen(payload[i]), hexbuf), len[i]); + + return OGS_OK; +} + uint16_t in_cksum(uint16_t *addr, int len); /* from pgw_gtp_path.c */ int testgtpu_build_ping( diff --git a/tests/common/test-packet.h b/tests/common/test-packet.h index 541c86f8a..d9656f92e 100644 --- a/tests/common/test-packet.h +++ b/tests/common/test-packet.h @@ -132,6 +132,8 @@ int tests1ap_build_handover_cancel(ogs_pkbuf_t **pkbuf, int i); int tests1ap_build_s1_reset(ogs_pkbuf_t **pkbuf, int i); +int tests1ap_build_uplink_nas_transport(ogs_pkbuf_t **pkbuf, int i); + int testgtpu_build_ping(ogs_pkbuf_t **sendbuf, const char *src_ip, const char *dst_ip); int testgtpu_build_slacc_rs(ogs_pkbuf_t **sendbuf, int i); diff --git a/tests/csfb/abts-main.c b/tests/csfb/abts-main.c index a978e7778..f0b390a20 100644 --- a/tests/csfb/abts-main.c +++ b/tests/csfb/abts-main.c @@ -33,6 +33,7 @@ abts_suite *test_mo_idle(abts_suite *suite); abts_suite *test_mt_idle(abts_suite *suite); abts_suite *test_mo_active(abts_suite *suite); abts_suite *test_mt_active(abts_suite *suite); +abts_suite *test_mo_sms(abts_suite *suite); const struct testlist { abts_suite *(*func)(abts_suite *suite); @@ -41,6 +42,7 @@ const struct testlist { {test_mt_idle}, {test_mo_active}, {test_mt_active}, + {test_mo_sms}, {NULL}, }; diff --git a/tests/csfb/mo-sms-test.c b/tests/csfb/mo-sms-test.c new file mode 100644 index 000000000..ed9f71e58 --- /dev/null +++ b/tests/csfb/mo-sms-test.c @@ -0,0 +1,254 @@ + +#include + +#include "core/abts.h" + +#include "app/context.h" +#include "mme/mme-context.h" +#include "mme/s1ap-build.h" +#include "asn1c/s1ap-message.h" + +#include "test-packet.h" + +extern ogs_socknode_t *sgsap; + +static void test1_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *s1ap; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + s1ap_message_t message; + int i; + int msgindex = 18; + enb_ue_t *enb_ue = NULL; + mme_ue_t *mme_ue = NULL; + uint32_t m_tmsi = 0; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c6\" }, " + "\"imsi\" : \"262420000118139\", " + "\"pdn\" : [" + "{" + "\"apn\" : \"internet\", " + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c7\" }, " + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 9, " + "\"arp\" : { " + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 0, " + "\"pre_emption_capability\" : 0" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"security\" : { " + "\"k\" : \"70D49A71DD1A2B806A25ABE0EF749F1E\", " + "\"opc\" : \"6F1BF53D624B3A43AF6592854E2444C7\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"2374\" }, " + "\"rand\" : \"aa266700bc2887354e9f87368d5d0ae7\" " + "}, " + "\"__v\" : 0 " + "}"; + + /* eNB connects to MME */ + s1ap = testenb_s1ap_client("127.0.0.1"); + ABTS_PTR_NOTNULL(tc, s1ap); + + /* Send S1-Setup Reqeust */ + rv = tests1ap_build_setup_req( + &sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0x0019b0, 7, 901, 70, 2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + rv = s1ap_decode_pdu(&message, recvbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + s1ap_free_pdu(&message); + ogs_pkbuf_free(recvbuf); + + collection = mongoc_client_get_collection( + context_self()->db.client, + context_self()->db.name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + /********** Insert Subscriber in Database */ + 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("262420000118139")); + 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); + + /* Send Attach Request */ + mme_self()->mme_ue_s1ap_id = 0; + rv = tests1ap_build_initial_ue_msg(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity-Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Identity Response */ + rv = tests1ap_build_identity_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Authentication Response */ + rv = tests1ap_build_authentication_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Security mode Complete */ + rv = tests1ap_build_security_mode_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive ESM Information Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send ESM Information Response */ + rv = tests1ap_build_esm_information_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive SGsAP-Location-Update-Request */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send SGsAP-Location-Update-Accept */ + rv = testsgsap_location_update_accept(&sendbuf, 0); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testvlr_sgsap_send(sgsap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Initial Context Setup Response */ + rv = tests1ap_build_initial_context_setup_response(&sendbuf, + 1, 1, 5, 0x00460003, "127.0.0.5"); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + rv = tests1ap_build_attach_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive EMM information */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Receive SGsAP TMSI-REALLOCATION-COMPLETE */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Uplink NAS Transport */ + rv = tests1ap_build_uplink_nas_transport(&sendbuf, 0); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive SGsAP UPLINK-UNITDATA */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send UE Context Release Request */ + rv = tests1ap_build_ue_context_release_request(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UE Context Release Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send UE Context Release Complete */ + rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8("262420000118139")); + 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 */ + testenb_s1ap_close(s1ap); +} + +abts_suite *test_mo_sms(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test1_func, NULL); + + return suite; +}