diff --git a/src/amf/context.c b/src/amf/context.c index 7205677b0..08f8510dc 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -2622,10 +2622,80 @@ static bool check_smf_info_nr_tai( return false; } +/* + * Issues #2482 + * + * Changed to that registration can be accepted only + * when the UE slice is available in the RAN slice. + * + * TS23.502 + * 4.2.2 Registration Management procedures + * 4.2.2.2 Registration procedures + * 4.2.2.2.2 General Registration + * + * 21. ... + * If the Requested NSSAI does not include S-NSSAIs which map to S-NSSAIs + * of the HPLMN subject to Network Slice-Specific Authentication and + * Authorization and the AMF determines that no S-NSSAI can be provided + * in the Allowed NSSAI for the UE in the current UE's Tracking Area and + * if no default S-NSSAI(s) not yet involved in the current UE Registration + * procedure could be further considered, the AMF shall reject the UE + * Registration and shall include in the rejection message the list + * of Rejected S-NSSAIs, each of them with the appropriate rejection + * cause value. + */ +static bool gnb_ta_is_supported( + amf_gnb_t *gnb, + ogs_plmn_id_t *plmn_id, ogs_uint24_t tac, ogs_s_nssai_t *s_nssai) +{ + int i, j, k; + + ogs_assert(gnb); + ogs_assert(plmn_id); + + for (i = 0; i < gnb->num_of_supported_ta_list; i++) { + if (gnb->supported_ta_list[i].tac.v != tac.v) + continue; + + for (j = 0; j < gnb->supported_ta_list[i].num_of_bplmn_list; j++) { + if (memcmp(&gnb->supported_ta_list[i].bplmn_list[j].plmn_id, + plmn_id, sizeof(*plmn_id)) != 0) + continue; + + for (k = 0; + k < gnb->supported_ta_list[i].bplmn_list[j].num_of_s_nssai; + k++) { + if (gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sst == + s_nssai->sst && + gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sd.v == + s_nssai->sd.v) + return true; + } + } + } + + return false; +} + + bool amf_update_allowed_nssai(amf_ue_t *amf_ue) { - int i; + int i, j, k; + amf_gnb_t *gnb = NULL; + ran_ue_t *ran_ue = NULL; + ogs_assert(amf_ue); + ran_ue = ran_ue_cycle(amf_ue->ran_ue); + if (!ran_ue) { + ogs_error("[%s] RAN-NG Context has already been removed", + amf_ue->supi); + return false; + } + gnb = amf_gnb_cycle(ran_ue->gnb); + if (!gnb) { + ogs_error("gNB has already been removed"); + return false; + } /* * TS23.501 @@ -2718,10 +2788,19 @@ bool amf_update_allowed_nssai(amf_ue_t *amf_ue) ogs_nas_rejected_s_nssai_t *rejected = &amf_ue->rejected_nssai. s_nssai[amf_ue->rejected_nssai.num_of_s_nssai]; + bool ta_supported = false; + + slice = ogs_slice_find_by_s_nssai( amf_ue->slice, amf_ue->num_of_slice, (ogs_s_nssai_t *)requested); - if (slice) { + if (slice) + ta_supported = gnb_ta_is_supported(gnb, + &amf_ue->nr_tai.plmn_id, amf_ue->nr_tai.tac, + &slice->s_nssai); + + if (ta_supported == true) { + allowed->sst = requested->sst; allowed->sd.v = requested->sd.v; allowed->mapped_hplmn_sst = requested->mapped_hplmn_sst; @@ -2753,13 +2832,18 @@ bool amf_update_allowed_nssai(amf_ue_t *amf_ue) &amf_ue->allowed_nssai. s_nssai[amf_ue->allowed_nssai.num_of_s_nssai]; - if (slice->default_indicator == true) { + if (slice->default_indicator == true && + gnb_ta_is_supported(gnb, + &amf_ue->nr_tai.plmn_id, amf_ue->nr_tai.tac, + &slice->s_nssai) == true) { + allowed->sst = slice->s_nssai.sst; allowed->sd.v = slice->s_nssai.sd.v; allowed->mapped_hplmn_sst = 0; allowed->mapped_hplmn_sd.v = OGS_S_NSSAI_NO_SD_VALUE; amf_ue->allowed_nssai.num_of_s_nssai++; + } } } @@ -2792,6 +2876,29 @@ bool amf_update_allowed_nssai(amf_ue_t *amf_ue) amf_ue->requested_nssai.s_nssai[i].sd.v); } + ogs_error(" (gNB) Number of TA List [%d]", gnb->num_of_supported_ta_list); + for (i = 0; i < gnb->num_of_supported_ta_list; i++) { + ogs_error(" TAC:%d", gnb->supported_ta_list[i].tac.v); + ogs_error(" Number of BPLMN List [%d]", + gnb->supported_ta_list[i].num_of_bplmn_list); + for (j = 0; j < gnb->supported_ta_list[i].num_of_bplmn_list; j++) { + ogs_plmn_id_t *plmn_id = + &gnb->supported_ta_list[i].bplmn_list[j].plmn_id; + ogs_error(" PLMN_ID[MCC:%d MNC:%d]", + ogs_plmn_id_mcc(plmn_id), ogs_plmn_id_mnc(plmn_id)); + ogs_error(" Number of S_NSSAI [%d]", + gnb->supported_ta_list[i].bplmn_list[j].num_of_s_nssai); + for (k = 0; k < + gnb->supported_ta_list[i].bplmn_list[j].num_of_s_nssai; + k++) { + ogs_s_nssai_t *s_nssai = + &gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k]; + ogs_error(" S_NSSAI[SST:%d SD:0x%x]", + s_nssai->sst, s_nssai->sd.v); + } + } + } + return false; } diff --git a/src/amf/gmm-build.c b/src/amf/gmm-build.c index 4e15c9b34..4657ba304 100644 --- a/src/amf/gmm-build.c +++ b/src/amf/gmm-build.c @@ -173,11 +173,16 @@ ogs_pkbuf_t *gmm_build_registration_accept(amf_ue_t *amf_ue) return pkbuf; } -ogs_pkbuf_t *gmm_build_registration_reject(ogs_nas_5gmm_cause_t gmm_cause) +ogs_pkbuf_t *gmm_build_registration_reject( + amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t gmm_cause) { ogs_nas_5gs_message_t message; ogs_nas_5gs_registration_reject_t *registration_reject = &message.gmm.registration_reject; + ogs_nas_rejected_nssai_t *rejected_nssai = + ®istration_reject->rejected_nssai; + + ogs_assert(amf_ue); memset(&message, 0, sizeof(message)); message.gmm.h.extended_protocol_discriminator = @@ -186,6 +191,14 @@ ogs_pkbuf_t *gmm_build_registration_reject(ogs_nas_5gmm_cause_t gmm_cause) registration_reject->gmm_cause = gmm_cause; + if (amf_ue->rejected_nssai.num_of_s_nssai) { + ogs_nas_build_rejected_nssai(rejected_nssai, + amf_ue->rejected_nssai.s_nssai, + amf_ue->rejected_nssai.num_of_s_nssai); + registration_reject->presencemask |= + OGS_NAS_5GS_REGISTRATION_REJECT_REJECTED_NSSAI_PRESENT; + } + return ogs_nas_5gs_plain_encode(&message); } diff --git a/src/amf/gmm-build.h b/src/amf/gmm-build.h index f5bed6000..b44ee30ee 100644 --- a/src/amf/gmm-build.h +++ b/src/amf/gmm-build.h @@ -27,7 +27,8 @@ extern "C" { #endif ogs_pkbuf_t *gmm_build_registration_accept(amf_ue_t *amf_ue); -ogs_pkbuf_t *gmm_build_registration_reject(ogs_nas_5gmm_cause_t gmm_cause); +ogs_pkbuf_t *gmm_build_registration_reject( + amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t gmm_cause); ogs_pkbuf_t *gmm_build_service_accept(amf_ue_t *amf_ue); ogs_pkbuf_t *gmm_build_service_reject( diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index b68a6a72d..4d187d4dd 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -1116,7 +1116,11 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e, if (amf_update_allowed_nssai(amf_ue) == false) { ogs_error("No Allowed-NSSAI"); - + r = nas_5gs_send_gmm_reject( + amf_ue, + OGS_5GMM_CAUSE_NO_NETWORK_SLICES_AVAILABLE); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); OGS_FSM_TRAN(s, gmm_state_exception); break; } @@ -1906,10 +1910,6 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) if (rv != OGS_OK) { ogs_error("[%s] amf_nudm_sdm_handle_provisioned(%s) failed", amf_ue->supi, sbi_message->h.resource.component[1]); - r = nas_5gs_send_gmm_reject( - amf_ue, OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_exception); break; } @@ -2292,6 +2292,12 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e) if (amf_update_allowed_nssai(amf_ue) == false) { ogs_error("No Allowed-NSSAI"); + r = nas_5gs_send_gmm_reject( + amf_ue, + OGS_5GMM_CAUSE_NO_NETWORK_SLICES_AVAILABLE); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + OGS_FSM_TRAN(s, gmm_state_exception); break; } diff --git a/src/amf/nas-path.c b/src/amf/nas-path.c index 4e6dca54b..a720b6682 100644 --- a/src/amf/nas-path.c +++ b/src/amf/nas-path.c @@ -218,7 +218,7 @@ int nas_5gs_send_registration_reject( ogs_warn("[%s] Registration reject [%d]", amf_ue->suci, gmm_cause); - gmmbuf = gmm_build_registration_reject(gmm_cause); + gmmbuf = gmm_build_registration_reject(amf_ue, gmm_cause); if (!gmmbuf) { ogs_error("gmm_build_registration_reject() failed"); return OGS_ERROR; diff --git a/src/amf/nudm-handler.c b/src/amf/nudm-handler.c index cf61f82b9..8f2585215 100644 --- a/src/amf/nudm-handler.c +++ b/src/amf/nudm-handler.c @@ -35,6 +35,10 @@ int amf_nudm_sdm_handle_provisioned( if (!ran_ue) { /* ran_ue is required for amf_ue_is_rat_restricted() */ ogs_error("NG context has already been removed"); + r = nas_5gs_send_gmm_reject( + amf_ue, OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); return OGS_ERROR; } @@ -151,11 +155,19 @@ int amf_nudm_sdm_handle_provisioned( if (amf_update_allowed_nssai(amf_ue) == false) { ogs_error("No Allowed-NSSAI"); + r = nas_5gs_send_gmm_reject( + amf_ue, OGS_5GMM_CAUSE_NO_NETWORK_SLICES_AVAILABLE); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); return OGS_ERROR; } if (amf_ue_is_rat_restricted(amf_ue)) { ogs_error("Registration rejected due to RAT restrictions"); + r = nas_5gs_send_gmm_reject( + amf_ue, OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); return OGS_ERROR; }