[AMF/MME] Support TAI Range

This commit is contained in:
Sukchan Lee 2023-03-19 18:25:59 +09:00
parent 2944fa2549
commit 424f382265
17 changed files with 691 additions and 276 deletions

View File

@ -348,34 +348,57 @@ sbi:
# <TAI>
#
# 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]
#
# <PLMN Support>
#

View File

@ -217,35 +217,57 @@ logger:
# <TAI>
#
# 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]
#
# <Network Name>
# mme:

View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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;
/* <Spec> 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;
/* <Spec> 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;
/* <Spec> 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);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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 */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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;
/* <Spec> 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;
/* <Spec> 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;
/* <Spec> 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);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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,

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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];

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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(&registration_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 */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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 */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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,

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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];

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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++;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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];

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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 =