From 21f99ad08d009e56bf525524fe6c207f5e2e0b49 Mon Sep 17 00:00:00 2001 From: Emanuele Di Pascale Date: Thu, 11 Jan 2024 12:15:24 +0100 Subject: [PATCH] MME: support for IDR EPS_USER_STATE keep track of whether we failed to page the UE, as that is needed to provide the correct user state to the HSS. --- src/mme/emm-sm.c | 1 + src/mme/mme-context.h | 2 ++ src/mme/mme-fd-path.c | 68 ++++++++++++++++++++++++++++++++++--------- src/mme/mme-path.c | 3 ++ 4 files changed, 60 insertions(+), 14 deletions(-) diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index b1ce78098..ffd814a32 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -144,6 +144,7 @@ void emm_state_registered(ogs_fsm_t *s, mme_event_t *e) ogs_warn("Paging to IMSI[%s] failed. Stop paging", mme_ue->imsi_bcd); CLEAR_MME_UE_TIMER(mme_ue->t3413); + mme_ue->paging.failed = true; if (MME_PAGING_ONGOING(mme_ue)) mme_send_after_paging(mme_ue, true); diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index db5612dad..359f0068a 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -586,6 +586,7 @@ struct mme_ue_s { ogs_assert(__mME); \ ogs_debug("[%s] Clear Paging Info", (__mME)->imsi_bcd); \ (__mME)->paging.type = 0; \ + (__mME)->paging.failed = false; \ } while(0) #define MME_STORE_PAGING_INFO(__mME, __tYPE, __dATA) \ @@ -608,6 +609,7 @@ struct mme_ue_s { #define MME_PAGING_TYPE_DETACH_TO_UE 7 int type; void *data; + bool failed; } paging; /* SGW UE context */ diff --git a/src/mme/mme-fd-path.c b/src/mme/mme-fd-path.c index 3c166fc06..b799c20e0 100644 --- a/src/mme/mme-fd-path.c +++ b/src/mme/mme-fd-path.c @@ -1932,7 +1932,7 @@ static int mme_ogs_diam_s6a_idr_cb( struct msg **msg, struct avp *avp, char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1]; uint32_t result_code = 0; bool has_subscriber_data; - + struct msg *ans, *qry; mme_event_t *e = NULL; @@ -2022,7 +2022,7 @@ static int mme_ogs_diam_s6a_idr_cb( struct msg **msg, struct avp *avp, uint32_t ida_cell_id = mme_ue->e_cgi.cell_id; uint16_t ida_tac = mme_ue->tai.tac; - + struct avp *avp_mme_location_information; struct avp *avp_e_utran_cell_global_identity; struct avp *avp_tracking_area_identity; @@ -2088,18 +2088,58 @@ static int mme_ogs_diam_s6a_idr_cb( struct msg **msg, struct avp *avp, ogs_assert(ret == 0); ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - } else { - if (!has_subscriber_data) { - ogs_error("Insert Subscriber Data " - "with unsupported IDR Flags " - "or no Subscriber-Data for IMSI[%s]", imsi_bcd); - /* Set the Origin-Host, Origin-Realm, and Result-Code AVPs */ - ret = fd_msg_rescode_set( - ans, (char*)"DIAMETER_UNABLE_TO_COMPLY", NULL, NULL, 1); - ogs_assert(ret == 0); - goto outnoexp; - } + ogs_assert(ret == 0); + } + if (idr_message->idr_flags & OGS_DIAM_S6A_IDR_FLAGS_EPS_USER_STATE) { +#define OGS_DIAM_S6A_USER_STATE_DETACHED 0 +#define OGS_DIAM_S6A_USER_STATE_ATTACHED_NOT_REACHABLE_FOR_PAGING 1 +#define OGS_DIAM_S6A_USER_STATE_ATTACHED_REACHABLE_FOR_PAGING 2 +#define OGS_DIAM_S6A_USER_STATE_CONNECTED_NOT_REACHABLE_FOR_PAGING 3 +#define OGS_DIAM_S6A_USER_STATE_CONNECTED_REACHABLE_FOR_PAGING 4 +#define OGS_DIAM_S6A_USER_STATE_RESERVED 5 + struct avp *avp_eps_user_state = NULL; + struct avp *avp_mme_user_state = NULL; + struct avp *avp_user_state = NULL; + uint32_t user_state = 0; + + /* check user state */ + if (!ECM_CONNECTED(mme_ue)) + user_state = OGS_DIAM_S6A_USER_STATE_DETACHED; + else if (mme_ue->paging.failed) + user_state = OGS_DIAM_S6A_USER_STATE_CONNECTED_NOT_REACHABLE_FOR_PAGING; + else + user_state = OGS_DIAM_S6A_USER_STATE_CONNECTED_REACHABLE_FOR_PAGING; + + /* Set the EPS-User-State AVP */ + ret = fd_msg_avp_new(ogs_diam_s6a_eps_user_state, 0, &avp_eps_user_state); + ogs_assert(ret == 0); + ret = fd_msg_avp_new(ogs_diam_s6a_mme_user_state, 0, &avp_mme_user_state); + ogs_assert(ret == 0); + ret = fd_msg_avp_new(ogs_diam_s6a_user_state, 0, &avp_user_state); + ogs_assert(ret == 0); + memset(&val, 0, sizeof(val)); + val.i32 = user_state; + ret = fd_msg_avp_setvalue(avp_user_state, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avp_mme_user_state, MSG_BRW_LAST_CHILD, avp_user_state); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avp_eps_user_state, MSG_BRW_LAST_CHILD, avp_mme_user_state); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp_eps_user_state); + ogs_assert(ret == 0); + } + if (!has_subscriber_data && + !(idr_message->idr_flags & OGS_DIAM_S6A_IDR_FLAGS_EPS_LOCATION_INFO) && + !(idr_message->idr_flags & OGS_DIAM_S6A_IDR_FLAGS_EPS_USER_STATE)) + { + ogs_error("Insert Subscriber Data " + "with unsupported IDR Flags " + "or no Subscriber-Data for IMSI[%s]", imsi_bcd); + /* Set the Origin-Host, Origin-Realm, and Result-Code AVPs */ + ret = fd_msg_rescode_set( + ans, (char*)"DIAMETER_UNABLE_TO_COMPLY", NULL, NULL, 1); + ogs_assert(ret == 0); + goto outnoexp; } /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index 5fb6c2d3c..c076fd212 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -296,4 +296,7 @@ void mme_send_after_paging(mme_ue_t *mme_ue, bool failed) cleanup: CLEAR_SERVICE_INDICATOR(mme_ue); MME_CLEAR_PAGING_INFO(mme_ue); + /* the above will clear the failure flag, restore it if we failed */ + if (failed) + mme_ue->paging.failed = true; }