fix : Allow NSSAI in Registration accept (#910)

Always Present Allow NSSAI in Registration accept
This commit is contained in:
Sukchan Lee 2021-04-03 14:07:44 +09:00
parent ec0752cb95
commit bb38c01229
10 changed files with 302 additions and 125 deletions

View File

@ -251,10 +251,6 @@ nrf:
# o Prefer IPv4 instead of IPv6 for estabishing new GTP connections.
# prefer_ipv4: true
#
# o AMF ignores the UE Requested NSSAI and creates an allowed-NSSAI
# based on the Default S-NSSAI in the Subscription DB.
# ignore_requested_nssai: true
#
parameter:
#

View File

@ -351,9 +351,6 @@ int ogs_app_context_parse_config(void)
parameter_key, "no_ipv4v6_local_addr_in_packet_filter")) {
self.parameter.no_ipv4v6_local_addr_in_packet_filter =
ogs_yaml_iter_bool(&parameter_iter);
} else if (!strcmp(parameter_key, "ignore_requested_nssai")) {
self.parameter.ignore_requested_nssai =
ogs_yaml_iter_bool(&parameter_iter);
} else
ogs_warn("unknown key `%s`", parameter_key);
}

View File

@ -75,7 +75,6 @@ typedef struct ogs_app_context_s {
int use_openair;
int no_ipv4v6_local_addr_in_packet_filter;
int ignore_requested_nssai;
} parameter;
struct {

View File

@ -537,14 +537,6 @@ ogs_slice_data_t *ogs_slice_find_by_s_nssai(
}
}
/* Compare Only SST if DefaultSingleNSSAI */
for (i = 0; i < num_of_slice_data; i++) {
if (slice_data[i].default_indicator == true &&
s_nssai->sst == slice_data[i].s_nssai.sst) {
return slice_data + i;
}
}
return NULL;
}

View File

@ -2018,3 +2018,145 @@ static bool check_smf_info_nr_tai(
return false;
}
void amf_update_allowed_nssai(amf_ue_t *amf_ue)
{
int i;
ogs_assert(amf_ue);
/*
* TS23.501
*
* 5.15.4 UE NSSAI configuration and NSSAI storage aspects
* 5.15.4.1 General
* 5.15.4.1.1 UE Network Slice configuration
*
* S-NSSAIs that the UE provides in the Requested NSSAI which are neither
* in the Allowed NSSAI nor provided as a rejected S-NSSAI, shall, by the
* UE, not be regarded as rejected, i.e. the UE may request to register
* these S-NSSAIs again next time the UE sends a Requested NSSAI
*
* 5.15.5 Detailed Operation Overview
*
* 5.15.5.2 Selection of a Serving AMF supporting the Network Slices
* 5.15.5.2.1 Registration to a set of Network Slices
*
* AMF checks whether it can serve all the S-NSSAI(s) from
* the Requested NSSAI present in the Subscribed S-NSSAIs
* (potentially using configuration for mapping S-NSSAI values
* between HPLMN and Serving PLMN), or all the S-NSSAI(s) marked
* as default in the Subscribed S-NSSAIs in the case that
* no Requested NSSAI was provided or none of the S-NSSAIs
* in the Requested NSSAI are permitted,
* i.e. do not match any of the Subscribed S-NSSAIs or not available
* at the current UE's Tracking Area (see clause 5.15.3).
*
*
* TS24.501
*
* 4.6.2 Mobility management aspects
* 4.6.2.1 General
*
* The UE in NB-N1 mode does not include the requested NSSAI during
* the registration procedure if the 5GS registration type IE indicates
* "mobility registration updating", procedure is not initiated
* to change the slice(s) that the UE is currently registered to,
* and the UE is still in the current registration area. The AMF does not
* include the allowed NSSAI during a registration procedure with the 5GS
* registration type IE indicating "mobility registration updating" except
* if the allowed NSSAI has changed for the UE. The UE considers
* the last received allowed NSSAI as valid until the UE receives
* a new allowed NSSAI.
*
* 5.5.1.2.4 Initial registration accepted by the network
*
* The AMF shall include the allowed NSSAI for the current PLMN
* and shall include the mapped S-NSSAI(s) for the allowed NSSAI
* contained in the requested NSSAI from the UE if available,
* in the REGISTRATION ACCEPT message if the UE included
* the requested NSSAI in the REGISTRATION REQUEST message
* and the AMF allows one or more S-NSSAIs in the requested NSSAI.
*
* 8.2.7.5 Allowed NSSAI
*
* This IE shall be included:
* a) if:
* 1) one or more S-NSSAIs in the requested NSSAI of
* the REGISTRATION REQUEST message are allowed by the AMF
* for a network not supporting NSSAA;
* 2) one or more S-NSSAIs in the requested NSSAI of
* the REGISTRATION REQUEST message are not subject
* to network slice-specific authentication and authorization
* and are allowed by the AMF; or
* 3) the network slice-specific authentication and authorization
* has been successfully performed for one or more S-NSSAIs in
* the requested NSSAI of the REGISTRATION REQUEST message; or
* b) if:
* 1) the requested NSSAI was not included in the REGISTRATION
* REQUEST message or none of the requested NSSAI are allowed;
* 2) the network not supporting NSSAA has one or more subscribed
* S-NSSAIs marked as default that are available; or
* 3) the network has one or more subscribed S-NSSAIs marked
* as default which are not subject to network slice-specific
* authentication and authorization that are available.
*/
amf_ue->allowed_nssai.num_of_s_nssai = 0;
amf_ue->rejected_nssai.num_of_s_nssai = 0;
if (amf_ue->requested_nssai.num_of_s_nssai) {
for (i = 0; i < amf_ue->requested_nssai.num_of_s_nssai; i++) {
ogs_slice_data_t *slice = NULL;
ogs_nas_s_nssai_ie_t *requested =
&amf_ue->requested_nssai.s_nssai[i];
ogs_nas_s_nssai_ie_t *allowed =
&amf_ue->allowed_nssai.
s_nssai[amf_ue->allowed_nssai.num_of_s_nssai];
ogs_nas_rejected_s_nssai_t *rejected =
&amf_ue->rejected_nssai.
s_nssai[amf_ue->rejected_nssai.num_of_s_nssai];
slice = ogs_slice_find_by_s_nssai(
amf_ue->slice, amf_ue->num_of_slice,
(ogs_s_nssai_t *)requested);
if (slice) {
allowed->sst = requested->sst;
allowed->sd.v = requested->sd.v;
allowed->mapped_hplmn_sst = requested->mapped_hplmn_sst;
allowed->mapped_hplmn_sd.v = requested->mapped_hplmn_sd.v;
amf_ue->allowed_nssai.num_of_s_nssai++;
} else {
rejected->sst = requested->sst;
rejected->sd.v = requested->sd.v;
if (rejected->sd.v != OGS_S_NSSAI_NO_SD_VALUE)
rejected->length_of_rejected_s_nssai = 4;
else
rejected->length_of_rejected_s_nssai = 1;
rejected->cause_value =
OGS_NAS_REJECTED_S_NSSAI_NOT_AVIALABLE_IN_PLMN;
amf_ue->rejected_nssai.num_of_s_nssai++;
}
}
}
if (!amf_ue->allowed_nssai.num_of_s_nssai) {
for (i = 0; i < amf_ue->num_of_slice; i++) {
ogs_slice_data_t *slice = &amf_ue->slice[i];
ogs_nas_s_nssai_ie_t *allowed =
&amf_ue->allowed_nssai.s_nssai[i];
if (slice->default_indicator == 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++;
}
}
}
}

View File

@ -279,8 +279,6 @@ struct amf_ue_s {
ogs_nas_s_nssai_ie_t s_nssai[OGS_MAX_NUM_OF_SLICE];
} requested_nssai, allowed_nssai;
bool allowed_nssai_present;
struct {
int num_of_s_nssai;
ogs_nas_rejected_s_nssai_t s_nssai[OGS_MAX_NUM_OF_SLICE];
@ -712,6 +710,8 @@ uint8_t amf_selected_enc_algorithm(amf_ue_t *amf_ue);
void amf_clear_subscribed_info(amf_ue_t *amf_ue);
void amf_update_allowed_nssai(amf_ue_t *amf_ue);
#ifdef __cplusplus
}
#endif

View File

@ -102,25 +102,21 @@ ogs_pkbuf_t *gmm_build_registration_accept(amf_ue_t *amf_ue)
&amf_self()->served_tai[served_tai_index].list2);
/* Set Allowed NSSAI */
if (amf_ue->allowed_nssai_present == true) {
ogs_assert(amf_ue->allowed_nssai.num_of_s_nssai);
ogs_assert(amf_ue->allowed_nssai.num_of_s_nssai);
ogs_nas_build_nssai(allowed_nssai,
amf_ue->allowed_nssai.s_nssai,
amf_ue->allowed_nssai.num_of_s_nssai);
ogs_nas_build_nssai(allowed_nssai,
amf_ue->allowed_nssai.s_nssai,
amf_ue->allowed_nssai.num_of_s_nssai);
registration_accept->presencemask |=
OGS_NAS_5GS_REGISTRATION_ACCEPT_ALLOWED_NSSAI_PRESENT;
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_accept->presencemask |=
OGS_NAS_5GS_REGISTRATION_ACCEPT_ALLOWED_NSSAI_PRESENT;
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_accept->presencemask |=
OGS_NAS_5GS_REGISTRATION_ACCEPT_REJECTED_NSSAI_PRESENT;
}
amf_ue->allowed_nssai_present = false;
OGS_NAS_5GS_REGISTRATION_ACCEPT_REJECTED_NSSAI_PRESENT;
}
/* 5GS network feature support */

View File

@ -153,8 +153,46 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e)
break;
}
if (amf_sess_xact_count(amf_ue) == xact_count)
if (amf_sess_xact_count(amf_ue) == xact_count) {
amf_update_allowed_nssai(amf_ue);
if (!amf_ue->allowed_nssai.num_of_s_nssai) {
int i;
ogs_error("No Allowed-NSSAI");
ogs_error(" Number of Subscribed S-NSSAI [%d]",
amf_ue->num_of_slice);
for (i = 0; i < amf_ue->num_of_slice; i++) {
ogs_slice_data_t *slice = &amf_ue->slice[i];
if (slice->default_indicator == true) {
ogs_error(
" Default S_NSSAI[SST:%d SD:0x%x]",
slice->s_nssai.sst, slice->s_nssai.sd.v);
} else {
ogs_error(
" S_NSSAI[SST:%d SD:0x%x]",
slice->s_nssai.sst, slice->s_nssai.sd.v);
}
}
ogs_error(" Number of Requested NSSAI [%d]",
amf_ue->requested_nssai.num_of_s_nssai);
for (i = 0; i < amf_ue->requested_nssai.
num_of_s_nssai; i++) {
ogs_error(" PLMN_ID[MCC:%d MNC:%d]",
ogs_plmn_id_mcc(&amf_ue->nr_tai.plmn_id),
ogs_plmn_id_mnc(&amf_ue->nr_tai.plmn_id));
ogs_error(" S_NSSAI[SST:%d SD:0x%x]",
amf_ue->requested_nssai.s_nssai[i].sst,
amf_ue->requested_nssai.s_nssai[i].sd.v);
}
OGS_FSM_TRAN(s, gmm_state_exception);
break;
}
nas_5gs_send_registration_accept(amf_ue);
}
OGS_FSM_TRAN(s, &gmm_state_registered);
@ -1086,8 +1124,46 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e)
break;
}
if (amf_sess_xact_count(amf_ue) == xact_count)
if (amf_sess_xact_count(amf_ue) == xact_count) {
amf_update_allowed_nssai(amf_ue);
if (!amf_ue->allowed_nssai.num_of_s_nssai) {
int i;
ogs_error("No Allowed-NSSAI");
ogs_error(" Number of Subscribed S-NSSAI [%d]",
amf_ue->num_of_slice);
for (i = 0; i < amf_ue->num_of_slice; i++) {
ogs_slice_data_t *slice = &amf_ue->slice[i];
if (slice->default_indicator == true) {
ogs_error(
" Default S_NSSAI[SST:%d SD:0x%x]",
slice->s_nssai.sst, slice->s_nssai.sd.v);
} else {
ogs_error(
" S_NSSAI[SST:%d SD:0x%x]",
slice->s_nssai.sst, slice->s_nssai.sd.v);
}
}
ogs_error(" Number of Requested NSSAI [%d]",
amf_ue->requested_nssai.num_of_s_nssai);
for (i = 0; i < amf_ue->requested_nssai.
num_of_s_nssai; i++) {
ogs_error(" PLMN_ID[MCC:%d MNC:%d]",
ogs_plmn_id_mcc(&amf_ue->nr_tai.plmn_id),
ogs_plmn_id_mnc(&amf_ue->nr_tai.plmn_id));
ogs_error(" S_NSSAI[SST:%d SD:0x%x]",
amf_ue->requested_nssai.s_nssai[i].sst,
amf_ue->requested_nssai.s_nssai[i].sd.v);
}
OGS_FSM_TRAN(s, gmm_state_exception);
break;
}
nas_5gs_send_registration_accept(amf_ue);
}
OGS_FSM_TRAN(s, &gmm_state_registered);

View File

@ -134,97 +134,9 @@ int amf_nudm_sdm_handle_provisioned(
}
}
/*
* TS23.501
*
* 5.15.4 UE NSSAI configuration and NSSAI storage aspects
* 5.15.4.1 General
* 5.15.4.1.1 UE Network Slice configuration
*
* S-NSSAIs that the UE provides in the Requested NSSAI which are neither
* in the Allowed NSSAI nor provided as a rejected S-NSSAI, shall, by the
* UE, not be regarded as rejected, i.e. the UE may request to register
* these S-NSSAIs again next time the UE sends a Requested NSSAI
*
* 5.15.5 Detailed Operation Overview
*
* 5.15.5.2 Selection of a Serving AMF supporting the Network Slices
* 5.15.5.2.1 Registration to a set of Network Slices
*
* AMF checks whether it can serve all the S-NSSAI(s) from
* the Requested NSSAI present in the Subscribed S-NSSAIs
* (potentially using configuration for mapping S-NSSAI values
* between HPLMN and Serving PLMN), or all the S-NSSAI(s) marked
* as default in the Subscribed S-NSSAIs in the case that
* no Requested NSSAI was provided or none of the S-NSSAIs
* in the Requested NSSAI are permitted,
* i.e. do not match any of the Subscribed S-NSSAIs or not available
* at the current UE's Tracking Area (see clause 5.15.3).
*/
amf_ue->allowed_nssai.num_of_s_nssai = 0;
amf_ue->rejected_nssai.num_of_s_nssai = 0;
if (ogs_app()->parameter.ignore_requested_nssai == 0 &&
amf_ue->requested_nssai.num_of_s_nssai) {
for (i = 0; i < amf_ue->requested_nssai.num_of_s_nssai; i++) {
ogs_slice_data_t *slice = NULL;
ogs_nas_s_nssai_ie_t *requested =
&amf_ue->requested_nssai.s_nssai[i];
ogs_nas_s_nssai_ie_t *allowed =
&amf_ue->allowed_nssai.
s_nssai[amf_ue->allowed_nssai.num_of_s_nssai];
ogs_nas_rejected_s_nssai_t *rejected =
&amf_ue->rejected_nssai.
s_nssai[amf_ue->rejected_nssai.num_of_s_nssai];
slice = ogs_slice_find_by_s_nssai(
amf_ue->slice, amf_ue->num_of_slice,
(ogs_s_nssai_t *)requested);
if (slice) {
allowed->sst = requested->sst;
allowed->sd.v = requested->sd.v;
allowed->mapped_hplmn_sst = requested->mapped_hplmn_sst;
allowed->mapped_hplmn_sd.v = requested->mapped_hplmn_sd.v;
amf_ue->allowed_nssai.num_of_s_nssai++;
} else {
rejected->sst = requested->sst;
rejected->sd.v = requested->sd.v;
if (rejected->sd.v != OGS_S_NSSAI_NO_SD_VALUE)
rejected->length_of_rejected_s_nssai = 4;
else
rejected->length_of_rejected_s_nssai = 1;
rejected->cause_value =
OGS_NAS_REJECTED_S_NSSAI_NOT_AVIALABLE_IN_PLMN;
amf_ue->rejected_nssai.num_of_s_nssai++;
}
}
}
amf_update_allowed_nssai(amf_ue);
if (!amf_ue->allowed_nssai.num_of_s_nssai) {
for (i = 0; i < amf_ue->num_of_slice; i++) {
ogs_slice_data_t *slice = &amf_ue->slice[i];
ogs_nas_s_nssai_ie_t *allowed =
&amf_ue->allowed_nssai.s_nssai[i];
if (slice->default_indicator == 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++;
}
}
}
if (amf_ue->allowed_nssai.num_of_s_nssai) {
amf_ue->allowed_nssai_present = true;
} else {
ogs_error("No Allowed-NSSAI");
ogs_error(" Number of Subscribed S-NSSAI [%d]",
amf_ue->num_of_slice);

View File

@ -247,6 +247,73 @@ static void test1_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Registration request : Uplink Data Status */
test_ue->registration_request_param.integrity_protected = 0;
test_ue->registration_request_param.guti = 1;
test_ue->registration_request_param.gmm_capability = 1;
test_ue->registration_request_param.requested_nssai = 1;
test_ue->requested_nssai.s_nssai[2].sd.v = 0x000006;
test_ue->registration_request_param.last_visited_registered_tai = 1;
test_ue->registration_request_param.ue_usage_setting = 1;
test_ue->registration_request_param.update_type = 1;
nasbuf = testgmm_build_registration_request(test_ue, NULL);
ABTS_PTR_NOTNULL(tc, nasbuf);
test_ue->registration_request_param.integrity_protected = 1;
test_ue->registration_request_param.guti = 1;
test_ue->registration_request_param.gmm_capability = 0;
test_ue->registration_request_param.requested_nssai = 0;
test_ue->registration_request_param.last_visited_registered_tai = 0;
test_ue->registration_request_param.ue_usage_setting = 0;
test_ue->registration_request_param.update_type = 0;
gmmbuf = testgmm_build_registration_request(test_ue, nasbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, true, true);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive InitialContextSetupRequest +
* Registration accept */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_InitialContextSetup,
test_ue->ngap_procedure_code);
ABTS_INT_EQUAL(tc, 0x0000, test_ue->pdu_session_reactivation_result);
/* Send InitialContextSetupResponse */
sendbuf = testngap_build_initial_context_setup_response(test_ue, false);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send UEContextReleaseRequest */
sendbuf = testngap_build_ue_context_release_request(test_ue,
NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity,
true);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive UEContextReleaseCommand */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_UEContextRelease,
test_ue->ngap_procedure_code);
/* Send UEContextReleaseComplete */
sendbuf = testngap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(300);
/********** Remove Subscriber in Database */