diff --git a/configs/open5gs/amf.yaml.in b/configs/open5gs/amf.yaml.in index b12150138..e50cae5db 100644 --- a/configs/open5gs/amf.yaml.in +++ b/configs/open5gs/amf.yaml.in @@ -293,7 +293,7 @@ pool: # nf_instance: # heartbeat: 10 # -# o Message Wait Duration (Default : 2000ms = 2 seconds) +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # # o Message Wait Duration (3000 ms) # message: diff --git a/configs/open5gs/ausf.yaml.in b/configs/open5gs/ausf.yaml.in index d27d23b10..0f24abca3 100644 --- a/configs/open5gs/ausf.yaml.in +++ b/configs/open5gs/ausf.yaml.in @@ -169,7 +169,7 @@ pool: # nf_instance: # heartbeat: 10 # -# o Message Wait Duration (Default : 2000ms = 2 seconds) +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # # o Message Wait Duration (3000 ms) # message: diff --git a/configs/open5gs/mme.yaml.in b/configs/open5gs/mme.yaml.in index 26b3e086f..29c982930 100644 --- a/configs/open5gs/mme.yaml.in +++ b/configs/open5gs/mme.yaml.in @@ -398,3 +398,13 @@ pool: # o usrsctp_udp_port : 9899 # sctp: + +# +# time: +# +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) +# +# o Message Wait Duration (3000 ms) +# message: +# duration: 3000 +time: diff --git a/configs/open5gs/nrf.yaml.in b/configs/open5gs/nrf.yaml.in index d83a5f63d..4e320da8c 100644 --- a/configs/open5gs/nrf.yaml.in +++ b/configs/open5gs/nrf.yaml.in @@ -145,7 +145,7 @@ pool: # subscription: # validity: 3600 # -# o Message Wait Duration (Default : 2000ms = 2 seconds) +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # # o Message Wait Duration (3000 ms) # message: diff --git a/configs/open5gs/sgwc.yaml.in b/configs/open5gs/sgwc.yaml.in index fe49174d0..7e87f8abe 100644 --- a/configs/open5gs/sgwc.yaml.in +++ b/configs/open5gs/sgwc.yaml.in @@ -162,3 +162,13 @@ max: # big: 8 # pool: + +# +# time: +# +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) +# +# o Message Wait Duration (3000 ms) +# message: +# duration: 3000 +time: diff --git a/configs/open5gs/sgwu.yaml.in b/configs/open5gs/sgwu.yaml.in index 6b2ce795f..2c1188111 100644 --- a/configs/open5gs/sgwu.yaml.in +++ b/configs/open5gs/sgwu.yaml.in @@ -153,3 +153,13 @@ max: # big: 8 # pool: + +# +# time: +# +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) +# +# o Message Wait Duration (3000 ms) +# message: +# duration: 3000 +time: diff --git a/configs/open5gs/smf.yaml.in b/configs/open5gs/smf.yaml.in index a5dc9dc67..f985b6afc 100644 --- a/configs/open5gs/smf.yaml.in +++ b/configs/open5gs/smf.yaml.in @@ -346,7 +346,7 @@ pool: # nf_instance: # heartbeat: 10 # -# o Message Wait Duration (Default : 2000ms = 2 seconds) +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # # o Message Wait Duration (3000 ms) # message: diff --git a/configs/open5gs/udm.yaml.in b/configs/open5gs/udm.yaml.in index a55ef1332..8302556ca 100644 --- a/configs/open5gs/udm.yaml.in +++ b/configs/open5gs/udm.yaml.in @@ -169,7 +169,7 @@ pool: # nf_instance: # heartbeat: 10 # -# o Message Wait Duration (Default : 2000ms = 2 seconds) +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # # o Message Wait Duration (3000 ms) # message: diff --git a/configs/open5gs/udr.yaml.in b/configs/open5gs/udr.yaml.in index 3039ec3cc..53d258b88 100644 --- a/configs/open5gs/udr.yaml.in +++ b/configs/open5gs/udr.yaml.in @@ -171,7 +171,7 @@ pool: # nf_instance: # heartbeat: 10 # -# o Message Wait Duration (Default : 2000ms = 2 seconds) +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # # o Message Wait Duration (3000 ms) # message: diff --git a/configs/open5gs/upf.yaml.in b/configs/open5gs/upf.yaml.in index 54de24cac..9a12f655e 100644 --- a/configs/open5gs/upf.yaml.in +++ b/configs/open5gs/upf.yaml.in @@ -238,3 +238,13 @@ max: # big: 8 # pool: + +# +# time: +# +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) +# +# o Message Wait Duration (3000 ms) +# message: +# duration: 3000 +time: diff --git a/lib/app/ogs-context.c b/lib/app/ogs-context.c index 7e8f62b8f..3ba6d36e2 100644 --- a/lib/app/ogs-context.c +++ b/lib/app/ogs-context.c @@ -193,8 +193,15 @@ static void app_context_prepare(void) /* 86400 seconds = 1 day */ self.time.subscription.validity_duration = 86400; - /* Message Wait Duration : 2 seconds */ - self.time.message.duration = ogs_time_from_sec(2); + /* + * Message Wait Duration : 10 seconds (Default) + * + * The paging retry timer is 2 seconds and the retry count is 3. + * + * It is recomended to set at least 9 seconds to reflect + * the paging failure result to GTPv2-C or HTTP2(SBI). + */ + self.time.message.duration = ogs_time_from_sec(10); regenerate_all_timer_duration(); } diff --git a/lib/gtp/xact.c b/lib/gtp/xact.c index 01d4ae52a..71595c4c7 100644 --- a/lib/gtp/xact.c +++ b/lib/gtp/xact.c @@ -155,6 +155,11 @@ ogs_gtp_xact_t *ogs_gtp_xact_remote_create(ogs_gtp_node_t *gnode, uint32_t sqn) return xact; } +ogs_gtp_xact_t *ogs_gtp_xact_cycle(ogs_gtp_xact_t *xact) +{ + return ogs_pool_cycle(&pool, xact); +} + void ogs_gtp_xact_delete_all(ogs_gtp_node_t *gnode) { ogs_gtp_xact_t *xact = NULL, *next_xact = NULL; diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index 711c2824d..fba5f4587 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -87,12 +87,16 @@ typedef struct ogs_gtp_xact_s { #define OGS_GTP_MODIFY_QOS_UPDATE ((uint64_t)1<<1) uint64_t update_flags; -#define OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST 1 +#define OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST 1 #define OGS_GTP_DELETE_SEND_DETACH_ACCEPT 2 #define OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST 3 #define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 4 #define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 5 int delete_action; + +#define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1 +#define OGS_GTP_RELEASE_S1_CONTEXT_REMOVE 2 + int release_action; } ogs_gtp_xact_t; int ogs_gtp_xact_init(void); @@ -103,6 +107,7 @@ ogs_gtp_xact_t *ogs_gtp_xact_local_create(ogs_gtp_node_t *gnode, void (*cb)(ogs_gtp_xact_t *xact, void *data), void *data); ogs_gtp_xact_t *ogs_gtp_xact_remote_create( ogs_gtp_node_t *gnode, uint32_t sqn); +ogs_gtp_xact_t *ogs_gtp_xact_cycle(ogs_gtp_xact_t *xact); void ogs_gtp_xact_delete_all(ogs_gtp_node_t *gnode); int ogs_gtp_xact_update_tx(ogs_gtp_xact_t *xact, diff --git a/lib/pfcp/xact.c b/lib/pfcp/xact.c index 2ffd4b17f..0164a0c46 100644 --- a/lib/pfcp/xact.c +++ b/lib/pfcp/xact.c @@ -153,6 +153,11 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create( return xact; } +ogs_pfcp_xact_t *ogs_pfcp_xact_cycle(ogs_pfcp_xact_t *xact) +{ + return ogs_pool_cycle(&pool, xact); +} + void ogs_pfcp_xact_delete_all(ogs_pfcp_node_t *node) { ogs_pfcp_xact_t *xact = NULL, *next_xact = NULL; diff --git a/lib/pfcp/xact.h b/lib/pfcp/xact.h index 94894a508..916255878 100644 --- a/lib/pfcp/xact.h +++ b/lib/pfcp/xact.h @@ -99,6 +99,7 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node, void (*cb)(ogs_pfcp_xact_t *xact, void *data), void *data); ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create( ogs_pfcp_node_t *node, uint32_t sqn); +ogs_pfcp_xact_t *ogs_pfcp_xact_cycle(ogs_pfcp_xact_t *xact); void ogs_pfcp_xact_delete_all(ogs_pfcp_node_t *node); int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact, diff --git a/src/amf/amf-sm.c b/src/amf/amf-sm.c index 01d2160b9..acc6634e2 100644 --- a/src/amf/amf-sm.c +++ b/src/amf/amf-sm.c @@ -601,8 +601,9 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) gnb = amf_gnb_find_by_addr(addr); if (gnb) { - ogs_info("gNB-N1[%s] connection refused!!!", - OGS_ADDR(addr, buf)); + ogs_info("gNB-N1[%s] connection refused!!!", OGS_ADDR(addr, buf)); + amf_sbi_send_deactivate_all_ue_in_gnb( + gnb, AMF_UPDATE_SM_CONTEXT_NG_RESET); amf_gnb_remove(gnb); } else { ogs_warn("gNB-N1[%s] connection refused, Already Removed!", diff --git a/src/amf/context.c b/src/amf/context.c index 3efecc825..2e285149e 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -885,8 +885,6 @@ int amf_gnb_remove(amf_gnb_t *gnb) ogs_hash_set(self.gnb_addr_hash, gnb->addr, sizeof(ogs_sockaddr_t), NULL); ogs_hash_set(self.gnb_id_hash, &gnb->gnb_id, sizeof(gnb->gnb_id), NULL); - ran_ue_remove_in_gnb(gnb); - if (gnb->sock_type == SOCK_STREAM) { ogs_pollset_remove(gnb->poll); ogs_sctp_destroy(gnb->sock); @@ -1001,20 +999,6 @@ void ran_ue_remove(ran_ue_t *ran_ue) stats_remove_ran_ue(); } -void ran_ue_remove_in_gnb(amf_gnb_t *gnb) -{ - ran_ue_t *ran_ue = NULL, *next_ran_ue = NULL; - - ran_ue = ran_ue_first_in_gnb(gnb); - while (ran_ue) { - next_ran_ue = ran_ue_next_in_gnb(ran_ue); - - ran_ue_remove(ran_ue); - - ran_ue = next_ran_ue; - } -} - void ran_ue_switch_to_gnb(ran_ue_t *ran_ue, amf_gnb_t *new_gnb) { ogs_assert(ran_ue); @@ -1036,12 +1020,9 @@ ran_ue_t *ran_ue_find_by_ran_ue_ngap_id( { ran_ue_t *ran_ue = NULL; - ran_ue = ran_ue_first_in_gnb(gnb); - while (ran_ue) { + ogs_list_for_each(&gnb->ran_ue_list, ran_ue) { if (ran_ue_ngap_id == ran_ue->ran_ue_ngap_id) break; - - ran_ue = ran_ue_next_in_gnb(ran_ue); } return ran_ue; @@ -1058,16 +1039,6 @@ ran_ue_t *ran_ue_find_by_amf_ue_ngap_id(uint64_t amf_ue_ngap_id) return ran_ue_find(amf_ue_ngap_id); } -ran_ue_t *ran_ue_first_in_gnb(amf_gnb_t *gnb) -{ - return ogs_list_first(&gnb->ran_ue_list); -} - -ran_ue_t *ran_ue_next_in_gnb(ran_ue_t *ran_ue) -{ - return ogs_list_next(ran_ue); -} - ran_ue_t *ran_ue_cycle(ran_ue_t *ran_ue) { return ogs_pool_cycle(&ran_ue_pool, ran_ue); diff --git a/src/amf/context.h b/src/amf/context.h index 3787defcf..710ed20aa 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -477,14 +477,11 @@ int amf_gnb_sock_type(ogs_sock_t *sock); ran_ue_t *ran_ue_add(amf_gnb_t *gnb, uint32_t ran_ue_ngap_id); void ran_ue_remove(ran_ue_t *ran_ue); -void ran_ue_remove_in_gnb(amf_gnb_t *gnb); void ran_ue_switch_to_gnb(ran_ue_t *ran_ue, amf_gnb_t *new_gnb); ran_ue_t *ran_ue_find_by_ran_ue_ngap_id( amf_gnb_t *gnb, uint32_t ran_ue_ngap_id); ran_ue_t *ran_ue_find(uint32_t index); ran_ue_t *ran_ue_find_by_amf_ue_ngap_id(uint64_t amf_ue_ngap_id); -ran_ue_t *ran_ue_first_in_gnb(amf_gnb_t *gnb); -ran_ue_t *ran_ue_next_in_gnb(ran_ue_t *ran_ue); ran_ue_t *ran_ue_cycle(ran_ue_t *ran_ue); amf_ue_t *amf_ue_add(ran_ue_t *ran_ue); diff --git a/src/amf/ngap-handler.c b/src/amf/ngap-handler.c index e23272b2b..17a2d6b59 100644 --- a/src/amf/ngap-handler.c +++ b/src/amf/ngap-handler.c @@ -907,13 +907,9 @@ void ngap_handle_initial_context_setup_failure( if (amf_ue) { old_xact_count = amf_sess_xact_count(amf_ue); -#if 0 /* change buffering instead of deletion */ - amf_sbi_send_release_all_sessions(amf_ue, - AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE); -#else amf_sbi_send_deactivate_all_sessions( - amf_ue, Cause->present, (int)Cause->choice.radioNetwork); -#endif + amf_ue, AMF_UPDATE_SM_CONTEXT_DEACTIVATED, + Cause->present, (int)Cause->choice.radioNetwork); new_xact_count = amf_sess_xact_count(amf_ue); } @@ -1045,7 +1041,8 @@ void ngap_handle_ue_context_release_request( if (!PDUSessionList) { amf_sbi_send_deactivate_all_sessions( - amf_ue, Cause->present, (int)Cause->choice.radioNetwork); + amf_ue, AMF_UPDATE_SM_CONTEXT_DEACTIVATED, + Cause->present, (int)Cause->choice.radioNetwork); } else { for (i = 0; i < PDUSessionList->list.count; i++) { PDUSessionItem = (NGAP_PDUSessionResourceItemCxtRelReq_t *) @@ -1072,8 +1069,8 @@ void ngap_handle_ue_context_release_request( PDUSessionItem->pDUSessionID); if (SESSION_CONTEXT_IN_SMF(sess)) { amf_sbi_send_deactivate_session( - sess, Cause->present, - (int)Cause->choice.radioNetwork); + sess, AMF_UPDATE_SM_CONTEXT_DEACTIVATED, + Cause->present, (int)Cause->choice.radioNetwork); } } } diff --git a/src/amf/nsmf-handler.c b/src/amf/nsmf-handler.c index 63930b492..8a0efb688 100644 --- a/src/amf/nsmf-handler.c +++ b/src/amf/nsmf-handler.c @@ -318,6 +318,27 @@ int amf_nsmf_pdu_session_handle_update_sm_context( sess->n1_released = true; + } else if (state == AMF_UPDATE_SM_CONTEXT_NG_RESET) { + /* + * 1. NG RESET + * 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify + * 3. PFCP Session Modifcation Request (Apply:Buff & NOCP) + * 4. PFCP Session Modifcation Response + * 5. NG RESET ACKNOWLEDGE + */ + + /* Nothing to do */ + if (SESSION_SYNC_DONE(amf_ue)) { + ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue); + if (ran_ue) { + ogs_debug(" SUPI[%s]", amf_ue->supi); + ran_ue_remove(ran_ue); + } else { + ogs_warn("[%s] RAN-NG Context has already been removed", + amf_ue->supi); + } + } + } else { ogs_error("Invalid STATE[%d]", state); } @@ -336,7 +357,6 @@ int amf_nsmf_pdu_session_handle_update_sm_context( amf_nsmf_pdu_session_handle_release_sm_context( sess, AMF_RELEASE_SM_CONTEXT_NO_STATE); } - } } else { amf_ue_t *amf_ue = NULL; diff --git a/src/amf/sbi-path.c b/src/amf/sbi-path.c index 2f6990e33..9a7e339a0 100644 --- a/src/amf/sbi-path.c +++ b/src/amf/sbi-path.c @@ -183,7 +183,7 @@ void amf_sbi_send_activating_session(amf_sess_t *sess) } void amf_sbi_send_deactivate_session( - amf_sess_t *sess, int group, int cause) + amf_sess_t *sess, int state, int group, int cause) { amf_nsmf_pdu_session_update_sm_context_param_t param; @@ -198,12 +198,11 @@ void amf_sbi_send_deactivate_session( /* UPDATE_UpCnxState - DEACTIVATED */ amf_sess_sbi_discover_and_send(OpenAPI_nf_type_SMF, - sess, AMF_UPDATE_SM_CONTEXT_DEACTIVATED, ¶m, - amf_nsmf_pdu_session_build_update_sm_context); + sess, state, ¶m, amf_nsmf_pdu_session_build_update_sm_context); } void amf_sbi_send_deactivate_all_sessions( - amf_ue_t *amf_ue, int group, int cause) + amf_ue_t *amf_ue, int state, int group, int cause) { amf_sess_t *sess = NULL; @@ -211,7 +210,32 @@ void amf_sbi_send_deactivate_all_sessions( ogs_list_for_each(&amf_ue->sess_list, sess) { if (SESSION_CONTEXT_IN_SMF(sess)) - amf_sbi_send_deactivate_session(sess, group, cause); + amf_sbi_send_deactivate_session(sess, state, group, cause); + } +} + +void amf_sbi_send_deactivate_all_ue_in_gnb(amf_gnb_t *gnb, int state) +{ + amf_ue_t *amf_ue = NULL; + ran_ue_t *ran_ue = NULL, *ran_ue_next; + + ogs_list_for_each_safe(&gnb->ran_ue_list, ran_ue_next, ran_ue) { + int old_xact_count = 0, new_xact_count = 0; + + amf_ue = ran_ue->amf_ue; + ogs_assert(amf_ue); + + old_xact_count = amf_sess_xact_count(amf_ue); + + amf_sbi_send_deactivate_all_sessions( + amf_ue, state, NGAP_Cause_PR_radioNetwork, + NGAP_CauseRadioNetwork_failure_in_radio_interface_procedure); + + new_xact_count = amf_sess_xact_count(amf_ue); + + if (old_xact_count == new_xact_count) { + ran_ue_remove(ran_ue); + } } } diff --git a/src/amf/sbi-path.h b/src/amf/sbi-path.h index 776eba4e7..fc88401da 100644 --- a/src/amf/sbi-path.h +++ b/src/amf/sbi-path.h @@ -43,6 +43,7 @@ void amf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, #define AMF_UPDATE_SM_CONTEXT_SUSPENDED 4 #define AMF_UPDATE_SM_CONTEXT_N2_RELEASED 5 #define AMF_UPDATE_SM_CONTEXT_N1_RELEASED 6 +#define AMF_UPDATE_SM_CONTEXT_NG_RESET 7 void amf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, amf_sess_t *sess, int state, void *data, ogs_sbi_request_t *(*build)(amf_sess_t *sess, void *data)); @@ -50,9 +51,10 @@ void amf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, void amf_sbi_send_activating_session(amf_sess_t *sess); void amf_sbi_send_deactivate_session( - amf_sess_t *sess, int group, int cause); + amf_sess_t *sess, int state, int group, int cause); void amf_sbi_send_deactivate_all_sessions( - amf_ue_t *amf_ue, int group, int cause); + amf_ue_t *amf_ue, int state, int group, int cause); +void amf_sbi_send_deactivate_all_ue_in_gnb(amf_gnb_t *gnb, int state); #define AMF_RELEASE_SM_CONTEXT_NO_STATE 0 #define AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE 1 diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index bb6864682..56ac79ad9 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -153,6 +153,14 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) break; } + if (!ACTIVE_EPS_BEARERS_IS_AVAIABLE(mme_ue)) { + ogs_warn("No active EPS bearers : IMSI[%s]", mme_ue->imsi_bcd); + nas_eps_send_service_reject(mme_ue, + EMM_CAUSE_NO_EPS_BEARER_CONTEXT_ACTIVATED); + OGS_FSM_TRAN(s, &emm_state_exception); + break; + } + s1ap_send_initial_context_setup_request(mme_ue); OGS_FSM_TRAN(s, &emm_state_registered); break; @@ -181,7 +189,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST); + OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); } else { mme_s6a_send_air(mme_ue, NULL); } @@ -224,7 +232,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) } else { if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST); + OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); } else { mme_s6a_send_air(mme_ue, NULL); } @@ -258,6 +266,14 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) break; } + if (!ACTIVE_EPS_BEARERS_IS_AVAIABLE(mme_ue)) { + ogs_warn("No active EPS bearers : IMSI[%s]", mme_ue->imsi_bcd); + nas_eps_send_service_reject(mme_ue, + EMM_CAUSE_NO_EPS_BEARER_CONTEXT_ACTIVATED); + OGS_FSM_TRAN(s, &emm_state_exception); + break; + } + if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) { mme_s6a_send_air(mme_ue, NULL); OGS_FSM_TRAN(&mme_ue->sm, &emm_state_authentication); @@ -469,10 +485,13 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) mme_ue->imsi_bcd); CLEAR_MME_UE_TIMER(mme_ue->t3413); + mme_send_after_paging(mme_ue, OGS_GTP_CAUSE_UNABLE_TO_PAGE_UE); + if (CS_CALL_SERVICE_INDICATOR(mme_ue) || SMS_SERVICE_INDICATOR(mme_ue)) { sgsap_send_ue_unreachable(mme_ue, SGSAP_SGS_CAUSE_UE_UNREACHABLE); + } CLEAR_SERVICE_INDICATOR(mme_ue); @@ -892,7 +911,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) } mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST); + OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); OGS_FSM_TRAN(s, &emm_state_authentication); break; case OGS_NAS_EPS_EMM_STATUS: @@ -1008,7 +1027,7 @@ void emm_state_exception(ogs_fsm_t *s, mme_event_t *e) } else { if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST); + OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); } else { mme_s6a_send_air(mme_ue, NULL); } diff --git a/src/mme/esm-sm.c b/src/mme/esm-sm.c index 8b1fa2150..9e160623f 100644 --- a/src/mme/esm-sm.c +++ b/src/mme/esm-sm.c @@ -136,7 +136,8 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) /* Check if Initial Context Setup Response or * E-RAB Setup Response is received */ if (MME_HAVE_ENB_S1U_PATH(bearer)) { - mme_gtp_send_create_bearer_response(bearer); + mme_gtp_send_create_bearer_response( + bearer, OGS_GTP_CAUSE_REQUEST_ACCEPTED); } OGS_FSM_TRAN(s, esm_state_active); @@ -235,14 +236,16 @@ void esm_state_active(ogs_fsm_t *s, mme_event_t *e) ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", mme_ue->imsi_bcd, sess->pti, bearer->ebi); - mme_gtp_send_update_bearer_response(bearer); + mme_gtp_send_update_bearer_response( + bearer, OGS_GTP_CAUSE_REQUEST_ACCEPTED); break; case OGS_NAS_EPS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: ogs_debug("Deactivate EPS bearer " "context accept"); ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", mme_ue->imsi_bcd, sess->pti, bearer->ebi); - mme_gtp_send_delete_bearer_response(bearer); + mme_gtp_send_delete_bearer_response( + bearer, OGS_GTP_CAUSE_REQUEST_ACCEPTED); OGS_FSM_TRAN(s, esm_state_bearer_deactivated); break; case OGS_NAS_EPS_BEARER_RESOURCE_ALLOCATION_REQUEST: diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 63b3f35ed..3cec13bba 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -1931,8 +1931,6 @@ int mme_enb_remove(mme_enb_t *enb) ogs_hash_set(self.enb_addr_hash, enb->addr, sizeof(ogs_sockaddr_t), NULL); ogs_hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL); - enb_ue_remove_in_enb(enb); - if (enb->sock_type == SOCK_STREAM) { ogs_pollset_remove(enb->poll); ogs_sctp_destroy(enb->sock); @@ -2050,20 +2048,6 @@ void enb_ue_remove(enb_ue_t *enb_ue) stats_remove_enb_ue(); } -void enb_ue_remove_in_enb(mme_enb_t *enb) -{ - enb_ue_t *enb_ue = NULL, *next_enb_ue = NULL; - - enb_ue = enb_ue_first_in_enb(enb); - while (enb_ue) { - next_enb_ue = enb_ue_next_in_enb(enb_ue); - - enb_ue_remove(enb_ue); - - enb_ue = next_enb_ue; - } -} - void enb_ue_switch_to_enb(enb_ue_t *enb_ue, mme_enb_t *new_enb) { ogs_assert(enb_ue); @@ -2085,12 +2069,9 @@ enb_ue_t *enb_ue_find_by_enb_ue_s1ap_id( { enb_ue_t *enb_ue = NULL; - enb_ue = enb_ue_first_in_enb(enb); - while (enb_ue) { + ogs_list_for_each(&enb->enb_ue_list, enb_ue) { if (enb_ue_s1ap_id == enb_ue->enb_ue_s1ap_id) break; - - enb_ue = enb_ue_next_in_enb(enb_ue); } return enb_ue; @@ -2107,16 +2088,6 @@ enb_ue_t *enb_ue_find_by_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) return enb_ue_find(mme_ue_s1ap_id); } -enb_ue_t *enb_ue_first_in_enb(mme_enb_t *enb) -{ - return ogs_list_first(&enb->enb_ue_list); -} - -enb_ue_t *enb_ue_next_in_enb(enb_ue_t *enb_ue) -{ - return ogs_list_next(enb_ue); -} - enb_ue_t *enb_ue_cycle(enb_ue_t *enb_ue) { return ogs_pool_cycle(&enb_ue_pool, enb_ue); @@ -2551,47 +2522,56 @@ int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd) return OGS_OK; } -int mme_ue_have_indirect_tunnel(mme_ue_t *mme_ue) +bool mme_ue_have_indirect_tunnel(mme_ue_t *mme_ue) { mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; - sess = mme_sess_first(mme_ue); - while (sess) { - mme_bearer_t *bearer = mme_bearer_first(sess); - while (bearer) { + ogs_assert(mme_ue); + + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { if (MME_HAVE_ENB_DL_INDIRECT_TUNNEL(bearer) || MME_HAVE_ENB_UL_INDIRECT_TUNNEL(bearer) || MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) || MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer)) { - return 1; + return true; } - - bearer = mme_bearer_next(bearer); } - sess = mme_sess_next(sess); } - return 0; + return false; } -int mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue) +void mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue) { mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; ogs_assert(mme_ue); - sess = mme_sess_first(mme_ue); - while (sess) { - mme_bearer_t *bearer = mme_bearer_first(sess); - while (bearer) { + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { CLEAR_INDIRECT_TUNNEL(bearer); - - bearer = mme_bearer_next(bearer); } - sess = mme_sess_next(sess); + } +} + +bool mme_ue_have_active_eps_bearers(mme_ue_t *mme_ue) +{ + mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; + + ogs_assert(mme_ue); + + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + if (OGS_FSM_CHECK(&bearer->sm, esm_state_active)) + return true; + } } - return OGS_OK; + return false; } void mme_ue_associate_enb_ue(mme_ue_t *mme_ue, enb_ue_t *enb_ue) @@ -3076,23 +3056,9 @@ mme_bearer_t *mme_bearer_next(mme_bearer_t *bearer) return ogs_list_next(bearer); } -int mme_bearer_set_inactive(mme_ue_t *mme_ue) +mme_bearer_t *mme_bearer_cycle(mme_bearer_t *bearer) { - mme_sess_t *sess = NULL; - - ogs_assert(mme_ue); - sess = mme_sess_first(mme_ue); - while (sess) { - mme_bearer_t *bearer = mme_bearer_first(sess); - while (bearer) { - CLEAR_ENB_S1U_PATH(bearer); - - bearer = mme_bearer_next(bearer); - } - sess = mme_sess_next(sess); - } - - return OGS_OK; + return ogs_pool_cycle(&mme_bearer_pool, bearer); } void mme_pdn_remove_all(mme_ue_t *mme_ue) diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 294d34f32..aacb6b740 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -406,13 +406,13 @@ struct mme_ue_s { } while(0) OGS_POOL(ebi_pool, uint8_t); + /* Paging Info */ #define ECM_CONNECTED(__mME) \ ((__mME) && ((__mME)->enb_ue != NULL) && enb_ue_cycle((__mME)->enb_ue)) #define ECM_IDLE(__mME) \ ((__mME) && \ (((__mME)->enb_ue == NULL) || (enb_ue_cycle((__mME)->enb_ue) == NULL))) - /* S1 UE context */ - enb_ue_t *enb_ue; + enb_ue_t *enb_ue; /* S1 UE context */ /* Save PDN Connectivity Request */ ogs_nas_esm_message_container_t pdn_connectivity_request; @@ -507,17 +507,6 @@ struct mme_ue_s { mme_csmap_t *csmap; }; -#define MME_HAVE_SGW_S1U_PATH(__sESS) \ - ((__sESS) && (mme_bearer_first(__sESS)) && \ - ((mme_default_bearer_in_sess(__sESS)->sgw_s1u_teid))) -#define CLEAR_SGW_S1U_PATH(__sESS) \ - do { \ - mme_bearer_t *__bEARER = NULL; \ - ogs_assert((__sESS)); \ - __bEARER = mme_default_bearer_in_sess(__sESS); \ - __bEARER->sgw_s1u_teid = 0; \ - } while(0) - #define SESSION_CONTEXT_IS_AVAILABLE(__mME) \ ((__mME) && ((__mME)->sgw_s11_teid)) @@ -530,6 +519,9 @@ struct mme_ue_s { (__mME)->sgw_s11_teid = 0; \ (__mME)->session_context_will_deleted = 0; \ } while(0) + +#define ACTIVE_EPS_BEARERS_IS_AVAIABLE(__mME) \ + (mme_ue_have_active_eps_bearers(__mME)) typedef struct mme_sess_s { ogs_lnode_t lnode; @@ -556,9 +548,6 @@ typedef struct mme_sess_s { ogs_tlv_octet_t pgw_pco; } mme_sess_t; -#define CLEAR_BEARER_CONTEXT(__mME) \ - mme_bearer_set_inactive(__mME) - #define MME_HAVE_ENB_S1U_PATH(__bEARER) \ ((__bEARER) && ((__bEARER)->enb_s1u_teid)) #define CLEAR_ENB_S1U_PATH(__bEARER) \ @@ -567,6 +556,17 @@ typedef struct mme_sess_s { (__bEARER)->enb_s1u_teid = 0; \ } while(0) +#define MME_HAVE_SGW_S1U_PATH(__sESS) \ + ((__sESS) && (mme_bearer_first(__sESS)) && \ + ((mme_default_bearer_in_sess(__sESS)->sgw_s1u_teid))) +#define CLEAR_SGW_S1U_PATH(__sESS) \ + do { \ + mme_bearer_t *__bEARER = NULL; \ + ogs_assert((__sESS)); \ + __bEARER = mme_default_bearer_in_sess(__sESS); \ + __bEARER->sgw_s1u_teid = 0; \ + } while(0) + #define MME_HAVE_ENB_DL_INDIRECT_TUNNEL(__bEARER) \ ((__bEARER) && ((__bEARER)->enb_dl_teid)) #define MME_HAVE_ENB_UL_INDIRECT_TUNNEL(__bEARER) \ @@ -678,14 +678,11 @@ int mme_enb_sock_type(ogs_sock_t *sock); enb_ue_t *enb_ue_add(mme_enb_t *enb, uint32_t enb_ue_s1ap_id); void enb_ue_remove(enb_ue_t *enb_ue); -void enb_ue_remove_in_enb(mme_enb_t *enb); void enb_ue_switch_to_enb(enb_ue_t *enb_ue, mme_enb_t *new_enb); enb_ue_t *enb_ue_find_by_enb_ue_s1ap_id( mme_enb_t *enb, uint32_t enb_ue_s1ap_id); enb_ue_t *enb_ue_find(uint32_t index); enb_ue_t *enb_ue_find_by_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id); -enb_ue_t *enb_ue_first_in_enb(mme_enb_t *enb); -enb_ue_t *enb_ue_next_in_enb(enb_ue_t *enb_ue); enb_ue_t *enb_ue_cycle(enb_ue_t *enb_ue); mme_ue_t *mme_ue_add(enb_ue_t *enb_ue); @@ -703,8 +700,10 @@ mme_ue_t *mme_ue_find_by_teid(uint32_t teid); mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message); int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd); -int mme_ue_have_indirect_tunnel(mme_ue_t *mme_ue); -int mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue); +bool mme_ue_have_indirect_tunnel(mme_ue_t *mme_ue); +void mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue); + +bool mme_ue_have_active_eps_bearers(mme_ue_t *mme_ue); /* * o RECV Initial UE-Message : S-TMSI @@ -785,9 +784,7 @@ mme_bearer_t *mme_default_bearer_in_sess(mme_sess_t *sess); mme_bearer_t *mme_linked_bearer(mme_bearer_t *bearer); mme_bearer_t *mme_bearer_first(mme_sess_t *sess); mme_bearer_t *mme_bearer_next(mme_bearer_t *bearer); - -int mme_bearer_is_inactive(mme_ue_t *mme_ue); -int mme_bearer_set_inactive(mme_ue_t *mme_ue); +mme_bearer_t *mme_bearer_cycle(mme_bearer_t *bearer); void mme_pdn_remove_all(mme_ue_t *mme_ue); ogs_pdn_t *mme_pdn_find_by_apn(mme_ue_t *mme_ue, char *apn); diff --git a/src/mme/mme-gtp-path.c b/src/mme/mme-gtp-path.c index 5e8d32ddc..e2c9abd29 100644 --- a/src/mme/mme-gtp-path.c +++ b/src/mme/mme-gtp-path.c @@ -79,18 +79,45 @@ static void timeout(ogs_gtp_xact_t *xact, void *data) mme_ue_t *mme_ue = NULL; enb_ue_t *enb_ue = NULL; mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; uint8_t type = 0; ogs_assert(xact); type = xact->seq[0].type; switch (type) { + case OGS_GTP_RELEASE_ACCESS_BEARERS_REQUEST_TYPE: + case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: + case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: + mme_ue = data; + ogs_assert(mme_ue); + break; + case OGS_GTP_CREATE_SESSION_REQUEST_TYPE: case OGS_GTP_DELETE_SESSION_REQUEST_TYPE: sess = data; ogs_assert(sess); mme_ue = sess->mme_ue; ogs_assert(mme_ue); + break; + case OGS_GTP_MODIFY_BEARER_REQUEST_TYPE: + case OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE: + bearer = data; + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + mme_ue = sess->mme_ue; + ogs_assert(mme_ue); + break; + default: + ogs_fatal("Invalid type [%d]", type); + ogs_assert_if_reached(); + break; + } + ogs_assert(mme_ue); + + switch (type) { + case OGS_GTP_DELETE_SESSION_REQUEST_TYPE: enb_ue = enb_ue_cycle(mme_ue->enb_ue); if (enb_ue) { s1ap_send_ue_context_release_command(enb_ue, @@ -100,9 +127,10 @@ static void timeout(ogs_gtp_xact_t *xact, void *data) ogs_warn("No S1 Context"); } break; + case OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE: + /* Nothing to do */ + break; default: - mme_ue = data; - ogs_assert(mme_ue); mme_send_delete_session_or_mme_ue_context_release(mme_ue); break; } @@ -182,7 +210,7 @@ void mme_gtp_send_create_session_request(mme_sess_t *sess) pkbuf = mme_s11_build_create_session_request(h.type, sess); ogs_expect_or_return(pkbuf); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); + xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, sess); ogs_expect_or_return(xact); rv = ogs_gtp_xact_commit(xact); @@ -211,7 +239,7 @@ void mme_gtp_send_modify_bearer_request( pkbuf = mme_s11_build_modify_bearer_request(h.type, bearer, uli_presence); ogs_expect_or_return(pkbuf); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); + xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, bearer); ogs_expect_or_return(xact); rv = ogs_gtp_xact_commit(xact); @@ -283,7 +311,8 @@ void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action) } } -void mme_gtp_send_create_bearer_response(mme_bearer_t *bearer) +void mme_gtp_send_create_bearer_response( + mme_bearer_t *bearer, uint8_t cause_value) { int rv; @@ -296,14 +325,14 @@ void mme_gtp_send_create_bearer_response(mme_bearer_t *bearer) ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); - xact = bearer->xact; + xact = ogs_gtp_xact_cycle(bearer->xact); ogs_assert(xact); memset(&h, 0, sizeof(ogs_gtp_header_t)); h.type = OGS_GTP_CREATE_BEARER_RESPONSE_TYPE; h.teid = mme_ue->sgw_s11_teid; - pkbuf = mme_s11_build_create_bearer_response(h.type, bearer); + pkbuf = mme_s11_build_create_bearer_response(h.type, bearer, cause_value); ogs_expect_or_return(pkbuf); rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf); @@ -313,7 +342,8 @@ void mme_gtp_send_create_bearer_response(mme_bearer_t *bearer) ogs_expect(rv == OGS_OK); } -void mme_gtp_send_update_bearer_response(mme_bearer_t *bearer) +void mme_gtp_send_update_bearer_response( + mme_bearer_t *bearer, uint8_t cause_value) { int rv; @@ -326,14 +356,14 @@ void mme_gtp_send_update_bearer_response(mme_bearer_t *bearer) ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); - xact = bearer->xact; + xact = ogs_gtp_xact_cycle(bearer->xact); ogs_assert(xact); memset(&h, 0, sizeof(ogs_gtp_header_t)); h.type = OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE; h.teid = mme_ue->sgw_s11_teid; - pkbuf = mme_s11_build_update_bearer_response(h.type, bearer); + pkbuf = mme_s11_build_update_bearer_response(h.type, bearer, cause_value); ogs_expect_or_return(pkbuf); rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf); @@ -343,7 +373,8 @@ void mme_gtp_send_update_bearer_response(mme_bearer_t *bearer) ogs_expect(rv == OGS_OK); } -void mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer) +void mme_gtp_send_delete_bearer_response( + mme_bearer_t *bearer, uint8_t cause_value) { int rv; @@ -356,14 +387,14 @@ void mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer) ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); - xact = bearer->xact; + xact = ogs_gtp_xact_cycle(bearer->xact); ogs_assert(xact); memset(&h, 0, sizeof(ogs_gtp_header_t)); h.type = OGS_GTP_DELETE_BEARER_RESPONSE_TYPE; h.teid = mme_ue->sgw_s11_teid; - pkbuf = mme_s11_build_delete_bearer_response(h.type, bearer); + pkbuf = mme_s11_build_delete_bearer_response(h.type, bearer, cause_value); ogs_expect_or_return(pkbuf); rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf); @@ -373,13 +404,14 @@ void mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer) ogs_expect(rv == OGS_OK); } -void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue) +void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue, int action) { int rv; ogs_gtp_header_t h; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *xact = NULL; + ogs_assert(action); ogs_assert(mme_ue); memset(&h, 0, sizeof(ogs_gtp_header_t)); @@ -391,11 +423,57 @@ void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue) xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return(xact); + xact->release_action = action; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); } +void mme_gtp_send_release_all_ue_in_enb(mme_enb_t *enb, int action) +{ + mme_ue_t *mme_ue = NULL; + enb_ue_t *enb_ue = NULL; + + ogs_list_for_each(&enb->enb_ue_list, enb_ue) { + mme_ue = enb_ue->mme_ue; + ogs_assert(mme_ue); + + mme_gtp_send_release_access_bearers_request(mme_ue, action); + } +} + +void mme_gtp_send_downlink_data_notification_ack( + mme_bearer_t *bearer, uint8_t cause_value) +{ + int rv; + mme_ue_t *mme_ue = NULL; + ogs_gtp_xact_t *xact = NULL; + + ogs_gtp_header_t h; + ogs_pkbuf_t *s11buf = NULL; + + ogs_assert(bearer); + xact = ogs_gtp_xact_cycle(bearer->xact); + ogs_assert(xact); + mme_ue = bearer->mme_ue; + ogs_assert(mme_ue); + + /* Build Downlink data notification ack */ + memset(&h, 0, sizeof(ogs_gtp_header_t)); + h.type = OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE; + h.teid = mme_ue->sgw_s11_teid; + + s11buf = mme_s11_build_downlink_data_notification_ack(h.type, cause_value); + ogs_expect_or_return(s11buf); + + rv = ogs_gtp_xact_update_tx(xact, &h, s11buf); + ogs_expect_or_return(rv == OGS_OK); + + rv = ogs_gtp_xact_commit(xact); + ogs_expect(rv == OGS_OK); + +} + void mme_gtp_send_create_indirect_data_forwarding_tunnel_request( mme_ue_t *mme_ue) { diff --git a/src/mme/mme-gtp-path.h b/src/mme/mme-gtp-path.h index 4362b10e3..cb558eb46 100644 --- a/src/mme/mme-gtp-path.h +++ b/src/mme/mme-gtp-path.h @@ -34,10 +34,17 @@ void mme_gtp_send_modify_bearer_request( mme_bearer_t *bearer, int uli_presence); void mme_gtp_send_delete_session_request(mme_sess_t *sess, int action); void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action); -void mme_gtp_send_create_bearer_response(mme_bearer_t *bearer); -void mme_gtp_send_update_bearer_response(mme_bearer_t *bearer); -void mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer); -void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue); +void mme_gtp_send_create_bearer_response( + mme_bearer_t *bearer, uint8_t cause_value); +void mme_gtp_send_update_bearer_response( + mme_bearer_t *bearer, uint8_t cause_value); +void mme_gtp_send_delete_bearer_response( + mme_bearer_t *bearer, uint8_t cause_value); +void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue, int action); +void mme_gtp_send_release_all_ue_in_enb(mme_enb_t *enb, int action); + +void mme_gtp_send_downlink_data_notification_ack( + mme_bearer_t *bearer, uint8_t cause_value); void mme_gtp_send_create_indirect_data_forwarding_tunnel_request( mme_ue_t *mme_ue); diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index c376148a5..35f979a8e 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -61,7 +61,8 @@ void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue) mme_ue = enb_ue->mme_ue; if (mme_ue) { ogs_debug("[%s] Release access bearer request", mme_ue->imsi_bcd); - mme_gtp_send_release_access_bearers_request(mme_ue); + mme_gtp_send_release_access_bearers_request( + mme_ue, OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND); } else { ogs_debug("[%s] No UE Context", mme_ue->imsi_bcd); s1ap_send_ue_context_release_command(enb_ue, @@ -69,3 +70,66 @@ void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue) S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0); } } + +void mme_send_after_paging(mme_ue_t *mme_ue, uint8_t cause_value) +{ + mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; + + ogs_assert(mme_ue); + + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + ogs_gtp_xact_t *xact = NULL; + uint8_t type; + + xact = ogs_gtp_xact_cycle(bearer->xact); + if (xact) { + /* + * It may conflict with GTP transaction already used. + * To avoid this, check `xact->step` to see if + * the transaction has already been committed. + */ + type = xact->seq[xact->step-1].type; + + switch (type) { + case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_TYPE: + mme_gtp_send_downlink_data_notification_ack( + bearer, cause_value); + break; + case OGS_GTP_CREATE_BEARER_REQUEST_TYPE: + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + nas_eps_send_activate_dedicated_bearer_context_request( + bearer); + } else { + mme_gtp_send_create_bearer_response( + bearer, cause_value); + } + break; + case OGS_GTP_UPDATE_BEARER_REQUEST_TYPE: + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + nas_eps_send_modify_bearer_context_request(bearer, + (xact->update_flags & + OGS_GTP_MODIFY_QOS_UPDATE) ? 1 : 0, + (xact->update_flags & + OGS_GTP_MODIFY_TFT_UPDATE) ? 1 : 0); + } else { + mme_gtp_send_update_bearer_response( + bearer, cause_value); + } + break; + case OGS_GTP_DELETE_BEARER_REQUEST_TYPE: + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + nas_eps_send_deactivate_bearer_context_request(bearer); + } else { + mme_gtp_send_delete_bearer_response( + bearer, cause_value); + } + break; + default: + break; + } + } + } + } +} diff --git a/src/mme/mme-path.h b/src/mme/mme-path.h index 4d625b72e..8d9b27391 100644 --- a/src/mme/mme-path.h +++ b/src/mme/mme-path.h @@ -30,6 +30,8 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue); void mme_send_delete_session_or_mme_ue_context_release(mme_ue_t *mme_ue); void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue); +void mme_send_after_paging(mme_ue_t *mme_ue, uint8_t cause_value); + #ifdef __cplusplus } #endif diff --git a/src/mme/mme-s11-build.c b/src/mme/mme-s11-build.c index 229975b30..0f62eb566 100644 --- a/src/mme/mme-s11-build.c +++ b/src/mme/mme-s11-build.c @@ -51,7 +51,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( mme_ue = sess->mme_ue; ogs_assert(mme_ue); - ogs_debug("[MME] Create Session Request"); + ogs_debug("Create Session Request"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); memset(>p_message, 0, sizeof(ogs_gtp_message_t)); @@ -286,7 +286,7 @@ ogs_pkbuf_t *mme_s11_build_modify_bearer_request( mme_ue = bearer->mme_ue; ogs_assert(mme_ue); - ogs_debug("[MME] Modifty Bearer Request"); + ogs_debug("Modifty Bearer Request"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]", @@ -347,7 +347,7 @@ ogs_pkbuf_t *mme_s11_build_delete_session_request( bearer = mme_default_bearer_in_sess(sess); ogs_assert(bearer); - ogs_debug("[MME] Delete Session Request"); + ogs_debug("Delete Session Request"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); @@ -379,7 +379,7 @@ ogs_pkbuf_t *mme_s11_build_delete_session_request( } ogs_pkbuf_t *mme_s11_build_create_bearer_response( - uint8_t type, mme_bearer_t *bearer) + uint8_t type, mme_bearer_t *bearer, uint8_t cause_value) { int rv; ogs_gtp_message_t gtp_message; @@ -400,7 +400,7 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response( mme_ue = bearer->mme_ue; ogs_assert(mme_ue); - ogs_debug("[MME] Create Bearer Response"); + ogs_debug("Create Bearer Response"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); @@ -408,40 +408,42 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response( /* Set Cause */ memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + cause.value = cause_value; rsp->cause.presence = 1; rsp->cause.len = sizeof(cause); rsp->cause.data = &cause; - /* Bearer Context : EBI */ - rsp->bearer_contexts.presence = 1; - rsp->bearer_contexts.eps_bearer_id.presence = 1; - rsp->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + /* Bearer Context : EBI */ + rsp->bearer_contexts.presence = 1; + rsp->bearer_contexts.eps_bearer_id.presence = 1; + rsp->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; - /* Data Plane(DL) : ENB-S1U */ - memset(&enb_s1u_teid, 0, sizeof(ogs_gtp_f_teid_t)); - enb_s1u_teid.interface_type = OGS_GTP_F_TEID_S1_U_ENODEB_GTP_U; - enb_s1u_teid.teid = htobe32(bearer->enb_s1u_teid); - rv = ogs_gtp_ip_to_f_teid(&bearer->enb_s1u_ip, &enb_s1u_teid, &len); - ogs_assert(rv == OGS_OK); - rsp->bearer_contexts.s1_u_enodeb_f_teid.presence = 1; - rsp->bearer_contexts.s1_u_enodeb_f_teid.data = &enb_s1u_teid; - rsp->bearer_contexts.s1_u_enodeb_f_teid.len = len; - - /* Data Plane(UL) : SGW-S1U */ - memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp_f_teid_t)); - sgw_s1u_teid.interface_type = OGS_GTP_F_TEID_S1_U_SGW_GTP_U; - sgw_s1u_teid.teid = htobe32(bearer->sgw_s1u_teid); - rv = ogs_gtp_ip_to_f_teid(&bearer->sgw_s1u_ip, &sgw_s1u_teid, &len); - ogs_assert(rv == OGS_OK); - rsp->bearer_contexts.s4_u_sgsn_f_teid.presence = 1; - rsp->bearer_contexts.s4_u_sgsn_f_teid.data = &sgw_s1u_teid; - rsp->bearer_contexts.s4_u_sgsn_f_teid.len = OGS_GTP_F_TEID_IPV4_LEN; + /* Data Plane(DL) : ENB-S1U */ + memset(&enb_s1u_teid, 0, sizeof(ogs_gtp_f_teid_t)); + enb_s1u_teid.interface_type = OGS_GTP_F_TEID_S1_U_ENODEB_GTP_U; + enb_s1u_teid.teid = htobe32(bearer->enb_s1u_teid); + rv = ogs_gtp_ip_to_f_teid(&bearer->enb_s1u_ip, &enb_s1u_teid, &len); + ogs_assert(rv == OGS_OK); + rsp->bearer_contexts.s1_u_enodeb_f_teid.presence = 1; + rsp->bearer_contexts.s1_u_enodeb_f_teid.data = &enb_s1u_teid; + rsp->bearer_contexts.s1_u_enodeb_f_teid.len = len; - /* Bearer Context : Cause */ - rsp->bearer_contexts.cause.presence = 1; - rsp->bearer_contexts.cause.len = sizeof(cause); - rsp->bearer_contexts.cause.data = &cause; + /* Data Plane(UL) : SGW-S1U */ + memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp_f_teid_t)); + sgw_s1u_teid.interface_type = OGS_GTP_F_TEID_S1_U_SGW_GTP_U; + sgw_s1u_teid.teid = htobe32(bearer->sgw_s1u_teid); + rv = ogs_gtp_ip_to_f_teid(&bearer->sgw_s1u_ip, &sgw_s1u_teid, &len); + ogs_assert(rv == OGS_OK); + rsp->bearer_contexts.s4_u_sgsn_f_teid.presence = 1; + rsp->bearer_contexts.s4_u_sgsn_f_teid.data = &sgw_s1u_teid; + rsp->bearer_contexts.s4_u_sgsn_f_teid.len = OGS_GTP_F_TEID_IPV4_LEN; + + /* Bearer Context : Cause */ + rsp->bearer_contexts.cause.presence = 1; + rsp->bearer_contexts.cause.len = sizeof(cause); + rsp->bearer_contexts.cause.data = &cause; + } /* User Location Information(ULI) */ memset(&uli, 0, sizeof(ogs_gtp_uli_t)); @@ -477,7 +479,7 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response( } ogs_pkbuf_t *mme_s11_build_update_bearer_response( - uint8_t type, mme_bearer_t *bearer) + uint8_t type, mme_bearer_t *bearer, uint8_t cause_value) { ogs_gtp_message_t gtp_message; ogs_gtp_update_bearer_response_t *rsp = >p_message.update_bearer_response; @@ -495,7 +497,7 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response( mme_ue = bearer->mme_ue; ogs_assert(mme_ue); - ogs_debug("[MME] Update Bearer Response"); + ogs_debug("Update Bearer Response"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); @@ -503,20 +505,22 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response( /* Set Cause */ memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + cause.value = cause_value; rsp->cause.presence = 1; rsp->cause.len = sizeof(cause); rsp->cause.data = &cause; - /* Bearer Context : EBI */ - rsp->bearer_contexts.presence = 1; - rsp->bearer_contexts.eps_bearer_id.presence = 1; - rsp->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + /* Bearer Context : EBI */ + rsp->bearer_contexts.presence = 1; + rsp->bearer_contexts.eps_bearer_id.presence = 1; + rsp->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; - /* Bearer Context : Cause */ - rsp->bearer_contexts.cause.presence = 1; - rsp->bearer_contexts.cause.len = sizeof(cause); - rsp->bearer_contexts.cause.data = &cause; + /* Bearer Context : Cause */ + rsp->bearer_contexts.cause.presence = 1; + rsp->bearer_contexts.cause.len = sizeof(cause); + rsp->bearer_contexts.cause.data = &cause; + } /* User Location Information(ULI) */ memset(&uli, 0, sizeof(ogs_gtp_uli_t)); @@ -552,7 +556,7 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response( } ogs_pkbuf_t *mme_s11_build_delete_bearer_response( - uint8_t type, mme_bearer_t *bearer) + uint8_t type, mme_bearer_t *bearer, uint8_t cause_value) { ogs_gtp_message_t gtp_message; ogs_gtp_delete_bearer_response_t *rsp = >p_message.delete_bearer_response; @@ -570,7 +574,7 @@ ogs_pkbuf_t *mme_s11_build_delete_bearer_response( mme_ue = bearer->mme_ue; ogs_assert(mme_ue); - ogs_debug("[MME] Delete Bearer Response"); + ogs_debug("Delete Bearer Response"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); @@ -578,20 +582,22 @@ ogs_pkbuf_t *mme_s11_build_delete_bearer_response( /* Set Cause */ memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + cause.value = cause_value; rsp->cause.presence = 1; rsp->cause.len = sizeof(cause); rsp->cause.data = &cause; - /* Bearer Context : EBI */ - rsp->bearer_contexts.presence = 1; - rsp->bearer_contexts.eps_bearer_id.presence = 1; - rsp->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + /* Bearer Context : EBI */ + rsp->bearer_contexts.presence = 1; + rsp->bearer_contexts.eps_bearer_id.presence = 1; + rsp->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; - /* Bearer Context : Cause */ - rsp->bearer_contexts.cause.presence = 1; - rsp->bearer_contexts.cause.len = sizeof(cause); - rsp->bearer_contexts.cause.data = &cause; + /* Bearer Context : Cause */ + rsp->bearer_contexts.cause.presence = 1; + rsp->bearer_contexts.cause.len = sizeof(cause); + rsp->bearer_contexts.cause.data = &cause; + } /* User Location Information(ULI) */ memset(&uli, 0, sizeof(ogs_gtp_uli_t)); @@ -632,7 +638,7 @@ ogs_pkbuf_t *mme_s11_build_release_access_bearers_request(uint8_t type) ogs_gtp_release_access_bearers_request_t *req = >p_message.release_access_bearers_request; - ogs_debug("[MME] Release Access Bearers Request"); + ogs_debug("Release Access Bearers Request"); memset(>p_message, 0, sizeof(ogs_gtp_message_t)); req->originating_node.presence = 1; @@ -642,7 +648,8 @@ ogs_pkbuf_t *mme_s11_build_release_access_bearers_request(uint8_t type) return ogs_gtp_build_msg(>p_message); } -ogs_pkbuf_t *mme_s11_build_downlink_data_notification_ack(uint8_t type) +ogs_pkbuf_t *mme_s11_build_downlink_data_notification_ack( + uint8_t type, uint8_t cause_value) { ogs_gtp_message_t gtp_message; ogs_gtp_downlink_data_notification_acknowledge_t *ack = @@ -650,12 +657,12 @@ ogs_pkbuf_t *mme_s11_build_downlink_data_notification_ack(uint8_t type) ogs_gtp_cause_t cause; - ogs_debug("[MME] Downlink Data Notification Ackknowledge"); + ogs_debug("Downlink Data Notification Ackknowledge"); memset(>p_message, 0, sizeof(ogs_gtp_message_t)); memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + cause.value = cause_value; ack->cause.presence = 1; ack->cause.data = &cause; @@ -684,7 +691,7 @@ ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request( ogs_assert(mme_ue); - ogs_debug("[MME] Create Indirect Data Forwarding Tunnel Request"); + ogs_debug("Create Indirect Data Forwarding Tunnel Request"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); @@ -779,15 +786,14 @@ ogs_pkbuf_t *mme_s11_build_bearer_resource_command( tad = &modification->traffic_flow_aggregate; break; default: - ogs_error("Invalid NAS ESM Type[%d]", - nas_message->esm.h.message_type); + ogs_error("Invalid NAS ESM Type[%d]", nas_message->esm.h.message_type); return NULL; } linked_bearer = mme_linked_bearer(bearer); ogs_assert(linked_bearer); - ogs_debug("[MME] Bearer Resource Command"); + ogs_debug("Bearer Resource Command"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); diff --git a/src/mme/mme-s11-build.h b/src/mme/mme-s11-build.h index f5f46a3a0..e515b26f8 100644 --- a/src/mme/mme-s11-build.h +++ b/src/mme/mme-s11-build.h @@ -31,13 +31,14 @@ ogs_pkbuf_t *mme_s11_build_modify_bearer_request( ogs_pkbuf_t *mme_s11_build_delete_session_request( uint8_t type, mme_sess_t *sess); ogs_pkbuf_t *mme_s11_build_create_bearer_response( - uint8_t type, mme_bearer_t *bearer); + uint8_t type, mme_bearer_t *bearer, uint8_t cause_value); ogs_pkbuf_t *mme_s11_build_update_bearer_response( - uint8_t type, mme_bearer_t *bearer); + uint8_t type, mme_bearer_t *bearer, uint8_t cause_value); ogs_pkbuf_t *mme_s11_build_delete_bearer_response( - uint8_t type, mme_bearer_t *bearer); + uint8_t type, mme_bearer_t *bearer, uint8_t cause_value); ogs_pkbuf_t *mme_s11_build_release_access_bearers_request(uint8_t type); -ogs_pkbuf_t *mme_s11_build_downlink_data_notification_ack(uint8_t type); +ogs_pkbuf_t *mme_s11_build_downlink_data_notification_ack( + uint8_t type, uint8_t cause_value); ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request( uint8_t type, mme_ue_t *mme_ue); diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index 7615903ea..0d5c77c48 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -37,7 +37,7 @@ void mme_s11_handle_echo_request( ogs_assert(xact); ogs_assert(req); - ogs_debug("[MME] Receiving Echo Request"); + ogs_debug("Receiving Echo Request"); /* FIXME : Before implementing recovery counter correctly, * I'll re-use the recovery value in request message */ ogs_gtp_send_echo_response(xact, req->recovery.u8, 0); @@ -68,41 +68,13 @@ void mme_s11_handle_create_session_response( ogs_assert(xact); ogs_assert(rsp); - ogs_debug("[MME] Create Session Response"); + ogs_debug("Create Session Response"); - if (!mme_ue) { - ogs_warn("No Context in TEID"); - mme_ue = xact->data; - ogs_assert(mme_ue); - } + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); - if (rsp->cause.presence) { - ogs_gtp_cause_t *cause = rsp->cause.data; - ogs_assert(cause); - - cause_value = cause->value; - if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - if (rsp->bearer_contexts_created.cause.presence) { - cause = rsp->bearer_contexts_created.cause.data; - ogs_assert(cause); - - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - } - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - - if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) - ogs_warn("Cause[%d] : No Accepted", cause_value); - if (rsp->pdn_address_allocation.presence == 0) { ogs_error("No PDN Address Allocation"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -125,6 +97,35 @@ void mme_s11_handle_create_session_response( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (!mme_ue) { + ogs_warn("No Context in TEID"); + mme_ue = xact->data; + ogs_assert(mme_ue); + } + + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts_created.cause.presence) { + cause = rsp->bearer_contexts_created.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } else { + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { if (sess && SESSION_CONTEXT_IN_ATTACH(sess)) { ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); @@ -215,7 +216,12 @@ void mme_s11_handle_modify_bearer_response( ogs_assert(xact); ogs_assert(rsp); - ogs_debug("[MME] Modify Bearer Response"); + ogs_debug("Modify Bearer Response"); + + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + + rv = ogs_gtp_xact_commit(xact); + ogs_expect_or_return(rv == OGS_OK); if (!mme_ue) { ogs_warn("No Context in TEID"); @@ -223,9 +229,6 @@ void mme_s11_handle_modify_bearer_response( ogs_assert(mme_ue); } - rv = ogs_gtp_xact_commit(xact); - ogs_expect_or_return(rv == OGS_OK); - if (rsp->cause.presence) { ogs_gtp_cause_t *cause = rsp->cause.data; ogs_assert(cause); @@ -233,16 +236,19 @@ void mme_s11_handle_modify_bearer_response( cause_value = cause->value; if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { mme_send_delete_session_or_mme_ue_context_release(mme_ue); return; } + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH, s1ap_send_path_switch_ack(mme_ue); ); @@ -275,16 +281,16 @@ void mme_s11_handle_delete_session_response( action = xact->delete_action; ogs_assert(action); - ogs_debug("[MME] Delete Session Response"); + ogs_debug("Delete Session Response"); + + rv = ogs_gtp_xact_commit(xact); + ogs_expect_or_return(rv == OGS_OK); sess = xact->data; ogs_assert(sess); mme_ue = sess->mme_ue; ogs_assert(mme_ue); - rv = ogs_gtp_xact_commit(xact); - ogs_expect_or_return(rv == OGS_OK); - if (rsp->cause.presence) { ogs_gtp_cause_t *cause = rsp->cause.data; ogs_assert(cause); @@ -297,7 +303,7 @@ void mme_s11_handle_delete_session_response( ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST) { + if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) { if (mme_sess_count(mme_ue) == 1) /* Last Session */ { mme_s6a_send_air(mme_ue, NULL); } @@ -373,7 +379,7 @@ void mme_s11_handle_create_bearer_request( ogs_assert(xact); ogs_assert(req); - ogs_debug("[MME] Create Bearer Response"); + ogs_debug("Create Bearer Response"); cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; @@ -381,17 +387,6 @@ void mme_s11_handle_create_bearer_request( ogs_error("No Linked EBI"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - - if (mme_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8); - if (sess) bearer = mme_bearer_add(sess); - } - - if (!bearer) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -413,6 +408,16 @@ void mme_s11_handle_create_bearer_request( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (mme_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8); + if (sess) bearer = mme_bearer_add(sess); + } + + if (!bearer) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value); @@ -456,19 +461,30 @@ void mme_s11_handle_create_bearer_request( /* Save Bearer TFT */ OGS_TLV_STORE_DATA(&bearer->tft, &req->bearer_contexts.tft); - /* Save Transaction. will be handled after EMM-attached */ + /* + * Save Transaction. It will be handled after EMM-attached + * + * You should not remove OLD bearer->xact. + * If GTP-xact Holding timer is expired, + * OLD bearer->xact memory will be automatically removed. + */ bearer->xact = xact; - /* Before Activate DEDICATED bearer, we'll check DEFAULT bearer status */ + /* Before Activate DEDICATED bearer, check DEFAULT bearer status */ default_bearer = mme_default_bearer_in_sess(sess); ogs_expect_or_return(default_bearer); - if (/* Check if Activate Default Bearer Accept is received */ - OGS_FSM_CHECK(&default_bearer->sm, esm_state_active) && - /* Check if Initial Context Setup Response or - * E-RAB Setup Response is received */ - MME_HAVE_ENB_S1U_PATH(default_bearer)) { - nas_eps_send_activate_dedicated_bearer_context_request(bearer); + if (OGS_FSM_CHECK(&default_bearer->sm, esm_state_active)) { + if (ECM_IDLE(mme_ue)) { + s1ap_send_paging(mme_ue, S1AP_CNDomain_ps); + } else { + nas_eps_send_activate_dedicated_bearer_context_request(bearer); + } + } else { + /* + * After received Activate EPS default bearer context accept + * Invoke nas_eps_send_activate_all_dedicated_bearers() + */ } } @@ -484,7 +500,7 @@ void mme_s11_handle_update_bearer_request( ogs_assert(xact); ogs_assert(req); - ogs_debug("[MME] Update Bearer Request"); + ogs_debug("Update Bearer Request"); cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; @@ -526,60 +542,62 @@ void mme_s11_handle_update_bearer_request( ogs_debug(" PTI[%d]", sess->pti); } - /* Save Transaction. will be handled after EMM-attached */ + /* + * Save Transaction. It will be handled after EMM-attached + * + * You should not remove OLD bearer->xact. + * If GTP-xact Holding timer is expired, + * OLD bearer->xact memory will be automatically removed. + */ bearer->xact = xact; - if (/* Check if Activate Default/Dedicated Bearer Accept is received */ - OGS_FSM_CHECK(&bearer->sm, esm_state_active) && - /* Check if Initial Context Setup Response or - * E-RAB Setup Response is received */ - MME_HAVE_ENB_S1U_PATH(bearer)) { - if (req->bearer_contexts.bearer_level_qos.presence == 1) { - /* Bearer QoS */ - ogs_expect_or_return(ogs_gtp_parse_bearer_qos(&bearer_qos, - &req->bearer_contexts.bearer_level_qos) == - req->bearer_contexts.bearer_level_qos.len); - bearer->qos.qci = bearer_qos.qci; - bearer->qos.arp.priority_level = bearer_qos.priority_level; - bearer->qos.arp.pre_emption_capability = - bearer_qos.pre_emption_capability; - bearer->qos.arp.pre_emption_vulnerability = - bearer_qos.pre_emption_vulnerability; - bearer->qos.mbr.downlink = bearer_qos.dl_mbr; - bearer->qos.mbr.uplink = bearer_qos.ul_mbr; - bearer->qos.gbr.downlink = bearer_qos.dl_gbr; - bearer->qos.gbr.uplink = bearer_qos.ul_gbr; - } + if (req->bearer_contexts.bearer_level_qos.presence == 1) { + /* Bearer QoS */ + ogs_expect_or_return(ogs_gtp_parse_bearer_qos(&bearer_qos, + &req->bearer_contexts.bearer_level_qos) == + req->bearer_contexts.bearer_level_qos.len); + bearer->qos.qci = bearer_qos.qci; + bearer->qos.arp.priority_level = bearer_qos.priority_level; + bearer->qos.arp.pre_emption_capability = + bearer_qos.pre_emption_capability; + bearer->qos.arp.pre_emption_vulnerability = + bearer_qos.pre_emption_vulnerability; + bearer->qos.mbr.downlink = bearer_qos.dl_mbr; + bearer->qos.mbr.uplink = bearer_qos.ul_mbr; + bearer->qos.gbr.downlink = bearer_qos.dl_gbr; + bearer->qos.gbr.uplink = bearer_qos.ul_gbr; - if (req->bearer_contexts.tft.presence == 1) { - /* Save Bearer TFT */ - OGS_TLV_STORE_DATA(&bearer->tft, &req->bearer_contexts.tft); - } + xact->update_flags |= OGS_GTP_MODIFY_QOS_UPDATE; + } - if (req->bearer_contexts.bearer_level_qos.presence == 1 || - req->bearer_contexts.tft.presence == 1) { - nas_eps_send_modify_bearer_context_request(bearer, + if (req->bearer_contexts.tft.presence == 1) { + /* Save Bearer TFT */ + OGS_TLV_STORE_DATA(&bearer->tft, &req->bearer_contexts.tft); + + xact->update_flags |= OGS_GTP_MODIFY_TFT_UPDATE; + } + + if (req->bearer_contexts.bearer_level_qos.presence == 1 || + req->bearer_contexts.tft.presence == 1) { + if (ECM_IDLE(mme_ue)) { + s1ap_send_paging(mme_ue, S1AP_CNDomain_ps); + } else { + nas_eps_send_modify_bearer_context_request(bearer, req->bearer_contexts.bearer_level_qos.presence, req->bearer_contexts.tft.presence); - } else { - ogs_warn("[IGNORE] Update Bearer Request : " - "Both QoS and TFT is NULL"); - - if (xact->xid & OGS_GTP_CMD_XACT_ID) { - /* MME recieved Bearer resource modification request */ - nas_eps_send_bearer_resource_modification_reject( - bearer, ESM_CAUSE_SERVICE_OPTION_NOT_SUPPORTED); - } - - mme_gtp_send_update_bearer_response(bearer); } } else { - if (!OGS_FSM_CHECK(&bearer->sm, esm_state_active)) { - ogs_assert_if_reached(); - } else if (!MME_HAVE_ENB_S1U_PATH(bearer)) { - ogs_assert_if_reached(); - } else - ogs_assert_if_reached(); + ogs_warn("[IGNORE] Update Bearer Request : " + "Both QoS and TFT is NULL"); + + if (xact->xid & OGS_GTP_CMD_XACT_ID) { + /* MME received Bearer Resource Modification Request */ + nas_eps_send_bearer_resource_modification_reject( + bearer, ESM_CAUSE_SERVICE_OPTION_NOT_SUPPORTED); + } + + mme_gtp_send_update_bearer_response( + bearer, OGS_GTP_CAUSE_REQUEST_ACCEPTED); } } @@ -593,7 +611,7 @@ void mme_s11_handle_delete_bearer_request( ogs_assert(xact); ogs_assert(req); - ogs_debug("[MME] Delete Bearer Request"); + ogs_debug("Delete Bearer Request"); if (mme_ue && req->linked_eps_bearer_id.presence == 1) { bearer = mme_bearer_find_by_ue_ebi( @@ -632,25 +650,21 @@ void mme_s11_handle_delete_bearer_request( ogs_debug(" PTI[%d]", sess->pti); } - /* Save Transaction. will be handled after EMM-attached */ ogs_assert(bearer); + /* + * Save Transaction. It will be handled after EMM-attached + * + * You should not remove OLD bearer->xact. + * If GTP-xact Holding timer is expired, + * OLD bearer->xact memory will be automatically removed. + */ bearer->xact = xact; - if (/* Check if Activate Default/Dedicated Bearer Accept is received */ - OGS_FSM_CHECK(&bearer->sm, esm_state_active) && - /* Check if Initial Context Setup Response or - * E-RAB Setup Response is received */ - MME_HAVE_ENB_S1U_PATH(bearer)) { - nas_eps_send_deactivate_bearer_context_request(bearer); + if (ECM_IDLE(mme_ue)) { + s1ap_send_paging(mme_ue, S1AP_CNDomain_ps); } else { - if (!OGS_FSM_CHECK(&bearer->sm, esm_state_active)) { - ogs_assert_if_reached(); - } else if (!MME_HAVE_ENB_S1U_PATH(bearer)) { - ogs_assert_if_reached(); - } else - ogs_assert_if_reached(); + nas_eps_send_deactivate_bearer_context_request(bearer); } - } void mme_s11_handle_release_access_bearers_response( @@ -659,12 +673,18 @@ void mme_s11_handle_release_access_bearers_response( { int rv; uint8_t cause_value = 0; + int action = 0; enb_ue_t *enb_ue = NULL; + mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; + ogs_assert(xact); ogs_assert(rsp); + action = xact->release_action; + ogs_assert(action); - ogs_debug("[MME] Release Access Bearers Response"); + ogs_debug("Release Access Bearers Response"); if (!mme_ue) { ogs_warn("No Context in TEID"); @@ -687,21 +707,31 @@ void mme_s11_handle_release_access_bearers_response( ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - mme_send_delete_session_or_mme_ue_context_release(mme_ue); - return; + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + CLEAR_ENB_S1U_PATH(bearer); + } } - rv = CLEAR_BEARER_CONTEXT(mme_ue); - ogs_expect(rv == OGS_OK); - - enb_ue = enb_ue_cycle(mme_ue->enb_ue); - if (enb_ue) { - s1ap_send_ue_context_release_command(enb_ue, - S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, - S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0); + if (action == OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND) { + enb_ue = enb_ue_cycle(mme_ue->enb_ue); + if (enb_ue) { + s1ap_send_ue_context_release_command(enb_ue, + S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, + S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0); + } else { + ogs_warn("ENB-S1 Context has already been removed"); + } + } else if (action == OGS_GTP_RELEASE_S1_CONTEXT_REMOVE) { + enb_ue = enb_ue_cycle(mme_ue->enb_ue); + if (enb_ue) { + enb_ue_remove(enb_ue); + } else { + ogs_warn("ENB-S1 Context has already been removed"); + } } else { - ogs_warn("ENB-S1 Context has already been removed"); + ogs_fatal("Invalid action = %d", action); + ogs_assert_if_reached(); } } @@ -709,18 +739,40 @@ void mme_s11_handle_downlink_data_notification( ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, ogs_gtp_downlink_data_notification_t *noti) { - int rv; uint8_t cause_value = 0; - ogs_gtp_header_t h; - ogs_pkbuf_t *s11buf = NULL; + + mme_bearer_t *bearer = NULL; ogs_assert(xact); ogs_assert(noti); - ogs_debug("[MME] Downlink Data Notification"); + ogs_debug("Downlink Data Notification"); + + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + + if (noti->eps_bearer_id.presence == 0) { + ogs_error("No Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } if (!mme_ue) { - ogs_warn("OGS_GTP_CAUSE_CONTEXT_NOT_FOUND"); + ogs_error("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = mme_bearer_find_by_ue_ebi(mme_ue, noti->eps_bearer_id.u8); + if (!bearer) + ogs_error("No Context for EPS Bearer ID[%d]", + noti->eps_bearer_id.u8); + } + + if (!bearer) { + ogs_error("No context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE, OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); @@ -728,22 +780,18 @@ void mme_s11_handle_downlink_data_notification( } ogs_assert(mme_ue); + ogs_assert(bearer); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - /* Build Downlink data notification ack */ - memset(&h, 0, sizeof(ogs_gtp_header_t)); - h.type = OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE; - h.teid = mme_ue->sgw_s11_teid; - - s11buf = mme_s11_build_downlink_data_notification_ack(h.type); - ogs_expect_or_return(s11buf); - - rv = ogs_gtp_xact_update_tx(xact, &h, s11buf); - ogs_expect_or_return(rv == OGS_OK); - - rv = ogs_gtp_xact_commit(xact); - ogs_expect(rv == OGS_OK); + /* + * Save Transaction. It will be handled after ECM-Connected + * + * You should not remove OLD bearer->xact. + * If GTP-xact Holding timer is expired, + * OLD bearer->xact memory will be automatically removed. + */ + bearer->xact = xact; if (noti->cause.presence) { ogs_gtp_cause_t *cause = noti->cause.data; @@ -805,6 +853,9 @@ void mme_s11_handle_downlink_data_notification( s1ap_send_ue_context_release_command(enb_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, S1AP_UE_CTX_REL_S1_PAGING, 0); + } else { + mme_gtp_send_downlink_data_notification_ack( + bearer, OGS_GTP_CAUSE_UE_ALREADY_RE_ATTACHED); } } } @@ -824,7 +875,7 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( ogs_assert(xact); ogs_assert(rsp); - ogs_debug("[MME] Create Indirect Data Forwarding Tunnel Response"); + ogs_debug("Create Indirect Data Forwarding Tunnel Response"); if (!mme_ue) { ogs_warn("No Context in TEID"); @@ -896,7 +947,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( ogs_assert(xact); ogs_assert(rsp); - ogs_debug("[MME] Delete Indirect Data Forwarding Tunnel Response"); + ogs_debug("Delete Indirect Data Forwarding Tunnel Response"); if (!mme_ue) { ogs_warn("No Context in TEID"); @@ -924,8 +975,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - rv = mme_ue_clear_indirect_tunnel(mme_ue); - ogs_expect(rv == OGS_OK); + mme_ue_clear_indirect_tunnel(mme_ue); } void mme_s11_handle_bearer_resource_failure_indication( @@ -941,7 +991,7 @@ void mme_s11_handle_bearer_resource_failure_indication( bearer = xact->data; ogs_assert(ind); - ogs_debug("[MME] Bearer Resource Failure Indication"); + ogs_debug("Bearer Resource Failure Indication"); rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 18424cb6b..37ae54afc 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -225,6 +225,8 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) enb = mme_enb_find_by_addr(addr); if (enb) { ogs_info("eNB-S1[%s] connection refused!!!", OGS_ADDR(addr, buf)); + mme_gtp_send_release_all_ue_in_enb( + enb, OGS_GTP_RELEASE_S1_CONTEXT_REMOVE); mme_enb_remove(enb); } else { ogs_warn("eNB-S1[%s] connection refused, Already Removed!", diff --git a/src/mme/s1ap-build.c b/src/mme/s1ap-build.c index 3769a339d..1398daf6c 100644 --- a/src/mme/s1ap-build.c +++ b/src/mme/s1ap-build.c @@ -358,17 +358,52 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request( &UEAggregateMaximumBitrate->uEaggregateMaximumBitRateDL, subscription_data->ambr.downlink); - sess = mme_sess_first(mme_ue); - while (sess) { - bearer = mme_bearer_first(sess); - while (bearer) { + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + S1AP_E_RABToBeSetupItemCtxtSUReqIEs_t *item = NULL; S1AP_E_RABToBeSetupItemCtxtSUReq_t *e_rab = NULL; S1AP_GBR_QosInformation_t *gbrQosInformation = NULL; S1AP_NAS_PDU_t *nasPdu = NULL; - item = CALLOC( - 1, sizeof(S1AP_E_RABToBeSetupItemCtxtSUReqIEs_t)); + if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) { + /* + * For Attach Request, + * Delete Session Request/Response removes ALL session/bearers. + * + * Since all bearers are INACTIVE, + * we should not check the bearer activation. + */ + } else if (OGS_FSM_CHECK(&bearer->sm, esm_state_active)) { + /* + * For Service Request/TAU Request/Extended Service Request, + * Only the active EPS bearer can be included. + * + * If MME received Create Bearer Request and + * if MME does not receive Activate EPS Bearer Context Accept, + * We should not include the INACTIVE bearer. + * + * For example, + * 1. SGW->MME : Create Bearer Request + * 2. MME->UE : S1 Paging + * 3. UE->MME : Service Request + * 4. MME->UE : Initial Context Setup Request + * (We should not include INACTIVE BEARER) + * 5. UE->MME : Initial Context Setup Response + * 6. MME->UE : Activate dedicated EPS Bearer Context Request + * 7. UE->MME : Activate dedicated EPS Bearer Context Accept + * 8. MME->SGW : Create Bearer Response + */ + } else { + ogs_warn("No active EPS bearer [%d]", bearer->ebi); + ogs_warn(" IMSI[%s] NAS-EPS Type[%d] " + "ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", + mme_ue->imsi_bcd, mme_ue->nas_eps.type, + enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); + continue; + } + + item = CALLOC(1, sizeof(S1AP_E_RABToBeSetupItemCtxtSUReqIEs_t)); ASN_SEQUENCE_ADD(&E_RABToBeSetupListCtxtSUReq->list, item); item->id = S1AP_ProtocolIE_ID_id_E_RABToBeSetupItemCtxtSUReq; @@ -435,12 +470,11 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request( * set emmbuf to NULL as shown below */ emmbuf = NULL; } - - bearer = mme_bearer_next(bearer); } - sess = mme_sess_next(sess); } + ogs_assert(E_RABToBeSetupListCtxtSUReq->list.count); + ie = CALLOC(1, sizeof(S1AP_InitialContextSetupRequestIEs_t)); ASN_SEQUENCE_ADD(&InitialContextSetupRequest->protocolIEs, ie); @@ -1600,10 +1634,9 @@ ogs_pkbuf_t *s1ap_build_handover_command(enb_ue_t *source_ue) ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", source_ue->enb_ue_s1ap_id, source_ue->mme_ue_s1ap_id); - sess = mme_sess_first(mme_ue); - while (sess) { - bearer = mme_bearer_first(sess); - while (bearer) { + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + S1AP_E_RABDataForwardingItem_t *e_rab = NULL; if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) || @@ -1673,10 +1706,7 @@ ogs_pkbuf_t *s1ap_build_handover_command(enb_ue_t *source_ue) bearer->sgw_ul_teid, e_rab->uL_GTP_TEID); ogs_debug(" SGW-UL-TEID[%d]", bearer->sgw_dl_teid); } - - bearer = mme_bearer_next(bearer); } - sess = mme_sess_next(sess); } ie = CALLOC(1, sizeof(S1AP_HandoverCommandIEs_t)); @@ -1915,10 +1945,9 @@ ogs_pkbuf_t *s1ap_build_handover_request( &UEAggregateMaximumBitrate->uEaggregateMaximumBitRateDL, subscription_data->ambr.downlink); - sess = mme_sess_first(mme_ue); - while (sess) { - bearer = mme_bearer_first(sess); - while (bearer) { + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + S1AP_E_RABToBeSetupItemHOReqIEs_t *item = NULL; S1AP_E_RABToBeSetupItemHOReq_t *e_rab = NULL; S1AP_GBR_QosInformation_t *gbrQosInformation = NULL; @@ -1976,10 +2005,7 @@ ogs_pkbuf_t *s1ap_build_handover_request( ogs_asn_uint32_to_OCTET_STRING( bearer->sgw_s1u_teid, &e_rab->gTP_TEID); ogs_debug(" SGW-S1U-TEID[%d]", bearer->sgw_s1u_teid); - - bearer = mme_bearer_next(bearer); } - sess = mme_sess_next(sess); } ogs_s1ap_buffer_to_OCTET_STRING( diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index f4afe8ae4..e21fa03f9 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -580,18 +580,24 @@ void s1ap_handle_initial_context_setup_response( ogs_debug(" EBI[%d] ENB-S1U-TEID[%d]", bearer->ebi, bearer->enb_s1u_teid); - if (OGS_FSM_CHECK(&bearer->sm, esm_state_active)) { - ogs_debug(" NAS_EPS Type[%d]", mme_ue->nas_eps.type); - int uli_presence = 0; - if (mme_ue->nas_eps.type != MME_EPS_TYPE_ATTACH_REQUEST) { - ogs_debug(" ### ULI PRESENT ###"); - uli_presence = 1; - } + if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) { + /* For Attach Request, Nothing to do */ + } else if (OGS_FSM_CHECK(&bearer->sm, esm_state_active)) { + int uli_presence = 1; + /* + * For Service Request/TAU Request/Extended Service Request, + * ULI is present if it's the active EPS bearer. + * + */ + ogs_debug(" ### ULI PRESENT ###"); mme_gtp_send_modify_bearer_request(bearer, uli_presence); } } } + if (mme_ue->nas_eps.type != MME_EPS_TYPE_ATTACH_REQUEST) + mme_send_after_paging(mme_ue, OGS_GTP_CAUSE_REQUEST_ACCEPTED); + if (SMS_SERVICE_INDICATOR(mme_ue)) { sgsap_send_service_request(mme_ue, SGSAP_EMM_CONNECTED_MODE); } @@ -949,7 +955,8 @@ void s1ap_handle_e_rab_setup_response( if (bearer->ebi == linked_bearer->ebi) { mme_gtp_send_modify_bearer_request(bearer, 0); } else { - mme_gtp_send_create_bearer_response(bearer); + mme_gtp_send_create_bearer_response( + bearer, OGS_GTP_CAUSE_REQUEST_ACCEPTED); } } } @@ -1107,7 +1114,6 @@ void s1ap_handle_ue_context_release_complete( void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) { - int rv; mme_ue_t *mme_ue = NULL; ogs_assert(enb_ue); @@ -1144,15 +1150,14 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) enb_ue_remove(enb_ue); ogs_expect_or_return(mme_ue); - if (mme_ue_have_indirect_tunnel(mme_ue)) { + if (mme_ue_have_indirect_tunnel(mme_ue) == true) { mme_gtp_send_delete_indirect_data_forwarding_tunnel_request( mme_ue); } else { ogs_warn("Check your eNodeB"); ogs_warn(" There is no INDIRECT TUNNEL"); ogs_warn(" Packet could be dropped during S1-Handover"); - rv = mme_ue_clear_indirect_tunnel(mme_ue); - ogs_expect(rv == OGS_OK); + mme_ue_clear_indirect_tunnel(mme_ue); } break; case S1AP_UE_CTX_REL_S1_PAGING: @@ -1685,7 +1690,7 @@ void s1ap_handle_handover_request_ack( OGS_ASN_STORE_DATA(&mme_ue->container, Target_ToSource_TransparentContainer); - if (mme_ue_have_indirect_tunnel(mme_ue) == 1) { + if (mme_ue_have_indirect_tunnel(mme_ue) == true) { mme_gtp_send_create_indirect_data_forwarding_tunnel_request( mme_ue); } else { @@ -2094,7 +2099,8 @@ void s1ap_handle_s1_reset( case S1AP_ResetType_PR_s1_Interface: ogs_warn(" S1AP_ResetType_PR_s1_Interface"); - enb_ue_remove_in_enb(enb); + mme_gtp_send_release_all_ue_in_enb( + enb, OGS_GTP_RELEASE_S1_CONTEXT_REMOVE); break; case S1AP_ResetType_PR_partOfS1_Interface: ogs_warn(" S1AP_ResetType_PR_partOfS1_Interface"); @@ -2106,6 +2112,7 @@ void s1ap_handle_s1_reset( S1AP_UE_associatedLogicalS1_ConnectionItem_t *item = NULL; enb_ue_t *enb_ue = NULL; + mme_ue_t *mme_ue = NULL; ie2 = (S1AP_UE_associatedLogicalS1_ConnectionItemRes_t *) partOfS1_Interface->list.array[i]; @@ -2119,8 +2126,7 @@ void s1ap_handle_s1_reset( item->eNB_UE_S1AP_ID ? (int)*item->eNB_UE_S1AP_ID : -1); if (item->mME_UE_S1AP_ID) - enb_ue = enb_ue_find_by_mme_ue_s1ap_id( - *item->mME_UE_S1AP_ID); + enb_ue = enb_ue_find_by_mme_ue_s1ap_id( *item->mME_UE_S1AP_ID); else if (item->eNB_UE_S1AP_ID) enb_ue = enb_ue_find_by_enb_ue_s1ap_id(enb, *item->eNB_UE_S1AP_ID); @@ -2133,7 +2139,11 @@ void s1ap_handle_s1_reset( continue; } - enb_ue_remove(enb_ue); + mme_ue = enb_ue->mme_ue; + ogs_assert(mme_ue); + + mme_gtp_send_release_access_bearers_request( + mme_ue, OGS_GTP_RELEASE_S1_CONTEXT_REMOVE); } break; default: @@ -2141,6 +2151,26 @@ void s1ap_handle_s1_reset( break; } + /* + * In the specification, eNB can send RESET ACK without waiting + * for resource release, but MME must send after releasing all resources. + * + * Why? Huh.. At this point, I implemented MME to send RESET ACK + * without waiting for resource release. If problems are found, + * I will fix them later. + * + * TS36.413 + * 8.7.1.2.1 Reset Procedure Initiated from the MME + * + * The eNB does not need to wait for the release of radio resources + * to be completed before returning the RESET ACKNOWLEDGE message. + * + * 8.7.1.2.2 Reset Procedure Initiated from the E-UTRAN + * After the MME has released all assigned S1 resources and + * the UE S1AP IDs for all indicated UE associations which can be used + * for new UE-associated logical S1-connections over the S1 interface, + * the MME shall respond with the RESET ACKNOWLEDGE message. + */ s1ap_send_s1_reset_ack(enb, partOfS1_Interface); } diff --git a/src/sgwc/gtp-path.c b/src/sgwc/gtp-path.c index bc0711650..5c74aa159 100644 --- a/src/sgwc/gtp-path.c +++ b/src/sgwc/gtp-path.c @@ -139,6 +139,32 @@ void sgwc_gtp_close(void) ogs_socknode_remove_all(&sgwc_self()->gtpc_list6); } +static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) +{ + sgwc_bearer_t *bearer = data; + sgwc_sess_t *sess = NULL; + sgwc_ue_t *sgwc_ue = NULL; + uint8_t type = 0; + + ogs_assert(xact); + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + + type = xact->seq[0].type; + + switch (type) { + case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_TYPE: + ogs_error("[%s] No Downlink Data Notification ACK", sgwc_ue->imsi_bcd); + break; + default: + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + sgwc_ue->imsi_bcd, type); + } +} + void sgwc_gtp_send_downlink_data_notification( uint8_t cause_value, sgwc_bearer_t *bearer) { @@ -171,7 +197,8 @@ void sgwc_gtp_send_downlink_data_notification( pkbuf = sgwc_s11_build_downlink_data_notification(cause_value, bearer); ogs_expect_or_return(pkbuf); - gtp_xact = ogs_gtp_xact_local_create(sgwc_ue->gnode, &h, pkbuf, NULL, sess); + gtp_xact = ogs_gtp_xact_local_create( + sgwc_ue->gnode, &h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(gtp_xact); rv = ogs_gtp_xact_commit(gtp_xact); diff --git a/src/sgwc/s11-handler.c b/src/sgwc/s11-handler.c index 9fa2c216b..4e4401c8a 100644 --- a/src/sgwc/s11-handler.c +++ b/src/sgwc/s11-handler.c @@ -22,7 +22,7 @@ #include "s11-handler.h" -static void timeout(ogs_gtp_xact_t *xact, void *data) +static void sess_timeout(ogs_gtp_xact_t *xact, void *data) { sgwc_sess_t *sess = data; sgwc_ue_t *sgwc_ue = NULL; @@ -35,6 +35,33 @@ static void timeout(ogs_gtp_xact_t *xact, void *data) type = xact->seq[0].type; + switch (type) { + case OGS_GTP_DELETE_SESSION_REQUEST_TYPE: + ogs_error("[%s] No Delete Session Response", sgwc_ue->imsi_bcd); + sgwc_pfcp_send_session_deletion_request(sess, NULL, NULL); + break; + default: + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + sgwc_ue->imsi_bcd, type); + } +} + +static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) +{ + sgwc_bearer_t *bearer = data; + sgwc_sess_t *sess = NULL; + sgwc_ue_t *sgwc_ue = NULL; + uint8_t type = 0; + + ogs_assert(xact); + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + + type = xact->seq[0].type; + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", sgwc_ue->imsi_bcd, type); } @@ -106,11 +133,6 @@ void sgwc_s11_handle_create_session_request( cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - if (!sgwc_ue) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - if (req->imsi.presence == 0) { ogs_error("No IMSI"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -148,6 +170,11 @@ void sgwc_s11_handle_create_session_request( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (!sgwc_ue) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, @@ -266,8 +293,17 @@ void sgwc_s11_handle_modify_bearer_request( ogs_error("No EPS Bearer ID"); cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence == 0) { + ogs_error("No eNB TEID"); + cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } - if (sgwc_ue && cause.value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (!sgwc_ue) { + ogs_error("No Context"); + cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause.value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { bearer = sgwc_bearer_find_by_ue_ebi(sgwc_ue, req->bearer_contexts_to_be_modified.eps_bearer_id.u8); if (!bearer) @@ -280,11 +316,6 @@ void sgwc_s11_handle_modify_bearer_request( cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; } - if (req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence == 0) { - ogs_error("No eNB TEID"); - cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, @@ -385,16 +416,28 @@ void sgwc_s11_handle_delete_session_request( cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - if (!sgwc_ue) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - if (req->linked_eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (!sgwc_ue) { + ogs_error("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + sess = sgwc_sess_find_by_ebi(sgwc_ue, req->linked_eps_bearer_id.u8); + if (!sess) + ogs_error("Unknown EPS Bearer [IMSI:%s, EBI:%d]", + sgwc_ue->imsi_bcd, req->linked_eps_bearer_id.u8); + } + + if (!sess) { + ogs_error("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, @@ -403,17 +446,6 @@ void sgwc_s11_handle_delete_session_request( } ogs_assert(sgwc_ue); - sess = sgwc_sess_find_by_ebi(sgwc_ue, req->linked_eps_bearer_id.u8); - if (!sess) { - ogs_error("No Context [IMSI:%s, EBI:%d]", - sgwc_ue->imsi_bcd, req->linked_eps_bearer_id.u8); - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); - return; - } - ogs_assert(sess); ogs_assert(sess->gnode); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", @@ -428,7 +460,7 @@ void sgwc_s11_handle_delete_session_request( ogs_expect_or_return(gtpbuf); s5c_xact = ogs_gtp_xact_local_create( - sess->gnode, &message->h, gtpbuf, timeout, sess); + sess->gnode, &message->h, gtpbuf, sess_timeout, sess); ogs_expect_or_return(s5c_xact); ogs_gtp_xact_associate(s11_xact, s5c_xact); @@ -465,40 +497,11 @@ void sgwc_s11_handle_create_bearer_response( ogs_debug("Create Bearer Response"); - if (!sgwc_ue) { - sgwc_sess_t *sess = NULL; - - ogs_warn("No Context in TEID"); - sess = s11_xact->data; - ogs_assert(sess); - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - } + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); - if (rsp->cause.presence) { - ogs_gtp_cause_t *cause = rsp->cause.data; - ogs_assert(cause); - - cause_value = cause->value; - if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - if (rsp->bearer_contexts.cause.presence) { - cause = rsp->bearer_contexts.cause.data; - ogs_assert(cause); - - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - } - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts.presence == 0) { ogs_error("No Bearer"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -520,14 +523,57 @@ void sgwc_s11_handle_create_bearer_response( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (s11_xact->xid & OGS_GTP_CMD_XACT_ID) + /* MME received Bearer Resource Modification Request */ + bearer = s5c_xact->data; + else + bearer = s11_xact->data; + + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + + if (!sgwc_ue) { + ogs_warn("No Context in TEID"); + + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts.cause.presence) { + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } else { + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + sgwc_pfcp_send_bearer_modification_request( + bearer, NULL, NULL, + OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE); ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value); return; } - ogs_assert(sgwc_ue); - /* Correlate with SGW-S1U-TEID */ sgw_s1u_teid = rsp->bearer_contexts.s4_u_sgsn_f_teid.data; ogs_assert(sgw_s1u_teid); @@ -535,12 +581,8 @@ void sgwc_s11_handle_create_bearer_response( /* Find the Tunnel by SGW-S1U-TEID */ ul_tunnel = sgwc_tunnel_find_by_teid(sgwc_ue, be32toh(sgw_s1u_teid->teid)); ogs_assert(ul_tunnel); - bearer = ul_tunnel->bearer; - ogs_assert(bearer); dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer); ogs_assert(dl_tunnel); - sess = bearer->sess; - ogs_assert(sess); /* Set EBI */ bearer->ebi = rsp->bearer_contexts.eps_bearer_id.u8; @@ -597,37 +639,58 @@ void sgwc_s11_handle_update_bearer_response( ogs_gtp_xact_t *s5c_xact = NULL; sgwc_sess_t *sess = NULL; sgwc_bearer_t *bearer = NULL; - ogs_gtp_update_bearer_response_t *req = NULL; + ogs_gtp_update_bearer_response_t *rsp = NULL; ogs_assert(s11_xact); s5c_xact = s11_xact->assoc_xact; ogs_assert(s5c_xact); ogs_assert(message); - req = &message->update_bearer_response; - ogs_assert(req); + rsp = &message->update_bearer_response; + ogs_assert(rsp); ogs_debug("Update Bearer Response"); - if (!sgwc_ue) { - sgwc_sess_t *sess = NULL; - ogs_warn("No Context in TEID"); - sess = s11_xact->data; - ogs_assert(sess); - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - } + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); - if (req->cause.presence) { - ogs_gtp_cause_t *cause = req->cause.data; + if (rsp->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (s11_xact->xid & OGS_GTP_CMD_XACT_ID) + /* MME received Bearer Resource Modification Request */ + bearer = s5c_xact->data; + else + bearer = s11_xact->data; + + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + + if (!sgwc_ue) { + ogs_warn("No Context in TEID"); + + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; ogs_assert(cause); cause_value = cause->value; if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - if (req->bearer_contexts.cause.presence) { - cause = req->bearer_contexts.cause.data; + if (rsp->bearer_contexts.cause.presence) { + cause = rsp->bearer_contexts.cause.data; ogs_assert(cause); cause_value = cause->value; @@ -635,41 +698,20 @@ void sgwc_s11_handle_update_bearer_response( ogs_error("No Cause"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + } else { + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } } else { ogs_error("No Cause"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (req->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - if (req->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - - if (sgwc_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - bearer = sgwc_bearer_find_by_ue_ebi( - sgwc_ue, req->bearer_contexts.eps_bearer_id.u8); - } - - if (!bearer) { - ogs_error("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE, cause_value); return; } - ogs_assert(bearer); - sess = bearer->sess; - ogs_assert(sess); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", @@ -698,38 +740,58 @@ void sgwc_s11_handle_delete_bearer_response( sgwc_sess_t *sess = NULL; sgwc_bearer_t *bearer = NULL; - ogs_gtp_delete_bearer_response_t *req = NULL; + ogs_gtp_delete_bearer_response_t *rsp = NULL; ogs_assert(s11_xact); s5c_xact = s11_xact->assoc_xact; ogs_assert(s5c_xact); ogs_assert(message); - req = &message->delete_bearer_response; - ogs_assert(req); + rsp = &message->delete_bearer_response; + ogs_assert(rsp); ogs_debug("Delete Bearer Response"); - if (!sgwc_ue) { - sgwc_sess_t *sess = NULL; - - ogs_warn("No Context in TEID"); - sess = s11_xact->data; - ogs_assert(sess); - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - } + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); - if (req->cause.presence) { - ogs_gtp_cause_t *cause = req->cause.data; + if (rsp->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (s11_xact->xid & OGS_GTP_CMD_XACT_ID) + /* MME received Bearer Resource Modification Request */ + bearer = s5c_xact->data; + else + bearer = s11_xact->data; + + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + + if (!sgwc_ue) { + ogs_warn("No Context in TEID"); + + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; ogs_assert(cause); cause_value = cause->value; if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - if (req->bearer_contexts.cause.presence) { - cause = req->bearer_contexts.cause.data; + if (rsp->bearer_contexts.cause.presence) { + cause = rsp->bearer_contexts.cause.data; ogs_assert(cause); cause_value = cause->value; @@ -737,41 +799,14 @@ void sgwc_s11_handle_delete_bearer_response( ogs_error("No Cause"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + } else { + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } } else { ogs_error("No Cause"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (req->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - if (req->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - - if (sgwc_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - bearer = sgwc_bearer_find_by_ue_ebi( - sgwc_ue, req->bearer_contexts.eps_bearer_id.u8); - ogs_assert(bearer); - } - - if (!bearer) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - - if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, - OGS_GTP_DELETE_BEARER_RESPONSE_TYPE, cause_value); - return; - } - - sess = bearer->sess; - ogs_assert(sess); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", @@ -833,6 +868,7 @@ void sgwc_s11_handle_downlink_data_notification_ack( int rv; uint8_t cause_value; + sgwc_bearer_t *bearer = NULL; sgwc_sess_t *sess = NULL; ogs_gtp_downlink_data_notification_acknowledge_t *ack = NULL; @@ -842,11 +878,15 @@ void sgwc_s11_handle_downlink_data_notification_ack( ack = &message->downlink_data_notification_acknowledge; ogs_assert(ack); - sess = s11_xact->data; + bearer = s11_xact->data; + ogs_assert(bearer); + sess = bearer->sess; ogs_assert(sess); sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); @@ -1048,6 +1088,7 @@ void sgwc_s11_handle_bearer_resource_command( ogs_gtp_xact_t *s5c_xact = NULL; sgwc_sess_t *sess = NULL; + sgwc_bearer_t *bearer = NULL; ogs_assert(s11_xact); ogs_assert(message); @@ -1057,23 +1098,6 @@ void sgwc_s11_handle_bearer_resource_command( cmd = &message->bearer_resource_command; cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - if (!sgwc_ue) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - - if (cmd->linked_eps_bearer_id.presence == 0) { - ogs_error("No Linked EPS Bearer ID"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } else { - sess = sgwc_sess_find_by_ebi(sgwc_ue, cmd->linked_eps_bearer_id.u8); - if (!sess) { - ogs_error("No Context for Linked EPS Bearer ID[%d]", - cmd->linked_eps_bearer_id.u8); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - } - if (cmd->procedure_transaction_id.presence == 0) { ogs_error("No PTI"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -1082,6 +1106,28 @@ void sgwc_s11_handle_bearer_resource_command( ogs_error("No Traffic aggregate description(TAD)"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (cmd->linked_eps_bearer_id.presence == 0) { + ogs_error("No Linked EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (!sgwc_ue) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = sgwc_bearer_find_by_ue_ebi( + sgwc_ue, cmd->linked_eps_bearer_id.u8); + if (!bearer) + ogs_error("No Context for Linked EPS Bearer ID[%d]", + cmd->linked_eps_bearer_id.u8); + } + + if (!bearer) { + ogs_error("No context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( @@ -1090,6 +1136,8 @@ void sgwc_s11_handle_bearer_resource_command( return; } + ogs_assert(bearer); + sess = bearer->sess; ogs_assert(sess); ogs_assert(sess->gnode); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", @@ -1104,7 +1152,7 @@ void sgwc_s11_handle_bearer_resource_command( ogs_expect_or_return(pkbuf); s5c_xact = ogs_gtp_xact_local_create( - sess->gnode, &message->h, pkbuf, timeout, sess); + sess->gnode, &message->h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(s5c_xact); ogs_gtp_xact_associate(s11_xact, s5c_xact); diff --git a/src/sgwc/s5c-handler.c b/src/sgwc/s5c-handler.c index bca61f413..4cf3e60dc 100644 --- a/src/sgwc/s5c-handler.c +++ b/src/sgwc/s5c-handler.c @@ -22,21 +22,35 @@ #include "s5c-handler.h" -static void timeout(ogs_gtp_xact_t *xact, void *data) +static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) { - sgwc_sess_t *sess = data; + sgwc_bearer_t *bearer = data; + sgwc_sess_t *sess = NULL; sgwc_ue_t *sgwc_ue = NULL; uint8_t type = 0; ogs_assert(xact); + ogs_assert(bearer); + sess = bearer->sess; ogs_assert(sess); sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); type = xact->seq[0].type; - ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", - sgwc_ue->imsi_bcd, type); + switch (type) { + case OGS_GTP_UPDATE_BEARER_REQUEST_TYPE: + ogs_error("[%s] No Update Bearer Response", sgwc_ue->imsi_bcd); + break; + case OGS_GTP_DELETE_BEARER_REQUEST_TYPE: + ogs_error("[%s] No Delete Bearer Response", sgwc_ue->imsi_bcd); + sgwc_pfcp_send_bearer_modification_request( + bearer, NULL, NULL, OGS_PFCP_MODIFY_REMOVE); + break; + default: + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + sgwc_ue->imsi_bcd, type); + } } void sgwc_s5c_handle_create_session_response( @@ -67,47 +81,11 @@ void sgwc_s5c_handle_create_session_response( ogs_debug("Create Session Response"); - if (!sess) { - ogs_warn("No Context in TEID"); - sess = s5c_xact->data; - ogs_assert(sess); - } + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(s5c_xact); ogs_expect(rv == OGS_OK); - if (rsp->cause.presence) { - ogs_gtp_cause_t *cause = rsp->cause.data; - ogs_assert(cause); - - cause_value = cause->value; - if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - if (rsp->bearer_contexts_created.cause.presence) { - cause = rsp->bearer_contexts_created.cause.data; - ogs_assert(cause); - - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - } else { - /* Deliver PGW cause value to the MME */ - ogs_warn("Cause[%d] : No Accepted", cause_value); - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - cause_value); - return; - } - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } - - if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) - ogs_warn("Cause[%d] : No Accepted", cause_value); - if (rsp->bearer_contexts_created.cause.presence == 0) { ogs_error("No EPS Bearer Cause"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -121,21 +99,6 @@ void sgwc_s5c_handle_create_session_response( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - bearer = sgwc_bearer_find_by_sess_ebi(sess, - rsp->bearer_contexts_created.eps_bearer_id.u8); - ogs_assert(bearer); - ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer); - ogs_assert(ul_tunnel); - - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - } - if (!bearer) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. presence == 0) { ogs_error("No GTP TEID"); @@ -167,13 +130,62 @@ void sgwc_s5c_handle_create_session_response( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (!sess) { + ogs_warn("No Context in TEID"); + sess = s5c_xact->data; + ogs_assert(sess); + } + + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = sgwc_bearer_find_by_sess_ebi(sess, + rsp->bearer_contexts_created.eps_bearer_id.u8); + if (!bearer) + ogs_error("No Context for EPS Bearer ID[%d]", + rsp->bearer_contexts_created.eps_bearer_id.u8); + } + if (!bearer) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts_created.cause.presence) { + cause = rsp->bearer_contexts_created.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } else { + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + sgwc_pfcp_send_session_deletion_request(sess, NULL, NULL); ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value); return; } + ogs_assert(bearer); + ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer); + ogs_assert(ul_tunnel); + /* Receive Data Plane(UL) : PGW-S5U */ pgw_s5u_teid = rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data; ogs_assert(pgw_s5u_teid); @@ -233,14 +245,19 @@ void sgwc_s5c_handle_delete_session_response( ogs_debug("Delete Session Response"); + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + + rv = ogs_gtp_xact_commit(s5c_xact); + ogs_expect(rv == OGS_OK); + if (!sess) { ogs_warn("No Context in TEID"); sess = s5c_xact->data; ogs_assert(sess); } - rv = ogs_gtp_xact_commit(s5c_xact); - ogs_expect(rv == OGS_OK); + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); if (rsp->cause.presence) { ogs_gtp_cause_t *cause = rsp->cause.data; @@ -253,15 +270,13 @@ void sgwc_s5c_handle_delete_session_response( } if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + sgwc_pfcp_send_session_deletion_request(sess, NULL, NULL); ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, cause_value); return; } - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - /* Remove a pgw session */ ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); @@ -295,11 +310,6 @@ void sgwc_s5c_handle_create_bearer_request( cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - if (req->linked_eps_bearer_id.presence == 0) { ogs_error("No Linked EBI"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -317,6 +327,11 @@ void sgwc_s5c_handle_create_bearer_request( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (!sess) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value); @@ -373,6 +388,7 @@ void sgwc_s5c_handle_update_bearer_request( ogs_gtp_update_bearer_request_t *req = NULL; ogs_pkbuf_t *pkbuf = NULL; sgwc_ue_t *sgwc_ue = NULL; + sgwc_bearer_t *bearer = NULL; ogs_assert(s5c_xact); ogs_assert(message); @@ -383,11 +399,6 @@ void sgwc_s5c_handle_update_bearer_request( cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -397,16 +408,36 @@ void sgwc_s5c_handle_update_bearer_request( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (!sess) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = sgwc_bearer_find_by_sess_ebi( + sess, req->bearer_contexts.eps_bearer_id.u8); + if (!bearer) + ogs_error("No Context for EPS Bearer ID[%d]", + req->bearer_contexts.eps_bearer_id.u8); + } + if (!bearer) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE, cause_value); return; } + ogs_assert(sess); + ogs_assert(bearer); sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); ogs_assert(sgwc_ue->gnode); + ogs_debug(" EBI[%d]", bearer->ebi); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", @@ -421,7 +452,7 @@ void sgwc_s5c_handle_update_bearer_request( s11_xact = s5c_xact->assoc_xact; if (!s11_xact) { s11_xact = ogs_gtp_xact_local_create( - sgwc_ue->gnode, &message->h, pkbuf, timeout, sess); + sgwc_ue->gnode, &message->h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(s11_xact); ogs_gtp_xact_associate(s5c_xact, s11_xact); @@ -446,6 +477,7 @@ void sgwc_s5c_handle_delete_bearer_request( ogs_gtp_delete_bearer_request_t *req = NULL; ogs_pkbuf_t *pkbuf = NULL; sgwc_ue_t *sgwc_ue = NULL; + sgwc_bearer_t *bearer = NULL; ogs_assert(s5c_xact); ogs_assert(message); @@ -456,14 +488,25 @@ void sgwc_s5c_handle_delete_bearer_request( cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + if (req->linked_eps_bearer_id.presence == 0 && + req->eps_bearer_ids.presence == 0) { + ogs_error("No Linked EBI or EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (!sess) { ogs_warn("No Context"); cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; } - if (req->linked_eps_bearer_id.presence == 0 && - req->eps_bearer_ids.presence == 0) { - ogs_error("No Linked EBI or EPS Bearer ID"); + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = sgwc_bearer_find_by_sess_ebi(sess, req->eps_bearer_ids.u8); + if (!bearer) + ogs_error("No Context for EPS Bearer ID[%d]", + req->eps_bearer_ids.u8); + } + if (!bearer) { + ogs_warn("No Context"); cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; } @@ -473,10 +516,13 @@ void sgwc_s5c_handle_delete_bearer_request( return; } + ogs_assert(sess); + ogs_assert(bearer); sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); ogs_assert(sgwc_ue->gnode); + ogs_debug(" EBI[%d]", bearer->ebi); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", @@ -491,7 +537,7 @@ void sgwc_s5c_handle_delete_bearer_request( s11_xact = s5c_xact->assoc_xact; if (!s11_xact) { s11_xact = ogs_gtp_xact_local_create( - sgwc_ue->gnode, &message->h, pkbuf, timeout, sess); + sgwc_ue->gnode, &message->h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(s11_xact); ogs_gtp_xact_associate(s5c_xact, s11_xact); diff --git a/src/sgwc/sxa-handler.c b/src/sgwc/sxa-handler.c index a02dd79e7..e744b9fd9 100644 --- a/src/sgwc/sxa-handler.c +++ b/src/sgwc/sxa-handler.c @@ -60,7 +60,7 @@ static uint8_t gtp_cause_from_pfcp(uint8_t pfcp_cause) return OGS_GTP_CAUSE_SYSTEM_FAILURE; } -static void timeout(ogs_gtp_xact_t *xact, void *data) +static void sess_timeout(ogs_gtp_xact_t *xact, void *data) { sgwc_sess_t *sess = data; sgwc_ue_t *sgwc_ue = NULL; @@ -73,8 +73,44 @@ static void timeout(ogs_gtp_xact_t *xact, void *data) type = xact->seq[0].type; - ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", - sgwc_ue->imsi_bcd, type); + switch (type) { + case OGS_GTP_CREATE_SESSION_REQUEST_TYPE: + ogs_error("[%s] No Create Session Response", sgwc_ue->imsi_bcd); + sgwc_pfcp_send_session_deletion_request(sess, NULL, NULL); + break; + default: + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + sgwc_ue->imsi_bcd, type); + } +} + +static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) +{ + sgwc_bearer_t *bearer = data; + sgwc_sess_t *sess = NULL; + sgwc_ue_t *sgwc_ue = NULL; + uint8_t type = 0; + + ogs_assert(xact); + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + + type = xact->seq[0].type; + + switch (type) { + case OGS_GTP_CREATE_BEARER_REQUEST_TYPE: + ogs_error("[%s] No Create Bearer Response", sgwc_ue->imsi_bcd); + sgwc_pfcp_send_bearer_modification_request( + bearer, NULL, NULL, + OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE); + break; + default: + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + sgwc_ue->imsi_bcd, type); + } } void sgwc_sxa_handle_session_establishment_response( @@ -269,7 +305,7 @@ void sgwc_sxa_handle_session_establishment_response( ogs_assert(sess->gnode); s5c_xact = ogs_gtp_xact_local_create( - sess->gnode, >p_message->h, pkbuf, timeout, sess); + sess->gnode, >p_message->h, pkbuf, sess_timeout, sess); ogs_expect_or_return(s5c_xact); ogs_gtp_xact_associate(s11_xact, s5c_xact); @@ -308,9 +344,38 @@ void sgwc_sxa_handle_session_modification_response( cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + if (flags & OGS_PFCP_MODIFY_SESSION) { + if (!sess) { + ogs_warn("No Context"); + + sess = pfcp_xact->data; + ogs_assert(sess); + + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + + } else { + bearer = pfcp_xact->data; + ogs_assert(bearer); + + if (!sess) { + ogs_warn("No Context"); + + sess = bearer->sess; + ogs_assert(sess); + + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + sgwc_ue = bearer->sgwc_ue; + ogs_assert(sgwc_ue); + + dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer); + ogs_assert(dl_tunnel); + ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer); + ogs_assert(ul_tunnel); } if (pfcp_rsp->cause.presence) { @@ -327,7 +392,6 @@ void sgwc_sxa_handle_session_modification_response( uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED; uint8_t offending_ie_value = 0; - ogs_assert(sess); for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) { sgwc_tunnel_t *tunnel = NULL; ogs_pfcp_pdr_t *pdr = NULL; @@ -364,7 +428,6 @@ void sgwc_sxa_handle_session_modification_response( } if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - if (sess) sgwc_ue = sess->sgwc_ue; if (flags & OGS_PFCP_MODIFY_CREATE) { s5c_xact = pfcp_xact->assoc_xact; ogs_assert(s5c_xact); @@ -375,11 +438,14 @@ void sgwc_sxa_handle_session_modification_response( } else if (flags & OGS_PFCP_MODIFY_REMOVE) { s5c_xact = pfcp_xact->assoc_xact; - ogs_assert(s5c_xact); - ogs_gtp_send_error_message( - s5c_xact, sess ? sess->pgw_s5c_teid : 0, - OGS_GTP_DELETE_BEARER_RESPONSE_TYPE, cause_value); + if (s5c_xact) { + ogs_gtp_send_error_message( + s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP_DELETE_BEARER_RESPONSE_TYPE, cause_value); + } + + sgwc_bearer_remove(bearer); } else if (flags & OGS_PFCP_MODIFY_ACTIVATE) { if (flags & OGS_PFCP_MODIFY_UL_ONLY) { @@ -414,24 +480,6 @@ void sgwc_sxa_handle_session_modification_response( return; } - if (flags & OGS_PFCP_MODIFY_SESSION) { - sess = pfcp_xact->data; - ogs_assert(sess); - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - - } else { - bearer = pfcp_xact->data; - ogs_assert(bearer); - sgwc_ue = bearer->sgwc_ue; - ogs_assert(sgwc_ue); - - dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer); - ogs_assert(dl_tunnel); - ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer); - ogs_assert(ul_tunnel); - } - if (flags & OGS_PFCP_MODIFY_CREATE) { if (flags & OGS_PFCP_MODIFY_UL_ONLY) { ogs_gtp_create_bearer_request_t *gtp_req = NULL; @@ -467,8 +515,9 @@ void sgwc_sxa_handle_session_modification_response( ogs_expect_or_return(pkbuf); ogs_assert(sgwc_ue->gnode); - s11_xact = ogs_gtp_xact_local_create( - sgwc_ue->gnode, &recv_message->h, pkbuf, timeout, sess); + ogs_assert(bearer); + s11_xact = ogs_gtp_xact_local_create(sgwc_ue->gnode, + &recv_message->h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(s11_xact); ogs_gtp_xact_associate(s5c_xact, s11_xact); @@ -720,20 +769,21 @@ void sgwc_sxa_handle_session_modification_response( } else { s5c_xact = pfcp_xact->assoc_xact; - ogs_assert(s5c_xact); - ogs_assert(recv_message); - recv_message->h.type = OGS_GTP_DELETE_BEARER_RESPONSE_TYPE; - recv_message->h.teid = sess->pgw_s5c_teid; + if (s5c_xact) { + ogs_assert(recv_message); + recv_message->h.type = OGS_GTP_DELETE_BEARER_RESPONSE_TYPE; + recv_message->h.teid = sess->pgw_s5c_teid; - pkbuf = ogs_gtp_build_msg(recv_message); - ogs_expect_or_return(pkbuf); + pkbuf = ogs_gtp_build_msg(recv_message); + ogs_expect_or_return(pkbuf); - rv = ogs_gtp_xact_update_tx(s5c_xact, &recv_message->h, pkbuf); - ogs_expect_or_return(rv == OGS_OK); + rv = ogs_gtp_xact_update_tx(s5c_xact, &recv_message->h, pkbuf); + ogs_expect_or_return(rv == OGS_OK); - rv = ogs_gtp_xact_commit(s5c_xact); - ogs_expect(rv == OGS_OK); + rv = ogs_gtp_xact_commit(s5c_xact); + ogs_expect(rv == OGS_OK); + } sgwc_bearer_remove(bearer); } @@ -928,9 +978,6 @@ void sgwc_sxa_handle_session_deletion_response( ogs_assert(pfcp_xact); ogs_assert(pfcp_rsp); - s11_xact = pfcp_xact->assoc_xact; - ogs_assert(s11_xact); - ogs_pfcp_xact_commit(pfcp_xact); cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; @@ -950,11 +997,15 @@ void sgwc_sxa_handle_session_deletion_response( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + s11_xact = pfcp_xact->assoc_xact; + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { if (sess) sgwc_ue = sess->sgwc_ue; - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, cause_value); + if (s11_xact) { + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, cause_value); + } return; } @@ -962,17 +1013,19 @@ void sgwc_sxa_handle_session_deletion_response( sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); - gtp_message->h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE; - gtp_message->h.teid = sgwc_ue->mme_s11_teid; + if (s11_xact) { + gtp_message->h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE; + gtp_message->h.teid = sgwc_ue->mme_s11_teid; - pkbuf = ogs_gtp_build_msg(gtp_message); - ogs_expect_or_return(pkbuf); + pkbuf = ogs_gtp_build_msg(gtp_message); + ogs_expect_or_return(pkbuf); - rv = ogs_gtp_xact_update_tx(s11_xact, >p_message->h, pkbuf); - ogs_expect_or_return(rv == OGS_OK); + rv = ogs_gtp_xact_update_tx(s11_xact, >p_message->h, pkbuf); + ogs_expect_or_return(rv == OGS_OK); - rv = ogs_gtp_xact_commit(s11_xact); - ogs_expect(rv == OGS_OK); + rv = ogs_gtp_xact_commit(s11_xact); + ogs_expect(rv == OGS_OK); + } sgwc_sess_remove(sess); } diff --git a/src/smf/bearer-binding.c b/src/smf/bearer-binding.c index 5c2062d3a..85e45bf74 100644 --- a/src/smf/bearer-binding.c +++ b/src/smf/bearer-binding.c @@ -23,17 +23,40 @@ #include "ipfw/ipfw2.h" -static void timeout(ogs_gtp_xact_t *xact, void *data) +static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) { - smf_sess_t *sess = data; + smf_bearer_t *bearer = data; + smf_sess_t *sess = NULL; + smf_ue_t *smf_ue = NULL; uint8_t type = 0; + ogs_assert(bearer); + sess = bearer->sess; ogs_assert(sess); + smf_ue = sess->smf_ue; + ogs_assert(smf_ue); type = xact->seq[0].type; - ogs_debug("GTP Timeout : SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x] " - "Message-Type[%d]", sess->sgw_s5c_teid, sess->smf_n4_teid, type); + switch (type) { + case OGS_GTP_CREATE_BEARER_REQUEST_TYPE: + ogs_error("[%s] No Create Bearer Response", smf_ue->imsi_bcd); + smf_epc_pfcp_send_bearer_modification_request( + bearer, OGS_PFCP_MODIFY_REMOVE); + break; + case OGS_GTP_UPDATE_BEARER_REQUEST_TYPE: + ogs_error("[%s] No Update Bearer Response", smf_ue->imsi_bcd); + break; + case OGS_GTP_DELETE_BEARER_REQUEST_TYPE: + ogs_error("[%s] No Delete Bearer Response", smf_ue->imsi_bcd); + smf_epc_pfcp_send_bearer_modification_request( + bearer, OGS_PFCP_MODIFY_REMOVE); + break; + default: + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + smf_ue->imsi_bcd, type); + break; + } } /* @@ -378,7 +401,7 @@ void smf_bearer_binding(smf_sess_t *sess) ogs_expect_or_return(pkbuf); xact = ogs_gtp_xact_local_create( - sess->gnode, &h, pkbuf, timeout, sess); + sess->gnode, &h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(xact); if (pcc_rule->num_of_flow) @@ -409,7 +432,7 @@ void smf_bearer_binding(smf_sess_t *sess) ogs_expect_or_return(pkbuf); xact = ogs_gtp_xact_local_create( - sess->gnode, &h, pkbuf, timeout, sess); + sess->gnode, &h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(xact); rv = ogs_gtp_xact_commit(xact); @@ -444,7 +467,8 @@ void smf_gtp_send_create_bearer_request(smf_bearer_t *bearer) pkbuf = smf_s5c_build_create_bearer_request(h.type, bearer, &tft); ogs_expect_or_return(pkbuf); - xact = ogs_gtp_xact_local_create(sess->gnode, &h, pkbuf, timeout, sess); + xact = ogs_gtp_xact_local_create( + sess->gnode, &h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(xact); rv = ogs_gtp_xact_commit(xact); diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index 0dda7b0e2..4999ed8a1 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -68,15 +68,10 @@ void smf_s5c_handle_create_session_request( ogs_assert(xact); ogs_assert(req); - ogs_debug("[SMF] Create Session Reqeust"); + ogs_debug("Create Session Reqeust"); cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_error("No Context"); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - if (req->imsi.presence == 0) { ogs_error("No IMSI"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -114,6 +109,11 @@ void smf_s5c_handle_create_session_request( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (!sess) { + ogs_error("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (!ogs_diam_peer_connected()) { ogs_warn("No Diameter Peer"); cause_value = OGS_GTP_CAUSE_REMOTE_PEER_NOT_RESPONDING; @@ -239,7 +239,7 @@ void smf_s5c_handle_delete_session_request( { uint8_t cause_value = 0; - ogs_debug("[SMF] Delete Session Request"); + ogs_debug("Delete Session Request"); ogs_assert(xact); ogs_assert(req); @@ -274,6 +274,7 @@ void smf_s5c_handle_create_bearer_response( ogs_gtp_create_bearer_response_t *rsp) { int rv; + uint8_t cause_value; ogs_gtp_f_teid_t *sgw_s5u_teid, *pgw_s5u_teid; smf_bearer_t *bearer = NULL; ogs_pfcp_far_t *dl_far = NULL; @@ -281,43 +282,68 @@ void smf_s5c_handle_create_bearer_response( ogs_assert(xact); ogs_assert(rsp); - ogs_debug("[SMF] Create Bearer Response"); + ogs_debug("Create Bearer Response"); + + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); - if (!sess) { - ogs_warn("No Context in TEID"); - return; + if (rsp->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.s5_s8_u_pgw_f_teid.presence == 0) { + ogs_error("No SMF TEID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.s5_s8_u_sgw_f_teid.presence == 0) { + ogs_error("No SGW TEID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); + bearer = xact->data; + ogs_assert(bearer); + + if (!sess) { + ogs_warn("No Context in TEID"); + + sess = bearer->sess; + ogs_assert(sess); + + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } if (rsp->cause.presence) { ogs_gtp_cause_t *cause = rsp->cause.data; ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("GTP Failed [CAUSE:%d]", cause->value); - return; + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts.cause.presence) { + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } else { + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (rsp->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - return; - } - if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - return; - } - if (rsp->bearer_contexts.s5_s8_u_pgw_f_teid.presence == 0) { - ogs_error("No SMF TEID"); - return; - } - if (rsp->bearer_contexts.s5_s8_u_sgw_f_teid.presence == 0) { - ogs_error("No SGW TEID"); + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + smf_epc_pfcp_send_bearer_modification_request( + bearer, OGS_PFCP_MODIFY_REMOVE); return; } @@ -339,7 +365,7 @@ void smf_s5c_handle_create_bearer_response( rv = ogs_gtp_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip); ogs_assert(rv == OGS_OK); - ogs_debug("[SMF] Create Bearer Response : SGW[0x%x] --> SMF[0x%x]", + ogs_debug("Create Bearer Response : SGW[0x%x] --> SMF[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); /* Setup FAR */ @@ -359,6 +385,7 @@ void smf_s5c_handle_update_bearer_response( ogs_gtp_update_bearer_response_t *rsp) { int rv; + uint8_t cause_value; uint64_t gtp_flags = 0; uint64_t pfcp_flags = 0; smf_bearer_t *bearer = NULL; @@ -368,43 +395,65 @@ void smf_s5c_handle_update_bearer_response( gtp_flags = xact->update_flags; ogs_assert(gtp_flags); - ogs_debug("[SMF] Update Bearer Response"); + ogs_debug("Update Bearer Response"); + + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); - if (!sess) { - ogs_warn("No Context in TEID"); - return; + if (rsp->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); + bearer = xact->data; + ogs_assert(bearer); + + if (!sess) { + ogs_warn("No Context in TEID"); + + sess = bearer->sess; + ogs_assert(sess); + + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } if (rsp->cause.presence) { ogs_gtp_cause_t *cause = rsp->cause.data; ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("GTP Failed [CAUSE:%d]", cause->value); - return; + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts.cause.presence) { + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } else { + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (rsp->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - return; - } - if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); + ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", + sess->sgw_s5c_teid, sess->smf_n4_teid); + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { return; } - bearer = smf_bearer_find_by_ebi( - sess, rsp->bearer_contexts.eps_bearer_id.u8); - ogs_expect_or_return(bearer); - - ogs_debug("[SMF] Update Bearer Response : SGW[0x%x] --> SMF[0x%x]", + ogs_debug("Update Bearer Response : SGW[0x%x] --> SMF[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); if (gtp_flags & OGS_GTP_MODIFY_TFT_UPDATE) { @@ -461,48 +510,67 @@ void smf_s5c_handle_delete_bearer_response( ogs_gtp_delete_bearer_response_t *rsp) { int rv; + uint8_t cause_value; smf_bearer_t *bearer = NULL; ogs_assert(xact); ogs_assert(rsp); - ogs_debug("[SMF] Delete Bearer Response"); + ogs_debug("Delete Bearer Response"); + + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); - if (!sess) { - ogs_warn("No Context in TEID"); - return; + if (rsp->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); + bearer = xact->data; + ogs_assert(bearer); + + if (!sess) { + ogs_warn("No Context in TEID"); + + sess = bearer->sess; + ogs_assert(sess); + + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } if (rsp->cause.presence) { ogs_gtp_cause_t *cause = rsp->cause.data; ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("GTP Failed [CAUSE:%d]", cause->value); - return; + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts.cause.presence) { + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } else { + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (rsp->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - return; - } - if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - return; - } + ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", + sess->sgw_s5c_teid, sess->smf_n4_teid); - bearer = smf_bearer_find_by_ebi( - sess, rsp->bearer_contexts.eps_bearer_id.u8); - ogs_expect_or_return(bearer); - - ogs_debug("[SMF] Delete Bearer Response : SGW[0x%x] --> SMF[0x%x]", + ogs_debug("Delete Bearer Response : SGW[0x%x] --> SMF[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); smf_epc_pfcp_send_bearer_modification_request( @@ -624,19 +692,6 @@ void smf_s5c_handle_bearer_resource_command( cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - if (cmd->linked_eps_bearer_id.presence == 0) { - ogs_error("No Linked EPS Bearer ID"); - cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; - } else { - bearer = smf_bearer_find_by_ebi( - sess, cmd->linked_eps_bearer_id.u8); - if (!bearer) { - ogs_error("No Context for Linked EPS Bearer ID[%d]", - cmd->linked_eps_bearer_id.u8); - cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; - } - } - if (cmd->procedure_transaction_id.presence == 0) { ogs_error("No PTI"); cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; @@ -646,6 +701,28 @@ void smf_s5c_handle_bearer_resource_command( cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + if (cmd->linked_eps_bearer_id.presence == 0) { + ogs_error("No Linked EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (!sess) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = smf_bearer_find_by_ebi(sess, cmd->linked_eps_bearer_id.u8); + if (!bearer) + ogs_error("No Context for Linked EPS Bearer ID[%d]", + cmd->linked_eps_bearer_id.u8); + } + + if (!bearer) { + ogs_error("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value); @@ -852,6 +929,24 @@ void smf_s5c_handle_bearer_resource_command( xact->update_flags |= OGS_GTP_MODIFY_QOS_UPDATE; } + /* IMPORTANT: + * + * When initiaited by Bearer Resource Command, there must be bearer context + * in the Transaction. Otherwise, the beare context cannot be found + * in GTP response message. + * + * For example, + * 1. MME sends Bearer Resource Command to SGW-C, SMF. + * 2. SMF sends Update/Delete Bearer Request to the SGW-C, MME. + * 3. MME sends Update/Delete Bearer Response to thw SGW-C, SMF. + * + * On number 3 step, if MME sends Response without Bearer Context, + * we need a way to find Bearer context. + * + * To do this, I saved Bearer Context in Transaction Context. + */ + xact->data = bearer; + rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); } diff --git a/tests/attach/ue-context-test.c b/tests/attach/ue-context-test.c index 90827bc2f..1673b2bef 100644 --- a/tests/attach/ue-context-test.c +++ b/tests/attach/ue-context-test.c @@ -982,6 +982,7 @@ static void test3_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); +#if 0 /* WITHOUT checking NO active EPS bearers */ /* Receive Initial Context Setup Request */ recvbuf = testenb_s1ap_read(s1ap); ABTS_PTR_NOTNULL(tc, recvbuf); @@ -1033,6 +1034,7 @@ static void test3_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id; +#endif /* Receive Service Reject */ recvbuf = testenb_s1ap_read(s1ap); diff --git a/tests/common/esm-handler.c b/tests/common/esm-handler.c index ff307edc2..30e2f8dd8 100644 --- a/tests/common/esm-handler.c +++ b/tests/common/esm-handler.c @@ -101,3 +101,19 @@ void testesm_handle_activate_dedicated_eps_bearer_context_request( bearer = test_bearer_add(sess, message->esm.h.eps_bearer_identity); ogs_assert(bearer); } + +void testesm_handle_deactivate_eps_bearer_context_request( + test_ue_t *test_ue, ogs_nas_eps_message_t *message) +{ + test_sess_t *sess = NULL; + test_bearer_t *bearer = NULL; + uint8_t ebi; + + ogs_assert(message); + + ebi = message->esm.h.eps_bearer_identity; + ogs_assert(ebi); + + bearer = test_bearer_find_by_ue_ebi(test_ue, ebi); + ogs_assert(bearer); +} diff --git a/tests/common/esm-handler.h b/tests/common/esm-handler.h index 8e1b9fccc..884a854e9 100644 --- a/tests/common/esm-handler.h +++ b/tests/common/esm-handler.h @@ -28,6 +28,8 @@ void testesm_handle_activate_default_eps_bearer_context_request( test_ue_t *test_ue, ogs_nas_eps_message_t *message); void testesm_handle_activate_dedicated_eps_bearer_context_request( test_ue_t *test_ue, ogs_nas_eps_message_t *message); +void testesm_handle_deactivate_eps_bearer_context_request( + test_ue_t *test_ue, ogs_nas_eps_message_t *message); #ifdef __cplusplus } diff --git a/tests/common/nas-path.c b/tests/common/nas-path.c index 054fb32ba..8c5e43de2 100644 --- a/tests/common/nas-path.c +++ b/tests/common/nas-path.c @@ -187,6 +187,7 @@ void testesm_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf) case OGS_NAS_EPS_MODIFY_EPS_BEARER_CONTEXT_REQUEST: break; case OGS_NAS_EPS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST: + testesm_handle_deactivate_eps_bearer_context_request(test_ue, &message); break; case OGS_NAS_EPS_BEARER_RESOURCE_ALLOCATION_REJECT: break; diff --git a/tests/common/s1ap-build.c b/tests/common/s1ap-build.c index ddd825bdb..4ae0e20de 100644 --- a/tests/common/s1ap-build.c +++ b/tests/common/s1ap-build.c @@ -489,10 +489,6 @@ ogs_pkbuf_t *test_s1ap_build_initial_context_setup_response(test_ue_t *test_ue) S1AP_E_RABSetupItemCtxtSURes_t *e_rab = NULL; ogs_assert(test_ue); - sess = ogs_list_first(&test_ue->sess_list); - ogs_assert(sess); - bearer = ogs_list_first(&sess->bearer_list); - ogs_assert(bearer); memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome; @@ -543,28 +539,32 @@ ogs_pkbuf_t *test_s1ap_build_initial_context_setup_response(test_ue_t *test_ue) E_RABSetupListCtxtSURes = &ie->value.choice.E_RABSetupListCtxtSURes; - item = CALLOC(1, sizeof(S1AP_E_RABSetupItemCtxtSUResIEs_t)); - ASN_SEQUENCE_ADD(&E_RABSetupListCtxtSURes->list, item); + ogs_list_for_each(&test_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + item = CALLOC(1, sizeof(S1AP_E_RABSetupItemCtxtSUResIEs_t)); + ASN_SEQUENCE_ADD(&E_RABSetupListCtxtSURes->list, item); - item->id = S1AP_ProtocolIE_ID_id_E_RABSetupItemCtxtSURes; - item->criticality = S1AP_Criticality_ignore; - item->value.present = - S1AP_E_RABSetupItemCtxtSUResIEs__value_PR_E_RABSetupItemCtxtSURes; + item->id = S1AP_ProtocolIE_ID_id_E_RABSetupItemCtxtSURes; + item->criticality = S1AP_Criticality_ignore; + item->value.present = + S1AP_E_RABSetupItemCtxtSUResIEs__value_PR_E_RABSetupItemCtxtSURes; - e_rab = &item->value.choice.E_RABSetupItemCtxtSURes; + e_rab = &item->value.choice.E_RABSetupItemCtxtSURes; - e_rab->e_RAB_ID = bearer->ebi; + e_rab->e_RAB_ID = bearer->ebi; - rv = ogs_gtp_sockaddr_to_f_teid( - bearer->enb_s1u_addr, bearer->enb_s1u_addr6, &f_teid, &len); - ogs_assert(rv == OGS_OK); + rv = ogs_gtp_sockaddr_to_f_teid( + bearer->enb_s1u_addr, bearer->enb_s1u_addr6, &f_teid, &len); + ogs_assert(rv == OGS_OK); - rv = ogs_gtp_f_teid_to_ip(&f_teid, &ip); - ogs_assert(rv == OGS_OK); + rv = ogs_gtp_f_teid_to_ip(&f_teid, &ip); + ogs_assert(rv == OGS_OK); - rv = ogs_asn_ip_to_BIT_STRING(&ip, &e_rab->transportLayerAddress); - ogs_assert(rv == OGS_OK); - ogs_asn_uint32_to_OCTET_STRING(bearer->enb_s1u_teid, &e_rab->gTP_TEID); + rv = ogs_asn_ip_to_BIT_STRING(&ip, &e_rab->transportLayerAddress); + ogs_assert(rv == OGS_OK); + ogs_asn_uint32_to_OCTET_STRING(bearer->enb_s1u_teid, &e_rab->gTP_TEID); + } + } return ogs_s1ap_encode(&pdu); } diff --git a/tests/csfb/crash-test.c b/tests/csfb/crash-test.c index 039c2a826..4743780ea 100644 --- a/tests/csfb/crash-test.c +++ b/tests/csfb/crash-test.c @@ -413,7 +413,7 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - ogs_msleep(100); + ogs_msleep(300); /********** Remove Subscriber in Database */ doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); diff --git a/tests/csfb/mo-idle-test.c b/tests/csfb/mo-idle-test.c index b75cf872f..d7046a126 100644 --- a/tests/csfb/mo-idle-test.c +++ b/tests/csfb/mo-idle-test.c @@ -1285,6 +1285,8 @@ static void test4_func(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, recvbuf); ogs_pkbuf_free(recvbuf); + ogs_msleep(300); + /********** Remove Subscriber in Database */ doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); ABTS_PTR_NOTNULL(tc, doc); diff --git a/tests/minimal/minimal-test.c b/tests/minimal/minimal-test.c index ffb9f52d4..16dabc16b 100644 --- a/tests/minimal/minimal-test.c +++ b/tests/minimal/minimal-test.c @@ -283,6 +283,8 @@ static void test1_func(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, recvbuf); ogs_pkbuf_free(recvbuf); + ogs_msleep(300); + /********** Remove Subscriber in Database */ doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); ABTS_PTR_NOTNULL(tc, doc); diff --git a/tests/volte/rx-test.c b/tests/volte/rx-test.c index 85d201024..b221a74b7 100644 --- a/tests/volte/rx-test.c +++ b/tests/volte/rx-test.c @@ -572,6 +572,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* Send Detach Request */ emmbuf = testemm_build_detach_request(test_ue, 1); ABTS_PTR_NOTNULL(tc, emmbuf); @@ -1047,6 +1050,9 @@ static void test2_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Session Remove */ + test_sess_remove(sess); + /* Send UE Context Release Request */ sendbuf = test_s1ap_build_ue_context_release_request(test_ue, S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity); @@ -1939,6 +1945,9 @@ static void test4_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Session Remove */ + test_sess_remove(sess); + /* Send PDN Connectivity Request */ sess = test_sess_add_by_apn(test_ue, "internet"); ogs_assert(sess); @@ -2034,6 +2043,9 @@ static void test4_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed in deactivate EPS bearer */ ogs_msleep(100); @@ -2055,9 +2067,17 @@ static void test4_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); - /* Send Attach Request */ + /* Test Session Remove */ sess = test_sess_find_by_apn(test_ue, "internet"); ogs_assert(sess); + test_sess_remove(sess); + sess = test_sess_find_by_apn(test_ue, "ims"); + ogs_assert(sess); + test_sess_remove(sess); + + /* Send Attach Request */ + sess = test_sess_add_by_apn(test_ue, "internet"); + ogs_assert(sess); memset(&sess->pdn_connectivity_param, 0, sizeof(sess->pdn_connectivity_param)); @@ -2178,6 +2198,612 @@ static void test4_func(abts_case *tc, void *data) test_ue_remove(test_ue); } +static void test5_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *s1ap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *emmbuf; + ogs_pkbuf_t *esmbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_s1ap_message_t message; + + uint8_t *rx_sid = NULL; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *bearer = NULL; + + uint32_t enb_ue_s1ap_id; + uint64_t mme_ue_s1ap_id; + + const char *_k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "e8ed289deba952e4283b54e88e6183ca"; + uint8_t opc[OGS_KEY_LEN]; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c6\" }, " + "\"imsi\" : \"001010123456819\", " + "\"pdn\" : [" + "{" + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd32\" }," + "\"apn\" : \"internet\"," + "\"qos\" : {" + "\"qci\" : 9," + "\"arp\" : {" + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 1," + "\"pre_emption_capability\" : 1" + "}" + "}," + "\"type\" : 2" + "}," + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c7\" }, " + "\"apn\" : \"ims\", " + "\"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 }" + "}" + "}" + "]," + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 5, " + "\"arp\" : { " + "\"priority_level\" : 1," + "\"pre_emption_vulnerability\" : 1, " + "\"pre_emption_capability\" : 1" + "} " + "}, " + "\"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\" : \"465B5CE8 B199B49F AA5F0A2E E238A6BC\", " + "\"opc\" : \"E8ED289D EBA952E4 283B54E8 8E6183CA\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"64\" } " + "}, " + "\"__v\" : 0 " + "}"; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0x10; + mobile_identity_suci.scheme_output[1] = 0x32; + mobile_identity_suci.scheme_output[2] = 0x54; + mobile_identity_suci.scheme_output[3] = 0x86; + mobile_identity_suci.scheme_output[4] = 0x91; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->e_cgi.cell_id = 0x1079baf; + test_ue->nas.ksi = 0; + test_ue->nas.value = OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH; + + OGS_HEX(_k_string, strlen(_k_string), test_ue->k); + OGS_HEX(_opc_string, strlen(_opc_string), test_ue->opc); + + sess = test_sess_add_by_apn(test_ue, "internet"); + ogs_assert(sess); + + /* eNB connects to MME */ + s1ap = tests1ap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, s1ap); + + /* eNB connects to SGW */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send S1-Setup Reqeust */ + sendbuf = test_s1ap_build_s1_setup_request( + S1AP_ENB_ID_PR_macroENB_ID, 0x54f64); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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); + tests1ap_recv(NULL, recvbuf); + + /********** Insert Subscriber in Database */ + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + if (count) { + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + } + bson_destroy(doc); + + 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(test_ue->imsi)); + 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); + + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + /* Send Attach Request */ + memset(&sess->pdn_connectivity_param, + 0, sizeof(sess->pdn_connectivity_param)); + sess->pdn_connectivity_param.eit = 1; + esmbuf = testesm_build_pdn_connectivity_request(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + + memset(&test_ue->attach_request_param, + 0, sizeof(test_ue->attach_request_param)); + test_ue->attach_request_param.integrity_protected = 1; + test_ue->attach_request_param.drx_parameter = 1; + test_ue->attach_request_param.ms_network_capability = 1; + test_ue->attach_request_param.tmsi_status = 1; + test_ue->attach_request_param.mobile_station_classmark_2 = 1; + test_ue->attach_request_param.ue_usage_setting = 1; + emmbuf = testemm_build_attach_request(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, emmbuf); + + memset(&test_ue->initial_ue_param, 0, sizeof(test_ue->initial_ue_param)); + sendbuf = test_s1ap_build_initial_ue_message( + test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Signalling, false); + 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + emmbuf = testemm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + test_ue->mobile_identity_imeisv_presence = true; + emmbuf = testemm_build_security_mode_complete(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send ESM Information Response */ + sess->esm_information_param.pco = 1; + esmbuf = testesm_build_esm_information_response(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send UE Capability Info Indication */ + sendbuf = tests1ap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Initial Context Setup Response */ + sendbuf = test_s1ap_build_initial_context_setup_response(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + test_ue->nr_cgi.cell_id = 0x1234502; + bearer = test_bearer_find_by_ue_ebi(test_ue, 5); + ogs_assert(bearer); + esmbuf = testesm_build_activate_default_eps_bearer_context_accept( + bearer, false); + ABTS_PTR_NOTNULL(tc, esmbuf); + emmbuf = testemm_build_attach_complete(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send PDN Connectivity Request */ + sess = test_sess_add_by_apn(test_ue, "ims"); + ogs_assert(sess); + sess->pti = 7; + + sess->pdn_connectivity_param.integrity_protected = 1; + sess->pdn_connectivity_param.ciphered = 1; + sess->pdn_connectivity_param.apn = 1; + sess->pdn_connectivity_param.pco = 1; + esmbuf = testesm_build_pdn_connectivity_request(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Setup Request + + * Activate default EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 6); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate default EPS bearer context accept */ + esmbuf = testesm_build_activate_default_eps_bearer_context_accept( + bearer, true); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send UE Context Release Request */ + sendbuf = test_s1ap_build_ue_context_release_request(test_ue, + S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send UE Context Release Complete */ + sendbuf = test_s1ap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AA-Request */ + pcscf_rx_send_aar_audio(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1); + + /* Receive S1-Paging */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Service Request */ + emmbuf = testemm_build_service_request(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_initial_ue_message( + test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Data, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Initial Context Setup Response */ + sendbuf = test_s1ap_build_initial_context_setup_response(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send UE Context Release Request */ + sendbuf = test_s1ap_build_ue_context_release_request(test_ue, + S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send UE Context Release Complete */ + sendbuf = test_s1ap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AA-Request without Flow */ + pcscf_rx_send_aar_audio(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 2, 1); + + /* Receive S1-Paging */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Service Request */ + emmbuf = testemm_build_service_request(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_initial_ue_message( + test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Data, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Initial Context Setup Response */ + sendbuf = test_s1ap_build_initial_context_setup_response(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Modify Request + + * Modify EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Modify Response */ + sendbuf = test_s1ap_build_e_rab_modify_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Modify EPS bearer context accept */ + esmbuf = testesm_build_modify_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(100); + + /* Send UE Context Release Request */ + sendbuf = test_s1ap_build_ue_context_release_request(test_ue, + S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send UE Context Release Complete */ + sendbuf = test_s1ap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Session-Termination-Request */ + pcscf_rx_send_str(rx_sid); + + /* Receive S1-Paging */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Service Request */ + emmbuf = testemm_build_service_request(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_initial_ue_message( + test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Data, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Initial Context Setup Response */ + sendbuf = test_s1ap_build_initial_context_setup_response(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Test Bearer Remove */ + test_bearer_remove(bearer); + + ogs_msleep(100); + + /* Send UE Context Release Request */ + sendbuf = test_s1ap_build_ue_context_release_request(test_ue, + S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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); + tests1ap_recv(test_ue, recvbuf); + + /* Send UE Context Release Complete */ + sendbuf = test_s1ap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + 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(test_ue->imsi)); + 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); + + /* eNB disonncect from SGW */ + test_gtpu_close(gtpu); + + test_ue_remove(test_ue); +} + abts_suite *test_rx(abts_suite *suite) { suite = ADD_SUITE(suite) @@ -2186,6 +2812,7 @@ abts_suite *test_rx(abts_suite *suite) abts_run_test(suite, test2_func, NULL); abts_run_test(suite, test3_func, NULL); abts_run_test(suite, test4_func, NULL); + abts_run_test(suite, test5_func, NULL); return suite; } diff --git a/tests/volte/session-test.c b/tests/volte/session-test.c index 62be87a46..2e1a045ed 100644 --- a/tests/volte/session-test.c +++ b/tests/volte/session-test.c @@ -422,6 +422,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Session Remove */ + test_sess_remove(sess); + /* Send INVALID PDN Connectivity Request */ sess = test_sess_add_by_apn(test_ue, "ims2"); ogs_assert(sess); diff --git a/tests/volte/video-test.c b/tests/volte/video-test.c index b3004401a..5ce54498a 100644 --- a/tests/volte/video-test.c +++ b/tests/volte/video-test.c @@ -494,6 +494,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before Session-Termination-Request */ ogs_msleep(100); @@ -524,6 +527,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before AA-Request */ ogs_msleep(100); @@ -638,6 +644,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before Session-Termination-Request */ ogs_msleep(100); @@ -668,6 +677,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before AA-Request */ ogs_msleep(100); @@ -782,6 +794,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before Session-Termination-Request */ ogs_msleep(100); @@ -812,6 +827,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before AA-Request */ ogs_msleep(100); @@ -926,6 +944,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before Session-Termination-Request */ ogs_msleep(100); @@ -956,6 +977,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before AA-Request */ ogs_msleep(100); @@ -1070,6 +1094,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before Session-Termination-Request */ ogs_msleep(100); @@ -1100,6 +1127,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before AA-Request */ ogs_msleep(100); @@ -1214,6 +1244,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + /* DELAY is needed before Session-Termination-Request */ ogs_msleep(100); @@ -1244,6 +1277,9 @@ static void test1_func(abts_case *tc, void *data) rv = testenb_s1ap_send(s1ap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Test Bearer Remove */ + test_bearer_remove(bearer); + ogs_msleep(300); /********** Remove Subscriber in Database */