From 16a8bea96b984a7884a88ad1ae55906d79afa6f3 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 8 Jul 2019 18:15:19 +0900 Subject: [PATCH] [CSFB] MT in idle-mode --- lib/base/types.c | 2 +- lib/base/types.h | 1 + src/mme/emm-handler.c | 1 - src/mme/emm-sm.c | 13 ++++++ src/mme/mme-context.h | 4 ++ src/mme/mme-sm.c | 7 +-- src/mme/s1ap-build.c | 5 ++- src/mme/s1ap-build.h | 3 +- src/mme/s1ap-handler.c | 56 ------------------------ src/mme/s1ap-handler.h | 3 -- src/mme/s1ap-path.c | 81 +++++++++++++++++++++++++++++++++++ src/mme/s1ap-path.h | 3 ++ src/mme/sgsap-build.c | 33 ++++++++++++--- src/mme/sgsap-build.h | 1 + src/mme/sgsap-handler.c | 87 ++++++++++++++++++++++++++++++++++++++ src/mme/sgsap-handler.h | 1 + src/mme/sgsap-path.c | 17 ++++++++ src/mme/sgsap-path.h | 1 + src/mme/sgsap-sm.c | 3 ++ src/mme/sgsap-types.h | 2 +- tests/common/test-packet.c | 34 ++++++++++++--- tests/common/test-packet.h | 11 ++--- tests/csfb/mo-idle-test.c | 6 +-- tests/csfb/mt-idle-test.c | 36 +++++++++------- 24 files changed, 308 insertions(+), 103 deletions(-) diff --git a/lib/base/types.c b/lib/base/types.c index d2a84a347..8ce334db1 100644 --- a/lib/base/types.c +++ b/lib/base/types.c @@ -97,7 +97,7 @@ int fqdn_parse(char *dst, char *src, int length) dst[j++] = '.'; else dst[j] = 0; - } while(i < length); + } while (i < length); return j; } diff --git a/lib/base/types.h b/lib/base/types.h index 09cccaa87..71f653fba 100644 --- a/lib/base/types.h +++ b/lib/base/types.h @@ -60,6 +60,7 @@ extern "C" { #define MAX_APN_LEN 100 #define MAX_PCO_LEN 251 #define MAX_FILEPATH_LEN 256 +#define MAX_FQDN_LEN 256 #define NEXT_ID(__id, __min, __max) \ ((__id) = ((__id) == (__max) ? (__min) : ((__id) + 1))) diff --git a/src/mme/emm-handler.c b/src/mme/emm-handler.c index 5d3cbd1a2..5e2e78d31 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.c @@ -437,7 +437,6 @@ int emm_handle_tau_request( * Update KeNB */ CLEAR_PAGING_INFO(mme_ue); - if (BEARER_CONTEXT_IS_ACTIVE(mme_ue)) ogs_debug(" Bearer-Active"); else diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 06d0d4590..73a319846 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -353,6 +353,19 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) ogs_debug(" MO-CSFB-INDICATION[%d]", mme_ue->nas_eps.service.service_type); sgsap_send_mo_csfb_indication(mme_ue); + } else if (mme_ue->nas_eps.service.service_type == + NAS_SERVICE_TYPE_CS_FALLBACK_TO_UE) { + ogs_debug(" SERVICE_REQUEST[%d]", + mme_ue->nas_eps.service.service_type); + sgsap_send_service_request(mme_ue); + } else { + ogs_warn(" Unknown CSFB Service Type[%d]", + mme_ue->nas_eps.service.service_type); + rv = nas_send_service_reject(mme_ue, + EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(s, &emm_state_exception); + return; } ogs_debug(" Iniital UE Message"); rv = s1ap_send_initial_context_setup_request(mme_ue); diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index b3a32c202..4b03189ef 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -413,6 +413,10 @@ struct mme_ue_s { #define MAX_NUM_OF_PAGING 2 uint32_t max_paging_retry; +#define SGSAP_CS_CALL_SERVICE_INDICATOR 1 +#define SGSAP_SMS_SERVICE_INDICATOR 2 + uint8_t service_indicator; + /* UE Radio Capability */ OCTET_STRING_t ueRadioCapability; diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index e4667a780..737b6c6bf 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -447,11 +447,8 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) * If the MME receives a Downlink Data Notification after step 2 and * before step 9, the MME shall not send S1 interface paging messages */ - if (ECM_IDLE(mme_ue)) { - s1ap_handle_paging(mme_ue); - /* Start T3413 */ - ogs_timer_start(mme_ue->t3413, mme_self()->t3413_value); - } + if (ECM_IDLE(mme_ue)) + s1ap_send_paging(mme_ue, S1AP_CNDomain_ps); break; case GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: mme_s11_handle_create_indirect_data_forwarding_tunnel_response( diff --git a/src/mme/s1ap-build.c b/src/mme/s1ap-build.c index e088dad7b..cb6cd7496 100644 --- a/src/mme/s1ap-build.c +++ b/src/mme/s1ap-build.c @@ -1065,7 +1065,8 @@ int s1ap_build_ue_context_release_command( return OGS_OK; } -int s1ap_build_paging(ogs_pkbuf_t **s1apbuf, mme_ue_t *mme_ue) +int s1ap_build_paging(ogs_pkbuf_t **s1apbuf, + mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain) { int rv; @@ -1168,7 +1169,7 @@ int s1ap_build_paging(ogs_pkbuf_t **s1apbuf, mme_ue_t *mme_ue) ogs_debug(" MME_CODE[%d] M_TMSI[0x%x]", mme_ue->guti.mme_code, mme_ue->guti.m_tmsi); - *CNDomain = S1AP_CNDomain_ps; + *CNDomain = cn_domain; item = ogs_calloc(1, sizeof(S1AP_TAIItemIEs_t)); ASN_SEQUENCE_ADD(&TAIList->list, item); diff --git a/src/mme/s1ap-build.h b/src/mme/s1ap-build.h index 61732f962..cfb6804c4 100644 --- a/src/mme/s1ap-build.h +++ b/src/mme/s1ap-build.h @@ -44,7 +44,8 @@ int s1ap_build_e_rab_release_command(ogs_pkbuf_t **s1apbuf, mme_bearer_t *bearer, ogs_pkbuf_t *esmbuf, S1AP_Cause_PR group, long cause); int s1ap_build_ue_context_release_command( ogs_pkbuf_t **s1apbuf, enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause); -int s1ap_build_paging(ogs_pkbuf_t **s1apbuf, mme_ue_t *mme_ue); +int s1ap_build_paging(ogs_pkbuf_t **s1apbuf, + mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain); int s1ap_build_mme_configuration_transfer( ogs_pkbuf_t **s1apbuf, diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index bca72b8cc..10e89d988 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -904,62 +904,6 @@ void s1ap_handle_ue_context_release_complete( } } -void s1ap_handle_paging(mme_ue_t *mme_ue) -{ - ogs_pkbuf_t *s1apbuf = NULL; - ogs_hash_index_t *hi = NULL; - mme_enb_t *enb = NULL; - int i; - int rv; - - /* Find enB with matched TAI */ - for (hi = mme_enb_first(); hi; hi = mme_enb_next(hi)) { - enb = mme_enb_this(hi); - for (i = 0; i < enb->num_of_supported_ta_list; i++) { - if (!memcmp(&enb->supported_ta_list[i], - &mme_ue->tai, sizeof(tai_t))) { - if (mme_ue->last_paging_msg) { - s1apbuf = mme_ue->last_paging_msg; - /* Save it for later use */ - mme_ue->last_paging_msg = ogs_pkbuf_copy(s1apbuf); - } else { - /* Buidl S1Ap Paging message */ - rv = s1ap_build_paging(&s1apbuf, mme_ue); - ogs_assert(rv == OGS_OK && s1apbuf); - - /* Save it for later use */ - mme_ue->last_paging_msg = ogs_pkbuf_copy(s1apbuf); - } - - /* Send to enb */ - ogs_assert(s1ap_send_to_enb( - enb, s1apbuf, S1AP_NON_UE_SIGNALLING) == OGS_OK); - } - } - } -} - -void s1ap_t3413_timeout(void *data) -{ - mme_ue_t *mme_ue = data; - ogs_assert(mme_ue); - - if (mme_ue->max_paging_retry >= MAX_NUM_OF_PAGING) { - /* Paging failed */ - ogs_warn("[EMM] Paging to IMSI[%s] failed. Stop paging", - mme_ue->imsi_bcd); - if (mme_ue->last_paging_msg) { - ogs_pkbuf_free(mme_ue->last_paging_msg); - mme_ue->last_paging_msg = NULL; - } - } else { - mme_ue->max_paging_retry++; - s1ap_handle_paging(mme_ue); - /* Start T3413 */ - ogs_timer_start(mme_ue->t3413, mme_self()->t3413_value); - } -} - void s1ap_handle_path_switch_request( mme_enb_t *enb, s1ap_message_t *message) { diff --git a/src/mme/s1ap-handler.h b/src/mme/s1ap-handler.h index 8e408fb70..fd8af2f73 100644 --- a/src/mme/s1ap-handler.h +++ b/src/mme/s1ap-handler.h @@ -48,9 +48,6 @@ void s1ap_handle_ue_context_release_request( void s1ap_handle_ue_context_release_complete( mme_enb_t *enb, s1ap_message_t *message); -void s1ap_handle_paging(mme_ue_t *mme_ue); -void s1ap_t3413_timeout(void *data); - void s1ap_handle_path_switch_request( mme_enb_t *enb, s1ap_message_t *message); diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index b93a9297d..b4e6dca4e 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -284,6 +284,87 @@ int s1ap_send_ue_context_release_command( return OGS_OK; } +void s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain) +{ + ogs_pkbuf_t *s1apbuf = NULL; + ogs_hash_index_t *hi = NULL; + mme_enb_t *enb = NULL; + int i; + int rv; + + /* Find enB with matched TAI */ + for (hi = mme_enb_first(); hi; hi = mme_enb_next(hi)) { + + enb = mme_enb_this(hi); + for (i = 0; i < enb->num_of_supported_ta_list; i++) { + + if (memcmp(&enb->supported_ta_list[i], &mme_ue->tai, + sizeof(tai_t)) == 0) { + + /* Build S1AP Paging message */ + rv = s1ap_build_paging(&s1apbuf, mme_ue, cn_domain); + ogs_assert(rv == OGS_OK && s1apbuf); + + /* Save it for later use */ + ogs_assert(mme_ue->last_paging_msg == NULL); + mme_ue->last_paging_msg = ogs_pkbuf_copy(s1apbuf); + + /* Send to enb */ + rv = s1ap_send_to_enb(enb, s1apbuf, S1AP_NON_UE_SIGNALLING); + ogs_assert(rv == OGS_OK); + } + } + } + + /* Start T3413 */ + ogs_timer_start(mme_ue->t3413, mme_self()->t3413_value); +} + +void s1ap_t3413_timeout(void *data) +{ + mme_ue_t *mme_ue = data; + ogs_assert(mme_ue); + + if (mme_ue->max_paging_retry < MAX_NUM_OF_PAGING) { + ogs_pkbuf_t *s1apbuf = NULL; + ogs_hash_index_t *hi = NULL; + mme_enb_t *enb = NULL; + int i; + int rv; + + /* Find enB with matched TAI */ + for (hi = mme_enb_first(); hi; hi = mme_enb_next(hi)) { + + enb = mme_enb_this(hi); + for (i = 0; i < enb->num_of_supported_ta_list; i++) { + + if (memcmp(&enb->supported_ta_list[i], &mme_ue->tai, + sizeof(tai_t)) == 0) { + + /* Save it for later use */ + ogs_assert(mme_ue->last_paging_msg); + s1apbuf = mme_ue->last_paging_msg; + mme_ue->last_paging_msg = ogs_pkbuf_copy(s1apbuf); + + /* Send to enb */ + rv = s1ap_send_to_enb(enb, s1apbuf, S1AP_NON_UE_SIGNALLING); + ogs_assert(rv == OGS_OK); + } + } + } + + /* Start T3413 */ + ogs_timer_start(mme_ue->t3413, mme_self()->t3413_value); + + mme_ue->max_paging_retry++; + } else { + /* Paging failed */ + ogs_warn("[EMM] Paging to IMSI[%s] failed. Stop paging", + mme_ue->imsi_bcd); + CLEAR_PAGING_INFO(mme_ue); + } +} + int s1ap_send_mme_configuration_transfer( mme_enb_t *target_enb, S1AP_SONConfigurationTransfer_t *SONConfigurationTransfer) diff --git a/src/mme/s1ap-path.h b/src/mme/s1ap-path.h index 5b2a79a5f..b815d7bca 100644 --- a/src/mme/s1ap-path.h +++ b/src/mme/s1ap-path.h @@ -56,6 +56,9 @@ int s1ap_send_ue_context_release_command( enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause, uint8_t action, uint32_t delay); +void s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain); +void s1ap_t3413_timeout(void *data); + int s1ap_send_mme_configuration_transfer( mme_enb_t *target_enb, S1AP_SONConfigurationTransfer_t *SONConfigurationTransfer); diff --git a/src/mme/sgsap-build.c b/src/mme/sgsap-build.c index 05a9c3228..5e824e10b 100644 --- a/src/mme/sgsap-build.c +++ b/src/mme/sgsap-build.c @@ -163,11 +163,6 @@ ogs_pkbuf_t *sgsap_build_detach_indication(mme_ue_t *mme_ue) return pkbuf; } -ogs_pkbuf_t *sgsap_build_service_request(mme_ue_t *mme_ue) -{ - return NULL; -} - ogs_pkbuf_t *sgsap_build_mo_csfb_indication(mme_ue_t *mme_ue) { mme_vlr_t *vlr = NULL; @@ -193,6 +188,34 @@ ogs_pkbuf_t *sgsap_build_mo_csfb_indication(mme_ue_t *mme_ue) return pkbuf; } +ogs_pkbuf_t *sgsap_build_service_request(mme_ue_t *mme_ue) +{ + 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); + + 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_SERVICE_INDICATOR_TYPE, + SGSAP_IE_SERVICE_INDICATOR_LEN, 0, &mme_ue->service_indicator); + + pkbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); + ogs_pkbuf_put_u8(pkbuf, SGSAP_SERVICE_REQUEST); + 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; +} + ogs_pkbuf_t *sgsap_build_reset_ack(mme_vlr_t *vlr) { ogs_tlv_t *root = NULL; diff --git a/src/mme/sgsap-build.h b/src/mme/sgsap-build.h index 0914d7f14..857aa5001 100644 --- a/src/mme/sgsap-build.h +++ b/src/mme/sgsap-build.h @@ -31,6 +31,7 @@ ogs_pkbuf_t *sgsap_build_tmsi_reallocation_complete(mme_ue_t *mme_ue); ogs_pkbuf_t *sgsap_build_detach_indication(mme_ue_t *mme_ue); ogs_pkbuf_t *sgsap_build_service_request(mme_ue_t *mme_ue); ogs_pkbuf_t *sgsap_build_mo_csfb_indication(mme_ue_t *mme_ue); +ogs_pkbuf_t *sgsap_build_service_request(mme_ue_t *mme_ue); ogs_pkbuf_t *sgsap_build_reset_ack(mme_vlr_t *vlr); #ifdef __cplusplus diff --git a/src/mme/sgsap-handler.c b/src/mme/sgsap-handler.c index 0addcd79d..83f8935f2 100644 --- a/src/mme/sgsap-handler.c +++ b/src/mme/sgsap-handler.c @@ -24,6 +24,7 @@ #include "mme-path.h" #include "nas-conv.h" #include "nas-path.h" +#include "s1ap-path.h" void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) { @@ -83,6 +84,10 @@ void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_assert(mme_ue); ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + if (lai) { + ogs_debug(" LAI[PLMN_ID:%06x,LAC:%d]", + plmn_id_hexdump(&lai->nas_plmn_id), lai->lac); + } if (nas_mobile_identity_tmsi) { if (nas_mobile_identity_tmsi->type == NAS_MOBILE_IDENTITY_TMSI) { @@ -118,6 +123,7 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) nas_mobile_identity_imsi_t *nas_mobile_identity_imsi = NULL; int nas_mobile_identity_imsi_len = 0; nas_emm_cause_t emm_cause = 0; + nas_lai_t *lai = NULL; ogs_assert(vlr); ogs_assert(pkbuf); @@ -137,6 +143,7 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) nas_mobile_identity_imsi_len = iter->length; break; case SGSAP_IE_LAI_TYPE: + lai = iter->value; break; case SGSAP_IE_REJECT_CAUSE_TYPE: emm_cause = *((uint8_t*)(iter->value)); @@ -165,6 +172,10 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_assert(mme_ue); ogs_debug(" IMSI[%s] CAUSE[%d]", mme_ue->imsi_bcd, emm_cause); + if (lai) { + ogs_debug(" LAI[PLMN_ID:%06x,LAC:%d]", + plmn_id_hexdump(&lai->nas_plmn_id), lai->lac); + } enb_ue = mme_ue->enb_ue; ogs_assert(enb_ue); @@ -230,9 +241,85 @@ void sgsap_handle_detach_ack(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_assert(mme_ue); ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + mme_send_delete_session_or_detach(mme_ue); } +void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) +{ + ogs_tlv_t *root = NULL, *iter = NULL; + mme_ue_t *mme_ue = NULL; + + nas_mobile_identity_imsi_t *nas_mobile_identity_imsi = NULL; + int nas_mobile_identity_imsi_len = 0; + nas_lai_t *lai = NULL; + char vlr_name[SGSAP_IE_VLR_NAME_LEN] = { 0, }; + uint8_t service_indicator = 0; + + ogs_assert(vlr); + ogs_assert(pkbuf); + + ogs_debug("[SGSAP] PAGING-REQUEST"); + + ogs_pkbuf_pull(pkbuf, 1); + + root = ogs_tlv_parse_block(pkbuf->len, pkbuf->data, OGS_TLV_MODE_T1_L1); + ogs_assert(root); + + iter = root; + while (iter) { + switch (iter->type) { + case SGSAP_IE_IMSI_TYPE: + nas_mobile_identity_imsi = iter->value; + nas_mobile_identity_imsi_len = iter->length; + break; + case SGSAP_IE_VLR_NAME_TYPE: + fqdn_parse(vlr_name, iter->value, iter->length); + break; + case SGSAP_IE_LAI_TYPE: + lai = iter->value; + break; + case SGSAP_IE_SERVICE_INDICATOR_TYPE: + service_indicator = *((uint8_t*)(iter->value)); + break; + default: + ogs_warn("Invalid Type [%d]", iter->type); + break; + } + iter = iter->next; + } + + ogs_tlv_free_all(root); + + ogs_assert(nas_mobile_identity_imsi); + ogs_assert(nas_mobile_identity_imsi_len == SGSAP_IE_IMSI_LEN); + + if (nas_mobile_identity_imsi->type == NAS_MOBILE_IDENTITY_IMSI) { + char imsi_bcd[MAX_IMSI_BCD_LEN+1]; + + nas_imsi_to_bcd(nas_mobile_identity_imsi, + nas_mobile_identity_imsi_len, imsi_bcd); + mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd); + } else + ogs_assert_if_reached(); + + ogs_assert(mme_ue); + + ogs_assert(service_indicator); + mme_ue->service_indicator = service_indicator; + + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + ogs_debug(" VLR_NAME[%s]", vlr_name); + ogs_debug(" SERVICE_INDICATOR[%d]", mme_ue->service_indicator); + + if (lai) { + ogs_debug(" LAI[PLMN_ID:%06x,LAC:%d]", + plmn_id_hexdump(&lai->nas_plmn_id), lai->lac); + } + + s1ap_send_paging(mme_ue, S1AP_CNDomain_cs); +} + void sgsap_handle_reset_indication(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) { ogs_debug("[SGSAP] RESET-INDICATION"); diff --git a/src/mme/sgsap-handler.h b/src/mme/sgsap-handler.h index 331bbfdc0..a7945693f 100644 --- a/src/mme/sgsap-handler.h +++ b/src/mme/sgsap-handler.h @@ -29,6 +29,7 @@ extern "C" { void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf); void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf); void sgsap_handle_detach_ack(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf); +void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf); void sgsap_handle_reset_indication(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf); #ifdef __cplusplus diff --git a/src/mme/sgsap-path.c b/src/mme/sgsap-path.c index c2f8a4f78..235cc25d5 100644 --- a/src/mme/sgsap-path.c +++ b/src/mme/sgsap-path.c @@ -178,6 +178,23 @@ int sgsap_send_mo_csfb_indication(mme_ue_t *mme_ue) return OGS_OK; } +int sgsap_send_service_request(mme_ue_t *mme_ue) +{ + int rv; + ogs_pkbuf_t *pkbuf = NULL; + ogs_assert(mme_ue); + + ogs_debug("[SGSAP] MO-CSFB-INDICATION"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + ogs_debug(" SERVICE_INDICATOR[%d]", mme_ue->service_indicator); + + pkbuf = sgsap_build_service_request(mme_ue); + rv = sgsap_send_to_vlr(mme_ue, pkbuf); + ogs_assert(rv == OGS_OK); + + return OGS_OK; +} + int sgsap_send_reset_ack(mme_vlr_t *vlr) { int rv; diff --git a/src/mme/sgsap-path.h b/src/mme/sgsap-path.h index 0d26ea5ed..e735a2040 100644 --- a/src/mme/sgsap-path.h +++ b/src/mme/sgsap-path.h @@ -46,6 +46,7 @@ int sgsap_send_location_update_request(mme_ue_t *mme_ue); int sgsap_send_tmsi_reallocation_complete(mme_ue_t *mme_ue); 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); int sgsap_send_reset_ack(mme_vlr_t *vlr); #ifdef __cplusplus diff --git a/src/mme/sgsap-sm.c b/src/mme/sgsap-sm.c index 9dbc3eb5c..a4551fb66 100644 --- a/src/mme/sgsap-sm.c +++ b/src/mme/sgsap-sm.c @@ -127,6 +127,9 @@ void sgsap_state_connected(ogs_fsm_t *s, mme_event_t *e) case SGSAP_IMSI_DETACH_ACK: sgsap_handle_detach_ack(vlr, pkbuf); break; + case SGSAP_PAGING_REQUEST: + sgsap_handle_paging_request(vlr, pkbuf); + break; case SGSAP_RESET_INDICATION: sgsap_handle_reset_indication(vlr, pkbuf); diff --git a/src/mme/sgsap-types.h b/src/mme/sgsap-types.h index 1ba8090c1..3d750e4fa 100644 --- a/src/mme/sgsap-types.h +++ b/src/mme/sgsap-types.h @@ -41,7 +41,7 @@ extern "C" { #define SGSAP_IE_IMSI_TYPE 1 #define SGSAP_IE_IMSI_LEN MAX_IMSI_LEN #define SGSAP_IE_VLR_NAME_TYPE 2 -#define SGSAP_IE_VLR_NAME_LEN 256 +#define SGSAP_IE_VLR_NAME_LEN MAX_FQDN_LEN #define SGSAP_IE_LAI_TYPE 4 #define SGSAP_IE_LAI_LEN 5 #define SGSAP_IE_MME_NAME_TYPE 9 diff --git a/tests/common/test-packet.c b/tests/common/test-packet.c index b77cc0f5e..313266508 100644 --- a/tests/common/test-packet.c +++ b/tests/common/test-packet.c @@ -100,7 +100,7 @@ ogs_socknode_t *testsctp_client(const char *ipstr) static ogs_sockaddr_t sctp_last_addr; -ogs_pkbuf_t *testsctp_read(ogs_socknode_t *node) +ogs_pkbuf_t *testsctp_read(ogs_socknode_t *node, int type) { int size; ogs_pkbuf_t *recvbuf = NULL; @@ -111,8 +111,8 @@ ogs_pkbuf_t *testsctp_read(ogs_socknode_t *node) recvbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); ogs_pkbuf_put(recvbuf, MAX_SDU_LEN); - size = ogs_sctp_recvdata(node->sock, - recvbuf->data, MAX_SDU_LEN, &sctp_last_addr, NULL); + size = ogs_sctp_recvdata(node->sock, recvbuf->data, MAX_SDU_LEN, + type == 1 ? &sctp_last_addr : NULL, NULL); if (size <= 0) { ogs_error("sgsap_recv() failed"); return NULL; @@ -1724,8 +1724,8 @@ int tests1ap_build_tau_request(ogs_pkbuf_t **pkbuf, int i, return OGS_OK; } -int tests1ap_build_extended_service_request(ogs_pkbuf_t **pkbuf, - int i, uint32_t m_tmsi, uint8_t seq, uint8_t *knas_int) +int tests1ap_build_extended_service_request(ogs_pkbuf_t **pkbuf, int i, + uint8_t service_type, uint32_t m_tmsi, uint8_t seq, uint8_t *knas_int) { char *payload[TESTS1AP_MAX_MESSAGE] = { "", @@ -1807,6 +1807,7 @@ int tests1ap_build_extended_service_request(ogs_pkbuf_t **pkbuf, *pkbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); ogs_pkbuf_put_data(*pkbuf, OGS_HEX(payload[i], strlen(payload[i]), hexbuf), len[i]); + memcpy((*pkbuf)->data + 26, &service_type, sizeof service_type); m_tmsi = htonl(m_tmsi); memcpy((*pkbuf)->data + 29, &m_tmsi, sizeof m_tmsi); @@ -3161,6 +3162,29 @@ int testsgsap_imsi_detach_ack(ogs_pkbuf_t **pkbuf, int i) return OGS_OK; } +int testsgsap_paging_request(ogs_pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "0101082926240000 111893021003766c 72076578616d706c 65036e6574200101" + "040509f1070926", + "", + "", + + }; + uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 39, + 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; +} + int testsgsap_reset_indication(ogs_pkbuf_t **pkbuf, int i) { char *payload[TESTS1AP_MAX_MESSAGE] = { diff --git a/tests/common/test-packet.h b/tests/common/test-packet.h index 6f401c7fc..4d84c02ad 100644 --- a/tests/common/test-packet.h +++ b/tests/common/test-packet.h @@ -31,15 +31,15 @@ int testpacket_final(); ogs_socknode_t *testsctp_server(const char *ipstr); ogs_socknode_t *testsctp_client(const char *ipstr); -ogs_pkbuf_t *testsctp_read(ogs_socknode_t *node); +ogs_pkbuf_t *testsctp_read(ogs_socknode_t *node, int type); #define testenb_s1ap_client testsctp_client -#define testenb_s1ap_read testsctp_read +#define testenb_s1ap_read(x) testsctp_read(x, 0); int testenb_s1ap_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf); #define testenb_s1ap_close ogs_socknode_free #define testvlr_sgsap_server testsctp_server -#define testvlr_sgsap_read testsctp_read +#define testvlr_sgsap_read(x) testsctp_read(x, 1); int testvlr_sgsap_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf); #define testvlr_sgsap_close ogs_socknode_free @@ -82,8 +82,8 @@ int tests1ap_build_service_request(ogs_pkbuf_t **pkbuf, int tests1ap_build_tau_request(ogs_pkbuf_t **pkbuf, int i, uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id, uint8_t active_flag, uint32_t m_tmsi, uint8_t seq, uint32_t mac, uint8_t *knas_int); -int tests1ap_build_extended_service_request(ogs_pkbuf_t **pkbuf, - int i, uint32_t m_tmsi, uint8_t seq, uint8_t *knas_int); +int tests1ap_build_extended_service_request(ogs_pkbuf_t **pkbuf, int i, + uint8_t service_type, uint32_t m_tmsi, uint8_t seq, uint8_t *knas_int); int tests1ap_build_pdn_connectivity_request( ogs_pkbuf_t **pkbuf, int i); int tests1ap_build_pdn_disconnectivity_request( @@ -134,6 +134,7 @@ int testgtpu_build_slacc_rs(ogs_pkbuf_t **sendbuf, int i); int testsgsap_location_update_accept(ogs_pkbuf_t **pkbuf, int i); int testsgsap_location_update_reject(ogs_pkbuf_t **pkbuf, int i); int testsgsap_imsi_detach_ack(ogs_pkbuf_t **pkbuf, int i); +int testsgsap_paging_request(ogs_pkbuf_t **pkbuf, int i); int testsgsap_reset_indication(ogs_pkbuf_t **pkbuf, int i); #ifdef __cplusplus diff --git a/tests/csfb/mo-idle-test.c b/tests/csfb/mo-idle-test.c index c70fe0678..15568a814 100644 --- a/tests/csfb/mo-idle-test.c +++ b/tests/csfb/mo-idle-test.c @@ -744,8 +744,8 @@ static void test3_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); /* Send Extended Service Request */ - rv = tests1ap_build_extended_service_request(&sendbuf, - msgindex, m_tmsi, 4, mme_ue->knas_int); + rv = tests1ap_build_extended_service_request(&sendbuf, msgindex, + 0, m_tmsi, 4, mme_ue->knas_int); ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -755,7 +755,7 @@ static void test3_func(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, recvbuf); ogs_pkbuf_free(recvbuf); - /* Initial Context Setup Request */ + /* Receive Initial Context Setup Request */ recvbuf = testenb_s1ap_read(s1ap); ABTS_PTR_NOTNULL(tc, recvbuf); ogs_pkbuf_free(recvbuf); diff --git a/tests/csfb/mt-idle-test.c b/tests/csfb/mt-idle-test.c index a6cea05e6..8c9a5d9a1 100644 --- a/tests/csfb/mt-idle-test.c +++ b/tests/csfb/mt-idle-test.c @@ -225,12 +225,29 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - /* Send Service Request */ - rv = tests1ap_build_service_request(&sendbuf, 0x000200, 3, 0xc340, m_tmsi); + /* Send SGsAP-Paging-Request */ + rv = testsgsap_paging_request(&sendbuf, 0); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testvlr_sgsap_send(sgsap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive S1AP Paging */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Extended Service Request */ + rv = tests1ap_build_extended_service_request(&sendbuf, msgindex, + 1, m_tmsi, 4, mme_ue->knas_int); ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Receive Service Request */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + /* Receive Initial Context Setup Request */ recvbuf = testenb_s1ap_read(s1ap); ABTS_PTR_NOTNULL(tc, recvbuf); @@ -243,23 +260,12 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - /* Send Detach Request */ - rv = tests1ap_build_detach_request(&sendbuf, msgindex); + /* Send UE Context Release Request */ + rv = tests1ap_build_ue_context_release_request(&sendbuf, msgindex+1); ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - /* Receive SGsAP IMSI-DETACH-INDICATION */ - recvbuf = testvlr_sgsap_read(sgsap); - ABTS_PTR_NOTNULL(tc, recvbuf); - ogs_pkbuf_free(recvbuf); - - /* Send SGsAP IMSI-DETACH-ACK */ - rv = testsgsap_imsi_detach_ack(&sendbuf, 0); - ABTS_INT_EQUAL(tc, OGS_OK, rv); - rv = testvlr_sgsap_send(sgsap, sendbuf); - ABTS_INT_EQUAL(tc, OGS_OK, rv); - /* Receive UE Context Release Command */ recvbuf = testenb_s1ap_read(s1ap); ABTS_PTR_NOTNULL(tc, recvbuf);