From 424f382265504bf1a09d69814a6f1c798da4a751 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 19 Mar 2023 18:25:59 +0900 Subject: [PATCH] [AMF/MME] Support TAI Range --- configs/open5gs/amf.yaml.in | 37 ++++- configs/open5gs/mme.yaml.in | 38 ++++- configs/open5gs/smf.yaml.in | 8 +- lib/nas/5gs/types.c | 44 ++++-- lib/nas/5gs/types.h | 22 ++- lib/nas/eps/types.c | 47 ++++-- lib/nas/eps/types.h | 25 ++- src/amf/context.c | 145 ++++++++++++----- src/amf/context.h | 3 +- src/amf/gmm-build.c | 3 +- src/mme/emm-build.c | 4 +- src/mme/mme-context.c | 144 ++++++++++++----- src/mme/mme-context.h | 3 +- src/smf/context.c | 153 +++++++++--------- tests/common/context.c | 283 +++++++++++++++++++++++++--------- tests/common/context.h | 4 +- tests/unit/nas-message-test.c | 4 +- 17 files changed, 691 insertions(+), 276 deletions(-) diff --git a/configs/open5gs/amf.yaml.in b/configs/open5gs/amf.yaml.in index 6ac06e0e5..e694dc573 100644 --- a/configs/open5gs/amf.yaml.in +++ b/configs/open5gs/amf.yaml.in @@ -348,34 +348,57 @@ sbi: # # # o Multiple TAI +# +# When multiple TAIs are configured as shown below, +# the Served TAI is determined by comparing UserLocationInformation +# of UplinkNASTransport sent from gNB. +# +# For example, if the gNB sends TAC with 30 to the AMF, +# the fourth TAI (TAC: 20, 28, 29-32, 36-38, 40-42, 50, 60, 70, 70) +# is determined as the Served TAI. The result is transmitted to the gNB +# as a Tracking Area identity List in Registration Accept. +# # amf: # tai: # - plmn_id: # mcc: 001 # mnc: 01 -# tac: [1, 2, 3] +# tac: [1, 3, 5] # tai: # - plmn_id: # mcc: 002 # mnc: 02 -# tac: 4 +# tac: [6-10, 15-18] +# tai: # - plmn_id: # mcc: 003 # mnc: 03 -# tac: 5 -# tai: +# tac: 20 # - plmn_id: # mcc: 004 # mnc: 04 -# tac: [6, 7] +# tac: 21 +# tai: # - plmn_id: # mcc: 005 # mnc: 05 -# tac: 8 +# tac: [22, 28] # - plmn_id: # mcc: 006 # mnc: 06 -# tac: [9, 10] +# tac: [30-32, 34, 36-38, 40-42, 44, 46, 48] +# - plmn_id: +# mcc: 007 +# mnc: 07 +# tac: 50 +# - plmn_id: +# mcc: 008 +# mnc: 08 +# tac: 60 +# - plmn_id: +# mcc: 009 +# mnc: 09 +# tac: [70, 80] # # # diff --git a/configs/open5gs/mme.yaml.in b/configs/open5gs/mme.yaml.in index 75d5d9017..96aaac05d 100644 --- a/configs/open5gs/mme.yaml.in +++ b/configs/open5gs/mme.yaml.in @@ -217,35 +217,57 @@ logger: # # # o Multiple TAI +# +# When multiple TAIs are configured as shown below, +# the Served TAI is determined by comparing UserLocationInformation +# of UplinkNASTransport sent from eNB. +# +# For example, if the eNB sends TAC with 30 to the MME, +# the fourth TAI (TAC: 20, 28, 29-32, 36-38, 40-42, 50, 60, 70, 70) +# is determined as the Served TAI. The result is transmitted to the eNB +# as a Tracking Area identity List in Registration Accept. +# # mme: # tai: # - plmn_id: # mcc: 001 # mnc: 01 -# tac: [1, 2, 3] +# tac: [1, 3, 5] # tai: # - plmn_id: # mcc: 002 # mnc: 02 -# tac: 4 +# tac: [6-10, 15-18] +# tai: # - plmn_id: # mcc: 003 # mnc: 03 -# tac: 5 -# tai: +# tac: 20 # - plmn_id: # mcc: 004 # mnc: 04 -# tac: [6, 7] +# tac: 21 +# tai: # - plmn_id: # mcc: 005 # mnc: 05 -# tac: 8 +# tac: [22, 28] # - plmn_id: # mcc: 006 # mnc: 06 -# tac: [9, 10] -# +# tac: [30-32, 34, 36-38, 40-42, 44, 46, 48] +# - plmn_id: +# mcc: 007 +# mnc: 07 +# tac: 50 +# - plmn_id: +# mcc: 008 +# mnc: 08 +# tac: 60 +# - plmn_id: +# mcc: 009 +# mnc: 09 +# tac: [70, 80] # # # mme: diff --git a/configs/open5gs/smf.yaml.in b/configs/open5gs/smf.yaml.in index 647ea9723..6ab1e7367 100644 --- a/configs/open5gs/smf.yaml.in +++ b/configs/open5gs/smf.yaml.in @@ -501,7 +501,7 @@ sbi: # - plmn_id: # mcc: 999 # mnc: 70 -# range: +# tac: # - 1-9 # - s_nssai: # - sst: 2 @@ -517,7 +517,7 @@ sbi: # - plmn_id: # mcc: 999 # mnc: 70 -# range: +# tac: # - 10-20 # - 30-40 # @@ -562,13 +562,13 @@ sbi: # - plmn_id: # mcc: 999 # mnc: 70 -# range: +# tac: # - 100-200 # - 300-400 # - plmn_id: # mcc: 999 # mnc: 70 -# range: +# tac: # - 500-600 # - 700-800 # - 900-1000 diff --git a/lib/nas/5gs/types.c b/lib/nas/5gs/types.c index 8d3dd2707..18d739e7e 100644 --- a/lib/nas/5gs/types.c +++ b/lib/nas/5gs/types.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -21,28 +21,30 @@ int ogs_nas_5gs_tai_list_build( ogs_nas_5gs_tracking_area_identity_list_t *target, - ogs_5gs_tai0_list_t *source0, ogs_5gs_tai2_list_t *source2) + ogs_5gs_tai0_list_t *source0, + ogs_5gs_tai1_list_t *source1, + ogs_5gs_tai2_list_t *source2) { int i = 0, j = 0, size = 0; ogs_5gs_tai0_list_t target0; + ogs_5gs_tai1_list_t target1; ogs_5gs_tai2_list_t target2; ogs_nas_plmn_id_t ogs_nas_plmn_id; ogs_assert(target); - ogs_assert(source0); - ogs_assert(source2); memset(target, 0, sizeof(ogs_nas_5gs_tracking_area_identity_list_t)); memset(&target0, 0, sizeof(ogs_5gs_tai0_list_t)); + memset(&target1, 0, sizeof(ogs_5gs_tai1_list_t)); memset(&target2, 0, sizeof(ogs_5gs_tai2_list_t)); - for (i = 0; source0->tai[i].num; i++) { + for (i = 0; source0 && source0->tai[i].num; i++) { ogs_assert(source0->tai[i].type == OGS_TAI0_TYPE); target0.tai[i].type = source0->tai[i].type; /* target->num = source->num - 1 */ - ogs_assert(source0->tai[i].num < OGS_MAX_NUM_OF_TAI); + ogs_assert(source0->tai[i].num <= OGS_MAX_NUM_OF_TAI); target0.tai[i].num = source0->tai[i].num - 1; memcpy(&target0.tai[i].plmn_id, ogs_nas_from_plmn_id(&ogs_nas_plmn_id, &source0->tai[i].plmn_id), @@ -62,15 +64,37 @@ int ogs_nas_5gs_tai_list_build( target->length += size; } - if (source2->num) { + for (i = 0; source1 && source1->tai[i].num; i++) { + ogs_assert(source1->tai[i].type == OGS_TAI1_TYPE); + target1.tai[i].type = source1->tai[i].type; + + /* target->num = source->num - 1 */ + ogs_assert(source1->tai[i].num <= OGS_MAX_NUM_OF_TAI); + target1.tai[i].num = source1->tai[i].num - 1; + memcpy(&target1.tai[i].plmn_id, + ogs_nas_from_plmn_id(&ogs_nas_plmn_id, &source1->tai[i].plmn_id), + OGS_PLMN_ID_LEN); + + target1.tai[i].tac = ogs_htobe24(source1->tai[i].tac); + + size = (1 + 3 + 3); + if ((target->length + size) > OGS_NAS_5GS_MAX_TAI_LIST_LEN) { + ogs_error("Overflow: Ignore remained TAI LIST(length:%d, size:%d)", + target->length, size); + return OGS_ERROR; + } + memcpy(target->buffer + target->length, &target1.tai[i], size); + target->length += size; + } + + if (source2 && source2->num) { memset(&target2, 0, sizeof(target2)); - ogs_assert(source2->type == OGS_TAI1_TYPE || - source2->type == OGS_TAI2_TYPE); + ogs_assert(source2->type == OGS_TAI2_TYPE); target2.type = source2->type; /* target->num = source->num - 1 */ - ogs_assert(source2->num < OGS_MAX_NUM_OF_TAI); + ogs_assert(source2->num <= OGS_MAX_NUM_OF_TAI); target2.num = source2->num - 1; size = (1 + (3 + 3) * source2->num); diff --git a/lib/nas/5gs/types.h b/lib/nas/5gs/types.h index b0457431f..cc35611db 100644 --- a/lib/nas/5gs/types.h +++ b/lib/nas/5gs/types.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -339,6 +339,22 @@ typedef struct ogs_5gs_tai0_list_s { } __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI]; } __attribute__ ((packed)) ogs_5gs_tai0_list_t; +typedef struct ogs_5gs_tai1_list_s { + struct { + ED3(uint8_t spare:1;, + uint8_t type:2;, + uint8_t num:5;) + /* + * Do not change 'ogs_plmn_id_t' to 'ogs_nas_plmn_id_t'. + * Use 'ogs_plmn_id_t' for easy implementation. + * ogs_nas_tai_list_build() changes to NAS format(ogs_nas_plmn_id_t) + * and is sent to the UE. + */ + ogs_plmn_id_t plmn_id; + ogs_uint24_t tac; + } __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI]; +} __attribute__ ((packed)) ogs_5gs_tai1_list_t; + typedef struct ogs_5gs_tai2_list_s { ED3(uint8_t spare:1;, uint8_t type:2;, @@ -360,7 +376,9 @@ typedef struct ogs_nas_5gs_tracking_area_identity_list_s { int ogs_nas_5gs_tai_list_build( ogs_nas_5gs_tracking_area_identity_list_t *target, - ogs_5gs_tai0_list_t *source0, ogs_5gs_tai2_list_t *source2); + ogs_5gs_tai0_list_t *source0, + ogs_5gs_tai1_list_t *source1, + ogs_5gs_tai2_list_t *source2); /* 9.11.3.9A 5GS update type * O TLV 3 */ diff --git a/lib/nas/eps/types.c b/lib/nas/eps/types.c index 7dcf0bf5a..d526c1924 100644 --- a/lib/nas/eps/types.c +++ b/lib/nas/eps/types.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -19,29 +19,32 @@ #include "ogs-nas-eps.h" -int ogs_nas_tai_list_build(ogs_nas_tracking_area_identity_list_t *target, - ogs_eps_tai0_list_t *source0, ogs_eps_tai2_list_t *source2) +int ogs_nas_tai_list_build( + ogs_nas_tracking_area_identity_list_t *target, + ogs_eps_tai0_list_t *source0, + ogs_eps_tai1_list_t *source1, + ogs_eps_tai2_list_t *source2) { int i = 0, j = 0, size = 0; ogs_eps_tai0_list_t target0; + ogs_eps_tai1_list_t target1; ogs_eps_tai2_list_t target2; ogs_nas_plmn_id_t ogs_nas_plmn_id; ogs_assert(target); - ogs_assert(source0); - ogs_assert(source2); memset(target, 0, sizeof(ogs_nas_tracking_area_identity_list_t)); memset(&target0, 0, sizeof(ogs_eps_tai0_list_t)); + memset(&target1, 0, sizeof(ogs_eps_tai1_list_t)); memset(&target2, 0, sizeof(ogs_eps_tai2_list_t)); - for (i = 0; source0->tai[i].num; i++) { + for (i = 0; source0 && source0->tai[i].num; i++) { ogs_assert(source0->tai[i].type == OGS_TAI0_TYPE); target0.tai[i].type = source0->tai[i].type; /* target->num = source->num - 1 */ - ogs_assert(source0->tai[i].num < OGS_MAX_NUM_OF_TAI); + ogs_assert(source0->tai[i].num <= OGS_MAX_NUM_OF_TAI); target0.tai[i].num = source0->tai[i].num - 1; memcpy(&target0.tai[i].plmn_id, ogs_nas_from_plmn_id(&ogs_nas_plmn_id, &source0->tai[i].plmn_id), @@ -61,15 +64,37 @@ int ogs_nas_tai_list_build(ogs_nas_tracking_area_identity_list_t *target, target->length += size; } - if (source2->num) { + for (i = 0; source1 && source1->tai[i].num; i++) { + ogs_assert(source1->tai[i].type == OGS_TAI1_TYPE); + target1.tai[i].type = source1->tai[i].type; + + /* target->num = source->num - 1 */ + ogs_assert(source1->tai[i].num <= OGS_MAX_NUM_OF_TAI); + target1.tai[i].num = source1->tai[i].num - 1; + memcpy(&target1.tai[i].plmn_id, + ogs_nas_from_plmn_id(&ogs_nas_plmn_id, &source1->tai[i].plmn_id), + OGS_PLMN_ID_LEN); + + target1.tai[i].tac = htobe16(source1->tai[i].tac); + + size = (1 + 3 + 2); + if ((target->length + size) > OGS_NAS_EPS_MAX_TAI_LIST_LEN) { + ogs_error("Overflow: Ignore remained TAI LIST(length:%d, size:%d)", + target->length, size); + return OGS_ERROR; + } + memcpy(target->buffer + target->length, &target1.tai[i], size); + target->length += size; + } + + if (source2 && source2->num) { memset(&target2, 0, sizeof(target2)); - ogs_assert(source2->type == OGS_TAI1_TYPE || - source2->type == OGS_TAI2_TYPE); + ogs_assert(source2->type == OGS_TAI2_TYPE); target2.type = source2->type; /* target->num = source->num - 1 */ - ogs_assert(source2->num < OGS_MAX_NUM_OF_TAI); + ogs_assert(source2->num <= OGS_MAX_NUM_OF_TAI); target2.num = source2->num - 1; size = (1 + (3 + 2) * source2->num); diff --git a/lib/nas/eps/types.h b/lib/nas/eps/types.h index 6fa3ecb9a..3d8909cd2 100644 --- a/lib/nas/eps/types.h +++ b/lib/nas/eps/types.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -546,6 +546,22 @@ typedef struct ogs_eps_tai0_list_s { } __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI]; } __attribute__ ((packed)) ogs_eps_tai0_list_t; +typedef struct ogs_eps_tai1_list_s { + struct { + ED3(uint8_t spare:1;, + uint8_t type:2;, + uint8_t num:5;) + /* + * Do not change 'ogs_plmn_id_t' to 'ogs_nas_plmn_id_t'. + * Use 'ogs_plmn_id_t' for easy implementation. + * ogs_nas_tai_list_build() changes to NAS format(ogs_nas_plmn_id_t) + * and is sent to the UE. + */ + ogs_plmn_id_t plmn_id; + uint16_t tac; + } __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI]; +} __attribute__ ((packed)) ogs_eps_tai1_list_t; + typedef struct ogs_eps_tai2_list_s { ED3(uint8_t spare:1;, uint8_t type:2;, @@ -565,8 +581,11 @@ typedef struct ogs_nas_tracking_area_identity_list_s { uint8_t buffer[OGS_NAS_EPS_MAX_TAI_LIST_LEN]; } __attribute__ ((packed)) ogs_nas_tracking_area_identity_list_t; -int ogs_nas_tai_list_build(ogs_nas_tracking_area_identity_list_t *target, - ogs_eps_tai0_list_t *source0, ogs_eps_tai2_list_t *source2); +int ogs_nas_tai_list_build( + ogs_nas_tracking_area_identity_list_t *target, + ogs_eps_tai0_list_t *source0, + ogs_eps_tai1_list_t *source1, + ogs_eps_tai2_list_t *source2); /* 9.9.3.35 UE radio capability information update needed diff --git a/src/amf/context.c b/src/amf/context.c index 4ead83d29..990cb784c 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -433,22 +433,24 @@ int amf_context_parse_config(void) YAML_SEQUENCE_NODE); } else if (!strcmp(amf_key, "tai")) { int num_of_list0 = 0; + int num_of_list1 = 0; ogs_5gs_tai0_list_t *list0 = NULL; + ogs_5gs_tai1_list_t *list1 = NULL; ogs_5gs_tai2_list_t *list2 = NULL; ogs_assert(self.num_of_served_tai < OGS_MAX_NUM_OF_SERVED_TAI); list0 = &self.served_tai[self.num_of_served_tai].list0; - ogs_assert(list0); + list1 = &self.served_tai[self.num_of_served_tai].list1; list2 = &self.served_tai[self.num_of_served_tai].list2; - ogs_assert(list2); ogs_yaml_iter_t tai_array, tai_iter; ogs_yaml_iter_recurse(&amf_iter, &tai_array); do { const char *mcc = NULL, *mnc = NULL; - ogs_uint24_t tac[OGS_MAX_NUM_OF_TAI]; int num_of_tac = 0; + ogs_uint24_t start[OGS_MAX_NUM_OF_TAI]; + ogs_uint24_t end[OGS_MAX_NUM_OF_TAI]; if (ogs_yaml_iter_type(&tai_array) == YAML_MAPPING_NODE) { @@ -489,23 +491,56 @@ int amf_context_parse_config(void) ogs_yaml_iter_t tac_iter; ogs_yaml_iter_recurse(&tai_iter, &tac_iter); ogs_assert(ogs_yaml_iter_type(&tac_iter) != - YAML_MAPPING_NODE); - + YAML_MAPPING_NODE); do { - const char *v = NULL; + char *v = NULL; + char *low = NULL, *high = NULL; - ogs_assert(num_of_tac < - OGS_MAX_NUM_OF_TAI); if (ogs_yaml_iter_type(&tac_iter) == YAML_SEQUENCE_NODE) { if (!ogs_yaml_iter_next(&tac_iter)) break; } - v = ogs_yaml_iter_value(&tac_iter); + v = (char *)ogs_yaml_iter_value( + &tac_iter); if (v) { - tac[num_of_tac].v = atoi(v); - num_of_tac++; + low = strsep(&v, "-"); + if (low && strlen(low) == 0) + low = NULL; + + high = v; + if (high && strlen(high) == 0) + high = NULL; + + if (low) { + ogs_assert(num_of_tac < + OGS_MAX_NUM_OF_TAI); + start[num_of_tac].v = atoi(low); + if (high) { + end[num_of_tac].v = atoi(high); + if (end[num_of_tac].v < + start[num_of_tac].v) + ogs_error( + "Invalid TAI range: " + "LOW:%s,HIGH:%s", + low, high); + else if ( + (end[num_of_tac].v- + start[num_of_tac].v+1) > + OGS_MAX_NUM_OF_TAI) + ogs_error( + "Overflow TAI range: " + "LOW:%s,HIGH:%s", + low, high); + else + num_of_tac++; + } else { + end[num_of_tac].v = + start[num_of_tac].v; + num_of_tac++; + } + } } } while ( ogs_yaml_iter_type(&tac_iter) == @@ -515,31 +550,60 @@ int amf_context_parse_config(void) } if (mcc && mnc && num_of_tac) { - if (num_of_tac == 1) { + if (num_of_tac == 1 && start[0].v == end[0].v) { + ogs_assert(list2->num < OGS_MAX_NUM_OF_TAI); + + list2->type = OGS_TAI2_TYPE; + ogs_plmn_id_build( &list2->tai[list2->num].plmn_id, atoi(mcc), atoi(mnc), strlen(mnc)); - list2->tai[list2->num].tac.v = tac[0].v; + list2->tai[list2->num].tac.v = start[0].v; list2->num++; - if (list2->num > 1) - list2->type = OGS_TAI2_TYPE; - else - list2->type = OGS_TAI1_TYPE; - } else if (num_of_tac > 1) { - int i; - ogs_plmn_id_build( - &list0->tai[num_of_list0].plmn_id, - atoi(mcc), atoi(mnc), strlen(mnc)); - for (i = 0; i < num_of_tac; i++) { - list0->tai[num_of_list0].tac[i].v = - tac[i].v; + + } else { + int tac, count = 0; + for (tac = 0; tac < num_of_tac; tac++) { + ogs_assert(end[tac].v >= start[tac].v); + if (start[tac].v == end[tac].v) { + ogs_assert(num_of_list0 < + OGS_MAX_NUM_OF_TAI); + + list0->tai[num_of_list0].type = + OGS_TAI0_TYPE; + + ogs_plmn_id_build( + &list0->tai[num_of_list0].plmn_id, + atoi(mcc), atoi(mnc), strlen(mnc)); + list0->tai[num_of_list0]. + tac[count].v = start[tac].v; + + list0->tai[num_of_list0].num = + ++count; + + } else if (start[tac].v < end[tac].v) { + ogs_assert(num_of_list1 < + OGS_MAX_NUM_OF_TAI); + + list1->tai[num_of_list1].type = + OGS_TAI1_TYPE; + + ogs_plmn_id_build( + &list1->tai[num_of_list1].plmn_id, + atoi(mcc), atoi(mnc), strlen(mnc)); + list1->tai[num_of_list1].tac.v = + start[tac].v; + + list1->tai[num_of_list1].num = + end[tac].v-start[tac].v+1; + + num_of_list1++; + } } - list0->tai[num_of_list0].num = num_of_tac; - list0->tai[num_of_list0].type = OGS_TAI0_TYPE; - - num_of_list0++; + if (count) + num_of_list0++; } } else { ogs_warn("Ignore tai : mcc(%p), mnc(%p), " @@ -548,7 +612,7 @@ int amf_context_parse_config(void) } while (ogs_yaml_iter_type(&tai_array) == YAML_SEQUENCE_NODE); - if (list2->num || num_of_list0) { + if (list2->num || num_of_list1 || num_of_list0) { self.num_of_served_tai++; } } else if (!strcmp(amf_key, "plmn_support")) { @@ -2154,13 +2218,12 @@ int amf_find_served_tai(ogs_5gs_tai_t *nr_tai) for (i = 0; i < self.num_of_served_tai; i++) { ogs_5gs_tai0_list_t *list0 = &self.served_tai[i].list0; - ogs_assert(list0); + ogs_5gs_tai1_list_t *list1 = &self.served_tai[i].list1; ogs_5gs_tai2_list_t *list2 = &self.served_tai[i].list2; - ogs_assert(list2); for (j = 0; list0->tai[j].num; j++) { ogs_assert(list0->tai[j].type == OGS_TAI0_TYPE); - ogs_assert(list0->tai[j].num < OGS_MAX_NUM_OF_TAI); + ogs_assert(list0->tai[j].num <= OGS_MAX_NUM_OF_TAI); for (k = 0; k < list0->tai[j].num; k++) { if (memcmp(&list0->tai[j].plmn_id, @@ -2171,10 +2234,18 @@ int amf_find_served_tai(ogs_5gs_tai_t *nr_tai) } } + for (j = 0; list1->tai[j].num; j++) { + ogs_assert(list1->tai[j].type == OGS_TAI1_TYPE); + ogs_assert(list1->tai[j].num <= OGS_MAX_NUM_OF_TAI); + + if (list1->tai[j].tac.v <= nr_tai->tac.v && + nr_tai->tac.v < (list1->tai[j].tac.v+list1->tai[j].num)) + return i; + } + if (list2->num) { - ogs_assert(list2->type == OGS_TAI1_TYPE || - list2->type == OGS_TAI2_TYPE); - ogs_assert(list2->num < OGS_MAX_NUM_OF_TAI); + ogs_assert(list2->type == OGS_TAI2_TYPE); + ogs_assert(list2->num <= OGS_MAX_NUM_OF_TAI); for (j = 0; j < list2->num; j++) { if (memcmp(&list2->tai[j].plmn_id, diff --git a/src/amf/context.h b/src/amf/context.h index fceb928a6..e126ce167 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -54,6 +54,7 @@ typedef struct amf_context_s { int num_of_served_tai; struct { ogs_5gs_tai0_list_t list0; + ogs_5gs_tai1_list_t list1; ogs_5gs_tai2_list_t list2; } served_tai[OGS_MAX_NUM_OF_SERVED_TAI]; diff --git a/src/amf/gmm-build.c b/src/amf/gmm-build.c index 6f2f5204e..4e15c9b34 100644 --- a/src/amf/gmm-build.c +++ b/src/amf/gmm-build.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -101,6 +101,7 @@ ogs_pkbuf_t *gmm_build_registration_accept(amf_ue_t *amf_ue) ogs_assert(OGS_OK == ogs_nas_5gs_tai_list_build(®istration_accept->tai_list, &amf_self()->served_tai[served_tai_index].list0, + &amf_self()->served_tai[served_tai_index].list1, &amf_self()->served_tai[served_tai_index].list2)); /* Set Allowed NSSAI */ diff --git a/src/mme/emm-build.c b/src/mme/emm-build.c index 69e9c3a11..17af992bd 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-build.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -161,6 +161,7 @@ ogs_pkbuf_t *emm_build_attach_accept( ogs_assert(OGS_OK == ogs_nas_tai_list_build(&attach_accept->tai_list, &mme_self()->served_tai[served_tai_index].list0, + &mme_self()->served_tai[served_tai_index].list1, &mme_self()->served_tai[served_tai_index].list2)); attach_accept->esm_message_container.buffer = esmbuf->data; @@ -562,6 +563,7 @@ ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue) ogs_assert(OGS_OK == ogs_nas_tai_list_build(&tau_accept->tai_list, &mme_self()->served_tai[served_tai_index].list0, + &mme_self()->served_tai[served_tai_index].list1, &mme_self()->served_tai[served_tai_index].list2)); /* Set EPS bearer context status */ diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 0faf3425d..889fa8b01 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -728,22 +728,24 @@ int mme_context_parse_config() YAML_SEQUENCE_NODE); } else if (!strcmp(mme_key, "tai")) { int num_of_list0 = 0; + int num_of_list1 = 0; ogs_eps_tai0_list_t *list0 = NULL; + ogs_eps_tai1_list_t *list1 = NULL; ogs_eps_tai2_list_t *list2 = NULL; ogs_assert(self.num_of_served_tai < OGS_MAX_NUM_OF_SERVED_TAI); list0 = &self.served_tai[self.num_of_served_tai].list0; - ogs_assert(list0); + list1 = &self.served_tai[self.num_of_served_tai].list1; list2 = &self.served_tai[self.num_of_served_tai].list2; - ogs_assert(list2); ogs_yaml_iter_t tai_array, tai_iter; ogs_yaml_iter_recurse(&mme_iter, &tai_array); do { const char *mcc = NULL, *mnc = NULL; - uint16_t tac[OGS_MAX_NUM_OF_TAI]; int num_of_tac = 0; + uint16_t start[OGS_MAX_NUM_OF_TAI]; + uint16_t end[OGS_MAX_NUM_OF_TAI]; if (ogs_yaml_iter_type(&tai_array) == YAML_MAPPING_NODE) { @@ -784,23 +786,56 @@ int mme_context_parse_config() ogs_yaml_iter_t tac_iter; ogs_yaml_iter_recurse(&tai_iter, &tac_iter); ogs_assert(ogs_yaml_iter_type(&tac_iter) != - YAML_MAPPING_NODE); - + YAML_MAPPING_NODE); do { - const char *v = NULL; + char *v = NULL; + char *low = NULL, *high = NULL; - ogs_assert(num_of_tac < - OGS_MAX_NUM_OF_TAI); if (ogs_yaml_iter_type(&tac_iter) == YAML_SEQUENCE_NODE) { if (!ogs_yaml_iter_next(&tac_iter)) break; } - v = ogs_yaml_iter_value(&tac_iter); + v = (char *)ogs_yaml_iter_value( + &tac_iter); if (v) { - tac[num_of_tac] = atoi(v); - num_of_tac++; + low = strsep(&v, "-"); + if (low && strlen(low) == 0) + low = NULL; + + high = v; + if (high && strlen(high) == 0) + high = NULL; + + if (low) { + ogs_assert(num_of_tac < + OGS_MAX_NUM_OF_TAI); + start[num_of_tac] = atoi(low); + if (high) { + end[num_of_tac] = atoi(high); + if (end[num_of_tac] < + start[num_of_tac]) + ogs_error( + "Invalid TAI range: " + "LOW:%s,HIGH:%s", + low, high); + else if ( + (end[num_of_tac]- + start[num_of_tac]+1) > + OGS_MAX_NUM_OF_TAI) + ogs_error( + "Overflow TAI range: " + "LOW:%s,HIGH:%s", + low, high); + else + num_of_tac++; + } else { + end[num_of_tac] = + start[num_of_tac]; + num_of_tac++; + } + } } } while ( ogs_yaml_iter_type(&tac_iter) == @@ -810,30 +845,60 @@ int mme_context_parse_config() } if (mcc && mnc && num_of_tac) { - if (num_of_tac == 1) { + if (num_of_tac == 1 && start[0] == end[0]) { + ogs_assert(list2->num < OGS_MAX_NUM_OF_TAI); + + list2->type = OGS_TAI2_TYPE; + ogs_plmn_id_build( &list2->tai[list2->num].plmn_id, atoi(mcc), atoi(mnc), strlen(mnc)); - list2->tai[list2->num].tac = tac[0]; + list2->tai[list2->num].tac = start[0]; list2->num++; - if (list2->num > 1) - list2->type = OGS_TAI2_TYPE; - else - list2->type = OGS_TAI1_TYPE; - } else if (num_of_tac > 1) { - int i; - ogs_plmn_id_build( - &list0->tai[num_of_list0].plmn_id, - atoi(mcc), atoi(mnc), strlen(mnc)); - for (i = 0; i < num_of_tac; i++) { - list0->tai[num_of_list0].tac[i] = tac[i]; + + } else { + int tac, count = 0; + for (tac = 0; tac < num_of_tac; tac++) { + ogs_assert(end[tac] >= start[tac]); + if (start[tac] == end[tac]) { + ogs_assert(num_of_list0 < + OGS_MAX_NUM_OF_TAI); + + list0->tai[num_of_list0].type = + OGS_TAI0_TYPE; + + ogs_plmn_id_build( + &list0->tai[num_of_list0].plmn_id, + atoi(mcc), atoi(mnc), strlen(mnc)); + list0->tai[num_of_list0]. + tac[count] = start[tac]; + + list0->tai[num_of_list0].num = + ++count; + + } else if (start[tac] < end[tac]) { + ogs_assert(num_of_list1 < + OGS_MAX_NUM_OF_TAI); + + list1->tai[num_of_list1].type = + OGS_TAI1_TYPE; + + ogs_plmn_id_build( + &list1->tai[num_of_list1].plmn_id, + atoi(mcc), atoi(mnc), strlen(mnc)); + list1->tai[num_of_list1].tac = + start[tac]; + + list1->tai[num_of_list1].num = + end[tac]-start[tac]+1; + + num_of_list1++; + } } - list0->tai[num_of_list0].num = num_of_tac; - list0->tai[num_of_list0].type = OGS_TAI0_TYPE; - - num_of_list0++; + if (count) + num_of_list0++; } } else { ogs_warn("Ignore tai : mcc(%p), mnc(%p), " @@ -842,7 +907,7 @@ int mme_context_parse_config() } while (ogs_yaml_iter_type(&tai_array) == YAML_SEQUENCE_NODE); - if (list2->num || num_of_list0) { + if (list2->num || num_of_list1 || num_of_list0) { self.num_of_served_tai++; } } else if (!strcmp(mme_key, "security")) { @@ -3560,13 +3625,12 @@ int mme_find_served_tai(ogs_eps_tai_t *tai) for (i = 0; i < self.num_of_served_tai; i++) { ogs_eps_tai0_list_t *list0 = &self.served_tai[i].list0; - ogs_assert(list0); + ogs_eps_tai1_list_t *list1 = &self.served_tai[i].list1; ogs_eps_tai2_list_t *list2 = &self.served_tai[i].list2; - ogs_assert(list2); for (j = 0; list0->tai[j].num; j++) { ogs_assert(list0->tai[j].type == OGS_TAI0_TYPE); - ogs_assert(list0->tai[j].num < OGS_MAX_NUM_OF_TAI); + ogs_assert(list0->tai[j].num <= OGS_MAX_NUM_OF_TAI); for (k = 0; k < list0->tai[j].num; k++) { if (memcmp(&list0->tai[j].plmn_id, @@ -3577,10 +3641,18 @@ int mme_find_served_tai(ogs_eps_tai_t *tai) } } + for (j = 0; list1->tai[j].num; j++) { + ogs_assert(list1->tai[j].type == OGS_TAI1_TYPE); + ogs_assert(list1->tai[j].num <= OGS_MAX_NUM_OF_TAI); + + if (list1->tai[j].tac <= tai->tac && + tai->tac < (list1->tai[j].tac+list1->tai[j].num)) + return i; + } + if (list2->num) { - ogs_assert(list2->type == OGS_TAI1_TYPE || - list2->type == OGS_TAI2_TYPE); - ogs_assert(list2->num < OGS_MAX_NUM_OF_TAI); + ogs_assert(list2->type == OGS_TAI2_TYPE); + ogs_assert(list2->num <= OGS_MAX_NUM_OF_TAI); for (j = 0; j < list2->num; j++) { if (memcmp(&list2->tai[j].plmn_id, diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 384f8d587..3961dea16 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -105,6 +105,7 @@ typedef struct mme_context_s { int num_of_served_tai; struct { ogs_eps_tai0_list_t list0; + ogs_eps_tai1_list_t list1; ogs_eps_tai2_list_t list2; } served_tai[OGS_MAX_NUM_OF_SERVED_TAI]; diff --git a/src/smf/context.c b/src/smf/context.c index df46fe6ca..e84002576 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -719,8 +719,6 @@ int smf_context_parse_config(void) do { const char *mcc = NULL, *mnc = NULL; int num_of_tac = 0; - ogs_uint24_t tac[OGS_MAX_NUM_OF_TAI]; - int num_of_range = 0; ogs_uint24_t start[OGS_MAX_NUM_OF_TAI]; ogs_uint24_t end[OGS_MAX_NUM_OF_TAI]; @@ -767,55 +765,25 @@ int smf_context_parse_config(void) } } else if (!strcmp(tai_key, "tac")) { ogs_yaml_iter_t tac_iter; - ogs_yaml_iter_recurse( - &tai_iter, &tac_iter); + ogs_yaml_iter_recurse(&tai_iter, + &tac_iter); ogs_assert(ogs_yaml_iter_type( - &tac_iter) != - YAML_MAPPING_NODE); - - do { - const char *v = NULL; - - ogs_assert(num_of_tac < - OGS_MAX_NUM_OF_TAI); - if (ogs_yaml_iter_type( - &tac_iter) == - YAML_SEQUENCE_NODE) { - if (!ogs_yaml_iter_next( - &tac_iter)) - break; - } - - v = ogs_yaml_iter_value( - &tac_iter); - if (v) { - tac[num_of_tac].v = atoi(v); - num_of_tac++; - } - } while ( - ogs_yaml_iter_type(&tac_iter) == - YAML_SEQUENCE_NODE); - } else if (!strcmp(tai_key, "range")) { - ogs_yaml_iter_t range_iter; - ogs_yaml_iter_recurse( - &tai_iter, &range_iter); - ogs_assert(ogs_yaml_iter_type( - &range_iter) != + &tac_iter) != YAML_MAPPING_NODE); do { char *v = NULL; char *low = NULL, *high = NULL; if (ogs_yaml_iter_type( - &range_iter) == + &tac_iter) == YAML_SEQUENCE_NODE) { if (!ogs_yaml_iter_next( - &range_iter)) + &tac_iter)) break; } v = (char *)ogs_yaml_iter_value( - &range_iter); + &tac_iter); if (v) { low = strsep(&v, "-"); if (low && strlen(low) == 0) @@ -826,20 +794,36 @@ int smf_context_parse_config(void) strlen(high) == 0) high = NULL; - if (low && high) { - ogs_assert( - num_of_range < + if (low) { + ogs_assert(num_of_tac < OGS_MAX_NUM_OF_TAI); - start[num_of_range].v = + start[num_of_tac].v = atoi(low); - end[num_of_range].v = - atoi(high); - num_of_range++; + if (high) { + end[num_of_tac].v = + atoi(high); + if (end[num_of_tac]. + v < + start[ + num_of_tac]. + v) + ogs_error( + "Invalid TAI " + "range: LOW:%s," + "HIGH:%s", + low, high); + else + num_of_tac++; + } else { + end[num_of_tac].v = + start[ + num_of_tac].v; + num_of_tac++; + } } } } while ( - ogs_yaml_iter_type( - &range_iter) == + ogs_yaml_iter_type(&tac_iter) == YAML_SEQUENCE_NODE); } else @@ -847,47 +831,55 @@ int smf_context_parse_config(void) tai_key); } - if (mcc && mnc) { - int i; - - if (num_of_range) { - ogs_assert(num_of_nr_tai_range < - OGS_MAX_NUM_OF_TAI); - ogs_plmn_id_build( - &smf_info->nr_tai_range - [num_of_nr_tai_range]. - plmn_id, - atoi(mcc), atoi(mnc), - strlen(mnc)); - for (i = 0; i < num_of_range; i++) { - smf_info->nr_tai_range - [num_of_nr_tai_range]. - start[i].v = start[i].v; - smf_info->nr_tai_range - [num_of_nr_tai_range]. - end[i].v = end[i].v; - } - smf_info->nr_tai_range - [num_of_nr_tai_range]. - num_of_tac_range = - num_of_range; - num_of_nr_tai_range++; - } else if (num_of_tac) { - for (i = 0; i < num_of_tac; i++) { + if (mcc && mnc && num_of_tac) { + int tac, num_of_tac_range = 0; + for (tac = 0; tac < num_of_tac; tac++) { + ogs_assert(end[tac].v >= + start[tac].v); + if (start[tac].v == end[tac].v) { ogs_assert(num_of_nr_tai < OGS_MAX_NUM_OF_TAI); ogs_plmn_id_build( - &smf_info->nr_tai - [num_of_nr_tai].plmn_id, + &smf_info->nr_tai[ + num_of_nr_tai].plmn_id, atoi(mcc), atoi(mnc), strlen(mnc)); smf_info->nr_tai[num_of_nr_tai]. - tac.v = tac[i].v; + tac.v = start[tac].v; num_of_nr_tai++; + } else if (start[tac].v < + end[tac].v) { + ogs_assert(num_of_nr_tai_range < + OGS_MAX_NUM_OF_TAI); + ogs_assert(num_of_tac_range < + OGS_MAX_NUM_OF_TAI); + smf_info->nr_tai_range[ + num_of_nr_tai_range]. + start[num_of_tac_range].v = + start[tac].v; + smf_info->nr_tai_range[ + num_of_nr_tai_range]. + end[num_of_tac_range].v = + end[tac].v; + num_of_tac_range++; } - } else { - ogs_warn("No TAC info"); } + if (num_of_tac_range) { + ogs_plmn_id_build( + &smf_info->nr_tai_range[ + num_of_nr_tai_range].plmn_id, + atoi(mcc), atoi(mnc), + strlen(mnc)); + smf_info->nr_tai_range[ + num_of_nr_tai_range]. + num_of_tac_range = + num_of_tac_range; + num_of_nr_tai_range++; + } + } else { + ogs_warn("Ignore tai : mcc(%p), " + "mnc(%p), num_of_tac(%d)", + mcc, mnc, num_of_tac); } } while (ogs_yaml_iter_type(&tai_array) == YAML_SEQUENCE_NODE); @@ -898,7 +890,6 @@ int smf_context_parse_config(void) } else ogs_warn("unknown key `%s`", info_key); } - } while (ogs_yaml_iter_type(&info_array) == YAML_SEQUENCE_NODE); diff --git a/tests/common/context.c b/tests/common/context.c index 976573662..7da2be750 100644 --- a/tests/common/context.c +++ b/tests/common/context.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -96,6 +96,7 @@ static int test_context_prepare(void) static int test_context_validation(void) { ogs_socknode_t *snode = NULL; + int index = 0; snode = ogs_list_first(&test_self()->s1ap_list); if (snode) test_self()->s1ap_addr = snode->addr; @@ -107,25 +108,37 @@ static int test_context_validation(void) snode = ogs_list_first(&test_self()->ngap_list6); if (snode) test_self()->ngap_addr6 = snode->addr; - if (test_self()->e_served_tai[0].list2.num) { + if (test_self()->e_served_tai[index].list2.num) { memcpy(&test_self()->e_tai, - &test_self()->e_served_tai[0].list2.tai[0], sizeof(ogs_5gs_tai_t)); - } else if (test_self()->e_served_tai[0].list0.tai[0].num) { + &test_self()->e_served_tai[index].list2.tai[0], sizeof(ogs_5gs_tai_t)); + } else if (test_self()->e_served_tai[index].list1.tai[0].num) { test_self()->e_tai.tac = - test_self()->e_served_tai[0].list0.tai[0].tac[0]; + test_self()->e_served_tai[index].list1.tai[0].tac; memcpy(&test_self()->e_tai.plmn_id, - &test_self()->e_served_tai[0].list0.tai[0].plmn_id, + &test_self()->e_served_tai[index].list1.tai[0].plmn_id, + OGS_PLMN_ID_LEN); + } else if (test_self()->e_served_tai[index].list0.tai[0].num) { + test_self()->e_tai.tac = + test_self()->e_served_tai[index].list0.tai[0].tac[0]; + memcpy(&test_self()->e_tai.plmn_id, + &test_self()->e_served_tai[index].list0.tai[0].plmn_id, OGS_PLMN_ID_LEN); } - if (test_self()->nr_served_tai[0].list2.num) { + if (test_self()->nr_served_tai[index].list2.num) { memcpy(&test_self()->nr_tai, - &test_self()->nr_served_tai[0].list2.tai[0], sizeof(ogs_5gs_tai_t)); - } else if (test_self()->nr_served_tai[0].list0.tai[0].num) { + &test_self()->nr_served_tai[index].list2.tai[0], sizeof(ogs_5gs_tai_t)); + } else if (test_self()->nr_served_tai[index].list1.tai[0].num) { test_self()->nr_tai.tac = - test_self()->nr_served_tai[0].list0.tai[0].tac[0]; + test_self()->nr_served_tai[index].list1.tai[0].tac; memcpy(&test_self()->nr_tai.plmn_id, - &test_self()->nr_served_tai[0].list0.tai[0].plmn_id, + &test_self()->nr_served_tai[index].list1.tai[0].plmn_id, + OGS_PLMN_ID_LEN); + } else if (test_self()->nr_served_tai[index].list0.tai[0].num) { + test_self()->nr_tai.tac = + test_self()->nr_served_tai[index].list0.tai[0].tac[0]; + memcpy(&test_self()->nr_tai.plmn_id, + &test_self()->nr_served_tai[index].list0.tai[0].plmn_id, OGS_PLMN_ID_LEN); } @@ -282,24 +295,27 @@ int test_context_parse_config(void) } } if (!strcmp(amf_key, "tai")) { int num_of_list0 = 0; + int num_of_list1 = 0; ogs_5gs_tai0_list_t *list0 = NULL; + ogs_5gs_tai1_list_t *list1 = NULL; ogs_5gs_tai2_list_t *list2 = NULL; ogs_assert(self.num_of_nr_served_tai <= OGS_MAX_NUM_OF_SERVED_TAI); list0 = &self.nr_served_tai[self.num_of_nr_served_tai].list0; - ogs_assert(list0); + list1 = + &self.nr_served_tai[self.num_of_nr_served_tai].list1; list2 = &self.nr_served_tai[self.num_of_nr_served_tai].list2; - ogs_assert(list2); ogs_yaml_iter_t tai_array, tai_iter; ogs_yaml_iter_recurse(&amf_iter, &tai_array); do { const char *mcc = NULL, *mnc = NULL; - ogs_uint24_t tac[OGS_MAX_NUM_OF_TAI]; int num_of_tac = 0; + ogs_uint24_t start[OGS_MAX_NUM_OF_TAI]; + ogs_uint24_t end[OGS_MAX_NUM_OF_TAI]; if (ogs_yaml_iter_type(&tai_array) == YAML_MAPPING_NODE) { @@ -340,23 +356,56 @@ int test_context_parse_config(void) ogs_yaml_iter_t tac_iter; ogs_yaml_iter_recurse(&tai_iter, &tac_iter); ogs_assert(ogs_yaml_iter_type(&tac_iter) != - YAML_MAPPING_NODE); - + YAML_MAPPING_NODE); do { - const char *v = NULL; + char *v = NULL; + char *low = NULL, *high = NULL; - ogs_assert(num_of_tac <= - OGS_MAX_NUM_OF_TAI); if (ogs_yaml_iter_type(&tac_iter) == YAML_SEQUENCE_NODE) { if (!ogs_yaml_iter_next(&tac_iter)) break; } - v = ogs_yaml_iter_value(&tac_iter); + v = (char *)ogs_yaml_iter_value( + &tac_iter); if (v) { - tac[num_of_tac].v = atoi(v); - num_of_tac++; + low = strsep(&v, "-"); + if (low && strlen(low) == 0) + low = NULL; + + high = v; + if (high && strlen(high) == 0) + high = NULL; + + if (low) { + ogs_assert(num_of_tac < + OGS_MAX_NUM_OF_TAI); + start[num_of_tac].v = atoi(low); + if (high) { + end[num_of_tac].v = atoi(high); + if (end[num_of_tac].v < + start[num_of_tac].v) + ogs_error( + "Invalid TAI range: " + "LOW:%s,HIGH:%s", + low, high); + else if ( + (end[num_of_tac].v- + start[num_of_tac].v+1) > + OGS_MAX_NUM_OF_TAI) + ogs_error( + "Overflow TAI range: " + "LOW:%s,HIGH:%s", + low, high); + else + num_of_tac++; + } else { + end[num_of_tac].v = + start[num_of_tac].v; + num_of_tac++; + } + } } } while ( ogs_yaml_iter_type(&tac_iter) == @@ -366,31 +415,60 @@ int test_context_parse_config(void) } if (mcc && mnc && num_of_tac) { - if (num_of_tac == 1) { + if (num_of_tac == 1 && start[0].v == end[0].v) { + ogs_assert(list2->num < OGS_MAX_NUM_OF_TAI); + + list2->type = OGS_TAI2_TYPE; + ogs_plmn_id_build( &list2->tai[list2->num].plmn_id, atoi(mcc), atoi(mnc), strlen(mnc)); - list2->tai[list2->num].tac.v = tac[0].v; + list2->tai[list2->num].tac.v = start[0].v; list2->num++; - if (list2->num > 1) - list2->type = OGS_TAI2_TYPE; - else - list2->type = OGS_TAI1_TYPE; - } else if (num_of_tac > 1) { - int i; - ogs_plmn_id_build( - &list0->tai[num_of_list0].plmn_id, - atoi(mcc), atoi(mnc), strlen(mnc)); - for (i = 0; i < num_of_tac; i++) { - list0->tai[num_of_list0].tac[i].v = - tac[i].v; + + } else { + int tac, count = 0; + for (tac = 0; tac < num_of_tac; tac++) { + ogs_assert(end[tac].v >= start[tac].v); + if (start[tac].v == end[tac].v) { + ogs_assert(num_of_list0 < + OGS_MAX_NUM_OF_TAI); + + list0->tai[num_of_list0].type = + OGS_TAI0_TYPE; + + ogs_plmn_id_build( + &list0->tai[num_of_list0].plmn_id, + atoi(mcc), atoi(mnc), strlen(mnc)); + list0->tai[num_of_list0]. + tac[count].v = start[tac].v; + + list0->tai[num_of_list0].num = + ++count; + + } else if (start[tac].v < end[tac].v) { + ogs_assert(num_of_list1 < + OGS_MAX_NUM_OF_TAI); + + list1->tai[num_of_list1].type = + OGS_TAI1_TYPE; + + ogs_plmn_id_build( + &list1->tai[num_of_list1].plmn_id, + atoi(mcc), atoi(mnc), strlen(mnc)); + list1->tai[num_of_list1].tac.v = + start[tac].v; + + list1->tai[num_of_list1].num = + end[tac].v-start[tac].v+1; + + num_of_list1++; + } } - list0->tai[num_of_list0].num = num_of_tac; - list0->tai[num_of_list0].type = OGS_TAI0_TYPE; - - num_of_list0++; + if (count) + num_of_list0++; } } else { ogs_warn("Ignore tai : mcc(%p), mnc(%p), " @@ -399,7 +477,7 @@ int test_context_parse_config(void) } while (ogs_yaml_iter_type(&tai_array) == YAML_SEQUENCE_NODE); - if (list2->num || num_of_list0) { + if (list2->num || num_of_list1 || num_of_list0) { self.num_of_nr_served_tai++; } } else if (!strcmp(amf_key, "plmn_support")) { @@ -677,22 +755,24 @@ int test_context_parse_config(void) } } else if (!strcmp(mme_key, "tai")) { int num_of_list0 = 0; + int num_of_list1 = 0; ogs_eps_tai0_list_t *list0 = NULL; + ogs_eps_tai1_list_t *list1 = NULL; ogs_eps_tai2_list_t *list2 = NULL; ogs_assert(self.num_of_e_served_tai <= OGS_MAX_NUM_OF_SERVED_TAI); list0 = &self.e_served_tai[self.num_of_e_served_tai].list0; - ogs_assert(list0); + list1 = &self.e_served_tai[self.num_of_e_served_tai].list1; list2 = &self.e_served_tai[self.num_of_e_served_tai].list2; - ogs_assert(list2); ogs_yaml_iter_t tai_array, tai_iter; ogs_yaml_iter_recurse(&mme_iter, &tai_array); do { const char *mcc = NULL, *mnc = NULL; - uint16_t tac[OGS_MAX_NUM_OF_TAI]; int num_of_tac = 0; + uint16_t start[OGS_MAX_NUM_OF_TAI]; + uint16_t end[OGS_MAX_NUM_OF_TAI]; if (ogs_yaml_iter_type(&tai_array) == YAML_MAPPING_NODE) { @@ -733,23 +813,56 @@ int test_context_parse_config(void) ogs_yaml_iter_t tac_iter; ogs_yaml_iter_recurse(&tai_iter, &tac_iter); ogs_assert(ogs_yaml_iter_type(&tac_iter) != - YAML_MAPPING_NODE); - + YAML_MAPPING_NODE); do { - const char *v = NULL; + char *v = NULL; + char *low = NULL, *high = NULL; - ogs_assert(num_of_tac <= - OGS_MAX_NUM_OF_TAI); if (ogs_yaml_iter_type(&tac_iter) == YAML_SEQUENCE_NODE) { if (!ogs_yaml_iter_next(&tac_iter)) break; } - v = ogs_yaml_iter_value(&tac_iter); + v = (char *)ogs_yaml_iter_value( + &tac_iter); if (v) { - tac[num_of_tac] = atoi(v); - num_of_tac++; + low = strsep(&v, "-"); + if (low && strlen(low) == 0) + low = NULL; + + high = v; + if (high && strlen(high) == 0) + high = NULL; + + if (low) { + ogs_assert(num_of_tac < + OGS_MAX_NUM_OF_TAI); + start[num_of_tac] = atoi(low); + if (high) { + end[num_of_tac] = atoi(high); + if (end[num_of_tac] < + start[num_of_tac]) + ogs_error( + "Invalid TAI range: " + "LOW:%s,HIGH:%s", + low, high); + else if ( + (end[num_of_tac]- + start[num_of_tac]+1) > + OGS_MAX_NUM_OF_TAI) + ogs_error( + "Overflow TAI range: " + "LOW:%s,HIGH:%s", + low, high); + else + num_of_tac++; + } else { + end[num_of_tac] = + start[num_of_tac]; + num_of_tac++; + } + } } } while ( ogs_yaml_iter_type(&tac_iter) == @@ -759,30 +872,60 @@ int test_context_parse_config(void) } if (mcc && mnc && num_of_tac) { - if (num_of_tac == 1) { + if (num_of_tac == 1 && start[0] == end[0]) { + ogs_assert(list2->num < OGS_MAX_NUM_OF_TAI); + + list2->type = OGS_TAI2_TYPE; + ogs_plmn_id_build( &list2->tai[list2->num].plmn_id, atoi(mcc), atoi(mnc), strlen(mnc)); - list2->tai[list2->num].tac = tac[0]; + list2->tai[list2->num].tac = start[0]; list2->num++; - if (list2->num > 1) - list2->type = OGS_TAI2_TYPE; - else - list2->type = OGS_TAI1_TYPE; - } else if (num_of_tac > 1) { - int i; - ogs_plmn_id_build( - &list0->tai[num_of_list0].plmn_id, - atoi(mcc), atoi(mnc), strlen(mnc)); - for (i = 0; i < num_of_tac; i++) { - list0->tai[num_of_list0].tac[i] = tac[i]; + + } else { + int tac, count = 0; + for (tac = 0; tac < num_of_tac; tac++) { + ogs_assert(end[tac] >= start[tac]); + if (start[tac] == end[tac]) { + ogs_assert(num_of_list0 < + OGS_MAX_NUM_OF_TAI); + + list0->tai[num_of_list0].type = + OGS_TAI0_TYPE; + + ogs_plmn_id_build( + &list0->tai[num_of_list0].plmn_id, + atoi(mcc), atoi(mnc), strlen(mnc)); + list0->tai[num_of_list0]. + tac[count] = start[tac]; + + list0->tai[num_of_list0].num = + ++count; + + } else if (start[tac] < end[tac]) { + ogs_assert(num_of_list1 < + OGS_MAX_NUM_OF_TAI); + + list1->tai[num_of_list1].type = + OGS_TAI1_TYPE; + + ogs_plmn_id_build( + &list1->tai[num_of_list1].plmn_id, + atoi(mcc), atoi(mnc), strlen(mnc)); + list1->tai[num_of_list1].tac = + start[tac]; + + list1->tai[num_of_list1].num = + end[tac]-start[tac]+1; + + num_of_list1++; + } } - list0->tai[num_of_list0].num = num_of_tac; - list0->tai[num_of_list0].type = OGS_TAI0_TYPE; - - num_of_list0++; + if (count) + num_of_list0++; } } else { ogs_warn("Ignore tai : mcc(%p), mnc(%p), " @@ -791,7 +934,7 @@ int test_context_parse_config(void) } while (ogs_yaml_iter_type(&tai_array) == YAML_SEQUENCE_NODE); - if (list2->num || num_of_list0) { + if (list2->num || num_of_list1 || num_of_list0) { self.num_of_e_served_tai++; } } diff --git a/tests/common/context.h b/tests/common/context.h index 1f56d2e58..081fbc1b7 100644 --- a/tests/common/context.h +++ b/tests/common/context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -76,6 +76,7 @@ typedef struct test_context_s { uint8_t num_of_e_served_tai; struct { ogs_eps_tai0_list_t list0; + ogs_eps_tai1_list_t list1; ogs_eps_tai2_list_t list2; } e_served_tai[OGS_MAX_NUM_OF_SERVED_TAI]; @@ -85,6 +86,7 @@ typedef struct test_context_s { uint8_t num_of_nr_served_tai; struct { ogs_5gs_tai0_list_t list0; + ogs_5gs_tai1_list_t list1; ogs_5gs_tai2_list_t list2; } nr_served_tai[OGS_MAX_NUM_OF_SERVED_TAI]; diff --git a/tests/unit/nas-message-test.c b/tests/unit/nas-message-test.c index e5fd6ef09..dd8ccdd0c 100644 --- a/tests/unit/nas-message-test.c +++ b/tests/unit/nas-message-test.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2023 by Sukchan Lee * * This file is part of Open5GS. * @@ -90,7 +90,7 @@ static void ogs_nas_eps_message_test2(abts_case *tc, void *data) tai0_list.tai[0].num = 1; ogs_plmn_id_build(&tai0_list.tai[0].plmn_id, 417, 99, 2); tai0_list.tai[0].tac[0] = 12345; - ogs_nas_tai_list_build(&attach_accept->tai_list, &tai0_list, &tai2_list); + ogs_nas_tai_list_build(&attach_accept->tai_list, &tai0_list, NULL, NULL); attach_accept->esm_message_container.length = sizeof(esm_buffer); attach_accept->esm_message_container.buffer =