Coverage Report

Created: 2026-10-16 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open5gs/lib/app/ogs-config.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
3
 *
4
 * This file is part of Open5GS.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
#include "ogs-app.h"
21
22
static ogs_app_global_conf_t global_conf;
23
static ogs_app_local_conf_t local_conf;
24
25
static OGS_POOL(policy_conf_pool, ogs_app_policy_conf_t);
26
static OGS_POOL(slice_conf_pool, ogs_app_slice_conf_t);
27
static OGS_POOL(session_conf_pool, ogs_app_session_conf_t);
28
29
static int initialized = 0;
30
31
int ogs_app_config_init(void)
32
0
{
33
0
    ogs_assert(initialized == 0);
34
35
0
    memset(&global_conf, 0, sizeof(ogs_app_global_conf_t));
36
0
    memset(&local_conf, 0, sizeof(ogs_app_local_conf_t));
37
38
0
    ogs_pool_init(&policy_conf_pool, OGS_MAX_NUM_OF_PLMN);
39
0
    ogs_pool_init(&slice_conf_pool, OGS_MAX_NUM_OF_SLICE);
40
0
    ogs_pool_init(&session_conf_pool,
41
0
            OGS_MAX_NUM_OF_SLICE*OGS_MAX_NUM_OF_SESS);
42
43
0
    initialized = 1;
44
45
0
    return OGS_OK;
46
0
}
47
48
void ogs_app_config_final(void)
49
0
{
50
0
    ogs_assert(initialized == 1);
51
52
0
    ogs_app_policy_conf_remove_all();
53
54
0
    ogs_pool_final(&policy_conf_pool);
55
0
    ogs_pool_final(&slice_conf_pool);
56
0
    ogs_pool_final(&session_conf_pool);
57
58
0
    initialized = 0;
59
0
}
60
61
static void recalculate_pool_size(void)
62
0
{
63
0
    ogs_app()->pool.gtpu =
64
0
        global_conf.max.ue * OGS_MAX_NUM_OF_GTPU_BUFFER;
65
66
0
#define MAX_NUM_OF_TUNNEL       3   /* Num of Tunnel per Bearer */
67
0
    ogs_app()->pool.sess = global_conf.max.ue * OGS_MAX_NUM_OF_SESS;
68
0
    ogs_app()->pool.bearer = ogs_app()->pool.sess * OGS_MAX_NUM_OF_BEARER;
69
0
    ogs_app()->pool.tunnel = ogs_app()->pool.bearer * MAX_NUM_OF_TUNNEL;
70
71
0
#define POOL_NUM_PER_UE 16
72
0
    ogs_app()->pool.timer = global_conf.max.ue * POOL_NUM_PER_UE;
73
0
    ogs_app()->pool.event = global_conf.max.ue * POOL_NUM_PER_UE;
74
0
    ogs_app()->pool.socket = global_conf.max.ue * POOL_NUM_PER_UE;
75
0
    ogs_app()->pool.xact = global_conf.max.ue * POOL_NUM_PER_UE;
76
0
    ogs_app()->pool.stream = global_conf.max.ue * POOL_NUM_PER_UE;
77
78
0
    ogs_app()->pool.nf = global_conf.max.peer;
79
80
    /* Size both SBI message pools for incoming requests and transactions. */
81
0
    ogs_app()->pool.message = ogs_app()->pool.event + ogs_app()->pool.xact;
82
83
0
#define NF_SERVICE_PER_NF_INSTANCE 16
84
0
    ogs_app()->pool.nf_service =
85
0
        ogs_app()->pool.nf * NF_SERVICE_PER_NF_INSTANCE;
86
0
    ogs_app()->pool.subscription =
87
0
        ogs_app()->pool.nf * NF_SERVICE_PER_NF_INSTANCE;
88
89
0
    ogs_app()->pool.gtp_node = ogs_app()->pool.nf;
90
0
    if (global_conf.max.gtp_peer)
91
0
        ogs_app()->pool.gtp_node = global_conf.max.gtp_peer;
92
93
    /* Num of TAI-LAI Mapping Table */
94
0
    ogs_app()->pool.csmap = ogs_app()->pool.nf;
95
96
0
#define MAX_NUM_OF_IMPU         8
97
0
    ogs_app()->pool.impi = global_conf.max.ue;
98
0
    ogs_app()->pool.impu = ogs_app()->pool.impi * MAX_NUM_OF_IMPU;
99
100
0
#define MAX_NUM_EMERG           8
101
0
    ogs_app()->pool.emerg = MAX_NUM_EMERG;
102
0
}
103
104
ogs_app_global_conf_t *ogs_global_conf(void)
105
0
{
106
0
    return &global_conf;
107
0
}
108
109
ogs_app_local_conf_t *ogs_local_conf(void)
110
0
{
111
0
    return &local_conf;
112
0
}
113
114
int ogs_app_global_conf_prepare(void)
115
0
{
116
0
    global_conf.sockopt.no_delay = true;
117
118
0
#define MAX_NUM_OF_UE               1024    /* Num of UEs */
119
0
#define MAX_NUM_OF_PEER             64      /* Num of Peer */
120
121
0
    global_conf.max.ue = MAX_NUM_OF_UE;
122
0
    global_conf.max.peer = MAX_NUM_OF_PEER;
123
124
0
    ogs_pkbuf_default_init(&global_conf.pkbuf_config);
125
126
0
    recalculate_pool_size();
127
128
0
    return OGS_OK;
129
0
}
130
131
static int global_conf_validation(void)
132
0
{
133
0
    if (global_conf.parameter.no_ipv4 == 1 &&
134
0
        global_conf.parameter.no_ipv6 == 1) {
135
0
        ogs_error("Both `no_ipv4` and `no_ipv6` set to `true` in `%s`",
136
0
                ogs_app()->file);
137
0
        return OGS_ERROR;
138
0
    }
139
140
0
    return OGS_OK;
141
0
}
142
143
int ogs_app_count_nf_conf_sections(const char *conf_section)
144
0
{
145
0
    if (!strcmp(conf_section, "amf"))
146
0
        global_conf.parameter.amf_count++;
147
0
    else if (!strcmp(conf_section, "smf"))
148
0
        global_conf.parameter.smf_count++;
149
0
    else if (!strcmp(conf_section, "upf"))
150
0
        global_conf.parameter.upf_count++;
151
0
    else if (!strcmp(conf_section, "ausf"))
152
0
        global_conf.parameter.ausf_count++;
153
0
    else if (!strcmp(conf_section, "udm"))
154
0
        global_conf.parameter.udm_count++;
155
0
    else if (!strcmp(conf_section, "pcf"))
156
0
        global_conf.parameter.pcf_count++;
157
0
    else if (!strcmp(conf_section, "nssf"))
158
0
        global_conf.parameter.nssf_count++;
159
0
    else if (!strcmp(conf_section, "bsf"))
160
0
        global_conf.parameter.bsf_count++;
161
0
    else if (!strcmp(conf_section, "udr"))
162
0
        global_conf.parameter.udr_count++;
163
0
    else if (!strcmp(conf_section, "eir"))
164
0
        global_conf.parameter.eir_count++;
165
166
0
    return OGS_OK;
167
0
}
168
169
int ogs_app_parse_global_conf(ogs_yaml_iter_t *parent)
170
0
{
171
0
    int rv;
172
0
    ogs_yaml_iter_t global_iter;
173
174
0
    ogs_assert(parent);
175
176
0
    ogs_yaml_iter_recurse(parent, &global_iter);
177
0
    while (ogs_yaml_iter_next(&global_iter)) {
178
0
        const char *global_key = ogs_yaml_iter_key(&global_iter);
179
0
        ogs_assert(global_key);
180
0
        if (!strcmp(global_key, "parameter")) {
181
0
            ogs_yaml_iter_t parameter_iter;
182
0
            ogs_yaml_iter_recurse(&global_iter, &parameter_iter);
183
0
            while (ogs_yaml_iter_next(&parameter_iter)) {
184
0
                const char *parameter_key = ogs_yaml_iter_key(&parameter_iter);
185
0
                ogs_assert(parameter_key);
186
0
                if (!strcmp(parameter_key, "no_hss")) {
187
0
                    global_conf.parameter.no_hss =
188
0
                        ogs_yaml_iter_bool(&parameter_iter);
189
0
                } else if (!strcmp(parameter_key, "no_mme")) {
190
0
                    global_conf.parameter.no_mme =
191
0
                        ogs_yaml_iter_bool(&parameter_iter);
192
0
                } else if (!strcmp(parameter_key, "no_sgwu")) {
193
0
                    global_conf.parameter.no_sgwu =
194
0
                        ogs_yaml_iter_bool(&parameter_iter);
195
0
                } else if (!strcmp(parameter_key, "no_sgwc")) {
196
0
                    global_conf.parameter.no_sgwc =
197
0
                        ogs_yaml_iter_bool(&parameter_iter);
198
0
                } else if (!strcmp(parameter_key, "no_sgw")) {
199
0
                    global_conf.parameter.no_sgw =
200
0
                        ogs_yaml_iter_bool(&parameter_iter);
201
0
                } else if (!strcmp(parameter_key, "no_pgw")) {
202
0
                    global_conf.parameter.no_pgw =
203
0
                        ogs_yaml_iter_bool(&parameter_iter);
204
0
                } else if (!strcmp(parameter_key, "no_pcrf")) {
205
0
                    global_conf.parameter.no_pcrf =
206
0
                        ogs_yaml_iter_bool(&parameter_iter);
207
0
                } else if (!strcmp(parameter_key, "no_nrf")) {
208
0
                    global_conf.parameter.no_nrf =
209
0
                        ogs_yaml_iter_bool(&parameter_iter);
210
0
                } else if (!strcmp(parameter_key, "no_scp")) {
211
0
                    global_conf.parameter.no_scp =
212
0
                        ogs_yaml_iter_bool(&parameter_iter);
213
0
                } else if (!strcmp(parameter_key, "no_sepp")) {
214
0
                    global_conf.parameter.no_sepp =
215
0
                        ogs_yaml_iter_bool(&parameter_iter);
216
0
                } else if (!strcmp(parameter_key, "no_amf")) {
217
0
                    global_conf.parameter.no_amf =
218
0
                        ogs_yaml_iter_bool(&parameter_iter);
219
0
                } else if (!strcmp(parameter_key, "no_smf")) {
220
0
                    global_conf.parameter.no_smf =
221
0
                        ogs_yaml_iter_bool(&parameter_iter);
222
0
                } else if (!strcmp(parameter_key, "no_upf")) {
223
0
                    global_conf.parameter.no_upf =
224
0
                        ogs_yaml_iter_bool(&parameter_iter);
225
0
                } else if (!strcmp(parameter_key, "no_ausf")) {
226
0
                    global_conf.parameter.no_ausf =
227
0
                        ogs_yaml_iter_bool(&parameter_iter);
228
0
                } else if (!strcmp(parameter_key, "no_udm")) {
229
0
                    global_conf.parameter.no_udm =
230
0
                        ogs_yaml_iter_bool(&parameter_iter);
231
0
                } else if (!strcmp(parameter_key, "no_pcf")) {
232
0
                    global_conf.parameter.no_pcf =
233
0
                        ogs_yaml_iter_bool(&parameter_iter);
234
0
                } else if (!strcmp(parameter_key, "no_nssf")) {
235
0
                    global_conf.parameter.no_nssf =
236
0
                        ogs_yaml_iter_bool(&parameter_iter);
237
0
                } else if (!strcmp(parameter_key, "no_bsf")) {
238
0
                    global_conf.parameter.no_bsf =
239
0
                        ogs_yaml_iter_bool(&parameter_iter);
240
0
                } else if (!strcmp(parameter_key, "no_udr")) {
241
0
                    global_conf.parameter.no_udr =
242
0
                        ogs_yaml_iter_bool(&parameter_iter);
243
0
                } else if (!strcmp(parameter_key, "no_eir")) {
244
0
                    global_conf.parameter.no_eir =
245
0
                        ogs_yaml_iter_bool(&parameter_iter);
246
0
                } else if (!strcmp(parameter_key, "no_ipv4")) {
247
0
                    global_conf.parameter.no_ipv4 =
248
0
                        ogs_yaml_iter_bool(&parameter_iter);
249
0
                } else if (!strcmp(parameter_key, "no_ipv6")) {
250
0
                    global_conf.parameter.no_ipv6 =
251
0
                        ogs_yaml_iter_bool(&parameter_iter);
252
0
                } else if (!strcmp(parameter_key, "prefer_ipv4")) {
253
0
                    global_conf.parameter.prefer_ipv4 =
254
0
                        ogs_yaml_iter_bool(&parameter_iter);
255
0
                } else if (!strcmp(parameter_key, "multicast")) {
256
0
                    global_conf.parameter.multicast =
257
0
                        ogs_yaml_iter_bool(&parameter_iter);
258
0
                } else if (!strcmp(parameter_key, "use_openair")) {
259
0
                    global_conf.parameter.use_openair =
260
0
                        ogs_yaml_iter_bool(&parameter_iter);
261
0
                } else if (!strcmp(parameter_key, "use_upg_vpp")) {
262
0
                    global_conf.parameter.use_upg_vpp =
263
0
                        ogs_yaml_iter_bool(&parameter_iter);
264
0
                } else if (!strcmp(parameter_key, "fake_csfb")) {
265
0
                    global_conf.parameter.fake_csfb =
266
0
                        ogs_yaml_iter_bool(&parameter_iter);
267
0
                } else if (!strcmp(parameter_key, "no_ims")) {
268
0
                    global_conf.parameter.no_ims =
269
0
                        ogs_yaml_iter_bool(&parameter_iter);
270
0
                } else if (!strcmp(parameter_key, "allow_unsecured_redirection")) {
271
0
                    global_conf.parameter.allow_unsecured_redirection =
272
0
                        ogs_yaml_iter_bool(&parameter_iter);
273
0
                } else if (!strcmp(parameter_key,
274
0
                            "no_ipv4v6_local_addr_in_packet_filter")) {
275
0
                    global_conf.parameter.
276
0
                        no_ipv4v6_local_addr_in_packet_filter =
277
0
                        ogs_yaml_iter_bool(&parameter_iter);
278
0
                } else if (!strcmp(parameter_key,
279
0
                            "no_pfcp_rr_select")) {
280
0
                    global_conf.parameter.no_pfcp_rr_select =
281
0
                        ogs_yaml_iter_bool(&parameter_iter);
282
0
                } else if (!strcmp(parameter_key,
283
0
                            "no_time_zone_information")) {
284
0
                    global_conf.parameter.no_time_zone_information =
285
0
                        ogs_yaml_iter_bool(&parameter_iter);
286
0
                } else
287
0
                    ogs_warn("unknown key `%s`", parameter_key);
288
0
            }
289
0
        } else if (!strcmp(global_key, "sockopt")) {
290
0
            ogs_yaml_iter_t sockopt_iter;
291
0
            ogs_yaml_iter_recurse(&global_iter, &sockopt_iter);
292
0
            while (ogs_yaml_iter_next(&sockopt_iter)) {
293
0
                const char *sockopt_key =
294
0
                    ogs_yaml_iter_key(&sockopt_iter);
295
0
                ogs_assert(sockopt_key);
296
0
                if (!strcmp(sockopt_key, "no_delay")) {
297
0
                    global_conf.sockopt.no_delay =
298
0
                        ogs_yaml_iter_bool(&sockopt_iter);
299
0
                } else if (!strcmp(sockopt_key, "linger")) {
300
0
                    const char *v = ogs_yaml_iter_value(&sockopt_iter);
301
0
                    if (v)
302
0
                        global_conf.sockopt.l_linger = atoi(v);
303
0
                    global_conf.sockopt.l_onoff = true;
304
0
                } else
305
0
                    ogs_warn("unknown key `%s`", sockopt_key);
306
0
            }
307
0
        } else if (!strcmp(global_key, "max")) {
308
0
            ogs_yaml_iter_t max_iter;
309
0
            ogs_yaml_iter_recurse(&global_iter, &max_iter);
310
0
            while (ogs_yaml_iter_next(&max_iter)) {
311
0
                const char *max_key = ogs_yaml_iter_key(&max_iter);
312
0
                ogs_assert(max_key);
313
0
                if (!strcmp(max_key, "ue")) {
314
0
                    const char *v = ogs_yaml_iter_value(&max_iter);
315
0
                    if (v) global_conf.max.ue = atoi(v);
316
0
                } else if (!strcmp(max_key, "peer") ||
317
0
                            !strcmp(max_key, "enb")) {
318
0
                    const char *v = ogs_yaml_iter_value(&max_iter);
319
0
                    if (v) global_conf.max.peer = atoi(v);
320
0
                } else if (!strcmp(max_key, "gtp_peer") ||
321
0
                            !strcmp(max_key, "enb")) {
322
0
                    const char *v = ogs_yaml_iter_value(&max_iter);
323
0
                    if (v) global_conf.max.gtp_peer = atoi(v);
324
0
                } else
325
0
                    ogs_warn("unknown key `%s`", max_key);
326
0
            }
327
328
0
            recalculate_pool_size();
329
330
0
        } else if (!strcmp(global_key, "pool")) {
331
0
            ogs_yaml_iter_t pool_iter;
332
0
            ogs_yaml_iter_recurse(&global_iter, &pool_iter);
333
0
            while (ogs_yaml_iter_next(&pool_iter)) {
334
0
                const char *pool_key = ogs_yaml_iter_key(&pool_iter);
335
0
                ogs_assert(pool_key);
336
0
                if (!strcmp(pool_key, "128")) {
337
0
                    const char *v = ogs_yaml_iter_value(&pool_iter);
338
0
                    if (v) global_conf.pkbuf_config.cluster_128_pool = atoi(v);
339
0
                } else if (!strcmp(pool_key, "256")) {
340
0
                    const char *v = ogs_yaml_iter_value(&pool_iter);
341
0
                    if (v) global_conf.pkbuf_config.cluster_256_pool = atoi(v);
342
0
                } else if (!strcmp(pool_key, "512")) {
343
0
                    const char *v = ogs_yaml_iter_value(&pool_iter);
344
0
                    if (v) global_conf.pkbuf_config.cluster_512_pool = atoi(v);
345
0
                } else if (!strcmp(pool_key, "1024")) {
346
0
                    const char *v = ogs_yaml_iter_value(&pool_iter);
347
0
                    if (v) global_conf.pkbuf_config.cluster_1024_pool = atoi(v);
348
0
                } else if (!strcmp(pool_key, "2048")) {
349
0
                    const char *v = ogs_yaml_iter_value(&pool_iter);
350
0
                    if (v) global_conf.pkbuf_config.cluster_2048_pool = atoi(v);
351
0
                } else if (!strcmp(pool_key, "8192")) {
352
0
                    const char *v = ogs_yaml_iter_value(&pool_iter);
353
0
                    if (v) global_conf.pkbuf_config.cluster_8192_pool = atoi(v);
354
0
                } else if (!strcmp(pool_key, "32768")) {
355
0
                    const char *v = ogs_yaml_iter_value(&pool_iter);
356
0
                    if (v) global_conf.pkbuf_config.cluster_32768_pool =
357
0
                        atoi(v);
358
0
                } else if (!strcmp(pool_key, "big")) {
359
0
                    const char *v = ogs_yaml_iter_value(&pool_iter);
360
0
                    if (v) global_conf.pkbuf_config.cluster_big_pool = atoi(v);
361
0
                } else
362
0
                    ogs_warn("unknown key `%s`", pool_key);
363
0
            }
364
0
        }
365
0
    }
366
367
0
    rv = global_conf_validation();
368
0
    if (rv != OGS_OK) return rv;
369
370
0
    return OGS_OK;
371
0
}
372
373
static void regenerate_all_timer_duration(void)
374
0
{
375
0
    ogs_assert(local_conf.time.message.duration);
376
377
0
    local_conf.time.message.sbi.client_wait_duration =
378
0
        local_conf.time.message.duration;
379
0
    local_conf.time.message.sbi.connection_deadline =
380
0
        local_conf.time.message.sbi.client_wait_duration + ogs_time_from_sec(1);
381
0
    local_conf.time.message.sbi.reconnect_interval =
382
0
        ogs_max(ogs_time_from_sec(3),
383
0
            local_conf.time.message.sbi.client_wait_duration +
384
0
            ogs_time_from_sec(1));
385
0
    local_conf.time.message.sbi.reconnect_interval_in_exception =
386
0
                ogs_time_from_sec(2);
387
388
0
#define PFCP_N1_RESPONSE_RETRY_COUNT  3
389
0
    local_conf.time.message.pfcp.n1_response_rcount =
390
0
        PFCP_N1_RESPONSE_RETRY_COUNT;
391
0
    local_conf.time.message.pfcp.t1_response_duration =
392
0
        (local_conf.time.message.duration /
393
0
         (local_conf.time.message.pfcp.n1_response_rcount + 1));
394
0
    ogs_assert(local_conf.time.message.pfcp.t1_response_duration);
395
396
0
#define PFCP_N1_HOLDING_RETRY_COUNT 1
397
0
    local_conf.time.message.pfcp.n1_holding_rcount =
398
0
        PFCP_N1_HOLDING_RETRY_COUNT;
399
0
    local_conf.time.message.pfcp.t1_holding_duration =
400
0
        local_conf.time.message.pfcp.n1_response_rcount *
401
0
        local_conf.time.message.pfcp.t1_response_duration;
402
0
    ogs_assert(local_conf.time.message.pfcp.t1_holding_duration);
403
404
0
    local_conf.time.message.pfcp.association_interval =
405
0
        ogs_max(ogs_time_from_sec(3),
406
0
            local_conf.time.message.sbi.client_wait_duration +
407
0
            ogs_time_from_sec(1));
408
409
0
    local_conf.time.message.pfcp.no_heartbeat_duration =
410
0
        ogs_max(ogs_time_from_sec(10),
411
0
            local_conf.time.message.sbi.client_wait_duration +
412
0
            ogs_time_from_sec(1));
413
414
0
#define GTP_N3_RESPONSE_RETRY_COUNT  3
415
0
    local_conf.time.message.gtp.n3_response_rcount =
416
0
        GTP_N3_RESPONSE_RETRY_COUNT;
417
0
    local_conf.time.message.gtp.t3_response_duration =
418
0
        (local_conf.time.message.duration /
419
0
         (local_conf.time.message.gtp.n3_response_rcount + 1));
420
0
    ogs_assert(local_conf.time.message.gtp.t3_response_duration);
421
422
0
#define GTP_N3_HOLDING_RETRY_COUNT 1
423
0
    local_conf.time.message.gtp.n3_holding_rcount = GTP_N3_HOLDING_RETRY_COUNT;
424
0
    local_conf.time.message.gtp.t3_holding_duration =
425
0
        local_conf.time.message.gtp.n3_response_rcount *
426
0
        local_conf.time.message.gtp.t3_response_duration;
427
0
    ogs_assert(local_conf.time.message.gtp.t3_holding_duration);
428
429
#if 0
430
    ogs_trace("%lld, %lld, %lld, %d, %lld, %d %lld, %d, %lld, %d, %lld",
431
        (long long)local_conf.time.message.duration,
432
        (long long)local_conf.time.message.sbi.client_wait_duration,
433
        (long long)local_conf.time.message.sbi.connection_deadline,
434
        local_conf.time.message.pfcp.n1_response_rcount,
435
        (long long)local_conf.time.message.pfcp.t1_response_duration,
436
        local_conf.time.message.pfcp.n1_holding_rcount,
437
        (long long)local_conf.time.message.pfcp.t1_holding_duration,
438
        local_conf.time.message.gtp.n3_response_rcount,
439
        (long long)local_conf.time.message.gtp.t3_response_duration,
440
        local_conf.time.message.gtp.n3_holding_rcount,
441
        (long long)local_conf.time.message.gtp.t3_holding_duration);
442
    ogs_trace("%lld, %lld, %lld",
443
        (long long)local_conf.time.message.sbi.reconnect_interval,
444
        (long long)local_conf.time.message.pfcp.association_interval,
445
        (long long)local_conf.time.message.pfcp.no_heartbeat_duration);
446
#endif
447
0
}
448
449
static int local_conf_prepare(void)
450
0
{
451
    /* <Heartbeat Checking Interval>
452
     *  Heartbeat Interval(e.g: 10 seconds) + No Heartbeat Margin(1 second) */
453
0
    local_conf.time.nf_instance.no_heartbeat_margin = 1;
454
455
    /* 30 seconds */
456
0
    local_conf.time.nf_instance.validity_duration = 30;
457
458
    /* 86400 seconds = 1 day */
459
0
    local_conf.time.subscription.validity_duration = 86400;
460
461
    /*
462
     * Message Wait Duration : 10 seconds (Default)
463
     *
464
     * The paging retry timer is 2 seconds and the retry count is 3.
465
     *
466
     * It is recomended to set at least 9 seconds to reflect
467
     * the paging failure result to GTPv2-C or HTTP2(SBI).
468
     */
469
0
    local_conf.time.message.duration = ogs_time_from_sec(10);
470
471
    /*
472
     * Handover Wait Duration : 300 ms (Default)
473
     *
474
     * Time to wait for AMF/MME to send UEContextReleaseCommand
475
     * to the source gNB/eNB after receiving HandoverNotify
476
     */
477
0
    local_conf.time.handover.duration = ogs_time_from_msec(300);
478
479
    /* Size of internal metrics pool (amount of ogs_metrics_spec_t) */
480
0
    ogs_app()->metrics.max_specs = 512;
481
482
0
    regenerate_all_timer_duration();
483
484
0
    return OGS_OK;
485
0
}
486
487
static int local_conf_validation(void)
488
0
{
489
0
    if (local_conf.time.nf_instance.validity_duration == 0) {
490
0
        ogs_error("NF Instance validity-time should not 0");
491
0
        ogs_error("time:");
492
0
        ogs_error("  nf_instance:");
493
0
        ogs_error("    validity: 0");
494
495
0
        return OGS_ERROR;
496
0
    }
497
498
0
    return OGS_OK;
499
0
}
500
501
int ogs_app_parse_local_conf(const char *local)
502
0
{
503
0
    int rv;
504
0
    yaml_document_t *document = NULL;
505
0
    ogs_yaml_iter_t root_iter;
506
0
    int idx = 0;
507
508
0
    document = ogs_app()->document;
509
0
    ogs_assert(document);
510
511
0
    rv = local_conf_prepare();
512
0
    if (rv != OGS_OK) return rv;
513
514
0
    ogs_yaml_iter_init(&root_iter, document);
515
0
    while (ogs_yaml_iter_next(&root_iter)) {
516
0
        const char *root_key = ogs_yaml_iter_key(&root_iter);
517
0
        ogs_assert(root_key);
518
0
        if (!strcmp(root_key, local) &&
519
0
            (idx++ == ogs_app()->config_section_id)) {
520
0
            ogs_yaml_iter_t local_iter;
521
0
            ogs_yaml_iter_recurse(&root_iter, &local_iter);
522
0
            while (ogs_yaml_iter_next(&local_iter)) {
523
0
                const char *local_key = ogs_yaml_iter_key(&local_iter);
524
0
                ogs_assert(local_key);
525
0
                if (!strcmp(local_key, "serving")) {
526
0
                    ogs_yaml_iter_t serving_array, serving_iter;
527
0
                    ogs_yaml_iter_recurse(&local_iter, &serving_array);
528
0
                    do {
529
0
                        const char *mnc = NULL, *mcc = NULL;
530
0
                        ogs_assert(local_conf.num_of_serving_plmn_id <
531
0
                                OGS_MAX_NUM_OF_PLMN);
532
533
0
                        OGS_YAML_ARRAY_NEXT(&serving_array, &serving_iter);
534
0
                        while (ogs_yaml_iter_next(&serving_iter)) {
535
0
                            const char *serving_key =
536
0
                                ogs_yaml_iter_key(&serving_iter);
537
0
                            ogs_assert(serving_key);
538
0
                            if (!strcmp(serving_key, "plmn_id")) {
539
0
                                ogs_yaml_iter_t plmn_id_iter;
540
541
0
                                ogs_yaml_iter_recurse(&serving_iter,
542
0
                                        &plmn_id_iter);
543
0
                                while (ogs_yaml_iter_next(&plmn_id_iter)) {
544
0
                                    const char *id_key =
545
0
                                        ogs_yaml_iter_key(&plmn_id_iter);
546
0
                                    ogs_assert(id_key);
547
0
                                    if (!strcmp(id_key, "mcc")) {
548
0
                                        mcc = ogs_yaml_iter_value(
549
0
                                                &plmn_id_iter);
550
0
                                    } else if (!strcmp(id_key, "mnc")) {
551
0
                                        mnc = ogs_yaml_iter_value(
552
0
                                                &plmn_id_iter);
553
0
                                    }
554
0
                                }
555
556
0
                                if (mcc && mnc) {
557
0
                                    ogs_plmn_id_build(
558
0
                                            &local_conf.serving_plmn_id[
559
0
                                                local_conf.
560
0
                                                num_of_serving_plmn_id],
561
0
                                            atoi(mcc), atoi(mnc), strlen(mnc));
562
0
                                    local_conf.num_of_serving_plmn_id++;
563
0
                                } else {
564
0
                                    ogs_error("Invalid [MCC:%s, MNC:%s]",
565
0
                                            mcc, mnc);
566
0
                                }
567
0
                            } else
568
0
                                ogs_warn("unknown key `%s`", serving_key);
569
0
                        }
570
0
                    } while (ogs_yaml_iter_type(&serving_array) ==
571
0
                            YAML_SEQUENCE_NODE);
572
0
                } else if (!strcmp(local_key, "time")) {
573
0
                    ogs_yaml_iter_t time_iter;
574
0
                    ogs_yaml_iter_recurse(&local_iter, &time_iter);
575
0
                    while (ogs_yaml_iter_next(&time_iter)) {
576
0
                        const char *time_key = ogs_yaml_iter_key(&time_iter);
577
0
                        ogs_assert(time_key);
578
0
                        if (!strcmp(time_key, "nf_instance")) {
579
0
                            ogs_yaml_iter_t sbi_iter;
580
0
                            ogs_yaml_iter_recurse(&time_iter, &sbi_iter);
581
582
0
                            while (ogs_yaml_iter_next(&sbi_iter)) {
583
0
                                const char *sbi_key =
584
0
                                    ogs_yaml_iter_key(&sbi_iter);
585
0
                                ogs_assert(sbi_key);
586
587
0
                                if (!strcmp(sbi_key, "heartbeat")) {
588
0
                                    const char *v = ogs_yaml_iter_value(
589
0
                                            &sbi_iter);
590
0
                                    if (v)
591
0
                                        local_conf.time.nf_instance.
592
0
                                            heartbeat_interval = atoi(v);
593
0
                                } else if (!strcmp(sbi_key, "validity")) {
594
0
                                    const char *v =
595
0
                                        ogs_yaml_iter_value(&sbi_iter);
596
0
                                    if (v)
597
0
                                        local_conf.time.nf_instance.
598
0
                                            validity_duration = atoi(v);
599
0
                                } else
600
0
                                    ogs_warn("unknown key `%s`", sbi_key);
601
0
                            }
602
0
                        } else if (!strcmp(time_key, "subscription")) {
603
0
                            ogs_yaml_iter_t sbi_iter;
604
0
                            ogs_yaml_iter_recurse(&time_iter, &sbi_iter);
605
606
0
                            while (ogs_yaml_iter_next(&sbi_iter)) {
607
0
                                const char *sbi_key =
608
0
                                    ogs_yaml_iter_key(&sbi_iter);
609
0
                                ogs_assert(sbi_key);
610
611
0
                                if (!strcmp(sbi_key, "validity")) {
612
0
                                    const char *v =
613
0
                                        ogs_yaml_iter_value(&sbi_iter);
614
0
                                    if (v)
615
0
                                        local_conf.time.subscription.
616
0
                                            validity_duration = atoi(v);
617
0
                                } else
618
0
                                    ogs_warn("unknown key `%s`", sbi_key);
619
0
                            }
620
0
                        } else if (!strcmp(time_key, "message")) {
621
0
                            ogs_yaml_iter_t msg_iter;
622
0
                            ogs_yaml_iter_recurse(&time_iter, &msg_iter);
623
624
0
                            while (ogs_yaml_iter_next(&msg_iter)) {
625
0
                                const char *msg_key =
626
0
                                    ogs_yaml_iter_key(&msg_iter);
627
0
                                ogs_assert(msg_key);
628
629
0
                                if (!strcmp(msg_key, "duration")) {
630
0
                                    const char *v =
631
0
                                        ogs_yaml_iter_value(&msg_iter);
632
0
                                    if (v) {
633
0
                                        local_conf.time.message.duration =
634
0
                                            ogs_time_from_msec(atoll(v));
635
0
                                        regenerate_all_timer_duration();
636
0
                                    }
637
0
                                } else
638
0
                                    ogs_warn("unknown key `%s`", msg_key);
639
0
                            }
640
0
                        } else if (!strcmp(time_key, "handover")) {
641
0
                            ogs_yaml_iter_t msg_iter;
642
0
                            ogs_yaml_iter_recurse(&time_iter, &msg_iter);
643
644
0
                            while (ogs_yaml_iter_next(&msg_iter)) {
645
0
                                const char *msg_key =
646
0
                                    ogs_yaml_iter_key(&msg_iter);
647
0
                                ogs_assert(msg_key);
648
649
0
                                if (!strcmp(msg_key, "duration")) {
650
0
                                    const char *v =
651
0
                                        ogs_yaml_iter_value(&msg_iter);
652
0
                                    if (v) {
653
0
                                        local_conf.time.handover.duration =
654
0
                                            ogs_time_from_msec(atoll(v));
655
0
                                    }
656
0
                                } else
657
0
                                    ogs_warn("unknown key `%s`", msg_key);
658
0
                            }
659
0
                        } else if (!strcmp(time_key, "t3502")) {
660
                            /* handle config in amf */
661
0
                        } else if (!strcmp(time_key, "t3512")) {
662
                            /* handle config in amf */
663
0
                        } else if (!strcmp(time_key, "t3513")) {
664
                            /* handle config in amf */
665
0
                        } else if (!strcmp(time_key, "t3522")) {
666
                            /* handle config in amf */
667
0
                        } else if (!strcmp(time_key, "t3550")) {
668
                            /* handle config in amf */
669
0
                        } else if (!strcmp(time_key, "t3555")) {
670
                            /* handle config in amf */
671
0
                        } else if (!strcmp(time_key, "t3560")) {
672
                            /* handle config in amf */
673
0
                        } else if (!strcmp(time_key, "t3570")) {
674
                            /* handle config in amf */
675
0
                        } else if (!strcmp(time_key, "t3402")) {
676
                            /* handle config in mme */
677
0
                        } else if (!strcmp(time_key, "t3396")) {
678
                            /* handle config in mme */
679
0
                        } else if (!strcmp(time_key, "t3412")) {
680
                            /* handle config in mme */
681
0
                        } else if (!strcmp(time_key, "t3423")) {
682
                            /* handle config in mme */
683
0
                        } else
684
0
                            ogs_warn("unknown key `%s`", time_key);
685
0
                    }
686
0
                }
687
0
            }
688
0
        }
689
0
    }
690
691
0
    rv = local_conf_validation();
692
0
    if (rv != OGS_OK) return rv;
693
694
0
    return OGS_OK;
695
0
}
696
697
int ogs_app_parse_eir_action(
698
        ogs_yaml_iter_t *iter, const char *key, ogs_eir_action_e *action)
699
0
{
700
0
    const char *value;
701
702
0
    ogs_assert(iter);
703
0
    ogs_assert(key);
704
0
    ogs_assert(action);
705
706
0
    value = ogs_yaml_iter_value(iter);
707
708
0
    if (!value || !strcmp(value, "allow"))
709
0
        *action = OGS_EIR_ACTION_ALLOW;
710
0
    else if (!strcmp(value, "reject"))
711
0
        *action = OGS_EIR_ACTION_REJECT;
712
0
    else {
713
0
        ogs_error("invalid %s `%s` (expected `allow` or `reject`)", key, value);
714
0
        return OGS_ERROR;
715
0
    }
716
717
0
    return OGS_OK;
718
0
}
719
720
int ogs_app_parse_timer_seconds(
721
        const char *local, ogs_yaml_iter_t *parent, ogs_time_t *seconds)
722
0
{
723
0
    ogs_yaml_iter_t iter;
724
0
    const char *name;
725
0
    ogs_time_t parsed_seconds = 0;
726
0
    bool have_value = false;
727
728
0
    ogs_assert(local);
729
0
    ogs_assert(parent);
730
0
    ogs_assert(seconds);
731
732
0
    name = ogs_yaml_iter_key(parent);
733
0
    ogs_assert(name);
734
735
    /* Reject duplicate timer keys in the same time mapping. */
736
0
    memcpy(&iter, parent, sizeof(ogs_yaml_iter_t));
737
0
    while (ogs_yaml_iter_next(&iter)) {
738
0
        const char *key = ogs_yaml_iter_key(&iter);
739
0
        ogs_assert(key);
740
741
0
        if (!strcmp(key, name)) {
742
0
            ogs_error("Duplicate %s.time.%s in '%s'",
743
0
                    local, name, ogs_app()->file);
744
0
            return OGS_ERROR;
745
0
        }
746
0
    }
747
748
0
    ogs_yaml_iter_recurse(parent, &iter);
749
0
    if (ogs_yaml_iter_type(&iter) != YAML_MAPPING_NODE) {
750
0
        ogs_error("Invalid %s.time.%s in '%s': "
751
0
                "expected a mapping with value", local, name, ogs_app()->file);
752
0
        return OGS_ERROR;
753
0
    }
754
755
0
    while (ogs_yaml_iter_next(&iter)) {
756
0
        const char *key = ogs_yaml_iter_key(&iter);
757
0
        ogs_assert(key);
758
759
0
        if (!strcmp(key, "value")) {
760
0
            const char *v;
761
0
            char *endptr = NULL;
762
0
            long long parsed;
763
764
0
            if (have_value) {
765
0
                ogs_error("Duplicate %s.time.%s.value in '%s'",
766
0
                        local, name, ogs_app()->file);
767
0
                return OGS_ERROR;
768
0
            }
769
0
            if (!ogs_yaml_iter_has_value(&iter)) {
770
0
                ogs_error("Invalid %s.time.%s.value in '%s': expected a scalar",
771
0
                        local, name, ogs_app()->file);
772
0
                return OGS_ERROR;
773
0
            }
774
0
            v = ogs_yaml_iter_value(&iter);
775
0
            if (!v || *v == '\0') {
776
0
                ogs_error("No %s.time.%s.value in '%s'",
777
0
                        local, name, ogs_app()->file);
778
0
                return OGS_ERROR;
779
0
            }
780
781
0
            errno = 0;
782
0
            parsed = strtoll(v, &endptr, 10);
783
0
            if (errno == ERANGE) {
784
0
                ogs_error("Invalid %s.time.%s.value `%s` in '%s': "
785
0
                        "integer is out of range",
786
0
                        local, name, v, ogs_app()->file);
787
0
                return OGS_ERROR;
788
0
            }
789
0
            if (errno != 0 || endptr == v || *endptr != '\0' || parsed < 0) {
790
0
                ogs_error("Invalid %s.time.%s.value `%s` in '%s': "
791
0
                        "expected a non-negative integer in seconds",
792
0
                        local, name, v, ogs_app()->file);
793
0
                return OGS_ERROR;
794
0
            }
795
0
            parsed_seconds = parsed;
796
0
            have_value = true;
797
0
        } else {
798
0
            ogs_warn("Unknown %s.time.%s key `%s` in '%s'",
799
0
                    local, name, key, ogs_app()->file);
800
0
        }
801
0
    }
802
803
0
    if (!have_value) {
804
0
        ogs_error("No %s.time.%s.value in '%s'",
805
0
                local, name, ogs_app()->file);
806
0
        return OGS_ERROR;
807
0
    }
808
809
0
    *seconds = parsed_seconds;
810
0
    return OGS_OK;
811
0
}
812
813
int ogs_app_parse_timer_duration(
814
        const char *local, ogs_yaml_iter_t *parent, ogs_time_t *duration)
815
0
{
816
0
    int rv;
817
0
    ogs_time_t seconds;
818
819
    /* poll/epoll use signed 32-bit millisecond timeouts. */
820
0
    const ogs_time_t max_duration = ogs_time_from_msec(INT32_MAX);
821
822
0
    ogs_assert(duration);
823
824
0
    rv = ogs_app_parse_timer_seconds(local, parent, &seconds);
825
0
    if (rv != OGS_OK)
826
0
        return rv;
827
828
0
    if (seconds <= 0 || seconds > ogs_time_sec(max_duration)) {
829
0
        ogs_error("Invalid %s.time.%s.value `%lld` in '%s': "
830
0
                "expected an integer from 1 to %lld seconds",
831
0
                local, ogs_yaml_iter_key(parent), (long long)seconds,
832
0
                ogs_app()->file, (long long)ogs_time_sec(max_duration));
833
0
        return OGS_ERROR;
834
0
    }
835
836
0
    *duration = ogs_time_from_sec(seconds);
837
0
    return OGS_OK;
838
0
}
839
840
int ogs_app_parse_sockopt_config(
841
        ogs_yaml_iter_t *parent, ogs_sockopt_t *option)
842
0
{
843
0
    ogs_yaml_iter_t sockopt_iter;
844
845
0
    ogs_assert(parent);
846
0
    ogs_assert(option);
847
848
0
    ogs_sockopt_init(option);
849
850
0
    ogs_yaml_iter_recurse(parent, &sockopt_iter);
851
0
    while (ogs_yaml_iter_next(&sockopt_iter)) {
852
0
        const char *sockopt_key = ogs_yaml_iter_key(&sockopt_iter);
853
0
        ogs_assert(sockopt_key);
854
855
0
        if (!strcmp(sockopt_key, "sctp")) {
856
0
            ogs_yaml_iter_t sctp_iter;
857
0
            ogs_yaml_iter_recurse(&sockopt_iter, &sctp_iter);
858
859
0
            while (ogs_yaml_iter_next(&sctp_iter)) {
860
0
                const char *sctp_key = ogs_yaml_iter_key(&sctp_iter);
861
0
                ogs_assert(sctp_key);
862
0
                if (!strcmp(sctp_key, "spp_hbinterval")) {
863
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
864
0
                    if (v) option->sctp.spp_hbinterval = atoi(v);
865
0
                } else if (!strcmp(sctp_key, "spp_sackdelay")) {
866
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
867
0
                    if (v) option->sctp.spp_sackdelay = atoi(v);
868
0
                } else if (!strcmp(sctp_key, "srto_initial")) {
869
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
870
0
                    if (v) option->sctp.srto_initial = atoi(v);
871
0
                } else if (!strcmp(sctp_key, "srto_min")) {
872
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
873
0
                    if (v) option->sctp.srto_min = atoi(v);
874
0
                } else if (!strcmp(sctp_key, "srto_max")) {
875
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
876
0
                    if (v) option->sctp.srto_max = atoi(v);
877
0
                } else if (!strcmp(sctp_key, "sinit_num_ostreams")) {
878
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
879
0
                    if (v) option->sctp.sinit_num_ostreams = atoi(v);
880
0
                } else if (!strcmp(sctp_key, "sinit_max_instreams")) {
881
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
882
0
                    if (v) option->sctp.sinit_max_instreams = atoi(v);
883
0
                } else if (!strcmp(sctp_key, "sinit_max_attempts")) {
884
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
885
0
                    if (v) option->sctp.sinit_max_attempts = atoi(v);
886
0
                } else if (!strcmp(sctp_key, "sinit_max_init_timeo")) {
887
0
                    const char *v = ogs_yaml_iter_value(&sctp_iter);
888
0
                    if (v) option->sctp.sinit_max_init_timeo = atoi(v);
889
0
                } else {
890
0
                    ogs_error("unknown key `%s`", sctp_key);
891
0
                    return OGS_ERROR;
892
0
                }
893
0
            }
894
0
        } else if (!strcmp(sockopt_key, "sctp_nodelay")) {
895
0
            option->sctp_nodelay = ogs_yaml_iter_bool(&sockopt_iter);
896
0
        } else if (!strcmp(sockopt_key, "tcp_nodelay")) {
897
0
            option->tcp_nodelay = ogs_yaml_iter_bool(&sockopt_iter);
898
899
0
        } else if (!strcmp(sockopt_key, "so_linger")) {
900
0
            ogs_yaml_iter_t so_linger_iter;
901
0
            ogs_yaml_iter_recurse(&sockopt_iter, &so_linger_iter);
902
903
0
            while (ogs_yaml_iter_next(&so_linger_iter)) {
904
0
                const char *so_linger_key = ogs_yaml_iter_key(&so_linger_iter);
905
0
                ogs_assert(so_linger_key);
906
0
                if (!strcmp(so_linger_key, "l_onoff")) {
907
0
                    option->so_linger.l_onoff =
908
0
                        ogs_yaml_iter_bool(&so_linger_iter);
909
0
                } else if (!strcmp(so_linger_key, "l_linger")) {
910
0
                    const char *v = ogs_yaml_iter_value(&so_linger_iter);
911
0
                    if (v) option->so_linger.l_linger = atoi(v);
912
0
                } else {
913
0
                    ogs_error("unknown key `%s`", so_linger_key);
914
0
                    return OGS_ERROR;
915
0
                }
916
0
            }
917
918
0
        } else if (!strcmp(sockopt_key, "so_bindtodevice")) {
919
0
            option->so_bindtodevice = ogs_yaml_iter_value(&sockopt_iter);
920
921
0
        } else {
922
0
            ogs_error("unknown key `%s`", sockopt_key);
923
0
            return OGS_ERROR;
924
0
        }
925
0
    }
926
927
0
    return OGS_OK;
928
0
}
929
930
/*----------------------------------------------------------------------
931
 * Function: ogs_app_parse_supi_range_conf
932
 *
933
 *   Parse the supi_range configuration from a YAML iterator.
934
 *
935
 *   The expected YAML format is:
936
 *
937
 *     supi_range:
938
 *       - 999700000000001-999700000099999
939
 *       - 310789000000005-310789000000888
940
 *
941
 *   Both start and end must be provided.
942
 *
943
 * Returns:
944
 *   OGS_OK on success, OGS_ERROR on failure.
945
 *----------------------------------------------------------------------*/
946
int ogs_app_parse_supi_range_conf(
947
        ogs_yaml_iter_t *parent, ogs_supi_range_t *supi_range)
948
0
{
949
0
    ogs_yaml_iter_t range_iter;
950
951
0
    ogs_assert(parent);
952
0
    ogs_assert(supi_range);
953
954
0
    memset(supi_range, 0, sizeof(ogs_supi_range_t));
955
956
    /* Recurse into the supi_range array node */
957
0
    ogs_yaml_iter_recurse(parent, &range_iter);
958
0
    ogs_assert(ogs_yaml_iter_type(&range_iter) != YAML_MAPPING_NODE);
959
960
0
    do {
961
0
        char *v = NULL;
962
0
        char *start_str = NULL, *end_str = NULL;
963
964
0
        if (ogs_yaml_iter_type(&range_iter) == YAML_SEQUENCE_NODE) {
965
0
            if (!ogs_yaml_iter_next(&range_iter))
966
0
                break;
967
0
        }
968
969
0
        v = (char *)ogs_yaml_iter_value(&range_iter);
970
971
0
        if (v) {
972
0
            ogs_assert(supi_range->num < OGS_MAX_NUM_OF_SUPI_RANGE);
973
974
            /* Split the string on '-' */
975
0
            start_str = strsep(&v, "-");
976
0
            if (start_str == NULL || strlen(start_str) == 0) {
977
0
                ogs_error("Invalid supi_range starter bound: %s", v);
978
0
                return OGS_ERROR;
979
0
            }
980
981
0
            end_str = v;
982
0
            if (end_str == NULL || strlen(end_str) == 0) {
983
0
                ogs_error("Invalid supi_range upper bound: %s", v);
984
0
                return OGS_ERROR;
985
0
            }
986
987
0
            supi_range->start[supi_range->num] =
988
0
                ogs_uint64_from_string_decimal(start_str);
989
0
            supi_range->end[supi_range->num] =
990
0
                ogs_uint64_from_string_decimal(end_str);
991
992
0
            supi_range->num++;
993
0
        }
994
995
0
    } while (ogs_yaml_iter_type(&range_iter) == YAML_SEQUENCE_NODE);
996
997
0
    return OGS_OK;
998
0
}
999
1000
static int parse_br_conf(ogs_yaml_iter_t *parent, ogs_bitrate_t *br)
1001
0
{
1002
0
    ogs_yaml_iter_t br_iter;
1003
1004
0
    ogs_assert(parent);
1005
0
    ogs_assert(br);
1006
1007
0
    ogs_yaml_iter_recurse(parent, &br_iter);
1008
1009
0
    while (ogs_yaml_iter_next(&br_iter)) {
1010
0
        const char *br_key = ogs_yaml_iter_key(&br_iter);
1011
0
        ogs_assert(br_key);
1012
0
        if (!strcmp(br_key, OGS_DOWNLINK_STRING)) {
1013
0
            uint8_t unit = 0;
1014
0
            int n;
1015
1016
0
            ogs_yaml_iter_t downlink_iter;
1017
0
            ogs_yaml_iter_recurse(&br_iter, &downlink_iter);
1018
1019
0
            while (ogs_yaml_iter_next(&downlink_iter)) {
1020
0
                const char *downlink_key =
1021
0
                    ogs_yaml_iter_key(&downlink_iter);
1022
0
                ogs_assert(downlink_key);
1023
0
                if (!strcmp(downlink_key, OGS_VALUE_STRING)) {
1024
0
                    const char *v = ogs_yaml_iter_value(&downlink_iter);
1025
0
                    if (v) br->downlink = atoi(v);
1026
0
                } else if (!strcmp(downlink_key, OGS_UNIT_STRING)) {
1027
0
                    const char *v = ogs_yaml_iter_value(&downlink_iter);
1028
0
                    if (v) {
1029
0
                        unit = atoi(v);
1030
0
                        if (unit == 0 || unit == 1 || unit == 2 ||
1031
0
                            unit == 3 || unit == 4) {
1032
0
                        } else {
1033
0
                            ogs_error("Unknown Unit [%d]", unit);
1034
0
                            return OGS_ERROR;
1035
0
                        }
1036
0
                    }
1037
0
                } else
1038
0
                    ogs_warn("unknown key `%s`", downlink_key);
1039
0
            }
1040
1041
0
            for (n = 0; n < unit; n++)
1042
0
                br->downlink *= 1000;
1043
0
        } else if (!strcmp(br_key, OGS_UPLINK_STRING)) {
1044
0
            uint8_t unit = 0;
1045
0
            int n;
1046
1047
0
            ogs_yaml_iter_t uplink_iter;
1048
0
            ogs_yaml_iter_recurse(&br_iter, &uplink_iter);
1049
1050
0
            while (ogs_yaml_iter_next(&uplink_iter)) {
1051
0
                const char *uplink_key =
1052
0
                    ogs_yaml_iter_key(&uplink_iter);
1053
0
                ogs_assert(uplink_key);
1054
0
                if (!strcmp(uplink_key, OGS_VALUE_STRING)) {
1055
0
                    const char *v = ogs_yaml_iter_value(&uplink_iter);
1056
0
                    if (v) br->uplink = atoi(v);
1057
0
                } else if (!strcmp(uplink_key, OGS_UNIT_STRING)) {
1058
0
                    const char *v = ogs_yaml_iter_value(&uplink_iter);
1059
0
                    if (v) {
1060
0
                        unit = atoi(v);
1061
0
                        if (unit == 0 || unit == 1 || unit == 2 ||
1062
0
                            unit == 3 || unit == 4) {
1063
0
                        } else {
1064
0
                            ogs_error("Unknown Unit [%d]", unit);
1065
0
                            return OGS_ERROR;
1066
0
                        }
1067
0
                    }
1068
0
                } else
1069
0
                    ogs_warn("unknown key `%s`", uplink_key);
1070
0
            }
1071
1072
0
            for (n = 0; n < unit; n++)
1073
0
                br->uplink *= 1000;
1074
0
        } else
1075
0
            ogs_warn("unknown key `%s`", br_key);
1076
0
    }
1077
1078
0
    return OGS_OK;
1079
0
}
1080
1081
static int parse_qos_conf(ogs_yaml_iter_t *parent, ogs_qos_t *qos)
1082
0
{
1083
0
    int rv;
1084
0
    ogs_yaml_iter_t qos_iter;
1085
1086
0
    ogs_assert(parent);
1087
0
    ogs_assert(qos);
1088
1089
0
    ogs_yaml_iter_recurse(parent, &qos_iter);
1090
0
    while (ogs_yaml_iter_next(&qos_iter)) {
1091
0
        const char *qos_key = ogs_yaml_iter_key(&qos_iter);
1092
0
        ogs_assert(qos_key);
1093
0
        if (!strcmp(qos_key, OGS_INDEX_STRING)) {
1094
0
            const char *v = ogs_yaml_iter_value(&qos_iter);
1095
0
            if (v) {
1096
0
                uint8_t index = atoi(v);
1097
0
                if (index == 1 || index == 2 || index == 3 || index == 4 ||
1098
0
                    index == 65 || index == 66 || index == 67 || index == 75 ||
1099
0
                    index == 71 || index == 72 || index == 73 || index == 74 ||
1100
0
                    index == 76 || index == 5 || index == 6 || index == 7 ||
1101
0
                    index == 8 || index == 9 || index == 69 || index == 70 ||
1102
0
                    index == 79 || index == 80 || index == 82 || index == 83 ||
1103
0
                    index == 84 || index == 85 || index == 86)
1104
0
                    qos->index = index;
1105
0
                else {
1106
0
                    ogs_error("Unknown QCI [%d]", index);
1107
0
                    return OGS_ERROR;
1108
0
                }
1109
0
            }
1110
0
        } else if (!strcmp(qos_key, OGS_ARP_STRING)) {
1111
0
            ogs_yaml_iter_t arp_iter;
1112
0
            ogs_yaml_iter_recurse(&qos_iter, &arp_iter);
1113
0
            while (ogs_yaml_iter_next(&arp_iter)) {
1114
0
                const char *arp_key = ogs_yaml_iter_key(&arp_iter);
1115
0
                ogs_assert(arp_key);
1116
0
                if (!strcmp(arp_key, OGS_PRIORITY_LEVEL_STRING)) {
1117
0
                    const char *v = ogs_yaml_iter_value(&arp_iter);
1118
0
                    if (v) {
1119
0
                        uint8_t priority_level = atoi(v);
1120
0
                        if (priority_level >= 1 && priority_level <= 15)
1121
0
                            qos->arp.priority_level = priority_level;
1122
0
                        else {
1123
0
                            ogs_error("Unknown Priority Level [%d]",
1124
0
                                    priority_level);
1125
0
                            return OGS_ERROR;
1126
0
                        }
1127
0
                    }
1128
0
                } else if (!strcmp(arp_key,
1129
0
                            OGS_PRE_EMPTION_CAPABILITY_STRING)) {
1130
0
                    const char *v = ogs_yaml_iter_value(&arp_iter);
1131
0
                    if (v) {
1132
0
                        uint8_t pre_emption_capability = atoi(v);
1133
0
                        if (pre_emption_capability ==
1134
0
                                OGS_5GC_PRE_EMPTION_DISABLED ||
1135
0
                            pre_emption_capability ==
1136
0
                            OGS_5GC_PRE_EMPTION_ENABLED)
1137
0
                            qos->arp.pre_emption_capability =
1138
0
                                pre_emption_capability;
1139
0
                        else {
1140
0
                            ogs_error("Unknown Preemption Capability [%d]",
1141
0
                                    pre_emption_capability);
1142
0
                            return OGS_ERROR;
1143
0
                        }
1144
0
                    }
1145
0
                } else if (!strcmp(arp_key,
1146
0
                            OGS_PRE_EMPTION_VULNERABILITY_STRING)) {
1147
0
                    const char *v = ogs_yaml_iter_value(&arp_iter);
1148
0
                    if (v) {
1149
0
                        uint8_t pre_emption_vulnerability = atoi(v);
1150
0
                        if (pre_emption_vulnerability ==
1151
0
                                OGS_5GC_PRE_EMPTION_DISABLED ||
1152
0
                            pre_emption_vulnerability ==
1153
0
                            OGS_5GC_PRE_EMPTION_ENABLED)
1154
0
                            qos->arp.pre_emption_vulnerability =
1155
0
                                pre_emption_vulnerability;
1156
0
                        else {
1157
0
                            ogs_error("Unknown Preemption Vulnerablility [%d]",
1158
0
                                    pre_emption_vulnerability);
1159
0
                            return OGS_ERROR;
1160
0
                        }
1161
0
                    }
1162
0
                } else
1163
0
                    ogs_warn("unknown key `%s`", arp_key);
1164
0
            }
1165
0
        } else if (!strcmp(qos_key, OGS_MBR_STRING)) {
1166
0
            rv = parse_br_conf(&qos_iter, &qos->mbr);
1167
0
            if (rv != OGS_OK) {
1168
0
                ogs_error("parse_br_conf() failed");
1169
0
                return rv;
1170
0
            }
1171
0
        } else if (!strcmp(qos_key, OGS_GBR_STRING)) {
1172
0
            rv = parse_br_conf(&qos_iter, &qos->gbr);
1173
0
            if (rv != OGS_OK) {
1174
0
                ogs_error("parse_br_conf() failed");
1175
0
                return rv;
1176
0
            }
1177
0
        }
1178
0
    }
1179
1180
0
    return OGS_OK;
1181
0
}
1182
1183
static int session_conf_prepare(ogs_app_slice_conf_t *slice_conf)
1184
0
{
1185
0
    ogs_assert(slice_conf);
1186
0
    return OGS_OK;
1187
0
}
1188
1189
static int session_conf_validation(ogs_app_slice_conf_t *slice_conf)
1190
0
{
1191
0
    int rv, j, k;
1192
0
    ogs_app_session_conf_t *session_conf = NULL;
1193
0
    ogs_assert(slice_conf);
1194
1195
0
    ogs_list_for_each(&slice_conf->sess_list, session_conf) {
1196
0
        ogs_session_data_t *session_data = &session_conf->data;
1197
1198
0
        ogs_info("NAME[%s]", session_data->session.name);
1199
0
        ogs_info("QCI[%d]", session_data->session.qos.index);
1200
0
        ogs_info("ARP[%d:%d:%d]",
1201
0
                session_data->session.qos.arp.priority_level,
1202
0
                session_data->session.qos.arp.pre_emption_capability,
1203
0
                session_data->session.qos.arp.pre_emption_vulnerability);
1204
0
        ogs_info("AMBR[Downlink:%lld:Uplink:%lld]",
1205
0
                (long long)session_data->session.ambr.downlink,
1206
0
                (long long)session_data->session.ambr.uplink);
1207
0
        for (j = 0; j < session_data->num_of_pcc_rule; j++) {
1208
0
            ogs_info("PCC_RULE[%d]", j+1);
1209
0
            ogs_info("  ID[%s]", session_data->pcc_rule[j].id);
1210
0
            ogs_info("  NAME[%s]", session_data->pcc_rule[j].name);
1211
0
            ogs_info("  QCI[%d]", session_data->pcc_rule[j].qos.index);
1212
0
            ogs_info("  ARP[%d:%d:%d]",
1213
0
                    session_data->pcc_rule[j].qos.arp.priority_level,
1214
0
                    session_data->pcc_rule[j].qos.arp.
1215
0
                    pre_emption_capability,
1216
0
                    session_data->pcc_rule[j].qos.arp.
1217
0
                    pre_emption_vulnerability);
1218
0
            ogs_info("  MBR[Downlink:%lld:Uplink:%lld]",
1219
0
                    (long long)session_data->pcc_rule[j].qos.mbr.downlink,
1220
0
                    (long long)session_data->pcc_rule[j].qos.mbr.uplink);
1221
0
            ogs_info("  GBR[Downlink:%lld:Uplink:%lld]",
1222
0
                    (long long)session_data->pcc_rule[j].qos.gbr.downlink,
1223
0
                    (long long)session_data->pcc_rule[j].qos.gbr.uplink);
1224
0
            ogs_info("  NUM_OF_FLOW [%d]",
1225
0
                session_data->pcc_rule[j].num_of_flow);
1226
1227
0
            for (k = 0; k < session_data->pcc_rule[j].num_of_flow; k++) {
1228
0
                ogs_info("    DIRECTION[%d]",
1229
0
                        session_data->pcc_rule[j].flow[k].direction);
1230
0
                ogs_info("    DESCRIPTION[%s]",
1231
0
                        session_data->pcc_rule[j].flow[k].description);
1232
0
            }
1233
0
        }
1234
1235
0
        rv = ogs_check_br_conf(&session_data->session.ambr);
1236
0
        if (rv != OGS_OK) {
1237
0
            ogs_error("check_br_conf(AMBR) failed");
1238
0
            return rv;
1239
0
        }
1240
0
        rv = ogs_check_qos_conf(&session_data->session.qos);
1241
0
        if (rv != OGS_OK) {
1242
0
            ogs_error("check_qos_conf(SESS) failed");
1243
0
            return rv;
1244
0
        }
1245
0
    }
1246
1247
0
    return OGS_OK;
1248
0
}
1249
1250
int ogs_app_parse_session_conf(
1251
        ogs_yaml_iter_t *parent, ogs_app_slice_conf_t *slice_conf)
1252
0
{
1253
0
    int rv;
1254
0
    ogs_yaml_iter_t session_array, session_iter;
1255
1256
0
    ogs_assert(parent);
1257
0
    ogs_assert(slice_conf);
1258
1259
0
    rv = session_conf_prepare(slice_conf);
1260
0
    if (rv != OGS_OK) return rv;
1261
1262
0
    ogs_yaml_iter_recurse(parent, &session_array);
1263
0
    do {
1264
0
        const char *name = NULL;
1265
0
        ogs_app_session_conf_t *session_conf = NULL;
1266
0
        ogs_session_data_t *session_data = NULL;
1267
1268
0
        OGS_YAML_ARRAY_NEXT(&session_array, &session_iter);
1269
0
        while (ogs_yaml_iter_next(&session_iter)) {
1270
0
            const char *session_key = ogs_yaml_iter_key(&session_iter);
1271
0
            ogs_assert(session_key);
1272
0
            if (!strcmp(session_key, OGS_NAME_STRING)) {
1273
0
                name = (char *)ogs_yaml_iter_value(&session_iter);
1274
0
            }
1275
0
        }
1276
1277
0
        if (name) {
1278
0
            session_conf = ogs_app_session_conf_add(slice_conf, (char *)name);
1279
0
            if (!session_conf) {
1280
0
                ogs_error("ogs_app_session_conf_add() failed [DNN:%s]", name);
1281
0
                return OGS_ERROR;
1282
0
            }
1283
0
        } else {
1284
0
            ogs_error("No APN/DNN");
1285
0
            return OGS_ERROR;
1286
0
        }
1287
1288
0
        session_data = &session_conf->data;
1289
0
        OGS_YAML_ARRAY_RECURSE(&session_array, &session_iter);
1290
0
        while (ogs_yaml_iter_next(&session_iter)) {
1291
0
            const char *session_key = ogs_yaml_iter_key(&session_iter);
1292
0
            ogs_assert(session_key);
1293
0
            if (!strcmp(session_key, OGS_TYPE_STRING)) {
1294
0
                const char *v = ogs_yaml_iter_value(&session_iter);
1295
0
                if (v) {
1296
0
                    uint8_t session_type = atoi(v);
1297
0
                    if (session_type == OGS_PDU_SESSION_TYPE_IPV4 ||
1298
0
                        session_type == OGS_PDU_SESSION_TYPE_IPV6 ||
1299
0
                        session_type == OGS_PDU_SESSION_TYPE_IPV4V6 ||
1300
0
                        session_type == OGS_PDU_SESSION_TYPE_UNSTRUCTURED ||
1301
0
                        session_type == OGS_PDU_SESSION_TYPE_ETHERNET)
1302
0
                        session_data->session.session_type = session_type;
1303
0
                    else {
1304
0
                        ogs_error("Unknown Session Type [%d]", session_type);
1305
0
                        return OGS_ERROR;
1306
0
                    }
1307
0
                }
1308
0
            } else if (!strcmp(session_key, OGS_AMBR_STRING)) {
1309
0
                rv = parse_br_conf(&session_iter, &session_data->session.ambr);
1310
0
                if (rv != OGS_OK) {
1311
0
                    ogs_error("parse_qos_conf() failed");
1312
0
                    return rv;
1313
0
                }
1314
0
            } else if (!strcmp(session_key, OGS_QOS_STRING)) {
1315
0
                rv = parse_qos_conf(&session_iter, &session_data->session.qos);
1316
0
                if (rv != OGS_OK) {
1317
0
                    ogs_error("parse_qos_conf() failed");
1318
0
                    return rv;
1319
0
                }
1320
0
            } else if (!strcmp(session_key, OGS_PCC_RULE_STRING)) {
1321
0
                int pcc_rule_index = 0;
1322
0
                ogs_yaml_iter_t pcc_rule_array, pcc_rule_iter;
1323
0
                ogs_yaml_iter_recurse(&session_iter, &pcc_rule_array);
1324
0
                do {
1325
0
                    ogs_pcc_rule_t *pcc_rule = NULL;
1326
1327
0
                    ogs_assert(session_data->num_of_pcc_rule <
1328
0
                            OGS_MAX_NUM_OF_PCC_RULE);
1329
0
                    pcc_rule = &session_data->
1330
0
                        pcc_rule[session_data->num_of_pcc_rule];
1331
1332
0
                    OGS_YAML_ARRAY_NEXT(&pcc_rule_array, &pcc_rule_iter);
1333
0
                    while (ogs_yaml_iter_next(&pcc_rule_iter)) {
1334
0
                        const char *pcc_rule_key =
1335
0
                            ogs_yaml_iter_key(&pcc_rule_iter);
1336
0
                        ogs_assert(pcc_rule_key);
1337
0
                        if (!strcmp(pcc_rule_key, OGS_QOS_STRING)) {
1338
0
                            rv = parse_qos_conf(&pcc_rule_iter, &pcc_rule->qos);
1339
0
                            if (rv != OGS_OK) {
1340
0
                                ogs_error("parse_qos_conf() failed");
1341
0
                                return rv;
1342
0
                            }
1343
0
                        } else if (!strcmp(pcc_rule_key, OGS_FLOW_STRING)) {
1344
0
                            ogs_yaml_iter_t flow_array, flow_iter;
1345
0
                            ogs_yaml_iter_recurse( &pcc_rule_iter, &flow_array);
1346
0
                            do {
1347
0
                                ogs_flow_t *flow = NULL;
1348
1349
0
                                ogs_assert(pcc_rule->num_of_flow <
1350
0
                                        OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE);
1351
0
                                flow = &pcc_rule->flow[pcc_rule->num_of_flow];
1352
1353
0
                                OGS_YAML_ARRAY_NEXT(&flow_array, &flow_iter);
1354
0
                                while (ogs_yaml_iter_next(&flow_iter)) {
1355
0
                                    const char *flow_key =
1356
0
                                        ogs_yaml_iter_key(&flow_iter);
1357
0
                                    ogs_assert(flow_key);
1358
0
                                    if (!strcmp(flow_key,
1359
0
                                                OGS_DIRECTION_STRING)) {
1360
0
                                        const char *v =
1361
0
                                            ogs_yaml_iter_value(&flow_iter);
1362
0
                                        if (v) {
1363
0
                                            uint8_t direction = atoi(v);
1364
0
                                            if (direction ==
1365
0
                                                    OGS_FLOW_DOWNLINK_ONLY ||
1366
0
                                                direction ==
1367
0
                                                OGS_FLOW_UPLINK_ONLY)
1368
0
                                                flow->direction = direction;
1369
0
                                            else {
1370
0
                                                ogs_error(
1371
0
                                                    "Unknown Direction [%d]",
1372
0
                                                    direction);
1373
0
                                                return OGS_ERROR;
1374
0
                                            }
1375
0
                                        }
1376
0
                                    } else if (!strcmp(flow_key,
1377
0
                                        OGS_DESCRIPTION_STRING)) {
1378
0
                                        const char *v =
1379
0
                                            (char *)ogs_yaml_iter_value(
1380
0
                                                    &flow_iter);
1381
0
                                        if (v) {
1382
0
                                            flow->description = ogs_strdup(v);
1383
0
                                            ogs_assert(flow->description);
1384
0
                                        }
1385
0
                                    }
1386
0
                                }
1387
1388
0
                                if (flow->direction && flow->description)
1389
0
                                    pcc_rule->num_of_flow++;
1390
1391
0
                            } while (ogs_yaml_iter_type(&flow_array) ==
1392
0
                                    YAML_SEQUENCE_NODE);
1393
1394
0
                        } else
1395
0
                            ogs_warn("unknown key `%s`", pcc_rule_key);
1396
0
                    }
1397
1398
0
                    if (pcc_rule->qos.index &&
1399
0
                        pcc_rule->qos.arp.priority_level &&
1400
0
                        pcc_rule->qos.arp.pre_emption_capability &&
1401
0
                        pcc_rule->qos.arp.pre_emption_vulnerability) {
1402
1403
                        /* EPC: Charing-Rule-Name */
1404
0
                        ogs_assert(!pcc_rule->name);
1405
0
                        pcc_rule->name = ogs_msprintf("%s-g%d",
1406
0
                                session_data->session.name, pcc_rule_index+1);
1407
0
                        ogs_assert(pcc_rule->name);
1408
1409
                        /* 5GC: PCC-Rule-Id */
1410
0
                        ogs_assert(!pcc_rule->id);
1411
0
                        pcc_rule->id = ogs_msprintf("%s-n%d",
1412
0
                                session_data->session.name, pcc_rule_index+1);
1413
0
                        ogs_assert(pcc_rule->id);
1414
1415
0
                        pcc_rule->precedence = pcc_rule_index+1;
1416
0
                        pcc_rule_index++;
1417
1418
0
                        session_data->num_of_pcc_rule++;
1419
0
                    } else
1420
0
                        ogs_warn("Mandatory is MISSING - "
1421
0
                                "QCI[%d], ARP[%d:%d:%d]",
1422
0
                            pcc_rule->qos.index,
1423
0
                            pcc_rule->qos.arp.priority_level,
1424
0
                            pcc_rule->qos.arp.
1425
0
                            pre_emption_capability,
1426
0
                            pcc_rule->qos.arp.
1427
0
                            pre_emption_vulnerability);
1428
1429
0
                } while (ogs_yaml_iter_type(&pcc_rule_array) ==
1430
0
                        YAML_SEQUENCE_NODE);
1431
0
            }
1432
0
        }
1433
1434
0
    } while (ogs_yaml_iter_type(&session_array) == YAML_SEQUENCE_NODE);
1435
1436
0
    rv = session_conf_validation(slice_conf);
1437
0
    if (rv != OGS_OK) return rv;
1438
1439
0
    return OGS_OK;
1440
0
}
1441
1442
ogs_app_policy_conf_t *ogs_app_policy_conf_add(
1443
        ogs_supi_range_t *supi_range, ogs_plmn_id_t *plmn_id)
1444
0
{
1445
0
    ogs_app_policy_conf_t *policy_conf = NULL;
1446
1447
0
    ogs_assert(supi_range || plmn_id);
1448
1449
0
    ogs_pool_alloc(&policy_conf_pool, &policy_conf);
1450
0
    if (!policy_conf) {
1451
0
        ogs_error("Maximum number of policy_conf[%d] reached",
1452
0
                OGS_MAX_NUM_OF_PLMN);
1453
0
        return NULL;
1454
0
    }
1455
0
    memset(policy_conf, 0, sizeof *policy_conf);
1456
1457
0
    if (supi_range) {
1458
0
        int i;
1459
1460
0
        memcpy(&policy_conf->supi_range, supi_range, sizeof(ogs_supi_range_t));
1461
1462
0
        ogs_info("SUPI[%d]", policy_conf->supi_range.num);
1463
0
        for (i = 0; i < policy_conf->supi_range.num; i++)
1464
0
            ogs_info("    START[%lld]-END[%lld]",
1465
0
                    (long long)policy_conf->supi_range.start[i],
1466
0
                    (long long)policy_conf->supi_range.end[i]);
1467
1468
0
    }
1469
0
    if (plmn_id) {
1470
0
        policy_conf->plmn_id_valid = true;
1471
0
        memcpy(&policy_conf->plmn_id, plmn_id, sizeof(ogs_plmn_id_t));
1472
0
        ogs_info("PLMN_ID[MCC:%03d.MNC:%03d]",
1473
0
                ogs_plmn_id_mcc(&policy_conf->plmn_id),
1474
0
                ogs_plmn_id_mnc(&policy_conf->plmn_id));
1475
0
    }
1476
1477
0
    ogs_list_init(&policy_conf->slice_list);
1478
1479
0
    ogs_list_add(&local_conf.policy_list, policy_conf);
1480
1481
0
    ogs_info("POLICY config added [%d]",
1482
0
            ogs_list_count(&local_conf.policy_list));
1483
0
    return policy_conf;
1484
0
}
1485
1486
ogs_app_policy_conf_t *ogs_app_policy_conf_find(
1487
        const char *supi, const ogs_plmn_id_t *plmn_id)
1488
0
{
1489
0
    ogs_app_policy_conf_t *policy_conf;
1490
0
    int i;
1491
1492
0
    char *supi_type = NULL;
1493
0
    char *supi_id = NULL;
1494
0
    uint64_t supi_decimal;
1495
1496
0
    ogs_assert(supi);
1497
1498
0
    supi_type = ogs_id_get_type(supi);
1499
0
    ogs_assert(supi_type);
1500
0
    supi_id = ogs_id_get_value(supi);
1501
0
    ogs_assert(supi_id);
1502
1503
0
    supi_decimal = ogs_uint64_from_string_decimal(supi_id);
1504
1505
0
    ogs_free(supi_type);
1506
0
    ogs_free(supi_id);
1507
1508
0
    ogs_list_for_each(&local_conf.policy_list, policy_conf) {
1509
        /* If supi_range is set, check if supi_decimal falls within
1510
         * any of the defined ranges.
1511
         */
1512
0
        if (policy_conf->supi_range.num > 0) {
1513
0
            int in_range = 0;
1514
0
            for (i = 0; i < policy_conf->supi_range.num; i++) {
1515
0
                if ((supi_decimal >= policy_conf->supi_range.start[i]) &&
1516
0
                    (supi_decimal <= policy_conf->supi_range.end[i])) {
1517
0
                    in_range = 1;
1518
0
                    break;
1519
0
                }
1520
0
            }
1521
0
            if (!in_range) {
1522
0
                continue;
1523
0
            }
1524
0
        }
1525
1526
        /* If a plmn_id is set and it does not match the
1527
         * current policy's plmn_id, skip this policy.
1528
         */
1529
0
        if (policy_conf->plmn_id_valid &&
1530
0
            memcmp(&policy_conf->plmn_id, plmn_id,
1531
0
                   sizeof(ogs_plmn_id_t)) != 0) {
1532
0
            continue;
1533
0
        }
1534
1535
        /* Both conditions met; return this policy configuration */
1536
0
        return policy_conf;
1537
0
    }
1538
1539
0
    return NULL;
1540
0
}
1541
void ogs_app_policy_conf_remove(ogs_app_policy_conf_t *policy_conf)
1542
0
{
1543
0
    ogs_assert(policy_conf);
1544
1545
0
    ogs_list_remove(&local_conf.policy_list, policy_conf);
1546
1547
0
    ogs_app_slice_conf_remove_all(policy_conf);
1548
1549
0
    ogs_pool_free(&policy_conf_pool, policy_conf);
1550
1551
0
    ogs_info("POLICY config removed [%d]",
1552
0
            ogs_list_count(&local_conf.policy_list));
1553
0
}
1554
void ogs_app_policy_conf_remove_all(void)
1555
0
{
1556
0
    ogs_app_policy_conf_t *policy_conf = NULL, *next_conf = NULL;;
1557
1558
0
    ogs_list_for_each_safe(&local_conf.policy_list, next_conf, policy_conf)
1559
0
        ogs_app_policy_conf_remove(policy_conf);
1560
0
}
1561
1562
ogs_app_slice_conf_t *ogs_app_slice_conf_add(
1563
        ogs_app_policy_conf_t *policy_conf, const ogs_s_nssai_t *s_nssai)
1564
0
{
1565
0
    ogs_app_slice_conf_t *slice_conf = NULL;
1566
1567
0
    ogs_assert(policy_conf);
1568
0
    ogs_assert(s_nssai);
1569
1570
0
    ogs_pool_alloc(&slice_conf_pool, &slice_conf);
1571
0
    if (!slice_conf) {
1572
0
        ogs_error("Maximum number of slice_conf[%d] reached",
1573
0
                OGS_MAX_NUM_OF_SLICE);
1574
0
        return NULL;
1575
0
    }
1576
0
    memset(slice_conf, 0, sizeof *slice_conf);
1577
1578
0
    slice_conf->data.s_nssai.sst = s_nssai->sst;
1579
0
    slice_conf->data.s_nssai.sd.v = s_nssai->sd.v;
1580
1581
0
    ogs_list_init(&slice_conf->sess_list);
1582
1583
0
    ogs_list_add(&policy_conf->slice_list, slice_conf);
1584
1585
0
    slice_conf->policy_conf = policy_conf;
1586
1587
0
    ogs_info("SLICE config added [%d]",
1588
0
            ogs_list_count(&policy_conf->slice_list));
1589
0
    return slice_conf;
1590
0
}
1591
1592
ogs_app_slice_conf_t *ogs_app_slice_conf_find_by_s_nssai(
1593
        ogs_app_policy_conf_t *policy_conf, const ogs_s_nssai_t *s_nssai)
1594
0
{
1595
0
    ogs_app_slice_conf_t *slice_conf = NULL;
1596
1597
0
    ogs_assert(policy_conf);
1598
0
    ogs_assert(s_nssai);
1599
1600
0
    ogs_list_for_each(&policy_conf->slice_list, slice_conf) {
1601
0
        if (slice_conf->data.s_nssai.sst == s_nssai->sst &&
1602
0
                slice_conf->data.s_nssai.sd.v == s_nssai->sd.v)
1603
0
            break;
1604
0
    }
1605
1606
0
    return slice_conf;
1607
0
}
1608
void ogs_app_slice_conf_remove(ogs_app_slice_conf_t *slice_conf)
1609
0
{
1610
0
    ogs_app_policy_conf_t *policy_conf = NULL;
1611
1612
0
    ogs_assert(slice_conf);
1613
0
    policy_conf = slice_conf->policy_conf;
1614
0
    ogs_assert(policy_conf);
1615
1616
0
    ogs_list_remove(&policy_conf->slice_list, slice_conf);
1617
1618
0
    ogs_app_session_conf_remove_all(slice_conf);
1619
1620
0
    ogs_pool_free(&slice_conf_pool, slice_conf);
1621
1622
0
    ogs_info("SLICE config removed [%d]",
1623
0
            ogs_list_count(&policy_conf->slice_list));
1624
0
}
1625
void ogs_app_slice_conf_remove_all(ogs_app_policy_conf_t *policy_conf)
1626
0
{
1627
0
    ogs_app_slice_conf_t *slice_conf = NULL, *next_conf = NULL;;
1628
1629
0
    ogs_assert(policy_conf);
1630
1631
0
    ogs_list_for_each_safe(&policy_conf->slice_list, next_conf, slice_conf)
1632
0
        ogs_app_slice_conf_remove(slice_conf);
1633
0
}
1634
1635
int ogs_app_check_policy_conf(void)
1636
0
{
1637
0
    ogs_app_policy_conf_t *policy_conf = NULL;
1638
1639
0
    ogs_list_for_each(&ogs_local_conf()->policy_list, policy_conf) {
1640
0
        ogs_app_slice_conf_t *slice_conf = NULL;
1641
0
        bool default_indicator = false;
1642
1643
0
        ogs_list_for_each(&policy_conf->slice_list, slice_conf) {
1644
0
            if (slice_conf->data.default_indicator == true)
1645
0
                default_indicator = true;
1646
1647
0
            if (ogs_list_count(&slice_conf->sess_list) == 0) {
1648
0
                ogs_error("At least 1 Session is required");
1649
0
                return OGS_ERROR;
1650
0
            }
1651
0
        }
1652
1653
0
        if (default_indicator == false) {
1654
0
            ogs_error("At least 1 Default S-NSSAI is required");
1655
0
            return OGS_ERROR;
1656
0
        }
1657
0
    }
1658
1659
0
    return OGS_OK;
1660
0
}
1661
1662
ogs_app_session_conf_t *ogs_app_session_conf_add(
1663
        ogs_app_slice_conf_t *slice_conf, const char *name)
1664
0
{
1665
0
    ogs_app_session_conf_t *session_conf = NULL;
1666
1667
0
    ogs_assert(slice_conf);
1668
0
    ogs_assert(name);
1669
1670
0
    ogs_pool_alloc(&session_conf_pool, &session_conf);
1671
0
    if (!session_conf) {
1672
0
        ogs_error("Maximum number of session_conf[%d] reached",
1673
0
                OGS_MAX_NUM_OF_SLICE*OGS_MAX_NUM_OF_SESS);
1674
0
        return NULL;
1675
0
    }
1676
0
    memset(session_conf, 0, sizeof *session_conf);
1677
1678
0
    session_conf->data.session.name = ogs_strdup(name);
1679
0
    if (!session_conf->data.session.name) {
1680
0
        ogs_error("No memory for DNN[%s]", name);
1681
0
        ogs_pool_free(&session_conf_pool, session_conf);
1682
0
        return NULL;
1683
0
    }
1684
1685
0
    ogs_list_add(&slice_conf->sess_list, session_conf);
1686
1687
0
    session_conf->slice_conf = slice_conf;
1688
1689
0
    ogs_info("SESSION config added [%d]",
1690
0
            ogs_list_count(&slice_conf->sess_list));
1691
1692
0
    return session_conf;
1693
0
}
1694
ogs_app_session_conf_t *ogs_app_session_conf_find_by_dnn(
1695
        ogs_app_slice_conf_t *slice_conf, const char *name)
1696
0
{
1697
0
    ogs_app_session_conf_t *session_conf = NULL;
1698
1699
0
    ogs_assert(slice_conf);
1700
0
    ogs_assert(name);
1701
1702
0
    ogs_list_for_each(&slice_conf->sess_list, session_conf) {
1703
0
        ogs_assert(session_conf->data.session.name);
1704
0
        if (strcmp(session_conf->data.session.name, name) == 0)
1705
0
            break;
1706
0
    }
1707
1708
0
    return session_conf;
1709
0
}
1710
void ogs_app_session_conf_remove(ogs_app_session_conf_t *session_conf)
1711
0
{
1712
0
    ogs_app_slice_conf_t *slice_conf = NULL;
1713
1714
0
    ogs_assert(session_conf);
1715
0
    slice_conf = session_conf->slice_conf;
1716
0
    ogs_assert(slice_conf);
1717
1718
0
    ogs_list_remove(&slice_conf->sess_list, session_conf);
1719
1720
0
    OGS_SESSION_DATA_FREE(&session_conf->data);
1721
1722
0
    ogs_pool_free(&session_conf_pool, session_conf);
1723
1724
0
    ogs_info("SESSION config removed [%d]",
1725
0
            ogs_list_count(&slice_conf->sess_list));
1726
0
}
1727
void ogs_app_session_conf_remove_all(ogs_app_slice_conf_t *slice_conf)
1728
0
{
1729
0
    ogs_app_session_conf_t *session_conf = NULL, *next_conf = NULL;;
1730
1731
0
    ogs_assert(slice_conf);
1732
1733
0
    ogs_list_for_each_safe(&slice_conf->sess_list, next_conf, session_conf)
1734
0
        ogs_app_session_conf_remove(session_conf);
1735
0
}
1736
1737
int ogs_app_config_session_data(
1738
        const char *supi, const ogs_plmn_id_t *plmn_id,
1739
        const ogs_s_nssai_t *s_nssai, const char *dnn,
1740
        ogs_session_data_t *session_data)
1741
0
{
1742
0
    ogs_app_policy_conf_t *policy_conf = NULL;
1743
0
    ogs_app_slice_conf_t *slice_conf = NULL;
1744
0
    ogs_app_session_conf_t *session_conf = NULL;
1745
1746
0
    ogs_assert(supi);
1747
0
    ogs_assert(dnn);
1748
0
    ogs_assert(session_data);
1749
1750
0
    policy_conf = ogs_app_policy_conf_find(supi, plmn_id);
1751
0
    if (!policy_conf) {
1752
0
        if (plmn_id)
1753
0
            ogs_error("No POLICY [SUPI:%s] [MCC:%03d,MNC:%03d]",
1754
0
                    supi, ogs_plmn_id_mcc(plmn_id), ogs_plmn_id_mnc(plmn_id));
1755
0
        else
1756
0
            ogs_error("No POLICY [SUPI:%s]", supi);
1757
1758
0
        return OGS_ERROR;
1759
0
    }
1760
1761
0
    if (s_nssai) {
1762
0
        slice_conf = ogs_app_slice_conf_find_by_s_nssai(policy_conf, s_nssai);
1763
0
        if (!slice_conf) {
1764
0
            ogs_error("No SLICE [SST:%d, SD:0x%x]",
1765
0
                    s_nssai->sst, s_nssai->sd.v);
1766
0
            return OGS_ERROR;
1767
0
        }
1768
0
    } else {
1769
0
        slice_conf = ogs_list_first(&policy_conf->slice_list);
1770
0
        if (!slice_conf) {
1771
0
            ogs_error("No default SLICE for EPC");
1772
0
            return OGS_ERROR;
1773
0
        }
1774
0
    }
1775
0
    session_conf = ogs_app_session_conf_find_by_dnn(slice_conf, dnn);
1776
0
    if (!session_conf) {
1777
0
        ogs_error("No SESSION [%s]", dnn);
1778
0
        return OGS_ERROR;
1779
0
    }
1780
1781
0
    OGS_STORE_SESSION_DATA(session_data, &session_conf->data);
1782
1783
0
    return OGS_OK;
1784
0
}