Retransmit paging if UE is not paged.

This commit is contained in:
James Park 2017-08-07 15:58:13 -07:00
parent f2a1bbeca1
commit d3cdbac70d
10 changed files with 125 additions and 47 deletions

View File

@ -796,9 +796,6 @@ void emm_handle_downlink_data_notification(gtp_xact_t *xact,
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess;
pkbuf_t *s11buf = NULL;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
int i;
d_assert(xact, return, "Null param");
d_assert(bearer, return, "Null param");
@ -816,31 +813,4 @@ void emm_handle_downlink_data_notification(gtp_xact_t *xact,
GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE,
sess->sgw_s11_teid, s11buf) == CORE_OK,
return , "xact commit error");
/* Send s1 paging */
/* Find enB with matched TAI */
enb = mme_enb_first();
while (enb)
{
for (i = 0; i < enb->num_of_tai; i++)
{
if (!memcmp(&enb->tai[i], &mme_ue->tai, sizeof(tai_t)))
{
/* Buidl S1Ap Paging message */
rv = s1ap_build_paging(&s1apbuf, mme_ue);
d_assert(rv == CORE_OK && s1apbuf, return,
"s1ap build error");
/* Send to enb */
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK, return,
"s1ap send error");
}
}
enb = mme_enb_next(enb);
}
/* FIXME : Need to start timer.
* After expiration, re-send paging message.
* Timeer should be stopped when UE sends initialUeMessage
*/
}

View File

@ -9,6 +9,7 @@
#include "emm_build.h"
#include "mme_s6a_handler.h"
#include "mme_kdf.h"
#include "s1ap_handler.h"
void emm_state_initial(fsm_t *s, event_t *e)
{
@ -62,8 +63,16 @@ void emm_state_operational(fsm_t *s, event_t *e)
break;
case GTP_DOWNLINK_DATA_NOTIFICATION_TYPE:
{
mme_ue_t *mme_ue = NULL;
gtp_xact_t *xact = (gtp_xact_t *)event_get_param3(e);
emm_handle_downlink_data_notification(xact, bearer);
mme_ue = bearer->mme_ue;
d_assert(mme_ue, break, "Null param");
s1ap_handle_paging(mme_ue);
/* Start T3413 */
tm_start(mme_ue->t3413);
break;
}
}
@ -137,6 +146,7 @@ void emm_state_operational(fsm_t *s, event_t *e)
if (message->emm.h.security_header_type
== NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE)
{
mme_ue_paged(mme_ue);
emm_handle_service_request(
mme_ue, &message->emm.service_request);
break;
@ -146,6 +156,7 @@ void emm_state_operational(fsm_t *s, event_t *e)
{
case NAS_ATTACH_REQUEST:
{
mme_ue_paged(mme_ue);
emm_handle_attach_request(
mme_ue, &message->emm.attach_request);
break;
@ -194,6 +205,11 @@ void emm_state_operational(fsm_t *s, event_t *e)
mme_ue, &message->emm.detach_request_from_ue);
break;
}
case NAS_TRACKING_AREA_UPDATE_REQUEST:
{
mme_ue_paged(mme_ue);
break;
}
default:
{
d_warn("Not implemented(type:%d)",
@ -213,6 +229,35 @@ void emm_state_operational(fsm_t *s, event_t *e)
d_assert(mme_ue, return, "Null param");
break;
}
case MME_EVT_EMM_UE_T3413:
{
index_t index = event_get_param1(e);
mme_ue_t *mme_ue = NULL;
d_assert(index, return, "Null param");
mme_ue = mme_ue_find(index);
d_assert(mme_ue, return, "Null param");
if (mme_ue->max_paging_retry >= MAX_NUM_OF_PAGING)
{
/* Paging failed */
d_warn("Paging to UE(%s) failed. Stop paging",
mme_ue->imsi_bcd);
if (mme_ue->last_paging_msg)
{
pkbuf_free(mme_ue->last_paging_msg);
mme_ue->last_paging_msg = NULL;
}
break;
}
mme_ue->max_paging_retry++;
s1ap_handle_paging(mme_ue);
/* Start T3413 */
tm_start(mme_ue->t3413);
break;
}
default:
{

View File

@ -59,6 +59,9 @@ status_t mme_context_init()
self.imsi_ue_hash = hash_make();
self.guti_ue_hash = hash_make();
/* Timer value */
self.t3413_value = 2; /* Paging retry Timer: 2 secs */
context_initialized = 1;
return CORE_OK;
@ -1166,6 +1169,10 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue)
list_init(&mme_ue->pdn_list);
list_init(&mme_ue->sess_list);
/* Create t3413 timer */
mme_ue->t3413 = event_timer(&self.tm_service, MME_EVT_EMM_UE_T3413,
self.t3413_value * 1000, mme_ue->index);
mme_ue->enb_ue = enb_ue;
enb_ue->mme_ue = mme_ue;
@ -1187,6 +1194,13 @@ status_t mme_ue_remove(mme_ue_t *mme_ue)
hash_set(self.guti_ue_hash, &mme_ue->guti, sizeof(guti_t), NULL);
if (mme_ue->imsi_len != 0)
hash_set(self.imsi_ue_hash, mme_ue->imsi, mme_ue->imsi_len, NULL);
/* Delete t3413 timer */
tm_delete(mme_ue->t3413);
/* Free the saved paging msg */
if (mme_ue->last_paging_msg)
pkbuf_free(mme_ue->last_paging_msg);
mme_sess_remove_all(mme_ue);
mme_pdn_remove_all(mme_ue);
@ -1797,3 +1811,15 @@ pdn_t* mme_pdn_next(pdn_t *pdn)
return list_next(pdn);
}
void mme_ue_paged(mme_ue_t *mme_ue)
{
d_assert(mme_ue, return , "Null param");
tm_stop(mme_ue->t3413);
if (mme_ue->last_paging_msg)
{
pkbuf_free(mme_ue->last_paging_msg);
mme_ue->last_paging_msg = NULL;
}
mme_ue->max_paging_retry = 0;
}

View File

@ -91,6 +91,9 @@ typedef struct _mme_context_t {
served_gummei_t served_gummei[MAX_NUM_OF_SERVED_GUMMEI];
c_uint8_t relative_capacity;
/* Timer value*/
c_uint32_t t3413_value; /* Paging retry timer */
list_t sgw_list;
list_t enb_list;
@ -227,6 +230,12 @@ struct _mme_ue_t {
/* Last Received NAS Messasge */
nas_message_t last_emm_message;
nas_message_t last_esm_message;
/* Paging */
pkbuf_t *last_paging_msg;
tm_block_id t3413;
#define MAX_NUM_OF_PAGING 2
c_uint32_t max_paging_retry;
};
typedef struct _mme_sess_t {
@ -364,6 +373,7 @@ CORE_DECLARE(enb_ue_t*) enb_ue_find_by_mme_ue_s1ap_id(c_uint32_t mme_ue_s1ap
CORE_DECLARE(enb_ue_t*) enb_ue_first_in_enb(mme_enb_t *enb);
CORE_DECLARE(enb_ue_t*) enb_ue_next_in_enb(enb_ue_t *enb_ue);
CORE_DECLARE(void) mme_ue_paged(mme_ue_t *mme_ue);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -26,6 +26,7 @@ typedef enum {
MME_EVT_EMM_UE_FROM_S11,
MME_EVT_EMM_BEARER_FROM_S11,
MME_EVT_EMM_UE_T3,
MME_EVT_EMM_UE_T3413,
MME_EVT_ESM_BEARER_MSG,
MME_EVT_ESM_BEARER_FROM_S6A,

View File

@ -224,6 +224,7 @@ void mme_state_operational(fsm_t *s, event_t *e)
case MME_EVT_EMM_UE_FROM_S11:
case MME_EVT_EMM_BEARER_FROM_S11:
case MME_EVT_EMM_UE_T3:
case MME_EVT_EMM_UE_T3413:
{
index_t index = event_get_param1(e);
mme_ue_t *mme_ue = NULL;

View File

@ -351,16 +351,6 @@ status_t s1ap_build_paging(pkbuf_t **s1apbuf, mme_ue_t *mme_ue)
c_uint16_t index_value;
c_uint64_t ue_imsi_value = 0;
int i = 0;
#if 0
uint16_t presenceMask;
S1ap_UEIdentityIndexValue_t ueIdentityIndexValue;
S1ap_UEPagingID_t uePagingID;
S1ap_PagingDRX_t pagingDRX; ///< Optional field
S1ap_CNDomain_t cnDomain;
S1ap_TAIList_IEs_t taiList;
S1ap_CSG_IdList_t csG_IdList; ///< Optional field
S1ap_PagingPriority_t pagingPriority; ///< Optional field
#endif
d_assert(mme_ue, return CORE_ERROR, "Null param");
@ -395,18 +385,11 @@ status_t s1ap_build_paging(pkbuf_t **s1apbuf, mme_ue_t *mme_ue)
ies->cnDomain = S1ap_CNDomain_ps;
/* List of TAIs */
//S1ap_TAIList_IEs_t taiList;
//S1ap_TAIItem_t
///S1ap_TAI_t tAI;
//S1ap_PLMNidentity_t pLMNidentity;
//S1ap_TAC_t tAC;
tai_item = core_calloc(1, sizeof(S1ap_TAIItem_t));
s1ap_buffer_to_OCTET_STRING(&mme_ue->tai.plmn_id, sizeof(plmn_id_t),
&tai_item->tAI.pLMNidentity);
s1ap_uint16_to_OCTET_STRING(mme_ue->tai.tac, &tai_item->tAI.tAC);
//S1ap_PagingIEs_t *ies = &message.s1ap_PagingIEs;
ASN_SEQUENCE_ADD(&ies->taiList, tai_item);
message.procedureCode = S1ap_ProcedureCode_id_Paging;

View File

@ -537,3 +537,40 @@ void s1ap_handle_ue_context_release_complete(
enb_ue_remove(enb_ue);
}
void s1ap_handle_paging(mme_ue_t *mme_ue)
{
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
int i;
status_t rv;
/* Find enB with matched TAI */
enb = mme_enb_first();
while (enb)
{
for (i = 0; i < enb->num_of_tai; i++)
{
if (!memcmp(&enb->tai[i], &mme_ue->tai, sizeof(tai_t)))
{
if (mme_ue->last_paging_msg)
s1apbuf = mme_ue->last_paging_msg;
else
{
/* Buidl S1Ap Paging message */
rv = s1ap_build_paging(&s1apbuf, mme_ue);
d_assert(rv == CORE_OK && s1apbuf, return,
"s1ap build error");
/* Save it for later use */
mme_ue->last_paging_msg = pkbuf_copy(s1apbuf);
}
/* Send to enb */
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK, return,
"s1ap send error");
}
}
enb = mme_enb_next(enb);
}
}

View File

@ -27,6 +27,7 @@ CORE_DECLARE(void) s1ap_handle_ue_context_release_complete(
CORE_DECLARE(void) s1ap_handle_detach_accept(mme_enb_t *enb, enb_ue_t *enb_ue);
CORE_DECLARE(void) s1ap_handle_release_access_bearers_response(
mme_enb_t *enb, enb_ue_t *enb_ue);
CORE_DECLARE(void) s1ap_handle_paging(mme_ue_t *mme_ue);
#ifdef __cplusplus
}

View File

@ -122,6 +122,10 @@ static int _gtpv1_s5u_recv_cb(net_sock_t *sock, void *data)
int i;
for (i = 0; i < bearer->num_buffered_pkt; i++)
{
gtp_h =
(gtp_header_t *)bearer->buffered_pkts[i]->payload;
gtp_h->teid = htonl(bearer->enb_s1u_teid);
gtp_send(sgw_self()->s1u_sock, &gnode,
bearer->buffered_pkts[i]);
pkbuf_free(bearer->buffered_pkts[i]);