[MME] Incorrect behavior of SGsAP+Dedicated-Bearer (#3072)

First of all, it crashes when creating a Dedicated Bearer
on the default Session that is created for the first time.
This behavior should be possible, so the related ASSERT is removed.

Next, the InitialContextRequest is modified
during the Attach Request to include the first Bearer.

Finally, there was an issue where trying to create a Dedicated Bearer
with SGsAP enabled resulted in an InitialContextSetupRequest message
with a PTI of zero. This is because MME initializes the PTI to 0
upon receiving the Create Bearer Request while processing SGsAP.

All of these issues has been fixed.
This commit is contained in:
Sukchan Lee 2024-04-01 22:07:19 +09:00
parent d32cc14a71
commit da5d424ed9
14 changed files with 621 additions and 106 deletions

View File

@ -124,7 +124,6 @@ ogs_pkbuf_t *esm_build_activate_default_bearer_context_request(
ogs_assert(session->name);
bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer);
ogs_assert(mme_bearer_next(bearer) == NULL);
ogs_debug("Activate default bearer context request");
ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]",
@ -254,6 +253,7 @@ ogs_pkbuf_t *esm_build_activate_dedicated_bearer_context_request(
mme_bearer_t *bearer)
{
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL;
mme_bearer_t *linked_bearer = NULL;
ogs_nas_eps_message_t message;
@ -269,6 +269,8 @@ ogs_pkbuf_t *esm_build_activate_dedicated_bearer_context_request(
&activate_dedicated_eps_bearer_context_request->tft;
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
mme_ue = bearer->mme_ue;
ogs_assert(mme_ue);
linked_bearer = mme_linked_bearer(bearer);
@ -284,7 +286,21 @@ ogs_pkbuf_t *esm_build_activate_dedicated_bearer_context_request(
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.esm.h.eps_bearer_identity = bearer->ebi;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = 0;
/*
* Issue #3072
*
* PTI 0 is set here to prevent a InitialContextSetupRequest message
* with a PTI of 0 from being created when the Create Bearer Request occurs
* and InitialContextSetupRequest occurs.
*
* If you implement the creation of a dedicated bearer
* in the ESM procedure reqeusted by the UE,
* you will need to refactor the part that sets the PTI.
*/
message.esm.h.procedure_transaction_identity =
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
message.esm.h.message_type =
OGS_NAS_EPS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST;

View File

@ -4287,7 +4287,8 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
}
if (pti == OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) {
ogs_error("Both PTI[%d] and EBI[%d] are 0", pti, ebi);
ogs_error("ESM message type: %d, Both PTI[%d] and EBI[%d] are 0",
message->esm.h.message_type, pti, ebi);
r = nas_eps_send_attach_reject(mme_ue->enb_ue, mme_ue,
OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED,
OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
@ -4373,6 +4374,9 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
sess = mme_sess_find_by_apn(mme_ue,
pdn_connectivity_request->access_point_name.apn);
if (sess && create_action != OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
sess->pti = pti;
r = nas_eps_send_pdn_connectivity_reject(
sess,
OGS_NAS_ESM_CAUSE_MULTIPLE_PDN_CONNECTIONS_FOR_A_GIVEN_APN_NOT_ALLOWED,

View File

@ -793,7 +793,7 @@ void mme_s11_handle_create_bearer_request(
ogs_assert(xact);
ogs_assert(req);
ogs_debug("Create Bearer Response");
ogs_debug("Create Bearer Request");
/***********************
* Check MME-UE Context
@ -877,12 +877,25 @@ void mme_s11_handle_create_bearer_request(
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
/*
* DEPRECATED : Issues #3072
*
* PTI 0 is set here to prevent a InitialContextSetupRequest message
* with a PTI of 0 from being created when the Create Bearer Request occurs
* and InitialContextSetupRequest occurs.
*
* If you implement the creation of a dedicated bearer
* in the ESM procedure reqeusted by the UE,
* you will need to refactor the part that sets the PTI.
*/
#if 0
/* Set PTI */
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
if (req->procedure_transaction_id.presence) {
sess->pti = req->procedure_transaction_id.u8;
ogs_debug(" PTI[%d]", sess->pti);
}
#endif
/* Data Plane(UL) : SGW-S1U */
sgw_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data;

View File

@ -106,7 +106,6 @@ int nas_eps_send_attach_accept(mme_ue_t *mme_ue)
{
int rv;
mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL;
ogs_pkbuf_t *s1apbuf = NULL;
ogs_pkbuf_t *esmbuf = NULL, *emmbuf = NULL;
@ -122,10 +121,10 @@ int nas_eps_send_attach_accept(mme_ue_t *mme_ue)
sess = mme_sess_first(mme_ue);
ogs_assert(sess);
ogs_assert(mme_sess_next(sess) == NULL);
bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer);
ogs_assert(mme_bearer_next(bearer) == NULL);
if (mme_sess_next(sess)) {
ogs_error("There should only be one SESSION");
return OGS_ERROR;
}
ogs_debug("[%s] Attach accept", mme_ue->imsi_bcd);

View File

@ -343,11 +343,72 @@ ogs_pkbuf_t *s1ap_build_downlink_nas_transport(
return ogs_s1ap_encode(&pdu);
}
static void fill_e_rab_to_be_setup(
S1AP_E_RABToBeSetupItemCtxtSUReq_t *e_rab, mme_bearer_t *bearer)
{
int rv;
S1AP_GBR_QosInformation_t *gbrQosInformation = NULL;
ogs_assert(e_rab);
ogs_assert(bearer);
e_rab->e_RAB_ID = bearer->ebi;
e_rab->e_RABlevelQoSParameters.qCI = bearer->qos.index;
ogs_debug(" EBI[%d] QCI[%d] SGW-S1U-TEID[%d]",
bearer->ebi, bearer->qos.index, bearer->sgw_s1u_teid);
ogs_debug(" ARP[%d:%d:%d]",
bearer->qos.arp.priority_level,
bearer->qos.arp.pre_emption_capability,
bearer->qos.arp.pre_emption_vulnerability);
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
priorityLevel = bearer->qos.arp.priority_level;
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
pre_emptionCapability =
!(bearer->qos.arp.pre_emption_capability);
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
pre_emptionVulnerability =
!(bearer->qos.arp.pre_emption_vulnerability);
if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink ||
bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) {
ogs_assert(bearer->qos.mbr.downlink);
ogs_assert(bearer->qos.mbr.uplink);
ogs_assert(bearer->qos.gbr.downlink);
ogs_assert(bearer->qos.gbr.uplink);
ogs_debug(" MBR[DL:%lld,UL:%lld]",
(long long)bearer->qos.mbr.downlink,
(long long)bearer->qos.mbr.uplink);
ogs_debug(" GBR[DL:%lld,UL:%lld]",
(long long)bearer->qos.gbr.downlink,
(long long)bearer->qos.gbr.uplink);
gbrQosInformation =
CALLOC(1, sizeof(struct S1AP_GBR_QosInformation));
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL,
bearer->qos.mbr.downlink);
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL,
bearer->qos.mbr.uplink);
asn_uint642INTEGER(&gbrQosInformation->
e_RAB_GuaranteedBitrateDL, bearer->qos.gbr.downlink);
asn_uint642INTEGER(&gbrQosInformation->
e_RAB_GuaranteedBitrateUL, bearer->qos.gbr.uplink);
e_rab->e_RABlevelQoSParameters.gbrQosInformation =
gbrQosInformation;
}
rv = ogs_asn_ip_to_BIT_STRING(
&bearer->sgw_s1u_ip, &e_rab->transportLayerAddress);
ogs_assert(rv == OGS_OK);
ogs_asn_uint32_to_OCTET_STRING(
bearer->sgw_s1u_teid, &e_rab->gTP_TEID);
}
ogs_pkbuf_t *s1ap_build_initial_context_setup_request(
mme_ue_t *mme_ue, ogs_pkbuf_t *emmbuf)
{
int rv;
S1AP_S1AP_PDU_t pdu;
S1AP_InitiatingMessage_t *initiatingMessage = NULL;
S1AP_InitialContextSetupRequest_t *InitialContextSetupRequest = NULL;
@ -443,50 +504,26 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request(
&UEAggregateMaximumBitrate->uEaggregateMaximumBitRateDL,
mme_ue->ambr.downlink);
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_NAS_PDU_t *nasPdu = NULL;
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;
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_inactive)) {
/*
* 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
*/
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;
}
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.
*/
sess = ogs_list_first(&mme_ue->sess_list);
/*
* Issue #3072 : Only first Bearer should be included.
*/
if (sess)
bearer = ogs_list_first(&sess->bearer_list);
if (sess && bearer) {
item = CALLOC(1, sizeof(S1AP_E_RABToBeSetupItemCtxtSUReqIEs_t));
ASN_SEQUENCE_ADD(&E_RABToBeSetupListCtxtSUReq->list, item);
@ -496,58 +533,7 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request(
e_rab = &item->value.choice.E_RABToBeSetupItemCtxtSUReq;
e_rab->e_RAB_ID = bearer->ebi;
e_rab->e_RABlevelQoSParameters.qCI = bearer->qos.index;
ogs_debug(" EBI[%d] QCI[%d] SGW-S1U-TEID[%d]",
bearer->ebi, bearer->qos.index, bearer->sgw_s1u_teid);
ogs_debug(" ARP[%d:%d:%d]",
bearer->qos.arp.priority_level,
bearer->qos.arp.pre_emption_capability,
bearer->qos.arp.pre_emption_vulnerability);
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
priorityLevel = bearer->qos.arp.priority_level;
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
pre_emptionCapability =
!(bearer->qos.arp.pre_emption_capability);
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
pre_emptionVulnerability =
!(bearer->qos.arp.pre_emption_vulnerability);
if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink ||
bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) {
ogs_assert(bearer->qos.mbr.downlink);
ogs_assert(bearer->qos.mbr.uplink);
ogs_assert(bearer->qos.gbr.downlink);
ogs_assert(bearer->qos.gbr.uplink);
ogs_debug(" MBR[DL:%lld,UL:%lld]",
(long long)bearer->qos.mbr.downlink,
(long long)bearer->qos.mbr.uplink);
ogs_debug(" GBR[DL:%lld,UL:%lld]",
(long long)bearer->qos.gbr.downlink,
(long long)bearer->qos.gbr.uplink);
gbrQosInformation =
CALLOC(1, sizeof(struct S1AP_GBR_QosInformation));
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL,
bearer->qos.mbr.downlink);
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL,
bearer->qos.mbr.uplink);
asn_uint642INTEGER(&gbrQosInformation->
e_RAB_GuaranteedBitrateDL, bearer->qos.gbr.downlink);
asn_uint642INTEGER(&gbrQosInformation->
e_RAB_GuaranteedBitrateUL, bearer->qos.gbr.uplink);
e_rab->e_RABlevelQoSParameters.gbrQosInformation =
gbrQosInformation;
}
rv = ogs_asn_ip_to_BIT_STRING(
&bearer->sgw_s1u_ip, &e_rab->transportLayerAddress);
ogs_assert(rv == OGS_OK);
ogs_asn_uint32_to_OCTET_STRING(
bearer->sgw_s1u_teid, &e_rab->gTP_TEID);
fill_e_rab_to_be_setup(e_rab, bearer);
if (emmbuf && emmbuf->len) {
ogs_debug(" NASPdu[%p:%d]", emmbuf, emmbuf->len);
@ -566,6 +552,66 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request(
emmbuf = NULL;
}
}
} else {
/*
* 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
*/
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_inactive)) {
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;
item->criticality = S1AP_Criticality_reject;
item->value.present = S1AP_E_RABToBeSetupItemCtxtSUReqIEs__value_PR_E_RABToBeSetupItemCtxtSUReq;
e_rab = &item->value.choice.E_RABToBeSetupItemCtxtSUReq;
fill_e_rab_to_be_setup(e_rab, bearer);
if (emmbuf && emmbuf->len) {
ogs_debug(" NASPdu[%p:%d]", emmbuf, emmbuf->len);
nasPdu = (S1AP_NAS_PDU_t *)CALLOC(1, sizeof(S1AP_NAS_PDU_t));
nasPdu->size = emmbuf->len;
nasPdu->buf = CALLOC(nasPdu->size, sizeof(uint8_t));
memcpy(nasPdu->buf, emmbuf->data, nasPdu->size);
e_rab->nAS_PDU = nasPdu;
ogs_pkbuf_free(emmbuf);
ogs_log_hexdump(OGS_LOG_DEBUG, nasPdu->buf, nasPdu->size);
/* Since Tracking area update accept is used only once,
* set emmbuf to NULL as shown below */
emmbuf = NULL;
}
}
}
}
if (emmbuf && emmbuf->len) {

View File

@ -196,6 +196,8 @@ static void test1_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send Attach Request */
sess->pti = 1;
sess->pdn_connectivity_param.eit = 1;
sess->pdn_connectivity_param.pco = 1;
sess->pdn_connectivity_param.request_type =
@ -269,6 +271,8 @@ static void test1_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send Attach Request - No Integrity */
sess->pti = 1;
sess->pdn_connectivity_param.eit = 1;
sess->pdn_connectivity_param.pco = 1;
sess->pdn_connectivity_param.request_type =

View File

@ -225,6 +225,8 @@ static void test1_func(abts_case *tc, void *data)
#endif
/* Send Attach Request */
sess->pti = 1;
memset(&sess->pdn_connectivity_param,
0, sizeof(sess->pdn_connectivity_param));
sess->pdn_connectivity_param.eit = 1;
@ -364,6 +366,7 @@ static void test1_func(abts_case *tc, void *data)
/* Send Attach Request - INVALID GUTI */
test_ue->nas_eps_guti.m_tmsi = 0x1234;
sess->pti = 1;
memset(&sess->pdn_connectivity_param,
0, sizeof(sess->pdn_connectivity_param));
@ -618,6 +621,8 @@ static void test2_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send Attach Request - No Integrity */
sess->pti = 1;
sess->pdn_connectivity_param.eit = 1;
sess->pdn_connectivity_param.pco = 1;
sess->pdn_connectivity_param.request_type =
@ -751,6 +756,8 @@ static void test2_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send Attach Request */
sess->pti = 1;
memset(&sess->pdn_connectivity_param,
0, sizeof(sess->pdn_connectivity_param));
sess->pdn_connectivity_param.eit = 1;
@ -1507,6 +1514,8 @@ static void test4_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send Attach Request */
sess->pti = 1;
memset(&sess->pdn_connectivity_param,
0, sizeof(sess->pdn_connectivity_param));
sess->pdn_connectivity_param.eit = 1;

View File

@ -1295,6 +1295,18 @@ test_sess_t *test_sess_find_by_apn(
return NULL;
}
test_sess_t *test_sess_find_by_pti(test_ue_t *test_ue, uint8_t pti)
{
test_sess_t *sess = NULL;
ogs_assert(test_ue);
ogs_list_for_each(&test_ue->sess_list, sess)
if (sess->pti == pti) return sess;
return NULL;
}
test_sess_t *test_sess_find_by_psi(test_ue_t *test_ue, uint8_t psi)
{
test_sess_t *sess = NULL;

View File

@ -513,6 +513,7 @@ void test_sess_remove_all(test_ue_t *test_ue);
test_sess_t *test_sess_find_by_apn(
test_ue_t *test_ue, char *apn, uint8_t rat_type);
test_sess_t *test_sess_find_by_pti(test_ue_t *test_ue, uint8_t pti);
test_sess_t *test_sess_find_by_psi(test_ue_t *test_ue, uint8_t psi);
test_bearer_t *test_bearer_add(test_sess_t *sess, uint8_t ebi);

View File

@ -63,7 +63,13 @@ ogs_pkbuf_t *testesm_build_pdn_connectivity_request(
}
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
if (!sess->pti) {
ogs_error("PTI should be not NULL in PDU Connectivity Request");
return NULL;
}
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.message_type = OGS_NAS_EPS_PDN_CONNECTIVITY_REQUEST;
request_type->type = OGS_NAS_EPS_PDN_TYPE_IPV4V6;
@ -136,7 +142,13 @@ ogs_pkbuf_t *testesm_build_pdn_disconnect_request(test_sess_t *sess)
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
if (!sess->pti) {
ogs_error("PTI should be not NULL in PDU Disonnectivity Request");
return NULL;
}
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.message_type = OGS_NAS_EPS_PDN_DISCONNECT_REQUEST;
linked_eps_bearer_identity->eps_bearer_identity = bearer->ebi;
@ -194,7 +206,13 @@ ogs_pkbuf_t *testesm_build_esm_information_response(test_sess_t *sess)
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
if (!sess->pti) {
ogs_error("PTI should be not 0 in ESM Information Response");
return NULL;
}
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.message_type = OGS_NAS_EPS_ESM_INFORMATION_RESPONSE;
esm_information_response->presencemask |= OGS_NAS_EPS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT;
@ -254,6 +272,7 @@ ogs_pkbuf_t *testesm_build_activate_default_eps_bearer_context_accept(
message.esm.h.eps_bearer_identity = bearer->ebi;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = sess->pti = 0;
message.esm.h.message_type =
OGS_NAS_EPS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT;
@ -289,6 +308,7 @@ ogs_pkbuf_t *testesm_build_activate_dedicated_eps_bearer_context_accept(
message.esm.h.eps_bearer_identity = bearer->ebi;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = sess->pti = 0;
message.esm.h.message_type =
OGS_NAS_EPS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT;
@ -321,6 +341,7 @@ ogs_pkbuf_t *testesm_build_activate_dedicated_eps_bearer_context_reject(
message.esm.h.eps_bearer_identity = bearer->ebi;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = sess->pti = 0;
message.esm.h.message_type =
OGS_NAS_EPS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT;
@ -352,7 +373,7 @@ ogs_pkbuf_t *testesm_build_modify_eps_bearer_context_accept(
message.esm.h.eps_bearer_identity = bearer->ebi;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.procedure_transaction_identity = sess->pti = 0;
message.esm.h.message_type = OGS_NAS_EPS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT;
return test_nas_eps_security_encode(test_ue, &message);
@ -381,6 +402,7 @@ ogs_pkbuf_t *testesm_build_deactivate_eps_bearer_context_accept(
message.esm.h.eps_bearer_identity = bearer->ebi;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = sess->pti = 0;
message.esm.h.message_type =
OGS_NAS_EPS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT;
@ -422,7 +444,13 @@ ogs_pkbuf_t *testesm_build_bearer_resource_allocation_request(
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
if (!sess->pti) {
ogs_error("PTI should be not 0 in Bearer Resource Allocation Request");
return NULL;
}
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.message_type = OGS_NAS_EPS_BEARER_RESOURCE_ALLOCATION_REQUEST;
linked_eps_bearer_identity->eps_bearer_identity = bearer->ebi;
@ -473,7 +501,14 @@ ogs_pkbuf_t *testesm_build_bearer_resource_modification_request(
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
if (!sess->pti) {
ogs_error("PTI should be not 0 "
"in Bearer Resource Modification Request");
return NULL;
}
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.message_type =
OGS_NAS_EPS_BEARER_RESOURCE_MODIFICATION_REQUEST;

View File

@ -19,6 +19,38 @@
#include "test-common.h"
void testesm_handle_esm_information_request(
test_ue_t *test_ue, ogs_nas_eps_message_t *message)
{
test_sess_t *sess = NULL;
ogs_assert(test_ue);
ogs_assert(message);
ogs_assert(message->esm.h.procedure_transaction_identity !=
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED);
sess = test_sess_find_by_pti(
test_ue, message->esm.h.procedure_transaction_identity);
ogs_assert(sess);
}
void testesm_handle_pdn_connectivity_reject(
test_ue_t *test_ue, ogs_nas_eps_message_t *message)
{
test_sess_t *sess = NULL;
ogs_assert(test_ue);
ogs_assert(message);
ogs_assert(message->esm.h.procedure_transaction_identity !=
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED);
sess = test_sess_find_by_pti(
test_ue, message->esm.h.procedure_transaction_identity);
ogs_assert(sess);
}
void testesm_handle_activate_default_eps_bearer_context_request(
test_ue_t *test_ue, ogs_nas_eps_message_t *message)
{
@ -43,6 +75,9 @@ void testesm_handle_activate_default_eps_bearer_context_request(
sess = test_sess_find_by_apn(
test_ue, access_point_name->apn, OGS_GTP2_RAT_TYPE_EUTRAN);
ogs_assert(sess);
ogs_assert(sess->pti == message->esm.h.procedure_transaction_identity);
bearer = test_bearer_find_by_sess_ebi(
sess, message->esm.h.eps_bearer_identity);
if (!bearer)
@ -96,6 +131,8 @@ void testesm_handle_activate_dedicated_eps_bearer_context_request(
sess = bearer->sess;
ogs_assert(sess);
ogs_assert(sess->pti == message->esm.h.procedure_transaction_identity);
bearer = test_bearer_find_by_sess_ebi(
sess, message->esm.h.eps_bearer_identity);
if (!bearer)
@ -103,6 +140,26 @@ void testesm_handle_activate_dedicated_eps_bearer_context_request(
ogs_assert(bearer);
}
void testesm_handle_modify_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);
sess = bearer->sess;
ogs_assert(sess);
ogs_assert(sess->pti == message->esm.h.procedure_transaction_identity);
}
void testesm_handle_deactivate_eps_bearer_context_request(
test_ue_t *test_ue, ogs_nas_eps_message_t *message)
{
@ -117,4 +174,40 @@ void testesm_handle_deactivate_eps_bearer_context_request(
bearer = test_bearer_find_by_ue_ebi(test_ue, ebi);
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
ogs_assert(sess->pti == message->esm.h.procedure_transaction_identity);
}
void testesm_handle_bearer_resource_allocation(
test_ue_t *test_ue, ogs_nas_eps_message_t *message)
{
test_sess_t *sess = NULL;
ogs_assert(test_ue);
ogs_assert(message);
ogs_assert(message->esm.h.procedure_transaction_identity !=
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED);
sess = test_sess_find_by_pti(
test_ue, message->esm.h.procedure_transaction_identity);
ogs_assert(sess);
}
void testesm_handle_bearer_resource_modification(
test_ue_t *test_ue, ogs_nas_eps_message_t *message)
{
test_sess_t *sess = NULL;
ogs_assert(test_ue);
ogs_assert(message);
ogs_assert(message->esm.h.procedure_transaction_identity !=
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED);
sess = test_sess_find_by_pti(
test_ue, message->esm.h.procedure_transaction_identity);
ogs_assert(sess);
}

View File

@ -24,12 +24,22 @@
extern "C" {
#endif
void testesm_handle_esm_information_request(
test_ue_t *test_ue, ogs_nas_eps_message_t *message);
void testesm_handle_pdn_connectivity_reject(
test_ue_t *test_ue, ogs_nas_eps_message_t *message);
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_modify_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);
void testesm_handle_bearer_resource_allocation(
test_ue_t *test_ue, ogs_nas_eps_message_t *message);
void testesm_handle_bearer_resource_modification(
test_ue_t *test_ue, ogs_nas_eps_message_t *message);
#ifdef __cplusplus
}

View File

@ -196,8 +196,10 @@ void testesm_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
test_ue->esm_message_type = message.esm.h.message_type;
switch (message.esm.h.message_type) {
case OGS_NAS_EPS_ESM_INFORMATION_REQUEST:
testesm_handle_esm_information_request(test_ue, &message);
break;
case OGS_NAS_EPS_PDN_CONNECTIVITY_REJECT:
testesm_handle_pdn_connectivity_reject(test_ue, &message);
break;
case OGS_NAS_EPS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST:
testesm_handle_activate_default_eps_bearer_context_request(
@ -208,13 +210,16 @@ void testesm_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
test_ue, &message);
break;
case OGS_NAS_EPS_MODIFY_EPS_BEARER_CONTEXT_REQUEST:
testesm_handle_modify_eps_bearer_context_request(test_ue, &message);
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:
testesm_handle_bearer_resource_allocation(test_ue, &message);
break;
case OGS_NAS_EPS_BEARER_RESOURCE_MODIFICATION_REJECT:
testesm_handle_bearer_resource_modification(test_ue, &message);
break;
default:
ogs_error("Unknown message[%d]", message.esm.h.message_type);

View File

@ -305,6 +305,273 @@ static void test1_func(abts_case *tc, void *data)
test_ue_remove(test_ue);
}
static void test_issues3072_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;
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;
bson_t *doc = NULL;
/* 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_PROTECTION_SCHEME_NULL;
mobile_identity_suci.home_network_pki_value = 0;
test_ue = test_ue_add_by_suci(&mobile_identity_suci, "3746000006");
ogs_assert(test_ue);
test_ue->e_cgi.cell_id = 0x19b010;
test_ue->nas.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE;
test_ue->nas.value = OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH;
test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca";
sess = test_sess_add_by_apn(test_ue, "internet", OGS_GTP2_RAT_TYPE_EUTRAN);
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, 0x19b0);
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 */
doc = test_db_new_qos_flow(test_ue);
ABTS_PTR_NOTNULL(tc, doc);
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc));
/* Send Attach Request */
memset(&sess->pdn_connectivity_param,
0, sizeof(sess->pdn_connectivity_param));
sess->pdn_connectivity_param.eit = 1;
sess->pdn_connectivity_param.pco = 1;
sess->pdn_connectivity_param.request_type =
OGS_NAS_EPS_REQUEST_TYPE_INITIAL;
esmbuf = testesm_build_pdn_connectivity_request(sess, false);
ABTS_PTR_NOTNULL(tc, esmbuf);
memset(&test_ue->attach_request_param,
0, sizeof(test_ue->attach_request_param));
test_ue->attach_request_param.guti = 1;
test_ue->attach_request_param.last_visited_registered_tai = 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.mobile_station_classmark_3 = 1;
test_ue->attach_request_param.supported_codecs = 1;
test_ue->attach_request_param.ue_usage_setting = 1;
test_ue->attach_request_param.old_guti_type = 1;
test_ue->attach_request_param.ms_network_feature_support = 1;
emmbuf = testemm_build_attach_request(test_ue, esmbuf, true, false);
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 Identity Request */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send Identity response */
emmbuf = testemm_build_identity_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 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 */
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 SGsAP-Location-Update-Request */
recvbuf = testvlr_sgsap_read(sgsap);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/*
* To raise the RACE CONDITION
* for the Create Bearer Request and InitialContextSetupRequest
*/
ogs_msleep(100);
/* Send SGsAP-Location-Update-Accept */
sendbuf = test_sgsap_location_update_accept(0);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testvlr_sgsap_send(sgsap, 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 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);
/* Receive SGsAP TMSI-REALLOCATION-COMPLETE */
recvbuf = testvlr_sgsap_read(sgsap);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Receive E-RABSetupRequest +
* Activate dedicated EPS bearer context request */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
S1AP_ProcedureCode_id_E_RABSetup,
test_ue->s1ap_procedure_code);
/* Send E-RABSetupResponse */
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 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);
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(100);
/********** Remove Subscriber in Database */
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue));
/* eNB disonncect from MME */
testenb_s1ap_close(s1ap);
/* eNB disonncect from SGW */
test_gtpu_close(gtpu);
test_ue_remove(test_ue);
}
static void test2_func(abts_case *tc, void *data)
{
int rv;
@ -1043,6 +1310,7 @@ abts_suite *test_mo_idle(abts_suite *suite)
suite = ADD_SUITE(suite)
abts_run_test(suite, test1_func, NULL);
abts_run_test(suite, test_issues3072_func, NULL);
abts_run_test(suite, test2_func, NULL);
abts_run_test(suite, test3_func, NULL);
abts_run_test(suite, test4_func, NULL);