forked from acouzens/open5gs
[MME] Introduce support for S6a Cancel Location Request
- Added diameter dictionary definitions for Cancel Location - Cancel Location will completely remove UE from MME, allow for a fresh IMSI attach to occur on next attempt. - T3422 is used for detach request. - Added new handling for s6a events in mme-sm, as not all s6a messages are at attach now. Maybe there's something in a state machine I should've been using here instead of a new flag? - Testing was completed with UE in idle and connected. With CLR flags indicating re-attach required and without. Also sending CLR after UE detach. And then sending again when mme_ue is empty.
This commit is contained in:
parent
ff5023e95b
commit
47cbaca149
|
@ -526,6 +526,63 @@ int ogs_dict_s6a_entry(char *conffile)
|
|||
PARSE_loc_rules( rules, cmd );
|
||||
}
|
||||
|
||||
/* Cancel-Location-Request (CLR) Command - 3GPP TS 29.272 #7.2.7 */
|
||||
{
|
||||
struct dict_object * cmd;
|
||||
struct dict_cmd_data data = {
|
||||
317, /* Code */
|
||||
"Cancel-Location-Request", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Destination-Host" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Destination-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "User-Name" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Supported-Features" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "Cancellation-Type" }, RULE_REQUIRED, -1, -1 },
|
||||
{ { .avp_vendor = 10415, .avp_name = "CLR-Flags" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 },
|
||||
};
|
||||
|
||||
CHECK_dict_new( DICT_COMMAND, &data, s6a, &cmd);
|
||||
PARSE_loc_rules( rules, cmd );
|
||||
}
|
||||
|
||||
/* Cancel-Location-Answer (CLA) Command - 3GPP TS 29.272 #7.2.8 */
|
||||
{
|
||||
struct dict_object * cmd;
|
||||
struct dict_cmd_data data = {
|
||||
317, /* Code */
|
||||
"Cancel-Location-Answer", /* Name */
|
||||
CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
|
||||
CMD_FLAG_PROXIABLE /* Fixed flag values */
|
||||
};
|
||||
struct local_rules_definition rules[] =
|
||||
{
|
||||
{ { .avp_name = "Session-Id" }, RULE_FIXED_HEAD, -1, 1 },
|
||||
{ { .avp_name = "Vendor-Specific-Application-Id" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Result-Code" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Experimental-Result" }, RULE_OPTIONAL, -1, 1 },
|
||||
{ { .avp_name = "Auth-Session-State" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Host" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Origin-Realm" }, RULE_REQUIRED, -1, 1 },
|
||||
{ { .avp_name = "Failed-AVP" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Proxy-Info" }, RULE_OPTIONAL, -1, -1 },
|
||||
{ { .avp_name = "Route-Record" }, RULE_OPTIONAL, -1, -1 },
|
||||
};
|
||||
|
||||
CHECK_dict_new( DICT_COMMAND, &data, s6a, &cmd);
|
||||
PARSE_loc_rules( rules, cmd );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LOG_D( "Extension 'Dictionary definitions for DCCA 3GPP S6A' initialized");
|
||||
|
|
|
@ -30,9 +30,13 @@ struct dict_object *ogs_diam_s6a_cmd_ulr = NULL;
|
|||
struct dict_object *ogs_diam_s6a_cmd_ula = NULL;
|
||||
struct dict_object *ogs_diam_s6a_cmd_pur = NULL;
|
||||
struct dict_object *ogs_diam_s6a_cmd_pua = NULL;
|
||||
struct dict_object *ogs_diam_s6a_cmd_clr = NULL;
|
||||
struct dict_object *ogs_diam_s6a_cmd_cla = NULL;
|
||||
|
||||
struct dict_object *ogs_diam_s6a_ulr_flags = NULL;
|
||||
struct dict_object *ogs_diam_s6a_ula_flags = NULL;
|
||||
struct dict_object *ogs_diam_s6a_clr_flags = NULL;
|
||||
struct dict_object *ogs_diam_s6a_cancellation_type = NULL;
|
||||
struct dict_object *ogs_diam_s6a_subscription_data = NULL;
|
||||
struct dict_object *ogs_diam_s6a_req_eutran_auth_info = NULL;
|
||||
struct dict_object *ogs_diam_s6a_number_of_requested_vectors = NULL;
|
||||
|
@ -91,9 +95,13 @@ int ogs_diam_s6a_init(void)
|
|||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Update-Location-Answer", &ogs_diam_s6a_cmd_ula);
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Purge-UE-Request", &ogs_diam_s6a_cmd_pur);
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Purge-UE-Answer", &ogs_diam_s6a_cmd_pua);
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Cancel-Location-Request", &ogs_diam_s6a_cmd_clr);
|
||||
CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Cancel-Location-Answer", &ogs_diam_s6a_cmd_cla);
|
||||
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "ULR-Flags", &ogs_diam_s6a_ulr_flags);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "ULA-Flags", &ogs_diam_s6a_ula_flags);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "CLR-Flags", &ogs_diam_s6a_clr_flags);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Cancellation-Type", &ogs_diam_s6a_cancellation_type);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "UE-SRVCC-Capability", &ogs_diam_s6a_ue_srvcc_capability);
|
||||
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Requested-EUTRAN-Authentication-Info", &ogs_diam_s6a_req_eutran_auth_info);
|
||||
|
|
|
@ -59,6 +59,9 @@ extern "C" {
|
|||
#define OGS_DIAM_S6A_ULR_INITIAL_ATTACH_IND (1 << 5)
|
||||
#define OGS_DIAM_S6A_ULR_PS_LCS_SUPPORTED_BY_UE (1 << 6)
|
||||
|
||||
#define OGS_DIAM_S6A_CLR_S6A_S6D_INDICATOR (1)
|
||||
#define OGS_DIAM_S6A_CLR_REATTACH_REQUIRED (1 << 1)
|
||||
|
||||
#define OGS_DIAM_S6A_UE_SRVCC_NOT_SUPPORTED (0)
|
||||
#define OGS_DIAM_S6A_UE_SRVCC_SUPPORTED (1)
|
||||
|
||||
|
@ -76,9 +79,13 @@ extern struct dict_object *ogs_diam_s6a_cmd_ulr;
|
|||
extern struct dict_object *ogs_diam_s6a_cmd_ula;
|
||||
extern struct dict_object *ogs_diam_s6a_cmd_pur;
|
||||
extern struct dict_object *ogs_diam_s6a_cmd_pua;
|
||||
extern struct dict_object *ogs_diam_s6a_cmd_clr;
|
||||
extern struct dict_object *ogs_diam_s6a_cmd_cla;
|
||||
|
||||
extern struct dict_object *ogs_diam_s6a_ulr_flags;
|
||||
extern struct dict_object *ogs_diam_s6a_ula_flags;
|
||||
extern struct dict_object *ogs_diam_s6a_clr_flags;
|
||||
extern struct dict_object *ogs_diam_s6a_cancellation_type;
|
||||
extern struct dict_object *ogs_diam_s6a_subscription_data;
|
||||
extern struct dict_object *ogs_diam_s6a_req_eutran_auth_info;
|
||||
extern struct dict_object *ogs_diam_s6a_number_of_requested_vectors;
|
||||
|
@ -140,8 +147,15 @@ typedef struct ogs_diam_s6a_ula_message_s {
|
|||
ogs_subscription_data_t subscription_data;
|
||||
} ogs_diam_s6a_ula_message_t;
|
||||
|
||||
typedef struct ogs_diam_s6a_clr_message_s {
|
||||
#define OGS_DIAM_S6A_CLR_FLAGS_S6A_S6D_INDICATOR (0)
|
||||
#define OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED (1)
|
||||
uint32_t clr_flags;
|
||||
} ogs_diam_s6a_clr_message_t;
|
||||
|
||||
typedef struct ogs_diam_s6a_message_s {
|
||||
#define OGS_DIAM_S6A_CMD_CODE_UPDATE_LOCATION 316
|
||||
#define OGS_DIAM_S6A_CMD_CODE_CANCEL_LOCATION 317
|
||||
#define OGS_DIAM_S6A_CMD_CODE_AUTHENTICATION_INFORMATION 318
|
||||
uint16_t cmd_code;
|
||||
|
||||
|
@ -157,6 +171,9 @@ typedef struct ogs_diam_s6a_message_s {
|
|||
uint32_t *err;
|
||||
uint32_t *exp_err;
|
||||
|
||||
bool during_attach;
|
||||
|
||||
ogs_diam_s6a_clr_message_t clr_message;
|
||||
ogs_diam_s6a_aia_message_t aia_message;
|
||||
ogs_diam_s6a_ula_message_t ula_message;
|
||||
} ogs_diam_s6a_message_t;
|
||||
|
|
|
@ -103,6 +103,7 @@ typedef struct ogs_gtp_xact_s {
|
|||
#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 5
|
||||
#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 6
|
||||
#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 7
|
||||
#define OGS_GTP_DELETE_NO_ACTION 8
|
||||
int delete_action;
|
||||
|
||||
#define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1
|
||||
|
|
|
@ -437,6 +437,25 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue)
|
|||
return nas_eps_security_encode(mme_ue, &message);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue)
|
||||
{
|
||||
ogs_nas_eps_message_t message;
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.security_header_type =
|
||||
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
|
||||
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
|
||||
|
||||
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
|
||||
message.emm.h.message_type = OGS_NAS_EPS_DETACH_REQUEST;
|
||||
|
||||
message.emm.detach_request_to_ue.detach_type.value = mme_ue->mme_to_ue_detach_type;
|
||||
|
||||
return nas_eps_security_encode(mme_ue, &message);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *emm_build_detach_accept(mme_ue_t *mme_ue)
|
||||
{
|
||||
ogs_nas_eps_message_t message;
|
||||
|
|
|
@ -37,6 +37,7 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue);
|
|||
ogs_pkbuf_t *emm_build_authentication_request(mme_ue_t *mme_ue);
|
||||
ogs_pkbuf_t *emm_build_authentication_reject(void);
|
||||
|
||||
ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue);
|
||||
ogs_pkbuf_t *emm_build_detach_accept(mme_ue_t *mme_ue);
|
||||
|
||||
ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue);
|
||||
|
|
|
@ -129,6 +129,16 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
|
|||
break;
|
||||
}
|
||||
|
||||
if (mme_ue->mme_to_ue_detach_pending) {
|
||||
ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue));
|
||||
mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION);
|
||||
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
|
||||
ogs_assert(OGS_OK ==
|
||||
sgsap_send_detach_indication(mme_ue));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!MME_UE_HAVE_IMSI(mme_ue)) {
|
||||
ogs_info("Service request : Unknown UE");
|
||||
ogs_assert(OGS_OK ==
|
||||
|
@ -539,6 +549,21 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
|
|||
OGS_FSM_TRAN(s, &emm_state_de_registered);
|
||||
break;
|
||||
|
||||
case OGS_NAS_EPS_DETACH_ACCEPT:
|
||||
ogs_debug("Detach accept");
|
||||
|
||||
CLEAR_MME_UE_TIMER(mme_ue->t3422);
|
||||
|
||||
if (enb_ue) {
|
||||
s1ap_send_ue_context_release_command(enb_ue,
|
||||
S1AP_Cause_PR_nas, S1AP_CauseNas_detach,
|
||||
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
|
||||
} else {
|
||||
ogs_warn("[%s] No S1 Context", mme_ue->imsi_bcd);
|
||||
}
|
||||
OGS_FSM_TRAN(s, &emm_state_de_registered);
|
||||
break;
|
||||
|
||||
case OGS_NAS_EPS_UPLINK_NAS_TRANSPORT:
|
||||
ogs_debug("Uplink NAS Transport");
|
||||
ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd);
|
||||
|
@ -627,6 +652,23 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
|
|||
}
|
||||
break;
|
||||
|
||||
case MME_TIMER_T3422:
|
||||
if (mme_ue->t3422.retry_count >=
|
||||
mme_timer_cfg(MME_TIMER_T3422)->max_count) {
|
||||
ogs_warn("Retransmission of Detach Request failed. "
|
||||
"Stop retransmission");
|
||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception);
|
||||
} else {
|
||||
rv = nas_eps_send_detach_request(mme_ue);
|
||||
if (rv == OGS_OK) {
|
||||
mme_ue->t3422.retry_count++;
|
||||
} else {
|
||||
ogs_error("nas_eps_send_detach_request() failed");
|
||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown timer[%s:%d]",
|
||||
mme_timer_get_name(e->timer_id), e->timer_id);
|
||||
|
|
|
@ -321,6 +321,9 @@ struct mme_ue_s {
|
|||
};
|
||||
} nas_eps;
|
||||
|
||||
bool mme_to_ue_detach_pending;
|
||||
uint8_t mme_to_ue_detach_type;
|
||||
|
||||
/* UE identity */
|
||||
#define MME_UE_HAVE_IMSI(__mME) \
|
||||
((__mME) && ((__mME)->imsi_len))
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#include "mme-event.h"
|
||||
#include "mme-fd-path.h"
|
||||
|
||||
/* handler for Cancel-Location-Request cb */
|
||||
static struct disp_hdl *hdl_s6a_clr = NULL;
|
||||
|
||||
static struct session_handler *mme_s6a_reg = NULL;
|
||||
|
||||
struct sess_state {
|
||||
|
@ -226,6 +229,7 @@ static void mme_s6a_aia_cb(void *data, struct msg **msg)
|
|||
s6a_message = ogs_calloc(1, sizeof(ogs_diam_s6a_message_t));
|
||||
ogs_assert(s6a_message);
|
||||
s6a_message->cmd_code = OGS_DIAM_S6A_CMD_CODE_AUTHENTICATION_INFORMATION;
|
||||
s6a_message->during_attach = true;
|
||||
aia_message = &s6a_message->aia_message;
|
||||
ogs_assert(aia_message);
|
||||
e_utran_vector = &aia_message->e_utran_vector;
|
||||
|
@ -634,6 +638,7 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
|||
s6a_message = ogs_calloc(1, sizeof(ogs_diam_s6a_message_t));
|
||||
ogs_assert(s6a_message);
|
||||
s6a_message->cmd_code = OGS_DIAM_S6A_CMD_CODE_UPDATE_LOCATION;
|
||||
s6a_message->during_attach = true;
|
||||
ula_message = &s6a_message->ula_message;
|
||||
ogs_assert(ula_message);
|
||||
subscription_data = &ula_message->subscription_data;
|
||||
|
@ -1403,10 +1408,129 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Callback for incoming Cancel-Location-Request messages */
|
||||
static int mme_ogs_diam_s6a_clr_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *session, void *opaque, enum disp_action *act)
|
||||
{
|
||||
int ret;
|
||||
int error = 0;
|
||||
|
||||
mme_event_t *e = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
struct msg *ans, *qry;
|
||||
ogs_diam_s6a_clr_message_t *clr_message = NULL;
|
||||
|
||||
struct avp_hdr *hdr;
|
||||
union avp_value val;
|
||||
|
||||
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
|
||||
|
||||
uint32_t result_code = 0;
|
||||
|
||||
ogs_assert(msg);
|
||||
|
||||
ogs_diam_s6a_message_t *s6a_message = NULL;
|
||||
|
||||
ogs_debug("Cancel-Location-Request");
|
||||
|
||||
s6a_message = ogs_calloc(1, sizeof(ogs_diam_s6a_message_t));
|
||||
ogs_assert(s6a_message);
|
||||
s6a_message->cmd_code = OGS_DIAM_S6A_CMD_CODE_CANCEL_LOCATION;
|
||||
clr_message = &s6a_message->clr_message;
|
||||
ogs_assert(clr_message);
|
||||
|
||||
|
||||
/* Create answer header */
|
||||
qry = *msg;
|
||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||
ogs_assert(ret == 0);
|
||||
ans = *msg;
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_cpystrn(imsi_bcd, (char*)hdr->avp_value->os.data,
|
||||
ogs_min(hdr->avp_value->os.len, OGS_MAX_IMSI_BCD_LEN)+1);
|
||||
|
||||
mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd);
|
||||
|
||||
if (!mme_ue) {
|
||||
ogs_error("Cancel Location for Unknown IMSI[%s]", imsi_bcd);
|
||||
result_code = OGS_DIAM_S6A_ERROR_USER_UNKNOWN;
|
||||
error++;
|
||||
}
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_cancellation_type, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
||||
ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Set the Auth-Session-State AVP */
|
||||
ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_DIAM_AUTH_SESSION_NO_STATE_MAINTAINED;
|
||||
ret = fd_msg_avp_setvalue(avp, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_search_avp(qry, ogs_diam_s6a_clr_flags, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
if (avp) {
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
clr_message->clr_flags = hdr->avp_value->i32;
|
||||
}
|
||||
|
||||
/* Set Vendor-Specific-Application-Id AVP */
|
||||
ret = ogs_diam_message_vendor_specific_appid_set(
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ogs_debug("Cancel-Location-Answer");
|
||||
|
||||
/* Add this value to the stats */
|
||||
ogs_assert( pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
ogs_diam_logger_self()->stats.nb_echoed++;
|
||||
ogs_assert( pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0);
|
||||
|
||||
if (!error) {
|
||||
int rv;
|
||||
e = mme_event_new(MME_EVT_S6A_MESSAGE);
|
||||
ogs_assert(e);
|
||||
e->mme_ue = mme_ue;
|
||||
e->s6a_message = s6a_message;
|
||||
rv = ogs_queue_push(ogs_app()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_free(s6a_message);
|
||||
mme_event_free(e);
|
||||
} else {
|
||||
ogs_pollset_notify(ogs_app()->pollset);
|
||||
}
|
||||
} else {
|
||||
ret = ogs_diam_message_experimental_rescode_set(ans, result_code);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mme_fd_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct disp_when data;
|
||||
|
||||
ret = ogs_diam_init(FD_MODE_CLIENT,
|
||||
mme_self()->diam_conf_path, mme_self()->diam_config);
|
||||
|
@ -1420,6 +1544,12 @@ int mme_fd_init(void)
|
|||
ret = fd_sess_handler_create(&mme_s6a_reg, &state_cleanup, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Specific handler for Cancel-Location-Request */
|
||||
data.command = ogs_diam_s6a_cmd_clr;
|
||||
ret = fd_disp_register(mme_ogs_diam_s6a_clr_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_s6a_clr);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
ret = fd_disp_app_support(ogs_diam_s6a_application, ogs_diam_vendor, 1, 0);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -1437,5 +1567,8 @@ void mme_fd_final(void)
|
|||
ret = fd_sess_handler_destroy(&mme_s6a_reg, NULL);
|
||||
ogs_assert(ret == OGS_OK);
|
||||
|
||||
if (hdl_s6a_clr)
|
||||
(void) fd_disp_unregister(&hdl_s6a_clr, NULL);
|
||||
|
||||
ogs_diam_final();
|
||||
}
|
||||
|
|
|
@ -636,6 +636,8 @@ void mme_s11_handle_delete_session_response(
|
|||
|
||||
return;
|
||||
|
||||
} else if (action == OGS_GTP_DELETE_NO_ACTION) {
|
||||
|
||||
} else {
|
||||
ogs_fatal("Invalid action = %d", action);
|
||||
ogs_assert_if_reached();
|
||||
|
|
|
@ -101,3 +101,27 @@ void mme_s6a_handle_ula(mme_ue_t *mme_ue,
|
|||
mme_ue->num_of_session = i;
|
||||
mme_ue->context_identifier = slice_data->context_identifier;
|
||||
}
|
||||
|
||||
void mme_s6a_handle_clr(mme_ue_t *mme_ue,
|
||||
ogs_diam_s6a_clr_message_t *clr_message)
|
||||
{
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(clr_message);
|
||||
|
||||
if (clr_message->clr_flags & OGS_DIAM_S6A_CLR_REATTACH_REQUIRED) {
|
||||
mme_ue->mme_to_ue_detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_REQUIRED;
|
||||
} else {
|
||||
mme_ue->mme_to_ue_detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_NOT_REQUIRED;
|
||||
}
|
||||
|
||||
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_de_registered)) {
|
||||
// Remove all trace of subscriber even when detached.
|
||||
mme_ue_hash_remove(mme_ue);
|
||||
mme_ue_remove(mme_ue);
|
||||
} else if (ECM_IDLE(mme_ue)) {
|
||||
ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps));
|
||||
mme_ue->mme_to_ue_detach_pending = true;
|
||||
} else {
|
||||
ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ void mme_s6a_handle_aia(mme_ue_t *mme_ue,
|
|||
ogs_diam_s6a_aia_message_t *aia_message);
|
||||
void mme_s6a_handle_ula(mme_ue_t *mme_ue,
|
||||
ogs_diam_s6a_ula_message_t *ula_message);
|
||||
void mme_s6a_handle_clr(mme_ue_t *mme_ue,
|
||||
ogs_diam_s6a_clr_message_t *clr_message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -437,6 +437,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
s6a_message = e->s6a_message;
|
||||
ogs_assert(s6a_message);
|
||||
|
||||
if (s6a_message->during_attach) {
|
||||
enb_ue = enb_ue_cycle(mme_ue->enb_ue);
|
||||
if (!enb_ue) {
|
||||
ogs_error("S1 context has already been removed");
|
||||
|
@ -472,6 +473,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
ogs_free(s6a_message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (s6a_message->cmd_code) {
|
||||
case OGS_DIAM_S6A_CMD_CODE_AUTHENTICATION_INFORMATION:
|
||||
|
@ -504,6 +506,17 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
ogs_assert_if_reached();
|
||||
}
|
||||
break;
|
||||
case OGS_DIAM_S6A_CMD_CODE_CANCEL_LOCATION:
|
||||
mme_s6a_handle_clr(mme_ue, &s6a_message->clr_message);
|
||||
|
||||
if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue) && !mme_ue->mme_to_ue_detach_pending) {
|
||||
mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION);
|
||||
}
|
||||
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
|
||||
ogs_assert(OGS_OK ==
|
||||
sgsap_send_detach_indication(mme_ue));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ogs_error("Invalid Type[%d]", s6a_message->cmd_code);
|
||||
break;
|
||||
|
|
|
@ -256,6 +256,42 @@ int nas_eps_send_authentication_reject(mme_ue_t *mme_ue)
|
|||
return rv;
|
||||
}
|
||||
|
||||
int nas_eps_send_detach_request(mme_ue_t *mme_ue)
|
||||
{
|
||||
int rv;
|
||||
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
ogs_pkbuf_t *emmbuf = NULL;
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
enb_ue = enb_ue_cycle(mme_ue->enb_ue);
|
||||
ogs_expect_or_return_val(enb_ue, OGS_ERROR);
|
||||
|
||||
ogs_debug("[%s] Detach request to UE", mme_ue->imsi_bcd);
|
||||
|
||||
if (mme_ue->t3422.pkbuf) {
|
||||
emmbuf = mme_ue->t3422.pkbuf;
|
||||
ogs_expect_or_return_val(emmbuf, OGS_ERROR);
|
||||
} else {
|
||||
emmbuf = emm_build_identity_request(mme_ue);
|
||||
ogs_expect_or_return_val(emmbuf, OGS_ERROR);
|
||||
}
|
||||
|
||||
mme_ue->t3422.pkbuf = ogs_pkbuf_copy(emmbuf);
|
||||
ogs_expect_or_return_val(mme_ue->t3422.pkbuf, OGS_ERROR);
|
||||
ogs_timer_start(mme_ue->t3422.timer,
|
||||
mme_timer_cfg(MME_TIMER_T3422)->duration);
|
||||
|
||||
/* send detach request */
|
||||
emmbuf = emm_build_detach_request(mme_ue);
|
||||
ogs_expect_or_return_val(emmbuf, OGS_ERROR);
|
||||
|
||||
rv = nas_eps_send_to_downlink_nas_transport(mme_ue, emmbuf);
|
||||
ogs_expect_or_return_val(rv == OGS_OK, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int nas_eps_send_detach_accept(mme_ue_t *mme_ue)
|
||||
{
|
||||
int rv;
|
||||
|
|
|
@ -43,6 +43,7 @@ int nas_eps_send_authentication_reject(mme_ue_t *mme_ue);
|
|||
|
||||
int nas_eps_send_security_mode_command(mme_ue_t *mme_ue);
|
||||
|
||||
int nas_eps_send_detach_request(mme_ue_t *mme_ue);
|
||||
int nas_eps_send_detach_accept(mme_ue_t *mme_ue);
|
||||
|
||||
int nas_eps_send_pdn_connectivity_reject(
|
||||
|
|
|
@ -272,7 +272,9 @@ void sgsap_handle_detach_ack(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
|
|||
|
||||
ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd);
|
||||
|
||||
if (!mme_ue->mme_to_ue_detach_pending) {
|
||||
mme_send_delete_session_or_detach(mme_ue);
|
||||
}
|
||||
}
|
||||
|
||||
void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
|
||||
|
|
Loading…
Reference in New Issue