refine SGW/UPF selection code

This commit is contained in:
Sukchan Lee 2020-07-09 01:38:09 -04:00
parent 8ddbb03f65
commit a71d2ee3db
119 changed files with 1927 additions and 2037 deletions

View File

@ -108,7 +108,7 @@ nrf:
upf:
pfcp:
addr: 127.0.0.4
- addr: 127.0.0.4
gtpu:
- addr:
- 127.0.0.4

View File

@ -165,6 +165,7 @@ amf:
- addr: 127.0.0.2
port: 7777
ngap:
- addr: 127.0.0.2
guami:
- plmn_id:
mcc: 901
@ -279,9 +280,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -156,9 +156,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -86,9 +86,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -255,31 +255,29 @@ mme:
# <SGW Selection Mode>
#
# o Round-Robin
# (If `selection_mode` is omitted, the default mode is Round-Robin)
#
# selection_mode: rr
# gtpc:
# addr: 127.0.0.2
# addr: 127.0.2.2
# addr: 127.0.4.2
#
# o SGW selection by eNodeB TAC (either single TAC or multiple TACs)
# o SGW selection by eNodeB TAC
# (either single TAC or multiple TACs, DECIMAL representation)
#
# selection_mode: tac
# gtpc:
# - addr: 127.0.0.2
# tac: 26000
# - addr: 127.0.2.2
# tac: [25000, 27000, 28000]
#
# o SGW selection by eNodeB ID (either single enb_id or multiple enb_ids, decimal or hex representation)
# o SGW selection by e_cell_id(28bit)
# (either single or multiple e_cell_id, HEX representation)
#
# selection_mode: enb_id
# gtpc:
# - addr: 127.0.0.2
# enb_id: 463
# e_cell_id: abcde01
# - addr: 127.0.2.2
# enb_id: [0x12345, 9413, 0x98765]
# e_cell_id: [12345, a9413, 98765]
#
sgw:
gtpc:
@ -388,9 +386,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -128,9 +128,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -85,9 +85,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -225,9 +225,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -122,9 +122,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -263,41 +263,39 @@ nrf:
# <UPF_SELECTION_MODE>
#
# o Round-Robin
# (If `upf_selection_mode` is omitted in smf/pfcp,
# the default mode is Round-Robin)
#
# upf:
# pfcp:
# - addr: 127.0.0.4
# - addr: 127.0.0.12
#
# o UPF selection by eNodeB TAC (either single TAC or multiple TACs)
# o UPF selection by eNodeB TAC
# (either single TAC or multiple TACs, DECIMAL representation)
#
# upf:
# pfcp:
# - addr: 127.0.0.4
# tac: 1 < either single TAC or multiple TACs
# tac: 1
# - addr: 127.0.0.12
# tac: [3,5,8]
#
# o SGW selection by UE's APN (either single APN or multiple APNs)
# o UPF selection by UE's DNN/APN (either single DNN/APN or multiple DNNs/APNs)
#
# upf:
# pfcp:
# - addr: 127.0.0.4
# apn: ims < either single APN or multiple APNs
# dnn: ims
# - addr: 127.0.0.12
# apn: [internet, web]
#
# o SGW selection by eNodeB ID
# (either single enb_id or multiple enb_ids, decimal or hex representation)
# o UPF selection by CellID(e_cell_id: 28bit, nr_cell_id: 36bit)
# (either single enb_id or multiple enb_ids, HEX representation)
#
# upf:
# pfcp:
# - addr: 127.0.0.4
# enb_id: 463 < either single enb_id or multiple enb_id,
# - addr: 127.0.0.12 can be entered in decimal or hex format
# enb_id: [0x12345, 9413]
# e_cell_id: 463
# - addr: 127.0.0.12
# nr_cell_id: [123456789, 9413]
#
upf:
pfcp:
@ -359,9 +357,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -156,9 +156,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -158,9 +158,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
#

View File

@ -61,6 +61,9 @@ upf:
pfcp:
- addr: 127.0.0.4
gtpu:
- addr:
- 127.0.0.4
- ::1
pdn:
#
@ -134,9 +137,9 @@ max:
# 8192: 128
# big: 8
#
# o Memory of Packet Buffering in SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in SGW
# - SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
# o Memory of Packet Buffering in UPF/SGW
# - Maximum Number of packet(SDU size = 8Kbytes) pool in UPF/SGW
# - UPF/SGW Memory Usage : 65536 * 8Kbytes = 512Mbytes
#
# packet: 65536
pool:

View File

@ -130,14 +130,18 @@ ogs_amf_id_t *ogs_amf_id_from_string(ogs_amf_id_t *amf_id, const char *hex)
return amf_id;
}
char *ogs_amf_id_to_string(ogs_amf_id_t *amf_id, char *buf)
#define OGS_AMFIDSTRLEN (sizeof(ogs_amf_id_t)*2+1)
char *ogs_amf_id_to_string(ogs_amf_id_t *amf_id)
{
char *str = NULL;
ogs_assert(amf_id);
ogs_assert(buf);
ogs_hex_to_ascii(amf_id, sizeof(ogs_amf_id_t), buf, OGS_AMFIDSTRLEN);
str = ogs_calloc(1, OGS_AMFIDSTRLEN);
ogs_assert(str);
return buf;
ogs_hex_to_ascii(amf_id, sizeof(ogs_amf_id_t), str, OGS_AMFIDSTRLEN);
return str;
}
uint8_t ogs_amf_region_id(ogs_amf_id_t *amf_id)
@ -167,29 +171,6 @@ ogs_amf_id_t *ogs_amf_id_build(ogs_amf_id_t *amf_id,
return amf_id;
}
char *ogs_s_nssai_sd_to_string(ogs_uint24_t sd)
{
if (sd.v != OGS_S_NSSAI_NO_SD_VALUE)
return ogs_msprintf("%06x", sd.v);
else
return NULL;
}
ogs_uint24_t ogs_s_nssai_sd_from_string(const char *hex)
{
ogs_uint24_t sd;
char hexbuf[sizeof(ogs_uint24_t)];
sd.v = OGS_S_NSSAI_NO_SD_VALUE;
if (hex == NULL)
return sd;
OGS_HEX(hex, strlen(hex), hexbuf);
memcpy(&sd, hexbuf, 3);
return ogs_be24toh(sd);
}
char *ogs_supi_from_suci(char *suci)
{
#define MAX_SUCI_TOKEN 16
@ -269,6 +250,25 @@ char *ogs_id_get_value(char *str)
return ueid;
}
char *ogs_s_nssai_sd_to_string(ogs_uint24_t sd)
{
if (sd.v == OGS_S_NSSAI_NO_SD_VALUE)
return NULL;
return ogs_uint24_to_string(sd);
}
ogs_uint24_t ogs_s_nssai_sd_from_string(const char *hex)
{
ogs_uint24_t sd;
sd.v = OGS_S_NSSAI_NO_SD_VALUE;
if (hex == NULL)
return sd;
return ogs_uint24_from_string((char *)hex);
}
int ogs_fqdn_build(char *dst, char *src, int length)
{
int i = 0, j = 0;

View File

@ -51,6 +51,7 @@ extern "C" {
#define OGS_MAX_MSISDN_LEN \
OGS_BCD_TO_BUFFER_LEN(OGS_MAX_MSISDN_BCD_LEN)
#define OGS_MAX_NUM_OF_CELL_ID 16
#define OGS_MAX_NUM_OF_ENB_ID 16
#define OGS_MAX_NUM_OF_APN 16
#define OGS_MAX_NUM_OF_HOSTNAME 16
@ -80,46 +81,6 @@ extern "C" {
#define OGS_ACCESS_TYPE_NON_3GPP 2
#define OGS_ACCESS_TYPE_BOTH_3GPP_AND_NON_3GPP 3
typedef struct ogs_uint24_s {
uint32_t v:24;
} __attribute__ ((packed)) ogs_uint24_t;
static ogs_inline ogs_uint24_t ogs_be24toh(ogs_uint24_t x)
{
uint32_t tmp = x.v;
tmp = be32toh(tmp);
x.v = tmp >> 8;
return x;
}
static ogs_inline ogs_uint24_t ogs_htobe24(ogs_uint24_t x)
{
uint32_t tmp = x.v;
tmp = htobe32(tmp);
x.v = tmp >> 8;
return x;
}
static ogs_inline ogs_uint24_t ogs_uint24_from_string(char *str)
{
ogs_uint24_t x;
ogs_assert(str);
OGS_HEX(str, strlen(str), &x);
return ogs_be24toh(x);
}
#define OGS_24BITSTRLEN (sizeof(ogs_uint24_t)*2+1)
static ogs_inline char *ogs_uint24_to_string(ogs_uint24_t x, char *str)
{
ogs_assert(str);
x = ogs_htobe24(x);
ogs_hex_to_ascii(&x, sizeof(x), str, OGS_24BITSTRLEN);
return str;
}
/************************************
* PLMN_ID Structure */
#define OGS_MAX_NUM_OF_PLMN 6
@ -157,11 +118,15 @@ ED2(uint8_t set2:2;,
uint8_t pointer:6;)
} __attribute__ ((packed)) ogs_amf_id_t;
typedef struct ogs_guami_s {
ogs_plmn_id_t plmn_id;
ogs_amf_id_t amf_id;
} ogs_guami_t;
uint32_t ogs_amf_id_hexdump(ogs_amf_id_t *amf_id);
#define OGS_AMFIDSTRLEN (sizeof(ogs_amf_id_t)*2+1)
ogs_amf_id_t *ogs_amf_id_from_string(ogs_amf_id_t *amf_id, const char *hex);
char *ogs_amf_id_to_string(ogs_amf_id_t *amf_id, char *buf);
char *ogs_amf_id_to_string(ogs_amf_id_t *amf_id);
uint8_t ogs_amf_region_id(ogs_amf_id_t *amf_id);
uint16_t ogs_amf_set_id(ogs_amf_id_t *amf_id);

View File

@ -155,3 +155,65 @@ char ogs_from_hex(char ch)
{
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}
char *ogs_uint24_to_string(ogs_uint24_t x)
{
return ogs_msprintf("%06x", x.v);
}
char *ogs_uint28_to_string(uint32_t x)
{
return ogs_msprintf("%07x", x);
}
char *ogs_uint32_to_string(uint32_t x)
{
return ogs_msprintf("%08x", x);
}
char *ogs_uint36_to_string(uint64_t x)
{
return ogs_msprintf("%09llx", (long long)x);
}
ogs_uint24_t ogs_uint24_from_string(char *str)
{
ogs_uint24_t x;
ogs_assert(str);
ogs_ascii_to_hex(str, strlen(str), &x, 3);
return ogs_be24toh(x);
}
uint32_t ogs_uint28_from_string(char *str)
{
uint32_t x;
ogs_assert(str);
x = 0;
ogs_ascii_to_hex(str, strlen(str), &x, 4);
return be32toh(x) >> 4;
}
uint32_t ogs_uint32_from_string(char *str)
{
uint32_t x;
ogs_assert(str);
ogs_ascii_to_hex(str, strlen(str), &x, 4);
return be32toh(x);
}
uint64_t ogs_uint36_from_string(char *str)
{
uint64_t x;
ogs_assert(str);
x = 0;
ogs_ascii_to_hex(str, strlen(str), &x, 5);
return be64toh(x) >> 28;
}

View File

@ -39,6 +39,16 @@ void *ogs_buffer_to_bcd(uint8_t *in, int in_len, void *out);
char ogs_from_hex(char ch);
char *ogs_uint24_to_string(ogs_uint24_t x);
char *ogs_uint28_to_string(uint32_t x);
char *ogs_uint32_to_string(uint32_t x);
char *ogs_uint36_to_string(uint64_t x);
ogs_uint24_t ogs_uint24_from_string(char *str);
uint32_t ogs_uint28_from_string(char *str);
uint32_t ogs_uint32_from_string(char *str);
uint64_t ogs_uint36_from_string(char *str);
#ifdef __cplusplus
}
#endif

View File

@ -124,6 +124,26 @@ extern "C" {
#endif
#endif
typedef struct ogs_uint24_s {
uint32_t v:24;
} __attribute__ ((packed)) ogs_uint24_t;
static ogs_inline ogs_uint24_t ogs_be24toh(ogs_uint24_t x)
{
uint32_t tmp = x.v;
tmp = be32toh(tmp);
x.v = tmp >> 8;
return x;
}
static ogs_inline ogs_uint24_t ogs_htobe24(ogs_uint24_t x)
{
uint32_t tmp = x.v;
tmp = htobe32(tmp);
x.v = tmp >> 8;
return x;
}
#if OGS_BYTE_ORDER == OGS_BIG_ENDIAN
#define ED2(x1, x2) x1 x2
#define ED3(x1, x2, x3) x1 x2 x3

View File

@ -36,7 +36,6 @@
* The following code is stolen from mongodb-c-driver
* https://github.com/mongodb/mongo-c-driver/blob/master/src/libbson/src/bson/bson-clock.c
*/
int ogs_gettimeofday(struct timeval *tv)
{
#if defined(_WIN32)
@ -84,6 +83,56 @@ int ogs_gettimeofday(struct timeval *tv)
#endif
}
ogs_time_t ogs_time_now(void)
{
int rc;
struct timeval tv;
rc = ogs_gettimeofday(&tv);
ogs_assert(rc == 0);
return tv.tv_sec * OGS_USEC_PER_SEC + tv.tv_usec;
}
/* The following code is stolen from APR library */
int ogs_time_from_lt(ogs_time_t *t, struct tm *tm, int tm_usec)
{
ogs_time_t year = tm->tm_year;
ogs_time_t days;
static const int dayoffset[12] =
{306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
if (tm->tm_mon < 0 || tm->tm_mon >= 12)
return OGS_ERROR;
/* shift new year to 1st March in order to make leap year calc easy */
if (tm->tm_mon < 2)
year--;
/* Find number of days since 1st March 1900 (in the Gregorian calendar). */
days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4;
days += dayoffset[tm->tm_mon] + tm->tm_mday - 1;
days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */
days = ((days * 24 + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
if (days < 0) {
return OGS_ERROR;
}
*t = days * OGS_USEC_PER_SEC + tm_usec;
return OGS_OK;
}
int ogs_time_from_gmt(ogs_time_t *t, struct tm *tm, int tm_usec)
{
int status = ogs_time_from_lt(t, tm, tm_usec);
if (status == OGS_OK)
*t -= (ogs_time_t) tm->tm_gmtoff * OGS_USEC_PER_SEC;
return status;
}
int ogs_timezone(void)
{
#if defined(_WIN32)
@ -109,18 +158,14 @@ int ogs_timezone(void)
#else
struct timeval tv;
struct tm tm;
time_t t1, t2;
int ret;
ret = ogs_gettimeofday(&tv);
ogs_assert(ret == 0);
t1 = tv.tv_sec;
ogs_gmtime(t1, &tm);
tm.tm_isdst = 0;
t2 = mktime(&tm);
ogs_localtime(tv.tv_sec, &tm);
return difftime(t1, t2);
return tm.tm_gmtoff;
#endif
}
@ -162,6 +207,7 @@ ogs_time_t ogs_get_monotonic_time(void)
void ogs_localtime(time_t s, struct tm *tm)
{
ogs_assert(tm);
memset(tm, 0, sizeof(*tm));
#if (HAVE_LOCALTIME_R)
(void)localtime_r(&s, tm);
@ -176,6 +222,7 @@ void ogs_localtime(time_t s, struct tm *tm)
void ogs_gmtime(time_t s, struct tm *tm)
{
ogs_assert(tm);
memset(tm, 0, sizeof(*tm));
#if (HAVE_LOCALTIME_R)
(void)gmtime_r(&s, tm);
@ -208,4 +255,3 @@ void ogs_usleep(time_t usec)
req = rem;
#endif
}

View File

@ -34,7 +34,7 @@ typedef int64_t ogs_time_t;
#define OGS_NO_WAIT_TIME (0)
/** number of microseconds per second */
#define OGS_USEC_PER_SEC (1000000)
#define OGS_USEC_PER_SEC (1000000L)
/** @return ogs_time_t as a second */
#define ogs_time_sec(time) ((time) / OGS_USEC_PER_SEC)
@ -56,6 +56,10 @@ typedef int64_t ogs_time_t;
int ogs_gettimeofday(struct timeval *tv);
ogs_time_t ogs_time_now(void); /* This returns GMT */
int ogs_time_from_lt(ogs_time_t *t, struct tm *tm, int tm_usec);
int ogs_time_from_gmt(ogs_time_t *t, struct tm *tm, int tm_usec);
/** @return number of microseconds since an arbitrary point */
ogs_time_t ogs_get_monotonic_time(void);
/** @return the GMT offset in seconds */
@ -67,9 +71,6 @@ void ogs_gmtime(time_t s, struct tm *tm);
void ogs_msleep(time_t msec);
void ogs_usleep(time_t usec);
#define OGS_TIME_ISO8601_FORMATTED_LENGTH 128
#define OGS_TIME_ISO8601_FORMAT "%Y-%m-%dT%H:%M:%S%z"
#define ogs_mktime mktime
#define ogs_strptime strptime
#define ogs_strftime strftime

View File

@ -19,41 +19,6 @@
#include "ogs-gtp.h"
void ogs_gtp_bearers_in_create_indirect_tunnel_request(
ogs_gtp_tlv_bearer_context_t *bearers[][OGS_GTP_MAX_INDIRECT_TUNNEL],
ogs_gtp_create_indirect_data_forwarding_tunnel_request_t *req)
{
(*bearers)[0] = &req->bearer_context_0;
(*bearers)[1] = &req->bearer_context_1;
(*bearers)[2] = &req->bearer_context_2;
(*bearers)[3] = &req->bearer_context_3;
(*bearers)[4] = &req->bearer_context_4;
(*bearers)[5] = &req->bearer_context_5;
(*bearers)[6] = &req->bearer_context_6;
(*bearers)[7] = &req->bearer_context_7;
(*bearers)[8] = &req->bearer_context_8;
(*bearers)[9] = &req->bearer_context_9;
(*bearers)[10] = &req->bearer_context_10;
}
void ogs_gtp_bearers_in_create_indirect_tunnel_response(
ogs_gtp_tlv_bearer_context_t *bearers[][OGS_GTP_MAX_INDIRECT_TUNNEL],
ogs_gtp_create_indirect_data_forwarding_tunnel_response_t *rsp)
{
(*bearers)[0] = &rsp->bearer_context_0;
(*bearers)[1] = &rsp->bearer_context_1;
(*bearers)[2] = &rsp->bearer_context_2;
(*bearers)[3] = &rsp->bearer_context_3;
(*bearers)[4] = &rsp->bearer_context_4;
(*bearers)[5] = &rsp->bearer_context_5;
(*bearers)[6] = &rsp->bearer_context_6;
(*bearers)[7] = &rsp->bearer_context_7;
(*bearers)[8] = &rsp->bearer_context_8;
(*bearers)[9] = &rsp->bearer_context_9;
(*bearers)[10] = &rsp->bearer_context_10;
}
int ogs_gtp_f_teid_to_sockaddr(
ogs_gtp_f_teid_t *f_teid, uint16_t port, ogs_sockaddr_t **list)
{

View File

@ -28,16 +28,6 @@
extern "C" {
#endif
#define OGS_GTP_MAX_INDIRECT_TUNNEL 11
/* Create Indirect Data Forwarding Tunnel Request/Response */
void ogs_gtp_bearers_in_create_indirect_tunnel_request(
ogs_gtp_tlv_bearer_context_t *bearers[][OGS_GTP_MAX_INDIRECT_TUNNEL],
ogs_gtp_create_indirect_data_forwarding_tunnel_request_t *req);
void ogs_gtp_bearers_in_create_indirect_tunnel_response(
ogs_gtp_tlv_bearer_context_t *bearers[][OGS_GTP_MAX_INDIRECT_TUNNEL],
ogs_gtp_create_indirect_data_forwarding_tunnel_response_t *rsp);
int ogs_gtp_f_teid_to_sockaddr(
ogs_gtp_f_teid_t *f_teid, uint16_t port, ogs_sockaddr_t **list);
int ogs_gtp_sockaddr_to_f_teid(ogs_sockaddr_t *addr, ogs_sockaddr_t *addr6,

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2020-06-30 21:17:14.937085 by acetcom
* Created on: 2020-07-08 16:42:53.180060 by acetcom
* from 29274-g30.docx
******************************************************************************/
@ -1868,357 +1868,6 @@ ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_1 =
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_2 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
2,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_3 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
3,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_4 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
4,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_5 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
5,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_6 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
6,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_7 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
7,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_8 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
8,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_9 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
9,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_10 =
{
OGS_TLV_COMPOUND,
"Bearer Context",
OGS_GTP_BEARER_CONTEXT_TYPE,
0,
10,
sizeof(ogs_gtp_tlv_bearer_context_t),
{
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_bearer_tft_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_f_teid_2,
&ogs_gtp_tlv_desc_f_teid_3,
&ogs_gtp_tlv_desc_f_teid_4,
&ogs_gtp_tlv_desc_f_teid_5,
&ogs_gtp_tlv_desc_f_teid_6,
&ogs_gtp_tlv_desc_bearer_qos_0,
&ogs_gtp_tlv_desc_f_teid_7,
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_charging_id_0,
&ogs_gtp_tlv_desc_bearer_flags_0,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_maximum_packet_loss_rate_0,
&ogs_gtp_tlv_desc_f_teid_8,
&ogs_gtp_tlv_desc_f_teid_9,
&ogs_gtp_tlv_desc_f_teid_10,
&ogs_gtp_tlv_desc_f_teid_11,
&ogs_gtp_tlv_desc_ran_nas_cause_0,
&ogs_gtp_tlv_desc_apco_0,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_ti_0,
&ogs_gtp_tlv_desc_packet_flow_id_0,
NULL,
}
};
ogs_tlv_desc_t ogs_gtp_tlv_desc_pdn_connection_0 =
{
OGS_TLV_COMPOUND,
@ -2911,16 +2560,7 @@ ogs_tlv_desc_t ogs_gtp_tlv_desc_create_indirect_data_forwarding_tunnel_request =
&ogs_gtp_tlv_desc_indication_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_bearer_context_0,
&ogs_gtp_tlv_desc_bearer_context_1,
&ogs_gtp_tlv_desc_bearer_context_2,
&ogs_gtp_tlv_desc_bearer_context_3,
&ogs_gtp_tlv_desc_bearer_context_4,
&ogs_gtp_tlv_desc_bearer_context_5,
&ogs_gtp_tlv_desc_bearer_context_6,
&ogs_gtp_tlv_desc_bearer_context_7,
&ogs_gtp_tlv_desc_bearer_context_8,
&ogs_gtp_tlv_desc_bearer_context_9,
&ogs_gtp_tlv_desc_bearer_context_10,
&ogs_tlv_desc_more8,
&ogs_gtp_tlv_desc_recovery_0,
NULL,
}};
@ -2933,16 +2573,7 @@ ogs_tlv_desc_t ogs_gtp_tlv_desc_create_indirect_data_forwarding_tunnel_response
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_bearer_context_0,
&ogs_gtp_tlv_desc_bearer_context_1,
&ogs_gtp_tlv_desc_bearer_context_2,
&ogs_gtp_tlv_desc_bearer_context_3,
&ogs_gtp_tlv_desc_bearer_context_4,
&ogs_gtp_tlv_desc_bearer_context_5,
&ogs_gtp_tlv_desc_bearer_context_6,
&ogs_gtp_tlv_desc_bearer_context_7,
&ogs_gtp_tlv_desc_bearer_context_8,
&ogs_gtp_tlv_desc_bearer_context_9,
&ogs_gtp_tlv_desc_bearer_context_10,
&ogs_tlv_desc_more8,
&ogs_gtp_tlv_desc_recovery_0,
NULL,
}};

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2020-06-30 21:17:14.929915 by acetcom
* Created on: 2020-07-08 16:42:53.173072 by acetcom
* from 29274-g30.docx
******************************************************************************/
@ -432,15 +432,6 @@ extern ogs_tlv_desc_t ogs_gtp_tlv_desc_remote_ue_context_0;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_v2x_context_0;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_0;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_1;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_2;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_3;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_4;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_5;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_6;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_7;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_8;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_9;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_context_10;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_pdn_connection_0;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_overload_control_information_0;
extern ogs_tlv_desc_t ogs_gtp_tlv_desc_overload_control_information_1;
@ -1167,34 +1158,14 @@ typedef struct ogs_gtp_create_indirect_data_forwarding_tunnel_request_s {
ogs_gtp_tlv_mei_t me_identity;
ogs_gtp_tlv_indication_t indication_flags;
ogs_gtp_tlv_f_teid_t sender_f_teid_for_control_plane;
ogs_gtp_tlv_bearer_context_t bearer_context_0;
ogs_gtp_tlv_bearer_context_t bearer_context_1;
ogs_gtp_tlv_bearer_context_t bearer_context_2;
ogs_gtp_tlv_bearer_context_t bearer_context_3;
ogs_gtp_tlv_bearer_context_t bearer_context_4;
ogs_gtp_tlv_bearer_context_t bearer_context_5;
ogs_gtp_tlv_bearer_context_t bearer_context_6;
ogs_gtp_tlv_bearer_context_t bearer_context_7;
ogs_gtp_tlv_bearer_context_t bearer_context_8;
ogs_gtp_tlv_bearer_context_t bearer_context_9;
ogs_gtp_tlv_bearer_context_t bearer_context_10;
ogs_gtp_tlv_bearer_context_t bearer_contexts[8];
ogs_gtp_tlv_recovery_t recovery;
} ogs_gtp_create_indirect_data_forwarding_tunnel_request_t;
typedef struct ogs_gtp_create_indirect_data_forwarding_tunnel_response_s {
ogs_gtp_tlv_cause_t cause;
ogs_gtp_tlv_f_teid_t sender_f_teid_for_control_plane;
ogs_gtp_tlv_bearer_context_t bearer_context_0;
ogs_gtp_tlv_bearer_context_t bearer_context_1;
ogs_gtp_tlv_bearer_context_t bearer_context_2;
ogs_gtp_tlv_bearer_context_t bearer_context_3;
ogs_gtp_tlv_bearer_context_t bearer_context_4;
ogs_gtp_tlv_bearer_context_t bearer_context_5;
ogs_gtp_tlv_bearer_context_t bearer_context_6;
ogs_gtp_tlv_bearer_context_t bearer_context_7;
ogs_gtp_tlv_bearer_context_t bearer_context_8;
ogs_gtp_tlv_bearer_context_t bearer_context_9;
ogs_gtp_tlv_bearer_context_t bearer_context_10;
ogs_gtp_tlv_bearer_context_t bearer_contexts[8];
ogs_gtp_tlv_recovery_t recovery;
} ogs_gtp_create_indirect_data_forwarding_tunnel_response_t;

Binary file not shown.

View File

@ -3,16 +3,6 @@ ies.append({ "ie_type" : "IMSI", "ie_value" : "IMSI", "presence" : "C", "instanc
ies.append({ "ie_type" : "MEI", "ie_value" : "ME Identity", "presence" : "C", "instance" : "0", "comment" : "This IE shall be included by the MME/SGSN if the SGW that the MME/SGSN selects for indirect data forwarding is different from the SGW already in use for the UE as the anchor point and if one of the following condition is satisfied:- If the UE is emergency or RLOS attached and the UE is UICCless; or- If the UE is emergency or RLOS attached and the IMSI is not authenticated"})
ies.append({ "ie_type" : "Indication", "ie_value" : "Indication Flags", "presence" : "CO", "instance" : "0", "comment" : "This IE shall be included if any one of the applicable flags is set to 1.Applicable flags are:Unauthenticated IMSI: This flag shall be set to 1 if the IMSI present in the message is not authenticated and is for an emergency or RLOS attached UE."})
ies.append({ "ie_type" : "F-TEID", "ie_value" : "Sender F-TEID for Control Plane", "presence" : "C", "instance" : "0", "comment" : "This IE shall be included by the MME/SGSN if the SGW that the MME/SGSN selects for indirect data forwarding is different from the SGW already in use for the UE as the anchor point.See NOTE1."})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 0", "presence" : "M", "instance" : "0", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 1", "presence" : "O", "instance" : "1", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 2", "presence" : "O", "instance" : "2", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 3", "presence" : "O", "instance" : "3", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 4", "presence" : "O", "instance" : "4", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 5", "presence" : "O", "instance" : "5", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 6", "presence" : "O", "instance" : "6", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 7", "presence" : "O", "instance" : "7", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 8", "presence" : "O", "instance" : "8", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 9", "presence" : "O", "instance" : "9", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 10", "presence" : "O", "instance" : "10", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Contexts", "presence" : "M", "instance" : "0", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Recovery", "ie_value" : "Recovery", "presence" : "CO", "instance" : "0", "comment" : "This IE shall be included if contacting the peer for the first time."})
msg_list[key]["ies"] = ies

View File

@ -1,25 +1,6 @@
ies = []
ies.append({ "ie_type" : "Cause", "ie_value" : "Cause", "presence" : "M", "instance" : "0", "comment" : ""})
ies.append({ "ie_type" : "F-TEID", "ie_value" : "Sender F-TEID for Control Plane", "presence" : "C", "instance" : "0", "comment" : "This IE shall be included by an SGW if the SGW receives a Sender F-TEID for Control Plane IE from an MME/SGSN in a Create Indirect Data Forwarding Tunnel Request message.See also NOTE 1 in Table 7.2.18-1."})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 0", "presence" : "M", "instance" : "0", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 1", "presence" : "O", "instance" : "1", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "2"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 2", "presence" : "O", "instance" : "2", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "3"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 3", "presence" : "O", "instance" : "3", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "4"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 4", "presence" : "O", "instance" : "4", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "5"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 5", "presence" : "O", "instance" : "5", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "6"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 6", "presence" : "O", "instance" : "6", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "7"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 7", "presence" : "O", "instance" : "7", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "8"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 8", "presence" : "O", "instance" : "8", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "9"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 9", "presence" : "O", "instance" : "9", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
type_list["Bearer Context"]["max_instance"] = "10"
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Context 10", "presence" : "O", "instance" : "10", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Bearer Context", "ie_value" : "Bearer Contexts", "presence" : "M", "instance" : "0", "comment" : "Several IEs with this type and instance value may be included as necessary to represent a list of Bearers"})
ies.append({ "ie_type" : "Recovery", "ie_value" : "Recovery", "presence" : "CO", "instance" : "0", "comment" : "This IE shall be included if contacting the peer for the first time"})
msg_list[key]["ies"] = ies

View File

@ -527,8 +527,12 @@ for (k, v) in sorted_msg_list:
if "ies" in msg_list[k]:
f.write("typedef struct ogs_gtp_" + v_lower(k) + "_s {\n")
for ies in msg_list[k]["ies"]:
f.write(" ogs_gtp_tlv_" + v_lower(ies["ie_type"]) + "_t " + \
v_lower(ies["ie_value"]) + ";\n")
if (k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts':
f.write(" ogs_gtp_tlv_" + v_lower(ies["ie_type"]) + "_t " + \
v_lower(ies["ie_value"]) + "[8];\n")
else:
f.write(" ogs_gtp_tlv_" + v_lower(ies["ie_type"]) + "_t " + \
v_lower(ies["ie_value"]) + ";\n")
f.write("} ogs_gtp_" + v_lower(k) + "_t;\n")
f.write("\n")
@ -613,7 +617,9 @@ for (k, v) in sorted_msg_list:
f.write(" \"%s\",\n" % k)
f.write(" 0, 0, 0, 0, {\n")
for ies in msg_list[k]["ies"]:
f.write(" &ogs_gtp_tlv_desc_%s_%s,\n" % (v_lower(ies["ie_type"]), v_lower(ies["instance"])))
f.write(" &ogs_gtp_tlv_desc_%s_%s,\n" % (v_lower(ies["ie_type"]), v_lower(ies["instance"])))
if (k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts':
f.write(" &ogs_tlv_desc_more8,\n")
f.write(" NULL,\n")
f.write("}};\n\n")
f.write("\n")

View File

@ -30,6 +30,8 @@ extern "C" {
#define OGS_GTPV1U_EXTENSION_HEADER_LEN 4
#define OGS_GTP_MAX_INDIRECT_TUNNEL 8
typedef struct ogs_gtp_extension_header_s {
#define OGS_GTP_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER 0x85
#define OGS_GTP_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS 0x0
@ -412,10 +414,10 @@ int16_t ogs_gtp_build_uli(ogs_tlv_octet_t *octet,
#define OGS_GTP_F_TEID_S11_MME_GTP_U 38
#define OGS_GTP_F_TEID_S11_SGW_GTP_U 39
#define OGS_GTP_F_TEID_HDR_LEN 5
#define OGS_GTP_F_TEID_IPV4_LEN OGS_IPV4_LEN+OGS_GTP_F_TEID_HDR_LEN
#define OGS_GTP_F_TEID_IPV6_LEN OGS_IPV6_LEN+OGS_GTP_F_TEID_HDR_LEN
#define OGS_GTP_F_TEID_IPV4V6_LEN OGS_IPV4V6_LEN+OGS_GTP_F_TEID_HDR_LEN
#define OGS_GTP_F_TEID_HDR_LEN 5
#define OGS_GTP_F_TEID_IPV4_LEN OGS_IPV4_LEN+OGS_GTP_F_TEID_HDR_LEN
#define OGS_GTP_F_TEID_IPV6_LEN OGS_IPV6_LEN+OGS_GTP_F_TEID_HDR_LEN
#define OGS_GTP_F_TEID_IPV4V6_LEN OGS_IPV4V6_LEN+OGS_GTP_F_TEID_HDR_LEN
typedef struct ogs_gtp_f_teid_s {
ED3(uint8_t ipv4:1;,
uint8_t ipv6:1;,
@ -477,4 +479,3 @@ ED2(uint8_t spare:6;,
#endif
#endif /* OGS_GTP_TYPES_H */

View File

@ -380,7 +380,7 @@ typedef uint8_t ogs_nas_time_zone_t;
* See subclause 10.5.3.9 in 3GPP TS 24.008 [13].
* 9.2.3.11 TPServiceCentreTimeStamp (TPSCTS) in 3GPP TS 23.040 [90]
* O TV 8 */
#define OGS_OGS_NAS_TIME_TO_BCD(x) OGS_TIME_TO_BCD(x)
#define OGS_NAS_TIME_TO_BCD(x) OGS_TIME_TO_BCD(x)
typedef struct ogs_nas_time_zone_and_time_s {
uint8_t year;
uint8_t mon;
@ -393,7 +393,7 @@ typedef struct ogs_nas_time_zone_and_time_s {
* the first bit (bit 3 of the seventh octet of
* the TP-Service-Centre-Time-Stamp field) represents
* the algebraic sign of this difference (0: positive, 1: negative). */
uint8_t timezone;
uint8_t timezone;
} ogs_nas_time_zone_and_time_t;
/* 9.9.3.33 Tracking area identity list

View File

@ -242,22 +242,6 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
dev = ogs_yaml_iter_value(&pfcp_iter);
} else if (!strcmp(pfcp_key, "apn")) {
/* Skip */
} else if (!strcmp(pfcp_key, "upf_selection_mode")) {
ogs_assert(ogs_yaml_iter_type(&pfcp_iter) !=
YAML_SCALAR_NODE);
const char *upf_selection_mode = ogs_yaml_iter_value(&pfcp_iter);
if (!strcmp(upf_selection_mode, "rr"))
self.upf_selection_mode = UPF_SELECT_RR;
else if (!strcmp(upf_selection_mode, "tac"))
self.upf_selection_mode = UPF_SELECT_TAC;
else if (!strcmp(upf_selection_mode, "apn"))
self.upf_selection_mode = UPF_SELECT_APN;
else if (!strcmp(upf_selection_mode, "enb_id"))
self.upf_selection_mode = UPF_SELECT_ENB_ID;
else
ogs_warn("unknown upf_selection_mode `%s`",
upf_selection_mode);
} else
ogs_warn("unknown key `%s`", pfcp_key);
}
@ -453,10 +437,12 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
uint16_t port = self.pfcp_port;
uint16_t tac[OGS_MAX_NUM_OF_TAI] = {0,};
uint8_t num_of_tac = 0;
const char * apn[OGS_MAX_NUM_OF_APN];
const char *apn[OGS_MAX_NUM_OF_APN];
uint8_t num_of_apn = 0;
uint32_t enb_id[OGS_MAX_NUM_OF_ENB_ID] = {0,};
uint8_t num_of_enb_id = 0;
uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID] = {0,};
uint8_t num_of_e_cell_id = 0;
uint32_t nr_cell_id[OGS_MAX_NUM_OF_CELL_ID] = {0,};
uint8_t num_of_nr_cell_id = 0;
if (ogs_yaml_iter_type(&pfcp_array) ==
YAML_MAPPING_NODE) {
@ -537,7 +523,8 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
} while (
ogs_yaml_iter_type(&tac_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(pfcp_key, "apn")) {
} else if (!strcmp(pfcp_key, "apn") ||
!strcmp(pfcp_key, "dnn")) {
ogs_yaml_iter_t apn_iter;
ogs_yaml_iter_recurse(&pfcp_iter, &apn_iter);
ogs_assert(ogs_yaml_iter_type(&apn_iter) !=
@ -562,38 +549,62 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
} while (
ogs_yaml_iter_type(&apn_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(pfcp_key, "enb_id")) {
ogs_yaml_iter_t enb_id_iter;
ogs_yaml_iter_recurse(&pfcp_iter, &enb_id_iter);
ogs_assert(ogs_yaml_iter_type(&enb_id_iter) !=
YAML_MAPPING_NODE);
} else if (!strcmp(pfcp_key, "e_cell_id")) {
ogs_yaml_iter_t e_cell_id_iter;
ogs_yaml_iter_recurse(
&pfcp_iter, &e_cell_id_iter);
ogs_assert(ogs_yaml_iter_type(
&e_cell_id_iter) != YAML_MAPPING_NODE);
do {
const char *v = NULL;
ogs_assert(num_of_enb_id <=
ogs_assert(num_of_e_cell_id <=
OGS_MAX_NUM_OF_ENB_ID);
if (ogs_yaml_iter_type(&enb_id_iter) ==
if (ogs_yaml_iter_type(&e_cell_id_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&enb_id_iter))
if (!ogs_yaml_iter_next(
&e_cell_id_iter))
break;
}
v = ogs_yaml_iter_value(&enb_id_iter);
v = ogs_yaml_iter_value(&e_cell_id_iter);
if (v) {
if (strncmp(v,"0x",2)) {
// integer enb_id
enb_id[num_of_enb_id] = atoi(v);
} else {
// hex enb_id
enb_id[num_of_enb_id] = strtol(v, NULL, 16);
}
num_of_enb_id++;
e_cell_id[num_of_e_cell_id]
= ogs_uint28_from_string((char*)v);
num_of_e_cell_id++;
}
} while (
ogs_yaml_iter_type(&enb_id_iter) ==
ogs_yaml_iter_type(&e_cell_id_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(pfcp_key, "nr_cell_id")) {
ogs_yaml_iter_t nr_cell_id_iter;
ogs_yaml_iter_recurse(
&pfcp_iter, &nr_cell_id_iter);
ogs_assert(ogs_yaml_iter_type(
&nr_cell_id_iter) != YAML_MAPPING_NODE);
do {
const char *v = NULL;
ogs_assert(num_of_nr_cell_id <=
OGS_MAX_NUM_OF_ENB_ID);
if (ogs_yaml_iter_type(&nr_cell_id_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(
&nr_cell_id_iter))
break;
}
v = ogs_yaml_iter_value(&nr_cell_id_iter);
if (v) {
nr_cell_id[num_of_nr_cell_id]
= ogs_uint28_from_string((char*)v);
num_of_nr_cell_id++;
}
} while (
ogs_yaml_iter_type(&nr_cell_id_iter) ==
YAML_SEQUENCE_NODE);
} else
ogs_warn("unknown key `%s`", pfcp_key);
}
@ -622,10 +633,15 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
if (num_of_apn != 0)
memcpy(node->apn, apn, sizeof(node->apn));
node->num_of_enb_id = num_of_enb_id;
if (num_of_enb_id != 0)
memcpy(node->enb_id, enb_id, sizeof(node->enb_id));
node->num_of_e_cell_id = num_of_e_cell_id;
if (num_of_e_cell_id != 0)
memcpy(node->e_cell_id, e_cell_id,
sizeof(node->e_cell_id));
node->num_of_nr_cell_id = num_of_nr_cell_id;
if (num_of_nr_cell_id != 0)
memcpy(node->nr_cell_id, nr_cell_id,
sizeof(node->nr_cell_id));
} while (ogs_yaml_iter_type(&pfcp_array) ==
YAML_SEQUENCE_NODE);
}

View File

@ -33,13 +33,6 @@ extern "C" {
typedef struct ogs_pfcp_node_s ogs_pfcp_node_t;
typedef enum {
UPF_SELECT_RR = 0, /* Default UPF Selection Method */
UPF_SELECT_TAC, /* Select UPF by enb_tac */
UPF_SELECT_APN, /* Select UPF by UE's APN */
UPF_SELECT_ENB_ID, /* Select UPF by enb_id */
} upf_select_e;
typedef struct ogs_pfcp_context_s {
uint32_t pfcp_port; /* PFCP local port */
const char *tun_ifname; /* PFCP TUN Interface Name */
@ -54,8 +47,7 @@ typedef struct ogs_pfcp_context_s {
uint32_t pfcp_started; /* UTC time when the PFCP entity started */
ogs_list_t n4_list; /* PFCP Node List */
upf_select_e upf_selection_mode; /* Selection algorithm for selecting UPF */
ogs_pfcp_node_t *node; /* Iterator for Peer round-robin */
ogs_pfcp_node_t *node; /* Iterator for Peer round-robin */
ogs_list_t dev_list; /* Tun Device List */
ogs_list_t subnet_list; /* UE Subnet List */
@ -89,8 +81,10 @@ typedef struct ogs_pfcp_node_s {
uint8_t num_of_tac;
const char* apn[OGS_MAX_APN_LEN];
uint8_t num_of_apn;
uint32_t enb_id[OGS_MAX_NUM_OF_ENB_ID];
uint8_t num_of_enb_id;
uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID];
uint8_t num_of_e_cell_id;
uint32_t nr_cell_id[OGS_MAX_NUM_OF_CELL_ID];
uint8_t num_of_nr_cell_id;
ogs_list_t gtpu_resource_list; /* User Plane IP Resource Information */
} ogs_pfcp_node_t;

View File

@ -52,6 +52,7 @@ typedef struct connection_s {
char error[CURL_ERROR_SIZE];
ogs_sbi_client_t *client;
ogs_sbi_client_cb_f client_cb;
} connection_t;
static OGS_POOL(client_pool, ogs_sbi_client_t);
@ -227,7 +228,8 @@ static char *add_params_to_uri(CURL *easy, char *uri, ogs_hash_t *params)
return uri;
}
static connection_t *connection_add(ogs_sbi_client_t *client,
static connection_t *connection_add(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data)
{
ogs_hash_index_t *hi;
@ -236,13 +238,18 @@ static connection_t *connection_add(ogs_sbi_client_t *client,
CURLMcode rc;
ogs_assert(client);
ogs_assert(client_cb);
ogs_assert(request);
ogs_assert(request->h.method);
ogs_pool_alloc(&connection_pool, &conn);
ogs_assert(conn);
memset(conn, 0, sizeof(connection_t));
ogs_assert(request->h.method);
conn->client = client;
conn->client_cb = client_cb;
conn->data = data;
conn->method = ogs_strdup(request->h.method);
conn->num_of_header = ogs_hash_count(request->http.headers);
@ -265,6 +272,8 @@ static connection_t *connection_add(ogs_sbi_client_t *client,
ogs_sbi_self()->timer_mgr, connection_timer_expired, conn);
ogs_assert(conn->timer);
ogs_list_add(&client->connection_list, conn);
/* If http response is not received within 1 second,
* we will discard this request. */
ogs_timer_start(conn->timer, ogs_time_from_sec(1));
@ -314,11 +323,6 @@ static connection_t *connection_add(ogs_sbi_client_t *client,
rc = curl_multi_add_handle(client->multi, conn->easy);
mcode_or_die("connection_add: curl_multi_add_handle", rc);
conn->client = client;
conn->data = data;
ogs_list_add(&client->connection_list, conn);
return conn;
}
@ -435,13 +439,8 @@ static void check_multi_info(ogs_sbi_client_t *client)
ogs_sbi_header_set(response->http.headers,
OGS_SBI_LOCATION, conn->location);
if (client->cb)
client->cb(response, conn->data);
else {
ogs_fatal("client callback is not registered");
ogs_sbi_response_free(response);
ogs_assert_if_reached();
}
ogs_assert(conn->client_cb);
conn->client_cb(response, conn->data);
} else
ogs_warn("[%d] %s", res, conn->error);
@ -455,7 +454,8 @@ static void check_multi_info(ogs_sbi_client_t *client)
}
void ogs_sbi_client_send_request(
ogs_sbi_client_t *client, ogs_sbi_request_t *request, void *data)
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data)
{
connection_t *conn = NULL;
@ -465,52 +465,12 @@ void ogs_sbi_client_send_request(
if (request->h.uri == NULL) {
request->h.uri = ogs_sbi_client_uri(client, &request->h);
}
ogs_debug("[%s] %s", request->h.method, request->h.uri);
conn = connection_add(client, request, data);
conn = connection_add(client, client_cb, request, data);
ogs_assert(conn);
}
void ogs_sbi_client_send_request_to_nf_instance(
ogs_sbi_nf_instance_t *nf_instance,
ogs_sbi_request_t *request, void *data)
{
ogs_sbi_client_t *client = NULL;
ogs_assert(request);
ogs_assert(nf_instance);
if (request->h.uri == NULL) {
client = ogs_sbi_client_find_by_service_name(nf_instance,
request->h.service.name, request->h.api.version);
if (!client) {
ogs_error("[%s] Cannot find client [%s:%s]",
nf_instance->id,
request->h.service.name, request->h.api.version);
return;
}
} else {
ogs_sockaddr_t *addr = NULL;
char buf[OGS_ADDRSTRLEN];
addr = ogs_sbi_getaddr_from_uri(request->h.uri);
if (!addr) {
ogs_error("[%s] Invalid confirmation URL [%s]",
nf_instance->id, request->h.uri);
return;
}
client = ogs_sbi_client_find(addr);
if (!client) {
ogs_error("[%s] Cannot find client [%s:%d]", nf_instance->id,
OGS_ADDR(addr, buf), OGS_PORT(addr));
ogs_freeaddrinfo(addr);
return;
}
ogs_freeaddrinfo(addr);
}
ogs_sbi_client_send_request(client, request, data);
}
static size_t write_cb(void *contents, size_t size, size_t nmemb, void *data)
{
size_t realsize = 0;

View File

@ -36,6 +36,9 @@ extern "C" {
__pCLIENT->reference_count++; \
(__cTX)->client = __pCLIENT; \
} while(0)
typedef int (*ogs_sbi_client_cb_f)(ogs_sbi_response_t *response, void *data);
typedef struct ogs_sbi_client_s {
ogs_lnode_t lnode;
@ -46,7 +49,7 @@ typedef struct ogs_sbi_client_s {
const char *pem;
} tls;
int (*cb)(ogs_sbi_response_t *response, void *data);
ogs_sbi_client_cb_f cb; /* Only used when NF send to NRF */
ogs_timer_t *t_curl; /* timer for CURL */
ogs_list_t connection_list; /* CURL connection list */
@ -67,9 +70,7 @@ void ogs_sbi_client_remove(ogs_sbi_client_t *client);
ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr);
void ogs_sbi_client_send_request(
ogs_sbi_client_t *client, ogs_sbi_request_t *request, void *data);
void ogs_sbi_client_send_request_to_nf_instance(
ogs_sbi_nf_instance_t *nf_instance,
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data);
#ifdef __cplusplus

View File

@ -121,6 +121,8 @@ typedef struct ogs_sbi_object_s {
ogs_sbi_session_t *session;
void *nf_state_registered;
ogs_sbi_client_cb_f client_cb;
} ogs_sbi_object_t;
typedef struct ogs_sbi_nf_service_s {

View File

@ -230,3 +230,303 @@ uint64_t ogs_sbi_bitrate_from_string(char *str)
END
return bitrate;
}
#define MAX_TIMESTR_LEN 128
char *ogs_sbi_localtime_string(ogs_time_t timestamp)
{
struct tm tm;
char datetime[MAX_TIMESTR_LEN];
char timezone[MAX_TIMESTR_LEN];
ogs_localtime(ogs_time_sec(timestamp), &tm);
ogs_strftime(datetime, sizeof datetime, "%Y-%m-%dT%H:%M:%S", &tm);
ogs_strftime(timezone, sizeof timezone, "%z", &tm);
return ogs_msprintf("%s.%06lld%s",
datetime, (long long)ogs_time_usec(timestamp), timezone);
}
char *ogs_sbi_gmtime_string(ogs_time_t timestamp)
{
struct tm tm;
char datetime[MAX_TIMESTR_LEN];
ogs_gmtime(ogs_time_sec(timestamp), &tm);
ogs_strftime(datetime, sizeof datetime, "%Y-%m-%dT%H:%M:%S", &tm);
return ogs_msprintf("%s.%06lldZ",
datetime, (long long)ogs_time_usec(timestamp));
}
char *ogs_sbi_timezone_string(int tm_gmtoff)
{
struct tm tm;
char timezone[MAX_TIMESTR_LEN];
memset(&tm, 0, sizeof(tm));
tm.tm_gmtoff = tm_gmtoff;
ogs_strftime(timezone, sizeof timezone, "%z", &tm);
return ogs_msprintf("%s", timezone);
}
bool ogs_sbi_time_from_string(ogs_time_t *timestamp, char *str)
{
int rv, i, j, k;
struct tm tm;
bool is_seconds;
char seconds[MAX_TIMESTR_LEN];
char subsecs[MAX_TIMESTR_LEN];
ogs_time_t usecs;
ogs_assert(str);
ogs_assert(timestamp);
memset(seconds, 0, sizeof seconds);
memset(subsecs, 0, sizeof subsecs);
is_seconds = true;
i = 0; j = 0, k = 0;
while(str[i]) {
if (is_seconds == true && str[i] == '.')
is_seconds = false;
else if (is_seconds == false && (str[i] < '0' || str[i] > '9'))
is_seconds = true;
if (is_seconds == true) seconds[j++] = str[i];
else subsecs[k++] = str[i];
i++;
}
memset(&tm, 0, sizeof(tm));
ogs_strptime(seconds, "%Y-%m-%dT%H:%M:%S%z", &tm);
usecs = (ogs_time_t)(atof(subsecs) * 1000000);
rv = ogs_time_from_gmt(timestamp, &tm, usecs);
if (rv != OGS_OK) {
ogs_error("Cannot convert time [%s]", str);
return false;
}
return true;
}
OpenAPI_plmn_id_t *ogs_sbi_build_plmn_id(ogs_plmn_id_t *plmn_id)
{
OpenAPI_plmn_id_t *PlmnId = NULL;
ogs_assert(plmn_id);
PlmnId = ogs_calloc(1, sizeof(*PlmnId));
ogs_assert(PlmnId);
PlmnId->mcc = ogs_plmn_id_mcc_string(plmn_id);
ogs_assert(PlmnId->mcc);
PlmnId->mnc = ogs_plmn_id_mnc_string(plmn_id);
ogs_assert(PlmnId->mnc);
return PlmnId;
}
bool ogs_sbi_parse_plmn_id(
ogs_plmn_id_t *plmn_id, OpenAPI_plmn_id_t *PlmnId)
{
ogs_assert(plmn_id);
ogs_assert(PlmnId);
ogs_assert(PlmnId->mcc);
ogs_assert(PlmnId->mnc);
ogs_plmn_id_build(plmn_id,
atoi(PlmnId->mcc), atoi(PlmnId->mnc), strlen(PlmnId->mnc));
return true;
}
void ogs_sbi_free_plmn_id(OpenAPI_plmn_id_t *PlmnId)
{
ogs_assert(PlmnId);
if (PlmnId->mcc)
ogs_free(PlmnId->mcc);
if (PlmnId->mnc)
ogs_free(PlmnId->mnc);
ogs_free(PlmnId);
}
OpenAPI_plmn_id_nid_t *ogs_sbi_build_plmn_id_nid(ogs_plmn_id_t *plmn_id)
{
OpenAPI_plmn_id_nid_t *PlmnIdNid = NULL;
ogs_assert(plmn_id);
PlmnIdNid = ogs_calloc(1, sizeof(*PlmnIdNid));
ogs_assert(PlmnIdNid);
PlmnIdNid->mcc = ogs_plmn_id_mcc_string(plmn_id);
ogs_assert(PlmnIdNid->mcc);
PlmnIdNid->mnc = ogs_plmn_id_mnc_string(plmn_id);
ogs_assert(PlmnIdNid->mnc);
return PlmnIdNid;
}
bool ogs_sbi_parse_plmn_id_nid(
ogs_plmn_id_t *plmn_id, OpenAPI_plmn_id_nid_t *PlmnIdNid)
{
ogs_assert(plmn_id);
ogs_assert(PlmnIdNid);
ogs_assert(PlmnIdNid->mcc);
ogs_assert(PlmnIdNid->mnc);
ogs_plmn_id_build(plmn_id,
atoi(PlmnIdNid->mcc), atoi(PlmnIdNid->mnc), strlen(PlmnIdNid->mnc));
return true;
}
void ogs_sbi_free_plmn_id_nid(OpenAPI_plmn_id_nid_t *PlmnIdNid)
{
ogs_assert(PlmnIdNid);
if (PlmnIdNid->mcc)
ogs_free(PlmnIdNid->mcc);
if (PlmnIdNid->mnc)
ogs_free(PlmnIdNid->mnc);
if (PlmnIdNid->nid)
ogs_free(PlmnIdNid->nid);
ogs_free(PlmnIdNid);
}
OpenAPI_guami_t *ogs_sbi_build_guami(ogs_guami_t *guami)
{
OpenAPI_guami_t *Guami = NULL;
ogs_assert(guami);
Guami = ogs_calloc(1, sizeof(*Guami));
ogs_assert(Guami);
Guami->plmn_id = ogs_sbi_build_plmn_id(&guami->plmn_id);
ogs_assert(Guami->plmn_id);
Guami->amf_id = ogs_amf_id_to_string(&guami->amf_id);
ogs_assert(Guami->amf_id);
return Guami;
}
bool ogs_sbi_parse_guami(ogs_guami_t *guami, OpenAPI_guami_t *Guami)
{
ogs_assert(guami);
ogs_assert(Guami);
ogs_assert(Guami->amf_id);
ogs_assert(Guami->plmn_id);
ogs_amf_id_from_string(&guami->amf_id, Guami->amf_id);
ogs_sbi_parse_plmn_id(&guami->plmn_id, Guami->plmn_id);
return true;
}
void ogs_sbi_free_guami(OpenAPI_guami_t *Guami)
{
ogs_assert(Guami);
if (Guami->plmn_id)
ogs_sbi_free_plmn_id(Guami->plmn_id);
if (Guami->amf_id)
ogs_free(Guami->amf_id);
ogs_free(Guami);
}
OpenAPI_nr_location_t *ogs_sbi_build_nr_location(
ogs_5gs_tai_t *tai, ogs_nr_cgi_t *nr_cgi)
{
OpenAPI_nr_location_t *NrLocation = NULL;
OpenAPI_tai_t *Tai = NULL;
OpenAPI_ncgi_t *Ncgi = NULL;
ogs_assert(tai);
ogs_assert(nr_cgi);
Tai = ogs_calloc(1, sizeof(*Tai));
ogs_assert(Tai);
Tai->plmn_id = ogs_sbi_build_plmn_id(&tai->plmn_id);
Tai->tac = ogs_uint24_to_string(tai->tac);
Ncgi = ogs_calloc(1, sizeof(*Ncgi));
ogs_assert(Ncgi);
Ncgi->plmn_id = ogs_sbi_build_plmn_id(&nr_cgi->plmn_id);
Ncgi->nr_cell_id = ogs_uint36_to_string(nr_cgi->cell_id);
NrLocation = ogs_calloc(1, sizeof(*NrLocation));
ogs_assert(NrLocation);
NrLocation->tai = Tai;
NrLocation->ncgi = Ncgi;
return NrLocation;
}
bool ogs_sbi_parse_nr_location(ogs_5gs_tai_t *tai, ogs_nr_cgi_t *nr_cgi,
OpenAPI_nr_location_t *NrLocation)
{
OpenAPI_tai_t *Tai = NULL;
OpenAPI_ncgi_t *Ncgi = NULL;
ogs_assert(tai);
ogs_assert(nr_cgi);
ogs_assert(NrLocation);
Tai = NrLocation->tai;
if (Tai) {
if (Tai->plmn_id)
ogs_sbi_parse_plmn_id(&tai->plmn_id, Tai->plmn_id);
if (Tai->tac)
tai->tac = ogs_uint24_from_string(Tai->tac);
}
Ncgi = NrLocation->ncgi;
if (Ncgi) {
if (Ncgi->plmn_id)
ogs_sbi_parse_plmn_id(&nr_cgi->plmn_id, Ncgi->plmn_id);
if (Ncgi->nr_cell_id)
nr_cgi->cell_id = ogs_uint36_from_string(Ncgi->nr_cell_id);
}
return true;
}
void ogs_sbi_free_nr_location(OpenAPI_nr_location_t *NrLocation)
{
OpenAPI_tai_t *Tai = NULL;
OpenAPI_ncgi_t *Ncgi = NULL;
ogs_assert(NrLocation);
Tai = NrLocation->tai;
if (Tai) {
if (Tai->plmn_id)
ogs_sbi_free_plmn_id(Tai->plmn_id);
if (Tai->tac)
ogs_free(Tai->tac);
ogs_free(Tai);
}
Ncgi = NrLocation->ncgi;
if (Ncgi) {
if (Ncgi->plmn_id)
ogs_sbi_free_plmn_id(Ncgi->plmn_id);
if (Ncgi->nr_cell_id)
ogs_free(Ncgi->nr_cell_id);
ogs_free(Ncgi);
}
ogs_free(NrLocation);
}

View File

@ -46,6 +46,31 @@ ogs_sockaddr_t *ogs_sbi_getaddr_from_uri(char *uri);
char *ogs_sbi_bitrate_to_string(uint64_t bitrate, int unit);
uint64_t ogs_sbi_bitrate_from_string(char *str);
char *ogs_sbi_localtime_string(ogs_time_t time);
char *ogs_sbi_gmtime_string(ogs_time_t time);
char *ogs_sbi_timezone_string(int tm_offset);
bool ogs_sbi_time_from_string(ogs_time_t *time, char *str);
OpenAPI_plmn_id_t *ogs_sbi_build_plmn_id(ogs_plmn_id_t *plmn_id);
bool ogs_sbi_parse_plmn_id(
ogs_plmn_id_t *plmn_id, OpenAPI_plmn_id_t *PlmnId);
void ogs_sbi_free_plmn_id(OpenAPI_plmn_id_t *PlmnId);
OpenAPI_plmn_id_nid_t *ogs_sbi_build_plmn_id_nid(ogs_plmn_id_t *plmn_id);
bool ogs_sbi_parse_plmn_id_nid(
ogs_plmn_id_t *plmn_id, OpenAPI_plmn_id_nid_t *PlmnIdNid);
void ogs_sbi_free_plmn_id_nid(OpenAPI_plmn_id_nid_t *PlmnIdNid);
OpenAPI_guami_t *ogs_sbi_build_guami(ogs_guami_t *guami);
bool ogs_sbi_parse_guami(ogs_guami_t *guami, OpenAPI_guami_t *Guami);
void ogs_sbi_free_guami(OpenAPI_guami_t *Guami);
OpenAPI_nr_location_t *ogs_sbi_build_nr_location(
ogs_5gs_tai_t *tai, ogs_nr_cgi_t *nr_cgi);
bool ogs_sbi_parse_nr_location(ogs_5gs_tai_t *tai, ogs_nr_cgi_t *nr_cgi,
OpenAPI_nr_location_t *NrLocation);
void ogs_sbi_free_nr_location(OpenAPI_nr_location_t *NrLocation);
#ifdef __cplusplus
}
#endif

View File

@ -31,6 +31,7 @@ libsbi_sources = files('''
nnrf-build.c
nnrf-handler.c
path.c
'''.split())

View File

@ -524,6 +524,7 @@ int ogs_sbi_parse_header(
message->h.method = header->method;
message->h.uri = header->uri;
ogs_assert(message->h.uri);
ogs_debug("[%s] %s", message->h.method, message->h.uri);
uri = ogs_strdup(header->uri);
ogs_assert(uri);
@ -721,6 +722,7 @@ static char *build_json(ogs_sbi_message_t *message)
if (item) {
content = cJSON_Print(item);
ogs_assert(content);
ogs_log_print(OGS_LOG_TRACE, "%s", content);
cJSON_Delete(item);
}
@ -738,6 +740,7 @@ static int parse_json(ogs_sbi_message_t *message,
if (!json)
return OGS_OK;
ogs_log_print(OGS_LOG_TRACE, "%s", json);
item = cJSON_Parse(json);
if (!item) {
ogs_error("JSON parse error");

View File

@ -77,6 +77,7 @@
#include "sbi/nnrf-build.h"
#include "sbi/nnrf-handler.h"
#include "sbi/path.h"
#undef OGS_SBI_INSIDE

View File

@ -60,22 +60,52 @@ static ogs_sbi_nf_instance_t *find_or_discover_nf_instance(
}
void ogs_sbi_send(
ogs_sbi_object_t *sbi_object, ogs_sbi_nf_instance_t *nf_instance)
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_object_t *sbi_object)
{
ogs_sbi_request_t *request = NULL;
ogs_sbi_client_t *client = NULL;
ogs_assert(sbi_object);
request = sbi_object->request;
ogs_assert(request);
ogs_assert(sbi_object->client_wait.duration);
ogs_assert(sbi_object->client_cb);
ogs_assert(nf_instance);
if (request->h.uri == NULL) {
client = ogs_sbi_client_find_by_service_name(nf_instance,
request->h.service.name, request->h.api.version);
if (!client) {
ogs_error("[%s] Cannot find client [%s:%s]",
nf_instance->id,
request->h.service.name, request->h.api.version);
return;
}
} else {
ogs_sockaddr_t *addr = NULL;
char buf[OGS_ADDRSTRLEN];
addr = ogs_sbi_getaddr_from_uri(request->h.uri);
if (!addr) {
ogs_error("[%s] Invalid URL [%s]", nf_instance->id, request->h.uri);
return;
}
client = ogs_sbi_client_find(addr);
if (!client) {
ogs_error("[%s] Cannot find client [%s:%d]", nf_instance->id,
OGS_ADDR(addr, buf), OGS_PORT(addr));
ogs_freeaddrinfo(addr);
return;
}
ogs_freeaddrinfo(addr);
}
ogs_timer_start(sbi_object->client_wait.timer,
sbi_object->client_wait.duration);
ogs_sbi_client_send_request_to_nf_instance(
nf_instance, sbi_object->request, sbi_object);
ogs_sbi_client_send_request(
client, sbi_object->client_cb, request, sbi_object);
}
bool ogs_sbi_discover_and_send(
@ -102,7 +132,7 @@ bool ogs_sbi_discover_and_send(
if (nrf == false && nf == false) return false;
if (!nf_instance) return true;
ogs_sbi_send(sbi_object, nf_instance);
ogs_sbi_send(nf_instance, sbi_object);
return true;
}
@ -118,7 +148,7 @@ void ogs_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance)
request = ogs_nnrf_nfm_build_register(nf_instance);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, nf_instance);
ogs_sbi_client_send_request(client, client->cb, request, nf_instance);
ogs_sbi_request_free(request);
}
@ -133,7 +163,7 @@ void ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance)
request = ogs_nnrf_nfm_build_update(nf_instance);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, nf_instance);
ogs_sbi_client_send_request(client, client->cb, request, nf_instance);
ogs_sbi_request_free(request);
}
@ -148,7 +178,7 @@ void ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance)
request = ogs_nnrf_nfm_build_de_register(nf_instance);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, nf_instance);
ogs_sbi_client_send_request(client, client->cb, request, nf_instance);
ogs_sbi_request_free(request);
}
@ -170,7 +200,7 @@ void ogs_nnrf_nfm_send_nf_status_subscribe(ogs_sbi_client_t *client,
request = ogs_nnrf_nfm_build_status_subscribe(subscription);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, subscription);
ogs_sbi_client_send_request(client, client->cb, request, subscription);
ogs_sbi_request_free(request);
}
@ -186,7 +216,7 @@ void ogs_nnrf_nfm_send_nf_status_unsubscribe(
request = ogs_nnrf_nfm_build_status_unsubscribe(subscription);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, subscription);
ogs_sbi_client_send_request(client, client->cb, request, subscription);
ogs_sbi_request_free(request);
}
@ -204,6 +234,6 @@ void ogs_nnrf_disc_send_nf_discover(ogs_sbi_nf_instance_t *nf_instance,
request = ogs_nnrf_disc_build_discover(
target_nf_type, nf_instance->nf_type);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, data);
ogs_sbi_client_send_request(client, client->cb, request, data);
ogs_sbi_request_free(request);
}

View File

@ -30,7 +30,7 @@ typedef ogs_sbi_request_t *(*ogs_sbi_build_f)(
ogs_sbi_object_t *sbi_object, void *data);
void ogs_sbi_send(
ogs_sbi_object_t *sbi_object, ogs_sbi_nf_instance_t *nf_instance);
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_object_t *sbi_object);
bool ogs_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, ogs_sbi_object_t *sbi_object, void *data,
ogs_sbi_build_f build);

View File

@ -46,11 +46,6 @@ typedef struct amf_ue_s amf_ue_t;
typedef uint32_t amf_m_tmsi_t;
typedef struct amf_guami_s {
ogs_plmn_id_t plmn_id;
ogs_amf_id_t amf_id;
} amf_guami_t;
typedef struct amf_context_s {
ogs_queue_t *queue; /* Queue for processing UPF control */
ogs_timer_mgr_t *timer_mgr; /* Timer Manager */
@ -60,7 +55,7 @@ typedef struct amf_context_s {
/* Served GUAMI */
uint8_t num_of_served_guami;
amf_guami_t served_guami[MAX_NUM_OF_SERVED_GUAMI];
ogs_guami_t served_guami[MAX_NUM_OF_SERVED_GUAMI];
/* Served TAI */
uint8_t num_of_served_tai;
@ -265,9 +260,10 @@ struct amf_ue_s {
int guti_present;
/* UE Info */
amf_guami_t *guami;
ogs_guami_t *guami;
ogs_5gs_tai_t tai;
ogs_nr_cgi_t nr_cgi;
ogs_time_t ue_location_timestamp;
ogs_plmn_id_t last_visited_plmn_id;
ogs_nas_ue_usage_setting_t ue_usage_setting;

View File

@ -463,14 +463,14 @@ ogs_pkbuf_t *gmm_build_configuration_update_command(amf_ue_t *amf_ue, int red)
ogs_gmtime(tv.tv_sec, &gmt);
ogs_localtime(tv.tv_sec, &local);
ogs_debug(" GMT Time[Y:M:D H:M:S GMT] - %d:%d:%d, %d:%d:%d, %d",
ogs_debug(" GMT Time[Y:M:D H:M:S GMT:DST] - %d:%d:%d, %d:%d:%d, %d:%d",
gmt.tm_year, gmt.tm_mon, gmt.tm_mday,
gmt.tm_hour, gmt.tm_min, gmt.tm_sec,
(int)gmt.tm_gmtoff);
ogs_debug(" LOCAL Time[Y:M:D H:M:S GMT] - %d:%d:%d, %d:%d:%d, %d",
(int)gmt.tm_gmtoff, gmt.tm_isdst);
ogs_debug(" LOCAL Time[Y:M:D H:M:S GMT:DST] - %d:%d:%d, %d:%d:%d, %d:%d",
local.tm_year, local.tm_mon, local.tm_mday,
local.tm_hour, local.tm_min, local.tm_sec,
(int)local.tm_gmtoff);
(int)local.tm_gmtoff, local.tm_isdst);
memset(&message, 0, sizeof(message));
message.h.security_header_type =
@ -491,23 +491,23 @@ ogs_pkbuf_t *gmm_build_configuration_update_command(amf_ue_t *amf_ue, int red)
configuration_update_command->presencemask |=
OGS_NAS_5GS_CONFIGURATION_UPDATE_COMMAND_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT;
universal_time_and_local_time_zone->year =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_year % 100);
OGS_NAS_TIME_TO_BCD(gmt.tm_year % 100);
universal_time_and_local_time_zone->mon =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_mon+1);
OGS_NAS_TIME_TO_BCD(gmt.tm_mon+1);
universal_time_and_local_time_zone->mday =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_mday);
OGS_NAS_TIME_TO_BCD(gmt.tm_mday);
universal_time_and_local_time_zone->hour =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_hour);
OGS_NAS_TIME_TO_BCD(gmt.tm_hour);
universal_time_and_local_time_zone->min =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_min);
OGS_NAS_TIME_TO_BCD(gmt.tm_min);
universal_time_and_local_time_zone->sec =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_sec);
OGS_NAS_TIME_TO_BCD(gmt.tm_sec);
if (local.tm_gmtoff >= 0) {
universal_time_and_local_time_zone->timezone =
OGS_OGS_NAS_TIME_TO_BCD(local.tm_gmtoff / 900);
OGS_NAS_TIME_TO_BCD(local.tm_gmtoff / 900);
} else {
universal_time_and_local_time_zone->timezone =
OGS_OGS_NAS_TIME_TO_BCD((-local.tm_gmtoff) / 900);
OGS_NAS_TIME_TO_BCD((-local.tm_gmtoff) / 900);
universal_time_and_local_time_zone->timezone |= 0x08;
}
ogs_debug(" Timezone:0x%x",

View File

@ -140,6 +140,7 @@ int gmm_handle_registration_request(amf_ue_t *amf_ue,
/* Copy TAI and ECGI from ran_ue */
memcpy(&amf_ue->tai, &ran_ue->saved.tai, sizeof(ogs_5gs_tai_t));
memcpy(&amf_ue->nr_cgi, &ran_ue->saved.nr_cgi, sizeof(ogs_nr_cgi_t));
amf_ue->ue_location_timestamp = ogs_time_now();
/* Check TAI */
served_tai_index = amf_find_served_tai(&amf_ue->tai);
@ -317,9 +318,14 @@ int gmm_handle_registration_update(amf_ue_t *amf_ue,
int gmm_handle_service_request(amf_ue_t *amf_ue,
ogs_nas_5gs_service_request_t *service_request)
{
int served_tai_index = 0;
ran_ue_t *ran_ue = NULL;
ogs_nas_key_set_identifier_t *ngksi = NULL;
ogs_assert(amf_ue);
ran_ue = amf_ue->ran_ue;
ogs_assert(ran_ue);
ngksi = &service_request->ngksi;
ogs_assert(ngksi);
@ -357,6 +363,35 @@ int gmm_handle_service_request(amf_ue_t *amf_ue,
amf_ue->nhcc = 1;
}
ogs_debug(" OLD TAI[PLMN_ID:%06x,TAC:%d]",
ogs_plmn_id_hexdump(&amf_ue->tai.plmn_id), amf_ue->tai.tac.v);
ogs_debug(" OLD NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]",
ogs_plmn_id_hexdump(&amf_ue->nr_cgi.plmn_id),
(long long)amf_ue->nr_cgi.cell_id);
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
ogs_plmn_id_hexdump(&ran_ue->saved.tai.plmn_id),
ran_ue->saved.tai.tac.v);
ogs_debug(" NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]",
ogs_plmn_id_hexdump(&ran_ue->saved.nr_cgi.plmn_id),
(long long)ran_ue->saved.nr_cgi.cell_id);
/* Copy TAI and ECGI from ran_ue */
memcpy(&amf_ue->tai, &ran_ue->saved.tai, sizeof(ogs_5gs_tai_t));
memcpy(&amf_ue->nr_cgi, &ran_ue->saved.nr_cgi, sizeof(ogs_nr_cgi_t));
amf_ue->ue_location_timestamp = ogs_time_now();
/* Check TAI */
served_tai_index = amf_find_served_tai(&amf_ue->tai);
if (served_tai_index < 0) {
/* Send Registration Reject */
ogs_warn("Cannot find Served TAI[PLMN_ID:%06x,TAC:%d]",
ogs_plmn_id_hexdump(&amf_ue->tai.plmn_id), amf_ue->tai.tac.v);
nas_5gs_send_registration_reject(amf_ue,
OGS_5GMM_CAUSE_TRACKING_AREA_NOT_ALLOWED);
return OGS_ERROR;
}
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
ogs_debug("[%s] 5G-S_GUTI[AMF_ID:0x%x,M_TMSI:0x%x]",
AMF_UE_HAVE_SUCI(amf_ue) ? amf_ue->suci : "Unknown ID",
ogs_amf_id_hexdump(&amf_ue->guti.amf_id), amf_ue->guti.m_tmsi);
@ -917,6 +952,12 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
memset(&param, 0, sizeof(param));
param.n1smbuf = sess->payload_container;
if (gsm_header->message_type ==
OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE) {
param.ue_location = true;
param.ue_timezone = true;
}
amf_sess_sbi_discover_and_send(
OpenAPI_nf_type_SMF, sess, &param,
amf_nsmf_pdu_session_build_update_sm_context);

View File

@ -68,39 +68,24 @@ void amf_nnrf_handle_nf_status_subscribe(
subscription, SubscriptionData->subscription_id);
if (SubscriptionData->validity_time) {
struct timeval tv;
struct tm local, next;
ogs_time_t diff, duration;
memset(&next, 0, sizeof(next));
if (ogs_strptime(SubscriptionData->validity_time,
OGS_TIME_ISO8601_FORMAT, &next)) {
ogs_gettimeofday(&tv);
ogs_localtime(tv.tv_sec, &local);
diff = ogs_mktime(&next) - ogs_mktime(&local);
#define VALIDITY_MARGIN 5 /* 5 seconds */
#define VALIDITY_MINIMUM 60 /* 60 seconds */
duration = diff - (int)VALIDITY_MARGIN;
if (duration < (int)VALIDITY_MINIMUM) {
char buf[64];
strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &local);
ogs_warn("[%s] Validation period [%lld seconds, "
"(%lld)(%lld)(%s)(%s)] is too small", subscription->id,
(long long)diff,
(long long)ogs_mktime(&next),
(long long)ogs_mktime(&local),
SubscriptionData->validity_time, buf);
#define VALIDITY_MARGIN (5 * OGS_USEC_PER_SEC) /* 5 seconds */
#define VALIDITY_MINIMUM (3600 * OGS_USEC_PER_SEC) /* 3600 seconds */
ogs_time_t time, duration;
if (ogs_sbi_time_from_string(
&time, SubscriptionData->validity_time) == true) {
duration = time - ogs_time_now() - VALIDITY_MARGIN;
if (duration < VALIDITY_MINIMUM) {
duration = VALIDITY_MINIMUM;
ogs_warn("[%s] Forced to %d seconds",
subscription->id, VALIDITY_MINIMUM);
subscription->id, (int)ogs_time_sec(VALIDITY_MINIMUM));
}
subscription->t_validity = ogs_timer_add(amf_self()->timer_mgr,
amf_timer_subscription_validity, subscription);
ogs_assert(subscription->t_validity);
ogs_timer_start(
subscription->t_validity, ogs_time_from_sec(duration));
ogs_timer_start(subscription->t_validity, duration);
} else {
ogs_error("Cannot parse validitiyTime [%s]",
SubscriptionData->validity_time);
}
}
}
@ -194,8 +179,6 @@ bool amf_nnrf_handle_nf_status_notify(
return false;
}
amf_sbi_setup_client_callback(nf_instance);
} else if (NotificationData->event ==
OpenAPI_notification_event_type_NF_DEREGISTERED) {
nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id);
@ -287,8 +270,6 @@ void amf_nnrf_handle_nf_discover(
continue;
}
amf_sbi_setup_client_callback(nf_instance);
if (!OGS_SBI_NF_INSTANCE_GET(
sbi_object->nf_types, nf_instance->nf_type))
ogs_sbi_nf_types_associate(sbi_object->nf_types,
@ -343,6 +324,6 @@ void amf_nnrf_handle_nf_discover(
OpenAPI_nf_type_ToString(sbi_object->nf_type));
}
} else {
ogs_sbi_send(sbi_object, nf_instance);
ogs_sbi_send(nf_instance, sbi_object);
}
}

View File

@ -28,15 +28,13 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
ogs_sbi_server_t *server = NULL;
ogs_sbi_header_t header;
char buf[OGS_AMFIDSTRLEN];
amf_ue_t *amf_ue = NULL;
OpenAPI_sm_context_create_data_t SmContextCreateData;
OpenAPI_plmn_id_nid_t plmn_id_nid;
OpenAPI_snssai_t s_nssai;
OpenAPI_snssai_t hplmn_snssai;
OpenAPI_snssai_t sNssai;
OpenAPI_snssai_t hplmnSnssai;
OpenAPI_ref_to_binary_data_t n1SmMsg;
OpenAPI_guami_t guami;
OpenAPI_user_location_t ueLocation;
ogs_assert(sess);
amf_ue = sess->amf_ue;
@ -54,10 +52,8 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
SmContextCreateData.serving_nf_id = ogs_sbi_self()->nf_instance_id;
plmn_id_nid.mcc = ogs_plmn_id_mcc_string(&amf_ue->tai.plmn_id);
plmn_id_nid.mnc = ogs_plmn_id_mnc_string(&amf_ue->tai.plmn_id);
plmn_id_nid.nid = NULL;
SmContextCreateData.serving_network = &plmn_id_nid;
SmContextCreateData.serving_network =
ogs_sbi_build_plmn_id_nid(&amf_ue->tai.plmn_id);
SmContextCreateData.supi = amf_ue->supi;
SmContextCreateData.pei = amf_ue->pei;
@ -70,24 +66,20 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
SmContextCreateData.pdu_session_id = sess->psi;
SmContextCreateData.dnn = sess->dnn;
memset(&s_nssai, 0, sizeof(s_nssai));
s_nssai.sst = sess->s_nssai.sst;
s_nssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd);
SmContextCreateData.s_nssai = &s_nssai;
memset(&sNssai, 0, sizeof(sNssai));
sNssai.sst = sess->s_nssai.sst;
sNssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd);
SmContextCreateData.s_nssai = &sNssai;
memset(&hplmn_snssai, 0, sizeof(hplmn_snssai));
memset(&hplmnSnssai, 0, sizeof(hplmnSnssai));
if (sess->s_nssai.mapped_hplmn_sst) {
hplmn_snssai.sst = sess->s_nssai.mapped_hplmn_sst;
hplmn_snssai.sd = ogs_s_nssai_sd_to_string(
hplmnSnssai.sst = sess->s_nssai.mapped_hplmn_sst;
hplmnSnssai.sd = ogs_s_nssai_sd_to_string(
sess->s_nssai.mapped_hplmn_sd);
SmContextCreateData.hplmn_snssai = &hplmn_snssai;
SmContextCreateData.hplmn_snssai = &hplmnSnssai;
}
ogs_assert(amf_ue->guami);
guami.amf_id = ogs_amf_id_to_string(&amf_ue->guami->amf_id, buf);
guami.plmn_id = (OpenAPI_plmn_id_t *)&plmn_id_nid;
SmContextCreateData.guami = &guami;
SmContextCreateData.guami = ogs_sbi_build_guami(amf_ue->guami);
SmContextCreateData.an_type = amf_ue->nas.access_type;
memset(&header, 0, sizeof(header));
@ -106,6 +98,16 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
n1SmMsg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
SmContextCreateData.n1_sm_msg = &n1SmMsg;
memset(&ueLocation, 0, sizeof(ueLocation));
ueLocation.nr_location = ogs_sbi_build_nr_location(
&amf_ue->tai, &amf_ue->nr_cgi);
ogs_assert(ueLocation.nr_location);
ueLocation.nr_location->ue_location_timestamp =
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
SmContextCreateData.ue_location = &ueLocation;
SmContextCreateData.ue_time_zone = ogs_sbi_timezone_string(ogs_timezone());
message.SmContextCreateData = &SmContextCreateData;
message.part[message.num_of_part].pkbuf = sess->payload_container;
@ -123,16 +125,25 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
request = ogs_sbi_build_request(&message);
ogs_assert(request);
ogs_free(plmn_id_nid.mcc);
ogs_free(plmn_id_nid.mnc);
if (SmContextCreateData.serving_network)
ogs_sbi_free_plmn_id_nid(SmContextCreateData.serving_network);
ogs_free(SmContextCreateData.sm_context_status_uri);
ogs_free(header.resource.component[2]);
if (s_nssai.sd)
ogs_free(s_nssai.sd);
if (hplmn_snssai.sd)
ogs_free(hplmn_snssai.sd);
if (sNssai.sd)
ogs_free(sNssai.sd);
if (hplmnSnssai.sd)
ogs_free(hplmnSnssai.sd);
if (SmContextCreateData.guami)
ogs_sbi_free_guami(SmContextCreateData.guami);
if (SmContextCreateData.gpsi)
ogs_free(SmContextCreateData.gpsi);
if (ueLocation.nr_location) {
if (ueLocation.nr_location->ue_location_timestamp)
ogs_free(ueLocation.nr_location->ue_location_timestamp);
ogs_sbi_free_nr_location(ueLocation.nr_location);
}
if (SmContextCreateData.ue_time_zone)
ogs_free(SmContextCreateData.ue_time_zone);
return request;
}
@ -148,10 +159,15 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_update_sm_context(
OpenAPI_ref_to_binary_data_t n1SmMsg;
OpenAPI_ref_to_binary_data_t n2SmInfo;
OpenAPI_ng_ap_cause_t ngApCause;
OpenAPI_user_location_t ueLocation;
amf_ue_t *amf_ue = NULL;
ogs_assert(param);
ogs_assert(sess);
ogs_assert(sess->sm_context_ref);
amf_ue = sess->amf_ue;
ogs_assert(amf_ue);
memset(&message, 0, sizeof(message));
message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST;
@ -211,9 +227,32 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_update_sm_context(
message.SmContextUpdateData = &SmContextUpdateData;
}
memset(&ueLocation, 0, sizeof(ueLocation));
if (param->ue_location) {
ueLocation.nr_location = ogs_sbi_build_nr_location(
&amf_ue->tai, &amf_ue->nr_cgi);
ogs_assert(ueLocation.nr_location);
ueLocation.nr_location->ue_location_timestamp =
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
SmContextUpdateData.ue_location = &ueLocation;
}
if (param->ue_timezone) {
SmContextUpdateData.ue_time_zone =
ogs_sbi_timezone_string(ogs_timezone());
}
request = ogs_sbi_build_request(&message);
ogs_assert(request);
if (ueLocation.nr_location) {
if (ueLocation.nr_location->ue_location_timestamp)
ogs_free(ueLocation.nr_location->ue_location_timestamp);
ogs_sbi_free_nr_location(ueLocation.nr_location);
}
if (SmContextUpdateData.ue_time_zone)
ogs_free(SmContextUpdateData.ue_time_zone);
return request;
}
@ -223,8 +262,15 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_release_sm_context(
ogs_sbi_message_t message;
ogs_sbi_request_t *request = NULL;
amf_ue_t *amf_ue = NULL;
OpenAPI_sm_context_release_data_t SmContextReleaseData;
OpenAPI_user_location_t ueLocation;
ogs_assert(sess);
ogs_assert(sess->sm_context_ref);
amf_ue = sess->amf_ue;
ogs_assert(amf_ue);
memset(&message, 0, sizeof(message));
message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST;
@ -235,8 +281,30 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_release_sm_context(
message.h.resource.component[1] = sess->sm_context_ref;
message.h.resource.component[2] = (char *)OGS_SBI_RESOURCE_NAME_RELEASE;
memset(&SmContextReleaseData, 0, sizeof(SmContextReleaseData));
memset(&ueLocation, 0, sizeof(ueLocation));
ueLocation.nr_location = ogs_sbi_build_nr_location(
&amf_ue->tai, &amf_ue->nr_cgi);
ogs_assert(ueLocation.nr_location);
ueLocation.nr_location->ue_location_timestamp =
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
SmContextReleaseData.ue_location = &ueLocation;
SmContextReleaseData.ue_time_zone = ogs_sbi_timezone_string(ogs_timezone());
message.SmContextReleaseData = &SmContextReleaseData;
request = ogs_sbi_build_request(&message);
ogs_assert(request);
if (ueLocation.nr_location) {
if (ueLocation.nr_location->ue_location_timestamp)
ogs_free(ueLocation.nr_location->ue_location_timestamp);
ogs_sbi_free_nr_location(ueLocation.nr_location);
}
if (SmContextReleaseData.ue_time_zone)
ogs_free(SmContextReleaseData.ue_time_zone);
return request;
}

View File

@ -35,6 +35,14 @@ typedef struct amf_nsmf_pdu_session_update_sm_context_param_s {
int group;
int value;
} ngApCause;
union {
struct {
ED3(uint8_t ue_location:1;,
uint8_t ue_timezone:1;,
uint8_t spare:6;)
};
uint8_t indications;
};
} amf_nsmf_pdu_session_update_sm_context_param_t;
ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(

View File

@ -27,11 +27,7 @@ ogs_sbi_request_t *amf_nudm_uecm_build_registration(
ogs_sbi_request_t *request = NULL;
ogs_sbi_server_t *server = NULL;
char buf[OGS_AMFIDSTRLEN];
OpenAPI_amf3_gpp_access_registration_t Amf3GppAccessRegistration;
OpenAPI_plmn_id_t plmn_id;
OpenAPI_guami_t guami;
ogs_assert(amf_ue);
ogs_assert(amf_ue->supi);
@ -63,14 +59,7 @@ ogs_sbi_request_t *amf_nudm_uecm_build_registration(
ogs_sbi_server_uri(server, &header);
ogs_assert(Amf3GppAccessRegistration.dereg_callback_uri);
plmn_id.mcc = ogs_plmn_id_mcc_string(&amf_ue->tai.plmn_id);
plmn_id.mnc = ogs_plmn_id_mnc_string(&amf_ue->tai.plmn_id);
ogs_assert(amf_ue->guami);
guami.amf_id = ogs_amf_id_to_string(&amf_ue->guami->amf_id, buf);
guami.plmn_id = &plmn_id;
Amf3GppAccessRegistration.guami = &guami;
Amf3GppAccessRegistration.guami = ogs_sbi_build_guami(amf_ue->guami);
Amf3GppAccessRegistration.rat_type = OpenAPI_rat_type_NR;
message.Amf3GppAccessRegistration = &Amf3GppAccessRegistration;
@ -78,8 +67,8 @@ ogs_sbi_request_t *amf_nudm_uecm_build_registration(
request = ogs_sbi_build_request(&message);
ogs_assert(request);
ogs_free(plmn_id.mcc);
ogs_free(plmn_id.mnc);
if (Amf3GppAccessRegistration.guami)
ogs_sbi_free_guami(Amf3GppAccessRegistration.guami);
ogs_free(Amf3GppAccessRegistration.dereg_callback_uri);
return request;

View File

@ -76,19 +76,36 @@ int amf_sbi_open(void)
ogs_sbi_server_start_all(server_cb);
/*
* The connection between NF and NRF is a little special.
*
* NF and NRF share nf_instance. I get the NRF EndPoint(client) information
* the configuration file via lib/sbi/context.c.
*
* ogs_sbi_self()->nf_instance_id means NF's InstanceId.
*/
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) {
ogs_sbi_nf_service_t *service = NULL;
ogs_sbi_client_t *client = NULL;
/* Build NF instance information. It will be transmitted to NRF. */
ogs_sbi_nf_instance_build_default(nf_instance, amf_self()->nf_type);
/* Build NF service information. It will be transmitted to NRF. */
service = ogs_sbi_nf_service_build_default(nf_instance,
(char*)OGS_SBI_SERVICE_NAME_NAMF_COMM);
ogs_assert(service);
ogs_sbi_nf_service_add_version(service, (char*)OGS_SBI_API_V1,
(char*)OGS_SBI_API_V1_0_0, NULL);
/* Client callback is only used when NF sends to NRF */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
/* NFRegister is sent and the response is received
* by the above client callback. */
amf_nf_fsm_init(nf_instance);
amf_sbi_setup_client_callback(nf_instance);
}
return OGS_OK;
@ -99,24 +116,6 @@ void amf_sbi_close(void)
ogs_sbi_server_stop_all();
}
void amf_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_client_t *client = NULL;
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
ogs_list_for_each(&nf_instance->nf_service_list, nf_service) {
client = nf_service->client;
if (client)
client->cb = client_cb;
}
}
void amf_ue_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, amf_ue_t *amf_ue, void *data,
ogs_sbi_request_t *(*build)(amf_ue_t *amf_ue, void *data))
@ -127,6 +126,7 @@ void amf_ue_sbi_discover_and_send(
amf_ue->sbi.nf_state_registered = amf_nf_state_registered;
amf_ue->sbi.client_wait.duration =
amf_timer_cfg(AMF_TIMER_SBI_CLIENT_WAIT)->duration;
amf_ue->sbi.client_cb = client_cb;
if (ogs_sbi_discover_and_send(
nf_type, &amf_ue->sbi, data, (ogs_sbi_build_f)build) != true) {
@ -146,6 +146,7 @@ void amf_sess_sbi_discover_and_send(
sess->sbi.nf_state_registered = amf_nf_state_registered;
sess->sbi.client_wait.duration =
amf_timer_cfg(AMF_TIMER_SBI_CLIENT_WAIT)->duration;
sess->sbi.client_cb = client_cb;
if (ogs_sbi_discover_and_send(
nf_type, &sess->sbi, data, (ogs_sbi_build_f)build) != true) {
@ -184,6 +185,8 @@ void amf_sbi_send_deactivate_session(
param.upCnxState = sess->ueUpCnxState;
param.ngApCause.group = group;
param.ngApCause.value = cause;
param.ue_location = true;
param.ue_timezone = true;
amf_sess_sbi_discover_and_send(
OpenAPI_nf_type_SMF, sess, &param,
amf_nsmf_pdu_session_build_update_sm_context);

View File

@ -31,8 +31,6 @@ extern "C" {
int amf_sbi_open(void);
void amf_sbi_close(void);
void amf_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance);
void amf_ue_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, amf_ue_t *amf_ue, void *data,
ogs_sbi_request_t *(*build)(amf_ue_t *amf_ue, void *data));

View File

@ -66,39 +66,24 @@ void ausf_nnrf_handle_nf_status_subscribe(
subscription, SubscriptionData->subscription_id);
if (SubscriptionData->validity_time) {
struct timeval tv;
struct tm local, next;
ogs_time_t diff, duration;
memset(&next, 0, sizeof(next));
if (ogs_strptime(SubscriptionData->validity_time,
OGS_TIME_ISO8601_FORMAT, &next)) {
ogs_gettimeofday(&tv);
ogs_localtime(tv.tv_sec, &local);
diff = ogs_mktime(&next) - ogs_mktime(&local);
#define VALIDITY_MARGIN 5 /* 5 seconds */
#define VALIDITY_MINIMUM 60 /* 60 seconds */
duration = diff - (int)VALIDITY_MARGIN;
if (duration < (int)VALIDITY_MINIMUM) {
char buf[64];
strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &local);
ogs_warn("[%s] Validation period [%lld seconds, "
"(%lld)(%lld)(%s)(%s)] is too small", subscription->id,
(long long)diff,
(long long)ogs_mktime(&next),
(long long)ogs_mktime(&local),
SubscriptionData->validity_time, buf);
#define VALIDITY_MARGIN (5 * OGS_USEC_PER_SEC) /* 5 seconds */
#define VALIDITY_MINIMUM (3600 * OGS_USEC_PER_SEC) /* 3600 seconds */
ogs_time_t time, duration;
if (ogs_sbi_time_from_string(
&time, SubscriptionData->validity_time) == true) {
duration = time - ogs_time_now() - VALIDITY_MARGIN;
if (duration < VALIDITY_MINIMUM) {
duration = VALIDITY_MINIMUM;
ogs_warn("[%s] Forced to %d seconds",
subscription->id, VALIDITY_MINIMUM);
subscription->id, (int)ogs_time_sec(VALIDITY_MINIMUM));
}
subscription->t_validity = ogs_timer_add(ausf_self()->timer_mgr,
ausf_timer_subscription_validity, subscription);
ogs_assert(subscription->t_validity);
ogs_timer_start(
subscription->t_validity, ogs_time_from_sec(duration));
ogs_timer_start(subscription->t_validity, duration);
} else {
ogs_error("Cannot parse validitiyTime [%s]",
SubscriptionData->validity_time);
}
}
}
@ -192,8 +177,6 @@ bool ausf_nnrf_handle_nf_status_notify(
return false;
}
ausf_sbi_setup_client_callback(nf_instance);
} else if (NotificationData->event ==
OpenAPI_notification_event_type_NF_DEREGISTERED) {
nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id);
@ -285,8 +268,6 @@ void ausf_nnrf_handle_nf_discover(
continue;
}
ausf_sbi_setup_client_callback(nf_instance);
if (!OGS_SBI_NF_INSTANCE_GET(
sbi_object->nf_types, nf_instance->nf_type))
ogs_sbi_nf_types_associate(sbi_object->nf_types,
@ -319,6 +300,6 @@ void ausf_nnrf_handle_nf_discover(
"(NF discover) No NF",
OpenAPI_nf_type_ToString(sbi_object->nf_type));
} else {
ogs_sbi_send(sbi_object, nf_instance);
ogs_sbi_send(nf_instance, sbi_object);
}
}

View File

@ -71,10 +71,6 @@ ogs_sbi_request_t *ausf_nudm_ueau_build_result_confirmation_inform(
ogs_sbi_message_t message;
ogs_sbi_request_t *request = NULL;
char buf[OGS_TIME_ISO8601_FORMATTED_LENGTH];
struct timeval tv;
struct tm local;
OpenAPI_auth_event_t *AuthEvent = NULL;
ogs_assert(ausf_ue);
@ -89,11 +85,7 @@ ogs_sbi_request_t *ausf_nudm_ueau_build_result_confirmation_inform(
AuthEvent = ogs_calloc(1, sizeof(*AuthEvent));
ogs_assert(AuthEvent);
ogs_gettimeofday(&tv);
ogs_localtime(tv.tv_sec, &local);
ogs_strftime(buf, OGS_TIME_ISO8601_FORMATTED_LENGTH,
OGS_TIME_ISO8601_FORMAT, &local);
AuthEvent->time_stamp = buf;
AuthEvent->time_stamp = ogs_sbi_localtime_string(ogs_time_now());
AuthEvent->nf_instance_id = ogs_sbi_self()->nf_instance_id;
if (ausf_ue->auth_result == OpenAPI_auth_result_AUTHENTICATION_SUCCESS)
@ -108,6 +100,8 @@ ogs_sbi_request_t *ausf_nudm_ueau_build_result_confirmation_inform(
request = ogs_sbi_build_request(&message);
ogs_assert(request);
if (AuthEvent->time_stamp)
ogs_free(AuthEvent->time_stamp);
ogs_free(AuthEvent);
return request;

View File

@ -73,19 +73,37 @@ int ausf_sbi_open(void)
ogs_sbi_server_start_all(server_cb);
/*
* The connection between NF and NRF is a little special.
*
* NF and NRF share nf_instance. I get the NRF EndPoint(client) information
* the configuration file via lib/sbi/context.c.
* And, the NFService information will be transmitted to NRF.
*
* ogs_sbi_self()->nf_instance_id means NF's InstanceId.
*/
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) {
ogs_sbi_nf_service_t *service = NULL;
ogs_sbi_client_t *client = NULL;
/* Build NF instance information. It will be transmitted to NRF. */
ogs_sbi_nf_instance_build_default(nf_instance, ausf_self()->nf_type);
/* Build NF service information. It will be transmitted to NRF. */
service = ogs_sbi_nf_service_build_default(nf_instance,
(char*)OGS_SBI_SERVICE_NAME_NAUSF_AUTH);
ogs_assert(service);
ogs_sbi_nf_service_add_version(service, (char*)OGS_SBI_API_V1,
(char*)OGS_SBI_API_V1_0_0, NULL);
/* Client callback is only used when NF sends to NRF */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
/* NFRegister is sent and the response is received
* by the above client callback. */
ausf_nf_fsm_init(nf_instance);
ausf_sbi_setup_client_callback(nf_instance);
}
return OGS_OK;
@ -96,24 +114,6 @@ void ausf_sbi_close(void)
ogs_sbi_server_stop_all();
}
void ausf_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_client_t *client = NULL;
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
ogs_list_for_each(&nf_instance->nf_service_list, nf_service) {
client = nf_service->client;
if (client)
client->cb = client_cb;
}
}
void ausf_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, ausf_ue_t *ausf_ue, void *data,
ogs_sbi_request_t *(*build)(ausf_ue_t *ausf_ue, void *data))
@ -128,6 +128,7 @@ void ausf_sbi_discover_and_send(
ausf_ue->sbi.nf_state_registered = ausf_nf_state_registered;
ausf_ue->sbi.client_wait.duration =
ausf_timer_cfg(AUSF_TIMER_SBI_CLIENT_WAIT)->duration;
ausf_ue->sbi.client_cb = client_cb;
if (ogs_sbi_discover_and_send(
nf_type, &ausf_ue->sbi, data, (ogs_sbi_build_f)build) != true) {

View File

@ -29,8 +29,6 @@ extern "C" {
int ausf_sbi_open(void);
void ausf_sbi_close(void);
void ausf_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance);
void ausf_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, ausf_ue_t *ausf_ue, void *data,
ogs_sbi_request_t *(*build)(ausf_ue_t *ausf_ue, void *data));

View File

@ -227,14 +227,14 @@ int emm_handle_attach_complete(
ogs_assert(mme_ue);
ogs_debug(" GMT Time[Y:M:D H:M:S GMT] - %d:%d:%d, %d:%d:%d, %d",
ogs_debug(" GMT Time[Y:M:D H:M:S GMT:DST] - %d:%d:%d, %d:%d:%d, %d:%d",
gmt.tm_year, gmt.tm_mon, gmt.tm_mday,
gmt.tm_hour, gmt.tm_min, gmt.tm_sec,
(int)gmt.tm_gmtoff);
ogs_debug(" LOCAL Time[Y:M:D H:M:S GMT] - %d:%d:%d, %d:%d:%d, %d",
(int)gmt.tm_gmtoff, gmt.tm_isdst);
ogs_debug(" LOCAL Time[Y:M:D H:M:S GMT:DST] - %d:%d:%d, %d:%d:%d, %d:%d",
local.tm_year, local.tm_mon, local.tm_mday,
local.tm_hour, local.tm_min, local.tm_sec,
(int)local.tm_gmtoff);
(int)local.tm_gmtoff, local.tm_isdst);
rv = nas_eps_send_emm_to_esm(
mme_ue, &attach_complete->esm_message_container);
@ -254,23 +254,23 @@ int emm_handle_attach_complete(
emm_information->presencemask |=
OGS_NAS_EPS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT;
universal_time_and_local_time_zone->year =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_year % 100);
OGS_NAS_TIME_TO_BCD(gmt.tm_year % 100);
universal_time_and_local_time_zone->mon =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_mon+1);
OGS_NAS_TIME_TO_BCD(gmt.tm_mon+1);
universal_time_and_local_time_zone->mday =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_mday);
OGS_NAS_TIME_TO_BCD(gmt.tm_mday);
universal_time_and_local_time_zone->hour =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_hour);
OGS_NAS_TIME_TO_BCD(gmt.tm_hour);
universal_time_and_local_time_zone->min =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_min);
OGS_NAS_TIME_TO_BCD(gmt.tm_min);
universal_time_and_local_time_zone->sec =
OGS_OGS_NAS_TIME_TO_BCD(gmt.tm_sec);
OGS_NAS_TIME_TO_BCD(gmt.tm_sec);
if (local.tm_gmtoff >= 0) {
universal_time_and_local_time_zone->timezone =
OGS_OGS_NAS_TIME_TO_BCD(local.tm_gmtoff / 900);
OGS_NAS_TIME_TO_BCD(local.tm_gmtoff / 900);
} else {
universal_time_and_local_time_zone->timezone =
OGS_OGS_NAS_TIME_TO_BCD((-local.tm_gmtoff) / 900);
OGS_NAS_TIME_TO_BCD((-local.tm_gmtoff) / 900);
universal_time_and_local_time_zone->timezone |= 0x08;
}
ogs_debug(" Timezone:0x%x",

View File

@ -1408,8 +1408,8 @@ int mme_context_parse_config()
uint16_t port = self.gtpc_port;
uint16_t tac[OGS_MAX_NUM_OF_TAI] = {0,};
uint8_t num_of_tac = 0;
uint32_t enb_id[OGS_MAX_NUM_OF_ENB_ID] = {0,};
uint8_t num_of_enb_id = 0;
uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID] = {0,};
uint8_t num_of_e_cell_id = 0;
if (ogs_yaml_iter_type(&gtpc_array) ==
YAML_MAPPING_NODE) {
@ -1490,35 +1490,32 @@ int mme_context_parse_config()
} while (
ogs_yaml_iter_type(&tac_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(gtpc_key, "enb_id")) {
ogs_yaml_iter_t enb_id_iter;
ogs_yaml_iter_recurse(&gtpc_iter, &enb_id_iter);
ogs_assert(ogs_yaml_iter_type(&enb_id_iter) !=
YAML_MAPPING_NODE);
} else if (!strcmp(gtpc_key, "e_cell_id")) {
ogs_yaml_iter_t e_cell_id_iter;
ogs_yaml_iter_recurse(&gtpc_iter,
&e_cell_id_iter);
ogs_assert(ogs_yaml_iter_type(&e_cell_id_iter)
!= YAML_MAPPING_NODE);
do {
const char *v = NULL;
ogs_assert(num_of_enb_id <=
OGS_MAX_NUM_OF_ENB_ID);
if (ogs_yaml_iter_type(&enb_id_iter) ==
ogs_assert(num_of_e_cell_id <=
OGS_MAX_NUM_OF_CELL_ID);
if (ogs_yaml_iter_type(&e_cell_id_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&enb_id_iter))
if (!ogs_yaml_iter_next(
&e_cell_id_iter))
break;
}
v = ogs_yaml_iter_value(&enb_id_iter);
v = ogs_yaml_iter_value(&e_cell_id_iter);
if (v) {
if (strncmp(v,"0x",2)) {
// integer enb_id
enb_id[num_of_enb_id] = atoi(v);
} else {
// hex enb_id
enb_id[num_of_enb_id] = strtol(v, NULL, 16);
}
num_of_enb_id++;
e_cell_id[num_of_e_cell_id]
= ogs_uint28_from_string((char*)v);
num_of_e_cell_id++;
}
} while (
ogs_yaml_iter_type(&enb_id_iter) ==
ogs_yaml_iter_type(&e_cell_id_iter) ==
YAML_SEQUENCE_NODE);
} else
ogs_warn("unknown key `%s`", gtpc_key);
@ -1543,25 +1540,13 @@ int mme_context_parse_config()
if (num_of_tac != 0)
memcpy(sgw->tac, tac, sizeof(sgw->tac));
sgw->num_of_enb_id = num_of_enb_id;
if (num_of_enb_id != 0)
memcpy(sgw->enb_id, enb_id, sizeof(sgw->enb_id));
sgw->num_of_e_cell_id = num_of_e_cell_id;
if (num_of_e_cell_id != 0)
memcpy(sgw->e_cell_id, e_cell_id,
sizeof(sgw->e_cell_id));
} while (ogs_yaml_iter_type(&gtpc_array) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(mme_key, "selection_mode")) {
const char *selection_mode =
ogs_yaml_iter_value(&sgw_iter);
if (!strcmp(selection_mode, "rr"))
self.sgw_selection = SGW_SELECT_RR;
else if (!strcmp(selection_mode, "tac"))
self.sgw_selection = SGW_SELECT_TAC;
else if (!strcmp(selection_mode, "enb_id"))
self.sgw_selection = SGW_SELECT_ENB_ID;
else
ogs_warn("unknown sgw_selection mode `%s`",
selection_mode);
}
}
} else if (!strcmp(root_key, "pgw") || !strcmp(root_key, "smf")) {
@ -2195,6 +2180,42 @@ static int mme_ue_new_guti(mme_ue_t *mme_ue)
return OGS_OK;
}
static bool compare_ue_info(mme_sgw_t *node, enb_ue_t *enb_ue)
{
int i;
ogs_assert(node);
ogs_assert(enb_ue);
for (i = 0; i < node->num_of_tac; i++)
if (node->tac[i] == enb_ue->saved.tai.tac) return true;
for (i = 0; i < node->num_of_e_cell_id; i++)
if (node->e_cell_id[i] == enb_ue->saved.e_cgi.cell_id) return true;
return false;
}
static mme_sgw_t *selected_sgw_node(mme_sgw_t *current, enb_ue_t *enb_ue)
{
mme_sgw_t *next, *node;
ogs_assert(current);
ogs_assert(enb_ue);
next = ogs_list_next(current);
for (node = next; node; node = ogs_list_next(node)) {
if (compare_ue_info(node, enb_ue) == true) return node;
}
for (node = ogs_list_first(&mme_self()->sgw_list);
node != next; node = ogs_list_next(node)) {
if (compare_ue_info(node, enb_ue) == true) return node;
}
return next ? next : ogs_list_first(&mme_self()->sgw_list);
}
mme_ue_t *mme_ue_add(enb_ue_t *enb_ue)
{
mme_enb_t *enb = NULL;
@ -2220,160 +2241,19 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue)
/* Create New GUTI */
mme_ue_new_guti(mme_ue);
// on first UE connection, initialise at top of SGW list
// for subsequent UE connections, begin from current position
/*
* When used for the first time, if last node is set,
* the search is performed from the first SGW in a round-robin manner.
*/
if (mme_self()->sgw == NULL)
mme_self()->sgw = ogs_list_first(&mme_self()->sgw_list);
mme_self()->sgw = ogs_list_last(&mme_self()->sgw_list);
if (mme_self()->sgw_selection == SGW_SELECT_RR) {
/* Select SGW with round-robin manner */
ogs_debug("Select SGW by RR");
/* setup GTP path with selected SGW */
mme_self()->sgw = selected_sgw_node(mme_self()->sgw, enb_ue);
ogs_assert(mme_self()->sgw);
OGS_SETUP_GTP_NODE(mme_ue, mme_self()->sgw->gnode);
ogs_debug("UE using SGW on IP[%s]", OGS_ADDR(&mme_ue->gnode->addr, buf));
// list SGW used
OGS_ADDR(&mme_self()->sgw->gnode->addr, buf);
ogs_debug("UE using SGW on IP[%s]",
buf);
// setup GTP path with selected SGW
ogs_assert(mme_self()->sgw);
OGS_SETUP_GTP_NODE(mme_ue, mme_self()->sgw->gnode);
// iterate to next SGW in list for next UE attach (RR)
mme_self()->sgw = ogs_list_next(mme_self()->sgw);
} else if (mme_self()->sgw_selection == SGW_SELECT_TAC) {
/* Select SGW by eNB TAC */
ogs_debug("Select SGW by enb_tac,(RR)");
/*
- starting from list position of last used SGW, search down list for a SGW that serves the enb_tac
- if suitable SGW found
- use it
- if no suitable SGW found, keep searching
- if bottom of list reached, reset search to top of list
- if completed full cyclic search of list and still not found a suitable SGW, use default (first)
*/
int i, found=0, numreset=0;;
char startSGWIP[OGS_ADDRSTRLEN];
OGS_ADDR(&mme_self()->sgw->gnode->addr, startSGWIP);
// search SGW list, find next SGW that serves the TAC || use default (first) if not found
while (!found) {
// (when end of SGW list reached, reset search to top of SGW list)
if(mme_self()->sgw == NULL){
mme_self()->sgw = ogs_list_first(&mme_self()->sgw_list);
numreset = 1;
}
// search SGW list, find next SGW that serves the TAC
while(mme_self()->sgw && !found) {
// if cyclic list check complete and still not found a SGW, break
OGS_ADDR(&mme_self()->sgw->gnode->addr, buf);
if (numreset == 1 && !strcmp(buf,startSGWIP)) {
break;
}
// search from current list position
for (i = 0; i < mme_self()->sgw->num_of_tac && !found; i++){
found = mme_self()->sgw->tac[i] == enb_ue->saved.tai.tac ? 1: 0;
}
if(found){
// found a SGW that serves the TAC
OGS_ADDR(&mme_self()->sgw->gnode->addr, buf);
ogs_debug("SGW on IP[%s] serves enb_tac[%d] - use it",
buf, enb_ue->saved.tai.tac);
} else {
// not found, check next SGW in list
mme_self()->sgw = ogs_list_next(mme_self()->sgw);
}
}
// after checking from the top of the list and not finding a suitable SGW
if (!found && numreset == 1 ){
// default to first in list
ogs_warn("No SGW found that serves enb_tac[%d], defaulting to first SGW in mme.yaml list",
enb_ue->saved.tai.tac);
mme_self()->sgw = ogs_list_first(&mme_self()->sgw_list);
break;
}
}
// list SGW used
OGS_ADDR(&mme_self()->sgw->gnode->addr, buf);
ogs_debug("UE using SGW on IP[%s]",
buf);
// setup GTP path with selected SGW
ogs_assert(mme_self()->sgw);
OGS_SETUP_GTP_NODE(mme_ue, mme_self()->sgw->gnode);
// iterate to next SGW in list for next UE attach (RR)
mme_self()->sgw = ogs_list_next(mme_self()->sgw);
} else if (mme_self()->sgw_selection == SGW_SELECT_ENB_ID) {
/* Select SGW by eNB_ID */
ogs_debug("Select SGW by enb_id,(RR)");
/*
- starting from list position of last used SGW, search down list for a SGW that serves the enb_id
- if suitable SGW found
- use it
- if no suitable SGW found, keep searching
- if bottom of list reached, reset search to top of list
- if completed full cyclic search of list and still not found a suitable SGW, use default (first)
*/
int i, found=0, numreset=0;
char startSGWIP[OGS_ADDRSTRLEN];
OGS_ADDR(&mme_self()->sgw->gnode->addr, startSGWIP);
// search SGW list, find next SGW that serves the enb_id || use default (first) if not found
while (!found) {
// (when end of SGW list reached, reset search to top of SGW list)
if(mme_self()->sgw == NULL){
mme_self()->sgw = ogs_list_first(&mme_self()->sgw_list);
numreset = 1;
}
// search SGW list, find next SGW that serves the enb_id
while(mme_self()->sgw && !found) {
// if cyclic list check complete and still not found a SGW, break
OGS_ADDR(&mme_self()->sgw->gnode->addr, buf);
if (numreset == 1 && !strcmp(buf,startSGWIP)) {
break;
}
// search from current list position
for (i = 0; i < mme_self()->sgw->num_of_enb_id && !found; i++){
found = mme_self()->sgw->enb_id[i] == enb->enb_id ? 1: 0;
}
if(found){
// found a SGW that serves the enb_id
OGS_ADDR(&mme_self()->sgw->gnode->addr, buf);
ogs_debug("SGW on IP[%s] serves enb_id[%d]/[0x%02x] - use it",
buf, enb->enb_id, enb->enb_id);
} else {
// not found, check next SGW in list
mme_self()->sgw = ogs_list_next(mme_self()->sgw);
}
}
// after checking from the top of the list and not finding a suitable SGW
if (!found && numreset == 1 ){
// default to first in list
ogs_warn("No SGW found that serves enb_id[%d]/[0x%02x], defaulting to first SGW in mme.yaml list",
enb->enb_id, enb->enb_id);
mme_self()->sgw = ogs_list_first(&mme_self()->sgw_list);
break;
}
}
// list SGW used
OGS_ADDR(&mme_self()->sgw->gnode->addr, buf);
ogs_debug("UE using SGW on IP[%s]",
buf);
// setup GTP path with selected SGW
ogs_assert(mme_self()->sgw);
OGS_SETUP_GTP_NODE(mme_ue, mme_self()->sgw->gnode);
// iterate to next SGW in list for next UE attach (RR)
mme_self()->sgw = ogs_list_next(mme_self()->sgw);
} else
ogs_assert_if_reached();
/* Clear VLR */
mme_ue->csmap = NULL;
mme_ue->vlr_ostream_id = 0;

View File

@ -60,12 +60,6 @@ typedef struct ogs_diam_config_s ogs_diam_config_t;
typedef uint32_t mme_m_tmsi_t;
typedef uint32_t mme_p_tmsi_t;
typedef enum {
SGW_SELECT_RR = 0, /* Default SGW Selection Method */
SGW_SELECT_TAC,
SGW_SELECT_ENB_ID,
} sgw_select_e;
typedef struct served_gummei_s {
uint32_t num_of_plmn_id;
ogs_plmn_id_t plmn_id[OGS_MAX_NUM_OF_PLMN];
@ -139,9 +133,6 @@ typedef struct mme_context_s {
/* MME Name */
const char *mme_name;
/* SGW Selection */
sgw_select_e sgw_selection;
/* S1SetupResponse */
uint8_t relative_capacity;
@ -171,8 +162,8 @@ typedef struct mme_sgw_s {
uint16_t tac[OGS_MAX_NUM_OF_TAI];
uint8_t num_of_tac;
uint32_t enb_id[OGS_MAX_NUM_OF_ENB_ID];
uint8_t num_of_enb_id;
uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID];
uint8_t num_of_e_cell_id;
ogs_gtp_node_t *gnode;
} mme_sgw_t;

View File

@ -139,7 +139,8 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
pgw_addr6 = mme_self()->pgw_addr6;
}
rv = ogs_gtp_sockaddr_to_f_teid(pgw_addr, pgw_addr6, &pgw_s5c_teid, &len);
rv = ogs_gtp_sockaddr_to_f_teid(
pgw_addr, pgw_addr6, &pgw_s5c_teid, &len);
ogs_assert(rv == OGS_OK);
req->pgw_s5_s8_address_for_control_plane_or_pmip.presence = 1;
req->pgw_s5_s8_address_for_control_plane_or_pmip.data = &pgw_s5c_teid;
@ -162,7 +163,11 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
pdn->pdn_type == OGS_DIAM_PDN_TYPE_IPV6 ||
pdn->pdn_type == OGS_DIAM_PDN_TYPE_IPV4V6) {
req->pdn_type.u8 = ((pdn->pdn_type + 1) & sess->request_type.type);
ogs_assert(req->pdn_type.u8 != 0);
if (req->pdn_type.u8 == 0) {
ogs_fatal("Cannot derive PDN Type [UE:%d,HSS:%d]",
sess->request_type.type, pdn->pdn_type);
ogs_assert_if_reached();
}
} else if (pdn->pdn_type == OGS_DIAM_PDN_TYPE_IPV4_OR_IPV6) {
req->pdn_type.u8 = sess->request_type.type;
} else {
@ -673,7 +678,6 @@ ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request(
ogs_gtp_create_indirect_data_forwarding_tunnel_request_t *req =
&gtp_message.create_indirect_data_forwarding_tunnel_request;
ogs_gtp_tlv_bearer_context_t *bearers[OGS_GTP_MAX_INDIRECT_TUNNEL];
ogs_gtp_f_teid_t dl_teid[OGS_GTP_MAX_INDIRECT_TUNNEL];
ogs_gtp_f_teid_t ul_teid[OGS_GTP_MAX_INDIRECT_TUNNEL];
int len;
@ -684,7 +688,6 @@ ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request(
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
ogs_gtp_bearers_in_create_indirect_tunnel_request(&bearers, req);
memset(&gtp_message, 0, sizeof(ogs_gtp_message_t));
i = 0;
@ -700,10 +703,9 @@ ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request(
rv = ogs_gtp_ip_to_f_teid(
&bearer->enb_dl_ip, &dl_teid[i], &len);
ogs_assert(rv == OGS_OK);
ogs_assert(bearers[i]);
bearers[i]->s1_u_enodeb_f_teid.presence = 1;
bearers[i]->s1_u_enodeb_f_teid.data = &dl_teid[i];
bearers[i]->s1_u_enodeb_f_teid.len = len;
req->bearer_contexts[i].s1_u_enodeb_f_teid.presence = 1;
req->bearer_contexts[i].s1_u_enodeb_f_teid.data = &dl_teid[i];
req->bearer_contexts[i].s1_u_enodeb_f_teid.len = len;
}
if (MME_HAVE_ENB_UL_INDIRECT_TUNNEL(bearer)) {
@ -714,17 +716,16 @@ ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request(
rv = ogs_gtp_ip_to_f_teid(
&bearer->enb_ul_ip, &ul_teid[i], &len);
ogs_assert(rv == OGS_OK);
ogs_assert(bearers[i]);
bearers[i]->s12_rnc_f_teid.presence = 1;
bearers[i]->s12_rnc_f_teid.data = &ul_teid[i];
bearers[i]->s12_rnc_f_teid.len = len;
req->bearer_contexts[i].s12_rnc_f_teid.presence = 1;
req->bearer_contexts[i].s12_rnc_f_teid.data = &ul_teid[i];
req->bearer_contexts[i].s12_rnc_f_teid.len = len;
}
if (MME_HAVE_ENB_DL_INDIRECT_TUNNEL(bearer) ||
MME_HAVE_ENB_UL_INDIRECT_TUNNEL(bearer)) {
bearers[i]->presence = 1;
bearers[i]->eps_bearer_id.presence = 1;
bearers[i]->eps_bearer_id.u8 = bearer->ebi;
req->bearer_contexts[i].presence = 1;
req->bearer_contexts[i].eps_bearer_id.presence = 1;
req->bearer_contexts[i].eps_bearer_id.u8 = bearer->ebi;
i++;
}
@ -763,80 +764,80 @@ ogs_pkbuf_t *mme_s11_build_bearer_resource_command(
ogs_assert(mme_ue);
ogs_assert(nas_message);
switch (nas_message->esm.h.message_type) {
case OGS_NAS_EPS_BEARER_RESOURCE_ALLOCATION_REQUEST:
allocation = &nas_message->esm.bearer_resource_allocation_request;
qos = &allocation->required_traffic_flow_qos;
tad = &allocation->traffic_flow_aggregate;
break;
case OGS_NAS_EPS_BEARER_RESOURCE_MODIFICATION_REQUEST:
modification = &nas_message->esm.bearer_resource_modification_request;
if (modification->presencemask &
OGS_NAS_EPS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_PRESENT) {
qos = &modification->required_traffic_flow_qos;
}
tad = &modification->traffic_flow_aggregate;
break;
default:
ogs_error("Invalid NAS ESM Type[%d]",
nas_message->esm.h.message_type);
return NULL;
switch (nas_message->esm.h.message_type) {
case OGS_NAS_EPS_BEARER_RESOURCE_ALLOCATION_REQUEST:
allocation = &nas_message->esm.bearer_resource_allocation_request;
qos = &allocation->required_traffic_flow_qos;
tad = &allocation->traffic_flow_aggregate;
break;
case OGS_NAS_EPS_BEARER_RESOURCE_MODIFICATION_REQUEST:
modification = &nas_message->esm.bearer_resource_modification_request;
if (modification->presencemask &
OGS_NAS_EPS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_PRESENT) {
qos = &modification->required_traffic_flow_qos;
}
linked_bearer = mme_linked_bearer(bearer);
ogs_assert(linked_bearer);
ogs_debug("[MME] Bearer Resource Command");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp_message_t));
/* Linked Bearer Context : EBI */
cmd->linked_eps_bearer_id.presence = 1;
cmd->linked_eps_bearer_id.u8 = bearer->ebi;
/* Procedure Transaction ID(PTI) */
cmd->procedure_transaction_id.presence = 1;
cmd->procedure_transaction_id.u8 = sess->pti;
/* Flow Quality of Service(QoS) */
if (qos) {
memset(&flow_qos, 0, sizeof(flow_qos));
flow_qos.qci = qos->qci;
/* Octet 4
*
* In UE to network direction:
* 00000000 Subscribed maximum bit rate
*
* In network to UE direction:
* 00000000 Reserved
*/
flow_qos.ul_mbr = qos->ul_mbr == 0 ? bearer->qos.mbr.uplink :
ogs_gtp_qos_to_bps(
qos->ul_mbr, qos->ul_mbr_extended, qos->ul_mbr_extended2);
flow_qos.dl_mbr = qos->dl_mbr == 0 ? bearer->qos.mbr.downlink :
ogs_gtp_qos_to_bps(
qos->dl_mbr, qos->dl_mbr_extended, qos->dl_mbr_extended2);
flow_qos.ul_gbr = qos->ul_gbr == 0 ? bearer->qos.gbr.uplink :
ogs_gtp_qos_to_bps(
qos->ul_gbr, qos->ul_gbr_extended, qos->ul_gbr_extended2);
flow_qos.dl_gbr = qos->dl_gbr == 0 ? bearer->qos.gbr.downlink :
ogs_gtp_qos_to_bps(
qos->dl_gbr, qos->dl_gbr_extended, qos->dl_gbr_extended2);
ogs_gtp_build_flow_qos(
&cmd->flow_quality_of_service,
&flow_qos, flow_qos_buf, GTP_FLOW_QOS_LEN);
cmd->flow_quality_of_service.presence = 1;
}
/* Traffic Aggregate Description(TAD) */
cmd->traffic_aggregate_description.presence = 1;
cmd->traffic_aggregate_description.data = tad->buffer;
cmd->traffic_aggregate_description.len = tad->length;
gtp_message.h.type = type;
return ogs_gtp_build_msg(&gtp_message);
tad = &modification->traffic_flow_aggregate;
break;
default:
ogs_error("Invalid NAS ESM Type[%d]",
nas_message->esm.h.message_type);
return NULL;
}
linked_bearer = mme_linked_bearer(bearer);
ogs_assert(linked_bearer);
ogs_debug("[MME] Bearer Resource Command");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp_message_t));
/* Linked Bearer Context : EBI */
cmd->linked_eps_bearer_id.presence = 1;
cmd->linked_eps_bearer_id.u8 = bearer->ebi;
/* Procedure Transaction ID(PTI) */
cmd->procedure_transaction_id.presence = 1;
cmd->procedure_transaction_id.u8 = sess->pti;
/* Flow Quality of Service(QoS) */
if (qos) {
memset(&flow_qos, 0, sizeof(flow_qos));
flow_qos.qci = qos->qci;
/* Octet 4
*
* In UE to network direction:
* 00000000 Subscribed maximum bit rate
*
* In network to UE direction:
* 00000000 Reserved
*/
flow_qos.ul_mbr = qos->ul_mbr == 0 ? bearer->qos.mbr.uplink :
ogs_gtp_qos_to_bps(
qos->ul_mbr, qos->ul_mbr_extended, qos->ul_mbr_extended2);
flow_qos.dl_mbr = qos->dl_mbr == 0 ? bearer->qos.mbr.downlink :
ogs_gtp_qos_to_bps(
qos->dl_mbr, qos->dl_mbr_extended, qos->dl_mbr_extended2);
flow_qos.ul_gbr = qos->ul_gbr == 0 ? bearer->qos.gbr.uplink :
ogs_gtp_qos_to_bps(
qos->ul_gbr, qos->ul_gbr_extended, qos->ul_gbr_extended2);
flow_qos.dl_gbr = qos->dl_gbr == 0 ? bearer->qos.gbr.downlink :
ogs_gtp_qos_to_bps(
qos->dl_gbr, qos->dl_gbr_extended, qos->dl_gbr_extended2);
ogs_gtp_build_flow_qos(
&cmd->flow_quality_of_service,
&flow_qos, flow_qos_buf, GTP_FLOW_QOS_LEN);
cmd->flow_quality_of_service.presence = 1;
}
/* Traffic Aggregate Description(TAD) */
cmd->traffic_aggregate_description.presence = 1;
cmd->traffic_aggregate_description.data = tad->buffer;
cmd->traffic_aggregate_description.len = tad->length;
gtp_message.h.type = type;
return ogs_gtp_build_msg(&gtp_message);
}

View File

@ -762,7 +762,6 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
enb_ue_t *source_ue = NULL;
int i;
ogs_gtp_tlv_bearer_context_t *bearers[OGS_GTP_MAX_INDIRECT_TUNNEL];
ogs_gtp_f_teid_t *teid = NULL;
ogs_assert(xact);
@ -796,28 +795,26 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
return;
}
ogs_gtp_bearers_in_create_indirect_tunnel_response(&bearers, rsp);
for (i = 0; bearers[i]->presence; i++) {
if (bearers[i]->eps_bearer_id.presence == 0) {
for (i = 0; rsp->bearer_contexts[i].presence; i++) {
if (rsp->bearer_contexts[i].eps_bearer_id.presence == 0) {
ogs_error("No EBI");
return;
}
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
bearers[i]->eps_bearer_id.u8);
rsp->bearer_contexts[i].eps_bearer_id.u8);
ogs_expect_or_return(bearer);
if (bearers[i]->s4_u_sgsn_f_teid.presence) {
teid = bearers[i]->s4_u_sgsn_f_teid.data;
if (rsp->bearer_contexts[i].s4_u_sgsn_f_teid.presence) {
teid = rsp->bearer_contexts[i].s4_u_sgsn_f_teid.data;
ogs_assert(teid);
bearer->sgw_dl_teid = ntohl(teid->teid);
rv = ogs_gtp_f_teid_to_ip(teid, &bearer->sgw_dl_ip);
ogs_expect_or_return(rv == OGS_OK);
}
if (bearers[i]->s2b_u_epdg_f_teid_5.presence) {
teid = bearers[i]->s2b_u_epdg_f_teid_5.data;
if (rsp->bearer_contexts[i].s2b_u_epdg_f_teid_5.presence) {
teid = rsp->bearer_contexts[i].s2b_u_epdg_f_teid_5.data;
ogs_assert(teid);
bearer->sgw_ul_teid = ntohl(teid->teid);

View File

@ -1410,7 +1410,8 @@ void s1ap_handle_handover_required(mme_enb_t *enb, ogs_s1ap_message_t *message)
Source_ToTarget_TransparentContainer);
}
void s1ap_handle_handover_request_ack(mme_enb_t *enb, ogs_s1ap_message_t *message)
void s1ap_handle_handover_request_ack(
mme_enb_t *enb, ogs_s1ap_message_t *message)
{
int rv;
char buf[OGS_ADDRSTRLEN];

View File

@ -179,18 +179,8 @@ bool nrf_nnrf_handle_nf_status_subscribe(
ogs_freeaddrinfo(addr);
if (subscription->time.validity) {
char buf[OGS_TIME_ISO8601_FORMATTED_LENGTH];
struct timeval tv;
struct tm local;
ogs_gettimeofday(&tv);
tv.tv_sec += subscription->time.validity;
ogs_localtime(tv.tv_sec, &local);
ogs_strftime(buf, OGS_TIME_ISO8601_FORMATTED_LENGTH,
OGS_TIME_ISO8601_FORMAT, &local);
SubscriptionData->validity_time = ogs_strdup(buf);
SubscriptionData->validity_time = ogs_sbi_localtime_string(
ogs_time_now() + ogs_time_from_sec(subscription->time.validity));
subscription->t_validity = ogs_timer_add(nrf_self()->timer_mgr,
nrf_timer_subscription_validity, subscription);

View File

@ -91,12 +91,11 @@ void nrf_nnrf_nfm_send_nf_status_notify(ogs_sbi_subscription_t *subscription,
ogs_assert(subscription);
client = subscription->client;
ogs_assert(client);
client->cb = client_notify_cb;
request = nrf_nnrf_nfm_build_nf_status_notify(
client, subscription, event, nf_instance);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, NULL);
ogs_sbi_client_send_request(client, client_notify_cb, request, NULL);
ogs_sbi_request_free(request);
}

View File

@ -974,8 +974,6 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
sgw_tunnel_t *tunnel = NULL;
ogs_gtp_cause_t cause;
ogs_gtp_tlv_bearer_context_t *req_bearers[OGS_GTP_MAX_INDIRECT_TUNNEL];
ogs_gtp_tlv_bearer_context_t *rsp_bearers[OGS_GTP_MAX_INDIRECT_TUNNEL];
ogs_gtp_f_teid_t *req_teid = NULL;
ogs_gtp_f_teid_t rsp_dl_teid[OGS_GTP_MAX_INDIRECT_TUNNEL];
ogs_gtp_f_teid_t rsp_ul_teid[OGS_GTP_MAX_INDIRECT_TUNNEL];
@ -1011,21 +1009,18 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_gtp_bearers_in_create_indirect_tunnel_request(&req_bearers, req);
ogs_gtp_bearers_in_create_indirect_tunnel_response(&rsp_bearers, rsp);
for (i = 0; req_bearers[i]->presence; i++) {
if (req_bearers[i]->eps_bearer_id.presence == 0) {
for (i = 0; req->bearer_contexts[i].presence; i++) {
if (req->bearer_contexts[i].eps_bearer_id.presence == 0) {
ogs_error("No EBI");
return;
}
bearer = sgw_bearer_find_by_ue_ebi(sgw_ue,
req_bearers[i]->eps_bearer_id.u8);
req->bearer_contexts[i].eps_bearer_id.u8);
ogs_assert(bearer);
if (req_bearers[i]->s1_u_enodeb_f_teid.presence) {
req_teid = req_bearers[i]->s1_u_enodeb_f_teid.data;
if (req->bearer_contexts[i].s1_u_enodeb_f_teid.presence) {
req_teid = req->bearer_contexts[i].s1_u_enodeb_f_teid.data;
ogs_assert(req_teid);
tunnel = sgw_tunnel_add(bearer,
@ -1056,16 +1051,16 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
rv = ogs_gtp_sockaddr_to_f_teid(sgw_self()->gtpu_addr,
sgw_self()->gtpu_addr6, &rsp_dl_teid[i], &len);
ogs_assert(len > 0);
rsp_bearers[i]->s4_u_sgsn_f_teid.presence = 1;
rsp_bearers[i]->s4_u_sgsn_f_teid.data = &rsp_dl_teid[i];
rsp_bearers[i]->s4_u_sgsn_f_teid.len = len;
rsp->bearer_contexts[i].s4_u_sgsn_f_teid.presence = 1;
rsp->bearer_contexts[i].s4_u_sgsn_f_teid.data = &rsp_dl_teid[i];
rsp->bearer_contexts[i].s4_u_sgsn_f_teid.len = len;
ogs_debug(" SGW_DL_TEID[%d] ENB_DL_TEID[%d]",
tunnel->local_teid, tunnel->remote_teid);
}
if (req_bearers[i]->s12_rnc_f_teid.presence) {
req_teid = req_bearers[i]->s12_rnc_f_teid.data;
if (req->bearer_contexts[i].s12_rnc_f_teid.presence) {
req_teid = req->bearer_contexts[i].s12_rnc_f_teid.data;
ogs_assert(req_teid);
tunnel = sgw_tunnel_add(bearer,
@ -1097,22 +1092,22 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
rv = ogs_gtp_sockaddr_to_f_teid(sgw_self()->gtpu_addr,
sgw_self()->gtpu_addr6, &rsp_ul_teid[i], &len);
ogs_assert(rv == OGS_OK);
rsp_bearers[i]->s2b_u_epdg_f_teid_5.presence = 1;
rsp_bearers[i]->s2b_u_epdg_f_teid_5.data = &rsp_ul_teid[i];
rsp_bearers[i]->s2b_u_epdg_f_teid_5.len = len;
rsp->bearer_contexts[i].s2b_u_epdg_f_teid_5.presence = 1;
rsp->bearer_contexts[i].s2b_u_epdg_f_teid_5.data = &rsp_ul_teid[i];
rsp->bearer_contexts[i].s2b_u_epdg_f_teid_5.len = len;
ogs_debug(" SGW_UL_TEID[%d] ENB_UL_TEID[%d]",
tunnel->local_teid, tunnel->remote_teid);
}
if (req_bearers[i]->s1_u_enodeb_f_teid.presence ||
req_bearers[i]->s12_rnc_f_teid.presence) {
rsp_bearers[i]->presence = 1;
rsp_bearers[i]->eps_bearer_id.presence = 1;
rsp_bearers[i]->eps_bearer_id.u8 = bearer->ebi;
if (req->bearer_contexts[i].s1_u_enodeb_f_teid.presence ||
req->bearer_contexts[i].s12_rnc_f_teid.presence) {
rsp->bearer_contexts[i].presence = 1;
rsp->bearer_contexts[i].eps_bearer_id.presence = 1;
rsp->bearer_contexts[i].eps_bearer_id.u8 = bearer->ebi;
rsp_bearers[i]->cause.presence = 1;
rsp_bearers[i]->cause.data = &cause;
rsp_bearers[i]->cause.len = sizeof(cause);
rsp->bearer_contexts[i].cause.presence = 1;
rsp->bearer_contexts[i].cause.data = &cause;
rsp->bearer_contexts[i].cause.len = sizeof(cause);
}
}

View File

@ -598,8 +598,55 @@ smf_ue_t *smf_ue_find_by_imsi(uint8_t *imsi, int imsi_len)
return (smf_ue_t *)ogs_hash_get(self.imsi_hash, imsi, imsi_len);
}
static bool compare_ue_info(ogs_pfcp_node_t *node, smf_sess_t *sess)
{
int i;
ogs_assert(node);
ogs_assert(sess);
for (i = 0; i < node->num_of_tac; i++)
if (node->tac[i] == sess->e_tai.tac ||
node->tac[i] == sess->nr_tai.tac.v) return true;
for (i = 0; i < node->num_of_e_cell_id; i++)
if (node->e_cell_id[i] == sess->e_cgi.cell_id) return true;
for (i = 0; i < node->num_of_nr_cell_id; i++)
if (node->nr_cell_id[i] == sess->nr_cgi.cell_id) return true;
for (i = 0; i < node->num_of_apn; i++)
if (strcmp(node->apn[i], sess->pdn.apn) == 0) return true;
return false;
}
static ogs_pfcp_node_t *selected_upf_node(
ogs_pfcp_node_t *current, smf_sess_t *sess)
{
ogs_pfcp_node_t *next, *node;
ogs_assert(current);
ogs_assert(sess);
next = ogs_list_next(current);
for (node = next; node; node = ogs_list_next(node)) {
if (OGS_FSM_CHECK(&node->sm, smf_pfcp_state_associated) &&
compare_ue_info(node, sess) == true) return node;
}
for (node = ogs_list_first(&ogs_pfcp_self()->n4_list);
node != next; node = ogs_list_next(node)) {
if (OGS_FSM_CHECK(&node->sm, smf_pfcp_state_associated) &&
compare_ue_info(node, sess) == true) return node;
}
return next ? next : ogs_list_first(&ogs_pfcp_self()->n4_list);
}
smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn,
uint8_t pdn_type, uint8_t ebi, ogs_paa_t *paa, ogs_gtp_create_session_request_t *req)
uint8_t pdn_type, uint8_t ebi, ogs_paa_t *paa, ogs_gtp_uli_t *uli)
{
ogs_debug("smf_sess_add_by_apn");
smf_event_t e;
@ -615,6 +662,7 @@ smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn,
ogs_assert(smf_ue);
ogs_assert(apn);
ogs_assert(paa);
ogs_assert(uli);
ogs_pool_alloc(&smf_sess_pool, &sess);
if (!sess) {
@ -674,342 +722,30 @@ smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn,
} else
ogs_assert_if_reached();
memcpy(&sess->e_tai, &uli->tai, sizeof(sess->e_tai));
memcpy(&sess->e_cgi, &uli->e_cgi, sizeof(sess->e_cgi));
ogs_info("UE IMSI:[%s] APN:[%s] IPv4:[%s] IPv6:[%s]",
sess->imsi_bcd, apn,
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
// on first UE connection, initialise at top of UPF (PFCP) list
// for subsequent UE connections, begin from current position
/*
* When used for the first time, if last node is set,
* the search is performed from the first SGW in a round-robin manner.
*/
if (ogs_pfcp_self()->node == NULL)
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
ogs_pfcp_self()->node = ogs_list_last(&ogs_pfcp_self()->n4_list);
if (ogs_pfcp_self()->upf_selection_mode == UPF_SELECT_RR) {
/* Select UPF (PFCP) with round-robin manner */
ogs_debug("Select UPF by RR");
/*
- starting from list position of last used UPF, search down list for next PFCP associated UPF
- if PFCP associated UPF found
- use it
- if no associated UPF found, keep searching
- if bottom of list reached, reset search to top of list
- if completed full cyclic search of list and still not found a UPF, use default (first)
*/
/* setup GTP session with selected UPF */
ogs_pfcp_self()->node = selected_upf_node(ogs_pfcp_self()->node, sess);
ogs_assert(ogs_pfcp_self()->node);
OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->node);
ogs_debug("UE using UPF on IP[%s]",
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf));
int connect=0, numreset=0;
char startUPFIP[OGS_ADDRSTRLEN];
OGS_ADDR(&ogs_pfcp_self()->node->addr, startUPFIP);
//search UPF list, find next UPF that is associated
while (!connect)
{
// (when end of UPF (PFCP) list reached, reset search to top of UPF list)
if(ogs_pfcp_self()->node == NULL){
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
numreset = 1;
}
// search UPF (PFCP) list, find next UPF that is associated
while(ogs_pfcp_self()->node && !connect) {
// if cyclic list check complete and still not found a UPF, break
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
if (numreset == 1 && !strcmp(buf,startUPFIP)) {
break;
}
// has UPF <x> associated over PFCP?
if (OGS_FSM_CHECK( &ogs_pfcp_self()->node->sm, smf_pfcp_state_associated) ){
// then use it
connect = 1;
} else {
// else check next UPF in list
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_debug("UPF on IP[%s] is not PFCP associated",
buf);
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
}
}
// after checking from the top of the list and not finding a suitable UPF
if (!connect && numreset == 1 ){
// default to first in list
ogs_error("No UPF (PFCP) is currently PFCP associated");
ogs_error("Defaulting to first UPF (PFCP) in smf.yaml list");
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
break;
}
}
// list UPF used
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_debug("UE using UPF on IP[%s]",
buf);
// setup GTP session with selected UPF
ogs_assert(ogs_pfcp_self()->node);
OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->node);
// iterate to next UPF in list for next UE attach (RR)
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
} else if (ogs_pfcp_self()->upf_selection_mode == UPF_SELECT_TAC) {
/* Select UPF by eNB/gNB TAC */
ogs_debug("Select UPF by UE's enb_tac,(RR)");
/*
- starting from list position of last used UPF, search down list for a UPF that serves the enb_tac **AND** is PFCP associated
- if suitable UPF found
- if PFCP associated
- use it
- else keep searching
- if no suitable UPF found, keep searching
- if bottom of list reached, reset search to top of list
- if completed full cyclic search of list and still not found a UPF, use default (first)
*/
int i, found=0, numreset=0;
char startUPFIP[OGS_ADDRSTRLEN];
OGS_ADDR(&ogs_pfcp_self()->node->addr, startUPFIP);
// fetch the user location information from the incoming S5c request
ogs_gtp_uli_t uli;
ogs_gtp_parse_uli(&uli, &req->user_location_information);
//ogs_info("UE enb_tac: [%d]", uli.tai.tac);
//search UPF list, find next UPF that serves the enb_tac **AND** is associated
while (!found)
{
// (when end of UPF (PFCP) list reached, reset search to top of UPF list)
if(ogs_pfcp_self()->node == NULL){
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
numreset = 1;
}
// search UPF list, find next UPF that serves the enb_tac **AND** is associated
while(ogs_pfcp_self()->node && !found) {
// if cyclic list check complete and still not found a UPF, break
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
if (numreset == 1 && !strcmp(buf,startUPFIP)) {
break;
}
// search from current list position
for (i = 0; i < ogs_pfcp_self()->node->num_of_tac && !found; i++){
found = ogs_pfcp_self()->node->tac[i] == uli.tai.tac ? 1: 0;
}
if(found){
// has UPF <x> associated over PFCP?
if (!OGS_FSM_CHECK( &ogs_pfcp_self()->node->sm, smf_pfcp_state_associated )){
// no - keep searching
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_warn("UPF on IP[%s] serves enb_tac[%d] - but is **NOT** associated",
buf, uli.tai.tac);
found = 0;
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
} else {
// found a UPF that serves the enb_tac **AND** is associated
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_debug("UPF on IP[%s] serves enb_tac[%d] - and is associated, use it",
buf, uli.tai.tac);
}
} else {
// not found, check next UPF in list
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
}
}
// after checking from the top of the list and not finding a suitable UPF
if (!found && numreset == 1 ){
// default to first in list
ogs_error("No UPF that serves enb_tac[%d] is currently PFCP associated",
uli.tai.tac);
ogs_error("Defaulting to first UPF (PFCP) in smf.yaml list");
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
break;
}
}
// list UPF used
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_debug("UE using UPF on IP[%s]",
buf);
// setup GTP session with selected UPF
ogs_assert(ogs_pfcp_self()->node);
OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->node);
// iterate to next UPF in list for next UE attach (RR)
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
} else if (ogs_pfcp_self()->upf_selection_mode == UPF_SELECT_APN) {
/* Select UPF by UE APN */
ogs_debug("Select UPF by UE's apn,(RR)");
/*
- starting from list position of last used UPF, search down list for a UPF that serves the UE's APN **AND** is PFCP associated
- if suitable UPF found
- if PFCP associated
- use it
- else keep searching
- if no suitable UPF found, keep searching
- if bottom of list reached, reset search to top of list
- if completed full cyclic search of list and still not found a UPF, use default (first)
*/
int i, found=0, numreset=0;
char startUPFIP[OGS_ADDRSTRLEN];
OGS_ADDR(&ogs_pfcp_self()->node->addr, startUPFIP);
//ogs_info("UE apn: [%s]", apn);
// search UPF list, find next UPF that serves the ue_apn **AND** is associated
while (!found)
{
// (when end of UPF (PFCP) list reached, reset search to top of UPF list)
if(ogs_pfcp_self()->node == NULL){
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
numreset = 1;
}
// search UPF list, find next UPF that serves the ue_apn **AND** is associated
while(ogs_pfcp_self()->node && !found) {
// if cyclic list check complete and still not found a UPF, break
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
if (numreset == 1 && !strcmp(buf,startUPFIP)) {
break;
}
// search from current list position
for (i = 0; i < ogs_pfcp_self()->node->num_of_apn && !found; i++){
found = strncmp( ogs_pfcp_self()->node->apn[i], apn, OGS_MAX_APN_LEN ) ? 0: 1;
}
if(found){
// has UPF <x> associated over PFCP?
if (!OGS_FSM_CHECK( &ogs_pfcp_self()->node->sm, smf_pfcp_state_associated )){
// no - keep searching
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_warn("UPF on IP[%s] serves ue_apn[%s] - but is **NOT** associated",
buf, apn);
found = 0;
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
} else {
// found a UPF that serves the ue_apn **AND** is associated
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_debug("UPF on IP[%s] serves ue_apn[%s] - and is associated, use it",
buf, apn);
}
} else {
// not found, check next UPF in list
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
}
}
// after checking from the top of the list and not finding a suitable UPF
if (!found && numreset == 1 ){
// default to first in list
ogs_error("No UPF that serves ue_apn[%s] is currently PFCP associated",
apn);
ogs_error("Defaulting to first UPF (PFCP) in smf.yaml list");
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
break;
}
}
// list UPF used
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_debug("UE using UPF on IP[%s]",
buf);
// setup GTP session with selected UPF
ogs_assert(ogs_pfcp_self()->node);
OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->node);
// iterate to next UPF in list for next UE attach (RR)
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
} else if (ogs_pfcp_self()->upf_selection_mode == UPF_SELECT_ENB_ID) {
/* Select UPF by eNB/gNB ID */
ogs_debug("Select UPF by UE's enb_id,(RR)");
/*
- starting from list position of last used UPF, search down list for a UPF that serves the enb_id **AND** is PFCP associated
- if suitable UPF found
- if PFCP associated
- use it
- else keep searching
- if no suitable UPF found, keep searching
- if bottom of list reached, reset search to top of list
- if completed full cyclic search of list and still not found a UPF, use default (first)
*/
int i, found=0, numreset=0;
char startUPFIP[OGS_ADDRSTRLEN];
OGS_ADDR(&ogs_pfcp_self()->node->addr, startUPFIP);
// fetch the user location information from the incoming S5c request
ogs_gtp_uli_t uli;
ogs_gtp_parse_uli(&uli, &req->user_location_information);
int UE_enb_id = ((uli.e_cgi.cell_id & 0xfffff00) >> 8); //shift 2 bytes right
//int UE_cell_id = (uli.e_cgi.cell_id & 0x00000ff);
// e_cgi.cell_id = [enb_id, cell_id] [20bit, 8bit]
//ogs_info("UE enb_id: [0x%02x]", UE_enb_id);
//search UPF list, find next UPF that serves the enb_id **AND** is associated
while (!found)
{
// (when end of UPF (PFCP) list reached, reset search to top of UPF list)
if(ogs_pfcp_self()->node == NULL){
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
numreset = 1;
}
// search UPF list, find next UPF that serves the enb_id **AND** is associated
while(ogs_pfcp_self()->node && !found) {
// if cyclic list check complete and still not found a UPF, break
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
if (numreset == 1 && !strcmp(buf,startUPFIP)) {
break;
}
// search from current list position
for (i = 0; i < ogs_pfcp_self()->node->num_of_enb_id && !found; i++){
found = ogs_pfcp_self()->node->enb_id[i] == UE_enb_id ? 1: 0;
}
if(found){
// has UPF <x> associated over PFCP?
if (!OGS_FSM_CHECK( &ogs_pfcp_self()->node->sm, smf_pfcp_state_associated )){
// no - keep searching
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_warn("UPF on IP[%s] serves enb_id[%d]/[0x%02x] - but is **NOT** associated",
buf, UE_enb_id, UE_enb_id);
found = 0;
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
} else {
// found a UPF that serves the enb_id **AND** is associated
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_debug("UPF on IP[%s] serves enb_id[%d]/[0x%02x] - and is associated, use it",
buf, UE_enb_id, UE_enb_id);
}
} else {
// not found, check next UPF in list
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
}
}
// after checking from the top of the list and not finding a suitable UPF
if (!found && numreset == 1 ){
// default to first in list
ogs_error("No UPF that serves enb_id[%d]/[0x%02x] is currently PFCP associated",
UE_enb_id, UE_enb_id);
ogs_error("Defaulting to first UPF (PFCP) in smf.yaml list");
ogs_pfcp_self()->node = ogs_list_first(&ogs_pfcp_self()->n4_list);
break;
}
}
// list UPF used
OGS_ADDR(&ogs_pfcp_self()->node->addr, buf);
ogs_debug("UE using UPF on IP[%s]",
buf);
// setup GTP session with selected UPF
ogs_assert(ogs_pfcp_self()->node);
OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->node);
// iterate to next UPF in list for next UE attach (RR)
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
} else
ogs_assert_if_reached();
/* iterate to next UPF in list for next UE attach */
ogs_pfcp_self()->node = ogs_list_next(ogs_pfcp_self()->node);
/* Set Default Bearer */
ogs_list_init(&sess->bearer_list);
@ -1045,6 +781,7 @@ smf_sess_t *smf_sess_add_by_gtp_message(ogs_gtp_message_t *message)
smf_sess_t *sess = NULL;
ogs_paa_t *paa = NULL;
char apn[OGS_MAX_APN_LEN];
ogs_gtp_uli_t uli;
ogs_gtp_create_session_request_t *req = &message->create_session_request;
@ -1070,7 +807,12 @@ smf_sess_t *smf_sess_add_by_gtp_message(ogs_gtp_message_t *message)
}
if (req->pdn_address_allocation.presence == 0) {
ogs_error("No PAA Type");
ogs_error("No PAA");
return NULL;
}
if (req->user_location_information.presence == 0) {
ogs_error("No UE Location Information");
return NULL;
}
@ -1083,6 +825,8 @@ smf_sess_t *smf_sess_add_by_gtp_message(ogs_gtp_message_t *message)
paa = (ogs_paa_t *)req->pdn_address_allocation.data;
ogs_gtp_parse_uli(&uli, &req->user_location_information);
/*
* 7.2.1 in 3GPP TS 29.274 Release 15
*
@ -1116,7 +860,7 @@ smf_sess_t *smf_sess_add_by_gtp_message(ogs_gtp_message_t *message)
}
sess = smf_sess_add_by_apn(smf_ue, apn, req->pdn_type.u8,
req->bearer_contexts_to_be_created.eps_bearer_id.u8, paa, req);
req->bearer_contexts_to_be_created.eps_bearer_id.u8, paa, &uli);
return sess;
}
@ -1471,6 +1215,7 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess)
ul_far->dst_if = OGS_PFCP_INTERFACE_CORE;
ogs_pfcp_pdr_associate_far(ul_pdr, ul_far);
ogs_assert(sess->pfcp_node);
resource = ogs_pfcp_gtpu_resource_find(
&sess->pfcp_node->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);

View File

@ -176,7 +176,15 @@ typedef struct smf_sess_s {
/* PLMN ID & NID */
ogs_plmn_id_t plmn_id;
char *nid;
/* LTE Location */
ogs_eps_tai_t e_tai;
ogs_e_cgi_t e_cgi;
/* NR Location */
ogs_5gs_tai_t nr_tai;
ogs_nr_cgi_t nr_cgi;
ogs_time_t ue_location_timestamp;
/* S_NSSAI & DNN */
ogs_s_nssai_t s_nssai;
@ -297,7 +305,7 @@ smf_ue_t *smf_ue_find_by_imsi(uint8_t *imsi, int imsi_len);
smf_sess_t *smf_sess_add_by_gtp_message(ogs_gtp_message_t *message);
smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn,
uint8_t pdn_type, uint8_t ebi, ogs_paa_t *addr, ogs_gtp_create_session_request_t *message);
uint8_t pdn_type, uint8_t ebi, ogs_paa_t *paa, ogs_gtp_uli_t *uli);
smf_sess_t *smf_sess_add_by_sbi_message(ogs_sbi_message_t *message);
smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi);

View File

@ -77,8 +77,7 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
smf_nsmf_handle_update_sm_context(sess, sbi_message);
break;
CASE(OGS_SBI_RESOURCE_NAME_RELEASE)
smf_5gc_pfcp_send_session_deletion_request(sess,
OGS_PFCP_5GC_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT);
smf_nsmf_handle_release_sm_context(sess, sbi_message);
break;
DEFAULT
smf_nsmf_handle_create_sm_context(sess, sbi_message);

View File

@ -66,39 +66,24 @@ void smf_nnrf_handle_nf_status_subscribe(
subscription, SubscriptionData->subscription_id);
if (SubscriptionData->validity_time) {
struct timeval tv;
struct tm local, next;
ogs_time_t diff, duration;
memset(&next, 0, sizeof(next));
if (ogs_strptime(SubscriptionData->validity_time,
OGS_TIME_ISO8601_FORMAT, &next)) {
ogs_gettimeofday(&tv);
ogs_localtime(tv.tv_sec, &local);
diff = ogs_mktime(&next) - ogs_mktime(&local);
#define VALIDITY_MARGIN 5 /* 5 seconds */
#define VALIDITY_MINIMUM 60 /* 60 seconds */
duration = diff - (int)VALIDITY_MARGIN;
if (duration < (int)VALIDITY_MINIMUM) {
char buf[64];
strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &local);
ogs_warn("[%s] Validation period [%lld seconds, "
"(%lld)(%lld)(%s)(%s)] is too small", subscription->id,
(long long)diff,
(long long)ogs_mktime(&next),
(long long)ogs_mktime(&local),
SubscriptionData->validity_time, buf);
#define VALIDITY_MARGIN (5 * OGS_USEC_PER_SEC) /* 5 seconds */
#define VALIDITY_MINIMUM (3600 * OGS_USEC_PER_SEC) /* 3600 seconds */
ogs_time_t time, duration;
if (ogs_sbi_time_from_string(
&time, SubscriptionData->validity_time) == true) {
duration = time - ogs_time_now() - VALIDITY_MARGIN;
if (duration < VALIDITY_MINIMUM) {
duration = VALIDITY_MINIMUM;
ogs_warn("[%s] Forced to %d seconds",
subscription->id, VALIDITY_MINIMUM);
subscription->id, (int)ogs_time_sec(VALIDITY_MINIMUM));
}
subscription->t_validity = ogs_timer_add(smf_self()->timer_mgr,
smf_timer_subscription_validity, subscription);
ogs_assert(subscription->t_validity);
ogs_timer_start(
subscription->t_validity, ogs_time_from_sec(duration));
ogs_timer_start(subscription->t_validity, duration);
} else {
ogs_error("Cannot parse validitiyTime [%s]",
SubscriptionData->validity_time);
}
}
}
@ -192,8 +177,6 @@ bool smf_nnrf_handle_nf_status_notify(
return false;
}
smf_sbi_setup_client_callback(nf_instance);
} else if (NotificationData->event ==
OpenAPI_notification_event_type_NF_DEREGISTERED) {
nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id);
@ -285,8 +268,6 @@ void smf_nnrf_handle_nf_discover(
continue;
}
smf_sbi_setup_client_callback(nf_instance);
if (!OGS_SBI_NF_INSTANCE_GET(
sbi_object->nf_types, nf_instance->nf_type))
ogs_sbi_nf_types_associate(sbi_object->nf_types,
@ -319,6 +300,6 @@ void smf_nnrf_handle_nf_discover(
"(NF discover) No NF",
OpenAPI_nf_type_ToString(sbi_object->nf_type));
} else {
ogs_sbi_send(sbi_object, nf_instance);
ogs_sbi_send(nf_instance, sbi_object);
}
}

View File

@ -35,6 +35,7 @@ bool smf_nsmf_handle_create_sm_context(
ogs_sockaddr_t *addr = NULL;
OpenAPI_sm_context_create_data_t *SmContextCreateData = NULL;
OpenAPI_nr_location_t *NrLocation = NULL;
OpenAPI_snssai_t *sNssai = NULL;
OpenAPI_plmn_id_nid_t *servingNetwork = NULL;
OpenAPI_ref_to_binary_data_t *n1SmMsg = NULL;
@ -82,6 +83,31 @@ bool smf_nsmf_handle_create_sm_context(
return false;
}
if (!SmContextCreateData->ue_location ||
!SmContextCreateData->ue_location->nr_location) {
ogs_error("[%s:%d] No UeLocation", smf_ue->supi, sess->psi);
n1smbuf = gsm_build_pdu_session_establishment_reject(sess,
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION);
smf_sbi_send_sm_context_create_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No UeLocation", smf_ue->supi, n1smbuf);
return false;
}
NrLocation = SmContextCreateData->ue_location->nr_location;
if (!NrLocation->tai ||
!NrLocation->tai->plmn_id || !NrLocation->tai->tac ||
!NrLocation->ncgi ||
!NrLocation->ncgi->plmn_id || !NrLocation->ncgi->nr_cell_id) {
ogs_error("[%s:%d] No NrLocation", smf_ue->supi, sess->psi);
n1smbuf = gsm_build_pdu_session_establishment_reject(sess,
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION);
smf_sbi_send_sm_context_create_error(session,
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
"No UeLocation", smf_ue->supi, n1smbuf);
return false;
}
n1SmMsg = SmContextCreateData->n1_sm_msg;
if (!n1SmMsg || !n1SmMsg->content_id) {
ogs_error("[%s:%d] No n1SmMsg", smf_ue->supi, sess->psi);
@ -129,10 +155,11 @@ bool smf_nsmf_handle_create_sm_context(
return false;
}
ogs_plmn_id_build(&sess->plmn_id,
atoi(servingNetwork->mcc), atoi(servingNetwork->mnc),
strlen(servingNetwork->mnc));
sess->nid = servingNetwork->nid;
ogs_sbi_parse_plmn_id_nid(&sess->plmn_id, servingNetwork);
ogs_sbi_parse_nr_location(&sess->nr_tai, &sess->nr_cgi, NrLocation);
if (NrLocation->ue_location_timestamp)
ogs_sbi_time_from_string(&sess->ue_location_timestamp,
NrLocation->ue_location_timestamp);
sess->s_nssai.sst = sNssai->sst;
sess->s_nssai.sd = ogs_s_nssai_sd_from_string(sNssai->sd);
@ -212,6 +239,28 @@ bool smf_nsmf_handle_update_sm_context(
return false;
}
if (SmContextUpdateData->ue_location &&
SmContextUpdateData->ue_location->nr_location) {
OpenAPI_nr_location_t *NrLocation =
SmContextUpdateData->ue_location->nr_location;
if (NrLocation->tai &&
NrLocation->tai->plmn_id && NrLocation->tai->tac &&
NrLocation->ncgi &&
NrLocation->ncgi->plmn_id && NrLocation->ncgi->nr_cell_id) {
ogs_sbi_parse_nr_location(&sess->nr_tai, &sess->nr_cgi, NrLocation);
if (NrLocation->ue_location_timestamp)
ogs_sbi_time_from_string(&sess->ue_location_timestamp,
NrLocation->ue_location_timestamp);
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
ogs_plmn_id_hexdump(&sess->nr_tai.plmn_id), sess->nr_tai.tac.v);
ogs_debug(" NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]",
ogs_plmn_id_hexdump(&sess->nr_cgi.plmn_id),
(long long)sess->nr_cgi.cell_id);
}
}
if (SmContextUpdateData->n1_sm_msg) {
n1SmMsg = SmContextUpdateData->n1_sm_msg;
if (!n1SmMsg || !n1SmMsg->content_id) {
@ -447,3 +496,44 @@ bool smf_nsmf_handle_update_sm_context(
return true;
}
bool smf_nsmf_handle_release_sm_context(
smf_sess_t *sess, ogs_sbi_message_t *message)
{
OpenAPI_sm_context_release_data_t *SmContextReleaseData = NULL;
ogs_assert(sess);
ogs_assert(message);
SmContextReleaseData = message->SmContextReleaseData;
if (SmContextReleaseData) {
if (SmContextReleaseData->ue_location &&
SmContextReleaseData->ue_location->nr_location) {
OpenAPI_nr_location_t *NrLocation =
SmContextReleaseData->ue_location->nr_location;
if (NrLocation->tai &&
NrLocation->tai->plmn_id && NrLocation->tai->tac &&
NrLocation->ncgi &&
NrLocation->ncgi->plmn_id && NrLocation->ncgi->nr_cell_id) {
ogs_sbi_parse_nr_location(
&sess->nr_tai, &sess->nr_cgi, NrLocation);
if (NrLocation->ue_location_timestamp)
ogs_sbi_time_from_string(&sess->ue_location_timestamp,
NrLocation->ue_location_timestamp);
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
ogs_plmn_id_hexdump(&sess->nr_tai.plmn_id),
sess->nr_tai.tac.v);
ogs_debug(" NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]",
ogs_plmn_id_hexdump(&sess->nr_cgi.plmn_id),
(long long)sess->nr_cgi.cell_id);
}
}
}
smf_5gc_pfcp_send_session_deletion_request(sess,
OGS_PFCP_5GC_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT);
return true;
}

View File

@ -30,6 +30,8 @@ bool smf_nsmf_handle_create_sm_context(
smf_sess_t *sess, ogs_sbi_message_t *message);
bool smf_nsmf_handle_update_sm_context(
smf_sess_t *sess, ogs_sbi_message_t *message);
bool smf_nsmf_handle_release_sm_context(
smf_sess_t *sess, ogs_sbi_message_t *message);
#ifdef __cplusplus
}

View File

@ -75,19 +75,37 @@ int smf_sbi_open(void)
ogs_sbi_server_start_all(server_cb);
/*
* The connection between NF and NRF is a little special.
*
* NF and NRF share nf_instance. I get the NRF EndPoint(client) information
* the configuration file via lib/sbi/context.c.
* And, the NFService information will be transmitted to NRF.
*
* ogs_sbi_self()->nf_instance_id means NF's InstanceId.
*/
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) {
ogs_sbi_nf_service_t *service = NULL;
ogs_sbi_client_t *client = NULL;
/* Build NF instance information. It will be transmitted to NRF. */
ogs_sbi_nf_instance_build_default(nf_instance, smf_self()->nf_type);
/* Build NF service information. It will be transmitted to NRF. */
service = ogs_sbi_nf_service_build_default(nf_instance,
(char*)OGS_SBI_SERVICE_NAME_NSMF_PDUSESSION);
ogs_assert(service);
ogs_sbi_nf_service_add_version(service, (char*)OGS_SBI_API_V1,
(char*)OGS_SBI_API_V1_0_0, NULL);
/* Client callback is only used when NF sends to NRF */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
/* NFRegister is sent and the response is received
* by the above client callback. */
smf_nf_fsm_init(nf_instance);
smf_sbi_setup_client_callback(nf_instance);
}
return OGS_OK;
@ -98,24 +116,6 @@ void smf_sbi_close(void)
ogs_sbi_server_stop_all();
}
void smf_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_client_t *client = NULL;
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
ogs_list_for_each(&nf_instance->nf_service_list, nf_service) {
client = nf_service->client;
if (client)
client->cb = client_cb;
}
}
void smf_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, smf_sess_t *sess, void *data,
ogs_sbi_request_t *(*build)(smf_sess_t *sess, void *data))
@ -135,6 +135,7 @@ void smf_sbi_discover_and_send(
sess->sbi.nf_state_registered = smf_nf_state_registered;
sess->sbi.client_wait.duration =
smf_timer_cfg(SMF_TIMER_SBI_CLIENT_WAIT)->duration;
sess->sbi.client_cb = client_cb;
if (ogs_sbi_discover_and_send(
nf_type, &sess->sbi, data, (ogs_sbi_build_f)build) != true) {
@ -361,7 +362,6 @@ void smf_sbi_send_sm_context_update_error(
ogs_pkbuf_free(n2smbuf);
}
#if 0
static int client_notify_cb(ogs_sbi_response_t *response, void *data)
{
int rv;
@ -386,7 +386,6 @@ static int client_notify_cb(ogs_sbi_response_t *response, void *data)
ogs_sbi_response_free(response);
return OGS_OK;
}
#endif
void smf_sbi_send_sm_context_status_notify(smf_sess_t *sess)
{
@ -400,6 +399,6 @@ void smf_sbi_send_sm_context_status_notify(smf_sess_t *sess)
request = smf_namf_callback_build_sm_context_status(sess, NULL);
ogs_assert(request);
ogs_sbi_client_send_request(client, request, NULL);
ogs_sbi_client_send_request(client, client_notify_cb, request, NULL);
ogs_sbi_request_free(request);
}

View File

@ -32,7 +32,6 @@ extern "C" {
int smf_sbi_open(void);
void smf_sbi_close(void);
void smf_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance);
void smf_sbi_send(smf_sess_t *sess, ogs_sbi_nf_instance_t *nf_instance);
void smf_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, smf_sess_t *sess, void *data,

View File

@ -538,6 +538,8 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
break;
DEFAULT
ogs_error("Invalid service name [%s]", sbi_message.h.service.name);
ogs_assert_if_reached();
END
ogs_sbi_message_free(&sbi_message);

View File

@ -74,8 +74,7 @@ struct udm_ue_s {
uint8_t rand[OGS_RAND_LEN];
uint8_t sqn[OGS_SQN_LEN];
ogs_amf_id_t amf_id;
ogs_plmn_id_t serving_plmn_id;
ogs_guami_t guami;
OpenAPI_auth_type_e auth_type;

View File

@ -66,39 +66,24 @@ void udm_nnrf_handle_nf_status_subscribe(
subscription, SubscriptionData->subscription_id);
if (SubscriptionData->validity_time) {
struct timeval tv;
struct tm local, next;
ogs_time_t diff, duration;
memset(&next, 0, sizeof(next));
if (ogs_strptime(SubscriptionData->validity_time,
OGS_TIME_ISO8601_FORMAT, &next)) {
ogs_gettimeofday(&tv);
ogs_localtime(tv.tv_sec, &local);
diff = ogs_mktime(&next) - ogs_mktime(&local);
#define VALIDITY_MARGIN 5 /* 5 seconds */
#define VALIDITY_MINIMUM 60 /* 60 seconds */
duration = diff - (int)VALIDITY_MARGIN;
if (duration < (int)VALIDITY_MINIMUM) {
char buf[64];
strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &local);
ogs_warn("[%s] Validation period [%lld seconds, "
"(%lld)(%lld)(%s)(%s)] is too small", subscription->id,
(long long)diff,
(long long)ogs_mktime(&next),
(long long)ogs_mktime(&local),
SubscriptionData->validity_time, buf);
#define VALIDITY_MARGIN (5 * OGS_USEC_PER_SEC) /* 5 seconds */
#define VALIDITY_MINIMUM (3600 * OGS_USEC_PER_SEC) /* 3600 seconds */
ogs_time_t time, duration;
if (ogs_sbi_time_from_string(
&time, SubscriptionData->validity_time) == true) {
duration = time - ogs_time_now() - VALIDITY_MARGIN;
if (duration < VALIDITY_MINIMUM) {
duration = VALIDITY_MINIMUM;
ogs_warn("[%s] Forced to %d seconds",
subscription->id, VALIDITY_MINIMUM);
subscription->id, (int)ogs_time_sec(VALIDITY_MINIMUM));
}
subscription->t_validity = ogs_timer_add(udm_self()->timer_mgr,
udm_timer_subscription_validity, subscription);
ogs_assert(subscription->t_validity);
ogs_timer_start(
subscription->t_validity, ogs_time_from_sec(duration));
ogs_timer_start(subscription->t_validity, duration);
} else {
ogs_error("Cannot parse validitiyTime [%s]",
SubscriptionData->validity_time);
}
}
}
@ -192,8 +177,6 @@ bool udm_nnrf_handle_nf_status_notify(
return false;
}
udm_sbi_setup_client_callback(nf_instance);
} else if (NotificationData->event ==
OpenAPI_notification_event_type_NF_DEREGISTERED) {
nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id);
@ -285,8 +268,6 @@ void udm_nnrf_handle_nf_discover(
continue;
}
udm_sbi_setup_client_callback(nf_instance);
if (!OGS_SBI_NF_INSTANCE_GET(
sbi_object->nf_types, nf_instance->nf_type))
ogs_sbi_nf_types_associate(sbi_object->nf_types,
@ -319,6 +300,6 @@ void udm_nnrf_handle_nf_discover(
"(NF discover) No NF",
OpenAPI_nf_type_ToString(sbi_object->nf_type));
} else {
ogs_sbi_send(sbi_object, nf_instance);
ogs_sbi_send(nf_instance, sbi_object);
}
}

View File

@ -196,8 +196,7 @@ bool udm_nudm_uecm_handle_registration(
ogs_sbi_session_t *session = NULL;
OpenAPI_amf3_gpp_access_registration_t *Amf3GppAccessRegistration = NULL;
OpenAPI_guami_t *guami = NULL;
OpenAPI_plmn_id_t *serving_plmn_id = NULL;
OpenAPI_guami_t *Guami = NULL;
ogs_assert(udm_ue);
session = udm_ue->sbi.session;
@ -220,37 +219,36 @@ bool udm_nudm_uecm_handle_registration(
return false;
}
guami = Amf3GppAccessRegistration->guami;
if (!guami) {
Guami = Amf3GppAccessRegistration->guami;
if (!Guami) {
ogs_error("[%s] No Guami", udm_ue->supi);
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No Guami", udm_ue->supi);
return false;
}
if (!guami->amf_id) {
if (!Guami->amf_id) {
ogs_error("[%s] No Guami.AmfId", udm_ue->supi);
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No Guami.AmfId", udm_ue->supi);
return false;
}
serving_plmn_id = guami->plmn_id;
if (!serving_plmn_id) {
if (!Guami->plmn_id) {
ogs_error("[%s] No PlmnId", udm_ue->supi);
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No PlmnId", udm_ue->supi);
return false;
}
if (!serving_plmn_id->mnc) {
if (!Guami->plmn_id->mnc) {
ogs_error("[%s] No PlmnId.Mnc", udm_ue->supi);
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No PlmnId.Mnc", udm_ue->supi);
return false;
}
if (!serving_plmn_id->mcc) {
if (!Guami->plmn_id->mcc) {
ogs_error("[%s] No PlmnId.Mcc", udm_ue->supi);
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No PlmnId.Mcc", udm_ue->supi);
@ -262,10 +260,7 @@ bool udm_nudm_uecm_handle_registration(
udm_ue->dereg_callback_uri = ogs_strdup(
Amf3GppAccessRegistration->dereg_callback_uri);
ogs_amf_id_from_string(&udm_ue->amf_id, guami->amf_id);
ogs_plmn_id_build(&udm_ue->serving_plmn_id,
atoi(serving_plmn_id->mcc), atoi(serving_plmn_id->mnc),
strlen(serving_plmn_id->mnc));
ogs_sbi_parse_guami(&udm_ue->guami, Guami);
udm_ue->amf_3gpp_access_registration =
OpenAPI_amf3_gpp_access_registration_copy(

View File

@ -162,7 +162,7 @@ ogs_sbi_request_t *udm_nudr_dr_build_query_subscription_provisioned(
(char *)OGS_SBI_RESOURCE_NAME_SUBSCRIPTION_DATA;
sendmsg.h.resource.component[1] = udm_ue->supi;
sendmsg.h.resource.component[2] =
(char *)ogs_plmn_id_to_string(&udm_ue->serving_plmn_id, buf);
(char *)ogs_plmn_id_to_string(&udm_ue->guami.plmn_id, buf);
sendmsg.h.resource.component[3] =
(char *)OGS_SBI_RESOURCE_NAME_PROVISIONED_DATA;
sendmsg.h.resource.component[4] = recvmsg->h.resource.component[1];

View File

@ -73,11 +73,23 @@ int udm_sbi_open(void)
ogs_sbi_server_start_all(server_cb);
/*
* The connection between NF and NRF is a little special.
*
* NF and NRF share nf_instance. I get the NRF EndPoint(client) information
* the configuration file via lib/sbi/context.c.
* And, the NFService information will be transmitted to NRF.
*
* ogs_sbi_self()->nf_instance_id means NF's InstanceId.
*/
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) {
ogs_sbi_nf_service_t *service = NULL;
ogs_sbi_client_t *client = NULL;
/* Build NF instance information. It will be transmitted to NRF. */
ogs_sbi_nf_instance_build_default(nf_instance, udm_self()->nf_type);
/* Build NF service information. It will be transmitted to NRF. */
service = ogs_sbi_nf_service_build_default(nf_instance,
(char*)OGS_SBI_SERVICE_NAME_NUDM_UEAU);
ogs_assert(service);
@ -94,8 +106,14 @@ int udm_sbi_open(void)
ogs_sbi_nf_service_add_version(service, (char*)OGS_SBI_API_V2,
(char*)OGS_SBI_API_V2_0_0, NULL);
/* Client callback is only used when NF sends to NRF */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
/* NFRegister is sent and the response is received
* by the above client callback. */
udm_nf_fsm_init(nf_instance);
udm_sbi_setup_client_callback(nf_instance);
}
return OGS_OK;
@ -106,24 +124,6 @@ void udm_sbi_close(void)
ogs_sbi_server_stop_all();
}
void udm_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_client_t *client = NULL;
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
ogs_list_for_each(&nf_instance->nf_service_list, nf_service) {
client = nf_service->client;
if (client)
client->cb = client_cb;
}
}
void udm_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, udm_ue_t *udm_ue, void *data,
ogs_sbi_request_t *(*build)(udm_ue_t *udm_ue, void *data))
@ -138,6 +138,7 @@ void udm_sbi_discover_and_send(
udm_ue->sbi.nf_state_registered = udm_nf_state_registered;
udm_ue->sbi.client_wait.duration =
udm_timer_cfg(UDM_TIMER_SBI_CLIENT_WAIT)->duration;
udm_ue->sbi.client_cb = client_cb;
if (ogs_sbi_discover_and_send(
nf_type, &udm_ue->sbi, data, (ogs_sbi_build_f)build) != true) {

View File

@ -31,8 +31,6 @@ extern "C" {
int udm_sbi_open(void);
void udm_sbi_close(void);
void udm_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance);
void udm_sbi_discover_and_send(
OpenAPI_nf_type_e nf_type, udm_ue_t *udm_ue, void *data,
ogs_sbi_request_t *(*build)(udm_ue_t *udm_ue, void *data));

View File

@ -66,39 +66,24 @@ void udr_nnrf_handle_nf_status_subscribe(
subscription, SubscriptionData->subscription_id);
if (SubscriptionData->validity_time) {
struct timeval tv;
struct tm local, next;
ogs_time_t diff, duration;
memset(&next, 0, sizeof(next));
if (ogs_strptime(SubscriptionData->validity_time,
OGS_TIME_ISO8601_FORMAT, &next)) {
ogs_gettimeofday(&tv);
ogs_localtime(tv.tv_sec, &local);
diff = ogs_mktime(&next) - ogs_mktime(&local);
#define VALIDITY_MARGIN 5 /* 5 seconds */
#define VALIDITY_MINIMUM 60 /* 60 seconds */
duration = diff - (int)VALIDITY_MARGIN;
if (duration < (int)VALIDITY_MINIMUM) {
char buf[64];
strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &local);
ogs_warn("[%s] Validation period [%lld seconds, "
"(%lld)(%lld)(%s)(%s)] is too small", subscription->id,
(long long)diff,
(long long)ogs_mktime(&next),
(long long)ogs_mktime(&local),
SubscriptionData->validity_time, buf);
#define VALIDITY_MARGIN (5 * OGS_USEC_PER_SEC) /* 5 seconds */
#define VALIDITY_MINIMUM (3600 * OGS_USEC_PER_SEC) /* 3600 seconds */
ogs_time_t time, duration;
if (ogs_sbi_time_from_string(
&time, SubscriptionData->validity_time) == true) {
duration = time - ogs_time_now() - VALIDITY_MARGIN;
if (duration < VALIDITY_MINIMUM) {
duration = VALIDITY_MINIMUM;
ogs_warn("[%s] Forced to %d seconds",
subscription->id, VALIDITY_MINIMUM);
subscription->id, (int)ogs_time_sec(VALIDITY_MINIMUM));
}
subscription->t_validity = ogs_timer_add(udr_self()->timer_mgr,
udr_timer_subscription_validity, subscription);
ogs_assert(subscription->t_validity);
ogs_timer_start(
subscription->t_validity, ogs_time_from_sec(duration));
ogs_timer_start(subscription->t_validity, duration);
} else {
ogs_error("Cannot parse validitiyTime [%s]",
SubscriptionData->validity_time);
}
}
}
@ -192,8 +177,6 @@ bool udr_nnrf_handle_nf_status_notify(
return false;
}
udr_sbi_setup_client_callback(nf_instance);
} else if (NotificationData->event ==
OpenAPI_notification_event_type_NF_DEREGISTERED) {
nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id);

View File

@ -73,19 +73,37 @@ int udr_sbi_open(void)
ogs_sbi_server_start_all(server_cb);
/*
* The connection between NF and NRF is a little special.
*
* NF and NRF share nf_instance. I get the NRF EndPoint(client) information
* the configuration file via lib/sbi/context.c.
* And, the NFService information will be transmitted to NRF.
*
* ogs_sbi_self()->nf_instance_id means NF's InstanceId.
*/
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) {
ogs_sbi_nf_service_t *service = NULL;
ogs_sbi_client_t *client = NULL;
/* Build NF instance information. It will be transmitted to NRF. */
ogs_sbi_nf_instance_build_default(nf_instance, udr_self()->nf_type);
/* Build NF service information. It will be transmitted to NRF. */
service = ogs_sbi_nf_service_build_default(nf_instance,
(char*)OGS_SBI_SERVICE_NAME_NUDR_DR);
ogs_assert(service);
ogs_sbi_nf_service_add_version(service, (char*)OGS_SBI_API_V1,
(char*)OGS_SBI_API_V1_0_0, NULL);
/* Client callback is only used when NF sends to NRF */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
/* NFRegister is sent and the response is received
* by the above client callback. */
udr_nf_fsm_init(nf_instance);
udr_sbi_setup_client_callback(nf_instance);
}
return OGS_OK;
@ -95,21 +113,3 @@ void udr_sbi_close(void)
{
ogs_sbi_server_stop_all();
}
void udr_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_client_t *client = NULL;
ogs_sbi_nf_service_t *nf_service = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
ogs_list_for_each(&nf_instance->nf_service_list, nf_service) {
client = nf_service->client;
if (client)
client->cb = client_cb;
}
}

View File

@ -29,8 +29,6 @@ extern "C" {
int udr_sbi_open(void);
void udr_sbi_close(void);
void udr_sbi_setup_client_callback(ogs_sbi_nf_instance_t *nf_instance);
#ifdef __cplusplus
}
#endif

View File

@ -376,7 +376,7 @@ static void upf_gtp_send_to_gnb(ogs_pfcp_far_t *far, ogs_pkbuf_t *sendbuf)
gtp_h->teid = htobe32(far->outer_header_creation.teid);
/* Send to gNB */
ogs_debug("[UPF] SEND GPU-U to gNB[%s] : TEID[0x%x]",
ogs_debug("SEND GPU-U to gNB[%s] : TEID[0x%x]",
OGS_ADDR(&gnode->addr, buf), far->outer_header_creation.teid);
rv = ogs_gtp_sendto(gnode, sendbuf);
if (rv != OGS_OK)
@ -478,7 +478,7 @@ static int upf_gtp_handle_slaac(upf_sess_t *sess, ogs_pkbuf_t *recvbuf)
struct icmp6_hdr *icmp_h =
(struct icmp6_hdr *)(recvbuf->data + sizeof(struct ip6_hdr));
if (icmp_h->icmp6_type == ND_ROUTER_SOLICIT) {
ogs_debug("[UPF] Router Solict");
ogs_debug(" Router Solict");
if (sess->ipv6) {
rv = upf_gtp_send_router_advertisement(
sess, ip6_h->ip6_src.s6_addr);
@ -581,7 +581,7 @@ static int upf_gtp_send_router_advertisement(
upf_gtp_handle_pdr(pdr, pkbuf);
ogs_debug("[UPF] Router Advertisement");
ogs_debug(" Router Advertisement");
ogs_pkbuf_free(pkbuf);
return rv;

View File

@ -33,7 +33,7 @@ ogs_pkbuf_t *upf_n4_build_association_setup_request(uint8_t type)
[OGS_PFCP_MAX_USER_PLANE_IP_RESOURCE_INFO_LEN];
int i = 0;
ogs_debug("[UPF] Association Setup Request");
ogs_debug("Association Setup Request");
req = &pfcp_message.pfcp_association_setup_request;
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
@ -84,7 +84,7 @@ ogs_pkbuf_t *upf_n4_build_association_setup_response(uint8_t type,
[OGS_PFCP_MAX_USER_PLANE_IP_RESOURCE_INFO_LEN];
int i = 0;
ogs_debug("[UPF] Association Setup Response");
ogs_debug("Association Setup Response");
rsp = &pfcp_message.pfcp_association_setup_response;
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
@ -136,7 +136,7 @@ ogs_pkbuf_t *upf_n4_build_session_establishment_response(uint8_t type,
ogs_pfcp_f_seid_t f_seid;
int len = 0;
ogs_debug("[UPF] Session Establishment Response");
ogs_debug("Session Establishment Response");
rsp = &pfcp_message.pfcp_session_establishment_response;
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
@ -185,7 +185,7 @@ ogs_pkbuf_t *upf_n4_build_session_modification_response(uint8_t type,
int i = 0;
ogs_debug("[UPF] Session Modification Response");
ogs_debug("Session Modification Response");
rsp = &pfcp_message.pfcp_session_modification_response;
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
@ -214,7 +214,7 @@ ogs_pkbuf_t *upf_n4_build_session_deletion_response(uint8_t type,
ogs_pfcp_message_t pfcp_message;
ogs_pfcp_session_deletion_response_t *rsp = NULL;
ogs_debug("[UPF] Session Deletion Response");
ogs_debug("Session Deletion Response");
rsp = &pfcp_message.pfcp_session_deletion_response;
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));

View File

@ -553,7 +553,7 @@ void upf_n4_handle_session_establishment_request(
ogs_assert(xact);
ogs_assert(req);
ogs_debug("[UPF] Session Establishment Request");
ogs_debug("Session Establishment Request");
cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
@ -615,7 +615,7 @@ void upf_n4_handle_session_modification_request(
ogs_assert(xact);
ogs_assert(req);
ogs_debug("[UPF] Session Modification Request");
ogs_debug("Session Modification Request");
cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
@ -711,7 +711,7 @@ void upf_n4_handle_session_deletion_request(
ogs_assert(xact);
ogs_assert(req);
ogs_debug("[UPF] Session Deletion Request");
ogs_debug("Session Deletion Request");
if (!sess) {
ogs_warn("No Context");

View File

@ -144,10 +144,10 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
} else
ogs_error("Invalid IP version = %d", ip_h->ip_v);
ogs_debug("[UPF] PROTO:%d SRC:%08x %08x %08x %08x",
ogs_debug("PROTO:%d SRC:%08x %08x %08x %08x",
proto, be32toh(src_addr[0]), be32toh(src_addr[1]),
be32toh(src_addr[2]), be32toh(src_addr[3]));
ogs_debug("[UPF] HLEN:%d DST:%08x %08x %08x %08x",
ogs_debug("HLEN:%d DST:%08x %08x %08x %08x",
ip_hlen, be32toh(dst_addr[0]), be32toh(dst_addr[1]),
be32toh(dst_addr[2]), be32toh(dst_addr[3]));
@ -159,18 +159,16 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
ogs_pfcp_far_t *far = NULL;
if (ip_h && sess->ipv4)
ogs_debug("[UPF] PAA IPv4:%s",
OGS_INET_NTOP(&sess->ipv4->addr, buf));
ogs_debug("PAA IPv4:%s", OGS_INET_NTOP(&sess->ipv4->addr, buf));
if (ip6_h && sess->ipv6)
ogs_debug("[UPF] PAA IPv6:%s",
OGS_INET6_NTOP(&sess->ipv6->addr, buf));
ogs_debug("PAA IPv6:%s", OGS_INET6_NTOP(&sess->ipv6->addr, buf));
/* Save the default PDR */
default_pdr = ogs_pfcp_sess_default_pdr(&sess->pfcp);
ogs_assert(default_pdr);
/* Found */
ogs_debug("[UPF] Found Session : Default PDR-ID[%d]", default_pdr->id);
ogs_debug("Found Session : Default PDR-ID[%d]", default_pdr->id);
ogs_list_for_each(&sess->sdf_filter_list, sdf_filter) {
int k;
@ -313,7 +311,7 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
return default_pdr;
} else {
ogs_debug("[UPF] No Session");
ogs_debug("No Session");
}
return NULL;

View File

@ -210,13 +210,13 @@ static void test1_func(abts_case *tc, void *data)
test_self()->nr_cgi.cell_id = 0x000000ce7;
/* Send Registration request */
test_ue.registration_request_type.guti = 1;
test_ue.registration_request_param.guti = 1;
gmmbuf = testgmm_build_registration_request(&test_ue, NULL);
ABTS_PTR_NOTNULL(tc, gmmbuf);
test_ue.registration_request_type.requested_nssai = 1;
test_ue.registration_request_type.last_visited_registered_tai = 1;
test_ue.registration_request_type.ue_usage_setting = 1;
test_ue.registration_request_param.requested_nssai = 1;
test_ue.registration_request_param.last_visited_registered_tai = 1;
test_ue.registration_request_param.ue_usage_setting = 1;
nasbuf = testgmm_build_registration_request(&test_ue, NULL);
ABTS_PTR_NOTNULL(tc, nasbuf);
@ -309,6 +309,11 @@ static void test1_func(abts_case *tc, void *data)
testngap_recv(&test_ue, recvbuf);
/* Send PDU session establishment request */
test_sess.ul_nas_transport_param.request_type =
OGS_NAS_5GS_REQUEST_TYPE_INITIAL;
test_sess.ul_nas_transport_param.dnn = 1;
test_sess.ul_nas_transport_param.s_nssai = 1;
gsmbuf = testgsm_build_pdu_session_establishment_request(&test_sess);
ABTS_PTR_NOTNULL(tc, gsmbuf);
gmmbuf = testgmm_build_ul_nas_transport(&test_sess,

View File

@ -15,12 +15,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
test00101_sources = files('''
test5gc_00101_sources = files('''
abts-main.c
issues-482-test.c
'''.split())
test00101_exe = executable('00101',
sources : test00101_sources,
c_args : testcore_cc_flags,
test5gc_00101_exe = executable('00101',
sources : test5gc_00101_sources,
c_args : testunit_core_cc_flags,
dependencies : libtest5gc_dep)

View File

@ -15,12 +15,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
test23504_sources = files('''
test5gc_23504_sources = files('''
abts-main.c
r16-test.c
'''.split())
test23504_exe = executable('23504',
sources : test23504_sources,
c_args : testcore_cc_flags,
test5gc_23504_exe = executable('23504',
sources : test5gc_23504_sources,
c_args : testunit_core_cc_flags,
dependencies : libtestepc_dep)

View File

@ -59,7 +59,7 @@ typedef struct test_context_s {
typedef struct test_sess_s test_sess_t;
typedef struct test_registration_request_type_s {
typedef struct test_registration_request_param_s {
union {
struct {
ED8(uint8_t integrity_protected:1;,
@ -78,9 +78,9 @@ typedef struct test_registration_request_type_s {
uint16_t uplink_data_status;
uint16_t allowed_pdu_session_status;
} psimask;
} __attribute__ ((packed)) test_registration_request_type_t;
} __attribute__ ((packed)) test_registration_request_param_t;
typedef struct test_service_request_type_s {
typedef struct test_service_request_param_s {
union {
struct {
ED6(uint8_t integrity_protected:1;,
@ -98,7 +98,19 @@ typedef struct test_service_request_type_s {
uint16_t uplink_data_status;
uint16_t allowed_pdu_session_status;
} psimask;
} __attribute__ ((packed)) test_service_request_type_t;
} __attribute__ ((packed)) test_service_request_param_t;
typedef struct test_ul_nas_transport_param_s {
union {
struct {
ED4(uint8_t request_type:4;,
uint8_t dnn:1;,
uint8_t s_nssai:1;,
uint8_t reserved:2;)
};
uint8_t value;
};
} __attribute__ ((packed)) test_ul_nas_transport_param_t;
typedef struct test_ue_s {
uint32_t ran_ue_ngap_id; /* eNB-UE-NGAP-ID received from eNB */
@ -170,8 +182,8 @@ typedef struct test_ue_s {
int security_context_available;
int mac_failed;
test_registration_request_type_t registration_request_type;
test_service_request_type_t service_request_type;
test_registration_request_param_t registration_request_param;
test_service_request_param_t service_request_param;
uint8_t gmm_message_type; /* Last received 5GMM message type */
uint16_t pdu_session_status;
@ -193,6 +205,8 @@ typedef struct test_sess_s {
ogs_ip_t gnb_n3_ip;
uint32_t gnb_n3_teid;
test_ul_nas_transport_param_t ul_nas_transport_param;
test_ue_t *test_ue;
} test_sess_t;

View File

@ -62,7 +62,7 @@ ogs_pkbuf_t *testgmm_build_registration_request(
ogs_assert(sess);
memset(&message, 0, sizeof(message));
if (test_ue->registration_request_type.integrity_protected) {
if (test_ue->registration_request_param.integrity_protected) {
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.extended_protocol_discriminator =
@ -74,7 +74,7 @@ ogs_pkbuf_t *testgmm_build_registration_request(
registration_type->data = test_ue->nas.data;
if (test_ue->registration_request_type.guti) {
if (test_ue->registration_request_param.guti) {
ogs_nas_5gs_nas_guti_to_mobilty_identity_guti(
&test_ue->nas_guti, &mobile_identity_guti);
registration_request->mobile_identity.length =
@ -89,34 +89,34 @@ ogs_pkbuf_t *testgmm_build_registration_request(
&test_ue->mobile_identity_suci;
}
if (test_ue->registration_request_type.uplink_data_status) {
if (test_ue->registration_request_param.uplink_data_status) {
registration_request->presencemask |=
OGS_NAS_5GS_REGISTRATION_REQUEST_UPLINK_DATA_STATUS_PRESENT;
uplink_data_status->length = 2;
uplink_data_status->psi |=
test_ue->registration_request_type.psimask.uplink_data_status << 8;
test_ue->registration_request_param.psimask.uplink_data_status << 8;
uplink_data_status->psi |=
test_ue->registration_request_type.psimask.uplink_data_status >> 8;
test_ue->registration_request_param.psimask.uplink_data_status >> 8;
}
if (test_ue->registration_request_type.pdu_session_status) {
if (test_ue->registration_request_param.pdu_session_status) {
registration_request->presencemask |=
OGS_NAS_5GS_REGISTRATION_REQUEST_PDU_SESSION_STATUS_PRESENT;
pdu_session_status->length = 2;
pdu_session_status->psi |=
test_ue->registration_request_type.psimask.pdu_session_status << 8;
test_ue->registration_request_param.psimask.pdu_session_status << 8;
pdu_session_status->psi |=
test_ue->registration_request_type.psimask.pdu_session_status >> 8;
test_ue->registration_request_param.psimask.pdu_session_status >> 8;
}
if (test_ue->registration_request_type.allowed_pdu_session_status) {
if (test_ue->registration_request_param.allowed_pdu_session_status) {
registration_request->presencemask |=
OGS_NAS_5GS_REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT;
allowed_pdu_session_status->length = 2;
allowed_pdu_session_status->psi |= test_ue->
registration_request_type.psimask.allowed_pdu_session_status << 8;
registration_request_param.psimask.allowed_pdu_session_status << 8;
allowed_pdu_session_status->psi |= test_ue->
registration_request_type.psimask.allowed_pdu_session_status >> 8;
registration_request_param.psimask.allowed_pdu_session_status >> 8;
}
registration_request->presencemask |=
@ -144,7 +144,7 @@ ogs_pkbuf_t *testgmm_build_registration_request(
s1_ue_network_capability->n1_mode = 1;
s1_ue_network_capability->dual_connectivity_with_nr = 1;
if (test_ue->registration_request_type.requested_nssai) {
if (test_ue->registration_request_param.requested_nssai) {
/* Set Requested NSSAI */
registration_request->presencemask |=
OGS_NAS_5GS_REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT;
@ -157,7 +157,7 @@ ogs_pkbuf_t *testgmm_build_registration_request(
}
}
if (test_ue->registration_request_type.last_visited_registered_tai) {
if (test_ue->registration_request_param.last_visited_registered_tai) {
/* Set Last visited registered TAI */
registration_request->presencemask |=
OGS_NAS_5GS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT;
@ -166,7 +166,7 @@ ogs_pkbuf_t *testgmm_build_registration_request(
last_visited_registered_tai->tac.v = test_self()->tai.tac.v;
}
if (test_ue->registration_request_type.ue_usage_setting) {
if (test_ue->registration_request_param.ue_usage_setting) {
/* Set UE's usage setting */
registration_request->presencemask |=
OGS_NAS_5GS_REGISTRATION_REQUEST_UE_USAGE_SETTING_PRESENT;
@ -182,7 +182,7 @@ ogs_pkbuf_t *testgmm_build_registration_request(
ogs_pkbuf_free(nasbuf);
}
if (test_ue->registration_request_type.integrity_protected)
if (test_ue->registration_request_param.integrity_protected)
return test_nas_5gs_security_encode(test_ue, &message);
else
return ogs_nas_5gs_plain_encode(&message);
@ -232,11 +232,11 @@ ogs_pkbuf_t *testgmm_build_service_request(
uplink_data_status = &service_request->uplink_data_status;
memset(&message, 0, sizeof(message));
if (test_ue->service_request_type.integrity_protected) {
if (test_ue->service_request_param.integrity_protected) {
message.h.extended_protocol_discriminator =
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GMM;
if (test_ue->service_request_type.ciphered)
if (test_ue->service_request_param.ciphered)
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
else
@ -248,7 +248,7 @@ ogs_pkbuf_t *testgmm_build_service_request(
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GMM;
message.gmm.h.message_type = OGS_NAS_5GS_SERVICE_REQUEST;
service_request->ngksi.type = test_ue->service_request_type.service_type;
service_request->ngksi.type = test_ue->service_request_param.service_type;
service_request->ngksi.tsc = test_ue->nas.tsc;
service_request->ngksi.value = test_ue->nas.ksi;
@ -286,37 +286,37 @@ ogs_pkbuf_t *testgmm_build_service_request(
ogs_pkbuf_free(nasbuf);
}
if (test_ue->service_request_type.uplink_data_status) {
if (test_ue->service_request_param.uplink_data_status) {
service_request->presencemask |=
OGS_NAS_5GS_SERVICE_REQUEST_UPLINK_DATA_STATUS_PRESENT;
uplink_data_status->length = 2;
uplink_data_status->psi |=
test_ue->service_request_type.psimask.uplink_data_status << 8;
test_ue->service_request_param.psimask.uplink_data_status << 8;
uplink_data_status->psi |=
test_ue->service_request_type.psimask.uplink_data_status >> 8;
test_ue->service_request_param.psimask.uplink_data_status >> 8;
}
if (test_ue->service_request_type.pdu_session_status) {
if (test_ue->service_request_param.pdu_session_status) {
service_request->presencemask |=
OGS_NAS_5GS_SERVICE_REQUEST_PDU_SESSION_STATUS_PRESENT;
pdu_session_status->length = 2;
pdu_session_status->psi |=
test_ue->service_request_type.psimask.pdu_session_status << 8;
test_ue->service_request_param.psimask.pdu_session_status << 8;
pdu_session_status->psi |=
test_ue->service_request_type.psimask.pdu_session_status >> 8;
test_ue->service_request_param.psimask.pdu_session_status >> 8;
}
if (test_ue->service_request_type.allowed_pdu_session_status) {
if (test_ue->service_request_param.allowed_pdu_session_status) {
service_request->presencemask |=
OGS_NAS_5GS_SERVICE_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT;
allowed_pdu_session_status->length = 2;
allowed_pdu_session_status->psi |= test_ue->
service_request_type.psimask.allowed_pdu_session_status << 8;
service_request_param.psimask.allowed_pdu_session_status << 8;
allowed_pdu_session_status->psi |= test_ue->
service_request_type.psimask.allowed_pdu_session_status >> 8;
service_request_param.psimask.allowed_pdu_session_status >> 8;
}
if (test_ue->service_request_type.integrity_protected)
if (test_ue->service_request_param.integrity_protected)
return test_nas_5gs_security_encode(test_ue, &message);
else
return ogs_nas_5gs_plain_encode(&message);
@ -574,10 +574,7 @@ ogs_pkbuf_t *testgmm_build_ul_nas_transport(test_sess_t *test_sess,
ogs_nas_payload_container_t *payload_container = NULL;
ogs_nas_pdu_session_identity_2_t *pdu_session_id = NULL;
ogs_nas_request_type_t *request_type = NULL;
#define S_NSSAI_PRECENSE 0
#if S_NSSAI_PRECENSE
ogs_nas_s_nssai_t *nas_s_nssai = NULL;
#endif
ogs_assert(test_sess);
test_ue = test_sess->test_ue;
@ -589,9 +586,7 @@ ogs_pkbuf_t *testgmm_build_ul_nas_transport(test_sess_t *test_sess,
payload_container = &ul_nas_transport->payload_container;
pdu_session_id = &ul_nas_transport->pdu_session_id;
request_type = &ul_nas_transport->request_type;
#if S_NSSAI_PRECENSE
nas_s_nssai = &ul_nas_transport->s_nssai;
#endif
memset(&message, 0, sizeof(message));
message.h.security_header_type =
@ -612,22 +607,26 @@ ogs_pkbuf_t *testgmm_build_ul_nas_transport(test_sess_t *test_sess,
OGS_NAS_5GS_UL_NAS_TRANSPORT_PDU_SESSION_ID_PRESENT;
*pdu_session_id = test_sess->psi;
ul_nas_transport->presencemask |=
OGS_NAS_5GS_UL_NAS_TRANSPORT_REQUEST_TYPE_PRESENT;
request_type->value = OGS_NAS_5GS_REQUEST_TYPE_INITIAL;
if (test_sess->ul_nas_transport_param.request_type) {
ul_nas_transport->presencemask |=
OGS_NAS_5GS_UL_NAS_TRANSPORT_REQUEST_TYPE_PRESENT;
request_type->value = test_sess->ul_nas_transport_param.request_type;
}
#if S_NSSAI_PRECENSE
ul_nas_transport->presencemask |=
OGS_NAS_5GS_UL_NAS_TRANSPORT_S_NSSAI_PRESENT;
ogs_nas_build_s_nssai(
nas_s_nssai, &test_self()->plmn_support[0].s_nssai[0]);
#endif
if (test_sess->ul_nas_transport_param.s_nssai) {
ul_nas_transport->presencemask |=
OGS_NAS_5GS_UL_NAS_TRANSPORT_S_NSSAI_PRESENT;
ogs_nas_build_s_nssai(
nas_s_nssai, &test_self()->plmn_support[0].s_nssai[0]);
}
ul_nas_transport->presencemask |=
OGS_NAS_5GS_UL_NAS_TRANSPORT_DNN_PRESENT;
ul_nas_transport->dnn.length = strlen(test_sess->dnn);
ogs_cpystrn(ul_nas_transport->dnn.value, test_sess->dnn,
ogs_min(ul_nas_transport->dnn.length, OGS_MAX_DNN_LEN) + 1);
if (test_sess->ul_nas_transport_param.dnn) {
ul_nas_transport->presencemask |=
OGS_NAS_5GS_UL_NAS_TRANSPORT_DNN_PRESENT;
ul_nas_transport->dnn.length = strlen(test_sess->dnn);
ogs_cpystrn(ul_nas_transport->dnn.value, test_sess->dnn,
ogs_min(ul_nas_transport->dnn.length, OGS_MAX_DNN_LEN) + 1);
}
pkbuf = test_nas_5gs_security_encode(test_ue, &message);
ogs_pkbuf_free(payload);

View File

@ -43,7 +43,7 @@ libtestcommon_inc = include_directories('.')
libtestcommon = static_library('testcomon',
sources : libtestcommon_sources,
c_args : testcore_cc_flags,
c_args : testunit_core_cc_flags,
include_directories : [libtestcommon_inc, testinc, srcinc],
dependencies : [libcore_dep,
libapp_dep,

View File

@ -315,6 +315,109 @@ static void list_test5(abts_case *tc, void *data)
}
}
lt_type1 *find_rr(lt_type1 *current, int m1)
{
lt_type1 *next, *node;
ogs_assert(current);
next = ogs_list_next(current);
for (node = next; node; node = ogs_list_next(node)) {
if (node->m1 == m1) return node;
}
for (node = ogs_list_first(&tlist1);
node != next; node = ogs_list_next(node)) {
if (node->m1 == m1) return node;
}
return next ? next : ogs_list_first(&tlist1);
}
static void list_test6(abts_case *tc, void *data)
{
int i;
lt_type1 *iter, *tmp, node[SIZE_OF_lt_type1];
for (i = 0; i < SIZE_OF_lt_type1; i++)
node[i].m1 = i/3;
ogs_list_init(&tlist1);
for (i = 0; i < 10; i++)
ogs_list_add(&tlist1, &node[i]);
ABTS_INT_EQUAL(tc, 10, ogs_list_count(&tlist1));
iter = ogs_list_last(&tlist1);
ABTS_INT_EQUAL(tc, 3, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 1, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 1, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 1, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 3, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 1, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 1, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 1, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 3, iter->m1);
iter = find_rr(iter, 2);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 2);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 3);
ABTS_INT_EQUAL(tc, 3, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 2);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 3);
ABTS_INT_EQUAL(tc, 3, iter->m1);
iter = find_rr(iter, 0);
ABTS_INT_EQUAL(tc, 0, iter->m1);
iter = find_rr(iter, 2);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 2, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 3, iter->m1);
iter = find_rr(iter, 9);
ABTS_INT_EQUAL(tc, 0, iter->m1);
}
abts_suite *test_list(abts_suite *suite)
{
suite = ADD_SUITE(suite)
@ -324,6 +427,7 @@ abts_suite *test_list(abts_suite *suite)
abts_run_test(suite, list_test3, NULL);
abts_run_test(suite, list_test4, NULL);
abts_run_test(suite, list_test5, NULL);
abts_run_test(suite, list_test6, NULL);
return suite;
}

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
testcore_sources = files('''
testunit_core_sources = files('''
list-test.c
pool-test.c
strings-test.c
@ -37,9 +37,9 @@ testcore_sources = files('''
abts-main.c
'''.split())
testcore_cc_flags = []
testunit_core_cc_flags = []
if cc.get_id() == 'gcc' or cc.get_id() == 'clang'
testcore_cc_flags += cc.get_supported_arguments([
testunit_core_cc_flags += cc.get_supported_arguments([
'-Wno-missing-prototypes',
'-Wno-missing-declarations',
'-Wno-discarded-qualifiers',
@ -48,9 +48,9 @@ if cc.get_id() == 'gcc' or cc.get_id() == 'clang'
'-Wno-deprecated-declarations'])
endif
testcore_exe = executable('core',
sources : testcore_sources,
c_args : testcore_cc_flags,
testunit_core_exe = executable('core',
sources : testunit_core_sources,
c_args : testunit_core_cc_flags,
dependencies : libcore_dep)
test('core', testcore_exe, is_parallel : false, suite: 'unit')
test('core', testunit_core_exe, is_parallel : false, suite: 'unit')

View File

@ -20,6 +20,9 @@
#include "ogs-core.h"
#include "core/abts.h"
/* 2002-09-14 12:05:36.186711 -25200 [257 Sat]. */
static ogs_time_t now = 1032030336186711L;
static void test_now(abts_case *tc, void *data)
{
struct timeval tv;
@ -38,21 +41,63 @@ static void test_now(abts_case *tc, void *data)
#define STR_SIZE 100
static void test_strftime(abts_case *tc, void *data)
static void test_gmtstr(abts_case *tc, void *data)
{
struct tm tm;
char str[STR_SIZE+1];
time_t now = (time_t)1542100786;
char *str = NULL;
ogs_gmtime(now, &tm);
strftime(str, sizeof str, "%Y/%m/%d %H:%M:%S", &tm);
ABTS_STR_EQUAL(tc, "2018/11/13 09:19:46", str);
char datetime[STR_SIZE];
ogs_localtime(now, &tm);
strftime(str, sizeof str, "%Y/%m/%d %H:%M:%S", &tm);
#if 0 /* FIXME */
ABTS_STR_EQUAL(tc, "2018/11/13 18:19:46", str);
#endif
ogs_gmtime(ogs_time_sec(now), &tm);
ogs_strftime(datetime, sizeof datetime, "%Y-%m-%dT%H:%M:%S", &tm);
str = ogs_msprintf("%s.%06lldZ",
datetime, (long long)ogs_time_usec(now));
ogs_assert(str);
ABTS_STR_EQUAL(tc, "2002-09-14T19:05:36.186711Z", str);
ogs_free(str);
}
static void test_get_gmt(abts_case *tc, void *data)
{
int rv;
struct tm xt;
ogs_time_t imp;
int64_t hr_off_64;
ogs_gmtime(ogs_time_sec(now), &xt);
rv = ogs_time_from_lt(&imp, &xt, ogs_time_usec(now));
ABTS_TRUE(tc, rv == OGS_OK);
hr_off_64 = (int64_t) xt.tm_gmtoff * OGS_USEC_PER_SEC;
ABTS_TRUE(tc, now + hr_off_64 == imp);
}
static void test_get_lt(abts_case *tc, void *data)
{
int rv;
struct tm xt;
ogs_time_t imp;
int64_t hr_off_64;
ogs_localtime(ogs_time_sec(now), &xt);
rv = ogs_time_from_lt(&imp, &xt, ogs_time_usec(now));
ABTS_TRUE(tc, rv == OGS_OK);
hr_off_64 = (int64_t) xt.tm_gmtoff * OGS_USEC_PER_SEC;
ABTS_TRUE(tc, now + hr_off_64 == imp);
}
static void test_imp_gmt(abts_case *tc, void *data)
{
int rv;
struct tm xt;
ogs_time_t imp;
ogs_gmtime(ogs_time_sec(now), &xt);
rv = ogs_time_from_gmt(&imp, &xt, ogs_time_usec(now));
ABTS_TRUE(tc, rv == OGS_OK);
ABTS_TRUE(tc, now == imp);
}
abts_suite *test_time(abts_suite *suite)
@ -60,7 +105,10 @@ abts_suite *test_time(abts_suite *suite)
suite = ADD_SUITE(suite)
abts_run_test(suite, test_now, NULL);
abts_run_test(suite, test_strftime, NULL);
abts_run_test(suite, test_gmtstr, NULL);
abts_run_test(suite, test_get_gmt, NULL);
abts_run_test(suite, test_get_lt, NULL);
abts_run_test(suite, test_imp_gmt, NULL);
return suite;
}

View File

@ -15,16 +15,16 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
testcrypt_sources = files('''
testunit_crypt_sources = files('''
aes-test.c
sha-test.c
base64-test.c
abts-main.c
'''.split())
testcrypt_exe = executable('crypt',
sources : testcrypt_sources,
c_args : testcore_cc_flags,
testunit_crypt_exe = executable('crypt',
sources : testunit_crypt_sources,
c_args : testunit_core_cc_flags,
dependencies : libcrypt_dep)
test('crypt', testcrypt_exe, is_parallel : false, suite: 'unit')
test('crypt', testunit_crypt_exe, is_parallel : false, suite: 'unit')

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
testcsfb_sources = files('''
testepc_csfb_sources = files('''
abts-main.c
mo-idle-test.c
mt-idle-test.c
@ -26,9 +26,9 @@ testcsfb_sources = files('''
crash-test.c
'''.split())
testcsfb_exe = executable('csfb',
sources : testcsfb_sources,
c_args : testcore_cc_flags,
testepc_csfb_exe = executable('csfb',
sources : testepc_csfb_sources,
c_args : testunit_core_cc_flags,
dependencies : libtestepc_dep)
test('csfb', testcsfb_exe, is_parallel : false, suite: 'epc')
test('csfb', testepc_csfb_exe, is_parallel : false, suite: 'epc')

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
testcups_sources = files('''
test5gc_cups_sources = files('''
pcscf-fd-path.h
pcscf-fd-path.c
@ -23,10 +23,10 @@ testcups_sources = files('''
cups-test.c
'''.split())
testcups_exe = executable('cups',
sources : testcups_sources,
c_args : [testcore_cc_flags,
test5gc_cups_exe = executable('cups',
sources : test5gc_cups_sources,
c_args : [testunit_core_cc_flags,
'-DFD_EXT_DIR="@0@"'.format(freediameter_extensions_builddir)],
dependencies : libtestepc_dep)
test('cups', testcups_exe, is_parallel : false, suite: '5gc')
test('cups', test5gc_cups_exe, is_parallel : false, suite: '5gc')

Some files were not shown because too many files have changed in this diff Show More