Retransmit paging if UE is not paged.
This commit is contained in:
parent
f2a1bbeca1
commit
d3cdbac70d
|
@ -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
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue